aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoracsawdey <acsawdey@138bc75d-0d04-0410-961f-82ee72b054a4>2014-06-03 19:41:58 +0000
committeracsawdey <acsawdey@138bc75d-0d04-0410-961f-82ee72b054a4>2014-06-03 19:41:58 +0000
commit6b985431598d7f166328e1d2f45977013602e6c3 (patch)
tree57605c37052cd963f96f8a323792832008295a72
parentab0010542ddd97647a266d183c8c5f3a067cbaf7 (diff)
parent8aa69b7b04f27881dcf133645286abb50f219064 (diff)
svnmerge up to trunk revision 211147lto-pressure
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/lto-pressure@211199 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--ChangeLog43
-rw-r--r--MAINTAINERS7
-rw-r--r--boehm-gc/ChangeLog8
-rw-r--r--boehm-gc/include/gc_config_macros.h2
-rw-r--r--boehm-gc/win32_threads.c10
-rw-r--r--config/ChangeLog4
-rw-r--r--config/mt-nios2-elf5
-rwxr-xr-xconfigure17
-rw-r--r--configure.ac17
-rw-r--r--contrib/ChangeLog37
-rw-r--r--contrib/config-list.mk4
-rw-r--r--contrib/dg-extract-results.py580
-rwxr-xr-xcontrib/dg-extract-results.sh9
-rwxr-xr-xcontrib/texi2pod.pl4
-rw-r--r--gcc/ChangeLog3577
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in4
-rw-r--r--gcc/REVISION2
-rw-r--r--gcc/ada/ChangeLog509
-rw-r--r--gcc/ada/ceinfo.adb9
-rw-r--r--gcc/ada/debug.adb21
-rw-r--r--gcc/ada/einfo.ads147
-rw-r--r--gcc/ada/errout.adb25
-rw-r--r--gcc/ada/errout.ads27
-rw-r--r--gcc/ada/erroutc.adb25
-rw-r--r--gcc/ada/erroutc.ads30
-rw-r--r--gcc/ada/exp_aggr.adb4
-rw-r--r--gcc/ada/exp_ch4.adb23
-rw-r--r--gcc/ada/exp_ch6.adb166
-rw-r--r--gcc/ada/exp_ch6.ads32
-rw-r--r--gcc/ada/exp_pakd.adb105
-rw-r--r--gcc/ada/fe.h15
-rw-r--r--gcc/ada/freeze.adb159
-rw-r--r--gcc/ada/g-dyntab.adb17
-rw-r--r--gcc/ada/g-socket.adb111
-rw-r--r--gcc/ada/g-table.adb24
-rw-r--r--gcc/ada/gcc-interface/ada-tree.h14
-rw-r--r--gcc/ada/gcc-interface/decl.c132
-rw-r--r--gcc/ada/gcc-interface/trans.c53
-rw-r--r--gcc/ada/gcc-interface/utils.c25
-rw-r--r--gcc/ada/gnat1drv.adb25
-rw-r--r--gcc/ada/gnat_rm.texi2
-rw-r--r--gcc/ada/gnat_ugn.texi231
-rw-r--r--gcc/ada/gnatcmd.adb207
-rw-r--r--gcc/ada/layout.adb70
-rw-r--r--gcc/ada/lib-xref-spark_specific.adb39
-rw-r--r--gcc/ada/lib-xref.adb8
-rw-r--r--gcc/ada/lib-xref.ads10
-rw-r--r--gcc/ada/makeusg.adb7
-rw-r--r--gcc/ada/makeutl.adb59
-rw-r--r--gcc/ada/osint.adb8
-rw-r--r--gcc/ada/par-ch4.adb16
-rw-r--r--gcc/ada/prj-dect.adb8
-rw-r--r--gcc/ada/prj.adb109
-rw-r--r--gcc/ada/prj.ads26
-rw-r--r--gcc/ada/restrict.adb12
-rw-r--r--gcc/ada/restrict.ads3
-rw-r--r--gcc/ada/rtsfind.ads28
-rw-r--r--gcc/ada/s-arit64.adb128
-rw-r--r--gcc/ada/s-oscons-tmplt.c5
-rw-r--r--gcc/ada/s-rident.ads3
-rw-r--r--gcc/ada/s-taprop.ads20
-rw-r--r--gcc/ada/seh_init.c13
-rw-r--r--gcc/ada/sem_attr.adb60
-rw-r--r--gcc/ada/sem_aux.adb4
-rw-r--r--gcc/ada/sem_ch12.adb116
-rw-r--r--gcc/ada/sem_ch13.adb117
-rw-r--r--gcc/ada/sem_ch13.ads25
-rw-r--r--gcc/ada/sem_ch3.adb166
-rw-r--r--gcc/ada/sem_ch5.adb22
-rw-r--r--gcc/ada/sem_ch6.adb358
-rw-r--r--gcc/ada/sem_ch7.adb4
-rw-r--r--gcc/ada/sem_ch8.adb16
-rw-r--r--gcc/ada/sem_ch9.adb90
-rw-r--r--gcc/ada/sem_ch9.ads16
-rw-r--r--gcc/ada/sem_dim.adb4
-rw-r--r--gcc/ada/sem_elab.adb150
-rw-r--r--gcc/ada/sem_elab.ads4
-rw-r--r--gcc/ada/sem_eval.adb53
-rw-r--r--gcc/ada/sem_eval.ads30
-rw-r--r--gcc/ada/sem_prag.adb121
-rw-r--r--gcc/ada/sem_res.adb10
-rw-r--r--gcc/ada/sem_util.adb204
-rw-r--r--gcc/ada/sem_util.ads9
-rw-r--r--gcc/ada/sem_warn.adb51
-rw-r--r--gcc/ada/sinfo.adb20
-rw-r--r--gcc/ada/sinfo.ads19
-rw-r--r--gcc/ada/sinput-l.adb128
-rw-r--r--gcc/ada/sinput-l.ads15
-rw-r--r--gcc/ada/stand.adb59
-rw-r--r--gcc/ada/stand.ads7
-rw-r--r--gcc/ada/tbuild.ads4
-rw-r--r--gcc/ada/usage.adb21
-rw-r--r--gcc/ada/warnsw.adb268
-rw-r--r--gcc/ada/warnsw.ads4
-rw-r--r--gcc/alias.c2
-rw-r--r--gcc/alloc-pool.c2
-rw-r--r--gcc/asan.c202
-rw-r--r--gcc/bb-reorder.c31
-rw-r--r--gcc/bitmap.c26
-rw-r--r--gcc/bt-load.c4
-rw-r--r--gcc/builtin-types.def12
-rw-r--r--gcc/builtins.c112
-rw-r--r--gcc/builtins.def2
-rw-r--r--gcc/builtins.h50
-rw-r--r--gcc/c-family/ChangeLog60
-rw-r--r--gcc/c-family/c-common.c90
-rw-r--r--gcc/c-family/c-common.h14
-rw-r--r--gcc/c-family/c-cppbuiltin.c75
-rw-r--r--gcc/c-family/c-pragma.c7
-rw-r--r--gcc/c-family/c-pretty-print.c18
-rw-r--r--gcc/c-family/c-ubsan.c6
-rw-r--r--gcc/c-family/c.opt2
-rw-r--r--gcc/c-family/cilk.c1
-rw-r--r--gcc/c/ChangeLog124
-rw-r--r--gcc/c/c-array-notation.c4
-rw-r--r--gcc/c/c-decl.c44
-rw-r--r--gcc/c/c-lang.h4
-rw-r--r--gcc/c/c-parser.c56
-rw-r--r--gcc/c/c-tree.h10
-rw-r--r--gcc/c/c-typeck.c306
-rw-r--r--gcc/caller-save.c13
-rw-r--r--gcc/cfg.c18
-rw-r--r--gcc/cfgcleanup.c14
-rw-r--r--gcc/cfgexpand.c65
-rw-r--r--gcc/cfghooks.c20
-rw-r--r--gcc/cfgloop.c8
-rw-r--r--gcc/cfgloop.h2
-rw-r--r--gcc/cfgrtl.c40
-rw-r--r--gcc/cgraph.c27
-rw-r--r--gcc/cgraph.h112
-rw-r--r--gcc/cgraphclones.c5
-rw-r--r--gcc/cgraphunit.c21
-rw-r--r--gcc/collect2.c2
-rw-r--r--gcc/combine.c21
-rw-r--r--gcc/common/config/i386/i386-common.c47
-rw-r--r--gcc/config.gcc65
-rw-r--r--gcc/config.in29
-rw-r--r--gcc/config/aarch64/aarch64-builtins.c158
-rw-r--r--gcc/config/aarch64/aarch64-protos.h16
-rw-r--r--gcc/config/aarch64/aarch64-simd-builtins.def3
-rw-r--r--gcc/config/aarch64/aarch64-simd.md29
-rw-r--r--gcc/config/aarch64/aarch64.c1417
-rw-r--r--gcc/config/aarch64/aarch64.h13
-rw-r--r--gcc/config/aarch64/aarch64.md74
-rw-r--r--gcc/config/aarch64/arm_neon.h602
-rw-r--r--gcc/config/aarch64/constraints.md7
-rw-r--r--gcc/config/aarch64/iterators.md1
-rw-r--r--gcc/config/aarch64/predicates.md4
-rw-r--r--gcc/config/alpha/alpha.c63
-rw-r--r--gcc/config/alpha/alpha.md4
-rw-r--r--gcc/config/arc/arc.c11
-rw-r--r--gcc/config/arc/arc.md18
-rw-r--r--gcc/config/arm/aout.h9
-rw-r--r--gcc/config/arm/arm-cores.def9
-rw-r--r--gcc/config/arm/arm-opts.h9
-rw-r--r--gcc/config/arm/arm.c352
-rw-r--r--gcc/config/arm/arm.h11
-rw-r--r--gcc/config/arm/arm.md77
-rw-r--r--gcc/config/arm/arm_neon.h305
-rw-r--r--gcc/config/arm/arm_neon_builtins.def21
-rw-r--r--gcc/config/arm/bpabi.h9
-rw-r--r--gcc/config/arm/elf.h9
-rw-r--r--gcc/config/arm/iterators.md17
-rw-r--r--gcc/config/arm/linux-elf.h9
-rw-r--r--gcc/config/arm/linux-gas.h9
-rw-r--r--gcc/config/arm/neon-docgen.ml424
-rw-r--r--gcc/config/arm/neon-gen.ml520
-rw-r--r--gcc/config/arm/neon.md122
-rw-r--r--gcc/config/arm/netbsd-elf.h9
-rw-r--r--gcc/config/arm/predicates.md9
-rw-r--r--gcc/config/arm/thumb2.md2
-rw-r--r--gcc/config/arm/uclinux-eabi.h9
-rw-r--r--gcc/config/arm/uclinux-elf.h9
-rw-r--r--gcc/config/arm/unspecs.md2
-rw-r--r--gcc/config/arm/vfp.md18
-rw-r--r--gcc/config/arm/vxworks.h9
-rw-r--r--gcc/config/avr/avr-fixed.md4
-rw-r--r--gcc/config/avr/avr-mcus.def2
-rw-r--r--gcc/config/avr/avr-tables.opt90
-rw-r--r--gcc/config/avr/avr.c16
-rw-r--r--gcc/config/avr/avr.h14
-rw-r--r--gcc/config/avr/avr.md8
-rw-r--r--gcc/config/avr/t-multilib2
-rw-r--r--gcc/config/bfin/bfin.c17
-rw-r--r--gcc/config/c6x/c6x.c7
-rw-r--r--gcc/config/cr16/cr16.c1
-rw-r--r--gcc/config/cris/cris.c3
-rw-r--r--gcc/config/darwin.c12
-rw-r--r--gcc/config/dbx.h9
-rw-r--r--gcc/config/dragonfly-stdint.h56
-rw-r--r--gcc/config/dragonfly.h129
-rw-r--r--gcc/config/dragonfly.opt64
-rw-r--r--gcc/config/epiphany/epiphany-protos.h2
-rw-r--r--gcc/config/epiphany/epiphany.c35
-rw-r--r--gcc/config/epiphany/epiphany.h13
-rw-r--r--gcc/config/epiphany/mode-switch-use.c2
-rw-r--r--gcc/config/fr30/fr30.c1
-rw-r--r--gcc/config/frv/frv.c3
-rw-r--r--gcc/config/h8300/h8300.c1
-rw-r--r--gcc/config/h8300/h8300.md2
-rw-r--r--gcc/config/i386/clflushoptintrin.h49
-rw-r--r--gcc/config/i386/constraints.md26
-rw-r--r--gcc/config/i386/cpuid.h3
-rw-r--r--gcc/config/i386/dragonfly.h104
-rw-r--r--gcc/config/i386/driver-i386.c12
-rw-r--r--gcc/config/i386/i386-c.c6
-rw-r--r--gcc/config/i386/i386-protos.h9
-rw-r--r--gcc/config/i386/i386.c214
-rw-r--r--gcc/config/i386/i386.h43
-rw-r--r--gcc/config/i386/i386.md124
-rw-r--r--gcc/config/i386/i386.opt12
-rw-r--r--gcc/config/i386/predicates.md10
-rw-r--r--gcc/config/i386/winnt.c8
-rw-r--r--gcc/config/i386/x86intrin.h6
-rw-r--r--gcc/config/i386/xmmintrin.h20
-rw-r--r--gcc/config/i386/xsavecintrin.h58
-rw-r--r--gcc/config/i386/xsavesintrin.h72
-rw-r--r--gcc/config/ia64/ia64.c60
-rw-r--r--gcc/config/ia64/ia64.opt6
-rw-r--r--gcc/config/initfini-array.h9
-rw-r--r--gcc/config/iq2000/iq2000.c3
-rw-r--r--gcc/config/iq2000/iq2000.md10
-rw-r--r--gcc/config/lm32/lm32.c1
-rw-r--r--gcc/config/m32c/m32c.c5
-rw-r--r--gcc/config/m32r/m32r.c1
-rw-r--r--gcc/config/m68k/m68k.c1
-rw-r--r--gcc/config/m68k/m68k.md14
-rw-r--r--gcc/config/mcore/mcore.c1
-rw-r--r--gcc/config/mep/mep.c9
-rw-r--r--gcc/config/microblaze/microblaze-protos.h4
-rw-r--r--gcc/config/microblaze/microblaze.c41
-rw-r--r--gcc/config/microblaze/microblaze.h5
-rw-r--r--gcc/config/microblaze/microblaze.md28
-rw-r--r--gcc/config/mips/mips.c30
-rw-r--r--gcc/config/mips/mips.h7
-rw-r--r--gcc/config/mmix/mmix-protos.h6
-rw-r--r--gcc/config/mmix/mmix.c100
-rw-r--r--gcc/config/mmix/mmix.md2
-rw-r--r--gcc/config/mn10300/mn10300.c1
-rw-r--r--gcc/config/moxie/moxie.c3
-rw-r--r--gcc/config/msp430/msp430.c243
-rw-r--r--gcc/config/msp430/msp430.h4
-rw-r--r--gcc/config/msp430/msp430.md109
-rw-r--r--gcc/config/msp430/predicates.md4
-rw-r--r--gcc/config/nds32/nds32.c3
-rw-r--r--gcc/config/nds32/nds32.md26
-rw-r--r--gcc/config/newlib-stdint.h9
-rw-r--r--gcc/config/nios2/nios2.c2
-rw-r--r--gcc/config/nios2/nios2.md4
-rw-r--r--gcc/config/pa/pa.c5
-rw-r--r--gcc/config/pdp11/pdp11.c1
-rw-r--r--gcc/config/picochip/picochip.c1
-rw-r--r--gcc/config/rl78/rl78.c3
-rw-r--r--gcc/config/rs6000/40x.md32
-rw-r--r--gcc/config/rs6000/440.md27
-rw-r--r--gcc/config/rs6000/476.md22
-rw-r--r--gcc/config/rs6000/601.md23
-rw-r--r--gcc/config/rs6000/603.md24
-rw-r--r--gcc/config/rs6000/6xx.md43
-rw-r--r--gcc/config/rs6000/7450.md27
-rw-r--r--gcc/config/rs6000/7xx.md28
-rw-r--r--gcc/config/rs6000/8540.md14
-rw-r--r--gcc/config/rs6000/a2.md18
-rw-r--r--gcc/config/rs6000/cell.md72
-rw-r--r--gcc/config/rs6000/dfp.md18
-rw-r--r--gcc/config/rs6000/e300c2c3.md20
-rw-r--r--gcc/config/rs6000/e500mc.md18
-rw-r--r--gcc/config/rs6000/e500mc64.md31
-rw-r--r--gcc/config/rs6000/e5500.md40
-rw-r--r--gcc/config/rs6000/e6500.md41
-rw-r--r--gcc/config/rs6000/htm.md2
-rw-r--r--gcc/config/rs6000/htmxlintrin.h9
-rw-r--r--gcc/config/rs6000/mpc.md21
-rw-r--r--gcc/config/rs6000/power4.md86
-rw-r--r--gcc/config/rs6000/power5.md86
-rw-r--r--gcc/config/rs6000/power6.md95
-rw-r--r--gcc/config/rs6000/power7.md68
-rw-r--r--gcc/config/rs6000/power8.md62
-rw-r--r--gcc/config/rs6000/predicates.md11
-rw-r--r--gcc/config/rs6000/rs6000-protos.h2
-rw-r--r--gcc/config/rs6000/rs6000.c673
-rw-r--r--gcc/config/rs6000/rs6000.md1344
-rw-r--r--gcc/config/rs6000/rs64.md34
-rw-r--r--gcc/config/rs6000/titan.md29
-rw-r--r--gcc/config/rs6000/vsx.md33
-rw-r--r--gcc/config/rs6000/vxworks.h7
-rw-r--r--gcc/config/rs6000/vxworksae.h23
-rw-r--r--gcc/config/rs6000/xfpu.md6
-rw-r--r--gcc/config/rtems.h9
-rw-r--r--gcc/config/rx/rx.c90
-rw-r--r--gcc/config/s390/s390.c3
-rw-r--r--gcc/config/score/score.c3
-rw-r--r--gcc/config/sh/predicates.md28
-rw-r--r--gcc/config/sh/sh-mem.cc35
-rw-r--r--gcc/config/sh/sh.c90
-rw-r--r--gcc/config/sh/sh.h23
-rw-r--r--gcc/config/sh/sh.md105
-rw-r--r--gcc/config/sol2-clearcap.map2
-rw-r--r--gcc/config/sol2-clearcapv2.map7
-rw-r--r--gcc/config/sol2.h11
-rw-r--r--gcc/config/sol2.opt4
-rw-r--r--gcc/config/sparc/sparc-protos.h1
-rw-r--r--gcc/config/sparc/sparc.c27
-rw-r--r--gcc/config/sparc/sparc.md299
-rw-r--r--gcc/config/spu/spu.c3
-rw-r--r--gcc/config/stormy16/stormy16.c1
-rw-r--r--gcc/config/t-sol27
-rw-r--r--gcc/config/tilegx/tilegx.c3
-rw-r--r--gcc/config/tilepro/tilepro.c3
-rw-r--r--gcc/config/v850/rtems.h9
-rw-r--r--gcc/config/v850/v850-opts.h9
-rw-r--r--gcc/config/v850/v850.c1
-rw-r--r--gcc/config/v850/v850.h9
-rw-r--r--gcc/config/vax/vax.c1
-rw-r--r--gcc/config/vax/vax.md2
-rw-r--r--gcc/config/xtensa/xtensa.c3
-rwxr-xr-xgcc/configure134
-rw-r--r--gcc/configure.ac37
-rw-r--r--gcc/convert.c15
-rw-r--r--gcc/coretypes.h4
-rw-r--r--gcc/coverage.c2
-rw-r--r--gcc/cp/ChangeLog356
-rw-r--r--gcc/cp/call.c388
-rw-r--r--gcc/cp/class.c7
-rw-r--r--gcc/cp/cp-array-notation.c7
-rw-r--r--gcc/cp/cp-cilkplus.c2
-rw-r--r--gcc/cp/cp-lang.c20
-rw-r--r--gcc/cp/cp-objcp-common.c2
-rw-r--r--gcc/cp/cp-tree.h24
-rw-r--r--gcc/cp/cvt.c9
-rw-r--r--gcc/cp/cxx-pretty-print.c4
-rw-r--r--gcc/cp/decl.c118
-rw-r--r--gcc/cp/decl2.c29
-rw-r--r--gcc/cp/error.c1
-rw-r--r--gcc/cp/init.c41
-rw-r--r--gcc/cp/lambda.c61
-rw-r--r--gcc/cp/lex.c11
-rw-r--r--gcc/cp/mangle.c11
-rw-r--r--gcc/cp/name-lookup.c14
-rw-r--r--gcc/cp/optimize.c8
-rw-r--r--gcc/cp/parser.c92
-rw-r--r--gcc/cp/pt.c584
-rw-r--r--gcc/cp/rtti.c7
-rw-r--r--gcc/cp/search.c6
-rw-r--r--gcc/cp/semantics.c41
-rw-r--r--gcc/cp/tree.c17
-rw-r--r--gcc/cp/typeck.c38
-rw-r--r--gcc/cp/typeck2.c67
-rw-r--r--gcc/dbgcnt.def1
-rw-r--r--gcc/dbxout.c2
-rw-r--r--gcc/df-scan.c5
-rw-r--r--gcc/doc/arm-neon-intrinsics.texi2
-rw-r--r--gcc/doc/avr-mmcu.texi4
-rw-r--r--gcc/doc/extend.texi1612
-rw-r--r--gcc/doc/gty.texi32
-rw-r--r--gcc/doc/invoke.texi115
-rw-r--r--gcc/doc/md.texi19
-rw-r--r--gcc/doc/passes.texi14
-rw-r--r--gcc/doc/sourcebuild.texi31
-rw-r--r--gcc/doc/tm.texi100
-rw-r--r--gcc/doc/tm.texi.in59
-rw-r--r--gcc/double-int.c2
-rw-r--r--gcc/dwarf2cfi.c8
-rw-r--r--gcc/dwarf2out.c80
-rw-r--r--gcc/emit-rtl.c139
-rw-r--r--gcc/emit-rtl.h4
-rw-r--r--gcc/except.c37
-rw-r--r--gcc/explow.c34
-rw-r--r--gcc/expr.c38
-rw-r--r--gcc/expr.h14
-rw-r--r--gcc/final.c120
-rw-r--r--gcc/flag-types.h4
-rw-r--r--gcc/fold-const.c191
-rw-r--r--gcc/fold-const.h1
-rw-r--r--gcc/fortran/ChangeLog303
-rw-r--r--gcc/fortran/check.c177
-rw-r--r--gcc/fortran/dump-parse-tree.c100
-rw-r--r--gcc/fortran/error.c2
-rw-r--r--gcc/fortran/f95-lang.c14
-rw-r--r--gcc/fortran/frontend-passes.c43
-rw-r--r--gcc/fortran/gfc-internals.texi8
-rw-r--r--gcc/fortran/gfortran.h94
-rw-r--r--gcc/fortran/gfortran.texi26
-rw-r--r--gcc/fortran/intrinsic.c63
-rw-r--r--gcc/fortran/intrinsic.h11
-rw-r--r--gcc/fortran/intrinsic.texi220
-rw-r--r--gcc/fortran/invoke.texi2
-rw-r--r--gcc/fortran/iresolve.c5
-rw-r--r--gcc/fortran/match.c21
-rw-r--r--gcc/fortran/match.h7
-rw-r--r--gcc/fortran/module.c110
-rw-r--r--gcc/fortran/openmp.c736
-rw-r--r--gcc/fortran/parse.c84
-rw-r--r--gcc/fortran/resolve.c101
-rw-r--r--gcc/fortran/simplify.c19
-rw-r--r--gcc/fortran/st.c8
-rw-r--r--gcc/fortran/symbol.c1
-rw-r--r--gcc/fortran/trans-array.c1
-rw-r--r--gcc/fortran/trans-decl.c39
-rw-r--r--gcc/fortran/trans-intrinsic.c175
-rw-r--r--gcc/fortran/trans-io.c9
-rw-r--r--gcc/fortran/trans-openmp.c627
-rw-r--r--gcc/fortran/trans-stmt.h1
-rw-r--r--gcc/fortran/trans-types.c12
-rw-r--r--gcc/fortran/trans.c12
-rw-r--r--gcc/fortran/trans.h10
-rw-r--r--gcc/fortran/types.def8
-rw-r--r--gcc/function.c833
-rw-r--r--gcc/function.h4
-rw-r--r--gcc/gcc.c2
-rw-r--r--gcc/gcov-dump.c26
-rw-r--r--gcc/gcov-io.c55
-rw-r--r--gcc/gcov-io.h11
-rw-r--r--gcc/gcov.c2
-rw-r--r--gcc/genattrtab.c11
-rw-r--r--gcc/gencodes.c10
-rw-r--r--gcc/gengenrtl.c7
-rw-r--r--gcc/gengtype-lex.l2
-rw-r--r--gcc/gengtype-parse.c32
-rw-r--r--gcc/gengtype-state.c2
-rw-r--r--gcc/gengtype.c221
-rw-r--r--gcc/gengtype.h12
-rw-r--r--gcc/genoutput.c5
-rw-r--r--gcc/ggc-common.c15
-rw-r--r--gcc/ggc-none.c13
-rw-r--r--gcc/ggc-page.c111
-rw-r--r--gcc/ggc.h147
-rw-r--r--gcc/gimple-fold.c98
-rw-r--r--gcc/gimple-ssa-strength-reduction.c1
-rw-r--r--gcc/gimple.c19
-rw-r--r--gcc/gimple.h28
-rw-r--r--gcc/gimplify.c40
-rw-r--r--gcc/ginclude/stddef.h4
-rw-r--r--gcc/go/ChangeLog8
-rw-r--r--gcc/go/go-gcc.cc1
-rw-r--r--gcc/go/go-lang.c2
-rw-r--r--gcc/haifa-sched.c276
-rw-r--r--gcc/hw-doloop.c4
-rw-r--r--gcc/hwint.h135
-rw-r--r--gcc/ifcvt.c20
-rw-r--r--gcc/ipa-comdats.c388
-rw-r--r--gcc/ipa-cp.c16
-rw-r--r--gcc/ipa-devirt.c20
-rw-r--r--gcc/ipa-inline-transform.c13
-rw-r--r--gcc/ipa-inline.c66
-rw-r--r--gcc/ipa-inline.h3
-rw-r--r--gcc/ipa-profile.c16
-rw-r--r--gcc/ipa-prop.c843
-rw-r--r--gcc/ipa-prop.h5
-rw-r--r--gcc/ipa-visibility.c816
-rw-r--r--gcc/ipa.c785
-rw-r--r--gcc/ira-build.c10
-rw-r--r--gcc/ira-color.c6
-rw-r--r--gcc/ira-conflicts.c4
-rw-r--r--gcc/ira-costs.c222
-rw-r--r--gcc/ira-int.h9
-rw-r--r--gcc/ira-lives.c48
-rw-r--r--gcc/ira.c68
-rw-r--r--gcc/java/ChangeLog23
-rw-r--r--gcc/java/class.c5
-rw-r--r--gcc/java/constants.c9
-rw-r--r--gcc/java/decl.c4
-rw-r--r--gcc/java/expr.c2
-rw-r--r--gcc/java/java-tree.h13
-rw-r--r--gcc/java/jcf-parse.c6
-rw-r--r--gcc/java/jcf-reader.c11
-rw-r--r--gcc/java/jcf.h2
-rw-r--r--gcc/jump.c6
-rw-r--r--gcc/langhooks-def.h5
-rw-r--r--gcc/langhooks.c9
-rw-r--r--gcc/langhooks.h6
-rw-r--r--gcc/loop-doloop.c2
-rw-r--r--gcc/loop-iv.c28
-rw-r--r--gcc/loop-unroll.c6
-rw-r--r--gcc/lra-assigns.c13
-rw-r--r--gcc/lra-constraints.c41
-rw-r--r--gcc/lra-eliminations.c10
-rw-r--r--gcc/lra-int.h6
-rw-r--r--gcc/lra-lives.c11
-rw-r--r--gcc/lra.c51
-rw-r--r--gcc/lto-cgraph.c103
-rw-r--r--gcc/lto-section-in.c2
-rw-r--r--gcc/lto-section-names.h28
-rw-r--r--gcc/lto-streamer-in.c8
-rw-r--r--gcc/lto-streamer-out.c7
-rw-r--r--gcc/lto-streamer.c1
-rw-r--r--gcc/lto-streamer.h6
-rw-r--r--gcc/lto-wrapper.c8
-rw-r--r--gcc/lto/ChangeLog45
-rw-r--r--gcc/lto/lto-lang.c12
-rw-r--r--gcc/lto/lto-object.c6
-rw-r--r--gcc/lto/lto-symtab.c10
-rw-r--r--gcc/lto/lto-tree.h4
-rw-r--r--gcc/lto/lto.c20
-rw-r--r--gcc/mcf.c48
-rw-r--r--gcc/mode-switching.c114
-rw-r--r--gcc/modulo-sched.c30
-rw-r--r--gcc/objc/ChangeLog11
-rw-r--r--gcc/objc/objc-act.c4
-rw-r--r--gcc/objc/objc-act.h3
-rw-r--r--gcc/objc/objc-map.c10
-rw-r--r--gcc/objc/objc-next-runtime-abi-02.c4
-rw-r--r--gcc/objcp/ChangeLog4
-rw-r--r--gcc/objcp/objcp-decl.h4
-rw-r--r--gcc/omp-low.c227
-rw-r--r--gcc/optabs.c28
-rw-r--r--gcc/optabs.h21
-rw-r--r--gcc/optc-gen.awk6
-rw-r--r--gcc/opts.c22
-rw-r--r--gcc/params.def6
-rw-r--r--gcc/passes.c2
-rw-r--r--gcc/passes.def4
-rw-r--r--gcc/po/ChangeLog4
-rw-r--r--gcc/po/zh_CN.po1532
-rw-r--r--gcc/postreload.c2
-rw-r--r--gcc/predict.c6
-rw-r--r--gcc/pretty-print.h2
-rw-r--r--gcc/print-rtl.c48
-rw-r--r--gcc/profile.c16
-rw-r--r--gcc/realmpfr.h3
-rw-r--r--gcc/recog.c81
-rw-r--r--gcc/recog.h42
-rw-r--r--gcc/ree.c47
-rw-r--r--gcc/reg-notes.def5
-rw-r--r--gcc/regcprop.c23
-rw-r--r--gcc/regcprop.h27
-rw-r--r--gcc/reginfo.c1
-rw-r--r--gcc/regs.h8
-rw-r--r--gcc/reload.c2
-rw-r--r--gcc/reload1.c101
-rw-r--r--gcc/reorg.c13
-rw-r--r--gcc/resource.c10
-rw-r--r--gcc/rtl.c2
-rw-r--r--gcc/rtl.def52
-rw-r--r--gcc/rtl.h126
-rw-r--r--gcc/sanitizer.def14
-rw-r--r--gcc/sched-int.h51
-rw-r--r--gcc/sel-sched-ir.c56
-rw-r--r--gcc/sel-sched.c32
-rw-r--r--gcc/sese.c2
-rw-r--r--gcc/shrink-wrap.c935
-rw-r--r--gcc/shrink-wrap.h52
-rw-r--r--gcc/simplify-rtx.c27
-rw-r--r--gcc/stmt.c19
-rw-r--r--gcc/stringpool.c8
-rw-r--r--gcc/symtab.c171
-rw-r--r--gcc/system.h11
-rw-r--r--gcc/target-globals.c7
-rw-r--r--gcc/target-globals.h3
-rw-r--r--gcc/target.def76
-rw-r--r--gcc/target.h2
-rw-r--r--gcc/targhooks.c25
-rw-r--r--gcc/testsuite/ChangeLog1009
-rw-r--r--gcc/testsuite/c-c++-common/asan/asan-interface-1.c13
-rw-r--r--gcc/testsuite/c-c++-common/asan/misalign-1.c42
-rw-r--r--gcc/testsuite/c-c++-common/asan/misalign-2.c42
-rw-r--r--gcc/testsuite/c-c++-common/attributes-1.c2
-rw-r--r--gcc/testsuite/c-c++-common/attributes-2.c3
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/AN/pr61191.c10
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/invalid_sync.cc9
-rw-r--r--gcc/testsuite/c-c++-common/gomp/simd4.c2
-rw-r--r--gcc/testsuite/c-c++-common/pr50459-2.c7
-rw-r--r--gcc/testsuite/c-c++-common/pr50459.c12
-rw-r--r--gcc/testsuite/c-c++-common/pr59280.c2
-rw-r--r--gcc/testsuite/c-c++-common/torture/pr61184.c18
-rw-r--r--gcc/testsuite/c-c++-common/tsan/mutexset1.c2
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c204
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c79
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-2.c73
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-3.c40
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-4.c52
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-5.c40
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-6.c40
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c196
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.h156
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c205
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c61
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/float-cast.h39
-rw-r--r--gcc/testsuite/g++.dg/asan/asan_mem_test.cc22
-rw-r--r--gcc/testsuite/g++.dg/asan/asan_oob_test.cc2
-rw-r--r--gcc/testsuite/g++.dg/asan/asan_str_test.cc37
-rw-r--r--gcc/testsuite/g++.dg/asan/asan_test.C2
-rw-r--r--gcc/testsuite/g++.dg/asan/asan_test.cc370
-rw-r--r--gcc/testsuite/g++.dg/asan/asan_test_config.h16
-rw-r--r--gcc/testsuite/g++.dg/asan/asan_test_utils.h24
-rw-r--r--gcc/testsuite/g++.dg/asan/sanitizer_pthread_wrappers.h64
-rw-r--r--gcc/testsuite/g++.dg/asan/sanitizer_test_config.h28
-rw-r--r--gcc/testsuite/g++.dg/asan/sanitizer_test_utils.h74
-rw-r--r--gcc/testsuite/g++.dg/asan/symbolize-callback-1.C21
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/AN/array_function.cc8
-rw-r--r--gcc/testsuite/g++.dg/compat/compat.exp1
-rw-r--r--gcc/testsuite/g++.dg/compat/struct-layout-1.exp1
-rw-r--r--gcc/testsuite/g++.dg/conversion/ambig1.C1
-rw-r--r--gcc/testsuite/g++.dg/conversion/op1.C1
-rw-r--r--gcc/testsuite/g++.dg/conversion/op4.C4
-rw-r--r--gcc/testsuite/g++.dg/conversion/op5.C2
-rw-r--r--gcc/testsuite/g++.dg/conversion/simd1.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wattributes1.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype-call1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype58.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype59.C41
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted14.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted18.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted20.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/diag2.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/explicit3.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/explicit4.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/forw_enum6.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist84.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-59483.C31
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-61148.C33
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-this.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice13.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice7.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi6.C23
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this18.C30
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept15.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-template11.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-union6.C56
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr19.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/overloadn.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31434.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31437.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr57543-1.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr57543-2.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr57543-3.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr61038.C40
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-cond1.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-cond2.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv1n.C70
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv2n.C395
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv3n.C679
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv4n.C712
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv5n.C462
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv6n.C209
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv7n.C45
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae50.C41
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae51.C28
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic157.C28
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-35147.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-init6.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-init8.C26
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-init9.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr60054.C11
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/pr13981.C12
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/ref1.C7
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/ref2.C9
-rw-r--r--gcc/testsuite/g++.dg/eh/spec6.C2
-rw-r--r--gcc/testsuite/g++.dg/expr/cast1.C2
-rw-r--r--gcc/testsuite/g++.dg/expr/cond10.C17
-rw-r--r--gcc/testsuite/g++.dg/expr/cond11.C20
-rw-r--r--gcc/testsuite/g++.dg/expr/cond12.C12
-rw-r--r--gcc/testsuite/g++.dg/expr/cond13.C9
-rw-r--r--gcc/testsuite/g++.dg/expr/cond14.C6
-rw-r--r--gcc/testsuite/g++.dg/expr/cond8.C5
-rw-r--r--gcc/testsuite/g++.dg/expr/cond9.C8
-rw-r--r--gcc/testsuite/g++.dg/expr/dtor1.C2
-rw-r--r--gcc/testsuite/g++.dg/expr/pmf-1.C1
-rw-r--r--gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/redecl1.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/visibility-7.C2
-rw-r--r--gcc/testsuite/g++.dg/fstack-protector-strong.C50
-rw-r--r--gcc/testsuite/g++.dg/gomp/pr26690-1.C1
-rw-r--r--gcc/testsuite/g++.dg/gomp/pr26690-2.C1
-rw-r--r--gcc/testsuite/g++.dg/gomp/pr49223-2.C2
-rw-r--r--gcc/testsuite/g++.dg/gomp/udr-4.C2
-rw-r--r--gcc/testsuite/g++.dg/init/copy7.C9
-rw-r--r--gcc/testsuite/g++.dg/init/delete1.C2
-rw-r--r--gcc/testsuite/g++.dg/init/synth2.C3
-rw-r--r--gcc/testsuite/g++.dg/ipa/comdat.C15
-rw-r--r--gcc/testsuite/g++.dg/ipa/devirt-11.C7
-rw-r--r--gcc/testsuite/g++.dg/ipa/devirt-15.C4
-rw-r--r--gcc/testsuite/g++.dg/ipa/devirt-16.C4
-rw-r--r--gcc/testsuite/g++.dg/ipa/devirt-17.C4
-rw-r--r--gcc/testsuite/g++.dg/ipa/devirt-26.C4
-rw-r--r--gcc/testsuite/g++.dg/ipa/devirt-33.C78
-rw-r--r--gcc/testsuite/g++.dg/ipa/imm-devirt-1.C2
-rw-r--r--gcc/testsuite/g++.dg/ipa/imm-devirt-2.C2
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr61085.C33
-rw-r--r--gcc/testsuite/g++.dg/lookup/conv-1.C1
-rw-r--r--gcc/testsuite/g++.dg/lookup/new1.C1
-rw-r--r--gcc/testsuite/g++.dg/lookup/two-stage4.C6
-rw-r--r--gcc/testsuite/g++.dg/lookup/using9.C1
-rw-r--r--gcc/testsuite/g++.dg/other/crash-2.C2
-rw-r--r--gcc/testsuite/g++.dg/other/error13.C1
-rw-r--r--gcc/testsuite/g++.dg/other/error20.C1
-rw-r--r--gcc/testsuite/g++.dg/other/error31.C1
-rw-r--r--gcc/testsuite/g++.dg/other/i386-2.C2
-rw-r--r--gcc/testsuite/g++.dg/other/i386-3.C2
-rw-r--r--gcc/testsuite/g++.dg/other/pr28114.C1
-rw-r--r--gcc/testsuite/g++.dg/overload/ambig1.C1
-rw-r--r--gcc/testsuite/g++.dg/overload/arg3.C7
-rw-r--r--gcc/testsuite/g++.dg/overload/builtin1.C1
-rw-r--r--gcc/testsuite/g++.dg/overload/conv-op1.C2
-rw-r--r--gcc/testsuite/g++.dg/overload/copy1.C7
-rw-r--r--gcc/testsuite/g++.dg/overload/new1.C1
-rw-r--r--gcc/testsuite/g++.dg/overload/template4.C3
-rw-r--r--gcc/testsuite/g++.dg/overload/using2.C3
-rw-r--r--gcc/testsuite/g++.dg/overload/volatile1.C7
-rw-r--r--gcc/testsuite/g++.dg/parse/crash24.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/crash25.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/crash31.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/crash41.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/crash49.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/crash5.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/crash50.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/crash54.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/dtor7.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/error19.C5
-rw-r--r--gcc/testsuite/g++.dg/parse/error28.C1
-rw-r--r--gcc/testsuite/g++.dg/parse/error40.C4
-rw-r--r--gcc/testsuite/g++.dg/parse/error54.C19
-rw-r--r--gcc/testsuite/g++.dg/parse/fused-params1.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/new1.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/pr58664.C66
-rw-r--r--gcc/testsuite/g++.dg/pr60969.C32
-rw-r--r--gcc/testsuite/g++.dg/pr61094.C31
-rw-r--r--gcc/testsuite/g++.dg/rtti/dyncast6.C14
-rw-r--r--gcc/testsuite/g++.dg/tc1/dr152.C6
-rw-r--r--gcc/testsuite/g++.dg/template/array28.C7
-rw-r--r--gcc/testsuite/g++.dg/template/copy1.C7
-rw-r--r--gcc/testsuite/g++.dg/template/crash107.C2
-rw-r--r--gcc/testsuite/g++.dg/template/crash35.C2
-rw-r--r--gcc/testsuite/g++.dg/template/crash59.C2
-rw-r--r--gcc/testsuite/g++.dg/template/crash77.C2
-rw-r--r--gcc/testsuite/g++.dg/template/dependent-expr5.C8
-rw-r--r--gcc/testsuite/g++.dg/template/error2.C3
-rw-r--r--gcc/testsuite/g++.dg/template/error38.C4
-rw-r--r--gcc/testsuite/g++.dg/template/error40.C2
-rw-r--r--gcc/testsuite/g++.dg/template/error46.C2
-rw-r--r--gcc/testsuite/g++.dg/template/error47.C2
-rw-r--r--gcc/testsuite/g++.dg/template/error51.C2
-rw-r--r--gcc/testsuite/g++.dg/template/incomplete1.C2
-rw-r--r--gcc/testsuite/g++.dg/template/incomplete2.C1
-rw-r--r--gcc/testsuite/g++.dg/template/incomplete3.C2
-rw-r--r--gcc/testsuite/g++.dg/template/incomplete4.C4
-rw-r--r--gcc/testsuite/g++.dg/template/incomplete5.C4
-rw-r--r--gcc/testsuite/g++.dg/template/inherit8.C2
-rw-r--r--gcc/testsuite/g++.dg/template/instantiate1.C2
-rw-r--r--gcc/testsuite/g++.dg/template/instantiate3.C2
-rw-r--r--gcc/testsuite/g++.dg/template/instantiate5.C1
-rw-r--r--gcc/testsuite/g++.dg/template/local4.C1
-rw-r--r--gcc/testsuite/g++.dg/template/local8.C18
-rw-r--r--gcc/testsuite/g++.dg/template/new3.C1
-rw-r--r--gcc/testsuite/g++.dg/template/offsetof2.C2
-rw-r--r--gcc/testsuite/g++.dg/template/operator9.C1
-rw-r--r--gcc/testsuite/g++.dg/template/pr51199.C17
-rw-r--r--gcc/testsuite/g++.dg/template/pr54310.C19
-rw-r--r--gcc/testsuite/g++.dg/template/ptrmem2.C1
-rw-r--r--gcc/testsuite/g++.dg/template/ptrmem20.C1
-rw-r--r--gcc/testsuite/g++.dg/template/qualttp5.C1
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae2.C1
-rw-r--r--gcc/testsuite/g++.dg/template/spec22.C2
-rw-r--r--gcc/testsuite/g++.dg/template/spec23.C1
-rw-r--r--gcc/testsuite/g++.dg/template/typedef4.C1
-rw-r--r--gcc/testsuite/g++.dg/tm/pr51928.C2
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr61009.C53
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr8781.C2
-rw-r--r--gcc/testsuite/g++.dg/ubsan/float-cast-overflow-bf.C62
-rw-r--r--gcc/testsuite/g++.dg/ubsan/pr61272.C24
-rw-r--r--gcc/testsuite/g++.dg/warn/Wdelete-incomplete-1.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/incomplete1.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/incomplete2.C4
-rw-r--r--gcc/testsuite/g++.dg/warn/return-reference.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.benjamin/15799.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.benjamin/15800-1.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bob/inherit2.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/ambiguity1.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/crash29.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/crash48.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/cvt3.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/friend4.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/overload1.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/overload4.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/overload9.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900121_01.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900127_01.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900205_04.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900214_01.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900404_03.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900514_03.C12
-rw-r--r--gcc/testsuite/g++.old-deja/g++.eh/catch1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.eh/ctor1.C5
-rw-r--r--gcc/testsuite/g++.old-deja/g++.eh/spec6.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/conversion10.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/conversion11.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/crash3.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/overload16.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/overload28.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/scoping10.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/template30.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/temporary2.C8
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/arg1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/arg11.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/arm9.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/ctors11.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/ctors17.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/ctors5.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/ctors9.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/cvt20.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/enum4.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/init8.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/missed-error2.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/operators9.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/net2.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/net22.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/net8.C8
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p1989.C7
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p2431.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p438.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p701.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p7868.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p807a.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p9068.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.niklas/t120.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.niklas/t121.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.niklas/t128.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.ns/overload2.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.ns/using12.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/crash24.C5
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/crash38.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/enum2.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/expr1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/incomplete.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/overload11.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/vaarg3.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/volatile1.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/auto_ptr.C9
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/crash60.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/crash9.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/explicit38.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/explicit39.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/explicit41.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/explicit67.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ptrmem10.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/spec35.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/t05.C5
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/t24.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/typename8.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/unify6.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/unify8.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.robertl/eb109.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.robertl/eb119.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.robertl/eb131.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.robertl/eb22.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.robertl/eb69.C1
-rw-r--r--gcc/testsuite/g++.old-deja/g++.robertl/ice990323-1.C2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr61222-1.c23
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr61222-2.c7
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20101011-1.c6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/bswap-2.c90
-rw-r--r--gcc/testsuite/gcc.dg/Wstrict-overflow-18.c9
-rw-r--r--gcc/testsuite/gcc.dg/Wstrict-overflow-25.c11
-rw-r--r--gcc/testsuite/gcc.dg/debug/pr35154.c3
-rw-r--r--gcc/testsuite/gcc.dg/dfp/wtr-conversion-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/fold-compare-8.c11
-rw-r--r--gcc/testsuite/gcc.dg/fstack-protector-strong.c20
-rw-r--r--gcc/testsuite/gcc.dg/init-string-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr61278_0.c30
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr61278_1.c10
-rw-r--r--gcc/testsuite/gcc.dg/nonnull-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/optimize-bswapdi-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/optimize-bswapdi-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/optimize-bswapdi-3.c64
-rw-r--r--gcc/testsuite/gcc.dg/optimize-bswaphi-1.c47
-rw-r--r--gcc/testsuite/gcc.dg/optimize-bswapsi-1.c3
-rw-r--r--gcc/testsuite/gcc.dg/optimize-bswapsi-2.c49
-rw-r--r--gcc/testsuite/gcc.dg/pedwarn-init.c19
-rw-r--r--gcc/testsuite/gcc.dg/pr55570.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr56724-1.c33
-rw-r--r--gcc/testsuite/gcc.dg/pr56724-2.c31
-rw-r--r--gcc/testsuite/gcc.dg/pr60866.c18
-rw-r--r--gcc/testsuite/gcc.dg/pr61045.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr61053.c75
-rw-r--r--gcc/testsuite/gcc.dg/pr61060.c19
-rw-r--r--gcc/testsuite/gcc.dg/pr61077.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr61096-1.c61
-rw-r--r--gcc/testsuite/gcc.dg/pr61096-2.c10
-rw-r--r--gcc/testsuite/gcc.dg/pr61158.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr61162.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr61220.c39
-rw-r--r--gcc/testsuite/gcc.dg/shrink-wrap-loop.c20
-rw-r--r--gcc/testsuite/gcc.dg/sibcall-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/sibcall-4.c2
-rw-r--r--gcc/testsuite/gcc.dg/tm/wrap-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr61095.c23
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr61136.c5
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr61221.c32
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr61346.c162
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-33.c20
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ivopts-lower_base.c61
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-12.c23
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-13.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr21559.c1
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr23401.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr27810.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr61090.c21
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr61140.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr61150.c24
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr61197.c26
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-6.c1
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-39.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-40.c17
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-41.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-2.c10
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp92.c23
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/writeonly.c20
-rw-r--r--gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-bf.c72
-rw-r--r--gcc/testsuite/gcc.dg/uninit-13.c4
-rw-r--r--gcc/testsuite/gcc.dg/uninit-17-O0.c15
-rw-r--r--gcc/testsuite/gcc.dg/uninit-17.c15
-rw-r--r--gcc/testsuite/gcc.dg/unused-8a.c4
-rw-r--r--gcc/testsuite/gcc.dg/unused-8b.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr52252-ld.c5
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr61194.c43
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect.exp25
-rw-r--r--gcc/testsuite/gcc.dg/wtr-conversion-1.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr61325.c19
-rw-r--r--gcc/testsuite/gcc.target/aarch64/tail_indirect_call_1.c18
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextQf32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextQp16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextQp64_1.c33
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextQp8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextQs16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextQs32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextQs64_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextQs8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextQu16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextQu32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextQu64_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextQu8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextf32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextp16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextp64_1.c26
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextp8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vexts16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vexts32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vexts64_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vexts8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextu16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextu32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextu64_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vextu8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev16p8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev16qp8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev16qs8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev16qu8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev16s8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev16u8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev32p16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev32p8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev32qp16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev32qp8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev32qs16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev32qs8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev32qu16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev32qu8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev32s16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev32s8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev32u16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev32u8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64f32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64p16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64p8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64qf32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64qp16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64qp8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64qs16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64qs32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64qs8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64qu16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64qu32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64qu8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64s16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64s32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64s8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64u16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64u32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vrev64u8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnf32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnp16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnp8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnqf32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnqp16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnqp8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnqs16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnqs32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnqs8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnqu16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnqu32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnqu8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrns16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrns32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrns8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnu16_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnu32_1.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vtrnu8_1.c12
-rw-r--r--gcc/testsuite/gcc.target/avr/pr60991.c21
-rw-r--r--gcc/testsuite/gcc.target/avr/torture/pr61055.c88
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/clearcap.map3
-rw-r--r--gcc/testsuite/gcc.target/i386/clearcapv2.map7
-rw-r--r--gcc/testsuite/gcc.target/i386/clflushopt-1.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/fuse-caller-save.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/i386.exp36
-rw-r--r--gcc/testsuite/gcc.target/i386/pause-2.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr49002-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr53712.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr53907.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr58066.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59539-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr60901.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr61215.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/sibcall-1.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/sibcall-2.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/sibcall-3.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/sibcall-4.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/sibcall-5.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/sibcall-6.c36
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-12.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-13.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-14.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-22.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-23.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/ssp-strong-reg.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/vectorize1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-imul32widen-vector.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-imul64-vector.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-rotate1-vector.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-rotate2-vector.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-rotate3-vector.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-shift1-vector.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-shift2-vector.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-shift3-vector.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/xsavec-1.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/xsavec64-1.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/xsaves-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/xsaves64-1.c13
-rw-r--r--gcc/testsuite/gcc.target/ia64/visibility-1.c4
-rw-r--r--gcc/testsuite/gcc.target/microblaze/others/break_handler.c15
-rw-r--r--gcc/testsuite/gcc.target/mips/fuse-caller-save-micromips.c17
-rw-r--r--gcc/testsuite/gcc.target/mips/fuse-caller-save-mips16.c17
-rw-r--r--gcc/testsuite/gcc.target/mips/fuse-caller-save.c17
-rw-r--r--gcc/testsuite/gcc.target/mips/fuse-caller-save.h17
-rw-r--r--gcc/testsuite/gcc.target/mips/loongson-simd.c8
-rw-r--r--gcc/testsuite/gcc.target/mips/mips.exp1
-rw-r--r--gcc/testsuite/gcc.target/mips/near-far-1.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/near-far-2.c8
-rw-r--r--gcc/testsuite/gcc.target/mips/near-far-4.c4
-rw-r--r--gcc/testsuite/gcc.target/nios2/custom-fp-lto.c29
-rw-r--r--gcc/testsuite/gcc.target/powerpc/htm-ttest.c14
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pack03.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsxcopy.c15
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-14.c5
-rw-r--r--gcc/testsuite/gcc.target/sh/pr53976-1.c9
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54236-3.c31
-rw-r--r--gcc/testsuite/gcc.target/sh/pr61195.c19
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx/abi-avx.exp16
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512f/abi-avx512f.exp16
-rw-r--r--gcc/testsuite/gfortran.dg/arrayio_14.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/associate_16.f9023
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_rank_5.f902
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_type_4.f902
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_array_params.f034
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_array_params_2.f904
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_usage_28.f904
-rw-r--r--gcc/testsuite/gfortran.dg/c_funloc_tests_5.f034
-rw-r--r--gcc/testsuite/gfortran.dg/c_funloc_tests_6.f904
-rw-r--r--gcc/testsuite/gfortran.dg/c_loc_tests_11.f032
-rw-r--r--gcc/testsuite/gfortran.dg/coarray/collectives_1.f9044
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_10.f902
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_collectives_1.f9038
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_collectives_2.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_collectives_3.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_collectives_4.f9020
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_collectives_5.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_collectives_6.f9026
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_this_image_1.f9020
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_this_image_2.f9020
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/affinity-1.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/omp_do_concurrent.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/namelist_85.f9066
-rw-r--r--gcc/testsuite/gfortran.dg/namelist_utf8.f908
-rw-r--r--gcc/testsuite/gfortran.dg/pr48636-2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/pr52835.f902
-rw-r--r--gcc/testsuite/gfortran.dg/pr61209.f9046
-rw-r--r--gcc/testsuite/gfortran.dg/pr61335.f90117
-rw-r--r--gcc/testsuite/gnat.dg/aliasing1.adb2
-rw-r--r--gcc/testsuite/gnat.dg/enum3.adb23
-rw-r--r--gcc/testsuite/gnat.dg/opt35.adb25
-rw-r--r--gcc/testsuite/gnat.dg/opt35_pkg.adb11
-rw-r--r--gcc/testsuite/gnat.dg/opt35_pkg.ads9
-rw-r--r--gcc/testsuite/gnat.dg/opt36.adb23
-rw-r--r--gcc/testsuite/gnat.dg/opt37.adb42
-rw-r--r--gcc/testsuite/gnat.dg/opt37.ads18
-rw-r--r--gcc/testsuite/gnat.dg/overflow_fixed.adb19
-rw-r--r--gcc/testsuite/gnat.dg/volatile12.adb7
-rw-r--r--gcc/testsuite/gnat.dg/volatile12.ads7
-rw-r--r--gcc/testsuite/lib/asan-dg.exp23
-rw-r--r--gcc/testsuite/lib/c-compat.exp3
-rw-r--r--gcc/testsuite/lib/clearcap.exp58
-rw-r--r--gcc/testsuite/lib/scanasm.exp10
-rw-r--r--gcc/testsuite/lib/target-libpath.exp46
-rw-r--r--gcc/testsuite/lib/target-supports.exp127
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-3.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-5.mm1
-rw-r--r--gcc/testsuite/objc.dg/ivar-scope-1.m24
-rw-r--r--gcc/testsuite/objc.dg/ivar-scope-2.m34
-rw-r--r--gcc/testsuite/objc.dg/ivar-scope-3.m60
-rw-r--r--gcc/testsuite/objc.dg/ivar-scope-4.m83
-rw-r--r--gcc/testsuite/objc.dg/ivar-visibility-1.m33
-rw-r--r--gcc/testsuite/objc.dg/ivar-visibility-2.m34
-rw-r--r--gcc/testsuite/objc.dg/ivar-visibility-3.m34
-rw-r--r--gcc/testsuite/objc.dg/ivar-visibility-4.m36
-rw-r--r--gcc/testsuite/objc.dg/shadow-1.m33
-rw-r--r--gcc/testsuite/objc.dg/shadow-2.m33
-rw-r--r--gcc/timevar.def1
-rw-r--r--gcc/toplev.c7
-rw-r--r--gcc/trans-mem.c8
-rw-r--r--gcc/tree-affine.c9
-rw-r--r--gcc/tree-cfg.c53
-rw-r--r--gcc/tree-complex.c4
-rw-r--r--gcc/tree-core.h4
-rw-r--r--gcc/tree-data-ref.h2
-rw-r--r--gcc/tree-dfa.h3
-rw-r--r--gcc/tree-eh.c2
-rw-r--r--gcc/tree-inline.c11
-rw-r--r--gcc/tree-iterator.c4
-rw-r--r--gcc/tree-nested.c2
-rw-r--r--gcc/tree-object-size.c1
-rw-r--r--gcc/tree-pass.h1
-rw-r--r--gcc/tree-phinodes.c2
-rw-r--r--gcc/tree-pretty-print.c6
-rw-r--r--gcc/tree-scalar-evolution.c2
-rw-r--r--gcc/tree-sra.c3
-rw-r--r--gcc/tree-ssa-alias.c10
-rw-r--r--gcc/tree-ssa-ccp.c1
-rw-r--r--gcc/tree-ssa-dom.c8
-rw-r--r--gcc/tree-ssa-forwprop.c55
-rw-r--r--gcc/tree-ssa-loop-ivcanon.c1
-rw-r--r--gcc/tree-ssa-loop-ivopts.c47
-rw-r--r--gcc/tree-ssa-loop-niter.c2
-rw-r--r--gcc/tree-ssa-math-opts.c545
-rw-r--r--gcc/tree-ssa-operands.c4
-rw-r--r--gcc/tree-ssa-operands.h2
-rw-r--r--gcc/tree-ssa-phiopt.c116
-rw-r--r--gcc/tree-ssa-pre.c47
-rw-r--r--gcc/tree-ssa-propagate.c30
-rw-r--r--gcc/tree-ssa-reassoc.c1
-rw-r--r--gcc/tree-ssa-sccvn.c376
-rw-r--r--gcc/tree-ssa-structalias.c19
-rw-r--r--gcc/tree-ssa-threadedge.c60
-rw-r--r--gcc/tree-ssa-uninit.c44
-rw-r--r--gcc/tree-ssa.c20
-rw-r--r--gcc/tree-ssanames.c11
-rw-r--r--gcc/tree-streamer-in.c11
-rw-r--r--gcc/tree-streamer-out.c5
-rw-r--r--gcc/tree-vect-data-refs.c1
-rw-r--r--gcc/tree-vect-patterns.c47
-rw-r--r--gcc/tree-vect-stmts.c1
-rw-r--r--gcc/tree-vrp.c79
-rw-r--r--gcc/tree.c189
-rw-r--r--gcc/tree.def2
-rw-r--r--gcc/tree.h61
-rw-r--r--gcc/ubsan.c154
-rw-r--r--gcc/ubsan.h1
-rw-r--r--gcc/value-prof.c72
-rw-r--r--gcc/var-tracking.c8
-rw-r--r--gcc/varasm.c159
-rw-r--r--gcc/varpool.c5
-rw-r--r--gcc/vec.h5
-rw-r--r--gcc/vmsdbg.h8
-rw-r--r--gcc/wide-int.cc18
-rw-r--r--gcc/wide-int.h30
-rw-r--r--include/ChangeLog4
-rw-r--r--include/libiberty.h5
-rw-r--r--libbacktrace/ChangeLog8
-rw-r--r--libbacktrace/mmap.c28
-rw-r--r--libcilkrts/ChangeLog4
-rw-r--r--libcilkrts/runtime/os-unix.c7
-rw-r--r--libcpp/ChangeLog35
-rw-r--r--libcpp/config.in13
-rwxr-xr-xlibcpp/configure104
-rw-r--r--libcpp/configure.ac37
-rw-r--r--libcpp/files.c10
-rw-r--r--libcpp/include/cpplib.h5
-rw-r--r--libcpp/init.c4
-rw-r--r--libcpp/macro.c3
-rw-r--r--libffi/ChangeLog13
-rw-r--r--libffi/src/java_raw_api.c4
-rw-r--r--libffi/src/x86/ffi.c2
-rw-r--r--libffi/src/x86/win64.S168
-rw-r--r--libffi/testsuite/lib/libffi.exp4
-rw-r--r--libgcc/ChangeLog39
-rw-r--r--libgcc/config.host17
-rw-r--r--libgcc/config/arm/bpabi-lib.h4
-rw-r--r--libgcc/config/arm/sfp-machine.h8
-rw-r--r--libgcc/config/i386/dragonfly-unwind.h180
-rw-r--r--libgcc/config/msp430/t-msp4302
-rw-r--r--libgcc/config/t-slibgcc-sld4
-rw-r--r--libgcc/crtstuff.c7
-rw-r--r--libgcc/enable-execute-stack-mprotect.c15
-rw-r--r--libgcc/libgcov-driver.c7
-rw-r--r--libgcc/unwind-dw2-fde-dip.c3
-rw-r--r--libgcc/unwind-seh.c42
-rw-r--r--libgfortran/ChangeLog133
-rw-r--r--libgfortran/caf/libcaf.h19
-rw-r--r--libgfortran/caf/mpi.c2
-rw-r--r--libgfortran/caf/single.c38
-rw-r--r--libgfortran/config.h.in6
-rwxr-xr-xlibgfortran/configure23
-rw-r--r--libgfortran/configure.ac11
-rw-r--r--libgfortran/intrinsics/ctime.c70
-rw-r--r--libgfortran/intrinsics/getcwd.c38
-rw-r--r--libgfortran/io/close.c11
-rw-r--r--libgfortran/io/fbuf.c5
-rw-r--r--libgfortran/io/io.h4
-rw-r--r--libgfortran/io/list_read.c383
-rw-r--r--libgfortran/io/open.c29
-rw-r--r--libgfortran/io/unit.c7
-rw-r--r--libgfortran/io/unix.c176
-rw-r--r--libgfortran/io/unix.h4
-rw-r--r--libgfortran/libgfortran.h5
-rw-r--r--libgfortran/runtime/main.c64
-rw-r--r--libgfortran/runtime/memory.c14
-rw-r--r--libgfortran/runtime/string.c44
-rw-r--r--libgo/Makefile.am5
-rw-r--r--libgo/Makefile.in9
-rw-r--r--libgo/config.h.in3
-rwxr-xr-xlibgo/configure27
-rw-r--r--libgo/configure.ac17
-rwxr-xr-xlibgo/mksysinfo.sh39
-rw-r--r--libgo/runtime/go-cdiv.c31
-rw-r--r--libgo/runtime/go-type-complex.c110
-rw-r--r--libgo/runtime/go-type-float.c88
-rw-r--r--libgo/runtime/print.c45
-rw-r--r--libgo/runtime/proc.c3
-rw-r--r--libgo/runtime/runtime.h3
-rw-r--r--libgo/runtime/yield.c6
-rw-r--r--libgo/testsuite/Makefile.in1
-rw-r--r--libgomp/ChangeLog37
-rw-r--r--libgomp/libgomp.texi84
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-9.C52
-rw-r--r--libgomp/testsuite/libgomp.fortran/cancel-do-1.f9014
-rw-r--r--libgomp/testsuite/libgomp.fortran/cancel-do-2.f9090
-rw-r--r--libgomp/testsuite/libgomp.fortran/cancel-parallel-1.f9010
-rw-r--r--libgomp/testsuite/libgomp.fortran/cancel-parallel-3.f9038
-rw-r--r--libgomp/testsuite/libgomp.fortran/cancel-sections-1.f9023
-rw-r--r--libgomp/testsuite/libgomp.fortran/cancel-taskgroup-2.f9028
-rw-r--r--libgomp/testsuite/libgomp.fortran/declare-simd-1.f9093
-rw-r--r--libgomp/testsuite/libgomp.fortran/declare-simd-2.f9025
-rw-r--r--libgomp/testsuite/libgomp.fortran/declare-simd-3.f9022
-rw-r--r--libgomp/testsuite/libgomp.fortran/depend-1.f90203
-rw-r--r--libgomp/testsuite/libgomp.fortran/depend-2.f9034
-rw-r--r--libgomp/testsuite/libgomp.fortran/omp_atomic5.f9059
-rw-r--r--libgomp/testsuite/libgomp.fortran/simd1.f9023
-rw-r--r--libgomp/testsuite/libgomp.fortran/simd2.f90101
-rw-r--r--libgomp/testsuite/libgomp.fortran/simd3.f90109
-rw-r--r--libgomp/testsuite/libgomp.fortran/simd4.f90103
-rw-r--r--libgomp/testsuite/libgomp.fortran/taskgroup1.f9080
-rw-r--r--libiberty/ChangeLog31
-rw-r--r--libiberty/cp-demangle.c66
-rw-r--r--libiberty/cplus-dem.c7
-rw-r--r--libiberty/pex-win32.c46
-rw-r--r--libiberty/testsuite/demangle-expected31
-rw-r--r--libitm/ChangeLog17
-rw-r--r--libitm/acinclude.m410
-rw-r--r--libitm/clearcap.map14
-rw-r--r--libitm/config/aarch64/sjlj.S93
-rw-r--r--libitm/config/aarch64/target.h45
-rw-r--r--libitm/configure8
-rw-r--r--libitm/configure.tgt3
-rw-r--r--libjava/ChangeLog13
-rw-r--r--libjava/boehm.cc6
-rw-r--r--libjava/classpath/ChangeLog6
-rw-r--r--libjava/classpath/native/fdlibm/mprec.c9
-rw-r--r--libjava/configure.host7
-rw-r--r--libjava/java/lang/natClass.cc6
-rw-r--r--libjava/testsuite/lib/libjava.exp4
-rw-r--r--libsanitizer/ChangeLog32
-rw-r--r--libsanitizer/MERGE2
-rw-r--r--libsanitizer/Makefile.am9
-rw-r--r--libsanitizer/Makefile.in64
-rw-r--r--libsanitizer/asan/Makefile.am1
-rw-r--r--libsanitizer/asan/Makefile.in15
-rw-r--r--libsanitizer/asan/asan_activation.cc72
-rw-r--r--libsanitizer/asan/asan_activation.h21
-rw-r--r--libsanitizer/asan/asan_allocator.h42
-rw-r--r--libsanitizer/asan/asan_allocator2.cc104
-rw-r--r--libsanitizer/asan/asan_asm_instrumentation.S599
-rw-r--r--libsanitizer/asan/asan_dll_thunk.cc158
-rw-r--r--libsanitizer/asan/asan_fake_stack.cc61
-rw-r--r--libsanitizer/asan/asan_fake_stack.h8
-rw-r--r--libsanitizer/asan/asan_flags.h64
-rw-r--r--libsanitizer/asan/asan_globals.cc13
-rw-r--r--libsanitizer/asan/asan_intercepted_functions.h77
-rw-r--r--libsanitizer/asan/asan_interceptors.cc170
-rw-r--r--libsanitizer/asan/asan_interceptors.h70
-rw-r--r--libsanitizer/asan/asan_interface_internal.h35
-rw-r--r--libsanitizer/asan/asan_internal.h38
-rw-r--r--libsanitizer/asan/asan_linux.cc144
-rw-r--r--libsanitizer/asan/asan_mac.cc76
-rw-r--r--libsanitizer/asan/asan_mac.h57
-rw-r--r--libsanitizer/asan/asan_malloc_linux.cc15
-rw-r--r--libsanitizer/asan/asan_malloc_mac.cc36
-rw-r--r--libsanitizer/asan/asan_malloc_win.cc17
-rw-r--r--libsanitizer/asan/asan_mapping.h80
-rw-r--r--libsanitizer/asan/asan_new_delete.cc43
-rw-r--r--libsanitizer/asan/asan_poisoning.cc102
-rw-r--r--libsanitizer/asan/asan_poisoning.h32
-rw-r--r--libsanitizer/asan/asan_posix.cc75
-rw-r--r--libsanitizer/asan/asan_report.cc328
-rw-r--r--libsanitizer/asan/asan_report.h13
-rw-r--r--libsanitizer/asan/asan_rtl.cc440
-rw-r--r--libsanitizer/asan/asan_stack.cc30
-rw-r--r--libsanitizer/asan/asan_stack.h75
-rw-r--r--libsanitizer/asan/asan_thread.cc45
-rw-r--r--libsanitizer/asan/asan_thread.h5
-rw-r--r--libsanitizer/asan/asan_win.cc67
-rw-r--r--libsanitizer/include/sanitizer/asan_interface.h39
-rw-r--r--libsanitizer/include/sanitizer/common_interface_defs.h29
-rw-r--r--libsanitizer/include/sanitizer/dfsan_interface.h11
-rw-r--r--libsanitizer/include/sanitizer/lsan_interface.h31
-rw-r--r--libsanitizer/include/sanitizer/msan_interface.h41
-rw-r--r--libsanitizer/include/sanitizer/tsan_interface_atomic.h (renamed from libsanitizer/tsan/tsan_interface_atomic.h)163
-rw-r--r--libsanitizer/interception/interception.h9
-rw-r--r--libsanitizer/interception/interception_linux.cc6
-rw-r--r--libsanitizer/interception/interception_linux.h20
-rw-r--r--libsanitizer/interception/interception_type_test.cc12
-rw-r--r--libsanitizer/interception/interception_win.cc137
-rw-r--r--libsanitizer/lsan/lsan.cc12
-rw-r--r--libsanitizer/lsan/lsan_allocator.cc6
-rw-r--r--libsanitizer/lsan/lsan_common.cc350
-rw-r--r--libsanitizer/lsan/lsan_common.h47
-rw-r--r--libsanitizer/lsan/lsan_common_linux.cc25
-rw-r--r--libsanitizer/lsan/lsan_interceptors.cc39
-rw-r--r--libsanitizer/sanitizer_common/Makefile.am11
-rw-r--r--libsanitizer/sanitizer_common/Makefile.in40
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_addrhashmap.h340
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_allocator.cc4
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_allocator.h42
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_allocator_internal.h7
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_atomic.h3
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_atomic_clang.h71
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_atomic_clang_other.h95
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_atomic_clang_x86.h114
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_atomic_msvc.h85
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_bitvector.h349
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_bvgraph.h163
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common.cc38
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common.h78
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc1736
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc554
-rwxr-xr-xlibsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc60
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_interceptors_scanf.inc309
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_libcdep.cc7
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc47
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_coverage.cc165
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_deadlock_detector.h410
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_deadlock_detector1.cc187
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_deadlock_detector2.cc427
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_deadlock_detector_interface.h91
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_flags.cc161
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_flags.h48
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_interception.h23
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_internal_defs.h45
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_libc.cc2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_libc.h4
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_libignore.cc7
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_linux.cc524
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_linux.h27
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc255
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_list.h17
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_mac.cc245
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_mac.h34
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_mutex.h84
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform.h63
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h248
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc420
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h445
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_posix.cc99
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cc62
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_printf.cc26
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_procmaps.h67
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_procmaps_linux.cc302
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_procmaps_mac.cc186
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_report_decorator.h11
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stacktrace.cc107
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stacktrace.h17
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cc76
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc58
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_suppressions.cc4
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_suppressions.h1
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer.h21
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc45
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.h12
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc456
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc87
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_syscall_generic.inc12
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_syscall_linux_x86_64.inc2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_thread_registry.cc17
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_thread_registry.h5
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_tls_get_addr.cc129
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_tls_get_addr.h56
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_win.cc101
-rw-r--r--libsanitizer/tsan/Makefile.am50
-rw-r--r--libsanitizer/tsan/Makefile.in70
-rw-r--r--libsanitizer/tsan/tsan_clock.cc355
-rw-r--r--libsanitizer/tsan/tsan_clock.h54
-rw-r--r--libsanitizer/tsan/tsan_defs.h7
-rw-r--r--libsanitizer/tsan/tsan_fd.cc6
-rw-r--r--libsanitizer/tsan/tsan_fd.h4
-rw-r--r--libsanitizer/tsan/tsan_flags.cc69
-rw-r--r--libsanitizer/tsan/tsan_flags.h17
-rw-r--r--libsanitizer/tsan/tsan_interceptors.cc572
-rw-r--r--libsanitizer/tsan/tsan_interface_ann.cc12
-rw-r--r--libsanitizer/tsan/tsan_interface_atomic.cc289
-rw-r--r--libsanitizer/tsan/tsan_interface_java.cc6
-rw-r--r--libsanitizer/tsan/tsan_mman.cc29
-rw-r--r--libsanitizer/tsan/tsan_mutex.cc17
-rw-r--r--libsanitizer/tsan/tsan_mutex.h5
-rw-r--r--libsanitizer/tsan/tsan_mutexset.h5
-rw-r--r--libsanitizer/tsan/tsan_platform.h19
-rw-r--r--libsanitizer/tsan/tsan_platform_linux.cc57
-rw-r--r--libsanitizer/tsan/tsan_platform_mac.cc25
-rw-r--r--libsanitizer/tsan/tsan_platform_windows.cc11
-rw-r--r--libsanitizer/tsan/tsan_report.cc95
-rw-r--r--libsanitizer/tsan/tsan_report.h9
-rw-r--r--libsanitizer/tsan/tsan_rtl.cc157
-rw-r--r--libsanitizer/tsan/tsan_rtl.h64
-rw-r--r--libsanitizer/tsan/tsan_rtl_mutex.cc239
-rw-r--r--libsanitizer/tsan/tsan_rtl_report.cc97
-rw-r--r--libsanitizer/tsan/tsan_rtl_thread.cc52
-rw-r--r--libsanitizer/tsan/tsan_stat.cc357
-rw-r--r--libsanitizer/tsan/tsan_stat.h358
-rw-r--r--libsanitizer/tsan/tsan_suppressions.cc10
-rw-r--r--libsanitizer/tsan/tsan_symbolize.cc10
-rw-r--r--libsanitizer/tsan/tsan_symbolize.h2
-rw-r--r--libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc191
-rw-r--r--libsanitizer/tsan/tsan_sync.cc11
-rw-r--r--libsanitizer/tsan/tsan_sync.h13
-rw-r--r--libsanitizer/tsan/tsan_vector.h16
-rw-r--r--libsanitizer/ubsan/ubsan_diag.cc21
-rw-r--r--libsanitizer/ubsan/ubsan_value.cc1
-rw-r--r--libsanitizer/ubsan/ubsan_value.h6
-rw-r--r--libstdc++-v3/ChangeLog399
-rw-r--r--libstdc++-v3/ChangeLog-20134
-rw-r--r--libstdc++-v3/acinclude.m426
-rw-r--r--libstdc++-v3/config/abi/pre/gnu.ver10
-rw-r--r--libstdc++-v3/config/locale/dragonfly/c_locale.cc299
-rw-r--r--libstdc++-v3/config/locale/dragonfly/ctype_members.cc173
-rw-r--r--libstdc++-v3/config/os/bsd/dragonfly/ctype_base.h58
-rw-r--r--libstdc++-v3/config/os/bsd/dragonfly/ctype_configure_char.cc99
-rw-r--r--libstdc++-v3/config/os/bsd/dragonfly/ctype_inline.h133
-rw-r--r--libstdc++-v3/config/os/bsd/dragonfly/os_defines.h32
-rwxr-xr-xlibstdc++-v3/configure29
-rw-r--r--libstdc++-v3/configure.host3
-rw-r--r--libstdc++-v3/doc/doxygen/user.cfg.in2329
-rw-r--r--libstdc++-v3/doc/html/faq.html2
-rw-r--r--libstdc++-v3/doc/xml/faq.xml2
-rw-r--r--libstdc++-v3/doc/xml/manual/appendix_contributing.xml14
-rw-r--r--libstdc++-v3/doc/xml/manual/status_cxx2011.xml5
-rw-r--r--libstdc++-v3/include/Makefile.am1
-rw-r--r--libstdc++-v3/include/Makefile.in1
-rw-r--r--libstdc++-v3/include/bits/hashtable.h146
-rw-r--r--libstdc++-v3/include/bits/ios_base.h8
-rw-r--r--libstdc++-v3/include/bits/parse_numbers.h339
-rw-r--r--libstdc++-v3/include/bits/regex.tcc2
-rw-r--r--libstdc++-v3/include/bits/regex_automaton.tcc4
-rw-r--r--libstdc++-v3/include/bits/regex_compiler.h43
-rw-r--r--libstdc++-v3/include/bits/regex_compiler.tcc36
-rw-r--r--libstdc++-v3/include/bits/regex_executor.h99
-rw-r--r--libstdc++-v3/include/bits/regex_executor.tcc168
-rw-r--r--libstdc++-v3/include/bits/regex_scanner.tcc11
-rw-r--r--libstdc++-v3/include/bits/uses_allocator.h31
-rw-r--r--libstdc++-v3/include/debug/array2
-rw-r--r--libstdc++-v3/include/experimental/string_view108
-rw-r--r--libstdc++-v3/include/experimental/string_view.tcc4
-rw-r--r--libstdc++-v3/include/profile/array36
-rw-r--r--libstdc++-v3/include/profile/base.h6
-rw-r--r--libstdc++-v3/include/profile/bitset159
-rw-r--r--libstdc++-v3/include/profile/deque359
-rw-r--r--libstdc++-v3/include/profile/forward_list115
-rw-r--r--libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h60
-rw-r--r--libstdc++-v3/include/profile/iterator_tracker.h21
-rw-r--r--libstdc++-v3/include/profile/list394
-rw-r--r--libstdc++-v3/include/profile/map.h412
-rw-r--r--libstdc++-v3/include/profile/multimap.h352
-rw-r--r--libstdc++-v3/include/profile/multiset.h322
-rw-r--r--libstdc++-v3/include/profile/ordered_base.h65
-rw-r--r--libstdc++-v3/include/profile/set.h334
-rw-r--r--libstdc++-v3/include/profile/unordered_base.h8
-rw-r--r--libstdc++-v3/include/profile/unordered_map248
-rw-r--r--libstdc++-v3/include/profile/unordered_set168
-rw-r--r--libstdc++-v3/include/profile/vector447
-rw-r--r--libstdc++-v3/include/std/array4
-rw-r--r--libstdc++-v3/include/std/chrono98
-rw-r--r--libstdc++-v3/include/std/condition_variable9
-rw-r--r--libstdc++-v3/include/std/fstream14
-rw-r--r--libstdc++-v3/include/std/functional18
-rw-r--r--libstdc++-v3/include/std/future43
-rw-r--r--libstdc++-v3/include/std/iostream6
-rw-r--r--libstdc++-v3/include/std/mutex60
-rw-r--r--libstdc++-v3/include/std/streambuf176
-rw-r--r--libstdc++-v3/include/std/tuple164
-rw-r--r--libstdc++-v3/include/std/type_traits82
-rw-r--r--libstdc++-v3/include/std/utility4
-rw-r--r--libstdc++-v3/include/tr2/bool_set2
-rw-r--r--libstdc++-v3/libsupc++/new_op.cc5
-rw-r--r--libstdc++-v3/libsupc++/new_opnt.cc6
-rw-r--r--libstdc++-v3/python/libstdcxx/v6/printers.py10
-rw-r--r--libstdc++-v3/scripts/run_doxygen11
-rwxr-xr-xlibstdc++-v3/scripts/testsuite_flags.in2
-rw-r--r--libstdc++-v3/src/c++98/ios_init.cc2
-rw-r--r--libstdc++-v3/testsuite/17_intro/headers/c++1998/stdc++.cc2
-rw-r--r--libstdc++-v3/testsuite/17_intro/headers/c++1998/stdc++_multiple_inclusion.cc2
-rw-r--r--libstdc++-v3/testsuite/17_intro/headers/c++200x/stdc++.cc2
-rw-r--r--libstdc++-v3/testsuite/17_intro/headers/c++200x/stdc++_multiple_inclusion.cc2
-rw-r--r--libstdc++-v3/testsuite/18_support/pthread_guard.cc4
-rw-r--r--libstdc++-v3/testsuite/20_util/aligned_union/1.cc72
-rw-r--r--libstdc++-v3/testsuite/20_util/auto_ptr/assign_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/20_util/bind/60497.cc40
-rw-r--r--libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/duration/literals/61166.cc39
-rw-r--r--libstdc++-v3/testsuite/20_util/duration/literals/range.cc31
-rw-r--r--libstdc++-v3/testsuite/20_util/forward/1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-4.cc33
-rw-r--r--libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc4
-rw-r--r--libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-1.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-2.cc3
-rw-r--r--libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc4
-rw-r--r--libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/assign/unique_ptr_lvalue_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/modifiers/reset_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/thread/default_weaktoshared.cc4
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/thread/mutex_weaktoshared.cc4
-rw-r--r--libstdc++-v3/testsuite/20_util/tuple/60497.cc6
-rw-r--r--libstdc++-v3/testsuite/20_util/tuple/comparison_operators/overloaded.cc52
-rw-r--r--libstdc++-v3/testsuite/20_util/tuple/element_access/get_by_type.cc4
-rw-r--r--libstdc++-v3/testsuite/20_util/unique_ptr/assign/assign_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/20_util/unique_ptr/cons/pointer_array_convertible_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/reset_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/pthread18185.cc4
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/pthread4.cc4
-rw-r--r--libstdc++-v3/testsuite/22_locale/locale/cons/12658_thread-1.cc4
-rw-r--r--libstdc++-v3/testsuite/22_locale/locale/cons/12658_thread-2.cc4
-rw-r--r--libstdc++-v3/testsuite/23_containers/array/element_access/60497.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/pthread1.cc4
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/pthread5.cc4
-rw-r--r--libstdc++-v3/testsuite/23_containers/map/pthread6.cc4
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/61143.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/swap.cc65
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/capacity/resize/1.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/debug/multithreaded_swap.cc4
-rw-r--r--libstdc++-v3/testsuite/26_numerics/headers/cmath/c_math_dynamic.cc2
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_ofstream/pthread2.cc4
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_ostringstream/pthread3.cc4
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_streambuf/cons/57394.cc113
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/quoted_char.cc10
-rw-r--r--libstdc++-v3/testsuite/28_regex/regex_error/base.cc32
-rw-r--r--libstdc++-v3/testsuite/30_threads/async/42819.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/async/49668.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/async/54297.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/async/any.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/async/async.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/async/forced_unwind.cc45
-rw-r--r--libstdc++-v3/testsuite/30_threads/async/launch.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/async/sync.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/call_once/39909.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/call_once/49668.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/call_once/60497.cc41
-rw-r--r--libstdc++-v3/testsuite/30_threads/call_once/call_once1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/condition_variable/54185.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/condition_variable/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/condition_variable/members/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/condition_variable/members/53841.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/condition_variable/native_handle/typesizes.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/condition_variable_any/50862.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/condition_variable_any/53830.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/condition_variable_any/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/condition_variable_any/members/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/condition_variable_any/members/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/future/cons/move.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/future/members/45133.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/future/members/get.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/future/members/get2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/future/members/share.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/future/members/valid.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/future/members/wait.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/future/members/wait_for.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/future/members/wait_until.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/lock/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/lock/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/lock/4.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/mutex/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/mutex/dest/destructor_locked.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/mutex/lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/mutex/native_handle/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/mutex/native_handle/typesizes.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/mutex/try_lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/mutex/try_lock/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/mutex/unlock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/49668.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/60564.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/cons/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/cons/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/cons/56492.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/cons/alloc.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/cons/move.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/cons/move_assign.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/forced_unwind.cc48
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/members/get_future.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/members/get_future2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke4.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke5.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/members/reset.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/members/reset2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/members/swap.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/members/valid.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/promise/60966.cc67
-rw-r--r--libstdc++-v3/testsuite/30_threads/promise/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/promise/cons/alloc.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/promise/cons/move.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/promise/cons/move_assign.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/promise/members/get_future.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/promise/members/get_future2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/promise/members/set_exception.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/promise/members/set_exception2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/promise/members/set_value.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/promise/members/set_value2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/promise/members/set_value3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/promise/members/swap.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_mutex/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_mutex/dest/destructor_locked.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_mutex/lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_mutex/native_handle/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_mutex/native_handle/typesizes.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_mutex/try_lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_mutex/try_lock/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_mutex/unlock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/dest/destructor_locked.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/typesizes.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/unlock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_future/cons/move.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_future/members/45133.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_future/members/get.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_future/members/get2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_future/members/valid.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_future/members/wait.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_future/members/wait_for.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_future/members/wait_until.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_lock/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_lock/cons/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_lock/cons/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_lock/cons/4.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_lock/cons/5.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_lock/cons/6.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_lock/locking/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_lock/locking/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_lock/locking/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_lock/locking/4.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_lock/modifiers/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_lock/modifiers/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_timed_mutex/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/this_thread/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/this_thread/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/this_thread/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/this_thread/4.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/cons/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/cons/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/cons/4.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/cons/49668.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/cons/5.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/cons/6.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/cons/7.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/cons/8.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/cons/9.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/cons/moveable.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/members/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/members/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/members/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/members/4.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/members/5.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/members/hardware_concurrency.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/native_handle/cancel.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/swap/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/dest/destructor_locked.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/typesizes.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/57641.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/unlock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/try_lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/try_lock/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/try_lock/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/try_lock/4.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/cons/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/cons/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/cons/4.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/cons/5.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/cons/6.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/cons/60497.cc49
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/locking/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/locking/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/locking/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/locking/4.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/modifiers/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/modifiers/2.cc4
-rw-r--r--libstdc++-v3/testsuite/experimental/string_view/cons/char/1.cc7
-rw-r--r--libstdc++-v3/testsuite/experimental/string_view/cons/wchar_t/1.cc7
-rw-r--r--libstdc++-v3/testsuite/experimental/string_view/operations/copy/char/1.cc3
-rw-r--r--libstdc++-v3/testsuite/experimental/string_view/operations/copy/wchar_t/1.cc3
-rw-r--r--libstdc++-v3/testsuite/experimental/string_view/operations/data/char/1.cc5
-rw-r--r--libstdc++-v3/testsuite/experimental/string_view/operations/data/wchar_t/1.cc5
-rw-r--r--libstdc++-v3/testsuite/experimental/string_view/operations/to_string/1.cc53
-rw-r--r--libstdc++-v3/testsuite/ext/rope/pthread7-rope.cc4
-rw-r--r--libstdc++-v3/testsuite/lib/libstdc++.exp9
-rw-r--r--libstdc++-v3/testsuite/libstdc++-abi/abi.exp4
-rw-r--r--libstdc++-v3/testsuite/performance/28_regex/range.cc41
-rw-r--r--libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/assign/auto_ptr_rvalue_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/modifiers/reset_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/thread/default_weaktoshared.cc4
-rw-r--r--libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/thread/mutex_weaktoshared.cc4
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_abi.cc3
-rw-r--r--lto-plugin/ChangeLog6
-rwxr-xr-xlto-plugin/configure30
-rw-r--r--lto-plugin/configure.ac14
-rw-r--r--maintainer-scripts/ChangeLog4
-rw-r--r--maintainer-scripts/generate_libstdcxx_web_docs56
1775 files changed, 59801 insertions, 26334 deletions
diff --git a/ChangeLog b/ChangeLog
index bac366014dc..174390e548d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,46 @@
+2014-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/61011
+ * configure.ac (--disable-libstdcxx): Set noconfigdirs correctly.
+ Disable libcilkrts, libitm, libsanitizer when not building libstdc++.
+ * configure: Regenerate.
+
+2014-05-28 Pedro Alves <palves@redhat.com>
+
+ * MAINTAINERS (Write After Approval): Add myself.
+
+2014-05-28 Olivier Hainque <hainque@adacore.com>
+
+ * config/rs6000/vxworks.h (VXCPU_FOR_8548): New. Default to PPC85XX.
+ (CPP_SPEC): Add entry for -mcpu=8548.
+ * config/rs6000/vxworksae.h: Reinstate. Override VXCPU_FOR_8548.
+ * config.gcc (powerpc-wrs-vxworksae, tm_file): Add back vxworksae.h.
+
+2014-05-26 Richard Sandiford <rdsandiford@googlemail.com>
+ Olivier Hainque <hainque@adacore.com>
+
+ * rtl.h (set_for_reg_notes): Declare.
+ * emit-rtl.c (set_for_reg_notes): New function.
+ (set_unique_reg_note): Use it.
+ * optabs.c (add_equal_note): Likewise
+
+2014-05-22 Maxim Kuvyrkov <maxim.kuvyrkov@linaro.org>
+
+ * MAINTAINERS: Update my affiliation/email.
+
+2014-05-19 Mike Stump <mikestump@comcast.net>
+
+ * MAINTAINERS: Add wide-int reviewers.
+
+2014-05-14 Sandra Loosemore <sandra@codesourcery.com>
+
+ * configure.ac (target_makefile_frag): Set for nios2-*-elf*.
+ * configure: Regenerated.
+
+2014-05-15 Torvald Riegel <triegel@redhat.com>
+
+ * MAINTAINERS (libitm): Add myself as maintainer.
+
2014-05-07 Charles Baylis <charles.baylis@linaro.org>
* MAINTAINERS (Write After Approval): Add myself.
diff --git a/MAINTAINERS b/MAINTAINERS
index ae3d330586e..a710ccbb84d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -174,6 +174,7 @@ libgomp Richard Henderson rth@redhat.com
libgomp Jakub Jelinek jakub@redhat.com
libiberty DJ Delorie dj@redhat.com
libiberty Ian Lance Taylor ian@airs.com
+libitm Torvald Riegel triegel@redhat.com
libffi testsuite Andreas Tobler andreast@gcc.gnu.org
libobjc Nicola Pero nicola.pero@meta-innovation.com
libobjc Andrew Pinski pinskia@gmail.com
@@ -300,6 +301,9 @@ register allocation Kenneth Zadeck zadeck@naturalbridge.com
register allocation Seongbae Park seongbae.park@gmail.com
RTL optimizers Steven Bosscher steven@gcc.gnu.org
selective scheduling Andrey Belevantsev abel@ispras.ru
+wide-int Kenneth Zadeck zadeck@naturalbridge.com
+wide-int Mike Stump mikestump@comcast.net
+wide-int Richard Sandiford rdsandiford@googlemail.com
Note that while reviewers can approve changes to parts of the compiler
that they maintain, they still need approval for their own patches
@@ -308,6 +312,7 @@ from other maintainers or reviewers.
Write After Approval (last name alphabetical order)
Mark G. Adams mark.g.adams@sympatico.ca
+Pedro Alves palves@redhat.com
Raksit Ashok raksit@google.com
Matt Austern austern@google.com
David Ayers ayers@fsfe.org
@@ -432,7 +437,7 @@ Michael Koch konqueror@gmx.de
Matt Kraai kraai@ftbfs.org
Jan Kratochvil jan.kratochvil@redhat.com
Venkataramanan Kumar venkataramanan.kumar@amd.com
-Maxim Kuvyrkov maxim@kugelworks.com
+Maxim Kuvyrkov maxim.kuvyrkov@linaro.org
Doug Kwan dougkwan@google.com
Scott Robert Ladd scott.ladd@coyotegulch.com
Razya Ladelsky razya@gcc.gnu.org
diff --git a/boehm-gc/ChangeLog b/boehm-gc/ChangeLog
index 1b5c92d878b..50a0802d9d8 100644
--- a/boehm-gc/ChangeLog
+++ b/boehm-gc/ChangeLog
@@ -1,3 +1,11 @@
+2014-05-13 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ Fix current cygwin-64 build problems.
+ * include/gc_config_macros.h (GC_PTHREADS): Use __CYGWIN__ instead
+ of __CYGWIN32__ here.
+ * win32_threads.c (GC_push_all_stacks): Push all X86_64 registers.
+ (GC_get_thread_stack_base): Get the stack base for X86_64.
+
2014-04-22 Jakub Jelinek <jakub@redhat.com>
PR other/43620
diff --git a/boehm-gc/include/gc_config_macros.h b/boehm-gc/include/gc_config_macros.h
index fd3006c1789..a01da4a1342 100644
--- a/boehm-gc/include/gc_config_macros.h
+++ b/boehm-gc/include/gc_config_macros.h
@@ -23,7 +23,7 @@
defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || \
defined(GC_DGUX386_THREADS) || defined(GC_DARWIN_THREADS) || \
defined(GC_AIX_THREADS) || \
- (defined(GC_WIN32_THREADS) && defined(__CYGWIN32__))
+ (defined(GC_WIN32_THREADS) && defined(__CYGWIN__))
# define GC_PTHREADS
# endif
diff --git a/boehm-gc/win32_threads.c b/boehm-gc/win32_threads.c
index ffb34e0a8b1..2de1c6953b8 100644
--- a/boehm-gc/win32_threads.c
+++ b/boehm-gc/win32_threads.c
@@ -365,7 +365,11 @@ void GC_push_all_stacks()
# define PUSH1(reg) GC_push_one((word)context.reg)
# define PUSH2(r1,r2) PUSH1(r1), PUSH1(r2)
# define PUSH4(r1,r2,r3,r4) PUSH2(r1,r2), PUSH2(r3,r4)
-# if defined(I386)
+# if defined(__x86_64__)
+ PUSH4(Rdi,Rsi,Rbx,Rdx), PUSH2(Rcx,Rax), PUSH1(Rbp);
+ PUSH4(R8,R9,R10,R11), PUSH4(R12,R13,R14,R15);
+ sp = (ptr_t)context.Rsp;
+# elif defined(I386)
PUSH4(Edi,Esi,Ebx,Edx), PUSH2(Ecx,Eax), PUSH1(Ebp);
sp = (ptr_t)context.Esp;
# elif defined(ARM32)
@@ -755,8 +759,12 @@ int GC_pthread_detach(pthread_t thread)
GC_PTR GC_get_thread_stack_base()
{
+#ifdef __x86_64__
+ return ((NT_TIB*)NtCurrentTeb())->StackBase;
+#else
extern GC_PTR _tlsbase __asm__ ("%fs:4");
return _tlsbase;
+#endif
}
#else /* !CYGWIN32 */
diff --git a/config/ChangeLog b/config/ChangeLog
index f4152c4ebff..1079c7fb6fc 100644
--- a/config/ChangeLog
+++ b/config/ChangeLog
@@ -1,3 +1,7 @@
+2014-05-14 Sandra Loosemore <sandra@codesourcery.com>
+
+ * mt-nios2-elf: New file.
+
2014-04-25 Marc Glisse <marc.glisse@inria.fr>
PR target/43538
diff --git a/config/mt-nios2-elf b/config/mt-nios2-elf
new file mode 100644
index 00000000000..1dee7c6439e
--- /dev/null
+++ b/config/mt-nios2-elf
@@ -0,0 +1,5 @@
+# We build library code with -mno-gpopt so that it can be linked with
+# larger executables with small-data sections that exceed the 16-bit
+# offset range for GP-relative addressing.
+CFLAGS_FOR_TARGET += -mno-gpopt
+CXXFLAGS_FOR_TARGET += -mno-gpopt
diff --git a/configure b/configure
index 3f217a2eeab..e9ca33e6f24 100755
--- a/configure
+++ b/configure
@@ -3090,7 +3090,7 @@ else
fi
if test "${ENABLE_LIBSTDCXX}" = "no" ; then
- noconfigdirs="$noconfigdirs libstdc++-v3"
+ noconfigdirs="$noconfigdirs target-libstdc++-v3"
fi
# Save it here so that, even in case of --enable-libgcj, if the Java
@@ -6628,9 +6628,17 @@ case ,${enable_languages},:${enable_objc_gc} in
;;
esac
-# Disable libitm, libsanitizer, libvtv if we're not building C++
+# Disable libcilkrts, libitm, libsanitizer, libvtv if we're not building C++
case ,${enable_languages}, in
- *,c++,*) ;;
+ *,c++,*)
+ # Disable libcilkrts, libitm, libsanitizer if we're not building libstdc++
+ case "${noconfigdirs}" in
+ *target-libstdc++-v3*)
+ noconfigdirs="$noconfigdirs target-libcilkrts target-libitm target-libsanitizer"
+ ;;
+ *) ;;
+ esac
+ ;;
*)
noconfigdirs="$noconfigdirs target-libcilkrts target-libitm target-libsanitizer target-libvtv"
;;
@@ -6992,6 +7000,9 @@ case "${target}" in
mips*-*-*linux* | mips*-*-gnu*)
target_makefile_frag="config/mt-mips-gnu"
;;
+ nios2-*-elf*)
+ target_makefile_frag="config/mt-nios2-elf"
+ ;;
*-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu | *-*-kopensolaris*-gnu)
target_makefile_frag="config/mt-gnu"
;;
diff --git a/configure.ac b/configure.ac
index 3c7b1ffac3a..548525b19ff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -435,7 +435,7 @@ AS_HELP_STRING([--disable-libstdcxx],
ENABLE_LIBSTDCXX=$enableval,
ENABLE_LIBSTDCXX=default)
[if test "${ENABLE_LIBSTDCXX}" = "no" ; then
- noconfigdirs="$noconfigdirs libstdc++-v3"
+ noconfigdirs="$noconfigdirs target-libstdc++-v3"
fi]
# Save it here so that, even in case of --enable-libgcj, if the Java
@@ -2057,9 +2057,17 @@ case ,${enable_languages},:${enable_objc_gc} in
;;
esac
-# Disable libitm, libsanitizer, libvtv if we're not building C++
+# Disable libcilkrts, libitm, libsanitizer, libvtv if we're not building C++
case ,${enable_languages}, in
- *,c++,*) ;;
+ *,c++,*)
+ # Disable libcilkrts, libitm, libsanitizer if we're not building libstdc++
+ case "${noconfigdirs}" in
+ *target-libstdc++-v3*)
+ noconfigdirs="$noconfigdirs target-libcilkrts target-libitm target-libsanitizer"
+ ;;
+ *) ;;
+ esac
+ ;;
*)
noconfigdirs="$noconfigdirs target-libcilkrts target-libitm target-libsanitizer target-libvtv"
;;
@@ -2370,6 +2378,9 @@ case "${target}" in
mips*-*-*linux* | mips*-*-gnu*)
target_makefile_frag="config/mt-mips-gnu"
;;
+ nios2-*-elf*)
+ target_makefile_frag="config/mt-nios2-elf"
+ ;;
*-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu | *-*-kopensolaris*-gnu)
target_makefile_frag="config/mt-gnu"
;;
diff --git a/contrib/ChangeLog b/contrib/ChangeLog
index 4d98be736e5..90a154e69b2 100644
--- a/contrib/ChangeLog
+++ b/contrib/ChangeLog
@@ -1,3 +1,26 @@
+2014-05-25 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * dg-extract-results.py (Named): Remove __cmp__ method.
+ (output_variation): Use a key to sort variation.harnesses.
+
+2014-05-24 Uros Bizjak <ubizjak@gmail.com>
+
+ * texi2pod.pl: Force .pod file to not be a numbered list.
+
+2014-05-20 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * dg-extract-results.py (parse_run): Handle warnings that are printed
+ before a test harness is run.
+
+2014-05-09 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * config-list.mk (show): New target.
+
+2014-05-08 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * dg-extract-results.py: New file.
+ * dg-extract-results.sh: Use it if the environment seems suitable.
+
2014-04-22 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* config-list.mk (LIST): Remove sparc-sun-solaris2.9, i686-solaris2.9.
@@ -76,7 +99,7 @@
2013-08-03 Caroline Tice <cmtice@google.com>
* gcc_update: Add libvtv files.
-
+
2013-06-06 Brooks Moses <bmoses@google.com>
* testsuite-management/validate_failures.py: Fix handling of
@@ -263,7 +286,7 @@
2012-08-24 Diego Novillo <dnovillo@google.com>
* testsuite-management/x86_64-unknown-linux-gnu.xfail: Update.
-
+
2012-08-14 Diego Novillo <dnovillo@google.com>
* testsuite-management/x86_64-unknown-linux-gnu.xfail: New.
@@ -664,7 +687,7 @@
2009-08-18 H.J. Lu <hongjiu.lu@intel.com>
PR testsuite/40704
- * test_summary: Filter out "\r".
+ * test_summary: Filter out "\r".
2009-06-02 Alexandre Oliva <aoliva@redhat.com>
@@ -737,7 +760,7 @@
2008-03-10 Janis Johnson <janis187@us.ibm.com>
* patch_tester.sh (initialization): Initialize svnpatch and stop.
- (usage): Add -svnpath and -stop.
+ (usage): Add -svnpath and -stop.
(makedir): New.
(argument handling): Process -stop and -svnpath.
(setup code): Use makedir, error out if initial svn checkout fails.
@@ -808,7 +831,7 @@
* texi2pod.pl: Handle @asis.
(postprocess): Move @gccoptlist{} after all formatting commands.
-
+
2007-10-01 Alexandre Oliva <aoliva@redhat.com>
* compare-debug: Avoid spurious errors when .stripped files
@@ -970,14 +993,14 @@
2005-10-28 Daniel Berlin <dberlin@dberlin.org>
Ben Elliston <bje@au1.ibm.com>
-
+
* gcc_update: Update for svn.
* newcvsroot: Ditto.
* gcc_build: Ditto.
2005-10-21 Mark Mitchell <mark@codesourcery.com>
- * texi2pod.pl: Substitue for @value even when part of @include.
+ * texi2pod.pl: Substitue for @value even when part of @include.
2005-10-21 Bob Wilson <bob.wilson@acm.org>
diff --git a/contrib/config-list.mk b/contrib/config-list.mk
index ddf24a286ef..cea0a946a4c 100644
--- a/contrib/config-list.mk
+++ b/contrib/config-list.mk
@@ -80,8 +80,10 @@ LIST = aarch64-elf aarch64-linux-gnu \
LOGFILES = $(patsubst %,log/%-make.out,$(LIST))
all: $(LOGFILES)
config: $(LIST)
+show:
+ @echo $(LIST)
-.PHONY: make-log-dir all config
+.PHONY: make-log-dir all config show
empty=
diff --git a/contrib/dg-extract-results.py b/contrib/dg-extract-results.py
new file mode 100644
index 00000000000..a5dfc5d8e92
--- /dev/null
+++ b/contrib/dg-extract-results.py
@@ -0,0 +1,580 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2014 Free Software Foundation, Inc.
+#
+# This script 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.
+
+import sys
+import getopt
+import re
+from datetime import datetime
+from operator import attrgetter
+
+# True if unrecognised lines should cause a fatal error. Might want to turn
+# this on by default later.
+strict = False
+
+# True if the order of .log segments should match the .sum file, false if
+# they should keep the original order.
+sort_logs = True
+
+class Named:
+ def __init__ (self, name):
+ self.name = name
+
+class ToolRun (Named):
+ def __init__ (self, name):
+ Named.__init__ (self, name)
+ # The variations run for this tool, mapped by --target_board name.
+ self.variations = dict()
+
+ # Return the VariationRun for variation NAME.
+ def get_variation (self, name):
+ if name not in self.variations:
+ self.variations[name] = VariationRun (name)
+ return self.variations[name]
+
+class VariationRun (Named):
+ def __init__ (self, name):
+ Named.__init__ (self, name)
+ # A segment of text before the harness runs start, describing which
+ # baseboard files were loaded for the target.
+ self.header = None
+ # The harnesses run for this variation, mapped by filename.
+ self.harnesses = dict()
+ # A list giving the number of times each type of result has
+ # been seen.
+ self.counts = []
+
+ # Return the HarnessRun for harness NAME.
+ def get_harness (self, name):
+ if name not in self.harnesses:
+ self.harnesses[name] = HarnessRun (name)
+ return self.harnesses[name]
+
+class HarnessRun (Named):
+ def __init__ (self, name):
+ Named.__init__ (self, name)
+ # Segments of text that make up the harness run, mapped by a test-based
+ # key that can be used to order them.
+ self.segments = dict()
+ # Segments of text that make up the harness run but which have
+ # no recognized test results. These are typically harnesses that
+ # are completely skipped for the target.
+ self.empty = []
+ # A list of results. Each entry is a pair in which the first element
+ # is a unique sorting key and in which the second is the full
+ # PASS/FAIL line.
+ self.results = []
+
+ # Add a segment of text to the harness run. If the segment includes
+ # test results, KEY is an example of one of them, and can be used to
+ # combine the individual segments in order. If the segment has no
+ # test results (e.g. because the harness doesn't do anything for the
+ # current configuration) then KEY is None instead. In that case
+ # just collect the segments in the order that we see them.
+ def add_segment (self, key, segment):
+ if key:
+ assert key not in self.segments
+ self.segments[key] = segment
+ else:
+ self.empty.append (segment)
+
+class Segment:
+ def __init__ (self, filename, start):
+ self.filename = filename
+ self.start = start
+ self.lines = 0
+
+class Prog:
+ def __init__ (self):
+ # The variations specified on the command line.
+ self.variations = []
+ # The variations seen in the input files.
+ self.known_variations = set()
+ # The tools specified on the command line.
+ self.tools = []
+ # Whether to create .sum rather than .log output.
+ self.do_sum = True
+ # Regexps used while parsing.
+ self.test_run_re = re.compile (r'^Test Run By (\S+) on (.*)$')
+ self.tool_re = re.compile (r'^\t\t=== (.*) tests ===$')
+ self.result_re = re.compile (r'^(PASS|XPASS|FAIL|XFAIL|UNRESOLVED'
+ r'|WARNING|ERROR|UNSUPPORTED|UNTESTED'
+ r'|KFAIL):\s*(\S+)')
+ self.completed_re = re.compile (r'.* completed at (.*)')
+ # Pieces of text to write at the head of the output.
+ # start_line is a pair in which the first element is a datetime
+ # and in which the second is the associated 'Test Run By' line.
+ self.start_line = None
+ self.native_line = ''
+ self.target_line = ''
+ self.host_line = ''
+ self.acats_premable = ''
+ # Pieces of text to write at the end of the output.
+ # end_line is like start_line but for the 'runtest completed' line.
+ self.acats_failures = []
+ self.version_output = ''
+ self.end_line = None
+ # Known summary types.
+ self.count_names = [
+ '# of expected passes\t\t',
+ '# of unexpected failures\t',
+ '# of unexpected successes\t',
+ '# of expected failures\t\t',
+ '# of unknown successes\t\t',
+ '# of known failures\t\t',
+ '# of untested testcases\t\t',
+ '# of unresolved testcases\t',
+ '# of unsupported tests\t\t'
+ ]
+ self.runs = dict()
+
+ def usage (self):
+ name = sys.argv[0]
+ sys.stderr.write ('Usage: ' + name
+ + ''' [-t tool] [-l variant-list] [-L] log-or-sum-file ...
+
+ tool The tool (e.g. g++, libffi) for which to create a
+ new test summary file. If not specified then output
+ is created for all tools.
+ variant-list One or more test variant names. If the list is
+ not specified then one is constructed from all
+ variants in the files for <tool>.
+ sum-file A test summary file with the format of those
+ created by runtest from DejaGnu.
+ If -L is used, merge *.log files instead of *.sum. In this
+ mode the exact order of lines may not be preserved, just different
+ Running *.exp chunks should be in correct order.
+''')
+ sys.exit (1)
+
+ def fatal (self, what, string):
+ if not what:
+ what = sys.argv[0]
+ sys.stderr.write (what + ': ' + string + '\n')
+ sys.exit (1)
+
+ # Parse the command-line arguments.
+ def parse_cmdline (self):
+ try:
+ (options, self.files) = getopt.getopt (sys.argv[1:], 'l:t:L')
+ if len (self.files) == 0:
+ self.usage()
+ for (option, value) in options:
+ if option == '-l':
+ self.variations.append (value)
+ elif option == '-t':
+ self.tools.append (value)
+ else:
+ self.do_sum = False
+ except getopt.GetoptError as e:
+ self.fatal (None, e.msg)
+
+ # Try to parse time string TIME, returning an arbitrary time on failure.
+ # Getting this right is just a nice-to-have so failures should be silent.
+ def parse_time (self, time):
+ try:
+ return datetime.strptime (time, '%c')
+ except ValueError:
+ return datetime.now()
+
+ # Parse an integer and abort on failure.
+ def parse_int (self, filename, value):
+ try:
+ return int (value)
+ except ValueError:
+ self.fatal (filename, 'expected an integer, got: ' + value)
+
+ # Return a list that represents no test results.
+ def zero_counts (self):
+ return [0 for x in self.count_names]
+
+ # Return the ToolRun for tool NAME.
+ def get_tool (self, name):
+ if name not in self.runs:
+ self.runs[name] = ToolRun (name)
+ return self.runs[name]
+
+ # Add the result counts in list FROMC to TOC.
+ def accumulate_counts (self, toc, fromc):
+ for i in range (len (self.count_names)):
+ toc[i] += fromc[i]
+
+ # Parse the list of variations after 'Schedule of variations:'.
+ # Return the number seen.
+ def parse_variations (self, filename, file):
+ num_variations = 0
+ while True:
+ line = file.readline()
+ if line == '':
+ self.fatal (filename, 'could not parse variation list')
+ if line == '\n':
+ break
+ self.known_variations.add (line.strip())
+ num_variations += 1
+ return num_variations
+
+ # Parse from the first line after 'Running target ...' to the end
+ # of the run's summary.
+ def parse_run (self, filename, file, tool, variation, num_variations):
+ header = None
+ harness = None
+ segment = None
+ final_using = 0
+
+ # If this is the first run for this variation, add any text before
+ # the first harness to the header.
+ if not variation.header:
+ segment = Segment (filename, file.tell())
+ variation.header = segment
+
+ # Parse up until the first line of the summary.
+ if num_variations == 1:
+ end = '\t\t=== ' + tool.name + ' Summary ===\n'
+ else:
+ end = ('\t\t=== ' + tool.name + ' Summary for '
+ + variation.name + ' ===\n')
+ while True:
+ line = file.readline()
+ if line == '':
+ self.fatal (filename, 'no recognised summary line')
+ if line == end:
+ break
+
+ # Look for the start of a new harness.
+ if line.startswith ('Running ') and line.endswith (' ...\n'):
+ # Close off the current harness segment, if any.
+ if harness:
+ segment.lines -= final_using
+ harness.add_segment (first_key, segment)
+ name = line[len ('Running '):-len(' ...\n')]
+ harness = variation.get_harness (name)
+ segment = Segment (filename, file.tell())
+ first_key = None
+ final_using = 0
+ continue
+
+ # Record test results. Associate the first test result with
+ # the harness segment, so that if a run for a particular harness
+ # has been split up, we can reassemble the individual segments
+ # in a sensible order.
+ #
+ # dejagnu sometimes issues warnings about the testing environment
+ # before running any tests. Treat them as part of the header
+ # rather than as a test result.
+ match = self.result_re.match (line)
+ if match and (harness or not line.startswith ('WARNING:')):
+ if not harness:
+ self.fatal (filename, 'saw test result before harness name')
+ name = match.group (2)
+ # Ugly hack to get the right order for gfortran.
+ if name.startswith ('gfortran.dg/g77/'):
+ name = 'h' + name
+ key = (name, len (harness.results))
+ harness.results.append ((key, line))
+ if not first_key and sort_logs:
+ first_key = key
+
+ # 'Using ...' lines are only interesting in a header. Splitting
+ # the test up into parallel runs leads to more 'Using ...' lines
+ # than there would be in a single log.
+ if line.startswith ('Using '):
+ final_using += 1
+ else:
+ final_using = 0
+
+ # Add other text to the current segment, if any.
+ if segment:
+ segment.lines += 1
+
+ # Close off the final harness segment, if any.
+ if harness:
+ segment.lines -= final_using
+ harness.add_segment (first_key, segment)
+
+ # Parse the rest of the summary (the '# of ' lines).
+ if len (variation.counts) == 0:
+ variation.counts = self.zero_counts()
+ while True:
+ before = file.tell()
+ line = file.readline()
+ if line == '':
+ break
+ if line == '\n':
+ continue
+ if not line.startswith ('# '):
+ file.seek (before)
+ break
+ found = False
+ for i in range (len (self.count_names)):
+ if line.startswith (self.count_names[i]):
+ count = line[len (self.count_names[i]):-1].strip()
+ variation.counts[i] += self.parse_int (filename, count)
+ found = True
+ break
+ if not found:
+ self.fatal (filename, 'unknown test result: ' + line[:-1])
+
+ # Parse an acats run, which uses a different format from dejagnu.
+ # We have just skipped over '=== acats configuration ==='.
+ def parse_acats_run (self, filename, file):
+ # Parse the preamble, which describes the configuration and logs
+ # the creation of support files.
+ record = (self.acats_premable == '')
+ if record:
+ self.acats_premable = '\t\t=== acats configuration ===\n'
+ while True:
+ line = file.readline()
+ if line == '':
+ self.fatal (filename, 'could not parse acats preamble')
+ if line == '\t\t=== acats tests ===\n':
+ break
+ if record:
+ self.acats_premable += line
+
+ # Parse the test results themselves, using a dummy variation name.
+ tool = self.get_tool ('acats')
+ variation = tool.get_variation ('none')
+ self.parse_run (filename, file, tool, variation, 1)
+
+ # Parse the failure list.
+ while True:
+ before = file.tell()
+ line = file.readline()
+ if line.startswith ('*** FAILURES: '):
+ self.acats_failures.append (line[len ('*** FAILURES: '):-1])
+ continue
+ file.seek (before)
+ break
+
+ # Parse the final summary at the end of a log in order to capture
+ # the version output that follows it.
+ def parse_final_summary (self, filename, file):
+ record = (self.version_output == '')
+ while True:
+ line = file.readline()
+ if line == '':
+ break
+ if line.startswith ('# of '):
+ continue
+ if record:
+ self.version_output += line
+ if line == '\n':
+ break
+
+ # Parse a .log or .sum file.
+ def parse_file (self, filename, file):
+ tool = None
+ target = None
+ num_variations = 1
+ while True:
+ line = file.readline()
+ if line == '':
+ return
+
+ # Parse the list of variations, which comes before the test
+ # runs themselves.
+ if line.startswith ('Schedule of variations:'):
+ num_variations = self.parse_variations (filename, file)
+ continue
+
+ # Parse a testsuite run for one tool/variation combination.
+ if line.startswith ('Running target '):
+ name = line[len ('Running target '):-1]
+ if not tool:
+ self.fatal (filename, 'could not parse tool name')
+ if name not in self.known_variations:
+ self.fatal (filename, 'unknown target: ' + name)
+ self.parse_run (filename, file, tool,
+ tool.get_variation (name),
+ num_variations)
+ # If there is only one variation then there is no separate
+ # summary for it. Record any following version output.
+ if num_variations == 1:
+ self.parse_final_summary (filename, file)
+ continue
+
+ # Parse the start line. In the case where several files are being
+ # parsed, pick the one with the earliest time.
+ match = self.test_run_re.match (line)
+ if match:
+ time = self.parse_time (match.group (2))
+ if not self.start_line or self.start_line[0] > time:
+ self.start_line = (time, line)
+ continue
+
+ # Parse the form used for native testing.
+ if line.startswith ('Native configuration is '):
+ self.native_line = line
+ continue
+
+ # Parse the target triplet.
+ if line.startswith ('Target is '):
+ self.target_line = line
+ continue
+
+ # Parse the host triplet.
+ if line.startswith ('Host is '):
+ self.host_line = line
+ continue
+
+ # Parse the acats premable.
+ if line == '\t\t=== acats configuration ===\n':
+ self.parse_acats_run (filename, file)
+ continue
+
+ # Parse the tool name.
+ match = self.tool_re.match (line)
+ if match:
+ tool = self.get_tool (match.group (1))
+ continue
+
+ # Skip over the final summary (which we instead create from
+ # individual runs) and parse the version output.
+ if tool and line == '\t\t=== ' + tool.name + ' Summary ===\n':
+ if file.readline() != '\n':
+ self.fatal (filename, 'expected blank line after summary')
+ self.parse_final_summary (filename, file)
+ continue
+
+ # Parse the completion line. In the case where several files
+ # are being parsed, pick the one with the latest time.
+ match = self.completed_re.match (line)
+ if match:
+ time = self.parse_time (match.group (1))
+ if not self.end_line or self.end_line[0] < time:
+ self.end_line = (time, line)
+ continue
+
+ # Sanity check to make sure that important text doesn't get
+ # dropped accidentally.
+ if strict and line.strip() != '':
+ self.fatal (filename, 'unrecognised line: ' + line[:-1])
+
+ # Output a segment of text.
+ def output_segment (self, segment):
+ with open (segment.filename, 'r') as file:
+ file.seek (segment.start)
+ for i in range (segment.lines):
+ sys.stdout.write (file.readline())
+
+ # Output a summary giving the number of times each type of result has
+ # been seen.
+ def output_summary (self, tool, counts):
+ for i in range (len (self.count_names)):
+ name = self.count_names[i]
+ # dejagnu only prints result types that were seen at least once,
+ # but acats always prints a number of unexpected failures.
+ if (counts[i] > 0
+ or (tool.name == 'acats'
+ and name.startswith ('# of unexpected failures'))):
+ sys.stdout.write ('%s%d\n' % (name, counts[i]))
+
+ # Output unified .log or .sum information for a particular variation,
+ # with a summary at the end.
+ def output_variation (self, tool, variation):
+ self.output_segment (variation.header)
+ for harness in sorted (variation.harnesses.values(),
+ key = attrgetter ('name')):
+ sys.stdout.write ('Running ' + harness.name + ' ...\n')
+ if self.do_sum:
+ # Keep the original test result order if there was only
+ # one segment for this harness. This is needed for
+ # unsorted.exp, which has unusual test names. Otherwise
+ # sort the tests by test filename. If there are several
+ # subtests for the same test filename (such as 'compilation',
+ # 'test for excess errors', etc.) then keep the subtests
+ # in the original order.
+ if len (harness.segments) > 1:
+ harness.results.sort()
+ for (key, line) in harness.results:
+ sys.stdout.write (line)
+ else:
+ # Rearrange the log segments into test order (but without
+ # rearranging text within those segments).
+ for key in sorted (harness.segments.keys()):
+ self.output_segment (harness.segments[key])
+ for segment in harness.empty:
+ self.output_segment (segment)
+ if len (self.variations) > 1:
+ sys.stdout.write ('\t\t=== ' + tool.name + ' Summary for '
+ + variation.name + ' ===\n\n')
+ self.output_summary (tool, variation.counts)
+
+ # Output unified .log or .sum information for a particular tool,
+ # with a summary at the end.
+ def output_tool (self, tool):
+ counts = self.zero_counts()
+ if tool.name == 'acats':
+ # acats doesn't use variations, so just output everything.
+ # It also has a different approach to whitespace.
+ sys.stdout.write ('\t\t=== ' + tool.name + ' tests ===\n')
+ for variation in tool.variations.values():
+ self.output_variation (tool, variation)
+ self.accumulate_counts (counts, variation.counts)
+ sys.stdout.write ('\t\t=== ' + tool.name + ' Summary ===\n')
+ else:
+ # Output the results in the usual dejagnu runtest format.
+ sys.stdout.write ('\n\t\t=== ' + tool.name + ' tests ===\n\n'
+ 'Schedule of variations:\n')
+ for name in self.variations:
+ if name in tool.variations:
+ sys.stdout.write (' ' + name + '\n')
+ sys.stdout.write ('\n')
+ for name in self.variations:
+ if name in tool.variations:
+ variation = tool.variations[name]
+ sys.stdout.write ('Running target '
+ + variation.name + '\n')
+ self.output_variation (tool, variation)
+ self.accumulate_counts (counts, variation.counts)
+ sys.stdout.write ('\n\t\t=== ' + tool.name + ' Summary ===\n\n')
+ self.output_summary (tool, counts)
+
+ def main (self):
+ self.parse_cmdline()
+ try:
+ # Parse the input files.
+ for filename in self.files:
+ with open (filename, 'r') as file:
+ self.parse_file (filename, file)
+
+ # Decide what to output.
+ if len (self.variations) == 0:
+ self.variations = sorted (self.known_variations)
+ else:
+ for name in self.variations:
+ if name not in self.known_variations:
+ self.fatal (None, 'no results for ' + name)
+ if len (self.tools) == 0:
+ self.tools = sorted (self.runs.keys())
+
+ # Output the header.
+ if self.start_line:
+ sys.stdout.write (self.start_line[1])
+ sys.stdout.write (self.native_line)
+ sys.stdout.write (self.target_line)
+ sys.stdout.write (self.host_line)
+ sys.stdout.write (self.acats_premable)
+
+ # Output the main body.
+ for name in self.tools:
+ if name not in self.runs:
+ self.fatal (None, 'no results for ' + name)
+ self.output_tool (self.runs[name])
+
+ # Output the footer.
+ if len (self.acats_failures) > 0:
+ sys.stdout.write ('*** FAILURES: '
+ + ' '.join (self.acats_failures) + '\n')
+ sys.stdout.write (self.version_output)
+ if self.end_line:
+ sys.stdout.write (self.end_line[1])
+ except IOError as e:
+ self.fatal (e.filename, e.strerror)
+
+Prog().main()
diff --git a/contrib/dg-extract-results.sh b/contrib/dg-extract-results.sh
index 7029281383b..a83c8e8d678 100755
--- a/contrib/dg-extract-results.sh
+++ b/contrib/dg-extract-results.sh
@@ -28,6 +28,15 @@
PROGNAME=dg-extract-results.sh
+# Try to use the python version if possible, since it tends to be faster.
+PYTHON_VER=`echo "$0" | sed 's/sh$/py/'`
+if test "$PYTHON_VER" != "$0" &&
+ test -f "$PYTHON_VER" &&
+ python -c 'import sys; sys.exit (0 if sys.version_info >= (2, 6) else 1)' \
+ > /dev/null 2> /dev/null; then
+ exec python $PYTHON_VER "$@"
+fi
+
usage() {
cat <<EOF >&2
Usage: $PROGNAME [-t tool] [-l variant-list] [-L] sum-file ...
diff --git a/contrib/texi2pod.pl b/contrib/texi2pod.pl
index 5a4bbacdf5e..55b6ba75227 100755
--- a/contrib/texi2pod.pl
+++ b/contrib/texi2pod.pl
@@ -1,6 +1,6 @@
#! /usr/bin/perl -w
-# Copyright (C) 1999, 2000, 2001, 2003, 2010 Free Software Foundation, Inc.
+# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# This file is part of GCC.
@@ -337,7 +337,7 @@ while(<$inf>) {
$_ = "\n=item $1\n";
}
} else {
- $_ = "\n=item $ic\n";
+ $_ = "\n=item Z\&LT;\&GT;$ic\n";
$ic =~ y/A-Ya-y/B-Zb-z/;
$ic =~ s/(\d+)/$1 + 1/eg;
}
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index afac89bf1d7..1f9f102c53e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,3397 @@
+2014-06-02 Andrew MacLeod <amacleod@redhat.com>
+
+ * expr.h: Remove prototypes of functions defined in builtins.c.
+ * tree.h: (build_call_expr_*, build_string_literal): Add prototypes.
+ Remove prototypes of functions defined in builtins.c.
+ * builtins.h: Update prototype list to include all exported functions.
+ * builtins.c: (default_libc_has_function, gnu_libc_has_function,
+ no_c99_libc_has_function): Move to targhooks.c
+ (build_string_literal, build_call_expr_loc_array,
+ build_call_expr_loc_vec, build_call_expr_loc, build_call_expr): Move
+ to tree.c.
+ (expand_builtin_object_size, fold_builtin_object_size): Make static.
+ * targhooks.c (default_libc_has_function, gnu_libc_has_function,
+ no_c99_libc_has_function): Relocate from builtins.c.
+ * tree.c: Include builtins.h.
+ (build_call_expr_loc_array, build_call_expr_loc_vec,
+ build_call_expr_loc, build_call_expr, build_string_literal): Relocate
+ from builtins.c.
+ * fold-const.h (fold_fma): Move prototype to builtins.h.
+ * realmpfr.h (do_mpc_arg2): Move prototype to builtins.h.
+ * asan.c: Include builtins.h.
+ * cfgexpand.c: Likewise.
+ * convert.c: Likewise.
+ * emit-rtl.c: Likewise.
+ * except.c: Likewise.
+ * expr.c: Likewise.
+ * fold-const.c: Likewise.
+ * gimple-fold.c: Likewise.
+ * gimple-ssa-strength-reduction.c: Likewise.
+ * gimplify.c: Likewise.
+ * ipa-inline.c: Likewise.
+ * ipa-prop.c: Likewise.
+ * lto-streamer-out.c: Likewise.
+ * stmt.c: Likewise.
+ * tree-inline.c: Likewise.
+ * tree-object-size.c: Likewise.
+ * tree-sra.c: Likewise.
+ * tree-ssa-ccp.c: Likewise.
+ * tree-ssa-forwprop.c: Likewise.
+ * tree-ssa-loop-ivcanon.c: Likewise.
+ * tree-ssa-loop-ivopts.c: Likewise.
+ * tree-ssa-math-opts.c: Likewise.
+ * tree-ssa-reassoc.c: Likewise.
+ * tree-ssa-threadedge.c: Likewise.
+ * tree-streamer-in.c: Likewise.
+ * tree-vect-data-refs.c: Likewise.
+ * tree-vect-patterns.c: Likewise.
+ * tree-vect-stmts.c: Likewise.
+ * config/aarch64/aarch64.c: Likewise.
+ * config/alpha/alpha.c: Likewise.
+ * config/arc/arc.c: Likewise.
+ * config/arm/arm.c: Likewise.
+ * config/avr/avr.c: Likewise.
+ * config/bfin/bfin.c: Likewise.
+ * config/c6x/c6x.c: Likewise.
+ * config/cr16/cr16.c: Likewise.
+ * config/cris/cris.c: Likewise.
+ * config/epiphany/epiphany.c: Likewise.
+ * config/fr30/fr30.c: Likewise.
+ * config/frv/frv.c: Likewise.
+ * config/h8300/h8300.c: Likewise.
+ * config/i386/i386.c: Likewise.
+ * config/i386/winnt.c: Likewise.
+ * config/ia64/ia64.c: Likewise.
+ * config/iq2000/iq2000.c: Likewise.
+ * config/lm32/lm32.c: Likewise.
+ * config/m32c/m32c.c: Likewise.
+ * config/m32r/m32r.c: Likewise.
+ * config/m68k/m68k.c: Likewise.
+ * config/mcore/mcore.c: Likewise.
+ * config/mep/mep.c: Likewise.
+ * config/microblaze/microblaze.c: Likewise.
+ * config/mips/mips.c: Likewise.
+ * config/mmix/mmix.c: Likewise.
+ * config/mn10300/mn10300.c: Likewise.
+ * config/moxie/moxie.c: Likewise.
+ * config/msp430/msp430.c: Likewise.
+ * config/nds32/nds32.c: Likewise.
+ * config/pa/pa.c: Likewise.
+ * config/pdp11/pdp11.c: Likewise.
+ * config/picochip/picochip.c: Likewise.
+ * config/rl78/rl78.c: Likewise.
+ * config/rs6000/rs6000.c: Likewise.
+ * config/rx/rx.c: Likewise.
+ * config/s390/s390.c: Likewise.
+ * config/score/score.c: Likewise.
+ * config/sh/sh.c: Likewise.
+ * config/sparc/sparc.c: Likewise.
+ * config/spu/spu.c: Likewise.
+ * config/stormy16/stormy16.c: Likewise.
+ * config/tilegx/tilegx.c: Likewise.
+ * config/tilepro/tilepro.c: Likewise.
+ * config/v850/v850.c: Likewise.
+ * config/vax/vax.c: Likewise.
+ * config/xtensa/xtensa.c: Likewise.
+
+2014-06-02 Jeff Law <law@redhat.com>
+
+ PR rtl-optimization/61094
+ * ree.c (combine_reaching_defs): Do not reextend an insn if it
+ was marked as do_no_reextend. If a copy is needed to eliminate
+ an extension, then mark it as do_not_reextend.
+
+2014-06-02 Marcus Shawcroft <marcus.shawcroft@arm.com>
+
+ * config/aarch64/aarch64.md (set_fpcr): Drop ISB after FPCR write.
+
+2014-06-02 Richard Henderson <rth@redhat.com>
+
+ PR target/61336
+ * config/alpha/alpha.c (print_operand_address): Allow symbolic
+ addresses inside asms. Use output_operand_lossage instead of
+ gcc_unreachable.
+
+2014-06-02 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/61239
+ * config/i386/i386.c (ix86_expand_vec_perm) [case V32QImode]: Use
+ GEN_INT (-128) instead of GEN_INT (128) to set MSB of QImode constant.
+
+2014-06-02 Tom de Vries <tom@codesourcery.com>
+
+ * config/aarch64/aarch64.c (aarch64_float_const_representable_p): Handle
+ case that x has VOIDmode.
+
+2014-06-02 Bernd Schmidt <bernds@codesourcery.com>
+
+ * varasm.c (copy_constant): Delete function.
+ (build_constant_desc): Don't call it.
+
+2014-06-02 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ PR target/61154
+ * config/arm/arm.h (TARGET_SUPPORTS_WIDE_INT): Define.
+ * config/arm/arm.md (mov64 splitter): Replace const_double_operand
+ with immediate_operand.
+
+2014-06-02 Andreas Schwab <schwab@suse.de>
+
+ * config/ia64/ia64.c
+ (ia64_first_cycle_multipass_dfa_lookahead_guard): Check
+ pending_data_specs first.
+
+2014-06-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61378
+ * tree-ssa-sccvn.c (vn_reference_lookup_3): Initialize
+ valueized_anything.
+
+2014-06-01 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/constraints.md (Bw): Rename from 'w'.
+ (Bz): Rename from 'z'.
+ * config/i386/i386.md: Change 'w' to 'Bw' and 'z' to 'Bz' globally.
+
+2014-06-01 Kai Tietz <ktietz@redhat.com>
+
+ PR target/61377
+ * config/i386/constrains.md (define_constrain): New 'Bs' constraint.
+ * config/i386/i386.md (sibcall_insn_operand): Use Bs
+ instead of m constraint.
+
+2014-05-31 Andreas Schwab <schwab@linux-m68k.org>
+
+ * config/m68k/m68k.md (beq0_di, bne0_di): Make the "o" constraint
+ a separate alternative where the scratch operand 2 is marked as
+ early clobber.
+
+2014-05-31 Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ * config/arm/arm.c (TARGET_ATOMIC_ASSIGN_EXPAND_FENV): New define.
+ (arm_builtins) : Add ARM_BUILTIN_GET_FPSCR and ARM_BUILTIN_SET_FPSCR.
+ (bdesc_2arg) : Add description for builtins __builtins_arm_set_fpscr
+ and __builtins_arm_get_fpscr.
+ (arm_init_builtins) : Initialize builtins __builtins_arm_set_fpscr and
+ __builtins_arm_get_fpscr.
+ (arm_expand_builtin) : Expand builtins __builtins_arm_set_fpscr and
+ __builtins_arm_ldfpscr.
+ (arm_atomic_assign_expand_fenv): New function.
+ * config/arm/vfp.md (set_fpscr): New pattern.
+ (get_fpscr) : Likewise.
+ * config/arm/unspecs.md (unspecv): Add VUNSPEC_GET_FPSCR and
+ VUNSPEC_SET_FPSCR.
+ * doc/extend.texi (AARCH64 Built-in Functions) : Document
+ __builtins_arm_set_fpscr, __builtins_arm_get_fpscr.
+
+2014-05-30 Jakub Jelinek <jakub@redhat.com>
+
+ * asan.c (report_error_func): Add SLOW_P argument, use
+ BUILT_IN_ASAN_*_N if set.
+ (build_check_stmt): Likewise.
+ (instrument_derefs): If T has insufficient alignment,
+ force same handling as for odd sizes.
+
+ * sanitizer.def (BUILT_IN_ASAN_REPORT_LOAD_N,
+ BUILT_IN_ASAN_REPORT_STORE_N): New.
+ * asan.c (struct asan_mem_ref): Change access_size type to
+ HOST_WIDE_INT.
+ (asan_mem_ref_init, asan_mem_ref_new, get_mem_refs_of_builtin_call,
+ update_mem_ref_hash_table): Likewise.
+ (asan_mem_ref_hasher::hash): Hash in a HWI.
+ (report_error_func): Change size_in_bytes argument to HWI.
+ Use *_N builtins if size_in_bytes is larger than 16 or not power of
+ two.
+ (build_shadow_mem_access): New function.
+ (build_check_stmt): Use it. Change size_in_bytes argument to HWI.
+ Handle size_in_bytes not power of two or larger than 16.
+ (instrument_derefs): Don't give up if size_in_bytes is not
+ power of two or is larger than 16.
+
+2014-05-30 Kai Tietz <ktietz@redhat.com>
+
+ PR target/60104
+ * config/i386/i386.c (x86_output_mi_thunk): Add memory case
+ for sibling-tail-calls.
+ * config/i386/i386.md (sibcall_insn_operand): Add memory-constrain
+ to its use.
+ * config/i386/predicates.md (sibcall_memory_operand): New predicate.
+ (sibcall_insn_operand): Add check for sibcall_memory_operand.
+
+2014-05-30 Pitchumani Sivanupandi <pitchumani.s@atmel.com>
+
+ * config/avr/avr-mcus.def: Change ATA6289 ISA to AVR4
+ * config/avr/avr-tables.opt: Regenerate.
+ * config/avr/t-multilib: Regenerate.
+ * doc/avr-mmcu.texi: Regenerate.
+
+2014-05-30 Ian Lance Taylor <iant@google.com>
+
+ * config/i386/xmmintrin.h (_mm_pause): Move out of scope of pragma
+ target("sse").
+
+2014-05-30 Tom de Vries <tom@codesourcery.com>
+
+ * config/i386/i386.c (TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS):
+ Redefine as true.
+
+2014-05-30 Tom de Vries <tom@codesourcery.com>
+
+ * lra-int.h (struct lra_reg): Add field actual_call_used_reg_set.
+ * lra.c (initialize_lra_reg_info_element): Add init of
+ actual_call_used_reg_set field.
+ (lra): Call lra_create_live_ranges before lra_inheritance for
+ -fuse-caller-save.
+ * lra-assigns.c (lra_assign): Allow call_used_regs to cross calls for
+ -fuse-caller-save.
+ * lra-constraints.c (need_for_call_save_p): Use actual_call_used_reg_set
+ instead of call_used_reg_set for -fuse-caller-save.
+ * lra-lives.c (process_bb_lives): Calculate actual_call_used_reg_set.
+
+2014-05-30 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/thumb2.md (*thumb2_movhi_insn): Set type of movw
+ to mov_imm.
+ * config/arm/vfp.md (*thumb2_movsi_vfp): Likewise.
+
+2014-05-30 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * ira.c (ira_get_dup_out_num): Check for output operands at
+ the start of the loop. Handle cases where an included alternative
+ follows an excluded one.
+
+2014-05-29 Mike Stump <mikestump@comcast.net>
+
+ PR debug/61352
+ * collect2.c (maybe_run_lto_and_relink): Be sure to always run
+ post ld passes when lto is used.
+
+2014-05-29 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/61325
+ * lra-constraints.c (process_address): Rename to process_address_1.
+ (process_address): New function.
+
+2014-05-29 Alan Lawrence <alan.lawrence@arm.com>
+
+ * config/aarch64/aarch64-builtins.c (aarch64_types_binopv_qualifiers,
+ TYPES_BINOPV): New static data.
+ * config/aarch64/aarch64-simd-builtins.def (im_lane_bound):
+ New builtin.
+ * config/aarch64/aarch64-simd.md (aarch64_ext,
+ aarch64_im_lane_boundsi): New patterns.
+ * config/aarch64/aarch64.c (aarch64_expand_vec_perm_const_1): Match
+ patterns for EXT.
+ (aarch64_evpc_ext): New function.
+
+ * config/aarch64/iterators.md (UNSPEC_EXT): New enum element.
+
+ * config/aarch64/arm_neon.h (vext_f32, vext_f64, vext_p8, vext_p16,
+ vext_s8, vext_s16, vext_s32, vext_s64, vext_u8, vext_u16, vext_u32,
+ vext_u64, vextq_f32, vextq_f64, vextq_p8, vextq_p16, vextq_s8,
+ vextq_s16, vextq_s32, vextq_s64, vextq_u8, vextq_u16, vextq_u32,
+ vextq_u64): Replace __asm with __builtin_shuffle and im_lane_boundsi.
+
+2014-05-29 Tom de Vries <tom@codesourcery.com>
+
+ * rtl.h (BLOCK_SYMBOL_CHECK): Use SYMBOL_REF_FLAGS.
+
+2014-05-29 Richard Earnshaw <rearnsha@arm.com>
+ Richard Sandiford <rdsandiford@googlemail.com>
+
+ * arm/iterators.md (shiftable_ops): New code iterator.
+ (t2_binop0, arith_shift_insn): New code attributes.
+ * arm/predicates.md (shift_nomul_operator): New predicate.
+ * arm/arm.md (insn_enabled): Delete.
+ (enabled): Remove insn_enabled test.
+ (*arith_shiftsi): Delete. Replace with ...
+ (*<arith_shift_insn>_multsi): ... new pattern.
+ (*<arith_shift_insn>_shiftsi): ... new pattern.
+ * config/arm/arm.c (arm_print_operand): Handle operand format 'b'.
+
+2014-05-29 Radovan Obradovic <robradovic@mips.com>
+ Tom de Vries <tom@codesourcery.com>
+
+ * config/mips/mips.h (POST_CALL_TMP_REG): Define.
+ * config/mips/mips.c (mips_emit_call_insn): Add POST_CALL_TMP_REG
+ clobber.
+ (mips_split_call): Use POST_CALL_TMP_REG.
+ (TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS): Redefine to true.
+
+2014-05-29 Tom de Vries <tom@codesourcery.com>
+
+ * final.c (collect_fn_hard_reg_usage): Guard variable declaration
+ with #ifdef STACK_REGS.
+
+2014-05-28 Jan Hubicka <hubicka@ucw.cz>
+
+ * varasm.c (get_variable_section): Walk aliases.
+ (place_block_symbol): Walk aliases.
+
+2014-05-28 Tom de Vries <tom@codesourcery.com>
+
+ Revert:
+ 2014-05-28 Tom de Vries <tom@codesourcery.com>
+
+ * lra-int.h (struct lra_reg): Add field actual_call_used_reg_set.
+ * lra.c (initialize_lra_reg_info_element): Add init of
+ actual_call_used_reg_set field.
+ (lra): Call lra_create_live_ranges before lra_inheritance for
+ -fuse-caller-save.
+ * lra-assigns.c (lra_assign): Allow call_used_regs to cross calls for
+ -fuse-caller-save.
+ * lra-constraints.c (need_for_call_save_p): Use
+ actual_call_used_reg_set instead of call_used_reg_set for
+ -fuse-caller-save.
+ * lra-lives.c (process_bb_lives): Calculate actual_call_used_reg_set.
+
+2014-05-28 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * doc/md.texi: Document that the % constraint character must
+ be at the beginning of the string.
+ * genoutput.c (validate_insn_alternatives): Check that '=',
+ '+' and '%' only appear at the beginning of a constraint.
+ * ira.c (commutative_constraint_p): Delete.
+ (ira_get_dup_out_num): Expect the '%' commutativity marker to be
+ at the start of the string.
+ * config/alpha/alpha.md (*movmemdi_1, *clrmemdi_1): Remove
+ duplicate '='s.
+ * config/arm/neon.md (bicdi3_neon): Likewise.
+ * config/iq2000/iq2000.md (addsi3_internal, subsi3_internal, sgt_si)
+ (slt_si, sltu_si): Likewise.
+ * config/vax/vax.md (sbcdi3): Likewise.
+ * config/h8300/h8300.md (*cmpstz): Remove duplicate '+'.
+ * config/arc/arc.md (mulsi_600, mulsidi_600, umulsidi_600)
+ (mul64): Move '%' to beginning of constraint.
+ * config/arm/arm.md (*xordi3_insn): Likewise.
+ * config/nds32/nds32.md (add<mode>3, mulsi3, andsi3, iorsi3)
+ (xorsi3): Likewise.
+
+2014-05-28 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * doc/md.texi: Document the restrictions on the "enabled" attribute.
+
+2014-05-28 Jason Merrill <jason@redhat.com>
+
+ PR c++/47202
+ * cgraph.h (symtab_node::get_comdat_group_id): New.
+ * cgraphunit.c (analyze_functions): Call it.
+ * symtab.c (dump_symtab_node): Likewise.
+ * tree.c (decl_comdat_group_id): New.
+ * tree.h: Declare it.
+ * lto-streamer-out.c (write_symbol): Use it.
+ * trans-mem.c (ipa_tm_create_version_alias): Likewise.
+
+2014-05-28 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR bootstrap/PR61146
+ * wide-int.cc: Do not include longlong.h when compiling with clang.
+
+2014-05-28 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-propagate.c (add_control_edge): Print less vertical space.
+ * tree-vrp.c (extract_range_from_ssa_name): Also copy VR_UNDEFINED.
+ (vrp_visit_assignment_or_call): Print less vertical space.
+ (vrp_visit_stmt): Likewise.
+ (vrp_visit_phi_node): Likewise. For a PHI argument with
+ VR_VARYING range consider recording it as copy.
+
+2014-05-28 Richard Biener <rguenther@suse.de>
+
+ Revert
+ 2014-05-28 Richard Biener <rguenther@suse.de>
+
+ * hwint.h (HOST_WIDE_INT_PRINT_*): Define in terms of PRI*64.
+
+2014-05-28 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * expr.c (expand_assignment): Fold the bitpos in the to_rtx if
+ sufficiently aligned and an offset is used at the same time.
+ (expand_expr_real_1): Likewise.
+
+2014-05-28 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/61045
+ * fold-const.c (fold_comparison): When folding
+ X +- C1 CMP Y +- C2 to X CMP Y +- C2 +- C1 also ensure
+ the sign of the remaining constant operand stays the same.
+
+2014-05-28 Kaushik Phatak <kaushik.phatak@kpit.com>
+
+ * config/rl78/rl78.h (TARGET_CPU_CPP_BUILTINS): Define
+ __RL78_64BIT_DOUBLES__ or __RL78_32BIT_DOUBLES__.
+ (ASM_SPEC): Pass -m64bit-doubles or -m32bit-doubles on
+ to the assembler.
+ (DOUBLE_TYPE_SIZE): Use 64 bit if TARGET_64BIT_DOUBLES is true.
+ * gcc/config/rl78/rl78.opt (m64bit-doubles): New option.
+ (m32bit-doubles) Likewise.
+ * gcc/config/rl78/t-rl78: Add 64-bit-double multilib.
+ * doc/invoke.texi: Document -m32bit-doubles and -m64bit-doubles
+ option for RL78.
+
+2014-05-28 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * configure.ac ($gcc_cv_ld_clearcap): New test.
+ * configure: Regenerate.
+ * config.in: Regenerate.
+ * config/sol2.opt (mclear-hwcap): New option.
+ * config/sol2.h (LINK_CLEARCAP_SPEC): Define.
+ * config/sol2-clearcap.map: Moved here from
+ testsuite/gcc.target/i386/clearcap.map.
+ * config/sol2-clearcapv2.map: Move here from
+ gcc.target/i386/clearcapv2.map.
+ * config/t-sol2 (install): Depend on install-clearcap-map.
+ (install-clearcap-map): New target.
+ * doc/invoke.texi (Option Summary, Solaris 2 Options): Document
+ -mclear-hwcap.
+
+2014-05-28 Richard Biener <rguenther@suse.de>
+
+ * hwint.h (*_HALF_WIDE_INT*): Move to ...
+ * wide-int.cc (HOST_BITS_PER_HALF_WIDE_INT, HOST_HALF_WIDE_INT):
+ ... here and remove the rest.
+ * hwint.h (HOST_WIDE_INT_PRINT_*): Define in terms of PRI*64.
+
+2014-05-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61335
+ * tree-vrp.c (vrp_visit_phi_node): If the compare of old and
+ new range fails, drop to varying.
+
+2014-05-28 Tom de Vries <tom@codesourcery.com>
+
+ * lra-int.h (struct lra_reg): Add field actual_call_used_reg_set.
+ * lra.c (initialize_lra_reg_info_element): Add init of
+ actual_call_used_reg_set field.
+ (lra): Call lra_create_live_ranges before lra_inheritance for
+ -fuse-caller-save.
+ * lra-assigns.c (lra_assign): Allow call_used_regs to cross calls for
+ -fuse-caller-save.
+ * lra-constraints.c (need_for_call_save_p): Use
+ actual_call_used_reg_set instead of call_used_reg_set for
+ -fuse-caller-save.
+ * lra-lives.c (process_bb_lives): Calculate actual_call_used_reg_set.
+
+2014-05-28 Radovan Obradovic <robradovic@mips.com>
+ Tom de Vries <tom@codesourcery.com>
+
+ * doc/invoke.texi (@item Optimization Options): Add -fuse-caller-save
+ to gccoptlist.
+ (@item -fuse-caller-save): New item.
+
+2014-05-28 Radovan Obradovic <robradovic@mips.com>
+ Tom de Vries <tom@codesourcery.com>
+
+ * opts.c (default_options_table): Add OPT_LEVELS_2_PLUS entry with
+ OPT_fuse_caller_save.
+
+2014-05-28 Radovan Obradovic <robradovic@mips.com>
+ Tom de Vries <tom@codesourcery.com>
+
+ * df-scan.c (df_get_call_refs): Use get_call_reg_set_usage.
+ * caller-save.c (setup_save_areas, save_call_clobbered_regs): Use
+ get_call_reg_set_usage.
+ * resource.c (mark_set_resources, mark_target_live_regs): Use
+ get_call_reg_set_usage.
+ * ira-int.h (struct ira_allocno): Add crossed_calls_clobbered_regs
+ field.
+ (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS): Define.
+ * ira-lives.c (process_bb_node_lives): Use get_call_reg_set_usage.
+ Calculate ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS.
+ * ira-build.c (ira_create_allocno): Init
+ ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS.
+ (create_cap_allocno, propagate_allocno_info)
+ (propagate_some_info_from_allocno)
+ (copy_info_to_removed_store_destinations): Handle
+ ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS.
+ * ira-costs.c (ira_tune_allocno_costs): Use
+ ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS to adjust costs.
+
+2014-05-28 Radovan Obradovic <robradovic@mips.com>
+ Tom de Vries <tom@codesourcery.com>
+
+ * cgraph.h (struct cgraph_rtl_info): Add function_used_regs
+ and function_used_regs_valid fields.
+ * final.c: Move include of hard-reg-set.h to before rtl.h to declare
+ find_all_hard_reg_sets.
+ (collect_fn_hard_reg_usage, get_call_fndecl, get_call_cgraph_rtl_info)
+ (get_call_reg_set_usage): New function.
+ (rest_of_handle_final): Use collect_fn_hard_reg_usage.
+ * regs.h (get_call_reg_set_usage): Declare.
+
+2014-05-28 Georg-Johann Lay <avr@gjlay.de>
+
+ PR libgcc/61152
+ * config/dbx.h (License): Add Runtime Library Exception.
+ * config/newlib-stdint.h (License): Same.
+ * config/rtems.h (License): Same
+ * config/initfini-array.h (License): Same
+ * config/v850/v850.h (License): Same.
+ * config/v850/v850-opts.h (License): Same
+ * config/v850/rtems.h (License): Same.
+
+2014-05-28 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/61044
+ * doc/extend.texi (Local Labels): Note that label differences are
+ not supported for AVR.
+
+2014-05-27 Andrew Pinski <apinski@cavium.com>
+
+ * config/aarch64/aarch64.md (stack_protect_set_<mode>):
+ Use <w> for the register in assembly template.
+ (stack_protect_test): Use the mode of operands[0] for the result.
+ (stack_protect_test_<mode>): Use <w> for the register
+ in assembly template.
+
+2014-05-27 DJ Delorie <dj@redhat.com>
+
+ * config/rx/rx.c (add_vector_labels): New.
+ (rx_output_function_prologue): Call it.
+ (rx_handle_func_attribute): Don't require empty arguments.
+ (rx_handle_vector_attribute): New.
+ (rx_attribute_table): Add "vector" attribute.
+ * doc/extend.texi (interrupt, vector): Document new/changed
+ RX-specific attributes.
+
+ * config/rx/rx.c (rx_adjust_insn_length): Skip for non-insns.
+
+2014-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * double-int.c (div_and_round_double) <ROUND_DIV_EXPR>: Use the proper
+ predicate to detect a negative quotient.
+
+2014-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * fold-const.c (fold_comparison): Clean up and extend X +- C1 CMP C2
+ to X CMP C2 -+ C1 transformation to EQ_EXPR/NE_EXPR.
+ Add X - Y CMP 0 to X CMP Y transformation.
+ (fold_binary_loc) <EQ_EXPR/NE_EXPR>: Remove same transformations.
+
+2014-05-27 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * stmt.c (dump_case_nodes): Don't convert values to HOST_WIDE_INT
+ before printing.
+
+2014-05-27 Steve Ellcey <sellcey@mips.com>
+
+ * config/mips/mips.c: Add include of cgraph.h.
+
+2014-05-27 Richard Biener <rguenther@suse.de>
+
+ * system.h (__STDC_FORMAT_MACROS): Define as very first thing.
+
+2014-05-27 Georg-Johann Lay <avr@gjlay.de>
+
+ PR libgcc/61152
+ * config/arm/arm.h (License): Add note to COPYING.RUNTIME.
+ * config/arm/arm-cores.def (License): Same.
+ * config/arm/arm-opts.h (License): Same.
+ * config/arm/aout.h (License): Same.
+ * config/arm/bpabi.h (License): Same.
+ * config/arm/elf.h (License): Same.
+ * config/arm/linux-elf.h (License): Same.
+ * config/arm/linux-gas.h (License): Same.
+ * config/arm/netbsd-elf.h (License): Same.
+ * config/arm/uclinux-eabi.h (License): Same.
+ * config/arm/uclinux-elf.h (License): Same.
+ * config/arm/vxworks.h (License): Same.
+
+2014-05-27 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/neon.md (neon_bswap<mode>): New pattern.
+ * config/arm/arm.c (neon_itype): Add NEON_BSWAP.
+ (arm_init_neon_builtins): Handle NEON_BSWAP.
+ Define required type nodes.
+ (arm_expand_neon_builtin): Handle NEON_BSWAP.
+ (arm_builtin_vectorized_function): Handle BUILTIN_BSWAP builtins.
+ * config/arm/arm_neon_builtins.def (bswap): Define builtins.
+ * config/arm/iterators.md (VDQHSD): New mode iterator.
+
+2014-05-27 Richard Biener <rguenther@suse.de>
+
+ * tree-vrp.c (vrp_evaluate_conditional_warnv_with_ops_using_ranges):
+ Try using literal operands when comparing value-ranges failed.
+
+2014-05-27 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * ira.c (commutative_operand): Adjust for change to recog_data.
+ [Missing from previous commit.]
+
+2014-05-27 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * system.h (TEST_BIT): New macro.
+ * recog.h (alternative_mask): New type.
+ (ALL_ALTERNATIVES, ALTERNATIVE_BIT): New macros.
+ (recog_data_d): Replace alternative_enabled_p array with
+ enabled_alternatives.
+ (target_recog): New structure.
+ (default_target_recog, this_target_recog): Declare.
+ (get_enabled_alternatives, recog_init): Likewise.
+ * recog.c (default_target_recog, this_target_recog): New variables.
+ (get_enabled_alternatives): New function.
+ (extract_insn): Use it.
+ (recog_init): New function.
+ (preprocess_constraints, constrain_operands): Adjust for change to
+ recog_data.
+ * postreload.c (reload_cse_simplify_operands): Likewise.
+ * reload.c (find_reloads): Likewise.
+ * ira-costs.c (record_reg_classes): Likewise.
+ * ira-lives.c (single_reg_class): Likewise. Fix bug in which
+ all alternatives after a disabled one would be skipped.
+ (ira_implicitly_set_insn_hard_regs): Likewise.
+ * ira.c (ira_setup_alts): Adjust for change to recog_data.
+ * lra-int.h (lra_insn_recog_data): Replace alternative_enabled_p
+ with enabled_alternatives.
+ * lra.c (free_insn_recog_data): Update accordingly.
+ (lra_update_insn_recog_data): Likewise.
+ (lra_set_insn_recog_data): Likewise. Use get_enabled_alternatives.
+ * lra-constraints.c (process_alt_operands): Likewise. Handle
+ only_alternative as part of the enabled mask.
+ * target-globals.h (this_target_recog): Declare.
+ (target_globals): Add a recog field.
+ (restore_target_globals): Restore this_target_recog.
+ * target-globals.c: Include recog.h.
+ (default_target_globals): Initialize recog field.
+ (save_target_globals): Likewise.
+ * reginfo.c (reinit_regs): Call recog_init.
+ * toplev.c (backend_init_target): Likewise.
+
+2014-05-27 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * gencodes.c (main): Make LAST_INSN_CODE higher than any insn code,
+ rather than any named insn's code.
+
+2014-05-27 Georg-Johann Lay <avr@gjlay.de>
+
+ PR libgcc/61152
+ * config/arm/arm-opts.h (License): Add GCC Runtime Library Exception.
+ * config/arm/arm-cores.def (License): Same.
+
+2014-05-26 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree.h (decl_comdat_group): Declare.
+ * cgraph.h (symtab_in_same_comdat_p): Move offline to ...
+ * tree.c (decl_comdat_group): Here.
+
+2014-05-26 Richard Sandiford <r.sandiford@uk.ibm.com>
+
+ PR rtl-optimization/61222
+ * combine.c (simplify_shift_const_1): When moving a PLUS outside
+ the shift, truncate the PLUS operand to the result mode.
+
+2014-05-26 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/61271
+ * config/i386/i386.c (ix86_rtx_costs)
+ <case CONST_INT, case CONST, case LABEL_REF, case SYMBOL_REF>:
+ Fix condition.
+
+2014-05-26 Martin Jambor <mjambor@suse.cz>
+
+ * ira.c (split_live_ranges_for_shrink_wrap): Remove bailout on
+ subreg uses.
+
+2014-05-26 Richard Biener <rguenther@suse.de>
+
+ * wide-int.h (wi::int_traits <long>, wi::int_traits <unsigned long>,
+ wi::int_traits <long long>, wi::int_traits <unsigned long long>):
+ Provide specializations.
+ (wi::int_traits <HOST_WIDE_INT>,
+ wi::int_traits <unsigned HOST_WIDE_INT>): Remove specializations.
+
+2014-05-26 Alan Modra <amodra@gmail.com>
+
+ PR target/61098
+ * config/rs6000/rs6000.c (rs6000_emit_set_const): Remove unneeded
+ params and return a bool. Remove dead code. Update comment.
+ Assert we have a const_int source. Remove bogus code from
+ 32-bit HWI days. Move !TARGET_POWERPC64 handling, and correct
+ handling of constants > 2G and reg_equal note, from..
+ (rs6000_emit_set_long_const): ..here. Remove unneeded param and
+ return value. Update comment. If we can, use a new pseudo
+ for intermediate calculations.
+ * config/rs6000/rs6000-protos.h (rs6000_emit_set_const): Update
+ prototype.
+ * config/rs6000/rs6000.md (movsi_internal1_single+1): Update
+ call to rs6000_emit_set_const in splitter.
+ (movdi_internal64+2, +3): Likewise.
+
+2014-05-26 Richard Biener <rguenther@suse.de>
+
+ * system.h: Define __STDC_FORMAT_MACROS before
+ including inttypes.h.
+ * hwint.h (HOST_WIDEST_INT, HOST_BITS_PER_WIDEST_INT,
+ HOST_WIDEST_INT_PRINT, HOST_WIDEST_INT_PRINT_DEC,
+ HOST_WIDEST_INT_PRINT_DEC_C, HOST_WIDEST_INT_PRINT_UNSIGNED,
+ HOST_WIDEST_INT_PRINT_HEX, HOST_WIDEST_INT_PRINT_DOUBLE_HEX,
+ HOST_WIDEST_INT_C): Remove.
+ (PRId64, PRIi64, PRIo64, PRIu64, PRIx64, PRIX64): Define
+ if C99 inttypes.h is not available.
+ * coretypes.h (gcov_type, gcov_type_unsigned): Use [u]int64_t.
+ * gcov-io.h (gcov_type, gcov_type_unsigned): Likewise.
+ * gcov-io.c (gcov_histo_index): Drop non-64bit hwi case.
+ * cfgloop.h (struct niter_desc): Use uint64_t for niter field.
+ * bitmap.c (struct bitmap_descriptor_d): Use uint64_t for counters.
+ (struct output_info): Likewise.
+ (print_statistics): Adjust.
+ (dump_bitmap_statistics): Likewise.
+ * bt-load.c (migrate_btr_defs): Print with PRId64.
+ * cfg.c (dump_edge_info, dump_bb_info): Likewise.
+ (MAX_SAFE_MULTIPLIER): Adjust.
+ * cfghooks.c (dump_bb_for_graph): Print with PRId64.
+ * cgraph.c (cgraph_redirect_edge_call_stmt_to_callee,
+ dump_cgraph_node): Likewise.
+ * final.c (dump_basic_block_info): Likewise.
+ * gcov-dump.c (tag_counters, tag_summary, dump_working_sets): Likewise.
+ * gcov.c (format_gcov): Likewise.
+ * ipa-cp.c (good_cloning_opportunity_p): Likewise. Use int64_t
+ for calculation.
+ (get_clone_agg_value): Use HOST_WIDE_INT for offset.
+ * ipa-inline.c (compute_max_insns): Use int64_t for calcuation.
+ (inline_small_functions, dump_overall_stats, dump_inline_stats):
+ Use PRId64 for dumping.
+ * ipa-profile.c (dump_histogram, ipa_profile): Likewise.
+ * ira-color.c (struct allocno_hard_regs): Use int64_t for cost.
+ (add_allocno_hard_regs): Adjust.
+ * loop-doloop.c (doloop_modify): Print using PRId64.
+ * loop-iv.c (inverse): Compute in uint64_t.
+ (determine_max_iter, iv_number_of_iterations): Likewise.
+ * loop-unroll.c (decide_peel_completely, decide_peel_simple):
+ Print using PRId64.
+ * lto-streamer-out.c (write_symbol): Use uint64_t.
+ * mcf.c (CAP_INFINITY): Use int64_t maximum.
+ (dump_fixup_edge, create_fixup_graph, cancel_negative_cycle,
+ find_max_flow, adjust_cfg_counts): Use int64_t and dump with PRId64.
+ * modulo-sched.c (const_iteration_count): Use int64_t.
+ (sms_schedule): Dump using PRId64.
+ * predict.c (dump_prediction): Likewise.
+ * pretty-print.h (pp_widest_integer): Remove.
+ * profile.c (get_working_sets, is_edge_inconsistent,
+ is_inconsistent, read_profile_edge_counts): Dump using PRId64.
+ * tree-pretty-print.c (pp_double_int): Remove case handling
+ HOST_BITS_PER_DOUBLE_INT == HOST_BITS_PER_WIDEST_INT.
+ * tree-ssa-math-opts.c (struct symbolic_number): Use uint64_t
+ and adjust users.
+ (pass_optimize_bswap::execute): Remove restriction on hosts.
+ * tree-streamer-in.c (streamer_alloc_tree): Use HOST_WIDE_INT.
+ * tree-streamer-out.c (streamer_write_tree_header): Likewise.
+ * tree.c (widest_int_cst_value): Remove.
+ * tree.h (widest_int_cst_value): Likewise.
+ * value-prof.c (dump_histogram_value): Print using PRId64.
+ * gengtype.c (main): Also inject int64_t.
+ * ggc-page.c (struct max_alignment): Use int64_t.
+ * alloc-pool.c (struct allocation_object_def): Likewise.
+ * ira-conflicts.c (build_conflict_bit_table): Use uint64_t
+ for computation.
+ * doc/tm.texi.in: Remove reference to HOST_WIDEST_INT.
+ * doc/tm.texi: Regenerated.
+ * gengtype-lex.l (IWORD): Handle [u]int64_t.
+ * config/sh/sh.c (expand_cbranchdi4): Use gcov_type.
+ * config/mmix/mmix-protos.h (mmix_intval, mmix_shiftable_wyde_value,
+ mmix_output_register_setting): Use [u]int64_t in prototypes.
+ * config/mmix/mmix.c (mmix_print_operand, mmix_output_register_setting,
+ mmix_shiftable_wyde_value, mmix_output_shiftvalue_op_from_str,
+ mmix_output_octa, mmix_output_shifted_value): Adjust.
+ (mmix_intval): Adjust. Remove unreachable case.
+ * config/mmix/mmix.md (*nonlocal_goto_receiver_expanded): Use int64_t.
+
+2014-05-26 Richard Biener <rguenther@suse.de>
+
+ * configure.ac: Drop __int64 type check. Insist that we
+ found uint64_t and int64_t.
+ * hwint.h (HOST_BITS_PER___INT64): Remove.
+ (HOST_BITS_PER_WIDE_INT): Define to 64 and remove __int64 case.
+ (HOST_WIDE_INT_PRINT_*): Remove 32bit case.
+ (HOST_WIDEST_INT*): Define to HOST_WIDE_INT*.
+ (HOST_WIDEST_FAST_INT): Remove __int64 case.
+ * vmsdbg.h (struct _DST_SRC_COMMAND): Use int64_t
+ for dst_q_src_df_rms_cdt.
+ * configure: Regenerate.
+ * config.in: Likewise.
+
+2014-05-26 Michael Tautschnig <mt@debian.org>
+
+ PR target/61249
+ * doc/extend.texi (X86 Built-in Functions): Fix parameter lists of
+ __builtin_ia32_vfrczs[sd] and __builtin_ia32_mpsadbw256.
+
+2014-05-26 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ PR rtl-optimization/61278
+ * shrink-wrap.c (move_insn_for_shrink_wrap): Check df_live.
+
+2014-05-26 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ PR rtl-optimization/61220
+ Part of PR rtl-optimization/61225
+ * shrink-wrap.c (move_insn_for_shrink_wrap): Skip SP and FP adjustment
+ insn; skip split_edge for a block with only one successor.
+
+2014-05-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * symtab.c (symtab_nonoverwritable_alias): Copy READONLY flag
+ for variables.
+
+2014-05-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-visibility.c (can_replace_by_local_alias_in_vtable): New function.
+ (update_vtable_references): New function.
+ (function_and_variable_visibility): Rewrite also vtable initializers.
+ * varpool.c (cgraph_variable_initializer_availability): Remove assert.
+
+2014-05-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * ggc.h (ggc_grow): New function.
+ * ggc-none.c (ggc_grow): New function.
+ * ggc-page.c (ggc_grow): Likewise.
+
+2014-05-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa.c (cgraph_non_local_node_p_1, cgraph_local_node_p,
+ address_taken_from_non_vtable_p, comdat_can_be_unshared_p_1,
+ comdat_can_be_unshared_p, cgraph_externally_visible_p,
+ varpool_externally_visible_p, can_replace_by_local_alias,
+ update_visibility_by_resolution_info, function_and_variable_visibility,
+ pass_data_ipa_function_and_variable_visibility,
+ make_pass_ipa_function_and_variable_visibility,
+ whole_program_function_and_variable_visibility,
+ pass_data_ipa_whole_program_visibility,
+ make_pass_ipa_whole_program_visibility): Move to ipa-visibility.c
+ * cgraph.h (cgraph_local_node_p): Declare.
+ * ipa-visibility.c: New file.
+ * Makefile.in (OBJS): Add ipa-visiblity.o
+
+2014-05-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * gimple-fold.c (can_refer_decl_in_current_unit_p): Be sure
+ that var decl is available.
+
+2014-05-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-core.h (tree_decl_with_vis): Replace comdat_group by
+ symtab_node pointer.
+ * tree.c (copy_node_stat): Be sure to not copy symtab_node pointer.
+ (find_decls_types_r): Do not walk COMDAT_GROUP.
+ * tree.h (DECL_COMDAT_GROUP): Revamp to use decl_comdat_group.
+ * varasm.c (make_decl_one_only): Use set_comdat_group;
+ create node if needed.
+ * ipa-inline-transform.c (save_inline_function_body): Update
+ way we decl->symtab mapping.
+ * symtab.c (symtab_hash, hash_node, eq_node
+ symtab_insert_node_to_hashtable): Remove.
+ (symtab_register_node): Update.
+ (symtab_unregister_node): Update.
+ (symtab_get_node): Reimplement as inline function.
+ (symtab_add_to_same_comdat_group): Update.
+ (symtab_dissolve_same_comdat_group_list): Update.
+ (dump_symtab_base): Update.
+ (verify_symtab_base): Update.
+ (symtab_make_decl_local): Update.
+ (fixup_same_cpp_alias_visibility): Update.
+ (symtab_nonoverwritable_alias): Update.
+ * cgraphclones.c (set_new_clone_decl_and_node_flags): Update.
+ * ipa.c (update_visibility_by_resolution_info): UPdate.
+ * bb-reorder.c: Include cgraph.h
+ * lto-streamer-out.c (DFS_write_tree_body, hash_tree): Do not deal
+ with comdat groups.
+ * ipa-comdats.c (set_comdat_group, ipa_comdats): Update.
+ * cgraph.c (cgraph_get_create_node): Update.
+ * cgraph.h (struct symtab_node): Add get_comdat_group, set_comdat_group
+ and comdat_group_.
+ (symtab_get_node): Make inline.
+ (symtab_insert_node_to_hashtable): Remove.
+ (symtab_can_be_discarded): Update.
+ (decl_comdat_group): New function.
+ * tree-streamer-in.c (lto_input_ts_decl_with_vis_tree_pointers):
+ Update.
+ * lto-cgraph.c (lto_output_node, lto_output_varpool_node): Stream out
+ comdat group name.
+ (read_comdat_group): New function.
+ (input_node, input_varpool_node): Use it.
+ * trans-mem.c (ipa_tm_create_version_alias): Update code creating
+ comdat groups.
+ * mips.c (mips_start_unique_function): Likewise.
+ (ix86_code_end): Likewise.
+ (rs6000_code_end): Likweise.
+ * tree-streamer-out.c (DECL_COMDAT_GROUP): Do not stream comdat group.
+
+2014-05-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * gengtype-state.c (fatal_reading_state): Bring offline.
+ * optabs.c (widening_optab_handler): Bring offline.
+ * optabs.h (widening_optab_handler): Likewise.
+ * final.c (get_attr_length_1): Likewise.
+
+2014-05-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * sched-int.h (sd_iterator_cond): Manually tail recurse.
+
+2014-05-23 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/440.md (ppc440-integer): Include shift without dot.
+ (ppc440-compare): Include shift with dot.
+ * config/rs6000/e300c2c3.md (ppce300c3_iu): Include shift without dot.
+ * config/rs6000/e5500.md (e5500_sfx2): Include constant shift
+ without dot.
+ * config/rs6000/e6500.md (e6500_sfx): Exclude constant shift
+ without dot.
+ (e6500_sfx2): Include it.
+ * config/rs6000/rs6000.md ( *zero_extend<mode>di2_internal1,
+ *zero_extend<mode>di2_internal2, *zero_extend<mode>di2_internal3,
+ *zero_extendsidi2_lfiwzx, andsi3_mc, andsi3_nomc,
+ andsi3_internal0_nomc, extzvsi_internal, extzvdi_internal,
+ *extzvdi_internal1, *extzvdi_internal2, rotlsi3, *rotlsi3_64,
+ *rotlsi3_internal4, *rotlsi3_internal7le, *rotlsi3_internal7be,
+ *rotlsi3_internal10le, *rotlsi3_internal10be, rlwinm,
+ *lshiftrt_internal1le, *lshiftrt_internal1be,
+ *lshiftrt_internal4le, *lshiftrt_internal4be, rotldi3,
+ *rotldi3_internal4, *rotldi3_internal7le, *rotldi3_internal7be,
+ *rotldi3_internal10le, *rotldi3_internal10be,
+ *rotldi3_internal13le, *rotldi3_internal13be, *ashldi3_internal4,
+ ashldi3_internal5, *ashldi3_internal6, *ashldi3_internal7,
+ ashldi3_internal8, *ashldi3_internal9, anddi3_mc, anddi3_nomc,
+ *anddi3_internal2_mc, *anddi3_internal3_mc, and 4 anonymous
+ define_insns): Use type "shift" in the appropriate alternatives.
+
+2014-05-23 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (type): Add "logical". Delete
+ "fast_compare".
+ (dot): Adjust comment.
+ (andsi3_mc, *andsi3_internal2_mc, *andsi3_internal3_mc,
+ *andsi3_internal4, *andsi3_internal5_mc, *boolsi3_internal2,
+ *boolsi3_internal3, *boolccsi3_internal2, *boolccsi3_internal3,
+ anddi3_mc, *anddi3_internal2_mc, *anddi3_internal3_mc,
+ *booldi3_internal2, *booldi3_internal3, *boolcdi3_internal2,
+ *boolcdi3_internal3, *boolccdi3_internal2, *boolccdi3_internal3,
+ *mov<mode>_internal2, and 10 anonymous define_insns): Use "logical".
+ * config/rs6000/rs6000.c (rs6000_adjust_cost): Adjust.
+
+ * config/rs6000/40x.md (ppc403-integer, ppc403-compare): Adjust.
+ * config/rs6000/440.md (ppc440-integer, ppc440-compare): Adjust.
+ * config/rs6000/476.md (ppc476-simple-integer, ppc476-compare): Adjust.
+ * config/rs6000/603.md (ppc603-integer, ppc603-compare): Adjust.
+ * config/rs6000/6xx.md (ppc604-integer, ppc604-compare): Adjust.
+ * config/rs6000/7450.md (ppc7450-integer, ppc7450-compare): Adjust.
+ * config/rs6000/7xx.md (ppc750-integer, ppc750-compare): Adjust.
+ * config/rs6000/8540.md (ppc8540_su): Adjust.
+ * config/rs6000/cell.md (cell-integer, cell-fast-cmp,
+ cell-cmp-microcoded): Adjust.
+ * config/rs6000/e300c2c3.md (ppce300c3_cmp, ppce300c3_iu): Adjust.
+ * config/rs6000/e500mc.md (e500mc_su): Adjust.
+ * config/rs6000/e500mc64.md (e500mc64_su, e500mc64_su2): Adjust.
+ * config/rs6000/e5500.md (e5500_sfx, e5500_sfx2): Adjust.
+ * config/rs6000/e6500.md (e6500_sfx, e6500_sfx2): Adjust.
+ * config/rs6000/mpc.md (mpccore-integer, mpccore-compare): Adjust.
+ * config/rs6000/power4.md (power4-integer, power4-cmp): Adjust.
+ * config/rs6000/power5.md (power5-integer, power5-cmp): Adjust.
+ * config/rs6000/power6.md (power6-integer, power6-fast-compare):
+ Adjust.
+ * config/rs6000/power7.md (power7-integer, power7-cmp): Adjust.
+ * config/rs6000/power8.md (power8-1cyc, power8-fast-compare):
+ Adjust. Adjust comment.
+ * config/rs6000/rs64.md (rs64a-integer, rs64a-compare): Adjust.
+ * config/rs6000/titan.md (titan_fxu_adder, titan_fxu_alu): Adjust.
+
+2014-05-23 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (type): Add "add".
+ (*add<mode>3_internal1, addsi3_high, *add<mode>3_internal2,
+ *add<mode>3_internal3, *neg<mode>2_internal, and 5 anonymous
+ define_insns): Use it.
+ * config/rs6000/rs6000.c (rs6000_adjust_cost): Adjust.
+
+ * config/rs6000/40x.md (ppc403-integer, ppc403-compare): Adjust.
+ * config/rs6000/440.md (ppc440-integer, ppc440-compare): Adjust.
+ * config/rs6000/476.md (ppc476-simple-integer, ppc476-compare): Adjust.
+ * config/rs6000/601.md (ppc601-integer): Adjust.
+ * config/rs6000/603.md (ppc603-integer, ppc603-compare): Adjust.
+ * config/rs6000/6xx.md (ppc604-integer, ppc604-compare): Adjust.
+ * config/rs6000/7450.md (ppc7450-integer, ppc7450-compare): Adjust.
+ * config/rs6000/7xx.md (ppc750-integer, ppc750-compare): Adjust.
+ * config/rs6000/8540.md (ppc8540_su): Adjust.
+ * config/rs6000/cell.md (cell-integer, cell-fast-cmp,
+ cell-cmp-microcoded): Adjust.
+ * config/rs6000/e300c2c3.md (ppce300c3_cmp, ppce300c3_iu): Adjust.
+ * config/rs6000/e500mc.md (e500mc_su): Adjust.
+ * config/rs6000/e500mc64.md (e500mc64_su, e500mc64_su2): Adjust.
+ * config/rs6000/e5500.md (e5500_sfx, e5500_sfx2): Adjust.
+ * config/rs6000/e6500.md (e6500_sfx, e6500_sfx2): Adjust.
+ * config/rs6000/mpc.md (mpccore-integer, mpccore-compare): Adjust.
+ * config/rs6000/power4.md (power4-integer, power4-cmp): Adjust.
+ * config/rs6000/power5.md (power5-integer, power5-cmp): Adjust.
+ * config/rs6000/power6.md (power6-integer, power6-fast-compare):
+ Adjust.
+ * config/rs6000/power7.md (power7-integer, power7-cmp): Adjust.
+ * config/rs6000/power8.md (power8-1cyc, power8-fast-compare): Adjust.
+ * config/rs6000/rs64.md (rs64a-integer, rs64a-compare): Adjust.
+ * config/rs6000/titan.md (titan_fxu_adder, titan_fxu_alu): Adjust.
+
+2014-05-23 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (type): Delete "var_shift_rotate",
+ "delayed_compare", "var_delayed_compare".
+ (var_shift): New attribute.
+ (cell_micro): Adjust.
+ (*andsi3_internal2_mc, *andsi3_internal3_mc, *andsi3_internal4,
+ *andsi3_internal5_mc, *extzvsi_internal1, *extzvsi_internal2,
+ rotlsi3, *rotlsi3_64, *rotlsi3_internal2, *rotlsi3_internal3,
+ *rotlsi3_internal4, *rotlsi3_internal5, *rotlsi3_internal6,
+ *rotlsi3_internal8le, *rotlsi3_internal8be, *rotlsi3_internal9le,
+ *rotlsi3_internal9be, *rotlsi3_internal10le, *rotlsi3_internal10be,
+ *rotlsi3_internal11le, *rotlsi3_internal11be, *rotlsi3_internal12le,
+ *rotlsi3_internal12be, ashlsi3, *ashlsi3_64, lshrsi3, *lshrsi3_64,
+ *lshiftrt_internal2le, *lshiftrt_internal2be, *lshiftrt_internal3le,
+ *lshiftrt_internal3be, *lshiftrt_internal5le, *lshiftrt_internal5be,
+ *lshiftrt_internal5le, *lshiftrt_internal5be, ashrsi3, *ashrsi3_64,
+ rotldi3, *rotldi3_internal2, *rotldi3_internal3, *rotldi3_internal4,
+ *rotldi3_internal5, *rotldi3_internal6, *rotldi3_internal7le,
+ *rotldi3_internal7be, *rotldi3_internal8le, *rotldi3_internal8be,
+ *rotldi3_internal9le, *rotldi3_internal9be, *rotldi3_internal10le,
+ *rotldi3_internal10be, *rotldi3_internal11le, *rotldi3_internal11be,
+ *rotldi3_internal12le, *rotldi3_internal12be, *rotldi3_internal13le,
+ *rotldi3_internal13be, *rotldi3_internal14le, *rotldi3_internal14be,
+ *rotldi3_internal15le, *rotldi3_internal15be, *ashldi3_internal1,
+ *ashldi3_internal2, *ashldi3_internal3, *lshrdi3_internal1,
+ *lshrdi3_internal2, *lshrdi3_internal3, *ashrdi3_internal1,
+ *ashrdi3_internal2, *ashrdi3_internal3, *anddi3_internal2_mc,
+ *anddi3_internal3_mc, as well as 11 anonymous define_insns): Adjust.
+ * config/rs6000/rs6000.c (rs6000_adjust_cost, is_cracked_insn,
+ insn_must_be_first_in_group, insn_must_be_last_in_group): Adjust.
+
+ * config/rs6000/40x.md (ppc403-integer, ppc403-compare): Adjust.
+ * config/rs6000/440.md (ppc440-integer): Adjust.
+ * config/rs6000/476.md (ppc476-simple-integer, ppc476-compare): Adjust.
+ * config/rs6000/601.md (ppc601-integer, ppc601-compare): Adjust.
+ * config/rs6000/603.md (ppc603-integer, ppc603-compare): Adjust.
+ * config/rs6000/6xx.md (ppc604-integer, ppc604-compare): Adjust.
+ * config/rs6000/7450.md (ppc7450-integer, ppc7450-compare): Adjust.
+ * config/rs6000/7xx.md (ppc750-integer, ppc750-compare): Adjust.
+ * config/rs6000/8540.md (ppc8540_su): Adjust.
+ * config/rs6000/cell.md (cell-integer, cell-fast-cmp,
+ cell-cmp-microcoded): Adjust.
+ * config/rs6000/e300c2c3.md (ppce300c3_cmp): Adjust.
+ * config/rs6000/e500mc.md (e500mc_su): Adjust.
+ * config/rs6000/e500mc64.md (e500mc64_su, e500mc64_su2,
+ e500mc64_delayed): Adjust.
+ * config/rs6000/e5500.md (e5500_sfx, e5500_delayed): Adjust.
+ * config/rs6000/e6500.md (e6500_sfx, e6500_delayed): Adjust.
+ * config/rs6000/mpc.md (mpccore-integer, mpccore-compare): Adjust.
+ * config/rs6000/power4.md (power4-integer, power4-compare): Adjust.
+ * config/rs6000/power5.md (power5-integer, power5-compare): Adjust.
+ * config/rs6000/power6.md (power6-shift, power6-var-rotate,
+ power6-delayed-compare, power6-var-delayed-compare): Adjust.
+ * config/rs6000/power7.md (power7-integer, power7-compare): Adjust.
+ * config/rs6000/power8.md (power8-1cyc, power8-compare): Adjust.
+ Adjust comment.
+ * config/rs6000/rs64.md (rs64a-integer, rs64a-compare): Adjust.
+ * config/rs6000/titan.md (titan_fxu_shift_and_rotate): Adjust.
+
+2014-05-23 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (type): Delete "idiv", "ldiv". Add "div".
+ (bits): New mode_attr.
+ (idiv_ldiv): Delete mode_attr.
+ (udiv<mode>3, *div<mode>3, div<div_extend>_<mode>): Adjust.
+ * config/rs6000/rs6000.c (rs6000_adjust_cost, is_cracked_insn,
+ rs6000_adjust_priority, is_nonpipeline_insn,
+ insn_must_be_first_in_group, insn_must_be_last_in_group): Adjust.
+
+ * config/rs6000/40x.md (ppc403-idiv): Adjust.
+ * config/rs6000/440.md (ppc440-idiv): Adjust.
+ * config/rs6000/476.md (ppc476-idiv): Adjust.
+ * config/rs6000/601.md (ppc601-idiv): Adjust.
+ * config/rs6000/603.md (ppc603-idiv): Adjust.
+ * config/rs6000/6xx.md (ppc604-idiv, ppc620-idiv, ppc630-idiv,
+ ppc620-ldiv): Adjust.
+ * config/rs6000/7450.md (ppc7450-idiv): Adjust.
+ * config/rs6000/7xx.md (ppc750-idiv): Adjust.
+ * config/rs6000/8540.md (ppc8540_divide): Adjust.
+ * config/rs6000/a2.md (ppca2-idiv, ppca2-ldiv): Adjust.
+ * config/rs6000/cell.md (cell-idiv, cell-ldiv): Adjust.
+ * config/rs6000/e300c2c3.md (ppce300c3_divide): Adjust.
+ * config/rs6000/e500mc.md (e500mc_divide): Adjust.
+ * config/rs6000/e500mc64.md (e500mc64_divide): Adjust.
+ * config/rs6000/e5500.md (e5500_divide, e5500_divide_d): Adjust.
+ * config/rs6000/e6500.md (e6500_divide, e6500_divide_d): Adjust.
+ * config/rs6000/mpc.md (mpccore-idiv): Adjust.
+ * config/rs6000/power4.md (power4-idiv, power4-ldiv): Adjust.
+ * config/rs6000/power5.md (power5-idiv, power5-ldiv): Adjust.
+ * config/rs6000/power6.md (power6-idiv, power6-ldiv): Adjust.
+ * config/rs6000/power7.md (power7-idiv, power7-ldiv): Adjust.
+ * config/rs6000/power8.md (power8-idiv, power8-ldiv): Adjust.
+ * config/rs6000/rs64.md (rs64a-idiv, rs64a-ldiv): Adjust.
+ * config/rs6000/titan.md (titan_fxu_div): Adjust.
+
+2014-05-23 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (type): Delete "insert_word",
+ "insert_dword". Add "insert".
+ (size): Update comment.
+ * config/rs6000/rs6000.c (rs6000_adjust_cost, is_cracked_insn,
+ insn_must_be_first_in_group): Adjust.
+ (insvsi_internal, *insvsi_internal1, *insvsi_internal2,
+ *insvsi_internal3, *insvsi_internal4, *insvsi_internal5,
+ *insvsi_internal6, insvdi_internal): Adjust.
+
+ * config/rs6000/40x.md (ppc403-integer): Adjust.
+ * config/rs6000/440.md (ppc440-integer): Adjust.
+ * config/rs6000/476.md (ppc476-simple-integer): Adjust.
+ * config/rs6000/601.md (ppc601-integer): Adjust.
+ * config/rs6000/603.md (ppc603-integer): Adjust.
+ * config/rs6000/6xx.md (ppc604-integer): Adjust.
+ * config/rs6000/7450.md (ppc7450-integer): Adjust.
+ * config/rs6000/7xx.md (ppc750-integer): Adjust.
+ * config/rs6000/8540.md (ppc8540_su): Adjust.
+ * config/rs6000/cell.md (cell-integer, cell-insert): Adjust.
+ * config/rs6000/e300c2c3.md (ppce300c3_iu): Adjust.
+ * config/rs6000/e500mc.md (e500mc_su): Adjust.
+ * config/rs6000/e500mc64.md (e500mc64_su): Adjust.
+ * config/rs6000/e5500.md (e5500_sfx): Adjust.
+ * config/rs6000/e6500.md (e6500_sfx): Adjust.
+ * config/rs6000/mpc.md (mpccore-integer): Adjust.
+ * config/rs6000/power4.md (power4-integer, power4-insert): Adjust.
+ * config/rs6000/power5.md (power5-integer, power5-insert): Adjust.
+ * config/rs6000/power6.md (power6-insert, power6-insert-dword): Adjust.
+ * config/rs6000/power7.md (power7-integer): Adjust.
+ * config/rs6000/power8.md (power8-1cyc): Adjust.
+ * config/rs6000/rs64.md (rs64a-integer): Adjust.
+ * config/rs6000/titan.md (titan_fxu_shift_and_rotate): Adjust.
+
+2014-05-23 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (type): Add "mul". Delete "imul",
+ "imul2", "imul3", "lmul", "imul_compare", "lmul_compare".
+ (size): New attribute.
+ (dot): New attribute.
+ (cell_micro): Adjust.
+ (mulsi3, *mulsi3_internal1, *mulsi3_internal2, mulsidi3,
+ umulsidi3, smulsi3_highpart, umulsi3_highpart, muldi3,
+ *muldi3_internal1, *muldi3_internal2, smuldi3_highpart,
+ umuldi3_highpart): Adjust.
+ * config/rs6000/rs6000.c (rs6000_adjust_cost, is_cracked_insn,
+ rs6000_adjust_priority, is_nonpipeline_insn,
+ insn_must_be_first_in_group, insn_must_be_last_in_group): Adjust.
+
+ * config/rs6000/40x.md (ppc403-imul, ppc405-imul, ppc405-imul2,
+ ppc405-imul3): Adjust.
+ * config/rs6000/440.md (ppc440-imul, ppc440-imul2): Adjust.
+ * config/rs6000/476.md (ppc476-imul): Adjust.
+ * config/rs6000/601.md (ppc601-imul): Adjust.
+ * config/rs6000/603.md (ppc603-imul, ppc603-imul2): Adjust.
+ * config/rs6000/6xx.md (ppc604-imul, ppc604e-imul, ppc620-imul,
+ ppc620-imul2, ppc620-imul3, ppc620-lmul): Adjust.
+ * config/rs6000/7450.md (ppc7450-imul, ppc7450-imul2): Adjust.
+ * config/rs6000/7xx.md (ppc750-imul, ppc750-imul2, ppc750-imul3):
+ Adjust.
+ * config/rs6000/8540.md (ppc8540_multiply): Adjust.
+ * config/rs6000/a2.md (ppca2-imul, ppca2-lmul): Adjust.
+ * config/rs6000/cell.md (cell-lmul, cell-lmul-cmp, cell-imul23,
+ cell-imul): Adjust.
+ * config/rs6000/e300c2c3.md (ppce300c3_multiply): Adjust.
+ * config/rs6000/e500mc.md (e500mc_multiply): Adjust.
+ * config/rs6000/e500mc64.md (e500mc64_multiply): Adjust.
+ * config/rs6000/e5500.md (e5500_multiply, e5500_multiply_i): Adjust.
+ * config/rs6000/e6500.md (e6500_multiply, e6500_multiply_i): Adjust.
+ * config/rs6000/mpc.md (mpccore-imul): Adjust.
+ * config/rs6000/power4.md (power4-lmul-cmp, power4-imul-cmp,
+ power4-lmul, power4-imul, power4-imul3): Adjust.
+ * config/rs6000/power5.md (power5-lmul-cmp, power5-imul-cmp,
+ power5-lmul, power5-imul, power5-imul3): Adjust.
+ * config/rs6000/power6.md (power6-lmul-cmp, power6-imul-cmp,
+ power6-lmul, power6-imul, power6-imul3): Adjust.
+ * config/rs6000/power7.md (power7-mul, power7-mul-compare): Adjust.
+ * config/rs6000/power8.md (power8-mul, power8-mul-compare): Adjust.
+
+ * config/rs6000/rs64.md (rs64a-imul, rs64a-imul2, rs64a-imul3,
+ rs64a-lmul): Adjust.
+ * config/rs6000/titan.md (titan_imul): Adjust.
+
+2014-05-23 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (type): Add new value "halfmul".
+ (*macchwc, *macchw, *macchwuc, *macchwu, *machhwc, *machhw,
+ *machhwuc, *machhwu, *maclhwc, *maclhw, *maclhwuc, *maclhwu,
+ *nmacchwc, *nmacchw, *nmachhwc, *nmachhw, *nmaclhwc, *nmaclhw,
+ *mulchwc, *mulchw, *mulchwuc, *mulchwu, *mulhhwc, *mulhhw,
+ *mulhhwuc, *mulhhwu, *mullhwc, *mullhw, *mullhwuc, *mullhwu): Use it.
+ * config/rs6000/40x.md (ppc405-imul3): Add type halfmul.
+ * config/rs6000/440.md (ppc440-imul2): Add type halfmul.
+ * config/rs6000/476.md (ppc476-imul): Add type halfmul.
+ * config/rs6000/titan.md: Delete nonsensical comment.
+ (titan_imul): Add type imul3.
+ (titan_mulhw): Remove type imul3; add type halfmul.
+
+2014-05-23 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (type): Reorder, reformat.
+
+2014-05-23 Martin Jambor <mjambor@suse.cz>
+
+ PR tree-optimization/53787
+ * params.def (PARAM_IPA_MAX_AA_STEPS): New param.
+ * ipa-prop.h (ipa_node_params): Rename uses_analysis_done to
+ analysis_done, update all uses.
+ * ipa-prop.c: Include domwalk.h
+ (param_analysis_info): Removed.
+ (param_aa_status): New type.
+ (ipa_bb_info): Likewise.
+ (func_body_info): Likewise.
+ (ipa_get_bb_info): New function.
+ (aa_overwalked): Likewise.
+ (find_dominating_aa_status): Likewise.
+ (parm_bb_aa_status_for_bb): Likewise.
+ (parm_preserved_before_stmt_p): Changed to use new param AA info.
+ (load_from_unmodified_param): Accept func_body_info as a parameter
+ instead of parms_ainfo.
+ (parm_ref_data_preserved_p): Changed to use new param AA info.
+ (parm_ref_data_pass_through_p): Likewise.
+ (ipa_load_from_parm_agg_1): Likewise. Update callers.
+ (compute_complex_assign_jump_func): Changed to use new param AA info.
+ (compute_complex_ancestor_jump_func): Likewise.
+ (ipa_compute_jump_functions_for_edge): Likewise.
+ (ipa_compute_jump_functions): Removed.
+ (ipa_compute_jump_functions_for_bb): New function.
+ (ipa_analyze_indirect_call_uses): Likewise, moved variable
+ declarations down.
+ (ipa_analyze_virtual_call_uses): Accept func_body_info instead of node
+ and info, moved variable declarations down.
+ (ipa_analyze_call_uses): Accept and pass on func_body_info instead of
+ node and info.
+ (ipa_analyze_stmt_uses): Likewise.
+ (ipa_analyze_params_uses): Removed.
+ (ipa_analyze_params_uses_in_bb): New function.
+ (ipa_analyze_controlled_uses): Likewise.
+ (free_ipa_bb_info): Likewise.
+ (analysis_dom_walker): New class.
+ (ipa_analyze_node): Handle node-specific forbidden analysis,
+ initialize and free func_body_info, use dominator walker.
+ (ipcp_modif_dom_walker): New class.
+ (ipcp_transform_function): Create and free func_body_info, use
+ ipcp_modif_dom_walker, moved a lot of functionality there.
+
+2014-05-23 Marek Polacek <polacek@redhat.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ * builtins.def: Change SANITIZE_FLOAT_DIVIDE to SANITIZE_NONDEFAULT.
+ * gcc.c (sanitize_spec_function): Likewise.
+ * convert.c (convert_to_integer): Include "ubsan.h". Add
+ floating-point to integer instrumentation.
+ * doc/invoke.texi: Document -fsanitize=float-cast-overflow.
+ * flag-types.h (enum sanitize_code): Add SANITIZE_FLOAT_CAST and
+ SANITIZE_NONDEFAULT.
+ * opts.c (common_handle_option): Handle -fsanitize=float-cast-overflow.
+ * sanitizer.def (BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW,
+ BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT): Add.
+ * ubsan.c: Include "realmpfr.h" and "dfp.h".
+ (get_ubsan_type_info_for_type): Handle REAL_TYPEs.
+ (ubsan_type_descriptor): Set tkind to 0xffff for types other than
+ float/double/long double.
+ (ubsan_instrument_float_cast): New function.
+ * ubsan.h (ubsan_instrument_float_cast): Declare.
+
+2014-05-23 Jiong Wang <jiong.wang@arm.com>
+
+ * config/aarch64/predicates.md (aarch64_call_insn_operand): New
+ predicate.
+ * config/aarch64/constraints.md ("Ucs", "Usf"): New constraints.
+ * config/aarch64/aarch64.md (*sibcall_insn, *sibcall_value_insn):
+ Adjust for tailcalling through registers.
+ * config/aarch64/aarch64.h (enum reg_class): New caller save
+ register class.
+ (REG_CLASS_NAMES): Likewise.
+ (REG_CLASS_CONTENTS): Likewise.
+ * config/aarch64/aarch64.c (aarch64_function_ok_for_sibcall):
+ Allow tailcalling without decls.
+
+2014-05-23 Thomas Schwinge <thomas@codesourcery.com>
+
+ * gimplify.c (omp_notice_variable) <case OMP_CLAUSE_DEFAULT_NONE>:
+ Rewrite check for ORT_PARALLEL and ORT_COMBINED_PARALLEL.
+
+ * omp-low.c (expand_omp_for_static_chunk): Rename variable si to
+ gsi, and variables v_* to v*.
+
+2014-05-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * varasm.c (output_constructor_bitfield): Fix thinkos in latest change.
+
+2014-05-23 Thomas Schwinge <thomas@codesourcery.com>
+
+ * gimple.h (enum gf_mask): Add and use GF_OMP_FOR_SIMD.
+ * omp-low.c: Update accordingly.
+
+ * gimple.h (enum gf_mask): Rewrite "<< 0" shift expressions used
+ for GF_OMP_FOR_KIND_MASK, GF_OMP_FOR_KIND_FOR,
+ GF_OMP_FOR_KIND_DISTRIBUTE, GF_OMP_FOR_KIND_SIMD,
+ GF_OMP_FOR_KIND_CILKSIMD, GF_OMP_TARGET_KIND_MASK,
+ GF_OMP_TARGET_KIND_REGION, GF_OMP_TARGET_KIND_DATA,
+ GF_OMP_TARGET_KIND_UPDATE.
+
+ * gimplify.c (omp_notice_variable) <case OMP_CLAUSE_DEFAULT_NONE>:
+ Explicitly enumerate the expected region types.
+
+2014-05-23 Paul Eggert <eggert@cs.ucla.edu>
+
+ PR other/56955
+ * doc/extend.texi (Function Attributes): Fix __attribute__ ((malloc))
+ documentation; the old documentation didn't clearly state the
+ constraints on the contents of the pointed-to storage.
+
+2014-05-23 Maxim Kuvyrkov <maxim.kuvyrkov@linaro.org>
+
+ Fix bootstrap error on ia64
+ * config/ia64/ia64.c (ia64_first_cycle_multipass_dfa_lookahead_guard):
+ Return default value.
+
+2014-05-23 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ PR tree-optimization/54733
+ * tree-ssa-math-opts.c (nop_stats): New "bswap_stats" structure.
+ (CMPNOP): Define.
+ (find_bswap_or_nop_load): New.
+ (find_bswap_1): Renamed to ...
+ (find_bswap_or_nop_1): This. Also add support for memory source.
+ (find_bswap): Renamed to ...
+ (find_bswap_or_nop): This. Also add support for memory source and
+ detection of bitwise operations equivalent to load in host endianness.
+ (execute_optimize_bswap): Likewise. Also move its leading comment back
+ in place and split statement transformation into ...
+ (bswap_replace): This.
+
+2014-05-22 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/61215
+ * lra-elelimination.c (lra_eliminate_regs_1): Don't use
+ simplify_gen_subreg until final substitution.
+
+2014-05-23 Alan Modra <amodra@gmail.com>
+
+ PR target/61231
+ * config/rs6000/rs6000.c (mem_operand_gpr): Handle SImode.
+ * config/rs6000/rs6000.md (extendsidi2_lfiwax, extendsidi2_nocell):
+ Use "Y" constraint rather than "m".
+
+2014-05-23 Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ * config/aarch64/aarch64.c (TARGET_ATOMIC_ASSIGN_EXPAND_FENV): New
+ define.
+ * config/aarch64/aarch64-protos.h (aarch64_atomic_assign_expand_fenv):
+ New function declaration.
+ * config/aarch64/aarch64-builtins.c (aarch64_builtins) : Add
+ AARCH64_BUILTIN_GET_FPCR, AARCH64_BUILTIN_SET_FPCR.
+ AARCH64_BUILTIN_GET_FPSR and AARCH64_BUILTIN_SET_FPSR.
+ (aarch64_init_builtins) : Initialize builtins
+ __builtins_aarch64_set_fpcr, __builtins_aarch64_get_fpcr.
+ __builtins_aarch64_set_fpsr and __builtins_aarch64_get_fpsr.
+ (aarch64_expand_builtin) : Expand builtins __builtins_aarch64_set_fpcr
+ __builtins_aarch64_get_fpcr, __builtins_aarch64_get_fpsr,
+ and __builtins_aarch64_set_fpsr.
+ (aarch64_atomic_assign_expand_fenv): New function.
+ * config/aarch64/aarch64.md (set_fpcr): New pattern.
+ (get_fpcr) : Likewise.
+ (set_fpsr) : Likewise.
+ (get_fpsr) : Likewise.
+ (unspecv): Add UNSPECV_GET_FPCR and UNSPECV_SET_FPCR, UNSPECV_GET_FPSR
+ and UNSPECV_SET_FPSR.
+ * doc/extend.texi (AARCH64 Built-in Functions) : Document
+ __builtins_aarch64_set_fpcr, __builtins_aarch64_get_fpcr.
+ __builtins_aarch64_set_fpsr and __builtins_aarch64_get_fpsr.
+
+2014-05-22 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/60969
+ * ira-costs.c (record_reg_classes): Process NO_REGS for matching
+ constraints. Set up mem cost for NO_REGS case.
+
+2014-05-22 Thomas Schwinge <thomas@codesourcery.com>
+
+ * builtin-types.def: Simplify examples for DEF_FUNCTION_TYPE_*.
+
+2012-05-22 Bernd Schmidt <bernds@codesourcery.com>
+
+ * config/darwin.c: Include "lto-section-names.h".
+ (LTO_SEGMENT_NAME): Don't define.
+ * config/i386/winnt.c: Include "lto-section-names.h".
+ * lto-streamer.c: Include "lto-section-names.h".
+ * lto-streamer.h (LTO_SECTION_NAME_PREFIX): Don't define.
+ * lto-wrapper.c: Include "lto-section-names.h".
+ (LTO_SECTION_NAME_PREFIX): Don't define.
+ * lto-section-names.h: New file.
+ * cgraphunit.c: Include "lto-section-names.h".
+
+2014-05-22 Peter Bergner <bergner@vnet.ibm.com>
+
+ * config/rs6000/htm.md (ttest): Use correct shift value to get CR0.
+
+2014-05-22 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/61208
+ * arm.md (arm_cmpdi_unsigned): Fix length calculation for Thumb2.
+
+2014-05-22 Nick Clifton <nickc@redhat.com>
+
+ * config/msp430/msp430.h (ASM_SPEC): Add spaces after inserted options.
+
+2014-05-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * tree-ssa-forwprop.c (associate_plusminus): Extend (T)(P + A) - (T)P
+ -> (T)A transformation to integer types.
+
+2014-05-22 Teresa Johnson <tejohnson@google.com>
+
+ * gcov-io.c (gcov_position): Use gcov_nonruntime_assert.
+ (gcov_is_error): Remove gcc_assert from IN_LIBGCOV code.
+ (gcov_rewrite): Use gcov_nonruntime_assert.
+ (gcov_open): Ditto.
+ (gcov_write_words): Ditto.
+ (gcov_write_length): Ditto.
+ (gcov_read_words): Use gcov_nonruntime_assert, and remove
+ gcc_assert from IN_LIBGCOV code.
+ (gcov_read_summary): Use gcov_error to flag profile corruption.
+ (gcov_sync): Use gcov_nonruntime_assert.
+ (gcov_seek): Remove gcc_assert from IN_LIBGCOV code.
+ (gcov_histo_index): Use gcov_nonruntime_assert.
+ (static void gcov_histogram_merge): Ditto.
+ (compute_working_sets): Ditto.
+ * gcov-io.h (gcov_nonruntime_assert): Define.
+ (gcov_error): Define for !IN_LIBGCOV
+
+2014-05-22 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Handle
+ BUILT_IN_REALLOC like BUILT_IN_STRDUP.
+ (call_may_clobber_ref_p_1): Handle BUILT_IN_REALLOC as allocation
+ and deallocation site.
+ * tree-ssa-structalias.c (find_func_aliases_for_builtin_call):
+ Handle BUILT_IN_REALLOC similar to BUILT_IN_STRDUP with also
+ passing through the incoming points-to set.
+ (handle_lhs_call): Use flags argument instead of recomputing it.
+ (find_func_aliases_for_call): Call handle_lhs_call with proper
+ call return flags.
+
+2014-05-22 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-streamer-in.c (unpack_ts_real_cst_value_fields): Make sure
+ all padding bits in REAL_VALUE_TYPE are cleared.
+
+2014-05-22 Maxim Kuvyrkov <maxim.kuvyrkov@linaro.org>
+
+ Cleanup and improve multipass_dfa_lookahead_guard
+ * config/i386/i386.c (core2i7_first_cycle_multipass_filter_ready_try,)
+ (core2i7_first_cycle_multipass_begin,)
+ (core2i7_first_cycle_multipass_issue,)
+ (core2i7_first_cycle_multipass_backtrack): Update signature.
+ * config/ia64/ia64.c
+ (ia64_first_cycle_multipass_dfa_lookahead_guard_spec): Remove.
+ (ia64_first_cycle_multipass_dfa_lookahead_guard): Update signature.
+ (TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC): Remove
+ hook definition.
+ (ia64_first_cycle_multipass_dfa_lookahead_guard): Merge logic from
+ ia64_first_cycle_multipass_dfa_lookahead_guard_spec. Update return
+ values.
+ * config/rs6000/rs6000.c (rs6000_use_sched_lookahead_guard): Update
+ return values.
+ * doc/tm.texi: Regenerate.
+ * doc/tm.texi.in
+ (TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC): Remove.
+ * haifa-sched.c (ready_try): Make signed to allow negative values.
+ (rebug_ready_list_1): Update.
+ (choose_ready): Simplify.
+ (sched_extend_ready_list): Update.
+
+2014-05-22 Maxim Kuvyrkov <maxim.kuvyrkov@linaro.org>
+
+ Remove IA64 speculation tweaking flags
+ * config/ia64/ia64.c (ia64_set_sched_flags): Delete handling of
+ speculation tuning flags.
+ (msched-prefer-non-data-spec-insns,)
+ (msched-prefer-non-control-spec-insns): Obsolete options.
+ * haifa-sched.c (choose_ready): Remove handling of
+ PREFER_NON_CONTROL_SPEC and PREFER_NON_DATA_SPEC.
+ * sched-int.h (enum SPEC_SCHED_FLAGS): Remove PREFER_NON_CONTROL_SPEC
+ and PREFER_NON_DATA_SPEC.
+ * sel-sched.c (process_spec_exprs): Remove handling of
+ PREFER_NON_CONTROL_SPEC and PREFER_NON_DATA_SPEC.
+
+2014-05-22 Maxim Kuvyrkov <maxim.kuvyrkov@linaro.org>
+
+ Improve scheduling debug output
+ * haifa-sched.c (debug_ready_list): Remove unnecessary prototype.
+ (advance_one_cycle): Update.
+ (schedule_insn, queue_to_ready): Add debug printouts.
+ (debug_ready_list_1): New static function.
+ (debug_ready_list): Update.
+ (max_issue): Add debug printouts.
+ (dump_insn_stream): New static function.
+ (schedule_block): Use it. Also better indent printouts.
+
+2014-05-22 Maxim Kuvyrkov <maxim.kuvyrkov@linaro.org>
+
+ Fix sched_insn debug counter
+ * haifa-sched.c (schedule_insn): Update.
+ (struct haifa_saved_data): Add nonscheduled_insns_begin.
+ (save_backtrack_point, restore_backtrack_point): Update.
+ (first_nonscheduled_insn): New static function.
+ (queue_to_ready, choose_ready): Use it.
+ (schedule_block): Init nonscheduled_insns_begin.
+ (sched_emit_insn): Update.
+
+
+2014-05-22 Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ * config/aarch64/aarch64.c (aarch64_regno_regclass) : Change CORE_REGS
+ to GENERAL_REGS.
+ (aarch64_secondary_reload) : LikeWise.
+ (aarch64_class_max_nregs) : Remove CORE_REGS.
+ * config/aarch64/aarch64.h (enum reg_class) : Remove CORE_REGS.
+ (REG_CLASS_NAMES) : Likewise.
+ (REG_CLASS_CONTENTS) : LikeWise.
+ (INDEX_REG_CLASS) : Change CORE_REGS to GENERAL_REGS.
+
+2014-05-21 Guozhi Wei <carrot@google.com>
+
+ PR target/61202
+ * config/aarch64/arm_neon.h (vqdmulh_n_s16): Change the last operand's
+ constraint.
+ (vqdmulhq_n_s16): Likewise.
+
+2014-05-21 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/predicates.md (update_indexed_address_mem): Delete.
+
+2014-05-21 Marek Polacek <polacek@redhat.com>
+
+ PR sanitizer/61272
+ * ubsan.c (is_ubsan_builtin_p): Turn assert into a condition.
+
+2014-05-21 Martin Jambor <mjambor@suse.cz>
+
+ * doc/invoke.texi (Optimize Options): Document parameters
+ ipa-cp-eval-threshold, ipa-max-agg-items, ipa-cp-loop-hint-bonus and
+ ipa-cp-array-index-hint-bonus.
+
+2014-05-21 Mark Wielaard <mjw@redhat.com>
+
+ PR debug/16063
+ * dwarf2out.c (gen_enumeration_type_die): Add DW_AT_type if DWARF
+ version >= 3 or not strict DWARF.
+ * langhooks.h (struct lang_hooks_for_types): Add
+ enum_underlying_base_type.
+ * langhooks.c (lhd_enum_underlying_base_type): New function.
+ * gcc/langhooks.h (struct lang_hooks_for_types): Add
+ enum_underlying_base_type.
+ * langhooks-def.h (lhd_enum_underlying_base_type): New declaration.
+ (LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE): New define.
+ (LANG_HOOKS_FOR_TYPES_INITIALIZER): Add new lang hook.
+
+2014-05-21 Richard Biener <rguenther@suse.de>
+
+ * doc/invoke.texi (-flto-partition=): Document one and none algorithms.
+
+2014-05-21 John Marino <gnugcc@marino.st>
+
+ * config.gcc (*-*-dragonfly*): New target.
+ * configure.ac: Detect dl_iterate_phdr (*freebsd*, *dragonfly*).
+ * configure: Regenerate.
+ * config/dragonfly-stdint.h: New.
+ * config/dragonfly.h: New.
+ * config/dragonfly.opt: New.
+ * config/i386/dragonfly.h: New.
+ * ginclude/stddef.h: Detect _PTRDIFF_T_DECLARED for DragonFly.
+
+2014-05-21 Richard Sandiford <rsandifo@linux.vnet.ibm.com>
+
+ * tree.def (VOID_CST): New.
+ * tree-core.h (TI_VOID): New.
+ * tree.h (void_node): New.
+ * tree.c (tree_node_structure_for_code, tree_code_size)
+ (iterative_hash_expr): Handle VOID_CST.
+ (build_common_tree_nodes): Initialize void_node.
+
+2014-05-21 Bernd Schmidt <bernds@codesourcery.com>
+
+ * reload1.c (remove_init_insns, will_delete_init_insn_p): New static
+ functions.
+ (reload, calculate_needs_all_insns, reload_as_needed): Use them.
+
+ * config/bfin/bfin.c (split_load_immediate): Use gen_int_mode in a few
+ more places.
+
+ * cfgrtl.c (cfg_layout_initialize): Weaken assert to only trigger if
+ flag_reorder_blocks_and_partition.
+ * hw-doloop.c (reorg_loops): Avoid reordering if that flag is set.
+
+2014-05-21 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/54236
+ * config/sh/sh.md (*addc_r_1): Rename to addc_t_r. Remove empty
+ constraints.
+ (*addc_r_t): Add new insn_and_split.
+
+2014-05-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/61252
+ * omp-low.c (handle_simd_reference): New function.
+ (lower_rec_input_clauses): Use it. Defer adding reference
+ initialization even for reduction without placeholder if in simd,
+ handle it properly later on.
+
+2014-05-20 Jan Hubicka <hubicka@ucw.cz>
+
+ PR tree-optimization/60899
+ * gimple-fold.c (can_refer_decl_in_current_unit_p): Cleanup;
+ assume all static symbols will have definition wile parsing and
+ check the do have definition later in compilation; check that
+ variable referring symbol will be output before concluding that
+ reference is safe; be conservative for referring local statics;
+ be more precise about when comdat is output in other partition.
+
+2014-05-20 Jan Hubicka <hubicka@ucw.cz>
+
+ PR bootstrap/60984
+ * ipa-inline-transform.c (inline_call): Use add CALLEE_REMOVED
+ parameter.
+ * ipa-inline.c (inline_to_all_callers): If callee was removed; return.
+ (ipa_inline): Loop inline_to_all_callers until no more aliases
+ are removed.
+
+2014-05-20 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa.c (ipa_discover_readonly_nonaddressable_var): Fix dumping;
+ set writeonly flag only for vars actually written to.
+
+2014-05-20 Dehao Chen <dehao@google.com>
+
+ * ipa-inline-transform.c (clone_inlined_nodes): Use min of edge count
+ and callee count to get clone count.
+ * tree-inline.c (expand_call_inline): Use callee count instead of bb
+ count in copy_body.
+
+2014-05-20 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR rtl-optimization/61243
+ * emit-rtl.c (emit_copy_of_insn_after): Copy CROSSING_JUMP_P.
+
+2014-05-20 Xinliang David Li <davidxl@google.com>
+
+ * cgraphunit.c (walk_polymorphic_call_targets): Add
+ dbgcnt and fopt-info support.
+ * ipa-prop.c (ipa_make_edge_direct_to_target): Ditto.
+ * ipa-devirt.c (ipa_devirt): Ditto.
+ * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): Ditto.
+ * ipa.c (walk_polymorphic_call_targets): Ditto.
+ * gimple-fold.c (fold_gimple_assign): Ditto.
+ (gimple_fold_call): Ditto.
+ * dbgcnt.def: New counter.
+
+2014-05-20 DJ Delorie <dj@redhat.com>
+
+ * config/msp430/msp430.md (split): Don't allow subregs when
+ splitting SImode adds.
+ (andneghi): Fix subtraction logic.
+ * config/msp430/predicates.md (msp430_nonsubreg_or_imm_operand): New.
+
+2014-05-20 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree.h (DECL_ONE_ONLY): Return true only for externally visible
+ symbols.
+ * except.c (switch_to_exception_section, resolve_unique_section,
+ get_named_text_section, default_function_rodata_section,
+ align_variable, get_block_for_decl, default_section_type_flags):
+ Use DECL_COMDAT_GROUP instead of DECL_ONE_ONLY.
+ * symtab.c (symtab_add_to_same_comdat_group,
+ symtab_make_decl_local, fixup_same_cpp_alias_visibility,
+ symtab_nonoverwritable_alias, symtab_get_symbol_partitioning_class):
+ Likewise.
+ * cgraphclones.c (cgraph_create_virtual_clone): Likewise.
+ * bb-reorder.c (pass_partition_blocks::gate): Likewise.
+ * config/c6x/c6x.c (c6x_elf_unique_section): Likewise.
+ (c6x_function_in_section_p): Likewise.
+ * config/darwin.c (machopic_select_section): Likewise.
+ * config/arm/arm.c (arm_function_in_section_p): Likewise.
+ * config/mips/mips.c (mips_function_rodata_section): Likewise.
+ * config/mep/mep.c (mep_select_section): LIkewise.
+ * config/i386/i386.c (x86_64_elf_unique_section): Likewise.
+
+2014-05-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * tree-ssa-dom.c (hashable_expr_equal_p) <EXPR_CALL>: Also compare the
+ EH region of calls to pure functions that can throw an exception.
+ * tree-ssa-sccvn.c (vn_reference_eq): Remove duplicated test.
+ (copy_reference_ops_from_call): Also copy the EH region of the call if
+ it can throw an exception.
+
+2014-05-20 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * simplify-rtx.c (simplify_binary_operation_1): Optimize case of
+ nested VEC_SELECTs that are inverses of each other.
+
+2014-05-20 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (process_scc): Dump SCC here, when iterating,
+ (extract_and_process_scc_for_name): not here.
+ (cond_dom_walker::before_dom_children): Only process
+ stmts that end the BB in interesting ways.
+ (run_scc_vn): Mark param uses as visited.
+
+2014-05-20 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/arm.md (arith_shiftsi): Do not predicate for
+ arm_restrict_it.
+
+2014-05-20 Nick Clifton <nickc@redhat.com>
+
+ * config/msp430/msp430.c (TARGET_GIMPLIFY_VA_ARG_EXPR): Define.
+ (msp430_gimplify_va_arg_expr): New function.
+ (msp430_print_operand): Handle (CONST (ZERO_EXTRACT)).
+
+ * config/msp430/msp430.md (zero_extendpsisi2): Use + constraint on
+ operand 0 in order to prevent confusion about the number of
+ registers involved.
+
+2014-05-20 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61221
+ * tree-ssa-pre.c (el_to_update): Remove.
+ (eliminate_dom_walker::before_dom_children): Handle released
+ VDEFs by value-numbering them to the associated VUSE. Update
+ stmt immediately for substituted call address.
+ (eliminate): Remove delayed stmt updating code.
+ * tree-ssa-sccvn.c (vuse_ssa_val): New function valueizing
+ possibly late re-numbered vuses.
+ (vn_reference_lookup_2): Adjust.
+ (vn_reference_lookup_pieces): Likewise.
+ (vn_reference_lookup): Likewise.
+
+2014-05-20 Richard Biener <rguenther@suse.de>
+
+ * config.gcc: Remove need_64bit_hwint.
+ * configure.ac: Do not define NEED_64BIT_HOST_WIDE_INT.
+ * hwint.h: Do not check NEED_64BIT_HOST_WIDE_INT but assume
+ it to be true.
+ * config.in: Regenerate.
+ * configure: Likewise.
+
+2014-05-19 David Wohlferd <dw@LimeGreenSocks.com>
+
+ * doc/extend.texi: Create Label Attributes section,
+ move all label attributes into it and reference it.
+
+2014-05-19 Richard Earnshaw <rearnsha@arm.com>
+
+ * arm.c (thumb1_reorg): When scanning backwards skip anything
+ that's not a proper insn.
+
+2014-05-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61221
+ * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children):
+ Do nothing for unreachable blocks.
+ * tree-ssa-sccvn.c (cond_dom_walker::before_dom_children):
+ Improve unreachability detection.
+
+2014-05-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61209
+ * tree-ssa-sccvn.c (visit_phi): Avoid setting expr to VN_TOP.
+
+2014-05-19 Nick Clifton <nickc@redhat.com>
+
+ * except.c (init_eh): Fix computation of builtin setjmp buffer
+ size to allow for targets where POINTER_SIZE > BITS_PER_WORD.
+
+2014-05-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61184
+ * tree-vrp.c (is_negative_overflow_infinity): Use
+ TREE_OVERFLOW_P and do that check first.
+ (is_positive_overflow_infinity): Likewise.
+ (is_overflow_infinity): Likewise.
+ (vrp_operand_equal_p): Properly treat operands with
+ differing overflow as not equal.
+
+2014-05-19 Bernd Schmidt <bernds@codesourcery.com>
+
+ * simplify-rtx.c (simplify_unary_operation_1): Use CONST_INT_P in
+ shift simplification where it was intended.
+
+2014-05-19 Christian Bruel <christian.bruel@st.com>
+
+ PR target/61195
+ * config/sh/sh.md (movsf_ie): Unset fp_mode for fmov.
+
+2014-05-19 Richard Sandiford <r.sandiford@uk.ibm.com>
+
+ PR target/61084
+ * config/sparc/sparc.c (sparc_fold_builtin): Use widest_int rather
+ than wide_int.
+
+2014-05-19 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * reg-notes.def (CROSSING_JUMP): Likewise.
+ * rtl.h (rtx_def): Update comment for jump flag.
+ (CROSSING_JUMP_P): Define.
+ * cfgcleanup.c (try_forward_edges, try_optimize_cfg): Use it instead
+ of a REG_CROSSING_JUMP note.
+ * cfghooks.c (tidy_fallthru_edges): Likewise.
+ * cfgrtl.c (fixup_partition_crossing, rtl_verify_edges): Likewise.
+ * emit-rtl.c (try_split): Likewise.
+ * haifa-sched.c (sched_create_recovery_edges): Likewise.
+ * ifcvt.c (find_if_case_1, find_if_case_2): Likewise.
+ * jump.c (redirect_jump_2): Likewise.
+ * reorg.c (follow_jumps, fill_slots_from_thread): Likewise.
+ (relax_delay_slots): Likewise.
+ * config/arc/arc.md (jump_i, cbranchsi4_scratch, *bbit): Likewise.
+ (bbit_di): Likewise.
+ * config/arc/arc.c (arc_reorg, arc_can_follow_jump): Likewise.
+ * config/sh/sh.md (jump_compact): Likewise.
+ * bb-reorder.c (rotate_loop): Likewise.
+ (pass_duplicate_computed_gotos::execute): Likewise.
+ (add_reg_crossing_jump_notes): Rename to...
+ (update_crossing_jump_flags): ...this.
+ (pass_partition_blocks::execute): Update accordingly.
+
+2014-05-19 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * tree.h: Remove extraneous template <>.
+
+2014-05-17 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa.c (symtab_remove_unreachable_nodes): Remove
+ symbol from comdat group if its body was eliminated.
+ (comdat_can_be_unshared_p_1): Static symbols can always be privatized.
+ * symtab.c (symtab_remove_from_same_comdat_group): Break out from ...
+ (symtab_unregister_node): ... this one.
+ (verify_symtab_base): More strict checking of comdats.
+ * cgraph.h (symtab_remove_from_same_comdat_group): Declare.
+
+2014-05-17 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-pass.h (make_pass_ipa_comdats): New pass.
+ * timevar.def (TV_IPA_COMDATS): New timevar.
+ * passes.def (pass_ipa_comdats): Add.
+ * Makefile.in (OBJS): Add ipa-comdats.o
+ * ipa-comdats.c: New file.
+
+2014-05-17 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa.c (update_visibility_by_resolution_info): New function.
+ (function_and_variable_visibility): Use it.
+
+2014-05-17 Jan Hubicka <hubicka@ucw.cz>
+
+ * cgraph.h (symtab_first_defined_symbol, symtab_next_defined_symbol):
+ New functions.
+ (FOR_EACH_DEFINED_SYMBOL): New macro.
+ (varpool_first_static_initializer, varpool_next_static_initializer,
+ varpool_first_defined_variable, varpool_next_defined_variable):
+ Fix comments.
+ (symtab_in_same_comdat_p): Correctly deal with inline functions.
+
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * ggc-page.c (ggc_handle_finalizers): Add comment.
+
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * ggc-common.c (ggc_internal_cleared_alloc): Adjust.
+ * ggc-none.c (ggc_internal_alloc): Assert if a finalizer is passed.
+ (ggc_internal_cleared_alloc): Likewise.
+ * ggc-page.c (finalizer): New class.
+ (vec_finalizer): Likewise.
+ (globals::finalizers): New member.
+ (globals::vec_finalizers): Likewise.
+ (ggc_internal_alloc): Record the finalizer if any for the block being
+ allocated.
+ (ggc_handle_finalizers): New function.
+ (ggc_collect): Call ggc_handle_finalizers.
+ * ggc.h (ggc_internal_alloc): Add arguments to allow installing a
+ finalizer.
+ (ggc_internal_cleared_alloc): Likewise.
+ (finalize): New function.
+ (need_finalization_p): Likewise.
+ (ggc_alloc): Install the type's destructor as the finalizer if it
+ might do something.
+ (ggc_cleared_alloc): Likewise.
+ (ggc_vec_alloc): Likewise.
+ (ggc_cleared_vec_alloc): Likewise.
+
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * ggc.h (ggc_alloc_cleared_simd_clone_stat): Remove function.
+
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * alias.c (record_alias_subset): Adjust.
+ * bitmap.c (bitmap_element_allocate): Likewise.
+ (bitmap_gc_alloc_stat): Likewise.
+ * cfg.c (init_flow): Likewise.
+ (alloc_block): Likewise.
+ (unchecked_make_edge): Likewise.
+ * cfgloop.c (alloc_loop): Likewise.
+ (flow_loops_find): Likewise.
+ (rescan_loop_exit): Likewise.
+ * cfgrtl.c (init_rtl_bb_info): Likewise.
+ * cgraph.c (insert_new_cgraph_node_version): Likewise.
+ (cgraph_allocate_node): Likewise.
+ (cgraph_create_edge_1): Likewise.
+ (cgraph_allocate_init_indirect_info): Likewise.
+ * cgraphclones.c (cgraph_clone_edge): Likewise.
+ * cgraphunit.c (add_asm_node): Likewise.
+ (init_lowered_empty_function): Likewise.
+ * config/aarch64/aarch64.c (aarch64_init_machine_status): Likewise.
+ * config/alpha/alpha.c (alpha_init_machine_status): Likewise.
+ (alpha_use_linkage): Likewise.
+ * config/arc/arc.c (arc_init_machine_status): Likewise.
+ * config/arm/arm.c (arm_init_machine_status): Likewise.
+ * config/avr/avr.c (avr_init_machine_status): Likewise.
+ * config/bfin/bfin.c (bfin_init_machine_status): Likewise.
+ * config/c6x/c6x.c (c6x_init_machine_status): Likewise.
+ * config/cris/cris.c (cris_init_machine_status): Likewise.
+ * config/darwin.c (machopic_indirection_name): Likewise.
+ (darwin_build_constant_cfstring): Likewise.
+ (darwin_enter_string_into_cfstring_table): Likewise.
+ * config/epiphany/epiphany.c (epiphany_init_machine_status): Likewise.
+ * config/frv/frv.c (frv_init_machine_status): Likewise.
+ * config/i386/i386.c (get_dllimport_decl): Likewise.
+ (ix86_init_machine_status): Likewise.
+ (assign_386_stack_local): Likewise.
+ * config/i386/winnt.c (i386_pe_record_external_function): Likewise.
+ (i386_pe_maybe_record_exported_symbol): Likewise.
+ (i386_pe_record_stub): Likewise.
+ * config/ia64/ia64.c (ia64_init_machine_status): Likewise.
+ * config/iq2000/iq2000.c (iq2000_init_machine_status): Likewise.
+ * config/m32c/m32c.c (m32c_init_machine_status): Likewise.
+ (m32c_note_pragma_address): Likewise.
+ * config/mep/mep.c (mep_init_machine_status): Likewise.
+ (mep_note_pragma_flag): Likewise.
+ * config/mips/mips.c (mflip_mips16_use_mips16_p): Likewise.
+ (mips16_local_alias): Likewise.
+ (mips_init_machine_status): Likewise.
+ * config/mmix/mmix.c (mmix_init_machine_status): Likewise.
+ * config/moxie/moxie.c (moxie_init_machine_status): Likewise.
+ * config/msp430/msp430.c (msp430_init_machine_status): Likewise.
+ * config/nds32/nds32.c (nds32_init_machine_status): Likewise.
+ * config/nios2/nios2.c (nios2_init_machine_status): Likewise.
+ * config/pa/pa.c (pa_init_machine_status): Likewise.
+ (pa_get_deferred_plabel): Likewise.
+ * config/rl78/rl78.c (rl78_init_machine_status): Likewise.
+ * config/rs6000/rs6000.c (builtin_function_type): Likewise.
+ (rs6000_init_machine_status): Likewise.
+ (output_toc): Likewise.
+ * config/s390/s390.c (s390_init_machine_status): Likewise.
+ * config/score/score.c (score_output_external): Likewise.
+ * config/sparc/sparc.c (sparc_init_machine_status): Likewise.
+ * config/spu/spu.c (spu_init_machine_status): Likewise.
+ * config/tilegx/tilegx.c (tilegx_init_machine_status): Likewise.
+ * config/tilepro/tilepro.c (tilepro_init_machine_status): Likewise.
+ * config/xtensa/xtensa.c (xtensa_init_machine_status): Likewise.
+ * coverage.c (coverage_end_function): Likewise.
+ * dbxout.c (dbxout_init): Likewise.
+ * doc/gty.texi: Don't mention variable_size attribute.
+ * dwarf2cfi.c (new_cfi): Adjust.
+ (new_cfi_row): Likewise.
+ (copy_cfi_row): Likewise.
+ (create_cie_data): Likewise.
+ * dwarf2out.c (dwarf2out_alloc_current_fde): Likewise.
+ (new_loc_descr): Likewise.
+ (find_AT_string_in_table): Likewise.
+ (add_addr_table_entry): Likewise.
+ (new_die): Likewise.
+ (add_var_loc_to_decl): Likewise.
+ (clone_die): Likewise.
+ (clone_as_declaration): Likewise.
+ (break_out_comdat_types): Likewise.
+ (new_loc_list): Likewise.
+ (add_loc_descr_to_each): Likewise.
+ (add_location_or_const_value_attribute): Likewise.
+ (add_linkage_name): Likewise.
+ (lookup_filename): Likewise.
+ (dwarf2out_var_location): Likewise.
+ (new_line_info_table): Likewise.
+ (dwarf2out_init): Likewise.
+ (mem_loc_descriptor): Likewise.
+ (loc_descriptor): Likewise.
+ (add_const_value_attribute): Likewise.
+ (tree_add_const_value_attribute): Likewise.
+ (comp_dir_string): Likewise.
+ (dwarf2out_vms_debug_main_pointer): Likewise.
+ (string_cst_pool_decl): Likewise.
+ * emit-rtl.c (set_mem_attrs): Likewise.
+ (get_reg_attrs): Likewise.
+ (start_sequence): Likewise.
+ (init_emit): Likewise.
+ (init_emit_regs): Likewise.
+ * except.c (init_eh_for_function): Likewise.
+ (gen_eh_region): Likewise.
+ (gen_eh_region_catch): Likewise.
+ (gen_eh_landing_pad): Likewise.
+ (add_call_site): Likewise.
+ * function.c (add_frame_space): Likewise.
+ (insert_temp_slot_address): Likewise.
+ (assign_stack_temp_for_type): Likewise.
+ (get_hard_reg_initial_val): Likewise.
+ (allocate_struct_function): Likewise.
+ (prepare_function_start): Likewise.
+ (types_used_by_var_decl_insert): Likewise.
+ * gengtype.c (variable_size_p): Remove function.
+ (enum alloc_quantity): Remove enum.
+ (write_typed_alloc_def): Remove function.
+ (write_typed_struct_alloc_def): Likewise.
+ (write_typed_typedef_alloc_def): Likewise.
+ (write_typed_alloc_defns): Likewise.
+ (main): Adjust.
+ * ggc-common.c (ggc_cleared_alloc_htab_ignore_args): Adjust.
+ (ggc_cleared_alloc_ptr_array_two_args): Likewise.
+ * ggc.h (ggc_alloc): new function.
+ (ggc_cleared_alloc): Likewise.
+ (ggc_vec_alloc): Template on type of vector element, and remove
+ element size argument.
+ (ggc_cleared_vec_alloc): Likewise.
+ * gimple.c (gimple_build_omp_for): Adjust.
+ (gimple_copy): Likewise.
+ * ipa-cp.c (get_replacement_map): Likewise.
+ (find_aggregate_values_for_callers_subset): Likewise.
+ (known_aggs_to_agg_replacement_list): Likewise.
+ * ipa-devirt.c (get_odr_type): Likewise.
+ * ipa-prop.c (ipa_node_duplication_hook): Likewise.
+ (read_agg_replacement_chain): Likewise.
+ * loop-iv.c (get_simple_loop_desc): Likewise.
+ * lto-cgraph.c (input_node_opt_summary): Likewise.
+ * lto-section-in.c (lto_new_in_decl_state): Likewise.
+ * lto-streamer-in.c (lto_input_eh_catch_list): Likewise.
+ (input_eh_region): Likewise.
+ (input_eh_lp): Likewise.
+ (input_cfg): Likewise.
+ * optabs.c (set_optab_libfunc): Likewise.
+ (init_tree_optimization_optabs): Likewise.
+ (set_conv_libfunc): Likewise.
+ * passes.c (do_per_function_toporder): Likewise.
+ * rtl.h: Don't use variable_size gty attribute.
+ * sese.c (if_region_set_false_region): Adjust.
+ * stringpool.c (gt_pch_save_stringpool): Likewise.
+ * target-globals.c (save_target_globals): Likewise.
+ * toplev.c (general_init): Likewise.
+ * trans-mem.c (record_tm_replacement): Likewise.
+ (split_bb_make_tm_edge): Likewise.
+ * tree-cfg.c (move_sese_region_to_fn): Likewise.
+ * tree-data-ref.h (lambda_vector_new): Likewise.
+ * tree-eh.c (add_stmt_to_eh_lp_fn): Likewise.
+ * tree-iterator.c (tsi_link_before): Likewise.
+ (tsi_link_after): Likewise.
+ * tree-scalar-evolution.c (new_scev_info_str): Likewise.
+ * tree-ssa-loop-niter.c (record_estimate): Likewise.
+ * tree-ssa-operands.c (ssa_operand_alloc): Likewise.
+ * tree-ssa-operands.h: Don't use variable_size gty attribute.
+ * tree-ssa.c (init_tree_ssa): Adjust.
+ * tree-ssanames.c (set_range_info): Likewise.
+ (get_ptr_info): Likewise.
+ (duplicate_ssa_name_ptr_info): Likewise.
+ (duplicate_ssa_name_range_info): Likewise.
+ * tree-streamer-in.c (unpack_ts_real_cst_value_fields): Likewise.
+ (unpack_ts_fixed_cst_value_fields): Likewise.
+ * tree.c (build_fixed): Likewise.
+ (build_real): Likewise.
+ (build_string): Likewise.
+ (decl_priority_info): Likewise.
+ (decl_debug_expr_insert): Likewise.
+ (decl_value_expr_insert): Likewise.
+ (decl_debug_args_insert): Likewise.
+ (type_hash_add): Likewise.
+ (build_omp_clause): Likewise.
+ * ubsan.c (decl_for_type_insert): Likewise.
+ * varasm.c (get_unnamed_section): Likewise.
+ (get_noswitch_section): Likewise.
+ (get_section): Likewise.
+ (get_block_for_section): Likewise.
+ (create_block_symbol): Likewise.
+ (build_constant_desc): Likewise.
+ (create_constant_pool): Likewise.
+ (force_const_mem): Likewise.
+ (record_tm_clone_pair): Likewise.
+ * varpool.c (varpool_create_empty_node): Likewise.
+
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * dwarf2out.c (tree_add_const_value_attribute): Call
+ ggc_internal_cleared_alloc instead of ggc_alloc_cleared_atomic.
+ * gengtype.c (write_typed_alloc_def): Call ggc_internal_<x>alloc
+ instead of ggc_internal_<x>alloc_stat.
+ * ggc-common.c (ggc_internal_cleared_alloc): Drop _stat suffix.
+ (ggc_realloc): Likewise.
+ * ggc-none.c (ggc_internal_alloc): Likewise.
+ (ggc_internal_cleared_alloc): Likewise.
+ * ggc-page.c: Likewise.
+ * ggc.h (ggc_internal_alloc_stat): Likewise.
+ (ggc_internal_alloc): Remove macro.
+ (ggc_internal_cleared_alloc_stat): Drop _stat suffix.
+ (ggc_internal_cleared_alloc): Remove macro.
+ (GGC_RESIZEVEC): Adjust.
+ (ggc_resizevar): Remove macro.
+ (ggc_internal_vec_alloc_stat): Drop _stat suffix.
+ (ggc_internal_cleared_vec_alloc_stat): Likewise.
+ (ggc_internal_vec_cleared_alloc): Remove macro.
+ (ggc_alloc_atomic_stat): Drop _stat suffix.
+ (ggc_alloc_atomic): Remove macro.
+ (ggc_alloc_cleared_atomic): Remove macro.
+ (ggc_alloc_string_stat): Drop _stat suffix.
+ (ggc_alloc_string): Remove macro.
+ (ggc_alloc_rtx_def_stat): Adjust.
+ (ggc_alloc_tree_node_stat): Likewise.
+ (ggc_alloc_cleared_tree_node_stat): Likewise.
+ (ggc_alloc_cleared_gimple_statement_stat): Likewise.
+ (ggc_alloc_cleared_simd_clone_stat): Likewise.
+ * gimple.c (gimple_build_omp_for): Likewise.
+ (gimple_copy): Likewise.
+ * stringpool.c (ggc_alloc_string_stat): Drop _stat suffix.
+ * toplev.c (realloc_for_line_map): Adjust.
+ * tree-data-ref.h (lambda_vector_new): Likewise.
+ * tree-phinodes.c (allocate_phi_node): Likewise.
+ * tree.c (grow_tree_vec_stat): Likewise.
+ * vec.h (va_gc::reserve): Adjust.
+
+2014-05-17 Ajit Agarwal <ajitkum@xilinx.com>
+
+ * config/microblaze/microblaze.c (break_handler): New Declaration.
+ (microblaze_break_function_p,microblaze_is_break_handler): New.
+ (compute_frame_size): Use microblaze_break_function_p.
+ Add the test of break_handler.
+ (microblaze_function_prologue) : Add the test of variable
+ break_handler. Check the fnname by BREAK_HANDLER_NAME.
+ (microblaze_function_epilogue) : Add the test of break_handler.
+ (microblaze_globalize_label) : Add the test of break_handler.
+ Check the name by BREAK_HANDLER_NAME.
+
+ * config/microblaze/microblaze.h (BREAK_HANDLER_NAME): New macro
+
+ * config/microblaze/microblaze.md (*<optab>,<optab>_internal): Add
+ microblaze_is_break_handler test.
+ (call_internal1,call_value_intern): Use microblaze_break_function_p.
+ Use SYMBOL_REF_DECL.
+
+ * config/microblaze/microblaze-protos.h
+ (microblaze_break_function_p,microblaze_is_break_handler):
+ New Declaration.
+
+ * doc/extend.texi (MicroBlaze break_handler Functions): Document
+ new MicroBlaze break_handler functions.
+
+2014-05-17 Uros Bizjak <ubizjak@gmail.com>
+
+ * doc/extend.texi (Size of an asm): Move node text according
+ to its @menu entry position.
+
+2014-05-17 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/61140
+ PR tree-optimization/61150
+ PR tree-optimization/61197
+ * tree-ssa-phiopt.c (value_replacement): Punt on multiple phis.
+
+2014-05-17 Uros Bizjak <ubizjak@gmail.com>
+
+ * doc/invoke.texi (free): Mention Alpha. Also enabled at -Os.
+
+2014-05-17 Richard Sandiford <r.sandiford@uk.ibm.com>
+
+ * wide-int.cc: Only include longlong.h if W_TYPE_SIZE==32 or
+ __SIZEOF_INT128__ is defined.
+
+2014-05-17 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * config/rs6000/rs6000.c (rs6000_real_tls_symbol_ref_p): New function.
+ (rs6000_delegitimize_address): Use it.
+
+2014-05-17 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * emit-rtl.h (replace_equiv_address, replace_equiv_address_nv): Add an
+ inplace argument. Store the new address in the original MEM when true.
+ * emit-rtl.c (change_address_1): Likewise.
+ (adjust_address_1, adjust_automodify_address_1, offset_address):
+ Update accordingly.
+ * rtl.h (plus_constant): Add an inplace argument.
+ * explow.c (plus_constant): Likewise. Try to reuse the original PLUS
+ when true. Avoid generating (plus X (const_int 0)).
+ * function.c (instantiate_virtual_regs_in_rtx): Adjust the PLUS
+ in-place. Pass true to plus_constant.
+ (instantiate_virtual_regs_in_insn): Pass true to replace_equiv_address.
+
+2014-05-16 Dehao Chen <dehao@google.com>
+
+ * tree-cfg.c (gimple_merge_blocks): Updates bb count with max count.
+
+2014-05-16 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/54089
+ * config/sh/predicates.md (negt_reg_shl31_operand): Match additional
+ patterns.
+ * config/sh/sh.md (*negt_msb): Merge SH2A and non-SH2A variants.
+
+2014-05-16 Dehao Chen <dehao@google.com>
+
+ * ira-int.h (REG_FREQ_FROM_EDGE_FREQ): Use
+ optimize_function_for_size_p.
+ * regs.h (REG_FREQ_FROM_BB): Likewise.
+
+2014-05-16 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/51244
+ * config/sh/sh.c (sh_eval_treg_value): Handle t_reg_operand and
+ negt_reg_operand cases.
+ * config/sh/sh.md (*cset_zero): Likewise by using cbranch_treg_value
+ predicate.
+ * config/sh/predicates.md (cbranch_treg_value): Simplify.
+
+2014-05-16 Oleg Endo <olegendo@gcc.gnu.org>
+
+ * config/sh/sh.c (sh_option_override): Set branch cost to 2 for all
+ target variants.
+
+2014-05-16 David Malcolm <dmalcolm@redhat.com>
+
+ Revert:
+ 2014-04-29 David Malcolm <dmalcolm@redhat.com>
+
+ * tree-cfg.c (dump_function_to_file): Dump the return type of
+ functions, in a line to itself before the function body, mimicking
+ the layout of a C function.
+
+2014-05-16 Dehao Chen <dehao@google.com>
+
+ * cfghooks.c (make_forwarder_block): Use direct computation to
+ get fall-through edge's count and frequency.
+
+2014-05-16 Benno Schulenberg <bensberg@justemail.net>
+
+ * config/arc/arc.c (arc_init): Fix typo in error message.
+ * config/i386/i386.c (ix86_expand_builtin): Likewise.
+ (split_stack_prologue_scratch_regno): Likewise.
+ * fortran/check.c (gfc_check_fn_rc2008): Remove duplicate
+ word from error message.
+
+2014-05-16 Zhouyi Zhou <yizhouzhou@ict.ac.cn>
+
+ * ira-costs.c: Fix typo in comment.
+
+2014-05-16 David Wohlferd <dw@LimeGreenSocks.com>
+
+ * doc/extend.texi: (Visibility Pragmas) Fix misplaced @xref
+
+2014-05-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * varpool.c (dump_varpool_node): Dump write-only flag.
+ * lto-cgraph.c (lto_output_varpool_node, input_varpool_node): Stream
+ write-only flag.
+ * tree-cfg.c (execute_fixup_cfg): Remove statements setting
+ write-only variables.
+ * ipa.c (process_references): New function.
+ (set_readonly_bit): New function.
+ (set_writeonly_bit): New function.
+ (clear_addressable_bit): New function.
+ (ipa_discover_readonly_nonaddressable_var): Mark write only variables;
+ fix handling of aliases.
+ * cgraph.h (struct varpool_node): Add writeonly flag.
+
+2014-05-16 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/60969
+ * ira-costs.c (record_reg_classes): Allow only memory for pseudo.
+ Calculate costs for this case.
+
+2014-05-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ * fold-const (fold_unary_loc) <NON_LVALUE_EXPR>: New case.
+ <CASE_CONVERT>: Pass arg0 instead of op0 to fold_convert_const.
+
+2014-05-16 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61194
+ * tree-vect-patterns.c (adjust_bool_pattern): Also handle
+ bool patterns ending in a COND_EXPR.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_mult_cost): Fix FNMUL case.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Handle the case
+ where we were unable to cost an RTX.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Cost SYMBOL_REF,
+ HIGH, LO_SUM.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+ Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Cost TRUNCATE.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+ Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Cost FMA,
+ FLOAT_EXTEND, FLOAT_TRUNCATE, ABS, SMAX, and SMIN.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+ Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Cost comparison
+ operators.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+ Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Improve costs for
+ DIV/MOD.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+ Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_arith_op_extract_p): New.
+ (aarch64_rtx_costs): Improve costs for SIGN/ZERO_EXTRACT.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+ Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Improve costs for
+ rotates and shifts.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+ Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Cost
+ ZERO_EXTEND and SIGN_EXTEND better.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+ Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Improve cost for
+ logical operations.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+ Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Use address
+ costs when costing loads and stores to memory.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+ Philip Tomsich <philipp.tomsich@theobroma-systems.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Improve costing
+ for SET RTX.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Set default costs.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+ Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+
+ * config/aarch64/aarch64.c (aarch64_strip_shift_or_extend): Rename
+ to...
+ (aarch64_strip_extend): ...this, don't strip shifts, check RTX is
+ well formed.
+ (aarch64_rtx_mult_cost): New.
+ (aarch64_rtx_costs): Use it, refactor as appropriate.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+ Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+
+ * config/aarch64/aarch64.c (aarch64_build_constant): Conditionally
+ emit instructions, return number of instructions which would
+ be emitted.
+ (aarch64_add_constant): Update call to aarch64_build_constant.
+ (aarch64_output_mi_thunk): Likewise.
+ (aarch64_rtx_costs): Estimate cost of a CONST_INT, cost of
+ a CONST_DOUBLE.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_rtx_costs_wrapper): New.
+ (TARGET_RTX_COSTS): Call it.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64.c (cortexa57_addrcost_table): New.
+ (cortexa57_vector_cost): Likewise.
+ (cortexa57_tunings): Use them.
+
+2014-05-16 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64-protos.h (scale_addr_mode_cost): New.
+ (cpu_addrcost_table): Use it.
+ * config/aarch64/aarch64.c (generic_addrcost_table): Initialize it.
+ (aarch64_address_cost): Rewrite using aarch64_classify_address,
+ move it.
+
+2014-05-16 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c: Include tree-cfg.h and domwalk.h.
+ (set_ssa_val_to): Handle unexpected sets to VN_TOP.
+ (visit_phi): Ignore edges marked as not executable.
+ (class cond_dom_walker): New.
+ (cond_dom_walker::before_dom_children): Value-number
+ control statements and mark successor edges as not
+ executable if possible.
+ (run_scc_vn): First walk all control statements in
+ dominator order, marking edges as not executable.
+ * tree-inline.c (copy_edges_for_bb): Be not confused
+ about random edge flags.
+
+2014-05-16 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (visit_use): Also constant-fold calls.
+
+2014-05-15 Peter Bergner <bergner@vnet.ibm.com>
+
+ PR target/61193
+ * config/rs6000/htmxlintrin.h (_HTM_TBEGIN_STARTED): New define.
+ (__TM_simple_begin): Use it.
+ (__TM_begin): Likewise.
+
+2014-05-15 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/61085
+ * ipa-prop.c (update_indirect_edges_after_inlining): Check
+ type_preserved flag when the indirect edge is polymorphic.
+
+2014-05-15 Martin Jambor <mjambor@suse.cz>
+
+ PR tree-optimization/61090
+ * tree-sra.c (sra_modify_expr): Pass the current gsi to
+ build_ref_for_model.
+
+2014-05-15 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/arm.c (arm_option_override): Use the SCHED_PRESSURE_MODEL
+ enum name for PARAM_SCHED_PRESSURE_ALGORITHM.
+
+2014-05-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/61158
+ * fold-const.c (fold_binary_loc): If X is zero-extended and
+ shiftc >= prec, make sure zerobits is all ones instead of
+ invoking undefined behavior.
+
+2014-05-15 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ * regcprop.h: New file.
+ * regcprop.c (skip_debug_insn_p): New decl.
+ (replace_oldest_value_reg): Check skip_debug_insn_p.
+ (copyprop_hardreg_forward_bb_without_debug_insn): New function.
+ * shrink-wrap.c: Include regcprop.h.
+ (prepare_shrink_wrap): Call
+ copyprop_hardreg_forward_bb_without_debug_insn.
+
+2014-05-15 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ * shrink-wrap.h: Update comment.
+ * shrink-wrap.c: Update comment.
+ (next_block_for_reg): Rename to live_edge_for_reg.
+ (live_edge_for_reg): Allow live_edge->dest has two predecessors.
+ (move_insn_for_shrink_wrap): Split live_edge.
+ (prepre_shrink_wrap): One more parameter for move_insn_for_shrink_wrap.
+
+2014-05-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/sparc/sparc-protos.h (sparc_absnegfloat_split_legitimate):
+ Delete.
+ * config/sparc/sparc.c (sparc_absnegfloat_split_legitimate): Likewise.
+ * config/sparc/sparc.md (fptype_ut699): New attribute.
+ (in_branch_delay): Return false if -mfix-ut699 is specified and
+ fptype_ut699 is set to single.
+ (truncdfsf2): Add fptype_ut699 attribute.
+ (fix_truncdfsi2): Likewise.
+ (floatsisf2): Change fptype attribute.
+ (fix_truncsfsi2): Likewise.
+ (negtf2_notv9): Delete.
+ (negtf2_v9): Likewise.
+ (negtf2_hq): New instruction.
+ (negtf2): New instruction and splitter.
+ (negdf2_notv9): Rewrite.
+ (abstf2_notv9): Delete.
+ (abstf2_hq_v9): Likewise.
+ (abstf2_v9): Likewise.
+ (abstf2_hq): New instruction.
+ (abstf2): New instruction and splitter.
+ (absdf2_notv9): Rewrite.
+
+2014-05-14 Cary Coutant <ccoutant@google.com>
+
+ PR debug/61013
+ * opts.c (common_handle_option): Don't special-case "-g".
+ (set_debug_level): Default to at least level 2 with "-g".
+
+2014-05-14 DJ Delorie <dj@redhat.com>
+
+ * config/msp430/msp430.c (msp430_builtin): Add
+ MSP430_BUILTIN_DELAY_CYCLES.
+ (msp430_init_builtins): Register void __delay_cycles(long long).
+ (msp430_builtin_decl): Add it.
+ (cg_magic_constant): New.
+ (msp430_expand_delay_cycles): New.
+ (msp430_expand_builtin): Call it.
+ (msp430_print_operand_raw): Change integer printing from "int" to
+ HOST_WIDE_INT.
+ * config/msp430/msp430.md (define_constants): Add delay_cycles tags.
+ (delay_cycles_start): New.
+ (delay_cycles_end): New.
+ (delay_cycles_32): New.
+ (delay_cycles_32x): New.
+ (delay_cycles_16): New.
+ (delay_cycles_16x): New.
+ (delay_cycles_2): New.
+ (delay_cycles_1): New.
+ * doc/extend.texi: Document __delay_cycles().
+
+2014-05-14 Sandra Loosemore <sandra@codesourcery.com>
+
+ * config/nios2/nios2.md (nios2_cbranch): Fix paste-o in
+ length attribute computation.
+
+2014-05-14 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR debug/61188
+ * print-rtl.c (print_rtx): Suppress uids if flag_dump_unnumbered.
+
+2014-05-14 Richard Sandiford <r.sandiford@uk.ibm.com>
+
+ PR target/61084
+ * config/sparc/sparc.md: Fix types of low and high in DI constant
+ splitter. Use gen_int_mode in some other splitters.
+
+2014-05-14 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/60897
+ * ipa-prop.c (ipa_modify_formal_parameters): Reset DECL_LANG_SPECIFIC.
+
+2014-05-14 James Norris <jnorris@codesourcery.com>
+
+ * omp-low.c (expand_parallel_call): Remove shadow variable.
+ (expand_omp_taskreg): Likewise.
+
+2014-05-14 Ilya Tocar <ilya.tocar@intel.com>
+
+ * common/config/i386/i386-common.c
+ (OPTION_MASK_ISA_CLFLUSHOPT_SET): Define.
+ (OPTION_MASK_ISA_XSAVES_SET): Ditto.
+ (OPTION_MASK_ISA_XSAVEC_SET): Ditto.
+ (OPTION_MASK_ISA_CLFLUSHOPT_UNSET): Ditto.
+ (OPTION_MASK_ISA_XSAVES_UNSET): Ditto.
+ (OPTION_MASK_ISA_XSAVEC_UNSET): Ditto.
+ (ix86_handle_option): Handle OPT_mxsavec, OPT_mxsaves, OPT_mclflushopt.
+ * config.gcc (i[34567]86-*-*): Add clflushoptintrin.h,
+ xsavecintrin.h, xsavesintrin.h.
+ (x86_64-*-*): Ditto.
+ * config/i386/clflushoptintrin.h: New.
+ * config/i386/xsavecintrin.h: Ditto.
+ * config/i386/xsavesintrin.h: Ditto.
+ * config/i386/cpuid.h (bit_CLFLUSHOPT): Define.
+ (bit_XSAVES): Ditto.
+ (bit_XSAVES): Ditto.
+ * config/i386/driver-i386.c (host_detect_local_cpu): Handle
+ -mclflushopt, -mxsavec, -mxsaves, -mno-xsaves, -mno-xsavec,
+ -mno-clflushopt.
+ * config/i386/i386-c.c (ix86_target_macros_internal): Handle
+ OPTION_MASK_ISA_CLFLUSHOPT, OPTION_MASK_ISA_XSAVEC,
+ OPTION_MASK_ISA_XSAVES.
+ * config/i386/i386.c (ix86_target_string): Handle -mclflushopt,
+ -mxsavec, -mxsaves.
+ (PTA_CLFLUSHOPT) Define.
+ (PTA_XSAVEC): Ditto.
+ (PTA_XSAVES): Ditto.
+ (ix86_option_override_internal): Handle new options.
+ (ix86_valid_target_attribute_inner_p): Ditto.
+ (ix86_builtins): Add IX86_BUILTIN_XSAVEC, IX86_BUILTIN_XSAVEC64,
+ IX86_BUILTIN_XSAVES, IX86_BUILTIN_XRSTORS, IX86_BUILTIN_XSAVES64,
+ IX86_BUILTIN_XRSTORS64, IX86_BUILTIN_CLFLUSHOPT.
+ (bdesc_special_args): Add __builtin_ia32_xsaves,
+ __builtin_ia32_xrstors, __builtin_ia32_xsavec, __builtin_ia32_xsaves64,
+ __builtin_ia32_xrstors64, __builtin_ia32_xsavec64.
+ (ix86_init_mmx_sse_builtins): Add __builtin_ia32_clflushopt.
+ (ix86_expand_builtin): Handle new builtins.
+ * config/i386/i386.h (TARGET_CLFLUSHOPT) Define.
+ (TARGET_CLFLUSHOPT_P): Ditto.
+ (TARGET_XSAVEC): Ditto.
+ (TARGET_XSAVEC_P): Ditto.
+ (TARGET_XSAVES): Ditto.
+ (TARGET_XSAVES_P): Ditto.
+ * config/i386/i386.md (ANY_XSAVE): Add UNSPECV_XSAVEC, UNSPECV_XSAVES.
+ (ANY_XSAVE64)" Add UNSPECV_XSAVEC64, UNSPECV_XSAVES64.
+ (attr xsave): Add xsavec, xsavec64, xsaves, xsaves64.
+ (ANY_XRSTOR): New.
+ (ANY_XRSTOR64): Ditto.
+ (xrstor): Ditto.
+ (xrstor): Change into <xrstor>.
+ (xrstor_rex64): Change into <xrstor>_rex64.
+ (xrstor64): Change into <xrstor>64
+ (clflushopt): New.
+ * config/i386/i386.opt (mclflushopt): New.
+ (mxsavec): Ditto.
+ (mxsaves): Ditto.
+ * config/i386/x86intrin.h: Add clflushoptintrin.h, xsavesintrin.h,
+ xsavecintrin.h.
+ * doc/invoke.texi: Document new options.
+
+2014-05-14 Andrey Belevantsev <abel@ispras.ru>
+
+ PR rtl-optimization/60866
+ * sel-sched-ir (sel_init_new_insn): New parameter old_seqno.
+ Default it to -1. Pass it down to init_simplejump_data.
+ (init_simplejump_data): New parameter old_seqno. Pass it down
+ to get_seqno_for_a_jump.
+ (get_seqno_for_a_jump): New parameter old_seqno. Use it for
+ initializing new jump seqno as a last resort. Add comment.
+ (sel_redirect_edge_and_branch): Save old seqno of the conditional
+ jump and pass it down to sel_init_new_insn.
+ (sel_redirect_edge_and_branch_force): Likewise.
+
+2014-05-14 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.h (REG_CLASS_CONTENTS): Use unsigned suffix for
+ shifted values to avoid build warning.
+
+2014-05-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * cfgcleanup.c (try_forward_edges): Use location_t for locations.
+ * cfgrtl.c (rtl_merge_blocks): Fix comment.
+ (cfg_layout_merge_blocks): Likewise.
+ * except.c (emit_to_new_bb_before): Remove prev_bb local variable.
+
+2014-05-14 Andrey Belevantsev <abel@ispras.ru>
+
+ PR rtl-optimization/60901
+ * config/i386/i386.c (ix86_dependencies_evaluation_hook): Check that
+ bb predecessor belongs to the same scheduling region. Adjust comment.
+
+2014-05-13 Peter Bergner <bergner@vnet.ibm.com>
+
+ * doc/sourcebuild.texi: (dfp_hw): Document.
+ (p8vector_hw): Likewise.
+ (powerpc_eabi_ok): Likewise.
+ (powerpc_elfv2): Likewise.
+ (powerpc_htm_ok): Likewise.
+ (ppc_recip_hw): Likewise.
+ (vsx_hw): Likewise.
+
+2014-05-13 Cary Coutant <ccoutant@google.com>
+
+ * opts.c (finish_options): Use -ggnu-pubnames with -gsplit-dwarf.
+
+2014-05-13 David Malcolm <dmalcolm@redhat.com>
+
+ * gengtype-parse.c (require3): Eliminate in favor of...
+ (require4): New.
+ (require_template_declaration): Update to support optional single *
+ on a type.
+
+ * gengtype.c (get_ultimate_base_class): Add a non-const overload.
+ (create_user_defined_type): Handle a single level of explicit
+ pointerness within template arguments.
+ (struct write_types_data): Add field "kind".
+ (filter_type_name): Handle "*" character.
+ (write_user_func_for_structure_ptr): Require a write_types_data
+ rather than just a prefix string, so that we can look up the kind
+ of the wtd and use it as an index into wrote_user_func_for_ptr,
+ ensuring that such functions are written at most once. Support
+ subclasses by invoking the marking function of the ultimate base class.
+ (write_user_func_for_structure_body): Require a write_types_data
+ rather than just a prefix string, so that we can pass this to
+ write_user_func_for_structure_ptr.
+ (write_func_for_structure): Likewise.
+ (ggc_wtd): Add initializer of new "kind" field.
+ (pch_wtd): Likewise.
+
+ * gengtype.h (enum write_types_kinds): New.
+ (struct type): Add field wrote_user_func_for_ptr to the "s"
+ union member.
+
+2014-05-13 Richard Sandiford <r.sandiford@uk.ibm.com>
+
+ * fold-const.c (optimize_bit_field_compare): Use wi:: operations
+ instead of const_binop.
+ (fold_binary_loc): Likewise.
+
+2014-05-13 Richard Sandiford <r.sandiford@uk.ibm.com>
+
+ * tree-dfa.h (get_addr_base_and_unit_offset_1): Update array index
+ calculation to match get_ref_base_and_extent.
+
+2014-05-13 Catherine Moore <clm@codesourcery.com>
+ Sandra Loosemore <sandra@codesourcery.com>
+
+ * configure.ac: Fix assembly for explicit JALR relocation check.
+ * configure: Regenerate.
+
+2014-05-13 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/arm.c (neon_itype): Remove NEON_RESULTPAIR.
+ (arm_init_neon_builtins): Remove handling of NEON_RESULTPAIR.
+ Remove associated type declarations and initialisations.
+ (arm_expand_neon_builtin): Likewise.
+ (neon_emit_pair_result_insn): Delete.
+ * config/arm/arm_neon_builtins (vtrn, vzip, vuzp): Delete.
+ * config/arm/neon.md (neon_vtrn<mode>): Delete.
+ (neon_vzip<mode>): Likewise.
+ (neon_vuzp<mode>): Likewise.
+
+2014-05-13 Richard Biener <rguenther@suse.de>
+
+ PR ipa/60973
+ * tree-inline.c (remap_gimple_stmt): Clear tail call flag,
+ it needs revisiting whether the call still may be tail-called.
+
+2014-05-13 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * rtl.def (SYMBOL_REF): Remove middle "0" field.
+ * rtl.h (block_symbol): Reduce number of fields to 2.
+ (rtx_def): Add u2.symbol_ref_flags.
+ (SYMBOL_REF_FLAGS): Use it.
+ (SYMBOL_REF_DATA, SET_SYMBOL_REF_DECL, SYMBOL_REF_DECL)
+ (SET_SYMBOL_REF_CONSTANT, SYMBOL_REF_CONSTANT): Lower index.
+ * gengtype.c (adjust_field_rtx_def): Remove SYMBOL_REF_FLAGS handling.
+ Lower index of SYMBOL_REF_DATA.
+ * print-rtl.c (print_rtx): Lower index for SYMBOL_REF_DATA.
+ Print SYMBOL_REF_FLAGS at the same time.
+ * genattrtab.c (attr_rtx_1): Only initialize 1 "0" SYMBOL_REF field.
+
+2014-05-13 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * rtl.def (VAR_LOCATION): Remove "i" field.
+ * rtl.h (rtx_def): Add u2.var_location_status.
+ (PAT_VAR_LOCATION_STATUS): Use it.
+ (gen_rtx_VAR_LOCATION): Declare.
+ * gengenrtl.c (excluded_rtx): Add VAR_LOCATION.
+ * emit-rtl.c (gen_rtx_VAR_LOCATION): New function.
+ * var-tracking.c (emit_note_insn_var_location): Remove casts.
+
+2014-05-13 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * rtl.def (scratch): Fix outdated comment and remove "0" field.
+ * gengtype.c (adjust_field_rtx_def): Update accordingly.
+
+2014-05-13 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * rtl.def (DEBUG_INSN, INSN, JUMP_INSN, CALL_INSN, JUMP_TABLE_DATA)
+ (BARRIER, CODE_LABEL, NOTE): Remove first "i" field.
+ * rtl.h (rtx_def): Add insn_uid to u2 field.
+ (RTX_FLAG_CHECK8): Delete in favor of...
+ (RTL_INSN_CHAIN_FLAG_CHECK): ...this new macro.
+ (INSN_DELETED_P): Update accordingly.
+ (INSN_UID): Use u2.insn_uid.
+ (INSN_CHAIN_CODE_P): Define.
+ (PREV_INSN, NEXT_INSN, BLOCK_FOR_INSN, PATTERN, INSN_LOCATION)
+ (INSN_CODE, REG_NOTES, CALL_INSN_FUNCTION_USAGE, CODE_LABEL_NUMBER)
+ (NOTE_DATA, NOTE_DELETED_LABEL_NAME, NOTE_BLOCK, NOTE_EH_HANDLER)
+ (NOTE_BASIC_BLOCK, NOTE_VAR_LOCATION, NOTE_CFI, NOTE_LABEL_NUMBER)
+ (NOTE_KIND, LABEL_NAME, LABEL_NUSES, JUMP_LABEL, LABEL_REFS): Lower
+ indices accordingly.
+ * print-rtl.c (print_rtx): Print INSN_UIDs before the main loop.
+ Update indices for insn-chain rtxes.
+ * gengtype.c (gen_rtx_next): Adjust test for insn-chain rtxes.
+ (adjust_field_rtx_def): Lower '0' indices for all insn-chain rtxes.
+ * emit-rtl.c (gen_label_rtx): Update gen_rtx_LABEL call.
+ * caller-save.c (init_caller_save): Update gen_rtx_INSN calls.
+ * combine.c (try_combine): Likewise.
+ * ira.c (setup_prohibited_mode_move_regs): Likewise.
+
+2014-05-13 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * rtl.def (REG): Remove middle field.
+ * rtl.h (rtx_def): Add orignal_regno to u2.
+ (ORIGINAL_REGNO): Use it instead of field 1.
+ (REG_ATTRS): Lower field index accordingly.
+ * gengtype.c (adjust_field_rtx_def): Remove handling of
+ ORIGINAL_REGNO. Move REG_ATTRS index down.
+ * print-rtl.c (print_rtx): Move ORIGINAL_REGNO handling to the
+ code that prints the REGNO.
+
+2014-05-13 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * print-rtl.c (print_rtx): Guard whole '0' block with ifndef
+ GENERATOR_FILE.
+
+2014-05-13 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * rtl.h (rtx_def): Mark u2 as GTY ((skip)).
+
+2014-05-13 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-ssa-loop-ivopts.c (contain_complex_addr_expr): New.
+ (alloc_iv): Lower base expressions containing ADDR_EXPR.
+
+2014-05-13 Ian Bolton <ian.bolton@arm.com>
+
+ * config/aarch64/aarch64-protos.h
+ (aarch64_hard_regno_caller_save_mode): New prototype.
+ * config/aarch64/aarch64.c (aarch64_hard_regno_caller_save_mode):
+ New function.
+ * config/aarch64/aarch64.h (HARD_REGNO_CALLER_SAVE_MODE): New macro.
+
+2014-05-13 Christian Bruel <christian.bruel@st.com>
+
+ * target.def (mode_switching): New hook vector.
+ (mode_emit, mode_needed, mode_after, mode_entry): New hooks.
+ (mode_exit, modepriority_to_mode): Likewise.
+ * mode-switching.c (MODE_NEEDED, MODE_AFTER, MODE_ENTRY): Hookify.
+ (MODE_EXIT, MODE_PRIORITY_TO_MODE, EMIT_MODE_SET): Likewise.
+ * target.h: Include tm.h and hard-reg-set.h.
+ * doc/tm.texi.in (EMIT_MODE_SET, MODE_NEEDED, MODE_AFTER, MODE_ENTRY)
+ (MODE_EXIT, MODE_PRIORITY_TO_MODE): Delete and hookify.
+ * doc/tm.texi Regenerate.
+ * config/sh/sh.h (MODE_NEEDED, MODE_AFTER, MODE_ENTRY): Delete
+ (MODE_EXIT, MODE_PRIORITY_TO_MODE, EMIT_MODE_SET): Likewise.
+ * config/sh/sh.c (sh_emit_mode_set, sh_mode_priority): Hookify.
+ (sh_mode_needed, sh_mode_after, sh_mode_entry, sh_mode_exit): Likewise.
+ * config/i386/i386.h (MODE_NEEDED, MODE_AFTER, MODE_ENTRY): Delete
+ (MODE_EXIT, MODE_PRIORITY_TO_MODE, EMIT_MODE_SET): Likewise.
+ * config/i386/i386-protos.h (ix86_mode_needed, ix86_mode_after)
+ (ix86_mode_entrym, ix86_emit_mode_set): Remove external declaration.
+ * config/i386/i386.c (ix86_mode_needed, ix86_mode_after,
+ (ix86_mode_exit, ix86_mode_entry, ix86_mode_priority)
+ (ix86_emit_mode_set): Hookify.
+ * config/epiphany/epiphany.h (MODE_NEEDED, MODE_AFTER, MODE_ENTRY):
+ Delete.
+ (MODE_EXIT, MODE_PRIORITY_TO_MODE, EMIT_MODE_SET): Likewise.
+ * config/epiphany/epiphany-protos.h (epiphany_mode_needed)
+ (emit_set_fp_mode, epiphany_mode_entry_exit, epiphany_mode_after)
+ (epiphany_mode_priority_to_mode): Remove declaration.
+ * config/epiphany/epiphany.c (emit_set_fp_mode): Hookify.
+ (epiphany_mode_needed, epiphany_mode_priority_to_mode): Likewise.
+ (epiphany_mode_entry, epiphany_mode_exit, epiphany_mode_after):
+ Likewise.
+ (epiphany_mode_priority_to_mode): Change priority type. Hookify.
+ (epiphany_mode_needed, epiphany_mode_entry_exit): Hookify.
+ (epiphany_mode_after, epiphany_mode_entry, emit_set_fp_mode): Hookify.
+
+2014-05-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/61060
+ * config/i386/i386.c (ix86_expand_set_or_movmem): If count_exp
+ is const0_rtx, return immediately. Don't test count == 0 when
+ it is always true.
+
+2014-05-13 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ * Makefile.in: add shrink-wrap.o.
+ * config/i386/i386.c: include "shrink-wrap.h"
+ * function.c: Likewise.
+ (requires_stack_frame_p, next_block_for_reg,
+ move_insn_for_shrink_wrap, prepare_shrink_wrap,
+ dup_block_and_redirect): Move to shrink-wrap.c
+ (thread_prologue_and_epilogue_insns): Extract three code segments
+ as functions in shrink-wrap.c
+ * function.h: Move #ifdef HAVE_simple_return ... #endif block to
+ shrink-wrap.h
+ * shrink-wrap.c: New file.
+ * shrink-wrap.h: New file.
+
+2014-05-12 David Wohlferd <dw@LimeGreenSocks.com>
+
+ * doc/extend.texi: Reflect current numbers of pragmas. Remove
+ reference to Solaris.
+
+2014-05-12 Mike Stump <mikestump@comcast.net>
+
+ PR other/31778
+ * genattrtab.c (filename): Add.
+ (convert_set_attr_alternative): Improve error message.
+ (check_defs): Restore read_md_filename for error messages.
+ (gen_insn): Save filename.
+
+2014-05-12 Dimitris Papavasiliou <dpapavas@gmail.com>
+
+ * doc/invoke.texi: Document new switches -Wno-shadow-ivar,
+ -fno-local-ivars and -fivar-visibility.
+ * c-family/c.opt: Make -Wshadow also implicitly enable
+ -Wshadow-ivar.
+
+2014-05-12 David Wohlferd <dw@LimeGreenSocks.com>
+
+ * doc/tm.texi: Remove reference to deleted macro.
+ * doc/tm.texi.in: Likewise.
+
+2014-05-12 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
+
+ PR target/60991
+ * config/avr/avr.c (avr_out_store_psi): Use correct constant
+ to restore Y.
+
+2014-05-12 Georg-Johann Lay <avr@gjlay.de>
+
+ PR libgcc/61152
+ * config/arm/arm.h (License): Add GCC Runtime Library Exception.
+ * config/arm/aout.h (License): Same.
+ * config/arm/bpabi.h (License): Same.
+ * config/arm/elf.h (License): Same.
+ * config/arm/linux-elf.h (License): Same.
+ * config/arm/linux-gas.h (License): Same.
+ * config/arm/netbsd-elf.h (License): Same.
+ * config/arm/uclinux-eabi.h (License): Same.
+ * config/arm/uclinux-elf.h (License): Same.
+ * config/arm/vxworks.h (License): Same.
+
+2014-05-11 Jakub Jelinek <jakub@redhat.com>
+
+ * tree.h (OMP_CLAUSE_LINEAR_STMT): Define.
+ * tree.c (omp_clause_num_ops): Increase OMP_CLAUSE_LINEAR
+ number of operands to 3.
+ (walk_tree_1): Walk all operands of OMP_CLAUSE_LINEAR.
+ * tree-nested.c (convert_nonlocal_omp_clauses,
+ convert_local_omp_clauses): Handle OMP_CLAUSE_DEPEND.
+ * gimplify.c (gimplify_scan_omp_clauses): Handle
+ OMP_CLAUSE_LINEAR_STMT.
+ * omp-low.c (lower_rec_input_clauses): Fix typo.
+ (maybe_add_implicit_barrier_cancel, lower_omp_1): Add
+ cast between Fortran boolean_type_node and C _Bool if
+ needed.
+
+2014-05-11 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR tree-optimization/61136
+ * wide-int.h (multiple_of_p): Define a version that doesn't return
+ the quotient.
+ * fold-const.c (extract_muldiv_1): Use wi::multiple_of_p instead of an
+ integer_zerop/const_binop pair.
+ (multiple_of_p): Likewise, converting both operands to widest_int
+ precision.
+
+2014-05-09 Teresa Johnson <tejohnson@google.com>
+
+ * cgraphunit.c (analyze_functions): Use correct dump file.
+
+2014-05-09 Florian Weimer <fweimer@redhat.com>
+
+ * cfgexpand.c (stack_protect_decl_p): New function, extracted from
+ expand_used_vars.
+ (stack_protect_return_slot_p): New function.
+ (expand_used_vars): Call stack_protect_decl_p and
+ stack_protect_return_slot_p for -fstack-protector-strong.
+
+2014-05-09 David Wohlferd <LimeGreenSocks@yahoo.com>
+ Andrew Haley <aph@redhat.com>
+ Richard Sandiford <rdsandiford@googlemail.com>
+
+ * doc/extend.texi: Rewrite inline asm page / re-org asm-related
+ pages.
+
+2014-05-09 Kenneth Zadeck <zadeck@naturalbridge.com>
+
+ PR middle-end/61111
+ * fold-const.c (fold_binary_loc): Changed width of mask.
+
+2014-05-09 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr-fixed.md (round<mode>3): Use -1U instead of -1 in
+ unsigned int initializers for regno_in, regno_out.
+
+2014-05-09 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/61055
+ * config/avr/avr.md (cc): Add new attribute set_vzn.
+ (addqi3, addqq3, adduqq3, subqi3, subqq3, subuqq3, negqi2) [cc]:
+ Set cc insn attribute to set_vzn instead of set_zn for alternatives
+ with INC, DEC or NEG.
+ * config/avr/avr.c (avr_notice_update_cc): Handle SET_VZN.
+ (avr_out_plus_1): ADIW sets cc0 to CC_SET_CZN.
+ INC, DEC and ADD+ADC set cc0 to CC_CLOBBER.
+
+2014-05-09 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ Revert:
+ 2014-05-08 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ * wide-int.cc (UTItype): Define.
+ (UDWtype): Define for appropriate W_TYPE_SIZE.
+
+2014-05-09 Richard Biener <rguenther@suse.de>
+
+ * Makefile.in (GTFILES): Remove tree-ssa-propagate.c.
+ * tree-ssa-propagate.c: Do not include gt-tree-ssa-propagate.h.
+ (interesting_ssa_edges, varying_ssa_edges): Move out of GC space.
+ (add_ssa_edge, process_ssa_edge_worklist, ssa_prop_init,
+ ssa_propagate): Adjust.
+
+2014-05-08 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/61009
+ * tree-ssa-threadedge.c (thread_through_normal_block): Return a
+ tri-state rather than a boolean. When a block is too big to
+ thread through, inform caller via negative return value.
+ (thread_across_edge): If a block was too big for normal threading,
+ then it's too big for a joiner too, so remove temporary equivalences
+ and return immediately.
+
+2014-05-08 Manuel López-Ibáñez <manu@gcc.gnu.org>
+ Matthias Klose <doko@ubuntu.com>
+
+ PR driver/61106
+ * optc-gen.awk: Fix option handling for -Wunused-parameter.
+
+2014-05-08 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/59952
+ * config/i386/i386.c (PTA_HASWELL): Remove PTA_RTM.
+
+2014-05-08 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/61092
+ * config/alpha/alpha.c: Include gimple-iterator.h.
+ (alpha_gimple_fold_builtin): New function. Move
+ ALPHA_BUILTIN_UMULH folding from ...
+ (alpha_fold_builtin): ... here.
+ (TARGET_GIMPLE_FOLD_BUILTIN): New define.
+
+2014-05-08 Wei Mi <wmi@google.com>
+
+ PR target/58066
+ * config/i386/i386.c (ix86_compute_frame_layout): Update
+ preferred_stack_boundary for call, expanded from tls descriptor.
+ * config/i386/i386.md (*tls_global_dynamic_32_gnu): Update RTX
+ to depend on SP register.
+ (*tls_local_dynamic_base_32_gnu): Ditto.
+ (*tls_local_dynamic_32_once): Ditto.
+ (tls_global_dynamic_64_<mode>): Set
+ ix86_tls_descriptor_calls_expanded_in_cfun.
+ (tls_local_dynamic_base_64_<mode>): Ditto.
+ (tls_global_dynamic_32): Set
+ ix86_tls_descriptor_calls_expanded_in_cfun. Update RTX
+ to depend on SP register.
+ (tls_local_dynamic_base_32): Ditto.
+
+2014-05-08 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ * config/arm/arm_neon.h: Update comment.
+ * config/arm/neon-docgen.ml: Delete.
+ * config/arm/neon-gen.ml: Delete.
+ * doc/arm-neon-intrinsics.texi: Update comment.
+
+2014-05-08 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ * config/arm/arm_neon_builtins.def (vadd, vsub): Only define the v2sf
+ and v4sf versions.
+ (vand, vorr, veor, vorn, vbic): Remove.
+ * config/arm/neon.md (neon_vadd, neon_vsub, neon_vadd_unspec): Adjust
+ iterator.
+ (neon_vsub_unspec): Likewise.
+ (neon_vorr, neon_vand, neon_vbic, neon_veor, neon_vorn): Remove.
+
+2014-05-08 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ * config/arm/arm_neon.h (vadd_s8): GNU C implementation
+ (vadd_s16): Likewise.
+ (vadd_s32): Likewise.
+ (vadd_f32): Likewise.
+ (vadd_u8): Likewise.
+ (vadd_u16): Likewise.
+ (vadd_u32): Likewise.
+ (vadd_s64): Likewise.
+ (vadd_u64): Likewise.
+ (vaddq_s8): Likewise.
+ (vaddq_s16): Likewise.
+ (vaddq_s32): Likewise.
+ (vaddq_s64): Likewise.
+ (vaddq_f32): Likewise.
+ (vaddq_u8): Likewise.
+ (vaddq_u16): Likewise.
+ (vaddq_u32): Likewise.
+ (vaddq_u64): Likewise.
+ (vmul_s8): Likewise.
+ (vmul_s16): Likewise.
+ (vmul_s32): Likewise.
+ (vmul_f32): Likewise.
+ (vmul_u8): Likewise.
+ (vmul_u16): Likewise.
+ (vmul_u32): Likewise.
+ (vmul_p8): Likewise.
+ (vmulq_s8): Likewise.
+ (vmulq_s16): Likewise.
+ (vmulq_s32): Likewise.
+ (vmulq_f32): Likewise.
+ (vmulq_u8): Likewise.
+ (vmulq_u16): Likewise.
+ (vmulq_u32): Likewise.
+ (vsub_s8): Likewise.
+ (vsub_s16): Likewise.
+ (vsub_s32): Likewise.
+ (vsub_f32): Likewise.
+ (vsub_u8): Likewise.
+ (vsub_u16): Likewise.
+ (vsub_u32): Likewise.
+ (vsub_s64): Likewise.
+ (vsub_u64): Likewise.
+ (vsubq_s8): Likewise.
+ (vsubq_s16): Likewise.
+ (vsubq_s32): Likewise.
+ (vsubq_s64): Likewise.
+ (vsubq_f32): Likewise.
+ (vsubq_u8): Likewise.
+ (vsubq_u16): Likewise.
+ (vsubq_u32): Likewise.
+ (vsubq_u64): Likewise.
+ (vand_s8): Likewise.
+ (vand_s16): Likewise.
+ (vand_s32): Likewise.
+ (vand_u8): Likewise.
+ (vand_u16): Likewise.
+ (vand_u32): Likewise.
+ (vand_s64): Likewise.
+ (vand_u64): Likewise.
+ (vandq_s8): Likewise.
+ (vandq_s16): Likewise.
+ (vandq_s32): Likewise.
+ (vandq_s64): Likewise.
+ (vandq_u8): Likewise.
+ (vandq_u16): Likewise.
+ (vandq_u32): Likewise.
+ (vandq_u64): Likewise.
+ (vorr_s8): Likewise.
+ (vorr_s16): Likewise.
+ (vorr_s32): Likewise.
+ (vorr_u8): Likewise.
+ (vorr_u16): Likewise.
+ (vorr_u32): Likewise.
+ (vorr_s64): Likewise.
+ (vorr_u64): Likewise.
+ (vorrq_s8): Likewise.
+ (vorrq_s16): Likewise.
+ (vorrq_s32): Likewise.
+ (vorrq_s64): Likewise.
+ (vorrq_u8): Likewise.
+ (vorrq_u16): Likewise.
+ (vorrq_u32): Likewise.
+ (vorrq_u64): Likewise.
+ (veor_s8): Likewise.
+ (veor_s16): Likewise.
+ (veor_s32): Likewise.
+ (veor_u8): Likewise.
+ (veor_u16): Likewise.
+ (veor_u32): Likewise.
+ (veor_s64): Likewise.
+ (veor_u64): Likewise.
+ (veorq_s8): Likewise.
+ (veorq_s16): Likewise.
+ (veorq_s32): Likewise.
+ (veorq_s64): Likewise.
+ (veorq_u8): Likewise.
+ (veorq_u16): Likewise.
+ (veorq_u32): Likewise.
+ (veorq_u64): Likewise.
+ (vbic_s8): Likewise.
+ (vbic_s16): Likewise.
+ (vbic_s32): Likewise.
+ (vbic_u8): Likewise.
+ (vbic_u16): Likewise.
+ (vbic_u32): Likewise.
+ (vbic_s64): Likewise.
+ (vbic_u64): Likewise.
+ (vbicq_s8): Likewise.
+ (vbicq_s16): Likewise.
+ (vbicq_s32): Likewise.
+ (vbicq_s64): Likewise.
+ (vbicq_u8): Likewise.
+ (vbicq_u16): Likewise.
+ (vbicq_u32): Likewise.
+ (vbicq_u64): Likewise.
+ (vorn_s8): Likewise.
+ (vorn_s16): Likewise.
+ (vorn_s32): Likewise.
+ (vorn_u8): Likewise.
+ (vorn_u16): Likewise.
+ (vorn_u32): Likewise.
+ (vorn_s64): Likewise.
+ (vorn_u64): Likewise.
+ (vornq_s8): Likewise.
+ (vornq_s16): Likewise.
+ (vornq_s32): Likewise.
+ (vornq_s64): Likewise.
+ (vornq_u8): Likewise.
+ (vornq_u16): Likewise.
+ (vornq_u32): Likewise.
+ (vornq_u64): Likewise.
+
+2014-05-08 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ * wide-int.cc (UTItype): Define.
+ (UDWtype): Define for appropriate W_TYPE_SIZE.
+
+2014-05-08 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/59100
+ * tree-ssa-phiopt.c: Include tree-inline.h.
+ (neutral_element_p, absorbing_element_p): New functions.
+ (value_replacement): Handle conditional binary operations with a
+ neutral or absorbing element.
+
+2014-05-08 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (vn_get_expr_for): Valueize operands before
+ folding the expression.
+ (valueize_expr): Remove.
+ (visit_reference_op_load): Do not valueize the result of
+ vn_get_expr_for.
+ (simplify_binary_expression): Likewise.
+ (simplify_unary_expression): Likewise.
+
+2014-05-08 Richard Biener <rguenther@suse.de>
+
+ * gimplify.c (gimplify_call_expr): Use saved fnptrtype for
+ looking at TYPE_ARG_TYPES.
+
+2014-05-08 Richard Biener <rguenther@suse.de>
+
+ * gimple-fold.c (gimple_fold_stmt_to_constant_1): Remove
+ pointer propagation special-case.
+
+2014-05-08 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-affine.c (tree_to_aff_combination): Handle MEM_REF for
+ core part of address expressions.
+
+2014-05-08 Alan Modra <amodra@gmail.com>
+
+ PR target/60737
+ * config/rs6000/rs6000.c (expand_block_move): Allow 64-bit
+ loads and stores when -mno-strict-align at any alignment.
+ (expand_block_clear): Similarly. Also correct calculation of
+ instruction count.
+
+2014-05-07 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ PR middle-end/39246
+ * tree-complex.c (expand_complex_move): Keep line info when expanding
+ complex move.
+ * tree-ssa-uninit.c (warn_uninit): New argument. Ignore assignment
+ of complex expression. Use new argument to display correct location
+ for values coming from phi statement.
+ (warn_uninitialized_vars): Adapt to new signature of warn_uninit.
+ (warn_uninitialized_phi): Pass location of phi argument to
+ warn_uninit.
+ * tree-ssa.c (ssa_undefined_value_p): For SSA_NAME initialized by a
+ COMPLEX_EXPR, recurse on each part of the COMPLEX_EXPR.
+
+2014-05-07 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/predicates.md (indexed_address_mem): New.
+ * config/rs6000/rs6000.md (type): Remove load_ext, load_ext_u,
+ load_ext_ux, load_ux, load_u, store_ux, store_u, fpload_ux, fpload_u,
+ fpstore_ux, fpstore_u.
+ (sign_extend, indexed, update): New.
+ (cell_micro): Adjust.
+ (*zero_extend<mode>di2_internal1, *zero_extendsidi2_lfiwzx,
+ *extendsidi2_lfiwax, *extendsidi2_nocell, *extendsfdf2_fpr,
+ *movsi_internal1, *movsi_internal1_single, *movhi_internal,
+ *movqi_internal, *movcc_internal1, mov<mode>_hardfloat,
+ *mov<mode>_softfloat, *mov<mode>_hardfloat32, *mov<mode>_hardfloat64,
+ *mov<mode>_softfloat64, *movdi_internal32, *movdi_internal64,
+ *mov<mode>_string, *ldmsi8, *ldmsi7, *ldmsi6, *ldmsi5, *ldmsi4,
+ *ldmsi3, *stmsi8, *stmsi7, *stmsi6, *stmsi5, *stmsi4, *stmsi3,
+ *movdi_update1, movdi_<mode>_update, movdi_<mode>_update_stack,
+ *movsi_update1, *movsi_update2, movsi_update, movsi_update_stack,
+ *movhi_update1, *movhi_update2, *movhi_update3, *movhi_update4,
+ *movqi_update1, *movqi_update2, *movqi_update3, *movsf_update1,
+ *movsf_update2, *movsf_update3, *movsf_update4, *movdf_update1,
+ *movdf_update2, load_toc_aix_si, load_toc_aix_di, probe_stack_<mode>,
+ *stmw, *lmw, as well as 10 anonymous patterns): Adjust.
+
+ * config/rs6000/dfp.md (movsd_store, movsd_load): Adjust.
+ * config/rs6000/vsx.md (*vsx_movti_32bit, *vsx_extract_<mode>_load,
+ *vsx_extract_<mode>_store): Adjust.
+ * config/rs6000/rs6000.c (rs6000_adjust_cost, is_microcoded_insn,
+ is_cracked_insn, insn_must_be_first_in_group,
+ insn_must_be_last_in_group): Adjust.
+
+ * config/rs6000/40x.md (ppc403-load, ppc403-store, ppc405-float):
+ Adjust.
+ * config/rs6000/440.md (ppc440-load, ppc440-store, ppc440-fpload,
+ ppc440-fpstore): Adjust.
+ * config/rs6000/476.md (ppc476-load, ppc476-store, ppc476-fpload,
+ ppc476-fpstore): Adjust.
+ * config/rs6000/601.md (ppc601-load, ppc601-store, ppc601-fpload,
+ ppc601-fpstore): Adjust.
+ * config/rs6000/603.md (ppc603-load, ppc603-store, ppc603-fpload):
+ Adjust.
+ * config/rs6000/6xx.md (ppc604-load, ppc604-store, ppc604-fpload):
+ Adjust.
+ * config/rs6000/7450.md (ppc7450-load, ppc7450-store, ppc7450-fpload,
+ ppc7450-fpstore): Adjust.
+ * config/rs6000/7xx.md (ppc750-load, ppc750-store): Adjust.
+ * config/rs6000/8540.md (ppc8540_load, ppc8540_store): Adjust.
+ * config/rs6000/a2.md (ppca2-load, ppca2-fp-load, ppca2-fp-store):
+ Adjust.
+ * config/rs6000/cell.md (cell-load, cell-load-ux, cell-load-ext,
+ cell-fpload, cell-fpload-update, cell-store, cell-store-update,
+ cell-fpstore, cell-fpstore-update): Adjust.
+ * config/rs6000/e300c2c3.md (ppce300c3_load, ppce300c3_fpload,
+ ppce300c3_store, ppce300c3_fpstore): Adjust.
+ * config/rs6000/e500mc.md (e500mc_load, e500mc_fpload, e500mc_store,
+ e500mc_fpstore): Adjust.
+ * config/rs6000/e500mc64.md (e500mc64_load, e500mc64_fpload,
+ e500mc64_store, e500mc64_fpstore): Adjust.
+ * config/rs6000/e5500.md (e5500_load, e5500_fpload, e5500_store,
+ e5500_fpstore): Adjust.
+ * config/rs6000/e6500.md (e6500_load, e6500_fpload, e6500_store,
+ e6500_fpstore): Adjust.
+ * config/rs6000/mpc.md (mpccore-load, mpccore-store, mpccore-fpload):
+ Adjust.
+ * config/rs6000/power4.md (power4-load, power4-load-ext,
+ power4-load-ext-update, power4-load-ext-update-indexed,
+ power4-load-update-indexed, power4-load-update, power4-fpload,
+ power4-fpload-update, power4-store, power4-store-update,
+ power4-store-update-indexed, power4-fpstore, power4-fpstore-update):
+ Adjust.
+ * config/rs6000/power5.md (power5-load, power5-load-ext,
+ power5-load-ext-update, power5-load-ext-update-indexed,
+ power5-load-update-indexed, power5-load-update, power5-fpload,
+ power5-fpload-update, power5-store, power5-store-update,
+ power5-store-update-indexed, power5-fpstore, power5-fpstore-update):
+ Adjust.
+ * config/rs6000/power6.md (power6-load, power6-load-ext,
+ power6-load-update, power6-load-update-indexed,
+ power6-load-ext-update, power6-load-ext-update-indexed, power6-fpload,
+ power6-fpload-update, power6-store, power6-store-update,
+ power6-store-update-indexed, power6-fpstore, power6-fpstore-update):
+ Adjust.
+ * config/rs6000/power7.md (power7-load, power7-load-ext,
+ power7-load-update, power7-load-update-indexed,
+ power7-load-ext-update, power7-load-ext-update-indexed, power7-fpload,
+ power7-fpload-update, power7-store, power7-store-update,
+ power7-store-update-indexed, power7-fpstore, power7-fpstore-update):
+ Adjust.
+ * config/rs6000/power8.md (power8-load, power8-load-update,
+ power8-load-ext, power8-load-ext-update, power8-fpload,
+ power8-fpload-update, power8-store, power8-store-update-indexed,
+ power8-fpstore, power8-fpstore-update): Adjust.
+ * config/rs6000/rs64.md (rs64a-load, rs64a-store, rs64a-fpload):
+ Adjust.
+ * config/rs6000/titan.md (titan_lsu_load, titan_lsu_fpload,
+ titan_lsu_store, titan_lsu_fpstore): Adjust.
+ * config/rs6000/xfpu.md (fp-load, fp-store): Adjust.
+
+2014-05-07 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/60884
+ * config/sh/sh-mem.cc (sh_expand_strlen): Use loop when emitting
+ unrolled byte insns. Emit address increments after move insns.
+
+2014-05-07 David Malcolm <dmalcolm@redhat.com>
+
+ * gimple.h (gimple_builtin_call_types_compatible_p): Accept a
+ const_gimple, rather than a gimple.
+ (gimple_call_builtin_p): Likewise, for the three variants.
+
+ * gimple.c (gimple_builtin_call_types_compatible_p): Likewise.
+ (gimple_call_builtin_p): Likewise, for the three variants.
+
+2014-05-07 Richard Sandiford <rsandifo@linux.vnet.ibm.com>
+
+ PR tree-optimization/61095
+ * tree-ssanames.c (get_nonzero_bits): Fix type extension in wi::shwi.
+
2014-05-07 Richard Biener <rguenther@suse.de>
PR tree-optimization/61034
@@ -5,16 +3399,13 @@
(maybe_skip_until): Use translate to take into account
lattices when trying to do disambiguations.
(get_continuation_for_phi_1): Likewise.
- (get_continuation_for_phi): Adjust for added translate
- arguments.
+ (get_continuation_for_phi): Adjust for added translate arguments.
(walk_non_aliased_vuses): Likewise.
- * tree-ssa-alias.h (get_continuation_for_phi): Adjust
- prototype.
+ * tree-ssa-alias.h (get_continuation_for_phi): Adjust prototype.
(walk_non_aliased_vuses): Likewise.
(call_may_clobber_ref_p_1): Declare.
- * tree-ssa-sccvn.c (vn_reference_lookup_3): Also
- disambiguate against calls. Stop early if we are
- only supposed to disambiguate.
+ * tree-ssa-sccvn.c (vn_reference_lookup_3): Also disambiguate against
+ calls. Stop early if we are only supposed to disambiguate.
* tree-ssa-pre.c (translate_vuse_through_block): Adjust.
2014-05-07 Joern Rennecke <joern.rennecke@embecosm.com>
@@ -989,9 +4380,10 @@
* ipa-devirt.c (get_class_context): Allow POD to change to non-POD.
2014-05-05 Radovan Obradovic <robradovic@mips.com>
- Tom de Vries <tom@codesourcery.com>
+ Tom de Vries <tom@codesourcery.com>
- * target.def (call_fusage_contains_non_callee_clobbers): New DEFHOOKPOD.
+ * target.def (call_fusage_contains_non_callee_clobbers): New
+ DEFHOOKPOD.
* doc/tm.texi.in (@node Stack and Calling): Add Miscellaneous Register
Hooks to @menu.
(@node Miscellaneous Register Hooks): New node.
@@ -1017,9 +4409,8 @@
2014-05-05 Richard Biener <rguenther@suse.de>
PR middle-end/61010
- * fold-const.c (fold_binary_loc): Consistently avoid
- canonicalizing X & CST away from a CST that is the mask
- of a mode.
+ * fold-const.c (fold_binary_loc): Consistently avoid canonicalizing
+ X & CST away from a CST that is the mask of a mode.
2014-05-05 Jan-Benedict Glaw <jbglaw@lug-owl.de>
@@ -1338,8 +4729,7 @@
* doc/invoke.texi: Fix typo.
* tree-vrp.c: Fix typos.
- * gimple.c (infer_nonnull_range): Reorder operands of an &&
- condition.
+ * gimple.c (infer_nonnull_range): Reorder operands of an && condition.
2014-04-29 Zhenqiang Chen <zhenqiang.chen@linaro.org>
@@ -1466,8 +4856,7 @@
2014-04-28 Richard Biener <rguenther@suse.de>
* tree-pass.h (execute_pass_list): Adjust prototype.
- * passes.c (pass_manager::execute_early_local_passes):
- Adjust.
+ * passes.c (pass_manager::execute_early_local_passes): Adjust.
(do_per_function): Change callback signature, push all actual
work to the callbals.
(do_per_function_toporder): Likewise.
@@ -1518,18 +4907,18 @@
2014-04-25 Cary Coutant <ccoutant@google.com>
- PR debug/60929
+ PR debug/60929
* dwarf2out.c (should_move_die_to_comdat): A type definition
- can contain a subprogram definition, but don't move it to a
- comdat unit.
+ can contain a subprogram definition, but don't move it to a
+ comdat unit.
(clone_as_declaration): Copy DW_AT_abstract_origin attribute.
- (generate_skeleton_bottom_up): Remove DW_AT_object_pointer attribute
- from original DIE.
+ (generate_skeleton_bottom_up): Remove DW_AT_object_pointer attribute
+ from original DIE.
(clone_tree_hash): Rename to...
(clone_tree_partial): ...this; change callers. Copy
- DW_TAG_subprogram DIEs as declarations.
+ DW_TAG_subprogram DIEs as declarations.
(copy_decls_walk): Don't copy children of a declaration into a
- type unit.
+ type unit.
2014-04-25 H.J. Lu <hongjiu.lu@intel.com>
@@ -1547,8 +4936,7 @@
2014-04-25 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
- * config/arm/arm.c (arm_cortex_a8_tune): Initialise
- T16-related fields.
+ * config/arm/arm.c (arm_cortex_a8_tune): Initialise T16-related fields.
2014-04-25 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
@@ -1574,7 +4962,7 @@
clobbers.
2014-04-25 Radovan Obradovic <robradovic@mips.com>
- Tom de Vries <tom@codesourcery.com>
+ Tom de Vries <tom@codesourcery.com>
* rtlanal.c (find_all_hard_reg_sets): Add bool implicit parameter and
handle.
@@ -1632,8 +5020,7 @@
2014-04-24 Michael Meissner <meissner@linux.vnet.ibm.com>
* doc/extend.texi (PowerPC Built-in Functions): Document new
- powerpc extended divide, bcd, pack/unpack 128-bit, builtin
- functions.
+ powerpc extended divide, bcd, pack/unpack 128-bit, builtin functions.
(PowerPC AltiVec/VSX Built-in Functions): Likewise.
* config/rs6000/predicates.md (const_0_to_3_operand): New
@@ -1693,8 +5080,7 @@
support for decimal floating point builtin functions.
(rs6000_expand_ternop_builtin): Add checks for the new builtin
functions that take constant arguments.
- (rs6000_invalid_builtin): Add decimal floating point builtin
- support.
+ (rs6000_invalid_builtin): Add decimal floating point builtin support.
(rs6000_init_builtins): Setup long double, _Decimal64, and
_Decimal128 types for new builtin functions.
(builtin_function_type): Set the unsigned flags appropriately for
@@ -1745,8 +5131,7 @@
builtin functions.
(UNSPEC_CDTBCD): Likewise.
(UNSPEC_CBCDTD): Likewise.
- (UNSPEC_DIVE): Add support for new extended divide builtin
- functions.
+ (UNSPEC_DIVE): Add support for new extended divide builtin functions.
(UNSPEC_DIVEO): Likewise.
(UNSPEC_DIVEU): Likewise.
(UNSPEC_DIVEUO): Likewise.
@@ -1759,8 +5144,7 @@
(addg6s): Add new BCD builtin functions.
(cdtbcd): Likewise.
(cbcdtd): Likewise.
- (UNSPEC_DIV_EXTEND): Add support for new extended divide
- instructions.
+ (UNSPEC_DIV_EXTEND): Add support for new extended divide instructions.
(div_extend): Likewise.
(div<div_extend>_<mode>"): Likewise.
(FP128_64): Add support for new builtin functions to pack/unpack
@@ -1816,7 +5200,7 @@
* config/aarch64/aarch64.c (aarch64_evpc_tbl): Enable for bigendian.
2014-04-24 Radovan Obradovic <robradovic@mips.com>
- Tom de Vries <tom@codesourcery.com>
+ Tom de Vries <tom@codesourcery.com>
* reg-notes.def (REG_NOTE (CALL_DECL)): New reg-note REG_CALL_DECL.
* calls.c (expand_call, emit_library_call_value_1): Add REG_CALL_DECL
@@ -1825,14 +5209,14 @@
* emit-rtl.c (try_split): Same.
2014-04-24 Radovan Obradovic <robradovic@mips.com>
- Tom de Vries <tom@codesourcery.com>
+ Tom de Vries <tom@codesourcery.com>
* common.opt (fuse-caller-save): New option.
2014-04-24 Tejas Belagod <tejas.belagod@arm.com>
- * config/aarch64/aarch64.c (aarch64_evpc_tbl): Reverse order of elements
- for big-endian.
+ * config/aarch64/aarch64.c (aarch64_evpc_tbl): Reverse order of
+ elements for big-endian.
2014-04-24 Richard Biener <rguenther@suse.de>
@@ -1997,12 +5381,9 @@
(is_a_helper <const gimple_statement_catch *>::test): ...this.
(is_a_helper <const gimple_statement_resx>::test): Convert to...
(is_a_helper <const gimple_statement_resx *>::test): ...this.
- (is_a_helper <const gimple_statement_eh_dispatch>::test):
- Convert to...
- (is_a_helper <const gimple_statement_eh_dispatch *>::test):
- ...this.
- (is_a_helper <const gimple_statement_eh_filter>::test): Convert
- to...
+ (is_a_helper <const gimple_statement_eh_dispatch>::test): Convert to...
+ (is_a_helper <const gimple_statement_eh_dispatch *>::test): ...this.
+ (is_a_helper <const gimple_statement_eh_filter>::test): Convert to...
(is_a_helper <const gimple_statement_eh_filter *>::test): ...this.
(is_a_helper <const gimple_statement_omp_atomic_load>::test):
Convert to...
@@ -2012,8 +5393,7 @@
Convert to...
(is_a_helper <const gimple_statement_omp_atomic_store *>::test):
...this.
- (is_a_helper <const gimple_statement_omp_return>::test): Convert
- to...
+ (is_a_helper <const gimple_statement_omp_return>::test): Convert to...
(is_a_helper <const gimple_statement_omp_return *>::test): ...this.
(is_a_helper <const gimple_statement_omp_continue>::test): Convert
to...
@@ -2023,43 +5403,35 @@
(is_a_helper <const gimple_statement_omp_critical *>::test): ...this.
(is_a_helper <const gimple_statement_omp_for>::test): Convert to...
(is_a_helper <const gimple_statement_omp_for *>::test): ...this.
- (is_a_helper <const gimple_statement_omp_taskreg>::test): Convert
- to...
+ (is_a_helper <const gimple_statement_omp_taskreg>::test): Convert to...
(is_a_helper <const gimple_statement_omp_taskreg *>::test): ...this.
(is_a_helper <const gimple_statement_omp_parallel>::test): Convert
to...
(is_a_helper <const gimple_statement_omp_parallel *>::test): ...this.
- (is_a_helper <const gimple_statement_omp_target>::test): Convert
- to...
+ (is_a_helper <const gimple_statement_omp_target>::test): Convert to...
(is_a_helper <const gimple_statement_omp_target *>::test): ...this.
(is_a_helper <const gimple_statement_omp_sections>::test): Convert
to...
(is_a_helper <const gimple_statement_omp_sections *>::test): ...this.
- (is_a_helper <const gimple_statement_omp_single>::test): Convert
- to...
+ (is_a_helper <const gimple_statement_omp_single>::test): Convert to...
(is_a_helper <const gimple_statement_omp_single *>::test): ...this.
- (is_a_helper <const gimple_statement_omp_teams>::test): Convert
- to...
+ (is_a_helper <const gimple_statement_omp_teams>::test): Convert to...
(is_a_helper <const gimple_statement_omp_teams *>::test): ...this.
- (is_a_helper <const gimple_statement_omp_task>::test): Convert
- to...
+ (is_a_helper <const gimple_statement_omp_task>::test): Convert to...
(is_a_helper <const gimple_statement_omp_task *>::test): ...this.
(is_a_helper <const gimple_statement_phi>::test): Convert to...
(is_a_helper <const gimple_statement_phi *>::test): ...this.
- (is_a_helper <const gimple_statement_transaction>::test): Convert
- to...
+ (is_a_helper <const gimple_statement_transaction>::test): Convert to...
(is_a_helper <const gimple_statement_transaction *>::test): ...this.
- (is_a_helper <const gimple_statement_with_ops>::test): Convert
- to...
+ (is_a_helper <const gimple_statement_with_ops>::test): Convert to...
(is_a_helper <const gimple_statement_with_ops *>::test): ...this.
(is_a_helper <gimple_statement_with_ops>::test): Convert to...
(is_a_helper <gimple_statement_with_ops *>::test): ...this.
- (is_a_helper <const gimple_statement_with_memory_ops>::test):
- Convert to...
+ (is_a_helper <const gimple_statement_with_memory_ops>::test): Convert
+ to...
(is_a_helper <const gimple_statement_with_memory_ops *>::test):
...this.
- (is_a_helper <gimple_statement_with_memory_ops>::test): Convert
- to...
+ (is_a_helper <gimple_statement_with_memory_ops>::test): Convert to...
(is_a_helper <gimple_statement_with_memory_ops *>::test): ...this.
(gimple_use_ops): Update for removal of implicit pointer from the
@@ -2280,7 +5652,7 @@
invalidate outputs from statements that do not produce useful
outputs for threading.
-2014-04-23 Venkataramanan Kumar <venkataramanan.kumar@linaro.org>
+2014-04-23 Venkataramanan Kumar <venkataramanan.kumar@linaro.org>
* config/aarch64/aarch64.md (stack_protect_set, stack_protect_test)
(stack_protect_set_<mode>, stack_protect_test_<mode>): Add
@@ -2309,41 +5681,41 @@
2014-04-23 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
- * config/aarch64/aarch64.md (rev16<mode>2): New pattern.
- (rev16<mode>2_alt): Likewise.
- * config/aarch64/aarch64.c (aarch64_rtx_costs): Handle rev16 case.
- * config/arm/aarch-common.c (aarch_rev16_shright_mask_imm_p): New.
- (aarch_rev16_shleft_mask_imm_p): Likewise.
- (aarch_rev16_p_1): Likewise.
- (aarch_rev16_p): Likewise.
- * config/arm/aarch-common-protos.h (aarch_rev16_p): Declare extern.
- (aarch_rev16_shright_mask_imm_p): Likewise.
- (aarch_rev16_shleft_mask_imm_p): Likewise.
+ * config/aarch64/aarch64.md (rev16<mode>2): New pattern.
+ (rev16<mode>2_alt): Likewise.
+ * config/aarch64/aarch64.c (aarch64_rtx_costs): Handle rev16 case.
+ * config/arm/aarch-common.c (aarch_rev16_shright_mask_imm_p): New.
+ (aarch_rev16_shleft_mask_imm_p): Likewise.
+ (aarch_rev16_p_1): Likewise.
+ (aarch_rev16_p): Likewise.
+ * config/arm/aarch-common-protos.h (aarch_rev16_p): Declare extern.
+ (aarch_rev16_shright_mask_imm_p): Likewise.
+ (aarch_rev16_shleft_mask_imm_p): Likewise.
2014-04-23 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
- * config/arm/aarch-common-protos.h (alu_cost_table): Add rev field.
- * config/arm/aarch-cost-tables.h (generic_extra_costs): Specify
- rev cost.
- (cortex_a53_extra_costs): Likewise.
- (cortex_a57_extra_costs): Likewise.
- * config/arm/arm.c (cortexa9_extra_costs): Likewise.
- (cortexa7_extra_costs): Likewise.
- (cortexa8_extra_costs): Likewise.
- (cortexa12_extra_costs): Likewise.
- (cortexa15_extra_costs): Likewise.
- (v7m_extra_costs): Likewise.
- (arm_new_rtx_costs): Handle BSWAP.
+ * config/arm/aarch-common-protos.h (alu_cost_table): Add rev field.
+ * config/arm/aarch-cost-tables.h (generic_extra_costs): Specify
+ rev cost.
+ (cortex_a53_extra_costs): Likewise.
+ (cortex_a57_extra_costs): Likewise.
+ * config/arm/arm.c (cortexa9_extra_costs): Likewise.
+ (cortexa7_extra_costs): Likewise.
+ (cortexa8_extra_costs): Likewise.
+ (cortexa12_extra_costs): Likewise.
+ (cortexa15_extra_costs): Likewise.
+ (v7m_extra_costs): Likewise.
+ (arm_new_rtx_costs): Handle BSWAP.
2013-04-23 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
- * config/arm/arm.c (cortexa8_extra_costs): New table.
- (arm_cortex_a8_tune): New tuning struct.
- * config/arm/arm-cores.def (cortex-a8): Use cortex_a8 tuning struct.
+ * config/arm/arm.c (cortexa8_extra_costs): New table.
+ (arm_cortex_a8_tune): New tuning struct.
+ * config/arm/arm-cores.def (cortex-a8): Use cortex_a8 tuning struct.
2014-04-23 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
- * config/arm/arm.c (arm_new_rtx_costs): Handle FMA.
+ * config/arm/arm.c (arm_new_rtx_costs): Handle FMA.
2014-04-23 Richard Biener <rguenther@suse.de>
@@ -2379,8 +5751,7 @@
(has_32bit_hwmult): Rename to use_32bit_hwmult. Add support for
-mhwmult command line option.
(msp430_hwmult_enabled): Delete.
- (msp43o_output_labelref): Add support for -mhwmult command line
- option.
+ (msp43o_output_labelref): Add support for -mhwmult command line option.
* config/msp430/msp430.md (mulhisi3, umulhisi3, mulsidi3)
(umulsidi3): Likewise.
* config/msp430/msp430.opt (mmcu): Add Report attribute.
@@ -2796,8 +6167,7 @@
* gcc/config/aarch64/aarch64-simd.md (aarch64_s<optab><mode>):
Pattern extended.
- * config/aarch64/aarch64-simd-builtins.def (sqneg): Iterator
- extended.
+ * config/aarch64/aarch64-simd-builtins.def (sqneg): Iterator extended.
(sqabs): Likewise.
* config/aarch64/arm_neon.h (vqneg_s64): New intrinsic.
(vqnegd_s64): Likewise.
@@ -2914,12 +6284,9 @@
2014-04-22 Alex Velenko <Alex.Velenko@arm.com>
- * config/aarch64/aarch64-builtins.c (BUILTIN_VDQF_DF): Macro
- added.
- * config/aarch64/aarch64-simd-builtins.def (frintn): Use added
- macro.
- * config/aarch64/aarch64-simd.md (<frint_pattern>): Comment
- corrected.
+ * config/aarch64/aarch64-builtins.c (BUILTIN_VDQF_DF): Macro added.
+ * config/aarch64/aarch64-simd-builtins.def (frintn): Use added macro.
+ * config/aarch64/aarch64-simd.md (<frint_pattern>): Comment corrected.
* config/aarch64/aarch64.md (<frint_pattern>): Likewise.
* config/aarch64/arm_neon.h (vrnd_f64): Added.
(vrnda_f64): Likewise.
@@ -3259,7 +6626,7 @@
* tree-vect-loop.c (vect_create_epilog_for_reduction): Force
initial PHI args to be gimple values.
-2014-04-17 Richard Biener <rguenther@suse.de>
+2014-04-17 Richard Biener <rguenther@suse.de>
PR tree-optimization/60841
* tree-vect-data-refs.c (vect_analyze_data_refs): Count stmts.
@@ -3508,7 +6875,7 @@
gen_type_die_with_usage, gen_type_die_with_usage): Likewise.
* dbxout.c (dbxout_type, dbxout_symbol): Likewise.
-2014-04-14 Jan Hubicka <hubicka@ucw.cz>
+2014-04-14 Jan Hubicka <hubicka@ucw.cz>
PR lto/60820
* varpool.c (varpool_remove_node): Do not alter decls when streaming.
@@ -5574,7 +8941,7 @@
PR ipa/60306
Revert:
- 2013-12-14 Jan Hubicka <jh@suse.cz>
+ 2013-12-14 Jan Hubicka <jh@suse.cz>
PR middle-end/58477
* ipa-prop.c (stmt_may_be_vtbl_ptr_store): Skip clobbers.
@@ -8466,7 +11833,7 @@
* Makefile.in: Add vec.o to OBJS-libcommon
2014-01-23 Kirill Yukhin <kirill.yukhin@intel.com>
- Ilya Tocar <ilya.tocar@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
* config/i386/avx512fintrin.h (_mm512_kmov): New.
* config/i386/i386.c (IX86_BUILTIN_KMOV16): Ditto.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 8fb79c300d4..19de908ce73 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20140507
+20140602
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index fd8c2c5b3ea..335018606e5 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1269,6 +1269,8 @@ OBJS = \
ipa-devirt.o \
ipa-split.o \
ipa-inline.o \
+ ipa-comdats.o \
+ ipa-visibility.o \
ipa-inline-analysis.o \
ipa-inline-transform.o \
ipa-profile.o \
@@ -1353,6 +1355,7 @@ OBJS = \
sel-sched-dump.o \
sel-sched.o \
sese.o \
+ shrink-wrap.o \
simplify-rtx.o \
sparseset.o \
sreal.o \
@@ -2272,7 +2275,6 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
$(srcdir)/omp-low.c \
$(srcdir)/targhooks.c $(out_file) $(srcdir)/passes.c $(srcdir)/cgraphunit.c \
$(srcdir)/cgraphclones.c \
- $(srcdir)/tree-ssa-propagate.c \
$(srcdir)/tree-phinodes.c \
$(srcdir)/tree-ssa-alias.h \
$(srcdir)/tree-ssanames.h \
diff --git a/gcc/REVISION b/gcc/REVISION
index 7d9107f44ba..fff3bad9968 100644
--- a/gcc/REVISION
+++ b/gcc/REVISION
@@ -1 +1 @@
-[lto-pressure branch merged from trunk revision 210164]
+[lto-pressure branch merged from trunk revision 211147]
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 57c5176c838..8ce8b256671 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,512 @@
+2014-05-22 Thomas Schwinge <thomas@codesourcery.com>
+
+ * gcc-interface/utils.c (DEF_FUNCTION_TYPE_0, DEF_FUNCTION_TYPE_6)
+ (DEF_FUNCTION_TYPE_7, DEF_FUNCTION_TYPE_8)
+ (DEF_FUNCTION_TYPE_VAR_5): Cosmetic fixes.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * layout.adb: Minor reformatting.
+ * sem_prag.adb (Analyze_Pragma, case Inspection_Point): Call
+ dummy procedure ip.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * restrict.ads (Implementation_Restriction): Add entry for
+ No_Fixed_IO.
+ * rtsfind.ads: Add entries for Fixed_IO and Decimal_IO in
+ Ada.[Wide_[Wide_]Text_IO.
+ * s-rident.ads (Restriction_Id): Add entry for No_Fixed_IO.
+ * sem_attr.adb (Analyze_Attribute): Disallow fixed point types
+ for Img, Image, Value, Wide_Image, Wide_Value, Wide_Wide_Image,
+ Wide_Wide_Value if restriction No_Fixed_IO is set.
+ * sem_util.adb (Set_Entity_Checks): Check restriction No_Fixed_IO.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * gnatcmd.adb: Minor error msg changes (no upper case letter
+ at start).
+ * sem_ch12.adb, sem_ch5.adb, sem_res.adb, sem_util.adb: Minor
+ reformatting.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * debug.adb: Debug flag -gnatd.G inhibits static elab tracing
+ via generic formals.
+ * sem_elab.adb (Is_Call_Of_Generic_Formal): Return False if
+ -gnatd.G is set.
+
+2014-05-21 Thomas Quinot <quinot@adacore.com>
+
+ * exp_pakd.adb (Revert_Storage_Order): Renamed from Byte_Swap to
+ more accurately describe that this subprogram needs to come into
+ play also in cases where no byte swapping is involved, because
+ it also takes care of some required shifts (left-justification
+ of values).
+
+2014-05-21 Thomas Quinot <quinot@adacore.com>
+
+ * freeze.adb (Check_Component_Storage_Order): Indicate whether
+ a Scalar_Storage_Order attribute definition is present for the
+ component's type.
+ (Freeze_Record_Type): Suppress junk warnings
+ about purportedly junk Bit_Order / Scalar_Storage_Order attribute
+ definitions.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch8.adb (Analyze_Subprogram_Renaming): Put back call
+ to Kill_Elaboration_Checks.
+
+2014-05-21 Gary Dismukes <dismukes@adacore.com>
+
+ * layout.adb (Assoc_Add): Suppress the optimization of the (E
+ - C1) + C2 case, when the expression type is unsigned and C1 <
+ C2, to avoid creating a negative literal when folding.
+
+2014-05-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * freeze.adb (Freeze_Record_Type): Update the use of
+ Is_SPARK_Volatile.
+ * sem_ch3.adb (Analyze_Object_Contract): Update the use of
+ Is_SPARK_Volatile.
+ (Process_Discriminants): Update the use of Is_SPARK_Volatile.
+ * sem_ch5.adb (Analyze_Iterator_Specification): Update the use
+ of Is_SPARK_Volatile.
+ (Analyze_Loop_Parameter_Specification):
+ Update the use of Is_SPARK_Volatile.
+ * sem_ch6.adb (Process_Formals): Catch an illegal use of an IN
+ formal parameter when its type is volatile.
+ * sem_prag.adb (Analyze_Global_Item): Update the use of
+ Is_SPARK_Volatile.
+ * sem_res.adb (Resolve_Entity_Name): Correct the guard which
+ determines whether an entity is a volatile source SPARK object.
+ * sem_util.adb (Has_Enabled_Property): Accout for external
+ properties being set on objects other than abstract states
+ and variables. An example would be a formal parameter.
+ (Is_SPARK_Volatile): New routine.
+ (Is_SPARK_Volatile_Object):
+ Remove the entity-specific tests. Call routine Is_SPARK_Volatile
+ when checking entities and/or types.
+ * sem_util.ads (Is_SPARK_Volatile): New routine.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_warn.adb: Minor fix to warning messages (use ?? instead
+ of ?).
+
+2014-05-21 Vincent Celier <celier@adacore.com>
+
+ * gnatcmd.adb (GNATCmd): For platforms other than VMS, recognize
+ switch --version and --help.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_elab.adb (Is_Call_Of_Generic_Formal): New function.
+
+2014-05-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch5.adb (Analyze_Iterator_Specification): Set type of
+ iterator variable when the domain of iteration is a formal
+ container and this is an element iterator.
+
+2014-05-21 Bob Duff <duff@adacore.com>
+
+ * sem_ch12.adb: Minor reformatting.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * sinfo.ads, sem_ch12.adb, sem_warn.adb: Minor reformatting.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_elab.adb: Minor reformatting.
+ * s-taprop.ads: Minor comment fix.
+ * sem_ch8.adb (Analyze_Subprogram_Renaming): Remove call to
+ Kill_Elaboration_Checks.
+ * errout.adb, erroutc.adb: Minor reformatting.
+
+2014-05-21 Thomas Quinot <quinot@adacore.com>
+
+ * exp_pakd.adb (Byte_Swap): Handle the case of a sub-byte
+ component. No byte swapping occurs, but this procedure also takes
+ care of appropriately justifying the argument.
+
+2014-05-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_ch6.adb: sem_ch6.adb (Analyze_Aspects_On_Body_Or_Stub):
+ New routine.
+ (Analyze_Subprogram_Body_Helper): Move the
+ analysis of aspect specifications and the processing of the
+ subprogram body contract after inlining has taken place.
+ (Diagnose_Misplaced_Aspect_Specifications): Removed.
+
+2014-05-21 Javier Miranda <miranda@adacore.com>
+
+ * sem_ch3.adb (Build_Derived_Record_Type): Revert previous change.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_eval.ads, sem_eval.adb (Why_Not_Static): Messages are not
+ continuations any more.
+
+2014-05-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sinfo.ads, sinfo.adb: New flag Needs_Initialized_Actual,
+ present in formal_Private_Definitions and on private extension
+ declarations of a formal derived type. Set when the use of the
+ formal type in a generic suggests that the actual should be a
+ fully initialized type.
+ * sem_warn.adb (May_Need_Initialized_Actual): new subprogram
+ to indicate that an entity of a generic type has default
+ initialization, and that the corresponing actual type in any
+ subsequent instantiation should be fully initialized.
+ * sem_ch12.adb (Check_Initialized_Type): new subprogram,
+ to emit a warning if the actual for a generic type on which
+ Needs_Initialized_Actual is set is not a fully initialized type.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_elab.adb, prj-dect.adb: Minor reformatting.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * erroutc.ads: Minor comment addition.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * errout.ads: Add documentation for use of >*> tag.
+ * restrict.adb: Make sure we use >*> tag for restriction warnings.
+
+2014-05-21 Gary Dismukes <dismukes@adacore.com>
+
+ * debug.adb: Add case of illegal overriding_indicator for a
+ protected subprogram body to description of -gnatd.E switch.
+ * sem_ch6.adb (Verify_Overriding_Indicator): Issue error message
+ for cases of giving overriding_indicators on protected subprogram
+ bodies, but change this to a warning if -gnatd.E is enabled. No
+ longer give a style warning about missing indicators on protected
+ subprogram bodies.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * prj.ads, sem_ch12.adb, prj.adb, exp_pakd.adb,
+ sem_elab.ads: Minor reformatting.
+ * erroutc.adb, erroutc.ads (Warning_Specifically_Suppressed): Make Tag
+ parameter optional.
+
+2014-05-21 Pascal Obry <obry@adacore.com>
+
+ * prj-dect.adb: Allow package Install in aggregate project.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch13.adb (Analyze_Aspect_Specifications):
+ Insert_Delayed_Pragma is now used for the case of Attach_Handler.
+ * sem_prag.adb: Minor comment improvements.
+
+2014-05-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch12.adb (Install_Body): When checking whether freezing of
+ instantiation must be delayed, verify that the common enclosing
+ subprogram to generic and instance is in fact an overloadable
+ entity.
+
+2014-05-21 Vincent Celier <celier@adacore.com>
+
+ * makeutl.adb (Mains.Complete_Mains.Do_Complete): Look for all
+ mains with the same name and fail if there is more than one.
+ * prj.ads, prj.adb (Find_All_Sources): New function
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch13.adb: Minor reformatting.
+ * lib-xref-spark_specific.adb, sem_util.adb: Minor reformatting.
+ * sem_prag.adb: Minor error message improvement.
+
+2014-05-21 Yannick Moy <moy@adacore.com>
+
+ * lib-xref-spark_specific.adb, lib-xref.ads, lib-xref.adb
+ (Enclosing_Subprogram_Or_Package): Only return a library-level
+ package.
+
+2014-05-21 Javier Miranda <miranda@adacore.com>
+
+ * sem_ch3.adb (Build_Derived_Record_Type): Initialize Parent_Base
+ to the full view of the parent type when processing a derived type
+ which is the full view of a private type not defined in a generic
+ unit which is derived from a private type with discriminants
+ whose full view is a non-tagged record type.
+
+2014-05-21 Javier Miranda <miranda@adacore.com>
+
+ * exp_ch4.adb (Expand_Allocator_Expression.Apply_Accessibility_Check):
+ Complete previous patch.
+
+2014-05-21 Thomas Quinot <quinot@adacore.com>
+
+ PR ada/9535
+ * g-socket.adb (Read and Write for Datagram_Socket_Stream_Type):
+ Provide a behaviour more consistent with underlying datagram
+ socket: do not attempt to loop over Send_Socket/Receive_Socket
+ iterating along the buffer.
+
+2014-05-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * freeze.adb (Freeze_Record_Type): Ensure that a discriminated
+ or a tagged type is not labelled as volatile. Ensure that a
+ non-volatile type has no volatile components.
+ * sem_ch3.adb (Analyze_Object_Contract): Add local constant
+ Obj_Typ. Code reformatting. Ensure that a discriminated or
+ tagged object is not labelled as volatile.
+ * sem_prag.adb (Process_Atomic_Shared_Volatile): Ensure that
+ pragma Volatile applies to a full type declaration or an object
+ declaration when SPARK mode is on.
+
+2014-05-21 Sergey Rybin <rybin@adacore.com frybin>
+
+ * gnat_ugn.texi: For ASIS tools, reword the paragraph about
+ providing options needed for compiling the argument source for
+ the situation when a project file can be used as a tool parameter.
+
+2014-05-21 Gary Dismukes <dismukes@adacore.com>
+
+ * gnat_rm.texi: Minor typo fix.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * stand.adb (Tree_Read): Read missing entities.
+ (Tree_Write): Write missing entities.
+
+2014-05-21 Ben Brosgol <brosgol@adacore.com>
+
+ * gnat_ugn.texi: Wordsmithing edits to Coupling Metrics Control
+ section in gnatmetric chapter.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * exp_ch6.adb (Expand_Actuals): Spec moved here, since not used
+ outside Exp_Ch6 (Expand_Actuals): Deal with proper insertion of
+ post-call copy write back (see detailed comment in code).
+ * exp_ch6.ads (Expand_Actuals): Moved to body, not used outside
+ Exp_Ch6.
+ * tbuild.ads: Minor reformatting.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * stand.ads: Add warning about adding new entities and
+ Tree_Read/Tree_Write.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * sem_util.adb (Set_Entity_With_Checks): Don't complain about
+ references to restricted entities within the units in which they
+ are declared.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * gnat1drv.adb (Check_Bad_Body): Use Source_File_Is_Body to
+ simplify the needed test, and also deal with failure to catch
+ situations with non-standard names.
+ * sinput-l.ads, sinput-l.adb (Source_File_Is_No_Body): New function
+ (Source_File_Is_Subunit): Removed, no longer used.
+
+2014-05-21 Javier Miranda <miranda@adacore.com>
+
+ * exp_ch4.adb
+ (Expand_Allocator_Expression.Apply_Accessibility_Check): for a
+ renaming of an access to interface object there is no need to
+ generate extra code to reference the tag.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * errout.adb, erroutc.adb, erroutc.ads: Allow warning tag in pragma
+ Warnings (Off, string).
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * osint.adb: Fix three error messages to say invalid instead
+ of erroneous.
+ * par-ch4.adb, exp_aggr.adb, sem_attr.adb, sem_aux.adb, sem_ch3.adb,
+ sem_ch5.adb, sem_ch6.adb, sem_ch7.adb, sem_dim.adb, sem_res.adb,
+ sem_util.adb, sem_util.ads: Fix incorrect use of erroneous in comments.
+
+2014-05-21 Ed Schonberg <schonberg@adacore.com>
+
+ * freeze.adb, sem_ch13.adb, sem_ch13.ads, sem_ch9.adb,
+ sem_ch9.ads: Move discriminant manipulation routines for analysis of
+ aspect specifications from sem_ch9 to sem_ch13, where they belong.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * gnat_ugn.texi: Clearly document -gnatw.g (GNAT warnings).
+ Clearly document -gnatyg (GNAT style switches).
+ * usage.adb: Add line line for -gnatw.g (GNAT warnings) More
+ detail for line for -gnatyg (GNAT style switches) -gnatw.d/D is
+ available for VMS after all.
+ * warnsw.adb: Reorganize to eliminate duplicated code
+ (Restore_Warnings): Add a couple of missing entries
+ (Save_Warnings): Add a couple of missing entries.
+ * warnsw.ads: Add missing entries to Warning_Record (not clear
+ what the impact is).
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * errout.adb (Set_Msg_Insertion_Warning): Handle ?*? (restriction
+ warning) case.
+ * errout.ads: Document ?*? (restriction warning) insertion.
+ * erroutc.adb (Get_Warning_Tag): Deal with ?*? (restriction
+ warning) case.
+ * erroutc.ads: Document use of * for restriction warning tag.
+ * restrict.adb (Restriction_Msg): Tag with ?*? instead of ??.
+
+2014-05-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch9.adb (Push_Scope_And_Install_Discriminants): Do not
+ make discriminants immediately visible when analyzing an aspect
+ of a subtype declaration.
+ (Uninstall_Discriminants): Do not apply to the entity in a
+ subtype declaration.
+
+2014-05-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_util.adb: Code clean up.
+
+2014-05-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat_ugn.texi: Document -Werror.
+
+2014-05-21 Bob Duff <duff@adacore.com>
+
+ * sem_util.adb (Is_Dependent_Component_Of_Mutable_Object):
+ This was returning False if the Object is a constant view. Fix
+ it to return True in that case, because it might be a view of
+ a variable.
+ (Has_Discriminant_Dependent_Constraint): Fix latent
+ bug; this function was crashing when passed a discriminant.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * gnat_ugn.texi: Remove misplaced section that is now obsolete.
+ * s-arit64.adb: Minor code reorganization.
+ * sem_prag.adb: Minor comment fix (remove erroneous use of the
+ term erroneous).
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * g-table.adb, g-dyntab.adb (Reallocate): Fix possible overflow in
+ computing new table size.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * einfo.ads: Minor reformatting.
+ * ceinfo.adb: Deal with slight format change of einfo.ads.
+
+2014-05-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_prag.adb (Analyze_Part_Of): Further work on the proper
+ implementation of the SPARK 2014 rule concerning private child
+ units (LRM 7.2.6).
+
+2014-05-21 Vincent Celier <celier@adacore.com>
+
+ * makeusg.adb: Add switch -d to usage.
+
+2014-05-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_util.adb (Find_Actual): If an actual that is the prefix
+ of an enclosing prefixed call has been rewritten, use Nkind
+ and Sloc to identify the corresponding formal, when handling
+ deferred references.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * debug.adb: Document -gnatd.z switch.
+ * sem_eval.adb (Why_Non_Static): Test -gnatd.z switch.
+
+2014-05-21 Robert Dewar <dewar@adacore.com>
+
+ * einfo.ads (Can_Never_Be_Null): Minor comment update.
+ * sem_prag.adb (Check_Arg_Is_Task_Dispatching_Policy): Minor
+ error message change.
+ * s-arit64.adb ("abs"): New function. Use expression functions
+ for the simple conversions and arithmetic.
+
+2014-05-18 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Subprogram_Body_to_gnu): Rework comment and
+ set function_start_locus.
+
+2014-05-18 Eric Botcazou <ebotcazou@adacore.com>
+
+ * utils.c (gnat_write_global_declarations): Adjust the flags put on
+ dummy_global.
+
+2014-05-18 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (change_qualified_type): New static function.
+ (gnat_to_gnu_entity): Use it throughout to add qualifiers on types.
+ <E_Array_Type>: Set TYPE_VOLATILE on the array type directly.
+ <E_Array_Subtype>: Likewise.
+ Do not set flags on an UNCONSTRAINED_ARRAY_TYPE directly.
+ (gnat_to_gnu_component_type): Likewise.
+ (gnat_to_gnu_param): Likewise.
+
+2014-05-18 Eric Botcazou <ebotcazou@adacore.com>
+
+ * fe.h (Set_Present_Expr): Move around.
+ (End_Location): New macro.
+ * gcc-interface/trans.c (Case_Statement_to_gnu): Use End_Location.
+
+2014-05-18 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity): Use Underlying_Type in
+ lieu of more verbose construct.
+ * gcc-interface/trans.c (Call_to_gnu): Likewise.
+ (gnat_to_gnu): Likewise. Remove obsolete code.
+
+2014-05-18 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Subtype>: Do not
+ consider that regular packed arrays can never be superflat.
+
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * gcc-interface/ada-tree.h: Remove usage of variable_size gty
+ annotation.
+ * gcc-interface/decl.c (annotate_value): Adjust.
+ * gcc-interface/trans.c (Attribute_to_gnu): Likewise.
+ (push_range_check_info): Likewise.
+ (Loop_Statement_to_gnu): Likewise.
+ (Subprogram_Body_to_gnu): Likewise.
+ (Compilation_Unit_to_gnu): Likewise.
+ (start_stmt_group): Likewise.
+ * gcc-interface/utils.c (init_gnat_utils): Likewise.
+ (gnat_pushlevel): Likewise.
+ (maybe_pad_type): Likewise.
+
+2014-05-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * seh_init.c: Fix copyright year.
+
+2014-05-14 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * seh_init.c (__gnat_map_SEH): Compile also when __CYGWIN__ and __SEH__
+ are defined. Move include windows.h before system.h.
+ * s-oscons-tmplt.c (DTR_CONTROL_ENABLE, RTS_CONTROL_ENABLE): Compile
+ also when __CYGWIN__ is defined. Include windef.h before winbase.h.
+
+2014-05-14 Richard Sandiford <r.sandiford@uk.ibm.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity): Convert integer_one_node
+ to the appropriate type.
+ * gcc-interface/trans.c (gnat_to_gnu): Likewise.
+ (pos_to_constructor): Likewise.
+
+2014-05-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (annotate_value): Fix thinko in latest change.
+
2014-05-06 Kenneth Zadeck <zadeck@naturalbridge.com>
Mike Stump <mikestump@comcast.net>
Richard Sandiford <rdsandiford@googlemail.com>
diff --git a/gcc/ada/ceinfo.adb b/gcc/ada/ceinfo.adb
index 3f073b357b0..9c3b6eaa126 100644
--- a/gcc/ada/ceinfo.adb
+++ b/gcc/ada/ceinfo.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1998-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1998-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -99,8 +99,15 @@ begin
loop
Next_Line;
+
+ -- Old format of einfo.ads
+
exit when Match (Line, " -- Access Kinds --");
+ -- New format of einfo.ads
+
+ exit when Match (Line, "-- Access Kinds --");
+
if Match (Line, Field_Def) then
Set (Fields, Fieldnm, Accessfunc);
end if;
diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb
index 11237e23dc9..8399a2c9900 100644
--- a/gcc/ada/debug.adb
+++ b/gcc/ada/debug.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -116,7 +116,7 @@ package body Debug is
-- d.w Do not check for infinite loops
-- d.x No exception handlers
-- d.y
- -- d.z
+ -- d.z Temporary ASIS kludge for why non-static messages
-- d.A Read/write Aspect_Specifications hash table to tree
-- d.B
@@ -124,7 +124,7 @@ package body Debug is
-- d.D
-- d.E Turn selected errors into warnings
-- d.F Debug mode for GNATprove
- -- d.G
+ -- d.G Ignore calls through generic formal parameters for elaboration
-- d.H
-- d.I Do not ignore enum representation clauses in CodePeer mode
-- d.J Disable parallel SCIL generation mode
@@ -589,6 +589,11 @@ package body Debug is
-- fully compiled and analyzed, they just get eliminated from the
-- code generation step.
+ -- d.z Temporary debug switch for control of the why non-static messages
+ -- generated by Why_Non_Static. Normally these messages are suppressed
+ -- in ASIS mode (d2), but if d.z is set they are not suppressed. This
+ -- is a temporary switch to aid in updating ASIS base lines.
+
-- d.A There seems to be a problem with ASIS if we activate the circuit
-- for reading and writing the aspect specification hash table, so
-- for now, this is controlled by the debug flag d.A. The hash table
@@ -609,10 +614,20 @@ package body Debug is
--
-- Errors relating to the new rules about not defining equality
-- too late so that composition of equality can be assured.
+ --
+ -- Errors relating to overriding indicators on protected subprogram
+ -- bodies (not an Ada 2012 incompatibility, but might cause errors
+ -- for existing programs assuming they were legal because GNAT
+ -- formerly allowed them).
-- d.F Sets GNATprove_Mode to True. This allows debugging the frontend in
-- the special mode used by GNATprove.
+ -- d.G Previously the compiler ignored calls via generic formal parameters
+ -- when doing the analysis for the static elaboration model. This is
+ -- now fixed, but we provide this debug flag to revert to the previous
+ -- situation of ignoring such calls to aid in transition.
+
-- d.I Do not ignore enum representation clauses in CodePeer mode.
-- The default of ignoring representation clauses for enumeration
-- types in CodePeer is good for the majority of Ada code, but in some
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index 473e2f186d0..998be8b7842 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -518,19 +518,19 @@ package Einfo is
-- Export pragma).
-- Can_Never_Be_Null (Flag38)
--- This flag is defined in all entities, but can only be set in an object
--- which can never have a null value. Set for constant access values
--- initialized to a non-null value. This is also set for all access
--- parameters in Ada 83 and Ada 95 modes, and for access parameters
--- that explicitly exclude null in Ada 2005.
+-- This flag is defined in all entities. It is set in an object which can
+-- never have a null value. Set for constant access values initialized to
+-- a non-null value. This is also set for all access parameters in Ada 83
+-- and Ada 95 modes, and for access parameters that explicitly exclude
+-- exclude null in Ada 2005 mode.
--
-- This is used to avoid unnecessary resetting of the Is_Known_Non_Null
-- flag for such entities. In Ada 2005 mode, this is also used when
-- determining subtype conformance of subprogram profiles to ensure
-- that two formals have the same null-exclusion status.
--
--- ??? This is also set on some access types, eg the Etype of the
--- anonymous access type of a controlling formal.
+-- This is also set on some access types, e.g. the Etype of the anonymous
+-- access type of a controlling formal.
-- Can_Use_Internal_Rep (Flag229) [base type only]
-- Defined in Access_Subprogram_Kind nodes. This flag is set by the
@@ -4114,6 +4114,53 @@ package Einfo is
-- Defined in functions and procedures which have been classified as
-- Is_Primitive_Wrapper. Set to the entity being wrapper.
+---------------------------
+-- Renaming and Aliasing --
+---------------------------
+
+-- Several entity attributes relate to renaming constructs, and to the use of
+-- different names to refer to the same entity. The following is a summary of
+-- these constructs and their prefered uses.
+
+-- There are three related attributes:
+
+-- Renamed_Entity
+-- Renamed_Object
+-- Alias
+
+-- They all overlap because they are supposed to apply to different entity
+-- kinds. They are semantically related, and have the following intended uses:
+
+-- a) Renamed_Entity appplies to entities in renaming declarations that rename
+-- an entity, so the value of the attribute IS an entity. This applies to
+-- generic renamings, package renamings, exception renamings, and subprograms
+-- renamings that rename a subprogram (rather than an attribute, an entry, a
+-- protected operation, etc).
+
+-- b) Alias applies to overloadable entities, and the value is an overloadable
+-- entity. so this is a subset of the previous one. We use the term Alias to
+-- cover both renamings and inherited operations, because both cases are
+-- handled in the same way when expanding a call. namely the Alias of a given
+-- subprogram is the subprogram that will actually be called.
+
+-- Both a) and b) are set transitively, so that in fact it is not necessary to
+-- traverse chains of renamings when looking for the original entity: it's
+-- there in one step (this is done when analyzing renaming declarations other
+-- than object renamings in sem_ch8).
+
+-- c) Renamed_Object applies to constants and variables. Given that the name
+-- in an object renaming declaration is not necessarily an entity name, the
+-- value of the attribute is the tree for that name, eg AR (1).Comp. The case
+-- when that name is in fact an entity is not handled specially. This is why
+-- in a few cases we need to use a loop to trace a chain of object renamings
+-- where all of them happen to be entities. So:
+
+-- X : integer;
+-- Y : integer renames X; -- renamed object is the identifier X
+-- Z : integer renames Y; -- renamed object is the identifier Y
+
+-- The front-end does not store explicitly the fact that Z renames X.
+
--------------------------------------
-- Delayed Freezing and Elaboration --
--------------------------------------
@@ -4147,56 +4194,56 @@ package Einfo is
-- If a subprogram has an access parameter whose designated type is incomplete
-- the subprogram has the flag set.
- ------------------
- -- Access Kinds --
- ------------------
+------------------
+-- Access Kinds --
+------------------
- -- The following entity kinds are introduced by the corresponding type
- -- definitions:
+-- The following entity kinds are introduced by the corresponding type
+-- definitions:
- -- E_Access_Type,
- -- E_General_Access_Type,
- -- E_Access_Subprogram_Type,
- -- E_Anonymous_Access_Subprogram_Type,
- -- E_Access_Protected_Subprogram_Type,
- -- E_Anonymous_Access_Protected_Subprogram_Type
- -- E_Anonymous_Access_Type.
+-- E_Access_Type,
+-- E_General_Access_Type,
+-- E_Access_Subprogram_Type,
+-- E_Anonymous_Access_Subprogram_Type,
+-- E_Access_Protected_Subprogram_Type,
+-- E_Anonymous_Access_Protected_Subprogram_Type
+-- E_Anonymous_Access_Type.
- -- E_Access_Subtype is for an access subtype created by a subtype
- -- declaration.
+-- E_Access_Subtype is for an access subtype created by a subtype
+-- declaration.
- -- In addition, we define the kind E_Allocator_Type to label allocators.
- -- This is because special resolution rules apply to this construct.
- -- Eventually the constructs are labeled with the access type imposed by
- -- the context. Gigi should never see the type E_Allocator.
+-- In addition, we define the kind E_Allocator_Type to label allocators.
+-- This is because special resolution rules apply to this construct.
+-- Eventually the constructs are labeled with the access type imposed by
+-- the context. Gigi should never see the type E_Allocator.
- -- Similarly, the type E_Access_Attribute_Type is used as the initial kind
- -- associated with an access attribute. After resolution a specific access
- -- type will be established as determined by the context.
+-- Similarly, the type E_Access_Attribute_Type is used as the initial kind
+-- associated with an access attribute. After resolution a specific access
+-- type will be established as determined by the context.
- -- Finally, the type Any_Access is used to label -null- during type
- -- resolution. Any_Access is also replaced by the context type after
- -- resolution.
+-- Finally, the type Any_Access is used to label -null- during type
+-- resolution. Any_Access is also replaced by the context type after
+-- resolution.
- --------------------------------
- -- Classification of Entities --
- --------------------------------
+--------------------------------
+-- Classification of Entities --
+--------------------------------
- -- The classification of program entities which follows is a refinement of
- -- the list given in RM 3.1(1). E.g., separate entities denote subtypes of
- -- different type classes. Ada 95 entities include class wide types,
- -- protected types, subprogram types, generalized access types, generic
- -- formal derived types and generic formal packages.
-
- -- The order chosen for these kinds allows us to classify related entities
- -- so that they are contiguous. As a result, they do not appear in the
- -- exact same order as their order of first appearance in the LRM (For
- -- example, private types are listed before packages). The contiguity
- -- allows us to define useful subtypes (see below) such as type entities,
- -- overloaded entities, etc.
-
- -- Each entity (explicitly or implicitly declared) has a kind, which is
- -- a value of the following type:
+-- The classification of program entities which follows is a refinement of
+-- the list given in RM 3.1(1). E.g., separate entities denote subtypes of
+-- different type classes. Ada 95 entities include class wide types,
+-- protected types, subprogram types, generalized access types, generic
+-- formal derived types and generic formal packages.
+
+-- The order chosen for these kinds allows us to classify related entities
+-- so that they are contiguous. As a result, they do not appear in the
+-- exact same order as their order of first appearance in the LRM (For
+-- example, private types are listed before packages). The contiguity
+-- allows us to define useful subtypes (see below) such as type entities,
+-- overloaded entities, etc.
+
+-- Each entity (explicitly or implicitly declared) has a kind, which is
+-- a value of the following type:
type Entity_Kind is (
diff --git a/gcc/ada/errout.adb b/gcc/ada/errout.adb
index b6255891779..37a1b64d686 100644
--- a/gcc/ada/errout.adb
+++ b/gcc/ada/errout.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -1010,14 +1010,11 @@ package body Errout is
exit when
Errors.Table (Cur_Msg).Sfile < Errors.Table (Next_Msg).Sfile;
- if Errors.Table (Cur_Msg).Sfile =
- Errors.Table (Next_Msg).Sfile
+ if Errors.Table (Cur_Msg).Sfile = Errors.Table (Next_Msg).Sfile
then
exit when Sptr < Errors.Table (Next_Msg).Sptr
- or else
- (Sptr = Errors.Table (Next_Msg).Sptr
- and then
- Optr < Errors.Table (Next_Msg).Optr);
+ or else (Sptr = Errors.Table (Next_Msg).Sptr
+ and then Optr < Errors.Table (Next_Msg).Optr);
end if;
Prev_Msg := Next_Msg;
@@ -1339,14 +1336,16 @@ package body Errout is
Cur := First_Error_Msg;
while Cur /= No_Error_Msg loop
declare
- CE : Error_Msg_Object renames Errors.Table (Cur);
+ CE : Error_Msg_Object renames Errors.Table (Cur);
+ Tag : constant String := Get_Warning_Tag (Cur);
begin
if (CE.Warn and not CE.Deleted)
- and then (Warning_Specifically_Suppressed (CE.Sptr, CE.Text) /=
+ and then
+ (Warning_Specifically_Suppressed (CE.Sptr, CE.Text, Tag) /=
No_String
- or else
- Warning_Specifically_Suppressed (CE.Optr, CE.Text) /=
+ or else
+ Warning_Specifically_Suppressed (CE.Optr, CE.Text, Tag) /=
No_String)
then
Delete_Warning (Cur);
@@ -2764,7 +2763,9 @@ package body Errout is
elsif P + 1 <= Text'Last
and then (Text (P) in 'a' .. 'z'
or else
- Text (P) in 'A' .. 'Z')
+ Text (P) in 'A' .. 'Z'
+ or else
+ Text (P) = '*')
and then Text (P + 1) = C
then
Warning_Msg_Char := Text (P);
diff --git a/gcc/ada/errout.ads b/gcc/ada/errout.ads
index 2a91a13427f..a42d3dba75c 100644
--- a/gcc/ada/errout.ads
+++ b/gcc/ada/errout.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -60,10 +60,12 @@ package Errout is
-- Exception raised if Raise_Exception_On_Error is true
Warning_Doc_Switch : Boolean renames Err_Vars.Warning_Doc_Switch;
- -- If this is set True, then the ??/?x?/?X? sequences in error messages
- -- are active (see errout.ads for details). If this switch is False, then
- -- these sequences are ignored (i.e. simply equivalent to a single ?). The
- -- -gnatw.d switch sets this flag True, -gnatw.D sets this flag False.
+ -- If this is set True, then the ??/?*?/?x?/?X? sequences in error messages
+ -- generate appropriate tags for the output error messages. If this switch
+ -- is False, then these sequences are still recognized (for the purposes
+ -- of implementing pragmas Warnings (Off,..) and Warning_As_Pragma(...) but
+ -- do not result in adding the error message tag. The -gnatw.d switch sets
+ -- this flag True, -gnatw.D sets this flag False.
-----------------------------------
-- Suppression of Error Messages --
@@ -281,7 +283,7 @@ package Errout is
-- messages, and the usual style is to include it, since it makes it
-- clear that the continuation is part of a warning message.
--
- -- Note: this usage is obsolete, use ??, ?x? or ?X? instead to specify
+ -- Note: this usage is obsolete, use ?? ?*? ?x? ?X? instead to specify
-- the string to be added when Warn_Doc_Switch is set to True. If this
-- switch is True, then for simple ? messages it has no effect. This
-- simple form is to ease transition and will be removed later.
@@ -302,13 +304,18 @@ package Errout is
-- letter corresponding to the lower case letter x in the message.
-- For continuations, use this on each continuation message.
+ -- Insertion character ?*? (restriction warning)
+ -- Like ?, but if the flag Warn_Doc_Switch is True, adds the string
+ -- "[restriction warning]" at the end of the warning message. For
+ -- continuations, use this on each continuation message.
+
-- Insertion character < (Less Than: conditional warning message)
-- The character < appearing anywhere in a message is used for a
-- conditional error message. If Error_Msg_Warn is True, then the
- -- effect is the same as ? described above, and in particular << and
- -- <X< have the effect of ?? and ?X? respectively. If Error_Msg_Warn
- -- is False, then the < << or <X< sequence is ignored and the message
- -- is treated as a error rather than a warning.
+ -- effect is the same as ? described above, and in particular <<
+ -- <X< and <*< have the effect of ?? ?X? and ?*? respectively. If
+ -- Error_Msg_Warn is False, then the < << or <X< sequence is ignored
+ -- and the message is treated as a error rather than a warning.
-- Insertion character A-Z (Upper case letter: Ada reserved word)
-- If two or more upper case letters appear in the message, they are
diff --git a/gcc/ada/erroutc.adb b/gcc/ada/erroutc.adb
index 3f167026d45..4a107d1df10 100644
--- a/gcc/ada/erroutc.adb
+++ b/gcc/ada/erroutc.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -113,13 +113,13 @@ package body Erroutc is
N1, N2 : Error_Msg_Id;
procedure Delete_Msg (Delete, Keep : Error_Msg_Id);
- -- Called to delete message Delete, keeping message Keep. Marks all
- -- messages of Delete with deleted flag set to True, and also makes sure
- -- that for the error messages that are retained the preferred message
- -- is the one retained (we prefer the shorter one in the case where one
- -- has an Instance tag). Note that we always know that Keep has at least
- -- as many continuations as Delete (since we always delete the shorter
- -- sequence).
+ -- Called to delete message Delete, keeping message Keep. Marks msg
+ -- Delete and all its continuations with deleted flag set to True.
+ -- Also makes sure that for the error messages that are retained the
+ -- preferred message is the one retained (we prefer the shorter one in
+ -- the case where one has an Instance tag). Note that we always know
+ -- that Keep has at least as many continuations as Delete (since we
+ -- always delete the shorter sequence).
----------------
-- Delete_Msg --
@@ -310,6 +310,8 @@ package body Erroutc is
if Warn and then Warn_Chr /= ' ' then
if Warn_Chr = '?' then
return "[enabled by default]";
+ elsif Warn_Chr = '*' then
+ return "[restriction warning]";
elsif Warn_Chr in 'a' .. 'z' then
return "[-gnatw" & Warn_Chr & ']';
else pragma Assert (Warn_Chr in 'A' .. 'Z');
@@ -1455,7 +1457,8 @@ package body Erroutc is
function Warning_Specifically_Suppressed
(Loc : Source_Ptr;
- Msg : String_Ptr) return String_Id
+ Msg : String_Ptr;
+ Tag : String := "") return String_Id
is
begin
-- Loop through specific warning suppression entries
@@ -1471,7 +1474,9 @@ package body Erroutc is
if SWE.Config
or else (SWE.Start <= Loc and then Loc <= SWE.Stop)
then
- if Matches (Msg.all, SWE.Msg.all) then
+ if Matches (Msg.all, SWE.Msg.all)
+ or else Matches (Tag, SWE.Msg.all)
+ then
SWE.Used := True;
return SWE.Reason;
end if;
diff --git a/gcc/ada/erroutc.ads b/gcc/ada/erroutc.ads
index 58611289da4..c638aac1b1e 100644
--- a/gcc/ada/erroutc.ads
+++ b/gcc/ada/erroutc.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -64,10 +64,11 @@ package Erroutc is
Warning_Msg_Char : Character;
-- Warning character, valid only if Is_Warning_Msg is True
- -- ' ' -- ? appeared on its own in message
- -- '?' -- ?? appeared in message
- -- 'x' -- ?x? appeared in message
- -- 'X' -- ?x? appeared in message (X is upper case of x)
+ -- ' ' -- ? appeared on its own in message
+ -- '?' -- ?? appeared in message
+ -- 'x' -- ?x? appeared in message (x = a .. z)
+ -- 'X' -- ?X? appeared in message (X = A .. Z)
+ -- '*' -- ?*? appeared in message
Is_Style_Msg : Boolean := False;
-- Set True to indicate if the current message is a style message
@@ -201,10 +202,11 @@ package Erroutc is
Warn_Chr : Character;
-- Warning character (note: set even if Warning_Doc_Switch is False)
- -- ' ' -- ? appeared on its own in message or no ? in message
- -- '?' -- ?? appeared in message
- -- 'x' -- ?x? appeared in message
- -- 'X' -- ?x? appeared in message (X is upper case of x)
+ -- ' ' -- ? appeared on its own in message
+ -- '?' -- ?? appeared in message
+ -- 'x' -- ?x? appeared in message (x = a .. z)
+ -- 'X' -- ?X? appeared in message (X = A .. Z)
+ -- '*' -- ?*? appeared in message
Style : Boolean;
-- True if style message (starts with "(style)")
@@ -554,12 +556,18 @@ package Erroutc is
function Warning_Specifically_Suppressed
(Loc : Source_Ptr;
- Msg : String_Ptr) return String_Id;
+ Msg : String_Ptr;
+ Tag : String := "") return String_Id;
-- Determines if given message to be posted at given location is suppressed
-- by specific ON/OFF Warnings pragmas specifying this particular message.
-- If the warning is not suppressed then No_String is returned, otherwise
-- the corresponding warning string is returned (or the null string if no
- -- Warning argument was present in the pragma).
+ -- Warning argument was present in the pragma). Tag is the error message
+ -- tag for the message in question or the null string if there is no tag.
+ --
+ -- Note: we have a null default for Tag to deal with calls from an old
+ -- branch of gnat2why, which does not know about tags in the calls but
+ -- which uses the latest version of erroutc.
function Warning_Treated_As_Error (Msg : String) return Boolean;
-- Returns True if the warning message Msg matches any of the strings
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index aa742d6a21f..676a6105bf3 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -5300,7 +5300,7 @@ package body Exp_Aggr is
-- interactions with bootstrapping. That limit is removed by
-- use of the No_Implicit_Loops restriction.
- -- b) It erroneously ends up with the resulting expressions being
+ -- b) It incorrectly ends up with the resulting expressions being
-- considered static when they are not. For example, the
-- following test should fail:
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 7065d945b2a..a3213aaeae5 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -831,13 +831,26 @@ package body Exp_Ch4 is
-- Step 2: Create the accessibility comparison
+ -- Reference the tag: for a renaming of an access to an interface
+ -- object Obj_Ref already references the tag of the secondary
+ -- dispatch table.
+
+ if Nkind (Obj_Ref) in N_Has_Entity
+ and then Present (Entity (Obj_Ref))
+ and then Present (Renamed_Object (Entity (Obj_Ref)))
+ and then Is_Interface (DesigT)
+ then
+ null;
+
-- Generate:
-- Ref'Tag
- Obj_Ref :=
- Make_Attribute_Reference (Loc,
- Prefix => Obj_Ref,
- Attribute_Name => Name_Tag);
+ else
+ Obj_Ref :=
+ Make_Attribute_Reference (Loc,
+ Prefix => Obj_Ref,
+ Attribute_Name => Name_Tag);
+ end if;
-- For tagged types, determine the accessibility level by looking
-- at the type specific data of the dispatch table. Generate:
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index 46cc9ca4d10..2aa9dc714b3 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -165,6 +165,41 @@ package body Exp_Ch6 is
-- the values are not changed for the call, we know immediately that
-- we have an infinite recursion.
+ procedure Expand_Actuals (N : in out Node_Id; Subp : Entity_Id);
+ -- For each actual of an in-out or out parameter which is a numeric
+ -- (view) conversion of the form T (A), where A denotes a variable,
+ -- we insert the declaration:
+ --
+ -- Temp : T[ := T (A)];
+ --
+ -- prior to the call. Then we replace the actual with a reference to Temp,
+ -- and append the assignment:
+ --
+ -- A := TypeA (Temp);
+ --
+ -- after the call. Here TypeA is the actual type of variable A. For out
+ -- parameters, the initial declaration has no expression. If A is not an
+ -- entity name, we generate instead:
+ --
+ -- Var : TypeA renames A;
+ -- Temp : T := Var; -- omitting expression for out parameter.
+ -- ...
+ -- Var := TypeA (Temp);
+ --
+ -- For other in-out parameters, we emit the required constraint checks
+ -- before and/or after the call.
+ --
+ -- For all parameter modes, actuals that denote components and slices of
+ -- packed arrays are expanded into suitable temporaries.
+ --
+ -- For non-scalar objects that are possibly unaligned, add call by copy
+ -- code (copy in for IN and IN OUT, copy out for OUT and IN OUT).
+ --
+ -- The parameter N is IN OUT because in some cases, the expansion code
+ -- rewrites the call as an expression actions with the call inside. In
+ -- this case N is reset to point to the inside call so that the caller
+ -- can continue processing of this call.
+
procedure Expand_Ctrl_Function_Call (N : Node_Id);
-- N is a function call which returns a controlled object. Transform the
-- call into a temporary which retrieves the returned object from the
@@ -939,7 +974,7 @@ package body Exp_Ch6 is
-- Expand_Actuals --
--------------------
- procedure Expand_Actuals (N : Node_Id; Subp : Entity_Id) is
+ procedure Expand_Actuals (N : in out Node_Id; Subp : Entity_Id) is
Loc : constant Source_Ptr := Sloc (N);
Actual : Node_Id;
Formal : Entity_Id;
@@ -976,10 +1011,10 @@ package body Exp_Ch6 is
-- the effect that this might lead to unaligned arguments.
function Make_Var (Actual : Node_Id) return Entity_Id;
- -- Returns an entity that refers to the given actual parameter,
- -- Actual (not including any type conversion). If Actual is an
- -- entity name, then this entity is returned unchanged, otherwise
- -- a renaming is created to provide an entity for the actual.
+ -- Returns an entity that refers to the given actual parameter, Actual
+ -- (not including any type conversion). If Actual is an entity name,
+ -- then this entity is returned unchanged, otherwise a renaming is
+ -- created to provide an entity for the actual.
procedure Reset_Packed_Prefix;
-- The expansion of a packed array component reference is delayed in
@@ -1604,8 +1639,8 @@ package body Exp_Ch6 is
-- Also pass by copy if change of representation
or else not Same_Representation
- (Etype (Formal),
- Etype (Expression (Actual))))
+ (Etype (Formal),
+ Etype (Expression (Actual))))
then
Add_Call_By_Copy_Code;
@@ -1809,7 +1844,7 @@ package body Exp_Ch6 is
if In_Open_Scopes (Entity (Actual)) then
Rewrite (Actual,
(Make_Function_Call (Loc,
- Name => New_Occurrence_Of (RTE (RE_Self), Loc))));
+ Name => New_Occurrence_Of (RTE (RE_Self), Loc))));
Analyze (Actual);
-- A task type cannot otherwise appear as an actual
@@ -1831,36 +1866,93 @@ package body Exp_Ch6 is
-- Cases where the call is not a member of a statement list
if not Is_List_Member (N) then
- declare
- P : Node_Id := Parent (N);
- begin
- -- In Ada 2012 the call may be a function call in an expression
- -- (since OUT and IN OUT parameters are now allowed for such
- -- calls. The write-back of (in)-out parameters is handled
- -- by the back-end, but the constraint checks generated when
- -- subtypes of formal and actual don't match must be inserted
- -- in the form of assignments, at the nearest point after the
- -- declaration or statement that contains the call.
-
- if Ada_Version >= Ada_2012
- and then Nkind (N) = N_Function_Call
- then
- while Nkind (P) not in N_Declaration
- and then
- Nkind (P) not in N_Statement_Other_Than_Procedure_Call
- loop
- P := Parent (P);
- end loop;
+ -- In Ada 2012 the call may be a function call in an expression
+ -- (since OUT and IN OUT parameters are now allowed for such
+ -- calls). The write-back of (in)-out parameters is handled
+ -- by the back-end, but the constraint checks generated when
+ -- subtypes of formal and actual don't match must be inserted
+ -- in the form of assignments.
- Insert_Actions_After (P, Post_Call);
+ if Ada_Version >= Ada_2012
+ and then Nkind (N) = N_Function_Call
+ then
+ -- We used to just do handle this by climbing up parents to
+ -- a non-statement/declaration and then simply making a call
+ -- to Insert_Actions_After (P, Post_Call), but that doesn't
+ -- work. If we are in the middle of an expression, e.g. the
+ -- condition of an IF, this call would insert after the IF
+ -- statement, which is much too late to be doing the write
+ -- back. For example:
+
+ -- if Clobber (X) then
+ -- Put_Line (X'Img);
+ -- else
+ -- goto Junk
+ -- end if;
+
+ -- Now assume Clobber changes X, if we put the write back
+ -- after the IF, the Put_Line gets the wrong value and the
+ -- goto causes the write back to be skipped completely.
+
+ -- To deal with this, we replace the call by
+
+ -- do
+ -- Tnnn : function-result-type renames function-call;
+ -- Post_Call actions
+ -- in
+ -- Tnnn;
+ -- end;
+
+ -- Note: this won't do in Modify_Tree_For_C mode, but we
+ -- will deal with that later (it will require creating a
+ -- declaration for Temp, using Insert_Declaration) ???
- -- If not the special Ada 2012 case of a function call, then
- -- we must have the triggering statement of a triggering
- -- alternative or an entry call alternative, and we can add
- -- the post call stuff to the corresponding statement list.
+ declare
+ Tnnn : constant Entity_Id := Make_Temporary (Loc, 'T');
+ FRTyp : constant Entity_Id := Etype (N);
+ Name : constant Node_Id := Relocate_Node (N);
- else
+ begin
+ Prepend_To (Post_Call,
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Tnnn,
+ Subtype_Mark => New_Occurrence_Of (FRTyp, Loc),
+ Name => Name));
+
+ Rewrite (N,
+ Make_Expression_With_Actions (Loc,
+ Actions => Post_Call,
+ Expression => New_Occurrence_Of (Tnnn, Loc)));
+
+ -- We don't want to just blindly call Analyze_And_Resolve
+ -- because that would cause unwanted recursion on the call.
+ -- So for a moment set the call as analyzed to prevent that
+ -- recursion, and get the rest analyzed properly, then reset
+ -- the analyzed flag, so our caller can continue.
+
+ Set_Analyzed (Name, True);
+ Analyze_And_Resolve (N, FRTyp);
+ Set_Analyzed (Name, False);
+
+ -- Reset calling argument to point to function call inside
+ -- the expression with actions so the caller can continue
+ -- to process the call.
+
+ N := Name;
+ end;
+
+ -- If not the special Ada 2012 case of a function call, then
+ -- we must have the triggering statement of a triggering
+ -- alternative or an entry call alternative, and we can add
+ -- the post call stuff to the corresponding statement list.
+
+ else
+ declare
+ P : Node_Id;
+
+ begin
+ P := Parent (N);
pragma Assert (Nkind_In (P, N_Triggering_Alternative,
N_Entry_Call_Alternative));
@@ -1870,15 +1962,17 @@ package body Exp_Ch6 is
else
Set_Statements (P, Post_Call);
end if;
- end if;
- end;
+ return;
+ end;
+ end if;
-- Otherwise, normal case where N is in a statement sequence,
-- just put the post-call stuff after the call statement.
else
Insert_Actions_After (N, Post_Call);
+ return;
end if;
end if;
diff --git a/gcc/ada/exp_ch6.ads b/gcc/ada/exp_ch6.ads
index 8cdd6fa7d37..801a5a2a61a 100644
--- a/gcc/ada/exp_ch6.ads
+++ b/gcc/ada/exp_ch6.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -37,36 +37,6 @@ package Exp_Ch6 is
procedure Expand_N_Subprogram_Body_Stub (N : Node_Id);
procedure Expand_N_Subprogram_Declaration (N : Node_Id);
- procedure Expand_Actuals (N : Node_Id; Subp : Entity_Id);
- -- For each actual of an in-out or out parameter which is a numeric
- -- (view) conversion of the form T (A), where A denotes a variable,
- -- we insert the declaration:
- --
- -- Temp : T[ := T (A)];
- --
- -- prior to the call. Then we replace the actual with a reference to Temp,
- -- and append the assignment:
- --
- -- A := TypeA (Temp);
- --
- -- after the call. Here TypeA is the actual type of variable A. For out
- -- parameters, the initial declaration has no expression. If A is not an
- -- entity name, we generate instead:
- --
- -- Var : TypeA renames A;
- -- Temp : T := Var; -- omitting expression for out parameter.
- -- ...
- -- Var := TypeA (Temp);
- --
- -- For other in-out parameters, we emit the required constraint checks
- -- before and/or after the call.
- --
- -- For all parameter modes, actuals that denote components and slices of
- -- packed arrays are expanded into suitable temporaries.
- --
- -- For non-scalar objects that are possibly unaligned, add call by copy
- -- code (copy in for IN and IN OUT, copy out for OUT and IN OUT).
-
procedure Expand_Call (N : Node_Id);
-- This procedure contains common processing for Expand_N_Function_Call,
-- Expand_N_Procedure_Statement, and Expand_N_Entry_Call.
diff --git a/gcc/ada/exp_pakd.adb b/gcc/ada/exp_pakd.adb
index 19264cb9ec4..9569979960a 100644
--- a/gcc/ada/exp_pakd.adb
+++ b/gcc/ada/exp_pakd.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -484,8 +484,8 @@ package body Exp_Pakd is
Expr : Node_Id) return Node_Id;
-- The packed array code does unchecked conversions which in some cases
-- may involve non-discrete types with differing sizes. The semantics of
- -- such conversions is potentially endian dependent, and the effect we
- -- want here for such a conversion is to do the conversion in size as
+ -- such conversions is potentially endianness dependent, and the effect
+ -- we want here for such a conversion is to do the conversion in size as
-- though numeric items are involved, and we extend or truncate on the
-- left side. This happens naturally in the little-endian case, but in
-- the big endian case we can get left justification, when what we want
@@ -543,25 +543,19 @@ package body Exp_Pakd is
-- array type on the fly). Such actions are inserted into the tree
-- directly using Insert_Action.
- function Byte_Swap
- (N : Node_Id;
- Left_Justify : Boolean := False;
- Right_Justify : Boolean := False) return Node_Id;
- -- Wrap N in a call to a byte swapping function, with appropriate type
- -- conversions. If Left_Justify is set True, the value is left justified
- -- before swapping. If Right_Justify is set True, the value is right
- -- justified after swapping. The Etype of the returned node is an
- -- integer type of an appropriate power-of-2 size.
-
- ---------------
- -- Byte_Swap --
- ---------------
-
- function Byte_Swap
- (N : Node_Id;
- Left_Justify : Boolean := False;
- Right_Justify : Boolean := False) return Node_Id
- is
+ function Revert_Storage_Order (N : Node_Id) return Node_Id;
+ -- Perform appropriate justification and byte ordering adjustments for N,
+ -- an element of a packed array type, when both the component type and
+ -- the enclosing packed array type have reverse scalar storage order.
+ -- On little-endian targets, the value is left justified before byte
+ -- swapping. The Etype of the returned expression is an integer type of
+ -- an appropriate power-of-2 size.
+
+ --------------------------
+ -- Revert_Storage_Order --
+ --------------------------
+
+ function Revert_Storage_Order (N : Node_Id) return Node_Id is
Loc : constant Source_Ptr := Sloc (N);
T : constant Entity_Id := Etype (N);
T_Size : constant Uint := RM_Size (T);
@@ -571,51 +565,59 @@ package body Exp_Pakd is
Swap_T : Entity_Id;
-- Swapping function
- Arg : Node_Id;
- Swapped : Node_Id;
- Shift : Uint;
+ Arg : Node_Id;
+ Adjusted : Node_Id;
+ Shift : Uint;
begin
- pragma Assert (T_Size > 8);
+ if T_Size <= 8 then
+
+ -- Array component size is less than a byte: no swapping needed
+
+ Swap_F := Empty;
+ Swap_T := RTE (RE_Unsigned_8);
+
+ else
+ -- Select byte swapping function depending on array component size
+
+ if T_Size <= 16 then
+ Swap_RE := RE_Bswap_16;
- if T_Size <= 16 then
- Swap_RE := RE_Bswap_16;
+ elsif T_Size <= 32 then
+ Swap_RE := RE_Bswap_32;
+
+ else pragma Assert (T_Size <= 64);
+ Swap_RE := RE_Bswap_64;
+ end if;
- elsif T_Size <= 32 then
- Swap_RE := RE_Bswap_32;
+ Swap_F := RTE (Swap_RE);
+ Swap_T := Etype (Swap_F);
- else pragma Assert (T_Size <= 64);
- Swap_RE := RE_Bswap_64;
end if;
- Swap_F := RTE (Swap_RE);
- Swap_T := Etype (Swap_F);
Shift := Esize (Swap_T) - T_Size;
Arg := RJ_Unchecked_Convert_To (Swap_T, N);
- if Left_Justify and then Shift > Uint_0 then
+ if not Bytes_Big_Endian and then Shift > Uint_0 then
Arg :=
Make_Op_Shift_Left (Loc,
Left_Opnd => Arg,
Right_Opnd => Make_Integer_Literal (Loc, Shift));
end if;
- Swapped :=
- Make_Function_Call (Loc,
- Name => New_Occurrence_Of (Swap_F, Loc),
- Parameter_Associations => New_List (Arg));
-
- if Right_Justify and then Shift > Uint_0 then
- Swapped :=
- Make_Op_Shift_Right (Loc,
- Left_Opnd => Swapped,
- Right_Opnd => Make_Integer_Literal (Loc, Shift));
+ if Present (Swap_F) then
+ Adjusted :=
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Swap_F, Loc),
+ Parameter_Associations => New_List (Arg));
+ else
+ Adjusted := Arg;
end if;
- Set_Etype (Swapped, Swap_T);
- return Swapped;
- end Byte_Swap;
+ Set_Etype (Adjusted, Swap_T);
+ return Adjusted;
+ end Revert_Storage_Order;
------------------------------
-- Compute_Linear_Subscript --
@@ -2085,15 +2087,10 @@ package body Exp_Pakd is
-- it back to its expected endianness after extraction.
if Reverse_Storage_Order (Atyp)
- and then Esize (Atyp) > 8
and then (Is_Record_Type (Ctyp) or else Is_Array_Type (Ctyp))
and then Reverse_Storage_Order (Ctyp)
then
- Arg :=
- Byte_Swap
- (Arg,
- Left_Justify => not Bytes_Big_Endian,
- Right_Justify => False);
+ Arg := Revert_Storage_Order (Arg);
end if;
-- We needed to analyze this before we do the unchecked convert
diff --git a/gcc/ada/fe.h b/gcc/ada/fe.h
index 3d670dc7bc3..f5554f866a1 100644
--- a/gcc/ada/fe.h
+++ b/gcc/ada/fe.h
@@ -56,8 +56,7 @@ extern char Fold_Lower[], Fold_Upper[];
extern Boolean Debug_Flag_NN;
/* einfo: We will be setting Esize for types, Component_Bit_Offset for fields,
- Alignment for types and objects, Component_Size for array types, and
- Present_Expr for N_Variant nodes. */
+ Alignment for types and objects, Component_Size for array types. */
#define Set_Alignment einfo__set_alignment
#define Set_Component_Bit_Offset einfo__set_component_bit_offset
@@ -65,7 +64,6 @@ extern Boolean Debug_Flag_NN;
#define Set_Esize einfo__set_esize
#define Set_Mechanism einfo__set_mechanism
#define Set_RM_Size einfo__set_rm_size
-#define Set_Present_Expr sinfo__set_present_expr
extern void Set_Alignment (Entity_Id, Uint);
extern void Set_Component_Bit_Offset (Entity_Id, Uint);
@@ -73,7 +71,6 @@ extern void Set_Component_Size (Entity_Id, Uint);
extern void Set_Esize (Entity_Id, Uint);
extern void Set_Mechanism (Entity_Id, Mechanism_Type);
extern void Set_RM_Size (Entity_Id, Uint);
-extern void Set_Present_Expr (Node_Id, Uint);
#define Is_Entity_Name einfo__is_entity_name
extern Boolean Is_Entity_Name (Node_Id);
@@ -253,11 +250,15 @@ extern Node_Id First_Actual (Node_Id);
extern Node_Id Next_Actual (Node_Id);
extern Boolean Requires_Transient_Scope (Entity_Id);
-/* sinfo: These functions aren't in sinfo.h since we don't make the
- setting functions, just the retrieval functions. */
+/* sinfo: */
-#define Set_Has_No_Elaboration_Code sinfo__set_has_no_elaboration_code
+#define End_Location sinfo__end_location
+#define Set_Has_No_Elaboration_Code sinfo__set_has_no_elaboration_code
+#define Set_Present_Expr sinfo__set_present_expr
+
+extern Source_Ptr End_Location (Node_Id);
extern void Set_Has_No_Elaboration_Code (Node_Id, Boolean);
+extern void Set_Present_Expr (Node_Id, Uint);
/* targparm: */
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index 73717239033..e091cea3076 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -50,7 +50,6 @@ with Sem_Cat; use Sem_Cat;
with Sem_Ch6; use Sem_Ch6;
with Sem_Ch7; use Sem_Ch7;
with Sem_Ch8; use Sem_Ch8;
-with Sem_Ch9; use Sem_Ch9;
with Sem_Ch13; use Sem_Ch13;
with Sem_Eval; use Sem_Eval;
with Sem_Mech; use Sem_Mech;
@@ -91,16 +90,19 @@ package body Freeze is
-- performed only after the object has been frozen.
procedure Check_Component_Storage_Order
- (Encl_Type : Entity_Id;
- Comp : Entity_Id;
- ADC : Node_Id);
+ (Encl_Type : Entity_Id;
+ Comp : Entity_Id;
+ ADC : Node_Id;
+ Comp_ADC_Present : out Boolean);
-- For an Encl_Type that has a Scalar_Storage_Order attribute definition
-- clause, verify that the component type has an explicit and compatible
-- attribute/aspect. For arrays, Comp is Empty; for records, it is the
-- entity of the component under consideration. For an Encl_Type that
-- does not have a Scalar_Storage_Order attribute definition clause,
-- verify that the component also does not have such a clause.
- -- ADC is the attribute definition clause if present (or Empty).
+ -- ADC is the attribute definition clause if present (or Empty). On return,
+ -- Comp_ADC_Present is set True if the component has a Scalar_Storage_Order
+ -- attribute definition clause.
procedure Check_Strict_Alignment (E : Entity_Id);
-- E is a base type. If E is tagged or has a component that is aliased
@@ -1071,9 +1073,10 @@ package body Freeze is
-----------------------------------
procedure Check_Component_Storage_Order
- (Encl_Type : Entity_Id;
- Comp : Entity_Id;
- ADC : Node_Id)
+ (Encl_Type : Entity_Id;
+ Comp : Entity_Id;
+ ADC : Node_Id;
+ Comp_ADC_Present : out Boolean)
is
Comp_Type : Entity_Id;
Comp_ADC : Node_Id;
@@ -1125,12 +1128,13 @@ package body Freeze is
Comp_ADC := Get_Attribute_Definition_Clause
(First_Subtype (Comp_Type),
Attribute_Scalar_Storage_Order);
+ Comp_ADC_Present := Present (Comp_ADC);
-- Case of enclosing type not having explicit SSO: component cannot
-- have it either.
if No (ADC) then
- if Present (Comp_ADC) then
+ if Comp_ADC_Present then
Error_Msg_N
("composite type must have explicit scalar storage order",
Err_Node);
@@ -2351,14 +2355,19 @@ package body Freeze is
-- Check for scalar storage order
- Check_Component_Storage_Order
- (Encl_Type => Arr,
- Comp => Empty,
- ADC => Get_Attribute_Definition_Clause
- (First_Subtype (Arr),
- Attribute_Scalar_Storage_Order));
+ declare
+ Dummy : Boolean;
+ begin
+ Check_Component_Storage_Order
+ (Encl_Type => Arr,
+ Comp => Empty,
+ ADC => Get_Attribute_Definition_Clause
+ (First_Subtype (Arr),
+ Attribute_Scalar_Storage_Order),
+ Comp_ADC_Present => Dummy);
+ end;
- -- Processing that is done only for subtypes
+ -- Processing that is done only for subtypes
else
-- Acquire alignment from base type
@@ -2550,8 +2559,8 @@ package body Freeze is
procedure Freeze_Record_Type (Rec : Entity_Id) is
Comp : Entity_Id;
IR : Node_Id;
- ADC : Node_Id;
Prev : Entity_Id;
+ ADC : Node_Id;
Junk : Boolean;
pragma Warnings (Off, Junk);
@@ -2561,6 +2570,9 @@ package body Freeze is
-- stack. Needed for the analysis of delayed aspects specified to the
-- components of Rec.
+ SSO_ADC : Node_Id;
+ -- Scalar_Storage_Order attribute definition clause for the record
+
Unplaced_Component : Boolean := False;
-- Set True if we find at least one component with no component
-- clause (used to warn about useless Pack pragmas).
@@ -2575,6 +2587,10 @@ package body Freeze is
-- is used to prevent Implicit_Packing of the record, since packing
-- cannot modify the size of alignment of an aliased component.
+ SSO_ADC_Component : Boolean := False;
+ -- Set True if we find at least one component whose type has a
+ -- Scalar_Storage_Order attribute definition clause.
+
All_Scalar_Components : Boolean := True;
-- Set False if we encounter a component of a non-scalar type
@@ -3015,56 +3031,80 @@ package body Freeze is
Next_Entity (Comp);
end loop;
- ADC := Get_Attribute_Definition_Clause
- (Rec, Attribute_Scalar_Storage_Order);
+ SSO_ADC := Get_Attribute_Definition_Clause
+ (Rec, Attribute_Scalar_Storage_Order);
- if Present (ADC) then
+ -- Check consistent attribute setting on component types
+
+ declare
+ Comp_ADC_Present : Boolean;
+ begin
+ Comp := First_Component (Rec);
+ while Present (Comp) loop
+ Check_Component_Storage_Order
+ (Encl_Type => Rec,
+ Comp => Comp,
+ ADC => SSO_ADC,
+ Comp_ADC_Present => Comp_ADC_Present);
+ SSO_ADC_Component := SSO_ADC_Component or Comp_ADC_Present;
+ Next_Component (Comp);
+ end loop;
+ end;
+
+ if Present (SSO_ADC) then
-- Check compatibility of Scalar_Storage_Order with Bit_Order, if
-- the former is specified.
if Reverse_Bit_Order (Rec) /= Reverse_Storage_Order (Rec) then
- -- Note: report error on Rec, not on ADC, as ADC may apply to
- -- an ancestor type.
+ -- Note: report error on Rec, not on SSO_ADC, as ADC may apply
+ -- to some ancestor type.
- Error_Msg_Sloc := Sloc (ADC);
+ Error_Msg_Sloc := Sloc (SSO_ADC);
Error_Msg_N
("scalar storage order for& specified# inconsistent with "
& "bit order", Rec);
end if;
- -- Warn if there is a Scalar_Storage_Order but no component clause
- -- (or pragma Pack).
+ -- Warn if there is an Scalar_Storage_Order attribute definition
+ -- clause but no component clause, no component that itself has
+ -- such an attribute definition, and no pragma Pack.
- if not (Placed_Component or else Is_Packed (Rec)) then
+ if not (Placed_Component
+ or else
+ SSO_ADC_Component
+ or else
+ Is_Packed (Rec))
+ then
Error_Msg_N
("??scalar storage order specified but no component clause",
- ADC);
+ SSO_ADC);
end if;
end if;
- -- Check consistent attribute setting on component types
-
- Comp := First_Component (Rec);
- while Present (Comp) loop
- Check_Component_Storage_Order
- (Encl_Type => Rec, Comp => Comp, ADC => ADC);
- Next_Component (Comp);
- end loop;
-
- -- Deal with Bit_Order aspect specifying a non-default bit order
+ -- Deal with Bit_Order aspect
ADC := Get_Attribute_Definition_Clause (Rec, Attribute_Bit_Order);
if Present (ADC) and then Base_Type (Rec) = Rec then
- if not (Placed_Component or else Is_Packed (Rec)) then
+ if not (Placed_Component
+ or else
+ Present (SSO_ADC)
+ or else
+ Is_Packed (Rec))
+ then
+ -- Warn if clause has no effect when no component clause is
+ -- present, but suppress warning if the Bit_Order is required
+ -- due to the presence of a Scalar_Storage_Order attribute.
+
Error_Msg_N
("??bit order specification has no effect", ADC);
Error_Msg_N
("\??since no component clauses were specified", ADC);
- -- Here is where we do the processing for reversed bit order
+ -- Here is where we do the processing to adjust component clauses
+ -- for reversed bit order.
elsif Reverse_Bit_Order (Rec)
and then not Reverse_Storage_Order (Rec)
@@ -3315,6 +3355,45 @@ package body Freeze is
end if;
end if;
+ -- The following checks are only relevant when SPARK_Mode is on as
+ -- they are not standard Ada legality rules.
+
+ if SPARK_Mode = On then
+ if Is_SPARK_Volatile (Rec) then
+
+ -- A discriminated type cannot be volatile (SPARK RM C.6(4))
+
+ if Has_Discriminants (Rec) then
+ Error_Msg_N ("discriminated type & cannot be volatile", Rec);
+
+ -- A tagged type cannot be volatile (SPARK RM C.6(5))
+
+ elsif Is_Tagged_Type (Rec) then
+ Error_Msg_N ("tagged type & cannot be volatile", Rec);
+ end if;
+
+ -- A non-volatile record type cannot contain volatile components
+ -- (SPARK RM C.6(2)). The check is performed at freeze point
+ -- because the volatility status of the record type and its
+ -- components is clearly known.
+
+ else
+ Comp := First_Component (Rec);
+ while Present (Comp) loop
+ if Comes_From_Source (Comp)
+ and then Is_SPARK_Volatile (Comp)
+ then
+ Error_Msg_Name_1 := Chars (Rec);
+ Error_Msg_N
+ ("component & of non-volatile record type % cannot be "
+ & "volatile", Comp);
+ end if;
+
+ Next_Component (Comp);
+ end loop;
+ end if;
+ end if;
+
-- All done if not a full record definition
if Ekind (Rec) /= E_Record_Type then
diff --git a/gcc/ada/g-dyntab.adb b/gcc/ada/g-dyntab.adb
index 634bbbbb4e8..e5e41c927a0 100644
--- a/gcc/ada/g-dyntab.adb
+++ b/gcc/ada/g-dyntab.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2000-2013, AdaCore --
+-- Copyright (C) 2000-2014, AdaCore --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -187,13 +187,24 @@ package body GNAT.Dynamic_Tables is
begin
if T.P.Max < T.P.Last_Val then
+
+ -- Now increment table length until it is sufficiently large. Use
+ -- the increment value or 10, which ever is larger (the reason
+ -- for the use of 10 here is to ensure that the table does really
+ -- increase in size (which would not be the case for a table of
+ -- length 10 increased by 3% for instance). Do the intermediate
+ -- calculation in Long_Long_Integer to avoid overflow.
+
while T.P.Max < T.P.Last_Val loop
- New_Length := T.P.Length * (100 + Table_Increment) / 100;
+ New_Length :=
+ Integer
+ (Long_Long_Integer (T.P.Length) *
+ (100 + Long_Long_Integer (Table_Increment)) / 100);
if New_Length > T.P.Length then
T.P.Length := New_Length;
else
- T.P.Length := T.P.Length + 1;
+ T.P.Length := T.P.Length + 10;
end if;
T.P.Max := Min + T.P.Length - 1;
diff --git a/gcc/ada/g-socket.adb b/gcc/ada/g-socket.adb
index d5b74c6d049..ee4d52a4cca 100644
--- a/gcc/ada/g-socket.adb
+++ b/gcc/ada/g-socket.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2001-2013, AdaCore --
+-- Copyright (C) 2001-2014, AdaCore --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -244,13 +244,6 @@ package body GNAT.Sockets is
(Stream : in out Stream_Socket_Stream_Type;
Item : Ada.Streams.Stream_Element_Array);
- procedure Stream_Write
- (Socket : Socket_Type;
- Item : Ada.Streams.Stream_Element_Array;
- To : access Sock_Addr_Type);
- -- Common implementation for the Write operation of Datagram_Socket_Stream_
- -- Type and Stream_Socket_Stream_Type.
-
procedure Wait_On_Socket
(Socket : Socket_Type;
For_Read : Boolean;
@@ -1732,27 +1725,12 @@ package body GNAT.Sockets is
Item : out Ada.Streams.Stream_Element_Array;
Last : out Ada.Streams.Stream_Element_Offset)
is
- First : Ada.Streams.Stream_Element_Offset := Item'First;
- Index : Ada.Streams.Stream_Element_Offset := First - 1;
- Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
-
begin
- loop
- Receive_Socket
- (Stream.Socket,
- Item (First .. Max),
- Index,
- Stream.From);
-
- Last := Index;
-
- -- Exit when all or zero data received. Zero means that the socket
- -- peer is closed.
-
- exit when Index < First or else Index = Max;
-
- First := Index + 1;
- end loop;
+ Receive_Socket
+ (Stream.Socket,
+ Item,
+ Last,
+ Stream.From);
end Read;
----------
@@ -2419,43 +2397,6 @@ package body GNAT.Sockets is
return Stream_Access (S);
end Stream;
- ------------------
- -- Stream_Write --
- ------------------
-
- procedure Stream_Write
- (Socket : Socket_Type;
- Item : Ada.Streams.Stream_Element_Array;
- To : access Sock_Addr_Type)
- is
- First : Ada.Streams.Stream_Element_Offset;
- Index : Ada.Streams.Stream_Element_Offset;
- Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
-
- begin
- First := Item'First;
- Index := First - 1;
- while First <= Max loop
- Send_Socket (Socket, Item (First .. Max), Index, To);
-
- -- Exit when all or zero data sent. Zero means that the socket has
- -- been closed by peer.
-
- exit when Index < First or else Index = Max;
-
- First := Index + 1;
- end loop;
-
- -- For an empty array, we have First > Max, and hence Index >= Max (no
- -- error, the loop above is never executed). After a successful send,
- -- Index = Max. The only remaining case, Index < Max, is therefore
- -- always an actual send failure.
-
- if Index < Max then
- Raise_Socket_Error (Socket_Errno);
- end if;
- end Stream_Write;
-
----------
-- To_C --
----------
@@ -2695,8 +2636,20 @@ package body GNAT.Sockets is
(Stream : in out Datagram_Socket_Stream_Type;
Item : Ada.Streams.Stream_Element_Array)
is
+ Last : Stream_Element_Offset;
+
begin
- Stream_Write (Stream.Socket, Item, To => Stream.To'Unrestricted_Access);
+ Send_Socket
+ (Stream.Socket,
+ Item,
+ Last,
+ Stream.To);
+
+ -- It is an error if not all of the data has been sent
+
+ if Last /= Item'Last then
+ Raise_Socket_Error (Socket_Errno);
+ end if;
end Write;
-----------
@@ -2707,8 +2660,32 @@ package body GNAT.Sockets is
(Stream : in out Stream_Socket_Stream_Type;
Item : Ada.Streams.Stream_Element_Array)
is
+ First : Ada.Streams.Stream_Element_Offset;
+ Index : Ada.Streams.Stream_Element_Offset;
+ Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
+
begin
- Stream_Write (Stream.Socket, Item, To => null);
+ First := Item'First;
+ Index := First - 1;
+ while First <= Max loop
+ Send_Socket (Stream.Socket, Item (First .. Max), Index, null);
+
+ -- Exit when all or zero data sent. Zero means that the socket has
+ -- been closed by peer.
+
+ exit when Index < First or else Index = Max;
+
+ First := Index + 1;
+ end loop;
+
+ -- For an empty array, we have First > Max, and hence Index >= Max (no
+ -- error, the loop above is never executed). After a successful send,
+ -- Index = Max. The only remaining case, Index < Max, is therefore
+ -- always an actual send failure.
+
+ if Index < Max then
+ Raise_Socket_Error (Socket_Errno);
+ end if;
end Write;
Sockets_Library_Controller_Object : Sockets_Library_Controller;
diff --git a/gcc/ada/g-table.adb b/gcc/ada/g-table.adb
index 9b3692bbe06..e12e84f7578 100644
--- a/gcc/ada/g-table.adb
+++ b/gcc/ada/g-table.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1998-2013, AdaCore --
+-- Copyright (C) 1998-2014, AdaCore --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -196,21 +196,25 @@ package body GNAT.Table is
----------------
procedure Reallocate is
- New_Size : size_t;
+ New_Size : size_t;
+ New_Length : Long_Long_Integer;
begin
if Max < Last_Val then
pragma Assert (not Locked);
- while Max < Last_Val loop
-
- -- Increase length using the table increment factor, but make
- -- sure that we add at least ten elements (this avoids a loop
- -- for silly small increment values)
+ -- Now increment table length until it is sufficiently large. Use
+ -- the increment value or 10, which ever is larger (the reason
+ -- for the use of 10 here is to ensure that the table does really
+ -- increase in size (which would not be the case for a table of
+ -- length 10 increased by 3% for instance). Do the intermediate
+ -- calculation in Long_Long_Integer to avoid overflow.
- Length := Integer'Max
- (Length * (100 + Table_Increment) / 100,
- Length + 10);
+ while Max < Last_Val loop
+ New_Length :=
+ Long_Long_Integer (Length) *
+ (100 + Long_Long_Integer (Table_Increment)) / 100;
+ Length := Integer'Max (Integer (New_Length), Length + 10);
Max := Min + Length - 1;
end loop;
end if;
diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
index 5ea386f860c..d43eefa004e 100644
--- a/gcc/ada/gcc-interface/ada-tree.h
+++ b/gcc/ada/gcc-interface/ada-tree.h
@@ -32,13 +32,9 @@ union GTY((desc ("0"),
desc ("tree_node_structure (&%h)"))) generic;
};
-/* Ada uses the lang_decl and lang_type fields to hold a tree.
-
- FIXME: the variable_size annotation here is needed because these types are
- variable-sized in some other front-ends. Due to gengtype deficiency, the
- GTY options of such types have to agree across all front-ends. */
-struct GTY((variable_size)) lang_type { tree t; };
-struct GTY((variable_size)) lang_decl { tree t; };
+/* Ada uses the lang_decl and lang_type fields to hold a tree. */
+struct GTY(()) lang_type { tree t; };
+struct GTY(()) lang_decl { tree t; };
/* Macros to get and set the tree in TYPE_LANG_SPECIFIC. */
#define GET_TYPE_LANG_SPECIFIC(NODE) \
@@ -49,7 +45,7 @@ do { \
tree tmp = (X); \
if (!TYPE_LANG_SPECIFIC (NODE)) \
TYPE_LANG_SPECIFIC (NODE) \
- = ggc_alloc_lang_type (sizeof (struct lang_type)); \
+ = ggc_alloc<struct lang_type> (); \
TYPE_LANG_SPECIFIC (NODE)->t = tmp; \
} while (0)
@@ -62,7 +58,7 @@ do { \
tree tmp = (X); \
if (!DECL_LANG_SPECIFIC (NODE)) \
DECL_LANG_SPECIFIC (NODE) \
- = ggc_alloc_lang_decl (sizeof (struct lang_decl)); \
+ = ggc_alloc<struct lang_decl> (); \
DECL_LANG_SPECIFIC (NODE)->t = tmp; \
} while (0)
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 6d0b8b25038..d448430e466 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -145,6 +145,7 @@ static tree gnat_to_gnu_component_type (Entity_Id, bool, bool);
static tree gnat_to_gnu_param (Entity_Id, Mechanism_Type, Entity_Id, bool,
bool *);
static tree gnat_to_gnu_field (Entity_Id, tree, int, bool, bool);
+static tree change_qualified_type (tree, int);
static bool same_discriminant_p (Entity_Id, Entity_Id);
static bool array_type_has_nonaliased_component (tree, Entity_Id);
static bool compile_time_known_address_p (Node_Id);
@@ -543,10 +544,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
This is a workaround for major problems in protected type
handling. */
Entity_Id Scop = Scope (Scope (gnat_entity));
- if ((Is_Protected_Type (Scop)
- || (Is_Private_Type (Scop)
- && Present (Full_View (Scop))
- && Is_Protected_Type (Full_View (Scop))))
+ if (Is_Protected_Type (Underlying_Type (Scop))
&& Present (Original_Record_Component (gnat_entity)))
{
gnu_decl
@@ -870,9 +868,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
/* If this is an aliased object with an unconstrained nominal subtype,
make a type that includes the template. */
if (Is_Constr_Subt_For_UN_Aliased (Etype (gnat_entity))
- && (Is_Array_Type (Etype (gnat_entity))
- || (Is_Private_Type (Etype (gnat_entity))
- && Is_Array_Type (Full_View (Etype (gnat_entity)))))
+ && Is_Array_Type (Underlying_Type (Etype (gnat_entity)))
&& !type_annotate_only)
{
tree gnu_array
@@ -1052,9 +1048,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
Note that we need to preserve the volatility of the renamed
object through the indirection. */
if (TREE_THIS_VOLATILE (gnu_expr) && !TYPE_VOLATILE (gnu_type))
- gnu_type = build_qualified_type (gnu_type,
- (TYPE_QUALS (gnu_type)
- | TYPE_QUAL_VOLATILE));
+ gnu_type
+ = change_qualified_type (gnu_type, TYPE_QUAL_VOLATILE);
gnu_type = build_reference_type (gnu_type);
inner_const_flag = TREE_READONLY (gnu_expr);
const_flag = true;
@@ -1112,9 +1107,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
|| imported_p
|| Present (Address_Clause (gnat_entity)))))
&& !TYPE_VOLATILE (gnu_type))
- gnu_type = build_qualified_type (gnu_type,
- (TYPE_QUALS (gnu_type)
- | TYPE_QUAL_VOLATILE));
+ gnu_type = change_qualified_type (gnu_type, TYPE_QUAL_VOLATILE);
/* If we are defining an aliased object whose nominal subtype is
unconstrained, the object is a record that contains both the
@@ -1383,9 +1376,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
Note that we have to do that this late because of the couple of
allocation adjustments that might be made just above. */
if (Is_Constr_Subt_For_UN_Aliased (Etype (gnat_entity))
- && (Is_Array_Type (Etype (gnat_entity))
- || (Is_Private_Type (Etype (gnat_entity))
- && Is_Array_Type (Full_View (Etype (gnat_entity)))))
+ && Is_Array_Type (Underlying_Type (Etype (gnat_entity)))
&& !type_annotate_only)
{
tree gnu_array
@@ -1415,8 +1406,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
}
if (const_flag)
- gnu_type = build_qualified_type (gnu_type, (TYPE_QUALS (gnu_type)
- | TYPE_QUAL_CONST));
+ gnu_type = change_qualified_type (gnu_type, TYPE_QUAL_CONST);
/* Convert the expression to the type of the object except in the
case where the object's type is unconstrained or the object's type
@@ -2250,6 +2240,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
SET_TYPE_MODE (tem, BLKmode);
}
+ TYPE_VOLATILE (tem) = Treat_As_Volatile (gnat_entity);
+
/* If an alignment is specified, use it if valid. But ignore it
for the original type of packed array types. If the alignment
was requested with an explicit alignment clause, state so. */
@@ -2420,8 +2412,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
we can just use the high bound of the index type. */
else if ((Nkind (gnat_index) == N_Range
&& cannot_be_superflat_p (gnat_index))
- /* Packed Array Types are never superflat. */
- || Is_Packed_Array_Type (gnat_entity))
+ /* Bit-Packed Array Types are never superflat. */
+ || (Is_Packed_Array_Type (gnat_entity)
+ && Is_Bit_Packed_Array
+ (Original_Array_Type (gnat_entity))))
gnu_high = gnu_max;
/* Otherwise, if the high bound is constant but the low bound is
@@ -2600,6 +2594,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
SET_TYPE_MODE (gnu_type, BLKmode);
}
+ TYPE_VOLATILE (gnu_type) = Treat_As_Volatile (gnat_entity);
+
/* Attach the TYPE_STUB_DECL in case we have a parallel type. */
TYPE_STUB_DECL (gnu_type)
= create_type_stub_decl (gnu_entity_name, gnu_type);
@@ -2730,9 +2726,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
process_attributes (&gnu_type, &attr_list, false, gnat_entity);
if (Treat_As_Volatile (gnat_entity))
gnu_type
- = build_qualified_type (gnu_type,
- TYPE_QUALS (gnu_type)
- | TYPE_QUAL_VOLATILE);
+ = change_qualified_type (gnu_type, TYPE_QUAL_VOLATILE);
/* Make it artificial only if the base type was artificial too.
That's sort of "morally" true and will make it possible for
the debugger to look it up by name in DWARF, which is needed
@@ -2840,7 +2834,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
= build_binary_op (PLUS_EXPR, gnu_string_index_type,
gnu_lower_bound,
int_const_binop (MINUS_EXPR, gnu_length,
- integer_one_node));
+ convert (gnu_string_index_type,
+ integer_one_node)));
tree gnu_index_type
= create_index_type (convert (sizetype, gnu_lower_bound),
convert (sizetype, gnu_upper_bound),
@@ -3222,9 +3217,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
&& Is_By_Reference_Type (gnat_entity))
SET_TYPE_MODE (gnu_type, BLKmode);
- /* We used to remove the associations of the discriminants and _Parent
- for validity checking but we may need them if there's a Freeze_Node
- for a subtype used in this record. */
TYPE_VOLATILE (gnu_type) = Treat_As_Volatile (gnat_entity);
/* Fill in locations of fields. */
@@ -3921,9 +3913,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
&& TREE_CODE (gnu_desig_type) != UNCONSTRAINED_ARRAY_TYPE)
{
gnu_desig_type
- = build_qualified_type
- (gnu_desig_type,
- TYPE_QUALS (gnu_desig_type) | TYPE_QUAL_CONST);
+ = change_qualified_type (gnu_desig_type, TYPE_QUAL_CONST);
/* Some extra processing is required if we are building a
pointer to an incomplete type (in the GCC sense). We might
@@ -4627,18 +4617,17 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
if (TREE_CODE (gnu_return_type) == VOID_TYPE)
const_flag = false;
- gnu_type
- = build_qualified_type (gnu_type,
- TYPE_QUALS (gnu_type)
- | (TYPE_QUAL_CONST * const_flag)
- | (TYPE_QUAL_VOLATILE * volatile_flag));
+ if (const_flag || volatile_flag)
+ {
+ const int quals
+ = (const_flag ? TYPE_QUAL_CONST : 0)
+ | (volatile_flag ? TYPE_QUAL_VOLATILE : 0);
- if (has_stub)
- gnu_stub_type
- = build_qualified_type (gnu_stub_type,
- TYPE_QUALS (gnu_stub_type)
- | (TYPE_QUAL_CONST * const_flag)
- | (TYPE_QUAL_VOLATILE * volatile_flag));
+ gnu_type = change_qualified_type (gnu_type, quals);
+
+ if (has_stub)
+ gnu_stub_type = change_qualified_type (gnu_stub_type, quals);
+ }
/* If we have a builtin decl for that function, use it. Check if the
profiles are compatible and warn if they are not. The checker is
@@ -4904,8 +4893,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnu_size = NULL_TREE;
}
- /* If the alignment hasn't already been processed and this is
- not an unconstrained array, see if an alignment is specified.
+ /* If the alignment has not already been processed and this is not
+ an unconstrained array type, see if an alignment is specified.
If not, we pick a default alignment for atomic objects. */
if (align != 0 || TREE_CODE (gnu_type) == UNCONSTRAINED_ARRAY_TYPE)
;
@@ -5092,19 +5081,21 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
}
}
- if (Treat_As_Volatile (gnat_entity))
- gnu_type
- = build_qualified_type (gnu_type,
- TYPE_QUALS (gnu_type) | TYPE_QUAL_VOLATILE);
-
if (Is_Atomic (gnat_entity))
check_ok_for_atomic (gnu_type, gnat_entity, false);
- if (Present (Alignment_Clause (gnat_entity)))
- TYPE_USER_ALIGN (gnu_type) = 1;
+ /* If this is not an unconstrained array type, set some flags. */
+ if (TREE_CODE (gnu_type) != UNCONSTRAINED_ARRAY_TYPE)
+ {
+ if (Treat_As_Volatile (gnat_entity))
+ gnu_type = change_qualified_type (gnu_type, TYPE_QUAL_VOLATILE);
- if (Universal_Aliasing (gnat_entity))
- TYPE_UNIVERSAL_ALIASING_P (TYPE_MAIN_VARIANT (gnu_type)) = 1;
+ if (Present (Alignment_Clause (gnat_entity)))
+ TYPE_USER_ALIGN (gnu_type) = 1;
+
+ if (Universal_Aliasing (gnat_entity))
+ TYPE_UNIVERSAL_ALIASING_P (TYPE_MAIN_VARIANT (gnu_type)) = 1;
+ }
if (!gnu_decl)
gnu_decl = create_type_decl (gnu_entity_name, gnu_type,
@@ -5652,9 +5643,7 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition,
}
if (Has_Volatile_Components (gnat_array))
- gnu_type
- = build_qualified_type (gnu_type,
- TYPE_QUALS (gnu_type) | TYPE_QUAL_VOLATILE);
+ gnu_type = change_qualified_type (gnu_type, TYPE_QUAL_VOLATILE);
return gnu_type;
}
@@ -5712,9 +5701,7 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech,
if (ro_param
&& TREE_CODE (gnu_param_type) != UNCONSTRAINED_ARRAY_TYPE
&& !CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_param_type)))
- gnu_param_type = build_qualified_type (gnu_param_type,
- (TYPE_QUALS (gnu_param_type)
- | TYPE_QUAL_CONST));
+ gnu_param_type = change_qualified_type (gnu_param_type, TYPE_QUAL_CONST);
/* For foreign conventions, pass arrays as pointers to the element type.
First check for unconstrained array and get the underlying array. */
@@ -5764,9 +5751,8 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech,
gnu_param_type = TREE_TYPE (gnu_param_type);
if (ro_param)
- gnu_param_type = build_qualified_type (gnu_param_type,
- (TYPE_QUALS (gnu_param_type)
- | TYPE_QUAL_CONST));
+ gnu_param_type
+ = change_qualified_type (gnu_param_type, TYPE_QUAL_CONST);
gnu_param_type = build_pointer_type (gnu_param_type);
}
@@ -5803,7 +5789,7 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech,
gnu_param_type = build_reference_type (gnu_param_type);
if (restrict_p)
gnu_param_type
- = build_qualified_type (gnu_param_type, TYPE_QUAL_RESTRICT);
+ = change_qualified_type (gnu_param_type, TYPE_QUAL_RESTRICT);
by_ref = true;
}
@@ -5869,6 +5855,15 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech,
return gnu_param;
}
+/* Like build_qualified_type, but TYPE_QUALS is added to the existing
+ qualifiers on TYPE. */
+
+static tree
+change_qualified_type (tree type, int type_quals)
+{
+ return build_qualified_type (type, TYPE_QUALS (type) | type_quals);
+}
+
/* Return true if DISCR1 and DISCR2 represent the same discriminant. */
static bool
@@ -7515,15 +7510,16 @@ annotate_value (tree gnu_size)
case BIT_AND_EXPR:
tcode = Bit_And_Expr;
- /* For negative values, build NEGATE_EXPR of the opposite. Such values
- appear in expressions containing aligning patterns. Note that, since
- sizetype is unsigned, we have to jump through some hoops. */
+ /* For negative values in sizetype, build NEGATE_EXPR of the opposite.
+ Such values appear in expressions with aligning patterns. Note that,
+ since sizetype is unsigned, we have to jump through some hoops. */
if (TREE_CODE (TREE_OPERAND (gnu_size, 1)) == INTEGER_CST)
{
tree op1 = TREE_OPERAND (gnu_size, 1);
- if (wi::neg_p (op1))
+ wide_int signed_op1 = wi::sext (op1, TYPE_PRECISION (sizetype));
+ if (wi::neg_p (signed_op1))
{
- op1 = wide_int_to_tree (sizetype, wi::neg (op1));
+ op1 = wide_int_to_tree (sizetype, wi::neg (signed_op1));
pre_op1 = annotate_value (build1 (NEGATE_EXPR, sizetype, op1));
}
}
@@ -7576,7 +7572,7 @@ annotate_value (tree gnu_size)
h = (struct tree_int_map **)
htab_find_slot (annotate_value_cache, &in, INSERT);
gcc_assert (!*h);
- *h = ggc_alloc_tree_int_map ();
+ *h = ggc_alloc<tree_int_map> ();
(*h)->base.from = gnu_size;
(*h)->to = ret;
}
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 11b89825c23..cd01d4d2420 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -2000,7 +2000,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
if (!pa)
{
- pa = ggc_alloc_cleared_parm_attr_d ();
+ pa = ggc_cleared_alloc<parm_attr_d> ();
pa->id = gnat_param;
pa->dim = Dimension;
vec_safe_push (f_parm_attr_cache, pa);
@@ -2384,8 +2384,7 @@ Case_Statement_to_gnu (Node_Id gnat_node)
/* We build a SWITCH_EXPR that contains the code with interspersed
CASE_LABEL_EXPRs for each label. */
- if (!Sloc_to_locus (Sloc (gnat_node) + UI_To_Int (End_Span (gnat_node)),
- &end_locus))
+ if (!Sloc_to_locus (End_Location (gnat_node), &end_locus))
end_locus = input_location;
gnu_label = create_artificial_label (end_locus);
start_stmt_group ();
@@ -2522,7 +2521,7 @@ push_range_check_info (tree var)
if (iter)
{
- struct range_check_info_d *rci = ggc_alloc_range_check_info_d ();
+ struct range_check_info_d *rci = ggc_alloc<range_check_info_d> ();
vec_safe_push (iter->checks, rci);
return rci;
}
@@ -2600,7 +2599,7 @@ static tree
Loop_Statement_to_gnu (Node_Id gnat_node)
{
const Node_Id gnat_iter_scheme = Iteration_Scheme (gnat_node);
- struct loop_info_d *gnu_loop_info = ggc_alloc_cleared_loop_info_d ();
+ struct loop_info_d *gnu_loop_info = ggc_cleared_alloc<loop_info_d> ();
tree gnu_loop_stmt = build4 (LOOP_STMT, void_type_node, NULL_TREE,
NULL_TREE, NULL_TREE, NULL_TREE);
tree gnu_loop_label = create_artificial_label (input_location);
@@ -3575,6 +3574,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
/* The entry in the CI_CO_LIST that represents a function return, if any. */
tree gnu_return_var_elmt = NULL_TREE;
tree gnu_result;
+ location_t locus;
struct language_function *gnu_subprog_language;
vec<parm_attr, va_gc> *cache;
@@ -3611,14 +3611,15 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
relayout_decl (gnu_result_decl);
}
- /* Set the line number in the decl to correspond to that of the body so that
- the line number notes are written correctly. */
- Sloc_to_locus (Sloc (gnat_node), &DECL_SOURCE_LOCATION (gnu_subprog_decl));
+ /* Set the line number in the decl to correspond to that of the body. */
+ Sloc_to_locus (Sloc (gnat_node), &locus);
+ DECL_SOURCE_LOCATION (gnu_subprog_decl) = locus;
/* Initialize the information structure for the function. */
allocate_struct_function (gnu_subprog_decl, false);
- gnu_subprog_language = ggc_alloc_cleared_language_function ();
+ gnu_subprog_language = ggc_cleared_alloc<language_function> ();
DECL_STRUCT_FUNCTION (gnu_subprog_decl)->language = gnu_subprog_language;
+ DECL_STRUCT_FUNCTION (gnu_subprog_decl)->function_start_locus = locus;
set_cfun (NULL);
begin_subprog_body (gnu_subprog_decl);
@@ -4269,9 +4270,7 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
if (TREE_CODE (TREE_TYPE (gnu_actual)) == RECORD_TYPE
&& TYPE_CONTAINS_TEMPLATE_P (TREE_TYPE (gnu_actual))
&& Is_Constr_Subt_For_UN_Aliased (Etype (gnat_actual))
- && (Is_Array_Type (Etype (gnat_actual))
- || (Is_Private_Type (Etype (gnat_actual))
- && Is_Array_Type (Full_View (Etype (gnat_actual))))))
+ && Is_Array_Type (Underlying_Type (Etype (gnat_actual))))
gnu_actual = convert (gnat_to_gnu_type (Etype (gnat_actual)),
gnu_actual);
}
@@ -5140,7 +5139,7 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
/* Save away what we've made so far and record this potential elaboration
procedure. */
- info = ggc_alloc_elab_info ();
+ info = ggc_alloc<elab_info> ();
set_current_block_context (gnu_elab_proc_decl);
gnat_poplevel ();
DECL_SAVED_TREE (gnu_elab_proc_decl) = end_stmt_group ();
@@ -5597,6 +5596,7 @@ gnat_to_gnu (Node_Id gnat_node)
int length = String_Length (gnat_string);
int i;
tree gnu_idx = TYPE_MIN_VALUE (TYPE_DOMAIN (gnu_result_type));
+ tree gnu_one_node = convert (TREE_TYPE (gnu_idx), integer_one_node);
vec<constructor_elt, va_gc> *gnu_vec;
vec_alloc (gnu_vec, length);
@@ -5606,7 +5606,7 @@ gnat_to_gnu (Node_Id gnat_node)
Get_String_Char (gnat_string, i + 1));
CONSTRUCTOR_APPEND_ELT (gnu_vec, gnu_idx, t);
- gnu_idx = int_const_binop (PLUS_EXPR, gnu_idx, integer_one_node);
+ gnu_idx = int_const_binop (PLUS_EXPR, gnu_idx, gnu_one_node);
}
gnu_result = gnat_build_constructor (gnu_result_type, gnu_vec);
@@ -6191,8 +6191,7 @@ gnat_to_gnu (Node_Id gnat_node)
/* These can either be operations on booleans or on modular types.
Fall through for boolean types since that's the way GNU_CODES is
set up. */
- if (IN (Ekind (Underlying_Type (Etype (gnat_node))),
- Modular_Integer_Kind))
+ if (Is_Modular_Integer_Type (Underlying_Type (Etype (gnat_node))))
{
enum tree_code code
= (kind == N_Op_Or ? BIT_IOR_EXPR
@@ -6235,22 +6234,14 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_lhs = maybe_vector_array (gnu_lhs);
gnu_rhs = maybe_vector_array (gnu_rhs);
- /* If this is a comparison operator, convert any references to
- an unconstrained array value into a reference to the
- actual array. */
+ /* If this is a comparison operator, convert any references to an
+ unconstrained array value into a reference to the actual array. */
if (TREE_CODE_CLASS (code) == tcc_comparison)
{
gnu_lhs = maybe_unconstrained_array (gnu_lhs);
gnu_rhs = maybe_unconstrained_array (gnu_rhs);
}
- /* If the result type is a private type, its full view may be a
- numeric subtype. The representation we need is that of its base
- type, given that it is the result of an arithmetic operation. */
- else if (Is_Private_Type (Etype (gnat_node)))
- gnu_type = gnu_result_type
- = get_unpadded_type (Base_Type (Full_View (Etype (gnat_node))));
-
/* If this is a shift whose count is not guaranteed to be correct,
we need to adjust the shift count. */
if (IN (kind, N_Op_Shift) && !Shift_Count_OK (gnat_node))
@@ -6360,9 +6351,7 @@ gnat_to_gnu (Node_Id gnat_node)
/* This case can apply to a boolean or a modular type.
Fall through for a boolean operand since GNU_CODES is set
up to handle this. */
- if (Is_Modular_Integer_Type (Etype (gnat_node))
- || (Is_Private_Type (Etype (gnat_node))
- && Is_Modular_Integer_Type (Full_View (Etype (gnat_node)))))
+ if (Is_Modular_Integer_Type (Underlying_Type (Etype (gnat_node))))
{
gnu_expr = gnat_to_gnu (Right_Opnd (gnat_node));
gnu_result_type = get_unpadded_type (Etype (gnat_node));
@@ -7438,7 +7427,7 @@ start_stmt_group (void)
if (group)
stmt_group_free_list = group->previous;
else
- group = ggc_alloc_stmt_group ();
+ group = ggc_alloc<stmt_group> ();
group->previous = current_stmt_group;
group->stmt_list = group->block = group->cleanups = NULL_TREE;
@@ -9092,7 +9081,9 @@ pos_to_constructor (Node_Id gnat_expr, tree gnu_array_type,
CONSTRUCTOR_APPEND_ELT (gnu_expr_vec, gnu_index,
convert (TREE_TYPE (gnu_array_type), gnu_expr));
- gnu_index = int_const_binop (PLUS_EXPR, gnu_index, integer_one_node);
+ gnu_index = int_const_binop (PLUS_EXPR, gnu_index,
+ convert (TREE_TYPE (gnu_index),
+ integer_one_node));
}
return gnat_build_constructor (gnu_array_type, gnu_expr_vec);
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index b9b9dc1c52d..56636a62f1c 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -245,10 +245,10 @@ void
init_gnat_utils (void)
{
/* Initialize the association of GNAT nodes to GCC trees. */
- associate_gnat_to_gnu = ggc_alloc_cleared_vec_tree (max_gnat_nodes);
+ associate_gnat_to_gnu = ggc_cleared_vec_alloc<tree> (max_gnat_nodes);
/* Initialize the association of GNAT nodes to GCC trees as dummies. */
- dummy_node_table = ggc_alloc_cleared_vec_tree (max_gnat_nodes);
+ dummy_node_table = ggc_cleared_vec_alloc<tree> (max_gnat_nodes);
/* Initialize the hash table of padded types. */
pad_type_hash_table
@@ -428,7 +428,7 @@ gnat_pushlevel (void)
free_binding_level = free_binding_level->chain;
}
else
- newlevel = ggc_alloc_gnat_binding_level ();
+ newlevel = ggc_alloc<gnat_binding_level> ();
/* Use a free BLOCK, if any; otherwise, allocate one. */
if (free_block_chain)
@@ -1182,7 +1182,7 @@ maybe_pad_type (tree type, tree size, unsigned int align,
goto built;
}
- h = ggc_alloc_pad_type_hash ();
+ h = ggc_alloc<pad_type_hash> ();
h->hash = hashcode;
h->type = record;
loc = htab_find_slot_with_hash (pad_type_hash_table, h, hashcode,
@@ -5756,9 +5756,10 @@ gnat_write_global_declarations (void)
dummy_global
= build_decl (BUILTINS_LOCATION, VAR_DECL, get_identifier (label),
void_type_node);
+ DECL_HARD_REGISTER (dummy_global) = 1;
TREE_STATIC (dummy_global) = 1;
- TREE_ASM_WRITTEN (dummy_global) = 1;
node = varpool_node_for_decl (dummy_global);
+ node->definition = 1;
node->force_output = 1;
while (!types_used_by_cur_var_decl->is_empty ())
@@ -5913,15 +5914,18 @@ enum c_builtin_type
#define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
#define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
#define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME,
-#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) NAME,
-#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) NAME,
-#define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) NAME,
+#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6) NAME,
+#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7) NAME,
+#define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7, ARG8) NAME,
#define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
#define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
#define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
#define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
#define DEF_FUNCTION_TYPE_VAR_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
-#define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG6) \
+#define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
NAME,
#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
#include "builtin-types.def"
@@ -6052,12 +6056,15 @@ install_builtin_function_types (void)
#include "builtin-types.def"
#undef DEF_PRIMITIVE_TYPE
+#undef DEF_FUNCTION_TYPE_0
#undef DEF_FUNCTION_TYPE_1
#undef DEF_FUNCTION_TYPE_2
#undef DEF_FUNCTION_TYPE_3
#undef DEF_FUNCTION_TYPE_4
#undef DEF_FUNCTION_TYPE_5
#undef DEF_FUNCTION_TYPE_6
+#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
#undef DEF_FUNCTION_TYPE_VAR_2
diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb
index d7d7d67f0f9..87dcaca6afe 100644
--- a/gcc/ada/gnat1drv.adb
+++ b/gcc/ada/gnat1drv.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -633,7 +633,6 @@ procedure Gnat1drv is
Sname := Unit_Name (Main_Unit);
-- If we do not already have a body name, then get the body name
- -- (but how can we have a body name here???)
if not Is_Body_Name (Sname) then
Sname := Get_Body_Name (Sname);
@@ -651,19 +650,15 @@ procedure Gnat1drv is
-- to include both in a partition, this is diagnosed at bind time. In
-- Ada 83 mode this is not a warning case.
- -- Note: if weird file names are being used, we can have a situation
- -- where the file name that supposedly contains body in fact contains
- -- a spec, or we can't tell what it contains. Skip the error message
- -- in these cases.
-
- -- Also ignore body that is nothing but pragma No_Body; (that's the
- -- whole point of this pragma, to be used this way and to cause the
- -- body file to be ignored in this context).
+ -- Note that in general we do not give the message if the file in
+ -- question does not look like a body. This includes weird cases,
+ -- but in particular means that if the file is just a No_Body pragma,
+ -- then we won't give the message (that's the whole point of this
+ -- pragma, to be used this way and to cause the body file to be
+ -- ignored in this context).
if Src_Ind /= No_Source_File
- and then Get_Expected_Unit_Type (Fname) = Expect_Body
- and then not Source_File_Is_Subunit (Src_Ind)
- and then not Source_File_Is_No_Body (Src_Ind)
+ and then Source_File_Is_Body (Src_Ind)
then
Errout.Finalize (Last_Call => False);
@@ -693,8 +688,8 @@ procedure Gnat1drv is
else
-- For generic instantiations, we never allow a body
- if Nkind (Original_Node (Unit (Main_Unit_Node)))
- in N_Generic_Instantiation
+ if Nkind (Original_Node (Unit (Main_Unit_Node))) in
+ N_Generic_Instantiation
then
Bad_Body_Error
("generic instantiation for $$ does not allow a body");
diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi
index 34ac0e17aa9..79e43ab90b0 100644
--- a/gcc/ada/gnat_rm.texi
+++ b/gcc/ada/gnat_rm.texi
@@ -15746,7 +15746,7 @@ end Overwrite_Array;
@end smallexample
@noindent
-then the program compiles without the waraning and when run will generate
+then the program compiles without the warning and when run will generate
the output @code{X was not clobbered}.
@node Effect of Convention on Representation
diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi
index 2d9c61865d9..9a347525e91 100644
--- a/gcc/ada/gnat_ugn.texi
+++ b/gcc/ada/gnat_ugn.texi
@@ -4018,7 +4018,7 @@ Internal GNAT implementation mode. This should not be used for
applications programs, it is intended only for use by the compiler
and its run-time library. For documentation, see the GNAT sources.
Note that @option{^-gnatg^/GNAT_INTERNAL^} implies
-@option{^-gnatwae^/WARNINGS=ALL,ERRORS^} and
+@option{^-gnatw.ge^/WARNINGS=GNAT,ERRORS^} and
@option{^-gnatyg^/STYLE_CHECKS=GNAT^}
so that all standard warnings and all standard style options are turned on.
All warnings and style messages are treated as errors.
@@ -5167,6 +5167,14 @@ Manual requirement that such warnings appear).
@cindex @option{-gnatwG} (@command{gcc})
This switch suppresses warnings for unrecognized pragmas.
+@item -gnatw.g
+@emph{Warnings used for GNAT sources}
+@cindex @option{-gnatw.g} (@command{gcc})
+This switch sets the warning categories that are used by the standard
+GNAT style. Currently this is equivalent to
+@option{-gnatwAao.sI.C.V.X}
+but more warnings may be added in the future without advanced notice.
+
@item -gnatwh
@emph{Activate warnings on hiding.}
@cindex @option{-gnatwh} (@command{gcc})
@@ -5867,6 +5875,12 @@ Conversely, this switch suppresses warnings from the @option{GCC} back end.
The use of this switch also sets the default front end warning mode to
@option{-gnatws}, that is, front end warnings suppressed as well.
+@item -Werror
+@cindex @option{-Werror}
+This switch causes warnings from the @option{GCC} back end to be treated as
+errors. The warning string still appears, but the warning messages are
+counted as errors, and prevent the generation of an object file.
+
@end table
@noindent
@@ -6375,7 +6389,9 @@ in the source text.
@emph{GNAT style mode.}
The set of style check switches is set to match that used by the GNAT sources.
This may be useful when developing code that is eventually intended to be
-incorporated into GNAT. For further details, see GNAT sources.
+incorporated into GNAT. Currently this is equivalent to @option{-gnatwydISux})
+but additional style switches may be added to this set in the future without
+advance notice.
@item ^h^HTABS^
@emph{No horizontal tabs.}
@@ -8369,11 +8385,6 @@ limit, then a message is output and the bind is abandoned.
A value of zero means that no limit is enforced. The equal
sign is optional.
-@ifset unw
-Furthermore, under Windows, the sources pointed to by the libraries path
-set in the registry are not searched for.
-@end ifset
-
@item ^-n^/NOMAIN^
@cindex @option{^-n^/NOMAIN^} (@command{gnatbind})
No main program.
@@ -14118,22 +14129,18 @@ Support for @option{--pp-old} will be removed in some future version.
To produce a reformatted file, @command{gnatpp} invokes the Ada
compiler and generates and uses the ASIS tree for the input source;
-thus the input must be legal Ada code.
+thus the input must be legal Ada code, and the tool should have all the
+information needed to compile the input source. To provide this information,
+you may specify as a tool parameter the project file the input source belongs to
+(or you may call @command{gnatpp}
+through the @command{gnat} driver (see @ref{The GNAT Driver and
+Project Files}). Another possibility is to specify the source search
+path and needed configuration files in @option{-cargs} section of @command{gnatpp}
+call, see the description of the @command{gnatpp} switches below.
@command{gnatpp} cannot process sources that contain
preprocessing directives.
-If the compilation unit contained in the input source depends
-semantically upon units located outside the current directory, you
-have to provide the source search path when invoking
-@command{gnatpp}. If these units are contained in files with names
-that do not follow the GNAT file naming rules, you have to provide a
-configuration file describing the corresponding naming scheme; see the
-description of the @command{gnatpp} switches below. Another
-possibility is to use a project file and to call @command{gnatpp}
-through the @command{gnat} driver (see @ref{The GNAT Driver and
-Project Files}).
-
The @command{gnatpp} command has the form
@smallexample
@@ -15568,23 +15575,16 @@ metrics are computed and output.
* Switches for gnatmetric::
@end menu
-@command{gnatmetric} generates and uses the ASIS
-tree for the input source and thus requires the input to be syntactically and
-semantically legal.
-If this condition is not met, @command{gnatmetric} will generate
-an error message; no metric information for this file will be
-computed and reported.
-
-If the compilation unit contained in the input source depends semantically
-upon units in files located outside the current directory, you have to provide
-the source search path when invoking @command{gnatmetric}.
-If it depends semantically upon units that are contained
-in files with names that do not follow the GNAT file naming rules, you have to
-provide the configuration file describing the corresponding naming scheme (see
-the description of the @command{gnatmetric} switches below.)
-Alternatively, you may use a project file and invoke @command{gnatmetric}
-through the @command{gnat} driver (see @ref{The GNAT Driver and Project Files}),
-or you can directly specify a project file as a @command{gnatmetric} parameter.
+To compute program metrics, @command{gnatmetric} invokes the Ada
+compiler and generates and uses the ASIS tree for the input source;
+thus the input must be legal Ada code, and the tool should have all the
+information needed to compile the input source. To provide this information,
+you may specify as a tool parameter the project file the input source belongs to
+(or you may call @command{gnatmetric}
+through the @command{gnat} driver (see @ref{The GNAT Driver and
+Project Files}). Another possibility is to specify the source search
+path and needed configuration files in @option{-cargs} section of @command{gnatmetric}
+call, see the description of the @command{gnatmetric} switches below.
The @command{gnatmetric} command has the form
@@ -16221,50 +16221,48 @@ Do not report the extra exit points for subprogram bodies
@cindex Coupling metrics control in @command{gnatmetric}
@noindent
-@cindex Coupling metrics (in in @command{gnatmetric})
+@cindex Coupling metrics (in @command{gnatmetric})
Coupling metrics measure the dependencies between a given entity and other
-entities the program consists of. The goal of these metrics is to estimate the
-stability of the whole program considered as the collection of entities
-(modules, classes etc.).
+entities in the program. This information is useful since high coupling
+may signal potential issues with maintainability as the program evolves.
-Gnatmetric computes the following coupling metrics:
+@command{gnatmetric} computes the following coupling metrics:
@itemize @bullet
@item
-@emph{object-oriented coupling} - for classes in traditional object-oriented
+@emph{object-oriented coupling}, for classes in traditional object-oriented
sense;
@item
-@emph{unit coupling} - for all the program units making up a program;
+@emph{unit coupling}, for all the program units making up a program;
@item
-@emph{control coupling} - this metric counts dependencies between a unit and
-only those units that define subprograms;
+@emph{control coupling}, reflecting dependencies between a unit and
+other units that contain subprograms.
@end itemize
@noindent
Two kinds of coupling metrics are computed:
-@table @asis
-@item fan-out coupling (efferent coupling)
+@itemize @bullet
+@item fan-out coupling (``efferent coupling''):
@cindex fan-out coupling
@cindex efferent coupling
-the number of entities the given entity depends upon. It
-estimates in what extent the given entity depends on the changes in
-``external world''
+the number of entities the given entity depends upon. This metric
+reflects how the given entity depends on the changes in the
+``external world''.
-@item fan-in coupling (afferent coupling)
+@item fan-in coupling (``afferent'' coupling):
@cindex fan-in coupling
@cindex afferent coupling
the number of entities that depend on a given entity.
-It estimates in what extent the ``external world'' depends on the changes in a
-given entity
-@end table
+This metric reflects how the ``external world'' depends on the changes in a
+given entity.
+@end itemize
@noindent
-
-Object-oriented coupling metrics are metrics that measure the dependencies
+Object-oriented coupling metrics measure the dependencies
between a given class (or a group of classes) and the other classes in the
program. In this subsection the term ``class'' is used in its traditional
object-oriented programming sense (an instantiable module that contains data
@@ -16281,68 +16279,78 @@ that depend upon @code{K}.
A category's fan-in coupling is the number of classes outside the
category that depend on classes belonging to the category.
-Ada's implementation of the object-oriented paradigm does not use the
-traditional class notion, so the definition of the coupling
+Ada's object-oriented paradigm separates the instantiable entity
+(type) from the module (package), so the definition of the coupling
metrics for Ada maps the class and class category notions
onto Ada constructs.
-For the coupling metrics, several kinds of modules -- a library package,
-a library generic package, and a library generic package instantiation --
-that define a tagged type or an interface type are
-considered to be a class. A category consists of a library package (or
+For the coupling metrics, several kinds of modules that define a tagged type
+or an interface type -- library packages, library generic packages, and
+library generic package instantiations -- are considered to be classes.
+A category consists of a library package (or
a library generic package) that defines a tagged or an interface type,
together with all its descendant (generic) packages that define tagged
-or interface types. That is a
-category is an Ada hierarchy of library-level program units. So class coupling
-in case of Ada is called as tagged coupling, and category coupling - as
-hierarchy coupling.
-
-For any package counted as a class, its body and subunits (if any) are
-considered together with its spec when counting the dependencies, and coupling
-metrics are reported for spec units only. For dependencies between classes,
-the Ada semantic dependencies are considered. For object-oriented coupling
-metrics, only dependencies on units that are considered as classes, are
+or interface types. Thus a
+category is an Ada hierarchy of library-level program units. Class
+coupling in Ada is referred to as ``tagged coupling'', and category coupling
+is referred to as ``hierarchy coupling''.
+
+For any package serving as a class, its body and subunits (if any) are
+considered together with its spec when computing dependencies, and coupling
+metrics are reported for spec units only. Dependencies between classes
+mean Ada semantic dependencies. For object-oriented coupling
+metrics, only dependencies on units treated as classes are
considered.
-For unit and control coupling also not compilation units but program units are
-counted. That is, for a package, its spec, its body and its subunits (if any)
-are considered as making up one unit, and the dependencies that are counted
-are the dependencies of all these compilation units collected together as
-the dependencies as a (whole) unit. And metrics are reported for spec
-compilation units only (or for a subprogram body unit in case if there is no
+Similarly, for unit and control coupling an entity is considered to be the
+conceptual construct consisting of the entity's specification, body, and
+any subunits (transitively).
+@command{gnatmetric} computes
+the dependencies of all these units as a whole, but
+metrics are only reported for spec
+units (or for a subprogram body unit in case if there is no
separate spec for the given subprogram).
-For unit coupling, dependencies between all kinds of program units are
-considered. For control coupling, for each unit the dependencies of this unit
-upon units that define subprograms are counted, so control fan-out coupling
-is reported for all units, but control fan-in coupling - only for the units
+For unit coupling, dependencies are computed between all kinds of program
+units. For control coupling, the dependencies of a given unit are limited to
+those units that define subprograms. Thus control fan-out coupling is reported
+for all units, but control fan-in coupling is only reported for units
that define subprograms.
The following simple example illustrates the difference between unit coupling
and control coupling metrics:
@smallexample @c ada
+@group
package Lib_1 is
function F_1 (I : Integer) return Integer;
end Lib_1;
+@end group
+@group
package Lib_2 is
type T_2 is new Integer;
end Lib_2;
+@end group
+@group
package body Lib_1 is
function F_1 (I : Integer) return Integer is
begin
return I + 1;
end F_1;
end Lib_1;
+@end group
+@group
with Lib_2; use Lib_2;
package Pack is
Var : T_2;
function Fun (I : Integer) return Integer;
end Pack;
+@end group
+@group
with Lib_1; use Lib_1;
package body Pack is
function Fun (I : Integer) return Integer is
@@ -16350,13 +16358,15 @@ package body Pack is
return F_1 (I);
end Fun;
end Pack;
+@end group
@end smallexample
@noindent
-if we apply @command{gnatmetric} with @code{--coupling-all} option to these
-units, the result will be:
+If we apply @command{gnatmetric} with the @option{--coupling-all} option to
+these units, the result will be:
@smallexample
+@group
Coupling metrics:
=================
Unit Lib_1 (C:\customers\662\L406-007\lib_1.ads)
@@ -16364,46 +16374,50 @@ Coupling metrics:
control fan-in coupling : 1
unit fan-out coupling : 0
unit fan-in coupling : 1
+@end group
+@group
Unit Pack (C:\customers\662\L406-007\pack.ads)
control fan-out coupling : 1
control fan-in coupling : 0
unit fan-out coupling : 2
unit fan-in coupling : 0
+@end group
+@group
Unit Lib_2 (C:\customers\662\L406-007\lib_2.ads)
control fan-out coupling : 0
unit fan-out coupling : 0
unit fan-in coupling : 1
+@end group
@end smallexample
@noindent
The result does not contain values for object-oriented
-coupling because none of the argument unit contains a tagged type and
+coupling because none of the argument units contains a tagged type and
therefore none of these units can be treated as a class.
-@code{Pack} (considered as a program unit, that is spec+body) depends on two
-units - @code{Lib_1} @code{and Lib_2}, therefore it has unit fan-out coupling
-equals to 2. And nothing depend on it, so its unit fan-in coupling is 0 as
-well as control fan-in coupling. Only one of the units @code{Pack} depends
+The @code{Pack} package (spec and body) depends on two
+units -- @code{Lib_1} @code{and Lib_2} -- and so its unit fan-out coupling
+is 2. Since nothing depends on it, its unit fan-in coupling is 0, as
+is its control fan-in coupling. Only one of the units @code{Pack} depends
upon defines a subprogram, so its control fan-out coupling is 1.
-@code{Lib_2} depends on nothing, so fan-out metrics for it are 0. It does
-not define a subprogram, so control fan-in metric cannot be applied to it,
-and there is one unit that depends on it (@code{Pack}), so it has
-unit fan-in coupling equals to 1.
+@code{Lib_2} depends on nothing, so its fan-out metrics are 0. It does
+not define any subprograms, so it has no control fan-in metric.
+One unit (@code{Pack}) depends on it , so its unit fan-in coupling is 1.
@code{Lib_1} is similar to @code{Lib_2}, but it does define a subprogram.
-So it has control fan-in coupling equals to 1 (because there is a unit
+Its control fan-in coupling is 1 (because there is one unit
depending on it).
When computing coupling metrics, @command{gnatmetric} counts only
dependencies between units that are arguments of the @command{gnatmetric}
-call. Coupling metrics are program-wide (or project-wide) metrics, so to
-get a valid result, you should call @command{gnatmetric} for
-the whole set of sources that make up your program. It can be done
-by calling @command{gnatmetric} from the GNAT driver with @option{-U}
-option (see @ref{The GNAT Driver and Project Files} for details).
+invocation. Coupling metrics are program-wide (or project-wide) metrics, so
+you should invoke @command{gnatmetric} for
+the complete set of sources comprising your program. This can be done
+by invoking @command{gnatmetric} with the corresponding project file
+and with the @option{-U} option.
By default, all the coupling metrics are disabled. You can use the following
switches to specify the coupling metrics to be computed and reported:
@@ -19290,15 +19304,16 @@ For full details, refer to @cite{GNATcheck Reference Manual} document.
@command{gnatstub} creates body stubs, that is, empty but compilable bodies
for library unit declarations.
-Note: to invoke @code{gnatstub} with a project file, use the @code{gnat}
-driver (see @ref{The GNAT Driver and Project Files}).
-
-To create a body stub, @command{gnatstub} has to compile the library
-unit declaration. Therefore, bodies can be created only for legal
-library units. Moreover, if a library unit depends semantically upon
-units located outside the current directory, you have to provide
-the source search path when calling @command{gnatstub}, see the description
-of @command{gnatstub} switches below.
+To create a body stub, @command{gnatstub} invokes the Ada
+compiler and generates and uses the ASIS tree for the input source;
+thus the input must be legal Ada code, and the tool should have all the
+information needed to compile the input source. To provide this information,
+you may specify as a tool parameter the project file the input source belongs to
+(or you may call @command{gnatstub}
+through the @command{gnat} driver (see @ref{The GNAT Driver and
+Project Files}). Another possibility is to specify the source search
+path and needed configuration files in @option{-cargs} section of @command{gnatstub}
+call, see the description of the @command{gnatstub} switches below.
By default, all the program unit body stubs generated by @code{gnatstub}
raise the predefined @code{Program_Error} exception, which will catch
diff --git a/gcc/ada/gnatcmd.adb b/gcc/ada/gnatcmd.adb
index 494fd4d9ceb..50bc3ad3568 100644
--- a/gcc/ada/gnatcmd.adb
+++ b/gcc/ada/gnatcmd.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1996-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1996-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -45,6 +45,7 @@ with Sdefault;
with Sinput.P;
with Snames; use Snames;
with Stringt;
+with Switch; use Switch;
with Table;
with Targparm;
with Tempdir;
@@ -1382,6 +1383,9 @@ procedure GNATCmd is
end if;
end Set_Library_For;
+ procedure Check_Version_And_Help is
+ new Check_Version_And_Help_G (Non_VMS_Usage);
+
-- Start of processing for GNATCmd
begin
@@ -1488,122 +1492,125 @@ begin
-- If not on VMS, scan the command line directly
else
- if Argument_Count = 0 then
- Non_VMS_Usage;
- return;
- else
- begin
- loop
- if Argument_Count > Command_Arg
- and then Argument (Command_Arg) = "-v"
- then
- Verbose_Mode := True;
- Command_Arg := Command_Arg + 1;
+ -- First, scan to detect --version and/or --help
- elsif Argument_Count > Command_Arg
- and then Argument (Command_Arg) = "-dn"
- then
- Keep_Temporary_Files := True;
- Command_Arg := Command_Arg + 1;
+ Check_Version_And_Help ("GNAT", "1996");
- else
- exit;
- end if;
- end loop;
+ begin
+ loop
+ if Command_Arg <= Argument_Count
+ and then Argument (Command_Arg) = "-v"
+ then
+ Verbose_Mode := True;
+ Command_Arg := Command_Arg + 1;
- The_Command := Real_Command_Type'Value (Argument (Command_Arg));
+ elsif Command_Arg <= Argument_Count
+ and then Argument (Command_Arg) = "-dn"
+ then
+ Keep_Temporary_Files := True;
+ Command_Arg := Command_Arg + 1;
- if Command_List (The_Command).VMS_Only then
- Non_VMS_Usage;
- Fail
- ("Command """
- & Command_List (The_Command).Cname.all
- & """ can only be used on VMS");
+ else
+ exit;
end if;
+ end loop;
- exception
- when Constraint_Error =>
+ -- If there is no command, just output the usage
- -- Check if it is an alternate command
+ if Command_Arg > Argument_Count then
+ Non_VMS_Usage;
+ return;
+ end if;
- declare
- Alternate : Alternate_Command;
+ The_Command := Real_Command_Type'Value (Argument (Command_Arg));
- begin
- Alternate := Alternate_Command'Value
- (Argument (Command_Arg));
- The_Command := Corresponding_To (Alternate);
-
- exception
- when Constraint_Error =>
- Non_VMS_Usage;
- Fail ("Unknown command: " & Argument (Command_Arg));
- end;
- end;
+ if Command_List (The_Command).VMS_Only then
+ Non_VMS_Usage;
+ Fail
+ ("command """
+ & Command_List (The_Command).Cname.all
+ & """ can only be used on VMS");
+ end if;
+
+ exception
+ when Constraint_Error =>
- -- Get the arguments from the command line and from the eventual
- -- argument file(s) specified on the command line.
+ -- Check if it is an alternate command
- for Arg in Command_Arg + 1 .. Argument_Count loop
declare
- The_Arg : constant String := Argument (Arg);
+ Alternate : Alternate_Command;
begin
- -- Check if an argument file is specified
+ Alternate := Alternate_Command'Value
+ (Argument (Command_Arg));
+ The_Command := Corresponding_To (Alternate);
+
+ exception
+ when Constraint_Error =>
+ Non_VMS_Usage;
+ Fail ("unknown command: " & Argument (Command_Arg));
+ end;
+ end;
- if The_Arg (The_Arg'First) = '@' then
- declare
- Arg_File : Ada.Text_IO.File_Type;
- Line : String (1 .. 256);
- Last : Natural;
+ -- Get the arguments from the command line and from the eventual
+ -- argument file(s) specified on the command line.
- begin
- -- Open the file and fail if the file cannot be found
-
- begin
- Open
- (Arg_File, In_File,
- The_Arg (The_Arg'First + 1 .. The_Arg'Last));
-
- exception
- when others =>
- Put
- (Standard_Error, "Cannot open argument file """);
- Put
- (Standard_Error,
- The_Arg (The_Arg'First + 1 .. The_Arg'Last));
-
- Put_Line (Standard_Error, """");
- raise Error_Exit;
- end;
+ for Arg in Command_Arg + 1 .. Argument_Count loop
+ declare
+ The_Arg : constant String := Argument (Arg);
- -- Read line by line and put the content of each non-
- -- empty line in the Last_Switches table.
+ begin
+ -- Check if an argument file is specified
- while not End_Of_File (Arg_File) loop
- Get_Line (Arg_File, Line, Last);
+ if The_Arg (The_Arg'First) = '@' then
+ declare
+ Arg_File : Ada.Text_IO.File_Type;
+ Line : String (1 .. 256);
+ Last : Natural;
- if Last /= 0 then
- Last_Switches.Increment_Last;
- Last_Switches.Table (Last_Switches.Last) :=
- new String'(Line (1 .. Last));
- end if;
- end loop;
+ begin
+ -- Open the file and fail if the file cannot be found
- Close (Arg_File);
+ begin
+ Open
+ (Arg_File, In_File,
+ The_Arg (The_Arg'First + 1 .. The_Arg'Last));
+
+ exception
+ when others =>
+ Put (Standard_Error, "Cannot open argument file """);
+ Put (Standard_Error,
+ The_Arg (The_Arg'First + 1 .. The_Arg'Last));
+ Put_Line (Standard_Error, """");
+ raise Error_Exit;
end;
- else
- -- It is not an argument file; just put the argument in
- -- the Last_Switches table.
+ -- Read line by line and put the content of each non-
+ -- empty line in the Last_Switches table.
- Last_Switches.Increment_Last;
- Last_Switches.Table (Last_Switches.Last) :=
- new String'(The_Arg);
- end if;
- end;
- end loop;
- end if;
+ while not End_Of_File (Arg_File) loop
+ Get_Line (Arg_File, Line, Last);
+
+ if Last /= 0 then
+ Last_Switches.Increment_Last;
+ Last_Switches.Table (Last_Switches.Last) :=
+ new String'(Line (1 .. Last));
+ end if;
+ end loop;
+
+ Close (Arg_File);
+ end;
+
+ else
+ -- It is not an argument file; just put the argument in
+ -- the Last_Switches table.
+
+ Last_Switches.Increment_Last;
+ Last_Switches.Table (Last_Switches.Last) :=
+ new String'(The_Arg);
+ end if;
+ end;
+ end loop;
end if;
declare
@@ -1806,7 +1813,7 @@ begin
end case;
else
Fail ("invalid verbosity level: "
- & Argv (Argv'First + 3 .. Argv'Last));
+ & Argv (Argv'First + 3 .. Argv'Last));
end if;
Remove_Switch (Arg_Num);
@@ -2094,13 +2101,13 @@ begin
end if;
end;
- if The_Command = Bind
- or else The_Command = Link
- or else The_Command = Elim
+ if The_Command = Bind or else
+ The_Command = Link or else
+ The_Command = Elim
then
if Project.Object_Directory.Name = No_Path then
- Fail ("project " & Get_Name_String (Project.Display_Name) &
- " has no object directory");
+ Fail ("project " & Get_Name_String (Project.Display_Name)
+ & " has no object directory");
end if;
Change_Dir (Get_Name_String (Project.Object_Directory.Name));
diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb
index 829d75c2eb9..466d1ca2929 100644
--- a/gcc/ada/layout.adb
+++ b/gcc/ada/layout.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2001-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 2001-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -270,8 +270,7 @@ package body Layout is
-- the Integer base type, but it is safe to reduce it to 1 at this
-- stage, since we will only be loading a single storage unit.
- if Is_Discrete_Type (Etype (E))
- and then not Has_Alignment_Clause (E)
+ if Is_Discrete_Type (Etype (E)) and then not Has_Alignment_Clause (E)
then
loop
Abits := Abits / 2;
@@ -353,7 +352,7 @@ package body Layout is
elsif Nkind (L) = N_Op_Subtract then
- -- (C1 - E) + C2 = (C1 + C2) + E
+ -- (C1 - E) + C2 = (C1 + C2) - E
if Compile_Time_Known_Value (Sinfo.Left_Opnd (L)) then
Rewrite_Integer
@@ -363,7 +362,14 @@ package body Layout is
-- (E - C1) + C2 = E - (C1 - C2)
- elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L)) then
+ -- If the type is unsigned then only do the optimization if C1 >= C2,
+ -- to avoid creating a negative literal that can't be used with the
+ -- unsigned type.
+
+ elsif Compile_Time_Known_Value (Sinfo.Right_Opnd (L))
+ and then (not Is_Unsigned_Type (Etype (Sinfo.Right_Opnd (L)))
+ or else Expr_Value (Sinfo.Right_Opnd (L)) >= R)
+ then
Rewrite_Integer
(Sinfo.Right_Opnd (L),
Expr_Value (Sinfo.Right_Opnd (L)) - R);
@@ -619,8 +625,8 @@ package body Layout is
-- parameter rather than passing "V" directly.
if Present (Comp)
- and then Base_Type (Etype (Comp))
- = Base_Type (Etype (First_Formal (Ent)))
+ and then Base_Type (Etype (Comp)) =
+ Base_Type (Etype (First_Formal (Ent)))
then
return
Make_Function_Call (Loc,
@@ -748,7 +754,8 @@ package body Layout is
-- Value of the current subscript range is statically known
if Compile_Time_Known_Value (Lo)
- and then Compile_Time_Known_Value (Hi)
+ and then
+ Compile_Time_Known_Value (Hi)
then
S := Expr_Value (Hi) - Expr_Value (Lo) + 1;
@@ -1085,7 +1092,8 @@ package body Layout is
-- Value of the current subscript range is statically known
if Compile_Time_Known_Value (Lo)
- and then Compile_Time_Known_Value (Hi)
+ and then
+ Compile_Time_Known_Value (Hi)
then
S := Expr_Value (Hi) - Expr_Value (Lo) + 1;
@@ -1381,9 +1389,7 @@ package body Layout is
-- not set by an explicit Object_Size attribute clause, then we reset
-- the Esize to unknown, since we really don't know it.
- if Unknown_Alignment (E)
- and then not Has_Size_Clause (E)
- then
+ if Unknown_Alignment (E) and then not Has_Size_Clause (E) then
Set_Esize (E, Uint_0);
end if;
end Layout_Object;
@@ -2505,12 +2511,12 @@ package body Layout is
elsif AAMP_On_Target
and then
((Ekind (E) = E_Access_Subprogram_Type
- and then Present (Enclosing_Subprogram (E)))
- or else
- (Ekind (E) = E_Anonymous_Access_Subprogram_Type
- and then
- (not Is_Local_Anonymous_Access (E)
- or else Present (Enclosing_Subprogram (E)))))
+ and then Present (Enclosing_Subprogram (E)))
+ or else
+ (Ekind (E) = E_Anonymous_Access_Subprogram_Type
+ and then
+ (not Is_Local_Anonymous_Access (E)
+ or else Present (Enclosing_Subprogram (E)))))
then
Init_Size (E, 2 * System_Address_Size);
else
@@ -2534,7 +2540,7 @@ package body Layout is
if Opt.True_VMS_Target
and then (Convention (E) = Convention_C
- or else
+ or else
Convention (E) = Convention_CPP)
and then No (Get_Attribute_Definition_Clause (E, Attribute_Size))
and then Esize (E) = 64
@@ -2646,14 +2652,12 @@ package body Layout is
-- component type is known and is a small power of 2 (8, 16, 32, 64),
-- since this is what will always be used.
- if Ekind (E) = E_Array_Type
- and then Unknown_Component_Size (E)
- then
+ if Ekind (E) = E_Array_Type and then Unknown_Component_Size (E) then
declare
CT : constant Entity_Id := Component_Type (E);
begin
- -- For some reasons, access types can cause trouble, So let's
+ -- For some reason, access types can cause trouble, So let's
-- just do this for scalar types ???
if Present (CT)
@@ -2693,9 +2697,7 @@ package body Layout is
-- For these types, we set a corresponding alignment matching
-- the size if possible, or as large as possible if not.
- if Convention (E) = Convention_Ada
- and then not Debug_Flag_Q
- then
+ if Convention (E) = Convention_Ada and then not Debug_Flag_Q then
Set_Composite_Alignment (E);
end if;
@@ -2717,9 +2719,7 @@ package body Layout is
-- arrays when passed to subprogram parameters (see special test
-- in Exp_Ch6.Expand_Actuals).
- if not Is_Packed (E)
- and then Unknown_Alignment (E)
- then
+ if not Is_Packed (E) and then Unknown_Alignment (E) then
if Known_Static_Component_Size (E)
and then Component_Size (E) = 1
then
@@ -2982,12 +2982,8 @@ package body Layout is
if Known_Static_Esize (E) then
Siz := Esize (E);
-
- elsif Unknown_Esize (E)
- and then Known_Static_RM_Size (E)
- then
+ elsif Unknown_Esize (E) and then Known_Static_RM_Size (E) then
Siz := RM_Size (E);
-
else
return;
end if;
@@ -3095,7 +3091,7 @@ package body Layout is
(Unknown_Esize (Comp)
or else (Known_Static_Esize (Comp)
and then
- Esize (Comp) =
+ Esize (Comp) =
Calign * System_Storage_Unit))
then
Align := UI_To_Int (Calign);
@@ -3187,9 +3183,7 @@ package body Layout is
-- For access types, do not set the alignment if the size is less than
-- the allowed minimum size. This avoids cascaded error messages.
- elsif Is_Access_Type (E)
- and then Esize (E) < System_Address_Size
- then
+ elsif Is_Access_Type (E) and then Esize (E) < System_Address_Size then
return;
end if;
diff --git a/gcc/ada/lib-xref-spark_specific.adb b/gcc/ada/lib-xref-spark_specific.adb
index 0b32aada218..7e7d52bb07b 100644
--- a/gcc/ada/lib-xref-spark_specific.adb
+++ b/gcc/ada/lib-xref-spark_specific.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2011-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 2011-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -23,10 +23,9 @@
-- --
------------------------------------------------------------------------------
-with SPARK_Xrefs; use SPARK_Xrefs;
-with Einfo; use Einfo;
-with Nmake; use Nmake;
-with Put_SPARK_Xrefs;
+with Einfo; use Einfo;
+with Nmake; use Nmake;
+with SPARK_Xrefs; use SPARK_Xrefs;
with GNAT.HTable;
@@ -972,7 +971,9 @@ package body SPARK_Specific is
-- Enclosing_Subprogram_Or_Package --
-------------------------------------
- function Enclosing_Subprogram_Or_Package (N : Node_Id) return Entity_Id is
+ function Enclosing_Subprogram_Or_Library_Package
+ (N : Node_Id) return Entity_Id
+ is
Result : Entity_Id;
begin
@@ -990,12 +991,26 @@ package body SPARK_Specific is
while Present (Result) loop
case Nkind (Result) is
when N_Package_Specification =>
- Result := Defining_Unit_Name (Result);
- exit;
+
+ -- Only return a library-level package
+
+ if Is_Library_Level_Entity (Defining_Entity (Result)) then
+ Result := Defining_Entity (Result);
+ exit;
+ else
+ Result := Parent (Result);
+ end if;
when N_Package_Body =>
- Result := Defining_Unit_Name (Result);
- exit;
+
+ -- Only return a library-level package
+
+ if Is_Library_Level_Entity (Defining_Entity (Result)) then
+ Result := Defining_Entity (Result);
+ exit;
+ else
+ Result := Parent (Result);
+ end if;
when N_Subprogram_Specification =>
Result := Defining_Unit_Name (Result);
@@ -1045,7 +1060,7 @@ package body SPARK_Specific is
end if;
return Result;
- end Enclosing_Subprogram_Or_Package;
+ end Enclosing_Subprogram_Or_Library_Package;
-----------------
-- Entity_Hash --
@@ -1107,7 +1122,7 @@ package body SPARK_Specific is
Create_Heap;
end if;
- Ref_Scope := Enclosing_Subprogram_Or_Package (N);
+ Ref_Scope := Enclosing_Subprogram_Or_Library_Package (N);
Deref.Ent := Heap;
Deref.Loc := Loc;
diff --git a/gcc/ada/lib-xref.adb b/gcc/ada/lib-xref.adb
index 28c5dbbd393..ed1138927cf 100644
--- a/gcc/ada/lib-xref.adb
+++ b/gcc/ada/lib-xref.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1998-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1998-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -1029,8 +1029,10 @@ package body Lib.Xref is
Ref := Sloc (Nod);
Def := Sloc (Ent);
- Ref_Scope := SPARK_Specific.Enclosing_Subprogram_Or_Package (Nod);
- Ent_Scope := SPARK_Specific.Enclosing_Subprogram_Or_Package (Ent);
+ Ref_Scope :=
+ SPARK_Specific.Enclosing_Subprogram_Or_Library_Package (Nod);
+ Ent_Scope :=
+ SPARK_Specific.Enclosing_Subprogram_Or_Library_Package (Ent);
-- Since we are reaching through renamings in SPARK mode, we may
-- end up with standard constants. Ignore those.
diff --git a/gcc/ada/lib-xref.ads b/gcc/ada/lib-xref.ads
index 7f397a868a5..17733a0c930 100644
--- a/gcc/ada/lib-xref.ads
+++ b/gcc/ada/lib-xref.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1998-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1998-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -624,8 +624,12 @@ package Lib.Xref is
package SPARK_Specific is
- function Enclosing_Subprogram_Or_Package (N : Node_Id) return Entity_Id;
- -- Return the closest enclosing subprogram of package
+ function Enclosing_Subprogram_Or_Library_Package
+ (N : Node_Id) return Entity_Id;
+ -- Return the closest enclosing subprogram of package. Only return a
+ -- library level package. If the package is enclosed in a subprogram,
+ -- return the subprogram. This ensures that GNATprove can distinguish
+ -- local variables from global variables.
procedure Generate_Dereference
(N : Node_Id;
diff --git a/gcc/ada/makeusg.adb b/gcc/ada/makeusg.adb
index 62cc703094b..16eb5f968b1 100644
--- a/gcc/ada/makeusg.adb
+++ b/gcc/ada/makeusg.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -86,6 +86,11 @@ begin
"invoke compiler with mapping file mapp");
Write_Eol;
+ -- Line for -d
+
+ Write_Str (" -d Display compilation progress");
+ Write_Eol;
+
-- Line for -D
Write_Str (" -D dir Specify dir as the object directory");
diff --git a/gcc/ada/makeutl.adb b/gcc/ada/makeutl.adb
index a220cbec0e2..d9772510cac 100644
--- a/gcc/ada/makeutl.adb
+++ b/gcc/ada/makeutl.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2004-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 2004-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -1732,7 +1732,7 @@ package body Makeutl is
-- no need to process them in turn.
J := Names.Last;
- loop
+ Main_Loop : loop
declare
File : Main_Info := Names.Table (J);
Main_Id : File_Name_Type := File.File;
@@ -1798,16 +1798,53 @@ package body Makeutl is
-- search for the base name though, and if needed
-- check later that we found the correct file.
- Source := Find_Source
- (In_Tree => File.Tree,
- Project => File.Project,
- Base_Name => Main_Id,
- Index => File.Index,
- In_Imported_Only => True);
+ declare
+ Sources : constant Source_Ids :=
+ Find_All_Sources
+ (In_Tree => File.Tree,
+ Project => File.Project,
+ Base_Name => Main_Id,
+ Index => File.Index,
+ In_Imported_Only => True);
+
+ begin
+ if Is_Absolute then
+ for J in Sources'Range loop
+ if File_Name_Type (Sources (J).Path.Name) =
+ File.File
+ then
+ Source := Sources (J);
+ exit;
+ end if;
+ end loop;
+
+ elsif Sources'Length > 1 then
+
+ -- This is only allowed if the units are from
+ -- the same multi-unit source file.
+
+ Source := Sources (1);
+
+ for J in 2 .. Sources'Last loop
+ if Sources (J).Path /= Source.Path
+ or else Sources (J).Index = Source.Index
+ then
+ Error_Msg_File_1 := Main_Id;
+ Prj.Err.Error_Msg
+ (Flags, "several main sources {",
+ No_Location, File.Project);
+ exit Main_Loop;
+ end if;
+ end loop;
+
+ elsif Sources'Length = 1 then
+ Source := Sources (Sources'First);
+ end if;
+ end;
if Source = No_Source then
Source := Find_File_Add_Extension
- (File.Tree, Get_Name_String (Main_Id));
+ (File.Tree, Get_Name_String (Main_Id));
end if;
if Is_Absolute
@@ -1883,8 +1920,8 @@ package body Makeutl is
end;
J := J - 1;
- exit when J < Names.First;
- end loop;
+ exit Main_Loop when J < Names.First;
+ end loop Main_Loop;
end if;
if Total_Errors_Detected > 0 then
diff --git a/gcc/ada/osint.adb b/gcc/ada/osint.adb
index c30ed8c0d05..0c15982597d 100644
--- a/gcc/ada/osint.adb
+++ b/gcc/ada/osint.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -2988,7 +2988,7 @@ package body Osint is
exception
when others =>
- Fail ("erroneous directory spec: " & Host_Dir);
+ Fail ("invalid directory spec: " & Host_Dir);
return null;
end To_Canonical_Dir_Spec;
@@ -3081,7 +3081,7 @@ package body Osint is
exception
when others =>
- Fail ("erroneous file spec: " & Host_File);
+ Fail ("invalid file spec: " & Host_File);
return null;
end To_Canonical_File_Spec;
@@ -3114,7 +3114,7 @@ package body Osint is
exception
when others =>
- Fail ("erroneous path spec: " & Host_Path);
+ Fail ("invalid path spec: " & Host_Path);
return null;
end To_Canonical_Path_Spec;
diff --git a/gcc/ada/par-ch4.adb b/gcc/ada/par-ch4.adb
index 8dd49f3166c..7926bd11766 100644
--- a/gcc/ada/par-ch4.adb
+++ b/gcc/ada/par-ch4.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -376,7 +376,7 @@ package body Ch4 is
-- If dot is at end of line and followed by nothing legal,
-- then assume end of name and quit (dot will be taken as
- -- an erroneous form of some other punctuation by our caller).
+ -- an incorrect form of some other punctuation by our caller).
elsif Token_Is_At_Start_Of_Line then
Restore_Scan_State (Scan_State);
@@ -770,11 +770,11 @@ package body Ch4 is
Expr_Node := P_Expression_If_OK;
goto LP_State_Expr;
- -- LP_State_Call corresponds to the situation in which at least
- -- one instance of Id => Expression has been encountered, so we
- -- know that we do not have a name, but rather a call. We enter
- -- it with the scan pointer pointing to the next argument to scan,
- -- and Arg_List containing the list of arguments scanned so far.
+ -- LP_State_Call corresponds to the situation in which at least one
+ -- instance of Id => Expression has been encountered, so we know that
+ -- we do not have a name, but rather a call. We enter it with the
+ -- scan pointer pointing to the next argument to scan, and Arg_List
+ -- containing the list of arguments scanned so far.
<<LP_State_Call>>
@@ -785,7 +785,7 @@ package body Ch4 is
Ident_Node := Token_Node;
Scan; -- past Id
- -- Deal with => (allow := as erroneous substitute)
+ -- Deal with => (allow := as incorrect substitute)
if Token = Tok_Arrow or else Token = Tok_Colon_Equal then
Arg_Node := New_Node (N_Parameter_Association, Prev_Token_Ptr);
diff --git a/gcc/ada/prj-dect.adb b/gcc/ada/prj-dect.adb
index 2ce031046ee..a4d07d8828b 100644
--- a/gcc/ada/prj-dect.adb
+++ b/gcc/ada/prj-dect.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2001-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 2001-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -214,8 +214,10 @@ package body Prj.Dect is
Project_Qualifier_Of (Project, In_Tree);
Name : constant Name_Id := Name_Of (Current_Package, In_Tree);
begin
- if Qualif in Aggregate_Project
- and then Name /= Snames.Name_Builder
+ if (Qualif = Aggregate and then Name /= Snames.Name_Builder)
+ or else (Qualif = Aggregate_Library
+ and then Name /= Snames.Name_Builder
+ and then Name /= Snames.Name_Install)
then
Error_Msg_Name_1 := Name;
Error_Msg
diff --git a/gcc/ada/prj.adb b/gcc/ada/prj.adb
index 6a0a830fe10..808325e3905 100644
--- a/gcc/ada/prj.adb
+++ b/gcc/ada/prj.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2001-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 2001-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -889,6 +889,109 @@ package body Prj is
return Result;
end Find_Source;
+ ----------------------
+ -- Find_All_Sources --
+ ----------------------
+
+ function Find_All_Sources
+ (In_Tree : Project_Tree_Ref;
+ Project : Project_Id;
+ In_Imported_Only : Boolean := False;
+ In_Extended_Only : Boolean := False;
+ Base_Name : File_Name_Type;
+ Index : Int := 0) return Source_Ids
+ is
+ Result : Source_Ids (1 .. 1_000);
+ Last : Natural := 0;
+
+ type Empty_State is null record;
+ No_State : Empty_State;
+ -- This is needed for the State parameter of procedure Look_For_Sources
+ -- below, because of the instantiation For_Imported_Projects of generic
+ -- procedure For_Every_Project_Imported. As procedure Look_For_Sources
+ -- does not modify parameter State, there is no need to give its type
+ -- more than one value.
+
+ procedure Look_For_Sources
+ (Proj : Project_Id;
+ Tree : Project_Tree_Ref;
+ State : in out Empty_State);
+ -- Look for Base_Name in the sources of Proj
+
+ ----------------------
+ -- Look_For_Sources --
+ ----------------------
+
+ procedure Look_For_Sources
+ (Proj : Project_Id;
+ Tree : Project_Tree_Ref;
+ State : in out Empty_State)
+ is
+ Iterator : Source_Iterator;
+ Src : Source_Id;
+
+ begin
+ State := No_State;
+
+ Iterator := For_Each_Source (In_Tree => Tree, Project => Proj);
+ while Element (Iterator) /= No_Source loop
+ if Element (Iterator).File = Base_Name
+ and then (Index = 0
+ or else
+ (Element (Iterator).Unit /= No_Unit_Index
+ and then
+ Element (Iterator).Index = Index))
+ then
+ Src := Element (Iterator);
+
+ -- If the source has been excluded, continue looking. We will
+ -- get the excluded source only if there is no other source
+ -- with the same base name that is not locally removed.
+
+ if not Element (Iterator).Locally_Removed then
+ Last := Last + 1;
+ Result (Last) := Src;
+ end if;
+ end if;
+
+ Next (Iterator);
+ end loop;
+ end Look_For_Sources;
+
+ procedure For_Imported_Projects is new For_Every_Project_Imported
+ (State => Empty_State, Action => Look_For_Sources);
+
+ Proj : Project_Id;
+
+ -- Start of processing for Find_All_Sources
+
+ begin
+ if In_Extended_Only then
+ Proj := Project;
+ while Proj /= No_Project loop
+ Look_For_Sources (Proj, In_Tree, No_State);
+ exit when Last > 0;
+ Proj := Proj.Extends;
+ end loop;
+
+ elsif In_Imported_Only then
+ Look_For_Sources (Project, In_Tree, No_State);
+
+ if Last = 0 then
+ For_Imported_Projects
+ (By => Project,
+ Tree => In_Tree,
+ Include_Aggregated => False,
+ With_State => No_State);
+ end if;
+
+ else
+ Look_For_Sources (No_Project, In_Tree, No_State);
+ end if;
+
+ return Result (1 .. Last);
+ end Find_All_Sources;
+
----------
-- Hash --
----------
@@ -896,6 +999,10 @@ package body Prj is
function Hash is new GNAT.HTable.Hash (Header_Num => Header_Num);
-- Used in implementation of other functions Hash below
+ ----------
+ -- Hash --
+ ----------
+
function Hash (Name : File_Name_Type) return Header_Num is
begin
return Hash (Get_Name_String (Name));
diff --git a/gcc/ada/prj.ads b/gcc/ada/prj.ads
index 519e8740161..ce6e01e7e16 100644
--- a/gcc/ada/prj.ads
+++ b/gcc/ada/prj.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 2001-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 2001-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -1525,6 +1525,30 @@ package Prj is
-- Else it searches in the whole tree.
-- If Index is specified, this only search for a source with that index.
+ type Source_Ids is array (Positive range <>) of Source_Id;
+ No_Sources : constant Source_Ids := (1 .. 0 => No_Source);
+
+ function Find_All_Sources
+ (In_Tree : Project_Tree_Ref;
+ Project : Project_Id;
+ In_Imported_Only : Boolean := False;
+ In_Extended_Only : Boolean := False;
+ Base_Name : File_Name_Type;
+ Index : Int := 0) return Source_Ids;
+ -- Find all source files with the given name:
+ --
+ -- If In_Extended_Only is True, it will search in project and the project
+ -- it extends, but not in the imported projects.
+ --
+ -- If Extended_Only is False, and In_Imported_Only is True, it will
+ -- search in project and the projects it imports, but not in the others
+ -- or in aggregated projects.
+ --
+ -- If both Extended_Only and In_Imported_Only are False (the default)
+ -- then it searches the whole tree.
+ --
+ -- If Index is specified, this only search for sources with that index.
+
-----------------------
-- Project_Tree_Data --
-----------------------
diff --git a/gcc/ada/restrict.adb b/gcc/ada/restrict.adb
index 01cd907edac..78591c1efcd 100644
--- a/gcc/ada/restrict.adb
+++ b/gcc/ada/restrict.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -303,7 +303,7 @@ package body Restrict is
Error_Msg_Node_1 := N;
Error_Msg_Warn := No_Use_Of_Attribute_Warning (A_Id);
Error_Msg_N
- ("<violation of restriction `No_Use_Of_Attribute '='> &`#", N);
+ ("<*<violation of restriction `No_Use_Of_Attribute '='> &`#", N);
end if;
end Check_Restriction_No_Use_Of_Attribute;
@@ -336,7 +336,7 @@ package body Restrict is
Error_Msg_Node_1 := Id;
Error_Msg_Warn := No_Use_Of_Pragma_Warning (P_Id);
Error_Msg_N
- ("<violation of restriction `No_Use_Of_Pragma '='> &`#", Id);
+ ("<*<violation of restriction `No_Use_Of_Pragma '='> &`#", Id);
end if;
end Check_Restriction_No_Use_Of_Pragma;
@@ -645,7 +645,7 @@ package body Restrict is
if No_Dependences.Table (J).Warn then
Error_Msg
- ("??violation of restriction `No_Dependence '='> &`#",
+ ("?*?violation of restriction `No_Dependence '='> &`#",
Sloc (Err));
else
Error_Msg
@@ -691,7 +691,7 @@ package body Restrict is
Error_Msg_Node_1 := Id;
Error_Msg_Warn := No_Specification_Of_Aspect_Warning (A_Id);
Error_Msg_N
- ("<violation of restriction `No_Specification_Of_Aspect '='> &`#",
+ ("<*<violation of restriction `No_Specification_Of_Aspect '='> &`#",
Id);
end if;
end Check_Restriction_No_Specification_Of_Aspect;
@@ -1047,7 +1047,7 @@ package body Restrict is
-- Set warning message if warning
if Restriction_Warnings (R) then
- Add_Str ("??");
+ Add_Str ("?*?");
-- If real violation (not warning), then mark it as non-serious unless
-- it is a violation of No_Finalization in which case we leave it as a
diff --git a/gcc/ada/restrict.ads b/gcc/ada/restrict.ads
index cef3167ea8e..882cb84b44e 100644
--- a/gcc/ada/restrict.ads
+++ b/gcc/ada/restrict.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -120,6 +120,7 @@ package Restrict is
No_Exception_Propagation => True,
No_Exception_Registration => True,
No_Finalization => True,
+ No_Fixed_IO => True,
No_Implementation_Attributes => True,
No_Implementation_Pragmas => True,
No_Implicit_Conditionals => True,
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index 5fcfb310c9d..1f50db32dab 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -108,8 +108,9 @@ package Rtsfind is
-- ambiguities).
type RTU_Id is (
- -- Runtime packages, for list of accessible entities in each
- -- package see declarations in the runtime entity table below.
+
+ -- Runtime packages, for list of accessible entities in each package,
+ -- see declarations in the runtime entity table below.
RTU_Null,
-- Used as a null entry (will cause an error if referenced)
@@ -132,6 +133,9 @@ package Rtsfind is
Ada_Tags,
Ada_Task_Identification,
Ada_Task_Termination,
+ Ada_Text_IO,
+ Ada_Wide_Text_IO,
+ Ada_Wide_Wide_Text_IO,
-- Children of Ada.Calendar
@@ -701,6 +705,15 @@ package Rtsfind is
RE_Current_Task, -- Ada.Task_Identification
RO_AT_Task_Id, -- Ada.Task_Identification
+ RE_Decimal_IO, -- Ada.Text_IO
+ RE_Fixed_IO, -- Ada.Text_IO
+
+ RO_WT_Decimal_IO, -- Ada.Wide_Text_IO
+ RO_WT_Fixed_IO, -- Ada.Wide_Text_IO
+
+ RO_WW_Decimal_IO, -- Ada.Wide_Wide_Text_IO
+ RO_WW_Fixed_IO, -- Ada.Wide_Wide_Text_IO
+
RE_Integer_8, -- Interfaces
RE_Integer_16, -- Interfaces
RE_Integer_32, -- Interfaces
@@ -1973,6 +1986,15 @@ package Rtsfind is
RE_Current_Task => Ada_Task_Identification,
RO_AT_Task_Id => Ada_Task_Identification,
+ RE_Decimal_IO => Ada_Text_IO,
+ RE_Fixed_IO => Ada_Text_IO,
+
+ RO_WT_Decimal_IO => Ada_Wide_Text_IO,
+ RO_WT_Fixed_IO => Ada_Wide_Text_IO,
+
+ RO_WW_Decimal_IO => Ada_Wide_Wide_Text_IO,
+ RO_WW_Fixed_IO => Ada_Wide_Wide_Text_IO,
+
RE_Integer_8 => Interfaces,
RE_Integer_16 => Interfaces,
RE_Integer_32 => Interfaces,
diff --git a/gcc/ada/s-arit64.adb b/gcc/ada/s-arit64.adb
index ce4f75abef5..51b05f9a235 100644
--- a/gcc/ada/s-arit64.adb
+++ b/gcc/ada/s-arit64.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -30,6 +30,7 @@
------------------------------------------------------------------------------
with Interfaces; use Interfaces;
+
with Ada.Unchecked_Conversion;
package body System.Arith_64 is
@@ -47,106 +48,55 @@ package body System.Arith_64 is
-- Local Subprograms --
-----------------------
- function "+" (A, B : Uns32) return Uns64;
- function "+" (A : Uns64; B : Uns32) return Uns64;
- pragma Inline ("+");
+ function "+" (A, B : Uns32) return Uns64 is (Uns64 (A) + Uns64 (B));
+ function "+" (A : Uns64; B : Uns32) return Uns64 is (A + Uns64 (B));
-- Length doubling additions
- function "*" (A, B : Uns32) return Uns64;
- pragma Inline ("*");
+ function "*" (A, B : Uns32) return Uns64 is (Uns64 (A) * Uns64 (B));
-- Length doubling multiplication
- function "/" (A : Uns64; B : Uns32) return Uns64;
- pragma Inline ("/");
+ function "/" (A : Uns64; B : Uns32) return Uns64 is (A / Uns64 (B));
-- Length doubling division
- function "rem" (A : Uns64; B : Uns32) return Uns64;
- pragma Inline ("rem");
- -- Length doubling remainder
-
- function "&" (Hi, Lo : Uns32) return Uns64;
- pragma Inline ("&");
+ function "&" (Hi, Lo : Uns32) return Uns64 is
+ (Shift_Left (Uns64 (Hi), 32) or Uns64 (Lo));
-- Concatenate hi, lo values to form 64-bit result
+ function "abs" (X : Int64) return Uns64 is
+ (if X = Int64'First then 2**63 else Uns64 (Int64'(abs X)));
+ -- Convert absolute value of X to unsigned. Note that we can't just use
+ -- the expression of the Else, because it overflows for X = Int64'First.
+
+ function "rem" (A : Uns64; B : Uns32) return Uns64 is (A rem Uns64 (B));
+ -- Length doubling remainder
+
function Le3 (X1, X2, X3 : Uns32; Y1, Y2, Y3 : Uns32) return Boolean;
-- Determines if 96 bit value X1&X2&X3 <= Y1&Y2&Y3
- function Lo (A : Uns64) return Uns32;
- pragma Inline (Lo);
+ function Lo (A : Uns64) return Uns32 is (Uns32 (A and 16#FFFF_FFFF#));
-- Low order half of 64-bit value
- function Hi (A : Uns64) return Uns32;
- pragma Inline (Hi);
+ function Hi (A : Uns64) return Uns32 is (Uns32 (Shift_Right (A, 32)));
-- High order half of 64-bit value
procedure Sub3 (X1, X2, X3 : in out Uns32; Y1, Y2, Y3 : Uns32);
-- Computes X1&X2&X3 := X1&X2&X3 - Y1&Y1&Y3 with mod 2**96 wrap
- function To_Neg_Int (A : Uns64) return Int64;
+ function To_Neg_Int (A : Uns64) return Int64 with Inline;
-- Convert to negative integer equivalent. If the input is in the range
-- 0 .. 2 ** 63, then the corresponding negative signed integer (obtained
-- by negating the given value) is returned, otherwise constraint error
-- is raised.
- function To_Pos_Int (A : Uns64) return Int64;
+ function To_Pos_Int (A : Uns64) return Int64 with Inline;
-- Convert to positive integer equivalent. If the input is in the range
-- 0 .. 2 ** 63-1, then the corresponding non-negative signed integer is
-- returned, otherwise constraint error is raised.
- procedure Raise_Error;
+ procedure Raise_Error with Inline;
pragma No_Return (Raise_Error);
-- Raise constraint error with appropriate message
- ---------
- -- "&" --
- ---------
-
- function "&" (Hi, Lo : Uns32) return Uns64 is
- begin
- return Shift_Left (Uns64 (Hi), 32) or Uns64 (Lo);
- end "&";
-
- ---------
- -- "*" --
- ---------
-
- function "*" (A, B : Uns32) return Uns64 is
- begin
- return Uns64 (A) * Uns64 (B);
- end "*";
-
- ---------
- -- "+" --
- ---------
-
- function "+" (A, B : Uns32) return Uns64 is
- begin
- return Uns64 (A) + Uns64 (B);
- end "+";
-
- function "+" (A : Uns64; B : Uns32) return Uns64 is
- begin
- return A + Uns64 (B);
- end "+";
-
- ---------
- -- "/" --
- ---------
-
- function "/" (A : Uns64; B : Uns32) return Uns64 is
- begin
- return A / Uns64 (B);
- end "/";
-
- -----------
- -- "rem" --
- -----------
-
- function "rem" (A : Uns64; B : Uns32) return Uns64 is
- begin
- return A rem Uns64 (B);
- end "rem";
-
--------------------------
-- Add_With_Ovflo_Check --
--------------------------
@@ -178,13 +128,13 @@ package body System.Arith_64 is
Q, R : out Int64;
Round : Boolean)
is
- Xu : constant Uns64 := To_Uns (abs X);
- Yu : constant Uns64 := To_Uns (abs Y);
+ Xu : constant Uns64 := abs X;
+ Yu : constant Uns64 := abs Y;
Yhi : constant Uns32 := Hi (Yu);
Ylo : constant Uns32 := Lo (Yu);
- Zu : constant Uns64 := To_Uns (abs Z);
+ Zu : constant Uns64 := abs Z;
Zhi : constant Uns32 := Hi (Zu);
Zlo : constant Uns32 := Lo (Zu);
@@ -260,15 +210,6 @@ package body System.Arith_64 is
end if;
end Double_Divide;
- --------
- -- Hi --
- --------
-
- function Hi (A : Uns64) return Uns32 is
- begin
- return Uns32 (Shift_Right (A, 32));
- end Hi;
-
---------
-- Le3 --
---------
@@ -288,25 +229,16 @@ package body System.Arith_64 is
end if;
end Le3;
- --------
- -- Lo --
- --------
-
- function Lo (A : Uns64) return Uns32 is
- begin
- return Uns32 (A and 16#FFFF_FFFF#);
- end Lo;
-
-------------------------------
-- Multiply_With_Ovflo_Check --
-------------------------------
function Multiply_With_Ovflo_Check (X, Y : Int64) return Int64 is
- Xu : constant Uns64 := To_Uns (abs X);
+ Xu : constant Uns64 := abs X;
Xhi : constant Uns32 := Hi (Xu);
Xlo : constant Uns32 := Lo (Xu);
- Yu : constant Uns64 := To_Uns (abs Y);
+ Yu : constant Uns64 := abs Y;
Yhi : constant Uns32 := Hi (Yu);
Ylo : constant Uns32 := Lo (Yu);
@@ -373,15 +305,15 @@ package body System.Arith_64 is
Q, R : out Int64;
Round : Boolean)
is
- Xu : constant Uns64 := To_Uns (abs X);
+ Xu : constant Uns64 := abs X;
Xhi : constant Uns32 := Hi (Xu);
Xlo : constant Uns32 := Lo (Xu);
- Yu : constant Uns64 := To_Uns (abs Y);
+ Yu : constant Uns64 := abs Y;
Yhi : constant Uns32 := Hi (Yu);
Ylo : constant Uns32 := Lo (Yu);
- Zu : Uns64 := To_Uns (abs Z);
+ Zu : Uns64 := abs Z;
Zhi : Uns32 := Hi (Zu);
Zlo : Uns32 := Lo (Zu);
@@ -646,7 +578,6 @@ package body System.Arith_64 is
function To_Neg_Int (A : Uns64) return Int64 is
R : constant Int64 := -To_Int (A);
-
begin
if R <= 0 then
return R;
@@ -661,7 +592,6 @@ package body System.Arith_64 is
function To_Pos_Int (A : Uns64) return Int64 is
R : constant Int64 := To_Int (A);
-
begin
if R >= 0 then
return R;
diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c
index 5a034d58457..9b5edb2a592 100644
--- a/gcc/ada/s-oscons-tmplt.c
+++ b/gcc/ada/s-oscons-tmplt.c
@@ -159,7 +159,8 @@ pragma Style_Checks ("M32766");
# include <signal.h>
#endif
-#ifdef __MINGW32__
+#if defined(__MINGW32__) || defined(__CYGWIN__)
+# include <windef.h>
# include <winbase.h>
#endif
@@ -986,7 +987,7 @@ CND(VEOL2, "Alternative EOL")
#endif /* HAVE_TERMIOS */
-#ifdef __MINGW32__
+#if defined(__MINGW32__) || defined(__CYGWIN__)
CNU(DTR_CONTROL_ENABLE, "Enable DTR flow ctrl")
CNU(RTS_CONTROL_ENABLE, "Enable RTS flow ctrl")
#endif
diff --git a/gcc/ada/s-rident.ads b/gcc/ada/s-rident.ads
index a7334c8f874..4f22a1943dd 100644
--- a/gcc/ada/s-rident.ads
+++ b/gcc/ada/s-rident.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -112,6 +112,7 @@ package System.Rident is
No_Exception_Registration, -- GNAT
No_Exceptions, -- (RM H.4(12))
No_Finalization, -- GNAT
+ No_Fixed_IO, -- GNAT
No_Fixed_Point, -- (RM H.4(15))
No_Floating_Point, -- (RM H.4(14))
No_IO, -- (RM H.4(20))
diff --git a/gcc/ada/s-taprop.ads b/gcc/ada/s-taprop.ads
index 6f15ce7f55e..efe9dd265a1 100644
--- a/gcc/ada/s-taprop.ads
+++ b/gcc/ada/s-taprop.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNARL is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -324,15 +324,15 @@ package System.Task_Primitives.Operations is
Prio : System.Any_Priority;
Loss_Of_Inheritance : Boolean := False);
pragma Inline (Set_Priority);
- -- Set the priority of the task specified by T to T.Current_Priority. The
- -- priority set is what would correspond to the Ada concept of "base
- -- priority" in the terms of the lower layer system, but the operation may
- -- be used by the upper layer to implement changes in "active priority"
- -- that are not due to lock effects. The effect should be consistent with
- -- the Ada Reference Manual. In particular, when a task lowers its
- -- priority due to the loss of inherited priority, it goes at the head of
- -- the queue for its new priority (RM D.2.2 par 9). Loss_Of_Inheritance
- -- helps the underlying implementation to do it right when the OS doesn't.
+ -- Set the priority of the task specified by T to Prio. The priority set
+ -- is what would correspond to the Ada concept of "base priority" in the
+ -- terms of the lower layer system, but the operation may be used by the
+ -- upper layer to implement changes in "active priority" that are not due
+ -- to lock effects. The effect should be consistent with the Ada Reference
+ -- Manual. In particular, when a task lowers its priority due to the loss
+ -- of inherited priority, it goes at the head of the queue for its new
+ -- priority (RM D.2.2 par 9). Loss_Of_Inheritance helps the underlying
+ -- implementation to do it right when the OS doesn't.
function Get_Priority (T : ST.Task_Id) return System.Any_Priority;
pragma Inline (Get_Priority);
diff --git a/gcc/ada/seh_init.c b/gcc/ada/seh_init.c
index 0d04b507578..c8e65124413 100644
--- a/gcc/ada/seh_init.c
+++ b/gcc/ada/seh_init.c
@@ -6,7 +6,7 @@
* *
* C Implementation File *
* *
- * Copyright (C) 2005-2013, Free Software Foundation, Inc. *
+ * Copyright (C) 2005-2014, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
@@ -32,6 +32,12 @@
/* This unit contains support for SEH (Structured Exception Handling).
Right now the only implementation is for Win32. */
+#if defined (_WIN32) || (defined (__CYGWIN__) && defined (__SEH__))
+/* Include system headers, before system.h poisons malloc. */
+#include <windows.h>
+#include <excpt.h>
+#endif
+
#ifdef IN_RTS
#include "tconfig.h"
#include "tsystem.h"
@@ -64,10 +70,7 @@ extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *)
ATTRIBUTE_NORETURN;
-#if defined (_WIN32)
-
-#include <windows.h>
-#include <excpt.h>
+#if defined (_WIN32) || (defined (__CYGWIN__) && defined (__SEH__))
/* Prototypes. */
extern void _global_unwind2 (void *);
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index a561f066d86..968ba008ec3 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -3627,6 +3627,16 @@ package body Sem_Attr is
Resolve (E1, P_Base_Type);
Check_Enum_Image;
Validate_Non_Static_Attribute_Function_Call;
+
+ -- Check restriction No_Fixed_IO. Note the check of Comes_From_Source
+ -- to avoid giving a duplicate message for Img expanded into Image.
+
+ if Restriction_Check_Required (No_Fixed_IO)
+ and then Comes_From_Source (N)
+ and then Is_Fixed_Point_Type (P_Type)
+ then
+ Check_Restriction (No_Fixed_IO, P);
+ end if;
end Image;
---------
@@ -3646,6 +3656,14 @@ package body Sem_Attr is
end if;
Check_Enum_Image;
+
+ -- Check restriction No_Fixed_IO
+
+ if Restriction_Check_Required (No_Fixed_IO)
+ and then Is_Fixed_Point_Type (P_Type)
+ then
+ Check_Restriction (No_Fixed_IO, P);
+ end if;
end Img;
-----------
@@ -6172,7 +6190,7 @@ package body Sem_Attr is
Comp_Or_Discr := Next_Entity (Comp_Or_Discr);
end loop;
- -- Diagnose possible erroneous references
+ -- Diagnose possible illegal references
if Present (Comp_Or_Discr) then
if Ekind (Comp_Or_Discr) = E_Discriminant then
@@ -6458,6 +6476,14 @@ package body Sem_Attr is
Set_Etype (N, P_Base_Type);
Validate_Non_Static_Attribute_Function_Call;
+
+ -- Check restriction No_Fixed_IO
+
+ if Restriction_Check_Required (No_Fixed_IO)
+ and then Is_Fixed_Point_Type (P_Type)
+ then
+ Check_Restriction (No_Fixed_IO, P);
+ end if;
end Value;
----------------
@@ -6498,6 +6524,14 @@ package body Sem_Attr is
Check_E1;
Resolve (E1, P_Base_Type);
Validate_Non_Static_Attribute_Function_Call;
+
+ -- Check restriction No_Fixed_IO
+
+ if Restriction_Check_Required (No_Fixed_IO)
+ and then Is_Fixed_Point_Type (P_Type)
+ then
+ Check_Restriction (No_Fixed_IO, P);
+ end if;
end Wide_Image;
---------------------
@@ -6511,6 +6545,14 @@ package body Sem_Attr is
Check_E1;
Resolve (E1, P_Base_Type);
Validate_Non_Static_Attribute_Function_Call;
+
+ -- Check restriction No_Fixed_IO
+
+ if Restriction_Check_Required (No_Fixed_IO)
+ and then Is_Fixed_Point_Type (P_Type)
+ then
+ Check_Restriction (No_Fixed_IO, P);
+ end if;
end Wide_Wide_Image;
----------------
@@ -6528,6 +6570,14 @@ package body Sem_Attr is
Set_Etype (N, P_Type);
Validate_Non_Static_Attribute_Function_Call;
+
+ -- Check restriction No_Fixed_IO
+
+ if Restriction_Check_Required (No_Fixed_IO)
+ and then Is_Fixed_Point_Type (P_Type)
+ then
+ Check_Restriction (No_Fixed_IO, P);
+ end if;
end Wide_Value;
---------------------
@@ -6544,6 +6594,14 @@ package body Sem_Attr is
Set_Etype (N, P_Type);
Validate_Non_Static_Attribute_Function_Call;
+
+ -- Check restriction No_Fixed_IO
+
+ if Restriction_Check_Required (No_Fixed_IO)
+ and then Is_Fixed_Point_Type (P_Type)
+ then
+ Check_Restriction (No_Fixed_IO, P);
+ end if;
end Wide_Wide_Value;
---------------------
diff --git a/gcc/ada/sem_aux.adb b/gcc/ada/sem_aux.adb
index 77ed9c2a225..897d99b4d22 100644
--- a/gcc/ada/sem_aux.adb
+++ b/gcc/ada/sem_aux.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -1008,7 +1008,7 @@ package body Sem_Aux is
-- Otherwise we will look around to see if there is some other reason
-- for it to be limited, except that if an error was posted on the
-- entity, then just assume it is non-limited, because it can cause
- -- trouble to recurse into a murky erroneous entity.
+ -- trouble to recurse into a murky entity resulting from other errors.
elsif Error_Posted (Ent) then
return False;
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index 5aa090446b6..2d7487667bc 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -3588,7 +3588,6 @@ package body Sem_Ch12 is
Set_Instance_Env (Gen_Unit, Act_Decl_Id);
Set_Defining_Unit_Name (Act_Spec, Act_Decl_Name);
Set_Is_Generic_Instance (Act_Decl_Id);
-
Set_Generic_Parent (Act_Spec, Gen_Unit);
-- References to the generic in its own declaration or its body are
@@ -8171,8 +8170,8 @@ package body Sem_Ch12 is
Must_Delay : Boolean;
- function Enclosing_Subp (Id : Entity_Id) return Entity_Id;
- -- Find subprogram (if any) that encloses instance and/or generic body
+ function In_Same_Enclosing_Subp return Boolean;
+ -- Check whether instance and generic body are within same subprogram.
function True_Sloc (N : Node_Id) return Source_Ptr;
-- If the instance is nested inside a generic unit, the Sloc of the
@@ -8182,23 +8181,39 @@ package body Sem_Ch12 is
-- origin of a node by finding the maximum sloc of any ancestor node.
-- Why is this not equivalent to Top_Level_Location ???
- --------------------
- -- Enclosing_Subp --
- --------------------
+ ----------------------------
+ -- In_Same_Enclosing_Subp --
+ ----------------------------
- function Enclosing_Subp (Id : Entity_Id) return Entity_Id is
+ function In_Same_Enclosing_Subp return Boolean is
Scop : Entity_Id;
+ Subp : Entity_Id;
begin
- Scop := Scope (Id);
+ Scop := Scope (Act_Id);
while Scop /= Standard_Standard
and then not Is_Overloadable (Scop)
loop
Scop := Scope (Scop);
end loop;
- return Scop;
- end Enclosing_Subp;
+ if Scop = Standard_Standard then
+ return False;
+ else
+ Subp := Scop;
+ end if;
+
+ Scop := Scope (Gen_Id);
+ while Scop /= Standard_Standard loop
+ if Scop = Subp then
+ return True;
+ else
+ Scop := Scope (Scop);
+ end if;
+ end loop;
+
+ return False;
+ end In_Same_Enclosing_Subp;
---------------
-- True_Sloc --
@@ -8242,10 +8257,10 @@ package body Sem_Ch12 is
-- the generic body appears textually later, and the generic body is
-- also in the main unit.
- -- If instance is nested within a subprogram, and the generic body is
- -- not, the instance is delayed because the enclosing body is. If
- -- instance and body are within the same scope, or the same sub-
- -- program body, indicate explicitly that the instance is delayed.
+ -- If instance is nested within a subprogram, and the generic body
+ -- is not, the instance is delayed because the enclosing body is. If
+ -- instance and body are within the same scope, or the same subprogram
+ -- body, indicate explicitly that the instance is delayed.
Must_Delay :=
(Gen_Unit = Act_Unit
@@ -8255,8 +8270,7 @@ package body Sem_Ch12 is
and then True_Sloc (N) < Sloc (Orig_Body)))
and then Is_In_Main_Unit (Gen_Unit)
and then (Scope (Act_Id) = Scope (Gen_Id)
- or else
- Enclosing_Subp (Act_Id) = Enclosing_Subp (Gen_Id)));
+ or else In_Same_Enclosing_Subp));
-- If this is an early instantiation, the freeze node is placed after
-- the generic body. Otherwise, if the generic appears in an instance,
@@ -8294,14 +8308,14 @@ package body Sem_Ch12 is
-- package Inst is new ...
-- In this particular scenario, the freeze node for Inst must
- -- be inserted in the same manner as that of Parent_Inst -
+ -- be inserted in the same manner as that of Parent_Inst,
-- before the next source body or at the end of the declarative
-- list (body not available). If body P did not exist and
-- Parent_Inst was frozen after Inst, either by a body
- -- following Inst or at the end of the declarative region, the
- -- freeze node for Inst must be inserted after that of
- -- Parent_Inst. This relation is established by comparing the
- -- Slocs of Parent_Inst freeze node and Inst.
+ -- following Inst or at the end of the declarative region,
+ -- the freeze node for Inst must be inserted after that of
+ -- Parent_Inst. This relation is established by comparing
+ -- the Slocs of Parent_Inst freeze node and Inst.
if List_Containing (Get_Package_Instantiation_Node (Par)) =
List_Containing (N)
@@ -9927,6 +9941,63 @@ package body Sem_Ch12 is
-- List of primitives made temporarily visible in the instantiation
-- to match the visibility of the formal type
+ procedure Check_Initialized_Types;
+ -- In a generic package body, an entity of a generic private type may
+ -- appear uninitialized. This is suspicious, unless the actual is a
+ -- fully initialized type.
+
+ -----------------------------
+ -- Check_Initialized_Types --
+ -----------------------------
+
+ procedure Check_Initialized_Types is
+ Decl : Node_Id;
+ Formal : Entity_Id;
+ Actual : Entity_Id;
+
+ begin
+ Decl := First (Generic_Formal_Declarations (Gen_Decl));
+ while Present (Decl) loop
+ if (Nkind (Decl) = N_Private_Extension_Declaration
+ and then Needs_Initialized_Actual (Decl))
+
+ or else (Nkind (Decl) = N_Formal_Type_Declaration
+ and then Nkind (Formal_Type_Definition (Decl)) =
+ N_Formal_Private_Type_Definition
+ and then Needs_Initialized_Actual
+ (Formal_Type_Definition (Decl)))
+ then
+ Formal := Defining_Identifier (Decl);
+ Actual := First_Entity (Act_Decl_Id);
+
+ -- For each formal there is a subtype declaration that renames
+ -- the actual and has the same name as the formal.
+
+ while Present (Actual) loop
+ exit when Ekind (Actual) = E_Package
+ and then Present (Renamed_Object (Actual));
+
+ if Chars (Actual) = Chars (Formal)
+ and then not Is_Scalar_Type (Actual)
+ and then not Is_Fully_Initialized_Type (Actual)
+ and then Warn_On_No_Value_Assigned
+ then
+ Error_Msg_NE
+ ("from its use in generic unit, actual for& should "
+ & "be fully initialized type??", Actual, Formal);
+ exit;
+ end if;
+
+ Next_Entity (Actual);
+ end loop;
+ end if;
+
+ Next (Decl);
+ end loop;
+ end Check_Initialized_Types;
+
+ -- Start of processing for Instantiate_Package_Body
+
begin
Gen_Body_Id := Corresponding_Body (Gen_Decl);
@@ -9999,6 +10070,7 @@ package body Sem_Ch12 is
Set_Corresponding_Spec (Act_Body, Act_Decl_Id);
Check_Generic_Actuals (Act_Decl_Id, False);
+ Check_Initialized_Types;
-- Install primitives hidden at the point of the instantiation but
-- visible when processing the generic formals
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 1f8d73f2519..bf42b0eebc4 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -48,7 +48,6 @@ with Sem_Case; use Sem_Case;
with Sem_Ch3; use Sem_Ch3;
with Sem_Ch6; use Sem_Ch6;
with Sem_Ch8; use Sem_Ch8;
-with Sem_Ch9; use Sem_Ch9;
with Sem_Dim; use Sem_Dim;
with Sem_Disp; use Sem_Disp;
with Sem_Eval; use Sem_Eval;
@@ -490,7 +489,7 @@ package body Sem_Ch13 is
-- We need to sort the component clauses on the basis of the
-- Position values in the clause, so we can group clauses with
- -- the same Position. together to determine the relevant machine
+ -- the same Position together to determine the relevant machine
-- scalar size.
Sort_CC : declare
@@ -538,7 +537,7 @@ package body Sem_Ch13 is
Comps (To) := Comps (From);
end CP_Move;
- -- Start of processing for Sort_CC
+ -- Start of processing for Sort_CC
begin
-- Collect the machine scalar relevant component clauses
@@ -1162,7 +1161,8 @@ package body Sem_Ch13 is
procedure Insert_Delayed_Pragma (Prag : Node_Id);
-- Insert a postcondition-like pragma into the tree depending on the
-- context. Prag must denote one of the following: Pre, Post, Depends,
- -- Global or Contract_Cases.
+ -- Global or Contract_Cases. This procedure is also used for the case
+ -- of Attach_Handler which has similar requirements for placement.
--------------------------------
-- Decorate_Aspect_And_Pragma --
@@ -1464,7 +1464,7 @@ package body Sem_Ch13 is
Check_Restriction_No_Specification_Of_Aspect (Aspect);
- -- Analyze this aspect (actual analysis is delayed till later)
+ -- Mark aspect analyzed (actual analysis is delayed till later)
Set_Analyzed (Aspect);
Set_Entity (Aspect, E);
@@ -1679,6 +1679,12 @@ package body Sem_Ch13 is
Expression => Relocate_Node (Expr))),
Pragma_Name => Name_Attach_Handler);
+ -- We need to insert this pragma into the tree to get proper
+ -- processing and to look valid from a placement viewpoint.
+
+ Insert_Delayed_Pragma (Aitem);
+ goto Continue;
+
-- Dynamic_Predicate, Predicate, Static_Predicate
when Aspect_Dynamic_Predicate |
@@ -10059,6 +10065,24 @@ package body Sem_Ch13 is
Unchecked_Conversions.Init;
end Initialize;
+ ---------------------------
+ -- Install_Discriminants --
+ ---------------------------
+
+ procedure Install_Discriminants (E : Entity_Id) is
+ Disc : Entity_Id;
+ Prev : Entity_Id;
+ begin
+ Disc := First_Discriminant (E);
+ while Present (Disc) loop
+ Prev := Current_Entity (Disc);
+ Set_Current_Entity (Disc);
+ Set_Is_Immediately_Visible (Disc);
+ Set_Homonym (Disc, Prev);
+ Next_Discriminant (Disc);
+ end loop;
+ end Install_Discriminants;
+
-------------------------
-- Is_Operational_Item --
-------------------------
@@ -10433,6 +10457,24 @@ package body Sem_Ch13 is
end if;
end New_Stream_Subprogram;
+ ------------------------------------------
+ -- Push_Scope_And_Install_Discriminants --
+ ------------------------------------------
+
+ procedure Push_Scope_And_Install_Discriminants (E : Entity_Id) is
+ begin
+ if Has_Discriminants (E) then
+ Push_Scope (E);
+
+ -- Make discriminants visible for type declarations and protected
+ -- type declarations, not for subtype declarations (RM 13.1.1 (12/3))
+
+ if Nkind (Parent (E)) /= N_Subtype_Declaration then
+ Install_Discriminants (E);
+ end if;
+ end if;
+ end Push_Scope_And_Install_Discriminants;
+
------------------------
-- Rep_Item_Too_Early --
------------------------
@@ -11138,6 +11180,69 @@ package body Sem_Ch13 is
end if;
end Set_Enum_Esize;
+ -----------------------------
+ -- Uninstall_Discriminants --
+ -----------------------------
+
+ procedure Uninstall_Discriminants (E : Entity_Id) is
+ Disc : Entity_Id;
+ Prev : Entity_Id;
+ Outer : Entity_Id;
+
+ begin
+ -- Discriminants have been made visible for type declarations and
+ -- protected type declarations, not for subtype declarations.
+
+ if Nkind (Parent (E)) /= N_Subtype_Declaration then
+ Disc := First_Discriminant (E);
+ while Present (Disc) loop
+ if Disc /= Current_Entity (Disc) then
+ Prev := Current_Entity (Disc);
+ while Present (Prev)
+ and then Present (Homonym (Prev))
+ and then Homonym (Prev) /= Disc
+ loop
+ Prev := Homonym (Prev);
+ end loop;
+ else
+ Prev := Empty;
+ end if;
+
+ Set_Is_Immediately_Visible (Disc, False);
+
+ Outer := Homonym (Disc);
+ while Present (Outer) and then Scope (Outer) = E loop
+ Outer := Homonym (Outer);
+ end loop;
+
+ -- Reset homonym link of other entities, but do not modify link
+ -- between entities in current scope, so that the back-end can
+ -- have a proper count of local overloadings.
+
+ if No (Prev) then
+ Set_Name_Entity_Id (Chars (Disc), Outer);
+
+ elsif Scope (Prev) /= Scope (Disc) then
+ Set_Homonym (Prev, Outer);
+ end if;
+
+ Next_Discriminant (Disc);
+ end loop;
+ end if;
+ end Uninstall_Discriminants;
+
+ -------------------------------------------
+ -- Uninstall_Discriminants_And_Pop_Scope --
+ -------------------------------------------
+
+ procedure Uninstall_Discriminants_And_Pop_Scope (E : Entity_Id) is
+ begin
+ if Has_Discriminants (E) then
+ Uninstall_Discriminants (E);
+ Pop_Scope;
+ end if;
+ end Uninstall_Discriminants_And_Pop_Scope;
+
------------------------------
-- Validate_Address_Clauses --
------------------------------
diff --git a/gcc/ada/sem_ch13.ads b/gcc/ada/sem_ch13.ads
index 222ae06c6a8..0f31265b621 100644
--- a/gcc/ada/sem_ch13.ads
+++ b/gcc/ada/sem_ch13.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -331,4 +331,27 @@ package Sem_Ch13 is
-- for First, Next, and Has_Element. Optionally an Element primitive may
-- also be defined.
+ -----------------------------------------------------------
+ -- Visibility of Discriminants in Aspect Specifications --
+ -----------------------------------------------------------
+
+ -- The discriminants of a type are visible when analyzing the aspect
+ -- specifications of a type declaration or protected type declaration,
+ -- but not when analyzing those of a subtype declaration. The following
+ -- routines enforce this distinction.
+
+ procedure Install_Discriminants (E : Entity_Id);
+ -- Make visible the discriminants of type entity E
+
+ procedure Push_Scope_And_Install_Discriminants (E : Entity_Id);
+ -- Push scope E and makes visible the discriminants of type entity E if E
+ -- has discriminants and is not a subtype.
+
+ procedure Uninstall_Discriminants (E : Entity_Id);
+ -- Remove visibility to the discriminants of type entity E
+
+ procedure Uninstall_Discriminants_And_Pop_Scope (E : Entity_Id);
+ -- Remove visibility to the discriminants of type entity E and pop the
+ -- scope stack if E has discriminants and is not a subtype.
+
end Sem_Ch13;
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index b6d22cb50cc..293a3f695cd 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -919,19 +919,16 @@ package body Sem_Ch3 is
-- include an expression that is an allocator, whose expansion needs the
-- proper Master for the created tasks.
- if Nkind (Related_Nod) = N_Object_Declaration
- and then Expander_Active
+ if Nkind (Related_Nod) = N_Object_Declaration and then Expander_Active
then
- if Is_Interface (Desig_Type)
- and then Is_Limited_Record (Desig_Type)
+ if Is_Interface (Desig_Type) and then Is_Limited_Record (Desig_Type)
then
Build_Class_Wide_Master (Anon_Type);
-- Similarly, if the type is an anonymous access that designates
-- tasks, create a master entity for it in the current context.
- elsif Has_Task (Desig_Type)
- and then Comes_From_Source (Related_Nod)
+ elsif Has_Task (Desig_Type) and then Comes_From_Source (Related_Nod)
then
Build_Master_Entity (Defining_Identifier (Related_Nod));
Build_Master_Renaming (Anon_Type);
@@ -1205,8 +1202,7 @@ package body Sem_Ch3 is
-- use previous subprogram type as the designated type, and then
-- remove scope added above.
- if ASIS_Mode
- and then Present (Scope (Defining_Identifier (F)))
+ if ASIS_Mode and then Present (Scope (Defining_Identifier (F)))
then
Set_Etype (T_Name, T_Name);
Init_Size_Align (T_Name);
@@ -1355,8 +1351,7 @@ package body Sem_Ch3 is
-- its own context, allowing the following circularity that cannot be
-- detected earlier
- elsif Is_Class_Wide_Type (Full_Desig)
- and then Etype (Full_Desig) = T
+ elsif Is_Class_Wide_Type (Full_Desig) and then Etype (Full_Desig) = T
then
Error_Msg_N
("access type cannot designate its own classwide type", S);
@@ -1755,9 +1750,8 @@ package body Sem_Ch3 is
case Nkind (Constr) is
when N_Attribute_Reference =>
- return
- Attribute_Name (Constr) = Name_Access
- and then Prefix (Constr) = Scope (Entity (Prefix (Constr)));
+ return Attribute_Name (Constr) = Name_Access
+ and then Prefix (Constr) = Scope (Entity (Prefix (Constr)));
when N_Discriminant_Association =>
return Denotes_Discriminant (Expression (Constr));
@@ -2319,9 +2313,7 @@ package body Sem_Ch3 is
-- ??? a cleaner approach may be possible and/or this solution
-- could be extended to general-purpose late primitives, TBD.
- if not ASIS_Mode
- and then not Body_Seen
- and then not Is_Body (Decl)
+ if not ASIS_Mode and then not Body_Seen and then not Is_Body (Decl)
then
Body_Seen := True;
@@ -2472,8 +2464,7 @@ package body Sem_Ch3 is
-- imported through a LIMITED WITH clause, it appears as incomplete
-- but has no full view.
- if Ekind (Prev) = E_Incomplete_Type
- and then Present (Full_View (Prev))
+ if Ekind (Prev) = E_Incomplete_Type and then Present (Full_View (Prev))
then
T := Full_View (Prev);
else
@@ -2980,12 +2971,13 @@ package body Sem_Ch3 is
-----------------------------
procedure Analyze_Object_Contract (Obj_Id : Entity_Id) is
- AR_Val : Boolean := False;
- AW_Val : Boolean := False;
- ER_Val : Boolean := False;
- EW_Val : Boolean := False;
- Prag : Node_Id;
- Seen : Boolean := False;
+ Obj_Typ : constant Entity_Id := Etype (Obj_Id);
+ AR_Val : Boolean := False;
+ AW_Val : Boolean := False;
+ ER_Val : Boolean := False;
+ EW_Val : Boolean := False;
+ Prag : Node_Id;
+ Seen : Boolean := False;
begin
if Ekind (Obj_Id) = E_Constant then
@@ -2996,7 +2988,7 @@ package body Sem_Ch3 is
-- actuals in instantiations (SPARK RM 7.1.3(6)).
if SPARK_Mode = On
- and then Is_SPARK_Volatile_Object (Obj_Id)
+ and then Is_SPARK_Volatile (Obj_Id)
and then No (Corresponding_Generic_Association (Parent (Obj_Id)))
then
Error_Msg_N ("constant cannot be volatile", Obj_Id);
@@ -3008,26 +3000,43 @@ package body Sem_Ch3 is
-- they are not standard Ada legality rules.
if SPARK_Mode = On then
+ if Is_SPARK_Volatile (Obj_Id) then
- -- A non-volatile object cannot have volatile components
- -- (SPARK RM 7.1.3(7)).
+ -- The declaration of a volatile object must appear at the
+ -- library level (SPARK RM 7.1.3(7), C.6(6)).
- if not Is_SPARK_Volatile_Object (Obj_Id)
- and then Has_Volatile_Component (Etype (Obj_Id))
- then
- Error_Msg_N
- ("non-volatile variable & cannot have volatile components",
- Obj_Id);
+ if not Is_Library_Level_Entity (Obj_Id) then
+ Error_Msg_N
+ ("volatile variable & must be declared at library level",
+ Obj_Id);
- -- The declaration of a volatile object must appear at the library
- -- level.
+ -- An object of a discriminated type cannot be volatile
+ -- (SPARK RM C.6(4)).
- elsif Is_SPARK_Volatile_Object (Obj_Id)
- and then not Is_Library_Level_Entity (Obj_Id)
- then
- Error_Msg_N
- ("volatile variable & must be declared at library level "
- & "(SPARK RM 7.1.3(5))", Obj_Id);
+ elsif Has_Discriminants (Obj_Typ) then
+ Error_Msg_N
+ ("discriminated object & cannot be volatile", Obj_Id);
+
+ -- An object of a tagged type cannot be volatile
+ -- (SPARK RM C.6(5)).
+
+ elsif Is_Tagged_Type (Obj_Typ) then
+ Error_Msg_N ("tagged object & cannot be volatile", Obj_Id);
+ end if;
+
+ -- The object is not volatile
+
+ else
+ -- A non-volatile object cannot have volatile components
+ -- (SPARK RM 7.1.3(7)).
+
+ if not Is_SPARK_Volatile (Obj_Id)
+ and then Has_Volatile_Component (Obj_Typ)
+ then
+ Error_Msg_N
+ ("non-volatile object & cannot have volatile components",
+ Obj_Id);
+ end if;
end if;
end if;
@@ -3178,7 +3187,6 @@ package body Sem_Ch3 is
if Present (Prev_Entity)
and then
-
-- If the homograph is an implicit subprogram, it is overridden
-- by the current declaration.
@@ -3256,12 +3264,11 @@ package body Sem_Ch3 is
-- Ada 2005 (AI-231): Propagate the null-excluding attribute and carry
-- out some static checks
- if Ada_Version >= Ada_2005
- and then Can_Never_Be_Null (T)
- then
+ if Ada_Version >= Ada_2005 and then Can_Never_Be_Null (T) then
+
-- In case of aggregates we must also take care of the correct
-- initialization of nested aggregates bug this is done at the
- -- point of the analysis of the aggregate (see sem_aggr.adb)
+ -- point of the analysis of the aggregate (see sem_aggr.adb).
if Present (Expression (N))
and then Nkind (Expression (N)) = N_Aggregate
@@ -3505,9 +3512,7 @@ package body Sem_Ch3 is
Set_Current_Value (Id, E);
end if;
- elsif Is_Scalar_Type (T)
- and then Is_OK_Static_Expression (E)
- then
+ elsif Is_Scalar_Type (T) and then Is_OK_Static_Expression (E) then
Set_Is_Known_Valid (Id);
end if;
@@ -3516,9 +3521,7 @@ package body Sem_Ch3 is
if Is_Access_Type (T) then
if Known_Non_Null (E) then
Set_Is_Known_Non_Null (Id, True);
- elsif Known_Null (E)
- and then not Can_Never_Be_Null (Id)
- then
+ elsif Known_Null (E) and then not Can_Never_Be_Null (Id) then
Set_Is_Known_Null (Id, True);
end if;
end if;
@@ -3955,9 +3958,7 @@ package body Sem_Ch3 is
declare
Val : constant Node_Id := Constant_Value (Entity (E));
begin
- if Present (Val)
- and then Nkind (Val) = N_String_Literal
- then
+ if Present (Val) and then Nkind (Val) = N_String_Literal then
Rewrite (E, New_Copy (Val));
end if;
end;
@@ -4009,8 +4010,7 @@ package body Sem_Ch3 is
-- Deal with setting In_Private_Part flag if in private part
- if Ekind (Scope (Id)) = E_Package
- and then In_Private_Part (Scope (Id))
+ if Ekind (Scope (Id)) = E_Package and then In_Private_Part (Scope (Id))
then
Set_In_Private_Part (Id);
end if;
@@ -4107,8 +4107,8 @@ package body Sem_Ch3 is
pragma Assert (Prev = T
or else (Ekind (Prev) = E_Incomplete_Type
- and then Present (Full_View (Prev))
- and then Full_View (Prev) = T));
+ and then Present (Full_View (Prev))
+ and then Full_View (Prev) = T));
end;
end if;
@@ -4193,9 +4193,7 @@ package body Sem_Ch3 is
-- Ada 2005 (AI-443): Synchronized private extension or a rewritten
-- synchronized formal derived type.
- if Ada_Version >= Ada_2005
- and then Synchronized_Present (N)
- then
+ if Ada_Version >= Ada_2005 and then Synchronized_Present (N) then
Set_Is_Limited_Record (T);
-- Formal derived type case
@@ -4206,9 +4204,9 @@ package body Sem_Ch3 is
-- interface.
if (not Is_Tagged_Type (Parent_Type)
- or else not Is_Limited_Type (Parent_Type))
+ or else not Is_Limited_Type (Parent_Type))
and then
- (not Is_Interface (Parent_Type)
+ (not Is_Interface (Parent_Type)
or else not Is_Synchronized_Interface (Parent_Type))
then
Error_Msg_NE ("parent type of & must be tagged limited " &
@@ -4246,8 +4244,7 @@ package body Sem_Ch3 is
else
if not Is_Interface (Parent_Type)
or else (not Is_Limited_Interface (Parent_Type)
- and then
- not Is_Synchronized_Interface (Parent_Type))
+ and then not Is_Synchronized_Interface (Parent_Type))
then
Error_Msg_NE
("parent type of & must be limited interface", N, T);
@@ -4441,9 +4438,7 @@ package body Sem_Ch3 is
-- Subtype of unconstrained array without constraint is not allowed
-- in SPARK.
- if Is_Array_Type (T)
- and then not Is_Constrained (T)
- then
+ if Is_Array_Type (T) and then not Is_Constrained (T) then
Check_SPARK_Restriction
("subtype of unconstrained array must have constraint", N);
end if;
@@ -4730,11 +4725,11 @@ package body Sem_Ch3 is
if Present (Generic_Parent_Type (N))
and then
- (Nkind
- (Parent (Generic_Parent_Type (N))) /= N_Formal_Type_Declaration
+ (Nkind (Parent (Generic_Parent_Type (N))) /=
+ N_Formal_Type_Declaration
or else Nkind
- (Formal_Type_Definition (Parent (Generic_Parent_Type (N))))
- /= N_Formal_Private_Type_Definition)
+ (Formal_Type_Definition (Parent (Generic_Parent_Type (N)))) /=
+ N_Formal_Private_Type_Definition)
then
if Is_Tagged_Type (Id) then
@@ -4755,9 +4750,7 @@ package body Sem_Ch3 is
end if;
end if;
- if Is_Private_Type (T)
- and then Present (Full_View (T))
- then
+ if Is_Private_Type (T) and then Present (Full_View (T)) then
Conditional_Delay (Id, Full_View (T));
-- The subtypes of components or subcomponents of protected types
@@ -4789,8 +4782,7 @@ package body Sem_Ch3 is
-- In the array case, check compatibility for each index
- elsif Is_Array_Type (Etype (Id))
- and then Present (First_Index (Id))
+ elsif Is_Array_Type (Etype (Id)) and then Present (First_Index (Id))
then
-- This really should be a subprogram that finds the indications
-- to check???
@@ -4805,7 +4797,7 @@ package body Sem_Ch3 is
begin
while Present (Subt_Index) loop
if ((Nkind (Subt_Index) = N_Identifier
- and then Ekind (Entity (Subt_Index)) in Scalar_Kind)
+ and then Ekind (Entity (Subt_Index)) in Scalar_Kind)
or else Nkind (Subt_Index) = N_Subtype_Indication)
and then
Nkind (Scalar_Range (Etype (Subt_Index))) = N_Range
@@ -5212,9 +5204,7 @@ package body Sem_Ch3 is
-- Ada 2005 (AI-231): Propagate the null-excluding attribute to the
-- array type to ensure that objects of this type are initialized.
- if Ada_Version >= Ada_2005
- and then Can_Never_Be_Null (Element_Type)
- then
+ if Ada_Version >= Ada_2005 and then Can_Never_Be_Null (Element_Type) then
Set_Can_Never_Be_Null (T);
if Null_Exclusion_Present (Component_Definition (Def))
@@ -5274,9 +5264,7 @@ package body Sem_Ch3 is
-- types created for packed entities do not need such, they are
-- compatible with the user-defined type.
- if Number_Dimensions (T) = 1
- and then not Is_Packed_Array_Type (T)
- then
+ if Number_Dimensions (T) = 1 and then not Is_Packed_Array_Type (T) then
New_Concatenation_Op (T);
end if;
@@ -5569,6 +5557,8 @@ package body Sem_Ch3 is
if Null_Exclusion_Present (Type_Definition (N)) then
Set_Can_Never_Be_Null (Derived_Type);
+ -- What is with the "AND THEN FALSE" here ???
+
if Can_Never_Be_Null (Parent_Type)
and then False
then
@@ -18061,7 +18051,7 @@ package body Sem_Ch3 is
-- (SPARK RM 7.1.3(6)).
if SPARK_Mode = On
- and then Is_SPARK_Volatile_Object (Defining_Identifier (Discr))
+ and then Is_SPARK_Volatile (Defining_Identifier (Discr))
then
Error_Msg_N ("discriminant cannot be volatile", Discr);
end if;
@@ -18184,7 +18174,7 @@ package body Sem_Ch3 is
if Ekind (Typ) = E_Record_Type_With_Private then
- -- Handle the following erroneous case:
+ -- Handle the following illegal usage:
-- type Private_Type is tagged private;
-- private
-- type Private_Type is new Type_Implementing_Iface;
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
index 409ea7bf432..db7e98516ca 100644
--- a/gcc/ada/sem_ch5.adb
+++ b/gcc/ada/sem_ch5.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -1868,9 +1868,17 @@ package body Sem_Ch5 is
if Of_Present (N) then
if Has_Aspect (Typ, Aspect_Iterable) then
- if No (Get_Iterable_Type_Primitive (Typ, Name_Element)) then
- Error_Msg_N ("missing Element primitive for iteration", N);
- end if;
+ declare
+ Elt : constant Entity_Id :=
+ Get_Iterable_Type_Primitive (Typ, Name_Element);
+ begin
+ if No (Elt) then
+ Error_Msg_N
+ ("missing Element primitive for iteration", N);
+ else
+ Set_Etype (Def_Id, Etype (Elt));
+ end if;
+ end;
-- For a predefined container, The type of the loop variable is
-- the Iterator_Element aspect of the container type.
@@ -1977,7 +1985,7 @@ package body Sem_Ch5 is
if SPARK_Mode = On
and then not Of_Present (N)
- and then Is_SPARK_Volatile_Object (Ent)
+ and then Is_SPARK_Volatile (Ent)
then
Error_Msg_N ("loop parameter cannot be volatile", Ent);
end if;
@@ -2352,7 +2360,7 @@ package body Sem_Ch5 is
-- Analyze the subtype definition and create temporaries for the bounds.
-- Do not evaluate the range when preanalyzing a quantified expression
-- because bounds expressed as function calls with side effects will be
- -- erroneously replicated.
+ -- incorrectly replicated.
if Nkind (DS) = N_Range
and then Expander_Active
@@ -2697,7 +2705,7 @@ package body Sem_Ch5 is
-- when SPARK_Mode is on as it is not a standard Ada legality check
-- (SPARK RM 7.1.3(6)).
- if SPARK_Mode = On and then Is_SPARK_Volatile_Object (Id) then
+ if SPARK_Mode = On and then Is_SPARK_Volatile (Id) then
Error_Msg_N ("loop parameter cannot be volatile", Id);
end if;
end Analyze_Loop_Parameter_Specification;
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 2bf9f263d42..01187831fe1 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -2038,9 +2038,9 @@ package body Sem_Ch6 is
Ref_Global : Node_Id := Empty;
begin
- -- When a subprogram body declaration is erroneous, its defining entity
- -- is left unanalyzed. There is nothing left to do in this case because
- -- the body lacks a contract.
+ -- When a subprogram body declaration is illegal, its defining entity is
+ -- left unanalyzed. There is nothing left to do in this case because the
+ -- body lacks a contract.
if not Analyzed (Body_Id) then
return;
@@ -2147,6 +2147,10 @@ package body Sem_Ch6 is
-- chained beyond that point. It is initialized to Empty to deal with
-- the case where there is no separate spec.
+ procedure Analyze_Aspects_On_Body_Or_Stub;
+ -- Analyze the aspect specifications of a subprogram body [stub]. It is
+ -- assumed that N has aspects.
+
procedure Check_Anonymous_Return;
-- Ada 2005: if a function returns an access type that denotes a task,
-- or a type that contains tasks, we must create a master entity for
@@ -2169,11 +2173,6 @@ package body Sem_Ch6 is
-- verify that a function ends with a RETURN and that a procedure does
-- not contain any RETURN.
- procedure Diagnose_Misplaced_Aspect_Specifications;
- -- It is known that subprogram body N has aspects, but they are not
- -- properly placed. Provide specific error messages depending on the
- -- aspects involved.
-
function Disambiguate_Spec return Entity_Id;
-- When a primitive is declared between the private view and the full
-- view of a concurrent type which implements an interface, a special
@@ -2203,6 +2202,127 @@ package body Sem_Ch6 is
-- indicator, check that it is consistent with the known status of the
-- entity.
+ -------------------------------------
+ -- Analyze_Aspects_On_Body_Or_Stub --
+ -------------------------------------
+
+ procedure Analyze_Aspects_On_Body_Or_Stub is
+ procedure Diagnose_Misplaced_Aspects;
+ -- Subprogram body [stub] N has aspects, but they are not properly
+ -- placed. Provide precise diagnostics depending on the aspects
+ -- involved.
+
+ --------------------------------
+ -- Diagnose_Misplaced_Aspects --
+ --------------------------------
+
+ procedure Diagnose_Misplaced_Aspects is
+ Asp : Node_Id;
+ Asp_Nam : Name_Id;
+ Asp_Id : Aspect_Id;
+ -- The current aspect along with its name and id
+
+ procedure SPARK_Aspect_Error (Ref_Nam : Name_Id);
+ -- Emit an error message concerning SPARK aspect Asp. Ref_Nam is
+ -- the name of the refined version of the aspect.
+
+ ------------------------
+ -- SPARK_Aspect_Error --
+ ------------------------
+
+ procedure SPARK_Aspect_Error (Ref_Nam : Name_Id) is
+ begin
+ -- The corresponding spec already contains the aspect in
+ -- question and the one appearing on the body must be the
+ -- refined form:
+
+ -- procedure P with Global ...;
+ -- procedure P with Global ... is ... end P;
+ -- ^
+ -- Refined_Global
+
+ if Has_Aspect (Spec_Id, Asp_Id) then
+ Error_Msg_Name_1 := Asp_Nam;
+
+ -- Subunits cannot carry aspects that apply to a subprogram
+ -- declaration.
+
+ if Nkind (Parent (N)) = N_Subunit then
+ Error_Msg_N ("aspect % cannot apply to a subunit", Asp);
+
+ else
+ Error_Msg_Name_2 := Ref_Nam;
+ Error_Msg_N ("aspect % should be %", Asp);
+ end if;
+
+ -- Otherwise the aspect must appear in the spec, not in the
+ -- body:
+
+ -- procedure P;
+ -- procedure P with Global ... is ... end P;
+
+ else
+ Error_Msg_N
+ ("aspect specification must appear in subprogram "
+ & "declaration", Asp);
+ end if;
+ end SPARK_Aspect_Error;
+
+ -- Start of processing for Diagnose_Misplaced_Aspects
+
+ begin
+ -- Iterate over the aspect specifications and emit specific errors
+ -- where applicable.
+
+ Asp := First (Aspect_Specifications (N));
+ while Present (Asp) loop
+ Asp_Nam := Chars (Identifier (Asp));
+ Asp_Id := Get_Aspect_Id (Asp_Nam);
+
+ -- Do not emit errors on aspects that can appear on a
+ -- subprogram body. This scenario occurs when the aspect
+ -- specification list contains both misplaced and properly
+ -- placed aspects.
+
+ if Aspect_On_Body_Or_Stub_OK (Asp_Id) then
+ null;
+
+ -- Special diagnostics for SPARK aspects
+
+ elsif Asp_Nam = Name_Depends then
+ SPARK_Aspect_Error (Name_Refined_Depends);
+
+ elsif Asp_Nam = Name_Global then
+ SPARK_Aspect_Error (Name_Refined_Global);
+
+ elsif Asp_Nam = Name_Post then
+ SPARK_Aspect_Error (Name_Refined_Post);
+
+ else
+ Error_Msg_N
+ ("aspect specification must appear in subprogram "
+ & "declaration", Asp);
+ end if;
+
+ Next (Asp);
+ end loop;
+ end Diagnose_Misplaced_Aspects;
+
+ -- Start of processing for Analyze_Aspects_On_Body_Or_Stub
+
+ begin
+ -- Language-defined aspects cannot be associated with a subprogram
+ -- body [stub] if the subprogram has a spec. Certain implementation
+ -- defined aspects are allowed to break this rule (for list, see
+ -- table Aspect_On_Body_Or_Stub_OK).
+
+ if Present (Spec_Id) and then not Aspects_On_Body_Or_Stub_OK (N) then
+ Diagnose_Misplaced_Aspects;
+ else
+ Analyze_Aspect_Specifications (N, Body_Id);
+ end if;
+ end Analyze_Aspects_On_Body_Or_Stub;
+
----------------------------
-- Check_Anonymous_Return --
----------------------------
@@ -2455,99 +2575,6 @@ package body Sem_Ch6 is
end if;
end Check_Missing_Return;
- ----------------------------------------------
- -- Diagnose_Misplaced_Aspect_Specifications --
- ----------------------------------------------
-
- procedure Diagnose_Misplaced_Aspect_Specifications is
- Asp : Node_Id;
- Asp_Nam : Name_Id;
- Asp_Id : Aspect_Id;
- -- The current aspect along with its name and id
-
- procedure SPARK_Aspect_Error (Ref_Nam : Name_Id);
- -- Emit an error message concerning SPARK aspect Asp. Ref_Nam is the
- -- name of the refined version of the aspect.
-
- ------------------------
- -- SPARK_Aspect_Error --
- ------------------------
-
- procedure SPARK_Aspect_Error (Ref_Nam : Name_Id) is
- begin
- -- The corresponding spec already contains the aspect in question
- -- and the one appearing on the body must be the refined form:
-
- -- procedure P with Global ...;
- -- procedure P with Global ... is ... end P;
- -- ^
- -- Refined_Global
-
- if Has_Aspect (Spec_Id, Asp_Id) then
- Error_Msg_Name_1 := Asp_Nam;
-
- -- Subunits cannot carry aspects that apply to a subprogram
- -- declaration.
-
- if Nkind (Parent (N)) = N_Subunit then
- Error_Msg_N ("aspect % cannot apply to a subunit", Asp);
-
- else
- Error_Msg_Name_2 := Ref_Nam;
- Error_Msg_N ("aspect % should be %", Asp);
- end if;
-
- -- Otherwise the aspect must appear in the spec, not in the body:
-
- -- procedure P;
- -- procedure P with Global ... is ... end P;
-
- else
- Error_Msg_N
- ("aspect specification must appear in subprogram declaration",
- Asp);
- end if;
- end SPARK_Aspect_Error;
-
- -- Start of processing for Diagnose_Misplaced_Aspect_Specifications
-
- begin
- -- Iterate over the aspect specifications and emit specific errors
- -- where applicable.
-
- Asp := First (Aspect_Specifications (N));
- while Present (Asp) loop
- Asp_Nam := Chars (Identifier (Asp));
- Asp_Id := Get_Aspect_Id (Asp_Nam);
-
- -- Do not emit errors on aspects that can appear on a subprogram
- -- body. This scenario occurs when the aspect specification list
- -- contains both misplaced and properly placed aspects.
-
- if Aspect_On_Body_Or_Stub_OK (Asp_Id) then
- null;
-
- -- Special diagnostics for SPARK aspects
-
- elsif Asp_Nam = Name_Depends then
- SPARK_Aspect_Error (Name_Refined_Depends);
-
- elsif Asp_Nam = Name_Global then
- SPARK_Aspect_Error (Name_Refined_Global);
-
- elsif Asp_Nam = Name_Post then
- SPARK_Aspect_Error (Name_Refined_Post);
-
- else
- Error_Msg_N
- ("aspect specification must appear in subprogram declaration",
- Asp);
- end if;
-
- Next (Asp);
- end loop;
- end Diagnose_Misplaced_Aspect_Specifications;
-
-----------------------
-- Disambiguate_Spec --
-----------------------
@@ -2782,6 +2809,16 @@ package body Sem_Ch6 is
elsif not Present (Overridden_Operation (Spec_Id)) then
Error_Msg_NE
("subprogram& is not overriding", Body_Spec, Spec_Id);
+
+ -- Overriding indicators aren't allowed for protected subprogram
+ -- bodies (see the Confirmation in Ada Comment AC95-00213). Change
+ -- this to a warning if -gnatd.E is enabled.
+
+ elsif Ekind (Scope (Spec_Id)) = E_Protected_Type then
+ Error_Msg_Warn := Error_To_Warning;
+ Error_Msg_N
+ ("<overriding indicator not allowed for protected "
+ & "subprogram body", Body_Spec);
end if;
elsif Must_Not_Override (Body_Spec) then
@@ -2797,20 +2834,37 @@ package body Sem_Ch6 is
("subprogram & overrides predefined operator ",
Body_Spec, Spec_Id);
- -- If this is not a primitive operation or protected subprogram,
- -- then the overriding indicator is altogether illegal.
+ -- Overriding indicators aren't allowed for protected subprogram
+ -- bodies (see the Confirmation in Ada Comment AC95-00213). Change
+ -- this to a warning if -gnatd.E is enabled.
+
+ elsif Ekind (Scope (Spec_Id)) = E_Protected_Type then
+ Error_Msg_Warn := Error_To_Warning;
- elsif not Is_Primitive (Spec_Id)
- and then Ekind (Scope (Spec_Id)) /= E_Protected_Type
- then
+ Error_Msg_N
+ ("<overriding indicator not allowed " &
+ "for protected subprogram body",
+ Body_Spec);
+
+ -- If this is not a primitive operation, then the overriding
+ -- indicator is altogether illegal.
+
+ elsif not Is_Primitive (Spec_Id) then
Error_Msg_N
("overriding indicator only allowed " &
"if subprogram is primitive",
Body_Spec);
end if;
+ -- If checking the style rule and the operation overrides, then
+ -- issue a warning about a missing overriding_indicator. Protected
+ -- subprogram bodies are excluded from this style checking, since
+ -- they aren't primitives (even though their declarations can
+ -- override) and aren't allowed to have an overriding_indicator.
+
elsif Style_Check
and then Present (Overridden_Operation (Spec_Id))
+ and then Ekind (Scope (Spec_Id)) /= E_Protected_Type
then
pragma Assert (Unit_Declaration_Node (Body_Id) = N);
Style.Missing_Overriding (N, Body_Id);
@@ -2921,21 +2975,6 @@ package body Sem_Ch6 is
end if;
end if;
- -- Language-defined aspects cannot appear on a subprogram body [stub] if
- -- the subprogram has a spec. Certain implementation-defined aspects are
- -- allowed to break this rule (see table Aspect_On_Body_Or_Stub_OK).
-
- if Has_Aspects (N) then
- if Present (Spec_Id)
- and then not Aspects_On_Body_Or_Stub_OK (N)
- then
- Diagnose_Misplaced_Aspect_Specifications;
-
- else
- Analyze_Aspect_Specifications (N, Body_Id);
- end if;
- end if;
-
-- Previously we scanned the body to look for nested subprograms, and
-- rejected an inline directive if nested subprograms were present,
-- because the back-end would generate conflicting symbols for the
@@ -3272,6 +3311,17 @@ package body Sem_Ch6 is
Check_Eliminated (Body_Id);
if Nkind (N) = N_Subprogram_Body_Stub then
+
+ -- Analyze any aspect specifications that appear on the subprogram
+ -- body stub.
+
+ if Has_Aspects (N) then
+ Analyze_Aspects_On_Body_Or_Stub;
+ end if;
+
+ -- Stop the analysis now as the stub cannot be inlined, plus it does
+ -- not have declarative or statement lists.
+
return;
end if;
@@ -3345,16 +3395,6 @@ package body Sem_Ch6 is
HSS := Handled_Statement_Sequence (N);
Set_Actual_Subtypes (N, Current_Scope);
- -- Deal with [refined] preconditions, postconditions, Contract_Cases,
- -- invariants and predicates associated with the body and its spec.
- -- Note that this is not pure expansion as Expand_Subprogram_Contract
- -- prepares the contract assertions for generic subprograms or for ASIS.
- -- Do not generate contract checks in SPARK mode.
-
- if not GNATprove_Mode then
- Expand_Subprogram_Contract (N, Spec_Id, Body_Id);
- end if;
-
-- Add a declaration for the Protection object, renaming declarations
-- for discriminals and privals and finally a declaration for the entry
-- family index (if applicable). This form of early expansion is done
@@ -3382,6 +3422,22 @@ package body Sem_Ch6 is
Exchange_Limited_Views (Spec_Id);
end if;
+ -- Analyze any aspect specifications that appear on the subprogram body
+
+ if Has_Aspects (N) then
+ Analyze_Aspects_On_Body_Or_Stub;
+ end if;
+
+ -- Deal with [refined] preconditions, postconditions, Contract_Cases,
+ -- invariants and predicates associated with the body and its spec.
+ -- Note that this is not pure expansion as Expand_Subprogram_Contract
+ -- prepares the contract assertions for generic subprograms or for ASIS.
+ -- Do not generate contract checks in SPARK mode.
+
+ if not GNATprove_Mode then
+ Expand_Subprogram_Contract (N, Spec_Id, Body_Id);
+ end if;
+
-- Analyze the declarations (this call will analyze the precondition
-- Check pragmas we prepended to the list, as well as the declaration
-- of the _Postconditions procedure).
@@ -11455,23 +11511,35 @@ package body Sem_Ch6 is
-- The following checks are relevant when SPARK_Mode is on as these
-- are not standard Ada legality rules.
- if SPARK_Mode = On
- and then Ekind_In (Scope (Formal), E_Function, E_Generic_Function)
- then
- -- A function cannot have a parameter of mode IN OUT or OUT
- -- (SPARK RM 6.1).
+ if SPARK_Mode = On then
+ if Ekind_In (Scope (Formal), E_Function, E_Generic_Function) then
- if Ekind_In (Formal, E_In_Out_Parameter, E_Out_Parameter) then
- Error_Msg_N
- ("function cannot have parameter of mode `OUT` or `IN OUT`",
- Formal);
+ -- A function cannot have a parameter of mode IN OUT or OUT
+ -- (SPARK RM 6.1).
- -- A function cannot have a volatile formal parameter
- -- (SPARK RM 7.1.3(10)).
+ if Ekind_In (Formal, E_In_Out_Parameter, E_Out_Parameter) then
+ Error_Msg_N
+ ("function cannot have parameter of mode `OUT` or "
+ & "`IN OUT`", Formal);
- elsif Is_SPARK_Volatile_Object (Formal) then
+ -- A function cannot have a volatile formal parameter
+ -- (SPARK RM 7.1.3(10)).
+
+ elsif Is_SPARK_Volatile (Formal) then
+ Error_Msg_N
+ ("function cannot have a volatile formal parameter",
+ Formal);
+ end if;
+
+ -- A procedure cannot have a formal parameter of mode IN because
+ -- it behaves as a constant (SPARK RM 7.1.3(6)).
+
+ elsif Ekind (Scope (Formal)) = E_Procedure
+ and then Ekind (Formal) = E_In_Parameter
+ and then Is_SPARK_Volatile (Formal)
+ then
Error_Msg_N
- ("function cannot have a volatile formal parameter", Formal);
+ ("formal parameter of mode `IN` cannot be volatile", Formal);
end if;
end if;
diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb
index de1a28a4c53..7afe23676c5 100644
--- a/gcc/ada/sem_ch7.adb
+++ b/gcc/ada/sem_ch7.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -917,7 +917,7 @@ package body Sem_Ch7 is
Analyze_Aspect_Specifications (N, Id);
end if;
- -- Ada 2005 (AI-217): Check if the package has been erroneously named
+ -- Ada 2005 (AI-217): Check if the package has been illegally named
-- in a limited-with clause of its own context. In this case the error
-- has been previously notified by Analyze_Context.
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index a727679270d..43cd4fde82f 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -2512,13 +2512,18 @@ package body Sem_Ch8 is
Set_Kill_Elaboration_Checks (New_S, True);
+ -- If we had a previous error, indicate a completely is present to stop
+ -- junk cascaded messages, but don't take any further action.
+
if Etype (Nam) = Any_Type then
Set_Has_Completion (New_S);
return;
+ -- Case where name has the form of a selected component
+
elsif Nkind (Nam) = N_Selected_Component then
- -- A prefix of the form A.B can designate an entry of task A, a
+ -- A name which has the form A.B can designate an entry of task A, a
-- protected operation of protected object A, or finally a primitive
-- operation of object A. In the later case, A is an object of some
-- tagged type, or an access type that denotes one such. To further
@@ -2567,6 +2572,8 @@ package body Sem_Ch8 is
end if;
end;
+ -- Case where name is an explicit dereference X.all
+
elsif Nkind (Nam) = N_Explicit_Dereference then
-- Renamed entity is designated by access_to_subprogram expression.
@@ -2575,14 +2582,21 @@ package body Sem_Ch8 is
Analyze_Renamed_Dereference (N, New_S, Present (Rename_Spec));
return;
+ -- Indexed component
+
elsif Nkind (Nam) = N_Indexed_Component then
Analyze_Renamed_Family_Member (N, New_S, Present (Rename_Spec));
return;
+ -- Character literal
+
elsif Nkind (Nam) = N_Character_Literal then
Analyze_Renamed_Character (N, New_S, Present (Rename_Spec));
return;
+ -- Only remaining case is where we have a non-entity name, or a
+ -- renaming of some other non-overloadable entity.
+
elsif not Is_Entity_Name (Nam)
or else not Is_Overloadable (Entity (Nam))
then
diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb
index 1e2e8325550..4894a646cff 100644
--- a/gcc/ada/sem_ch9.adb
+++ b/gcc/ada/sem_ch9.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -3420,92 +3420,4 @@ package body Sem_Ch9 is
Next_Entity (E);
end loop;
end Install_Declarations;
-
- ---------------------------
- -- Install_Discriminants --
- ---------------------------
-
- procedure Install_Discriminants (E : Entity_Id) is
- Disc : Entity_Id;
- Prev : Entity_Id;
- begin
- Disc := First_Discriminant (E);
- while Present (Disc) loop
- Prev := Current_Entity (Disc);
- Set_Current_Entity (Disc);
- Set_Is_Immediately_Visible (Disc);
- Set_Homonym (Disc, Prev);
- Next_Discriminant (Disc);
- end loop;
- end Install_Discriminants;
-
- ------------------------------------------
- -- Push_Scope_And_Install_Discriminants --
- ------------------------------------------
-
- procedure Push_Scope_And_Install_Discriminants (E : Entity_Id) is
- begin
- if Has_Discriminants (E) then
- Push_Scope (E);
- Install_Discriminants (E);
- end if;
- end Push_Scope_And_Install_Discriminants;
-
- -----------------------------
- -- Uninstall_Discriminants --
- -----------------------------
-
- procedure Uninstall_Discriminants (E : Entity_Id) is
- Disc : Entity_Id;
- Prev : Entity_Id;
- Outer : Entity_Id;
-
- begin
- Disc := First_Discriminant (E);
- while Present (Disc) loop
- if Disc /= Current_Entity (Disc) then
- Prev := Current_Entity (Disc);
- while Present (Prev)
- and then Present (Homonym (Prev))
- and then Homonym (Prev) /= Disc
- loop
- Prev := Homonym (Prev);
- end loop;
- else
- Prev := Empty;
- end if;
-
- Set_Is_Immediately_Visible (Disc, False);
-
- Outer := Homonym (Disc);
- while Present (Outer) and then Scope (Outer) = E loop
- Outer := Homonym (Outer);
- end loop;
-
- -- Reset homonym link of other entities, but do not modify link
- -- between entities in current scope, so that the back-end can have
- -- a proper count of local overloadings.
-
- if No (Prev) then
- Set_Name_Entity_Id (Chars (Disc), Outer);
-
- elsif Scope (Prev) /= Scope (Disc) then
- Set_Homonym (Prev, Outer);
- end if;
-
- Next_Discriminant (Disc);
- end loop;
- end Uninstall_Discriminants;
-
- -------------------------------------------
- -- Uninstall_Discriminants_And_Pop_Scope --
- -------------------------------------------
-
- procedure Uninstall_Discriminants_And_Pop_Scope (E : Entity_Id) is
- begin
- if Has_Discriminants (E) then
- Uninstall_Discriminants (E);
- Pop_Scope;
- end if;
- end Uninstall_Discriminants_And_Pop_Scope;
end Sem_Ch9;
diff --git a/gcc/ada/sem_ch9.ads b/gcc/ada/sem_ch9.ads
index 1ab0b8ceca4..1a953b60f2c 100644
--- a/gcc/ada/sem_ch9.ads
+++ b/gcc/ada/sem_ch9.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -58,20 +58,6 @@ package Sem_Ch9 is
-- Make visible in corresponding body the entities defined in a task,
-- protected type declaration, or entry declaration.
- procedure Install_Discriminants (E : Entity_Id);
- -- Make visible the discriminants of type entity E
-
- procedure Push_Scope_And_Install_Discriminants (E : Entity_Id);
- -- Push scope E and makes visible the discriminants of type entity E if E
- -- has discriminants.
-
- procedure Uninstall_Discriminants (E : Entity_Id);
- -- Remove visibility to the discriminants of type entity E
-
- procedure Uninstall_Discriminants_And_Pop_Scope (E : Entity_Id);
- -- Remove visibility to the discriminants of type entity E and pop the
- -- scope stack if E has discriminants.
-
------------------------------
-- Lock Free Data Structure --
------------------------------
diff --git a/gcc/ada/sem_dim.adb b/gcc/ada/sem_dim.adb
index 825eb029cd1..6bb74ee0714 100644
--- a/gcc/ada/sem_dim.adb
+++ b/gcc/ada/sem_dim.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2011-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 2011-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -772,7 +772,7 @@ package body Sem_Dim is
Others_Seen := True;
- -- All other cases are erroneous declarations of dimension names
+ -- All other cases are illegal declarations of dimension names
else
Error_Msg_NE ("wrong syntax for aspect&", Choice, Id);
diff --git a/gcc/ada/sem_elab.adb b/gcc/ada/sem_elab.adb
index 8b8c58a66cd..7f494d85183 100644
--- a/gcc/ada/sem_elab.adb
+++ b/gcc/ada/sem_elab.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1997-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1997-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -541,12 +541,39 @@ package body Sem_Elab is
-- warnings on the scope are also suppressed. For the internal case,
-- we ignore this flag.
+ function Is_Call_Of_Generic_Formal return Boolean;
+ -- Returns True if node N is a call to a generic formal subprogram
+
+ -------------------------------
+ -- Is_Call_Of_Generic_Formal --
+ -------------------------------
+
+ function Is_Call_Of_Generic_Formal return Boolean is
+ begin
+ return Nkind_In (N, N_Function_Call, N_Procedure_Call_Statement)
+
+ -- Always return False if debug flag -gnatd.G is set
+
+ and then not Debug_Flag_Dot_GG
+
+ -- For now, we detect this by looking for the strange identifier
+ -- node, whose Chars reflect the name of the generic formal, but
+ -- the Chars of the Entity references the generic actual.
+
+ and then Nkind (Name (N)) = N_Identifier
+ and then Chars (Name (N)) /= Chars (Entity (Name (N)));
+ end Is_Call_Of_Generic_Formal;
+
+ -- Start of processing for Check_A_Call
+
begin
-- If the call is known to be within a local Suppress Elaboration
- -- pragma, nothing to check. This can happen in task bodies.
+ -- pragma, nothing to check. This can happen in task bodies. But
+ -- we ignore this for a call to a generic formal.
if Nkind (N) in N_Subprogram_Call
and then No_Elaboration_Check (N)
+ and then not Is_Call_Of_Generic_Formal
then
return;
end if;
@@ -578,16 +605,15 @@ package body Sem_Elab is
if Nkind (Decl) = N_Subprogram_Body then
Body_Acts_As_Spec := True;
- elsif Nkind (Decl) = N_Subprogram_Declaration
- or else Nkind (Decl) = N_Subprogram_Body_Stub
+ elsif Nkind_In (Decl, N_Subprogram_Declaration, N_Subprogram_Body_Stub)
or else Inst_Case
then
Body_Acts_As_Spec := False;
- -- If we have none of an instantiation, subprogram body or
- -- subprogram declaration, then it is not a case that we want
- -- to check. (One case is a call to a generic formal subprogram,
- -- where we do not want the check in the template).
+ -- If we have none of an instantiation, subprogram body or subprogram
+ -- declaration, then it is not a case that we want to check. (One case
+ -- is a call to a generic formal subprogram, where we do not want the
+ -- check in the template).
else
return;
@@ -605,7 +631,7 @@ package body Sem_Elab is
exit when Is_Compilation_Unit (E_Scope)
and then (Is_Child_Unit (E_Scope)
- or else Scope (E_Scope) = Standard_Standard);
+ or else Scope (E_Scope) = Standard_Standard);
-- If we did not find a compilation unit, other than standard,
-- then nothing to check (happens in some instantiation cases)
@@ -633,17 +659,15 @@ package body Sem_Elab is
-- However, this assumption is only valid if we are in static mode.
if not Dynamic_Elaboration_Checks
- and then Instantiation_Depth (Sloc (Ent)) >
- Instantiation_Depth (Sloc (N))
+ and then
+ Instantiation_Depth (Sloc (Ent)) > Instantiation_Depth (Sloc (N))
then
return;
end if;
-- Do not give a warning for a package with no body
- if Ekind (Ent) = E_Generic_Package
- and then not Has_Generic_Body (N)
- then
+ if Ekind (Ent) = E_Generic_Package and then not Has_Generic_Body (N) then
return;
end if;
@@ -738,7 +762,7 @@ package body Sem_Elab is
-- the sgi build and storage errors. To be resolved later ???
if (Callee_Unit_Internal and Caller_Unit_Internal)
- and then not Debug_Flag_EE
+ and then not Debug_Flag_EE
then
return;
end if;
@@ -755,8 +779,9 @@ package body Sem_Elab is
-- However, if we are doing dynamic elaboration, we need to chase the
-- call in the usual manner.
- -- We do not handle the case of calling a generic formal correctly in
- -- the static case.???
+ -- We also need to chase the call in the usual manner if it is a call
+ -- to a generic formal parameter, since that case was not handled as
+ -- part of the processing of the template.
Inst_Caller := Instantiation (Get_Source_File_Index (Sloc (N)));
Inst_Callee := Instantiation (Get_Source_File_Index (Sloc (Ent)));
@@ -776,6 +801,7 @@ package body Sem_Elab is
if Unit_Caller /= No_Unit
and then Unit_Callee /= Unit_Caller
and then not Dynamic_Elaboration_Checks
+ and then not Is_Call_Of_Generic_Formal
then
E_Scope := Spec_Entity (Cunit_Entity (Unit_Caller));
@@ -792,19 +818,18 @@ package body Sem_Elab is
E_Scope := Scope (E_Scope);
end loop;
- -- For the case N is not an instance, or a call within instance, we
- -- recompute E_Scope for the error message, since we do NOT want to
- -- go to the unit which has the ultimate declaration in the case of
- -- renaming and derivation and we also want to go to the generic unit
- -- in the case of an instance, and no further.
+ -- For the case where N is not an instance, and is not a call within
+ -- instance to other than a generic formal, we recompute E_Scope
+ -- for the error message, since we do NOT want to go to the unit
+ -- which has the ultimate declaration in the case of renaming and
+ -- derivation and we also want to go to the generic unit in the
+ -- case of an instance, and no further.
else
-- Loop to carefully follow renamings and derivations one step
-- outside the current unit, but not further.
- if not Inst_Case
- and then Present (Alias (Ent))
- then
+ if not Inst_Case and then Present (Alias (Ent)) then
E_Scope := Alias (Ent);
else
E_Scope := Ent;
@@ -1182,7 +1207,7 @@ package body Sem_Elab is
-- For an entry call, check relevant restriction
if Nkind (N) = N_Entry_Call_Statement
- and then not In_Subprogram_Or_Concurrent_Unit
+ and then not In_Subprogram_Or_Concurrent_Unit
then
Check_Restriction (No_Entry_Calls_In_Elaboration_Code, N);
@@ -1339,9 +1364,8 @@ package body Sem_Elab is
-- Filter out case of default expressions, where we do not
-- do the check at this stage.
- if Nkind (P) = N_Parameter_Specification
- or else
- Nkind (P) = N_Component_Declaration
+ if Nkind_In (P, N_Parameter_Specification,
+ N_Component_Declaration)
then
return;
end if;
@@ -1352,13 +1376,10 @@ package body Sem_Elab is
if Nkind (P) = N_Protected_Body then
return;
- elsif Nkind (P) = N_Subprogram_Body
- or else
- Nkind (P) = N_Task_Body
- or else
- Nkind (P) = N_Block_Statement
- or else
- Nkind (P) = N_Entry_Body
+ elsif Nkind_In (P, N_Subprogram_Body,
+ N_Task_Body,
+ N_Block_Statement,
+ N_Entry_Body)
then
if L = Declarations (P) then
exit;
@@ -1499,9 +1520,7 @@ package body Sem_Elab is
-- treat the current node as a call to each of these functions, to check
-- their elaboration impact.
- if Is_Init_Proc (Ent)
- and then From_Elab_Code
- then
+ if Is_Init_Proc (Ent) and then From_Elab_Code then
Process_Init_Proc : declare
Unit_Decl : constant Node_Id := Unit_Declaration_Node (Ent);
@@ -1713,7 +1732,7 @@ package body Sem_Elab is
begin
if Nkind (Decl) = N_Object_Declaration
and then (Present (Expression (Decl))
- or else No_Initialization (Decl))
+ or else No_Initialization (Decl))
then
return;
end if;
@@ -1842,9 +1861,7 @@ package body Sem_Elab is
C_Scope := Current_Scope;
- if Present (Outer_Scope)
- and then Within (Scope (Ent), Outer_Scope)
- then
+ if Present (Outer_Scope) and then Within (Scope (Ent), Outer_Scope) then
Set_C_Scope;
Check_A_Call (N, Ent, Outer_Scope, Inter_Unit_Only => False);
@@ -1992,8 +2009,8 @@ package body Sem_Elab is
-- code, do not trace past an accept statement, because the rendez-
-- vous will happen after elaboration.
- if (Nkind (Original_Node (N)) = N_Accept_Statement
- or else Nkind (Original_Node (N)) = N_Selective_Accept)
+ if Nkind_In (Original_Node (N), N_Accept_Statement,
+ N_Selective_Accept)
and then Restriction_Active (No_Entry_Calls_In_Elaboration_Code)
then
return Abandon;
@@ -2021,8 +2038,8 @@ package body Sem_Elab is
return OK;
- -- If we have an access attribute for a subprogram, check
- -- it. Suppress this behavior under debug flag.
+ -- If we have an access attribute for a subprogram, check it.
+ -- Suppress this behavior under debug flag.
elsif not Debug_Flag_Dot_UU
and then Nkind (N) = N_Attribute_Reference
@@ -2086,10 +2103,7 @@ package body Sem_Elab is
Sbody := Unit_Declaration_Node (E);
- if Nkind (Sbody) /= N_Subprogram_Body
- and then
- Nkind (Sbody) /= N_Package_Body
- then
+ if not Nkind_In (Sbody, N_Subprogram_Body, N_Package_Body) then
Ebody := Corresponding_Body (Sbody);
if No (Ebody) then
@@ -2406,8 +2420,7 @@ package body Sem_Elab is
if No (Corresponding_Body (Unit_Declaration_Node (Proc)))
and then
(not Is_Generic_Instance (Scope (Proc))
- or else
- Scope (Proc) = Scope (Defining_Identifier (Decl)))
+ or else Scope (Proc) = Scope (Defining_Identifier (Decl)))
then
Error_Msg_Warn := SPARK_Mode /= On;
Error_Msg_N
@@ -2503,7 +2516,7 @@ package body Sem_Elab is
Collect_Tasks (Declarations (N));
end if;
- -- We only perform detailed checks in all tasks are library level
+ -- We only perform detailed checks in all tasks that are library level
-- entities. If the master is a subprogram or task, activation will
-- depend on the activation of the master itself.
@@ -2636,9 +2649,8 @@ package body Sem_Elab is
-- that is, on which we need to place to elaboration flag. This happens
-- with init proc calls.
- if Is_Init_Proc (Subp)
- or else Init_Call
- then
+ if Is_Init_Proc (Subp) or else Init_Call then
+
-- The initialization call is on an object whose type is not declared
-- in the same scope as the subprogram. The type of the object must
-- be a subtype of the type of operation. This object is the first
@@ -2996,9 +3008,7 @@ package body Sem_Elab is
begin
-- Check whether Id is a procedure with at least one parameter
- if Ekind (Id) = E_Procedure
- and then Present (First_Formal (Id))
- then
+ if Ekind (Id) = E_Procedure and then Present (First_Formal (Id)) then
declare
Typ : constant Entity_Id := Etype (First_Formal (Id));
Deep_Fin : Entity_Id := Empty;
@@ -3025,10 +3035,8 @@ package body Sem_Elab is
Fin := Find_Prim_Op (Typ, Name_Finalize);
end if;
- return
- (Present (Deep_Fin) and then Id = Deep_Fin)
- or else
- (Present (Fin) and then Id = Fin);
+ return (Present (Deep_Fin) and then Id = Deep_Fin)
+ or else (Present (Fin) and then Id = Fin);
end;
end if;
@@ -3100,11 +3108,7 @@ package body Sem_Elab is
S1 := Scop1;
while S1 /= Standard_Standard
and then not Is_Compilation_Unit (S1)
- and then (Ekind (S1) = E_Package
- or else
- Ekind (S1) = E_Protected_Type
- or else
- Ekind (S1) = E_Block)
+ and then Ekind_In (S1, E_Package, E_Protected_Type, E_Block)
loop
S1 := Scope (S1);
end loop;
@@ -3114,11 +3118,7 @@ package body Sem_Elab is
S2 := Scop2;
while S2 /= Standard_Standard
and then not Is_Compilation_Unit (S2)
- and then (Ekind (S2) = E_Package
- or else
- Ekind (S2) = E_Protected_Type
- or else
- Ekind (S2) = E_Block)
+ and then Ekind_In (S2, E_Package, E_Protected_Type, E_Block)
loop
S2 := Scope (S2);
end loop;
@@ -3172,8 +3172,8 @@ package body Sem_Elab is
if Nkind (N) = N_Subprogram_Declaration then
declare
Ent : constant Entity_Id := Defining_Unit_Name (Specification (N));
- begin
+ begin
-- Internal subprograms will already have a generated body, so
-- there is no need to provide a stub for them.
diff --git a/gcc/ada/sem_elab.ads b/gcc/ada/sem_elab.ads
index abae4dd56c6..797e04a98ad 100644
--- a/gcc/ada/sem_elab.ads
+++ b/gcc/ada/sem_elab.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1997-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1997-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -158,7 +158,7 @@ package Sem_Elab is
-- not be generated (see detailed description in body).
procedure Check_Task_Activation (N : Node_Id);
- -- at the point at which tasks are activated in a package body, check
+ -- Tt the point at which tasks are activated in a package body, check
-- that the bodies of the tasks are elaborated.
end Sem_Elab;
diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb
index bd1398aee51..3c06188b97e 100644
--- a/gcc/ada/sem_eval.adb
+++ b/gcc/ada/sem_eval.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -5488,7 +5488,6 @@ package body Sem_Eval is
procedure Why_Not_Static_List (L : List_Id) is
N : Node_Id;
-
begin
if Is_Non_Empty_List (L) then
N := First (L);
@@ -5503,9 +5502,11 @@ package body Sem_Eval is
begin
-- If in ACATS mode (debug flag 2), then suppress all these messages,
- -- this avoids massive updates to the ACATS base line.
+ -- this avoids massive updates to the ACATS base line. But if the flag
+ -- d.z is set, then don't suppress the messages. This is a temporary
+ -- kludge to aid in doing the necessary updates to the ACATS base line.
- if Debug_Flag_2 then
+ if Debug_Flag_2 and then not Debug_Flag_Dot_Z then
return;
end if;
@@ -5529,7 +5530,7 @@ package body Sem_Eval is
if Raises_Constraint_Error (Expr) then
Error_Msg_N
- ("\expression raises exception, cannot be static " &
+ ("!expression raises exception, cannot be static " &
"(RM 4.9(34))", N);
return;
end if;
@@ -5550,7 +5551,7 @@ package body Sem_Eval is
and then not Is_RTE (Typ, RE_Bignum)
then
Error_Msg_N
- ("\static expression must have scalar or string type " &
+ ("!static expression must have scalar or string type " &
"(RM 4.9(2))", N);
return;
end if;
@@ -5614,17 +5615,17 @@ package body Sem_Eval is
or else
Is_Aggregate (Right_Opnd (CO))))
then
- Error_Msg_N ("\aggregate (#) is never static", N);
+ Error_Msg_N ("!aggregate (#) is never static", N);
elsif No (CV) or else not Is_Static_Expression (CV) then
Error_Msg_NE
- ("\& is not a static constant (RM 4.9(5))", N, E);
+ ("!& is not a static constant (RM 4.9(5))", N, E);
end if;
end Entity_Case;
else
Error_Msg_NE
- ("\& is not static constant or named number "
+ ("!& is not static constant or named number "
& "(RM 4.9(5))", N, E);
end if;
@@ -5633,7 +5634,7 @@ package body Sem_Eval is
when N_Binary_Op | N_Short_Circuit | N_Membership_Test =>
if Nkind (N) in N_Op_Shift then
Error_Msg_N
- ("\shift functions are never static (RM 4.9(6,18))", N);
+ ("!shift functions are never static (RM 4.9(6,18))", N);
else
Why_Not_Static (Left_Opnd (N));
@@ -5660,7 +5661,7 @@ package body Sem_Eval is
if Attribute_Name (N) = Name_Size then
Error_Msg_N
- ("\size attribute is only static for static scalar type "
+ ("!size attribute is only static for static scalar type "
& "(RM 4.9(7,8))", N);
-- Flag array cases
@@ -5673,7 +5674,7 @@ package body Sem_Eval is
Attribute_Name (N) /= Name_Length
then
Error_Msg_N
- ("\static array attribute must be Length, First, or Last "
+ ("!static array attribute must be Length, First, or Last "
& "(RM 4.9(8))", N);
-- Since we know the expression is not-static (we already
@@ -5681,7 +5682,7 @@ package body Sem_Eval is
else
Error_Msg_N
- ("\prefix is non-static array (RM 4.9(8))", Prefix (N));
+ ("!prefix is non-static array (RM 4.9(8))", Prefix (N));
end if;
return;
@@ -5694,7 +5695,7 @@ package body Sem_Eval is
Is_Generic_Type (E)
then
Error_Msg_N
- ("\attribute of generic type is never static "
+ ("!attribute of generic type is never static "
& "(RM 4.9(7,8))", N);
elsif Is_Static_Subtype (E) then
@@ -5702,12 +5703,12 @@ package body Sem_Eval is
elsif Is_Scalar_Type (E) then
Error_Msg_N
- ("\prefix type for attribute is not static scalar subtype "
+ ("!prefix type for attribute is not static scalar subtype "
& "(RM 4.9(7))", N);
else
Error_Msg_N
- ("\static attribute must apply to array/scalar type "
+ ("!static attribute must apply to array/scalar type "
& "(RM 4.9(7,8))", N);
end if;
@@ -5715,13 +5716,13 @@ package body Sem_Eval is
when N_String_Literal =>
Error_Msg_N
- ("\subtype of string literal is non-static (RM 4.9(4))", N);
+ ("!subtype of string literal is non-static (RM 4.9(4))", N);
-- Explicit dereference
when N_Explicit_Dereference =>
Error_Msg_N
- ("\explicit dereference is never static (RM 4.9)", N);
+ ("!explicit dereference is never static (RM 4.9)", N);
-- Function call
@@ -5733,7 +5734,7 @@ package body Sem_Eval is
-- scalar arithmetic operation.
if not Is_RTE (Typ, RE_Bignum) then
- Error_Msg_N ("\non-static function call (RM 4.9(6,18))", N);
+ Error_Msg_N ("!non-static function call (RM 4.9(6,18))", N);
end if;
-- Parameter assocation (test actual parameter)
@@ -5744,12 +5745,12 @@ package body Sem_Eval is
-- Indexed component
when N_Indexed_Component =>
- Error_Msg_N ("\indexed component is never static (RM 4.9)", N);
+ Error_Msg_N ("!indexed component is never static (RM 4.9)", N);
-- Procedure call
when N_Procedure_Call_Statement =>
- Error_Msg_N ("\procedure call is never static (RM 4.9)", N);
+ Error_Msg_N ("!procedure call is never static (RM 4.9)", N);
-- Qualified expression (test expression)
@@ -5759,7 +5760,7 @@ package body Sem_Eval is
-- Aggregate
when N_Aggregate | N_Extension_Aggregate =>
- Error_Msg_N ("\an aggregate is never static (RM 4.9)", N);
+ Error_Msg_N ("!an aggregate is never static (RM 4.9)", N);
-- Range
@@ -5780,12 +5781,12 @@ package body Sem_Eval is
-- Selected component
when N_Selected_Component =>
- Error_Msg_N ("\selected component is never static (RM 4.9)", N);
+ Error_Msg_N ("!selected component is never static (RM 4.9)", N);
-- Slice
when N_Slice =>
- Error_Msg_N ("\slice is never static (RM 4.9)", N);
+ Error_Msg_N ("!slice is never static (RM 4.9)", N);
when N_Type_Conversion =>
Why_Not_Static (Expression (N));
@@ -5794,7 +5795,7 @@ package body Sem_Eval is
or else not Is_Static_Subtype (Entity (Subtype_Mark (N)))
then
Error_Msg_N
- ("\static conversion requires static scalar subtype result "
+ ("!static conversion requires static scalar subtype result "
& "(RM 4.9(9))", N);
end if;
@@ -5802,7 +5803,7 @@ package body Sem_Eval is
when N_Unchecked_Type_Conversion =>
Error_Msg_N
- ("\unchecked type conversion is never static (RM 4.9)", N);
+ ("!unchecked type conversion is never static (RM 4.9)", N);
-- All other cases, no reason to give
diff --git a/gcc/ada/sem_eval.ads b/gcc/ada/sem_eval.ads
index 8bd8761f0da..7d8779d373a 100644
--- a/gcc/ada/sem_eval.ads
+++ b/gcc/ada/sem_eval.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -470,17 +470,23 @@ package Sem_Eval is
procedure Why_Not_Static (Expr : Node_Id);
-- This procedure may be called after generating an error message that
- -- complains that something is non-static. If it finds good reasons,
- -- it generates one or more continuation error messages pointing the
- -- appropriate offending component of the expression. If no good reasons
- -- can be figured out, then no messages are generated. The expectation here
- -- is that the caller has already issued a message complaining that the
- -- expression is non-static. Note that this message should be placed using
- -- Error_Msg_F or Error_Msg_FE, so that it will sort before any messages
- -- placed by this call. Note that it is fine to call Why_Not_Static with
- -- something that is not an expression, and usually this has no effect, but
- -- in some cases (N_Parameter_Association or N_Range), it makes sense for
- -- the internal recursive calls.
+ -- complains that something is non-static. If it finds good reasons, it
+ -- generates one or more error messages pointing the appropriate offending
+ -- component of the expression. If no good reasons can be figured out, then
+ -- no messages are generated. The expectation here is that the caller has
+ -- already issued a message complaining that the expression is non-static.
+ -- Note that this message should be placed using Error_Msg_F or
+ -- Error_Msg_FE, so that it will sort before any messages placed by this
+ -- call. Note that it is fine to call Why_Not_Static with something that
+ -- is not an expression, and usually this has no effect, but in some cases
+ -- (N_Parameter_Association or N_Range), it makes sense for the internal
+ -- recursive calls.
+ --
+ -- Note that these messages are not continuation messages, instead they are
+ -- separate unconditional messages, marked with '!'. The reason for this is
+ -- that they can be posted at a different location from the maim message as
+ -- documented above ("appropriate offending component"), and continuation
+ -- messages must always point to the same location as the parent message.
procedure Initialize;
-- Initializes the internal data structures. Must be called before each
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 42f080de4da..30607203141 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -1239,7 +1239,7 @@ package body Sem_Prag is
Is_Input : Boolean)
is
procedure Usage_Error (Item : Node_Id; Item_Id : Entity_Id);
- -- Emit an error concerning the erroneous usage of an item
+ -- Emit an error concerning the illegal usage of an item
-----------------
-- Usage_Error --
@@ -1783,10 +1783,11 @@ package body Sem_Prag is
Is_Last => Clause = Last_Clause);
end if;
- -- Do not normalize an erroneous clause because the inputs
- -- and/or outputs may denote illegal items. Normalization is
- -- disabled in ASIS mode as it alters the tree by introducing
- -- new nodes similar to expansion.
+ -- Do not normalize a clause if errors were detected (count
+ -- of Serious_Errors has increased) because the inputs and/or
+ -- outputs may denote illegal items. Normalization is disabled
+ -- in ASIS mode as it alters the tree by introducing new nodes
+ -- similar to expansion.
if Serious_Errors_Detected = Errors and then not ASIS_Mode then
Normalize_Clause (Clause);
@@ -2037,9 +2038,8 @@ package body Sem_Prag is
-- SPARK_Mode is on as they are not standard Ada legality
-- rules.
- elsif SPARK_Mode = On
- and then Is_SPARK_Volatile_Object (Item_Id)
- then
+ elsif SPARK_Mode = On and then Is_SPARK_Volatile (Item_Id) then
+
-- A volatile object cannot appear as a global item of a
-- function (SPARK RM 7.1.3(9)).
@@ -2288,7 +2288,7 @@ package body Sem_Prag is
raise Program_Error;
end if;
- -- Any other attempt to declare a global item is erroneous
+ -- Any other attempt to declare a global item is illegal
else
Error_Msg_N ("malformed global list", List);
@@ -3444,9 +3444,10 @@ package body Sem_Prag is
Indic : Node_Id;
Legal : out Boolean)
is
- Pack_Id : Entity_Id;
- Placement : State_Space_Kind;
- State_Id : Entity_Id;
+ Pack_Id : Entity_Id;
+ Placement : State_Space_Kind;
+ Parent_Unit : Entity_Id;
+ State_Id : Entity_Id;
begin
-- Assume that the pragma/option is illegal
@@ -3509,22 +3510,43 @@ package body Sem_Prag is
if Is_Child_Unit (Pack_Id)
and then Is_Private_Descendant (Pack_Id)
then
- if not Is_Child_Or_Sibling (Pack_Id, Scope (State_Id)) then
- Error_Msg_N
- ("indicator Part_Of must denote an abstract state of "
- & "parent unit or descendant (SPARK RM 7.2.6(3))", Indic);
+ -- A variable or state abstraction which is part of the
+ -- visible state of a private child unit (or a public
+ -- descendant thereof) shall have its Part_Of indicator
+ -- specified; the Part_Of indicator shall denote a state
+ -- abstraction declared by either the parent unit of the
+ -- private unit or by a public descendant of that parent unit.
+
+ -- Find nearest nearest private ancestor (which can be the
+ -- current unit itself).
+
+ Parent_Unit := Pack_Id;
+ while Present (Parent_Unit) loop
+ exit when Private_Present
+ (Parent (Unit_Declaration_Node (Parent_Unit)));
+ Parent_Unit := Scope (Parent_Unit);
+ end loop;
- -- If the unit is a public child of a private unit it cannot
- -- refine the state of a private parent, only that of a
- -- public ancestor or descendant thereof.
+ Parent_Unit := Scope (Parent_Unit);
- elsif not Private_Present
- (Parent (Unit_Declaration_Node (Pack_Id)))
- and then Is_Private_Descendant (Scope (State_Id))
+ if not Is_Child_Or_Sibling (Pack_Id, Scope (State_Id)) then
+ Error_Msg_NE
+ ("indicator Part_Of must denote an abstract state of& "
+ & "or public descendant (SPARK RM 7.2.6(3))",
+ Indic, Parent_Unit);
+
+ elsif Scope (State_Id) = Parent_Unit
+ or else (Is_Ancestor_Package (Parent_Unit, Scope (State_Id))
+ and then
+ not Is_Private_Descendant (Scope (State_Id)))
then
- Error_Msg_N
- ("indicator Part_Of must denote the abstract state of "
- & "a public ancestor", State);
+ null;
+
+ else
+ Error_Msg_NE
+ ("indicator Part_Of must denote an abstract state of& "
+ & "or public descendant (SPARK RM 7.2.6(3))",
+ Indic, Parent_Unit);
end if;
-- Indicator Part_Of is not needed when the related package is not
@@ -4021,7 +4043,7 @@ package body Sem_Prag is
if not Is_Task_Dispatching_Policy_Name (Chars (Argx)) then
Error_Pragma_Arg
- ("& is not a valid task dispatching policy name", Argx);
+ ("& is not an allowed task dispatching policy name", Argx);
end if;
end Check_Arg_Is_Task_Dispatching_Policy;
@@ -4529,7 +4551,7 @@ package body Sem_Prag is
-- For pragma case (as opposed to access case), check placement.
-- We don't need to do that for aspects, because we have the
- -- check that they are apply an appropriate procedure.
+ -- check that they aspect applies an appropriate procedure.
if not From_Aspect_Specification (N)
and then Parent (N) /= Protected_Definition (Parent (Proc_Scope))
@@ -4681,7 +4703,7 @@ package body Sem_Prag is
Prag := Stmt;
-- A non-pragma is separating the group from the
- -- current pragma, the placement is erroneous.
+ -- current pragma, the placement is illegal.
else
Grouping_Error (Prag);
@@ -6364,8 +6386,22 @@ package body Sem_Prag is
Set_Treat_As_Volatile (E);
else
+ Error_Pragma_Arg ("inappropriate entity for pragma%", Arg1);
+ end if;
+
+ -- The following check is only relevant when SPARK_Mode is on as
+ -- this is not a standard Ada legality rule. Pragma Volatile can
+ -- only apply to a full type declaration or an object declaration
+ -- (SPARK RM C.6(1)).
+
+ if SPARK_Mode = On
+ and then Prag_Id = Pragma_Volatile
+ and then not Nkind_In (K, N_Full_Type_Declaration,
+ N_Object_Declaration)
+ then
Error_Pragma_Arg
- ("inappropriate entity for pragma%", Arg1);
+ ("argument of pragma % must denote a full type or object "
+ & "declaration", Arg1);
end if;
end Process_Atomic_Shared_Volatile;
@@ -10565,7 +10601,7 @@ package body Sem_Prag is
then
Analyze_External_Option (Opt);
- -- When an erroneous option Part_Of is without a parent
+ -- When an illegal option Part_Of is without a parent
-- state, it appears in the list of expression of the
-- aggregate rather than the component associations
-- (SPARK RM 7.1.4(9)).
@@ -10608,7 +10644,7 @@ package body Sem_Prag is
Next (Opt);
end loop;
- -- Any other attempt to declare a state is erroneous
+ -- Any other attempt to declare a state is illegal
else
Error_Msg_N ("malformed abstract state declaration", State);
@@ -15291,7 +15327,26 @@ package body Sem_Prag is
Arg : Node_Id;
Exp : Node_Id;
+ procedure ip;
+ -- A dummy procedure called when pragma Inspection_Point is
+ -- analyzed. This is just to help debugging the front end. If
+ -- a pragma Inspection_Point is added to a source program, then
+ -- breaking on ip will get you to that point in the program.
+
+ --------
+ -- ip --
+ --------
+
+ procedure ip is
+ begin
+ null;
+ end ip;
+
+ -- Start of processing for Inspection_Point
+
begin
+ ip;
+
if Arg_Count > 0 then
Arg := Arg1;
loop
@@ -25496,7 +25551,7 @@ package body Sem_Prag is
elsif N = Name_Off then
return Off;
- -- Any other argument is erroneous
+ -- Any other argument is illegal
else
raise Program_Error;
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index 5a70b2d56ba..c1f9f8c4deb 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -4684,7 +4684,7 @@ package body Sem_Res is
Check_Restriction (No_Task_Hierarchy, N);
end if;
- -- An erroneous allocator may be rewritten as a raise Program_Error
+ -- An illegal allocator may be rewritten as a raise Program_Error
-- statement.
if Nkind (N) = N_Allocator then
@@ -6579,11 +6579,11 @@ package body Sem_Res is
-- standard Ada legality rules.
if SPARK_Mode = On
- and then Ekind_In (E, E_Abstract_State, E_Variable)
- and then Is_SPARK_Volatile_Object (E)
+ and then Is_Object (E)
+ and then Is_SPARK_Volatile (E)
+ and then Comes_From_Source (E)
and then
- (Async_Writers_Enabled (E)
- or else Effective_Reads_Enabled (E))
+ (Async_Writers_Enabled (E) or else Effective_Reads_Enabled (E))
then
-- The volatile object can appear on either side of an assignment
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 6894a3ae937..afb62c13cce 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -5518,6 +5518,18 @@ package body Sem_Util is
while Present (Formal) and then Present (Actual) loop
if Actual = N then
return;
+
+ -- An actual that is the prefix in a prefixed call may have
+ -- been rewritten in the call, after the deferred reference
+ -- was collected. Check if sloc and kinds and names match.
+
+ elsif Sloc (Actual) = Sloc (N)
+ and then Nkind (Actual) = N_Identifier
+ and then Nkind (Actual) = Nkind (N)
+ and then Chars (Actual) = Chars (N)
+ then
+ return;
+
else
Actual := Next_Actual (Actual);
Formal := Next_Formal (Formal);
@@ -7290,39 +7302,46 @@ package body Sem_Util is
(Comp : Entity_Id) return Boolean
is
Comp_Decl : constant Node_Id := Parent (Comp);
- Subt_Indic : constant Node_Id :=
- Subtype_Indication (Component_Definition (Comp_Decl));
+ Subt_Indic : Node_Id;
Constr : Node_Id;
Assn : Node_Id;
begin
- if Nkind (Subt_Indic) = N_Subtype_Indication then
- Constr := Constraint (Subt_Indic);
+ -- Discriminants can't depend on discriminants
- if Nkind (Constr) = N_Index_Or_Discriminant_Constraint then
- Assn := First (Constraints (Constr));
- while Present (Assn) loop
- case Nkind (Assn) is
- when N_Subtype_Indication |
- N_Range |
- N_Identifier
- =>
- if Depends_On_Discriminant (Assn) then
- return True;
- end if;
+ if Ekind (Comp) = E_Discriminant then
+ return False;
- when N_Discriminant_Association =>
- if Depends_On_Discriminant (Expression (Assn)) then
- return True;
- end if;
+ else
+ Subt_Indic := Subtype_Indication (Component_Definition (Comp_Decl));
- when others =>
- null;
+ if Nkind (Subt_Indic) = N_Subtype_Indication then
+ Constr := Constraint (Subt_Indic);
- end case;
+ if Nkind (Constr) = N_Index_Or_Discriminant_Constraint then
+ Assn := First (Constraints (Constr));
+ while Present (Assn) loop
+ case Nkind (Assn) is
+ when N_Subtype_Indication |
+ N_Range |
+ N_Identifier
+ =>
+ if Depends_On_Discriminant (Assn) then
+ return True;
+ end if;
- Next (Assn);
- end loop;
+ when N_Discriminant_Association =>
+ if Depends_On_Discriminant (Expression (Assn)) then
+ return True;
+ end if;
+
+ when others =>
+ null;
+ end case;
+
+ Next (Assn);
+ end loop;
+ end if;
end if;
end if;
@@ -7447,7 +7466,7 @@ package body Sem_Util is
begin
-- A non-volatile object can never possess external properties
- if not Is_SPARK_Volatile_Object (Item_Id) then
+ if not Is_SPARK_Volatile (Item_Id) then
return False;
-- External properties related to variables come in two flavors -
@@ -7481,9 +7500,7 @@ package body Sem_Util is
elsif Property = Name_Effective_Writes
and then
- (Present (EW)
- or else
- (No (AR) and then No (AW) and then No (ER)))
+ (Present (EW) or else (No (AR) and then No (AW) and then No (ER)))
then
return True;
@@ -7495,11 +7512,19 @@ package body Sem_Util is
-- Start of processing for Has_Enabled_Property
begin
+ -- Abstract states and variables have a flexible scheme of specifying
+ -- external properties.
+
if Ekind (Item_Id) = E_Abstract_State then
return State_Has_Enabled_Property;
- else pragma Assert (Ekind (Item_Id) = E_Variable);
+ elsif Ekind (Item_Id) = E_Variable then
return Variable_Has_Enabled_Property;
+
+ -- Otherwise a property is enabled when the related object is volatile
+
+ else
+ return Is_SPARK_Volatile (Item_Id);
end if;
end Has_Enabled_Property;
@@ -8222,7 +8247,7 @@ package body Sem_Util is
Index := First_Index (Typ);
for Indx in 1 .. Ndims loop
- -- In case of an erroneous index which is not a discrete type, return
+ -- In case of an illegal index which is not a discrete type, return
-- that the type is not static.
if not Is_Discrete_Type (Etype (Index))
@@ -9730,11 +9755,6 @@ package body Sem_Util is
function Is_Dependent_Component_Of_Mutable_Object
(Object : Node_Id) return Boolean
is
- P : Node_Id;
- Prefix_Type : Entity_Id;
- P_Aliased : Boolean := False;
- Comp : Entity_Id;
-
function Is_Declared_Within_Variant (Comp : Entity_Id) return Boolean;
-- Returns True if and only if Comp is declared within a variant part
@@ -9749,17 +9769,41 @@ package body Sem_Util is
return Nkind (Parent (Comp_List)) = N_Variant;
end Is_Declared_Within_Variant;
+ P : Node_Id;
+ Prefix_Type : Entity_Id;
+ P_Aliased : Boolean := False;
+ Comp : Entity_Id;
+
+ Deref : Node_Id := Object;
+ -- Dereference node, in something like X.all.Y(2)
+
-- Start of processing for Is_Dependent_Component_Of_Mutable_Object
begin
- if Is_Variable (Object) then
+ -- Find the dereference node if any
+
+ while Nkind_In (Deref, N_Indexed_Component,
+ N_Selected_Component,
+ N_Slice)
+ loop
+ Deref := Prefix (Deref);
+ end loop;
+
+ -- Ada 2005: If we have a component or slice of a dereference,
+ -- something like X.all.Y (2), and the type of X is access-to-constant,
+ -- Is_Variable will return False, because it is indeed a constant
+ -- view. But it might be a view of a variable object, so we want the
+ -- following condition to be True in that case.
+ if Is_Variable (Object)
+ or else (Ada_Version >= Ada_2005
+ and then Nkind (Deref) = N_Explicit_Dereference)
+ then
if Nkind (Object) = N_Selected_Component then
P := Prefix (Object);
Prefix_Type := Etype (P);
if Is_Entity_Name (P) then
-
if Ekind (Entity (P)) = E_Generic_In_Out_Parameter then
Prefix_Type := Base_Type (Prefix_Type);
end if;
@@ -9791,10 +9835,10 @@ package body Sem_Util is
-- the dereferenced case, since the access value might denote an
-- unconstrained aliased object, whereas in Ada 95 the designated
-- object is guaranteed to be constrained. A worst-case assumption
- -- has to apply in Ada 2005 because we can't tell at compile time
- -- whether the object is "constrained by its initial value"
- -- (despite the fact that 3.10.2(26/2) and 8.5.1(5/2) are
- -- semantic rules -- these rules are acknowledged to need fixing).
+ -- has to apply in Ada 2005 because we can't tell at compile
+ -- time whether the object is "constrained by its initial value"
+ -- (despite the fact that 3.10.2(26/2) and 8.5.1(5/2) are semantic
+ -- rules (these rules are acknowledged to need fixing).
if Ada_Version < Ada_2005 then
if Is_Access_Type (Prefix_Type)
@@ -9803,7 +9847,7 @@ package body Sem_Util is
return False;
end if;
- elsif Ada_Version >= Ada_2005 then
+ else pragma Assert (Ada_Version >= Ada_2005);
if Is_Access_Type (Prefix_Type) then
-- If the access type is pool-specific, and there is no
@@ -11060,7 +11104,7 @@ package body Sem_Util is
begin
return (Ekind (E) = E_Access_Subprogram_Type
or else (Ekind (E) = E_Record_Type
- and then Present (Corresponding_Remote_Type (E))))
+ and then Present (Corresponding_Remote_Type (E))))
and then (Is_Remote_Call_Interface (E) or else Is_Remote_Types (E));
end Is_Remote_Access_To_Subprogram_Type;
@@ -11375,22 +11419,26 @@ package body Sem_Util is
end if;
end Is_SPARK_Object_Reference;
+ -----------------------
+ -- Is_SPARK_Volatile --
+ -----------------------
+
+ function Is_SPARK_Volatile (Id : Entity_Id) return Boolean is
+ begin
+ return Is_Volatile (Id) or else Is_Volatile (Etype (Id));
+ end Is_SPARK_Volatile;
+
------------------------------
-- Is_SPARK_Volatile_Object --
------------------------------
function Is_SPARK_Volatile_Object (N : Node_Id) return Boolean is
begin
- if Nkind (N) = N_Defining_Identifier then
- return Is_Volatile (N) or else Is_Volatile (Etype (N));
-
- elsif Is_Entity_Name (N) then
- return
- Is_SPARK_Volatile_Object (Entity (N))
- or else Is_Volatile (Etype (N));
+ if Is_Entity_Name (N) then
+ return Is_SPARK_Volatile (Entity (N));
elsif Nkind (N) = N_Expanded_Name then
- return Is_SPARK_Volatile_Object (Entity (N));
+ return Is_SPARK_Volatile (Entity (N));
elsif Nkind (N) = N_Indexed_Component then
return Is_SPARK_Volatile_Object (Prefix (N));
@@ -15819,12 +15867,6 @@ package body Sem_Util is
Set_Entity (N, Val);
- -- Remaining checks are only done on source nodes
-
- if not Comes_From_Source (N) then
- return;
- end if;
-
-- The node to post on is the selector in the case of an expanded name,
-- and otherwise the node itself.
@@ -15834,11 +15876,54 @@ package body Sem_Util is
Post_Node := N;
end if;
+ -- Check for violation of No_Fixed_IO
+
+ if Restriction_Check_Required (No_Fixed_IO)
+ and then
+ ((RTU_Loaded (Ada_Text_IO)
+ and then (Is_RTE (Val, RE_Decimal_IO)
+ or else
+ Is_RTE (Val, RE_Fixed_IO)))
+
+ or else
+ (RTU_Loaded (Ada_Wide_Text_IO)
+ and then (Is_RTE (Val, RO_WT_Decimal_IO)
+ or else
+ Is_RTE (Val, RO_WT_Fixed_IO)))
+
+ or else
+ (RTU_Loaded (Ada_Wide_Wide_Text_IO)
+ and then (Is_RTE (Val, RO_WW_Decimal_IO)
+ or else
+ Is_RTE (Val, RO_WW_Fixed_IO))))
+
+ -- A special extra check, don't complain about a reference from within
+ -- the Ada.Interrupts package itself!
+
+ and then not In_Same_Extended_Unit (N, Val)
+ then
+ Check_Restriction (No_Fixed_IO, Post_Node);
+ end if;
+
+ -- Remaining checks are only done on source nodes. Note that we test
+ -- for violation of No_Fixed_IO even on non-source nodes, because the
+ -- cases for checking violations of this restriction are instantiations
+ -- where the refernece in the instance has Comes_From_Source False.
+
+ if not Comes_From_Source (N) then
+ return;
+ end if;
+
-- Check for violation of No_Abort_Statements, which is triggered by
-- call to Ada.Task_Identification.Abort_Task.
if Restriction_Check_Required (No_Abort_Statements)
and then (Is_RTE (Val, RE_Abort_Task))
+
+ -- A special extra check, don't complain about a reference from within
+ -- the Ada.Task_Identification package itself!
+
+ and then not In_Same_Extended_Unit (N, Val)
then
Check_Restriction (No_Abort_Statements, Post_Node);
end if;
@@ -15854,6 +15939,11 @@ package body Sem_Util is
Is_RTE (Val, RE_Exchange_Handler) or else
Is_RTE (Val, RE_Detach_Handler) or else
Is_RTE (Val, RE_Reference))
+
+ -- A special extra check, don't complain about a reference from within
+ -- the Ada.Interrupts package itself!
+
+ and then not In_Same_Extended_Unit (N, Val)
then
Check_Restriction (No_Dynamic_Attachment, Post_Node);
end if;
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index 4e55734f202..8629d767d2b 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -1302,10 +1302,15 @@ package Sem_Util is
function Is_SPARK_Object_Reference (N : Node_Id) return Boolean;
-- Determines if the tree referenced by N represents an object in SPARK
+ function Is_SPARK_Volatile (Id : Entity_Id) return Boolean;
+ -- This routine is similar to predicate Is_Volatile, but it takes SPARK
+ -- semantics into account. In SPARK volatile components to not render a
+ -- type volatile.
+
function Is_SPARK_Volatile_Object (N : Node_Id) return Boolean;
-- Determine whether an arbitrary node denotes a volatile object reference
-- according to the semantics of SPARK. To qualify as volatile, an object
- -- must be subject to aspect/pragma Volatile or Atomic or have a [sub]type
+ -- must be subject to aspect/pragma Volatile or Atomic, or have a [sub]type
-- subject to the same attributes. Note that volatile components do not
-- render an object volatile.
@@ -1451,7 +1456,7 @@ package Sem_Util is
procedure Mark_Coextensions (Context_Nod : Node_Id; Root_Nod : Node_Id);
-- Given a node which designates the context of analysis and an origin in
-- the tree, traverse from Root_Nod and mark all allocators as either
- -- dynamic or static depending on Context_Nod. Any erroneous marking is
+ -- dynamic or static depending on Context_Nod. Any incorrect marking is
-- cleaned up during resolution.
function May_Be_Lvalue (N : Node_Id) return Boolean;
diff --git a/gcc/ada/sem_warn.adb b/gcc/ada/sem_warn.adb
index e73a54e615a..6571a9ea7c2 100644
--- a/gcc/ada/sem_warn.adb
+++ b/gcc/ada/sem_warn.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1999-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1999-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -766,6 +766,14 @@ package body Sem_Warn is
-- For an entry formal entity from an entry declaration, find the
-- corresponding body formal from the given accept statement.
+ function May_Need_Initialized_Actual (Ent : Entity_Id) return Boolean;
+ -- If an entity of a generic type has default initialization, then the
+ -- corresponding actual type should be fully initialized, or else there
+ -- will be uninitialized components in the instantiation, that might go
+ -- unreported. This predicate allows the compiler to emit an appropriate
+ -- warning in the generic itself. In a sense, the use of a type that
+ -- requires full initialization is a weak part of the generic contract.
+
function Missing_Subunits return Boolean;
-- We suppress warnings when there are missing subunits, because this
-- may generate too many false positives: entities in a parent may only
@@ -815,6 +823,44 @@ package body Sem_Warn is
raise Program_Error;
end Body_Formal;
+ -----------------------------------
+ -- May_Need_Initialized_Actual --
+ -----------------------------------
+
+ function May_Need_Initialized_Actual (Ent : Entity_Id) return Boolean is
+ T : constant Entity_Id := Etype (Ent);
+ Par : constant Node_Id := Parent (T);
+ Res : Boolean;
+
+ begin
+ if not Is_Generic_Type (T) then
+ Res := False;
+
+ elsif (Nkind (Par)) = N_Private_Extension_Declaration then
+ Set_Needs_Initialized_Actual (Par);
+ Res := True;
+
+ elsif (Nkind (Par)) = N_Formal_Type_Declaration
+ and then Nkind (Formal_Type_Definition (Par))
+ = N_Formal_Private_Type_Definition
+ then
+ Set_Needs_Initialized_Actual (Formal_Type_Definition (Par));
+ Res := True;
+
+ else
+ Res := False;
+ end if;
+
+ if Res then
+ Error_Msg_N ("??!variable& of a generic type is potentially "
+ & "uninitialized", Ent);
+ Error_Msg_NE ("\??instantiations must provide fully initialized "
+ & "type for&", Ent, T);
+ end if;
+
+ return Res;
+ end May_Need_Initialized_Actual;
+
----------------------
-- Missing_Subunits --
----------------------
@@ -1266,6 +1312,7 @@ package body Sem_Warn is
if not Has_Unmodified (E1)
and then not Warnings_Off_E1
and then not Is_Junk_Name (Chars (E1))
+ and then not May_Need_Initialized_Actual (E1)
then
Output_Reference_Error
("?v?variable& is read but never assigned!");
@@ -1274,6 +1321,7 @@ package body Sem_Warn is
elsif not Has_Unreferenced (E1)
and then not Warnings_Off_E1
and then not Is_Junk_Name (Chars (E1))
+ and then not May_Need_Initialized_Actual (E1)
then
Output_Reference_Error -- CODEFIX
("?v?variable& is never read and never assigned!");
@@ -1403,6 +1451,7 @@ package body Sem_Warn is
end if;
goto Continue;
+
end if;
end if;
diff --git a/gcc/ada/sinfo.adb b/gcc/ada/sinfo.adb
index dbd54bbdf1e..c1eaae55793 100644
--- a/gcc/ada/sinfo.adb
+++ b/gcc/ada/sinfo.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -2224,6 +2224,15 @@ package body Sinfo is
return List2 (N);
end Names;
+ function Needs_Initialized_Actual
+ (N : Node_Id) return Boolean is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Formal_Private_Type_Definition
+ or else NT (N).Nkind = N_Private_Extension_Declaration);
+ return Flag18 (N);
+ end Needs_Initialized_Actual;
+
function Next_Entity
(N : Node_Id) return Node_Id is
begin
@@ -5364,6 +5373,15 @@ package body Sinfo is
Set_List2_With_Parent (N, Val);
end Set_Names;
+ procedure Set_Needs_Initialized_Actual
+ (N : Node_Id; Val : Boolean := True) is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Formal_Private_Type_Definition
+ or else NT (N).Nkind = N_Private_Extension_Declaration);
+ Set_Flag18 (N, Val);
+ end Set_Needs_Initialized_Actual;
+
procedure Set_Next_Entity
(N : Node_Id; Val : Node_Id) is
begin
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index ec4a3bdab9d..9a0afe7f5a7 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -1701,6 +1701,12 @@ package Sinfo is
-- present in an N_Subtype_Indication node, since we also use these in
-- calls to Freeze_Expression.
+ -- Needs_Initialized_Actual (Flag18-Sem)
+ -- Present in formal_private_type_definitions and on private extension
+ -- declarations. Set when the use of a formal type in a generic suggests
+ -- that the actual should be a fully initialized type, to avoid potential
+ -- use of uninitialized values.
+
-- Next_Entity (Node2-Sem)
-- Present in defining identifiers, defining character literals and
-- defining operator symbols (i.e. in all entities). The entities of a
@@ -5280,6 +5286,7 @@ package Sinfo is
-- Synchronized_Present (Flag7)
-- Subtype_Indication (Node5)
-- Interface_List (List2) (set to No_List if none)
+ -- Needs_Initialized_Actual (Flag18-Sem)
---------------------
-- 8.4 Use Clause --
@@ -6705,6 +6712,7 @@ package Sinfo is
-- Abstract_Present (Flag4)
-- Tagged_Present (Flag15)
-- Limited_Present (Flag17)
+ -- Needs_Initialized_Actual (Flag18-Sem)
--------------------------------------------
-- 12.5.1 Formal Derived Type Definition --
@@ -8930,7 +8938,6 @@ package Sinfo is
function Generalized_Indexing
(N : Node_Id) return Node_Id; -- Node4
-
function Generic_Associations
(N : Node_Id) return List_Id; -- List3
@@ -9195,6 +9202,9 @@ package Sinfo is
function Names
(N : Node_Id) return List_Id; -- List2
+ function Needs_Initialized_Actual
+ (N : Node_Id) return Boolean; -- Flag18
+
function Next_Entity
(N : Node_Id) return Node_Id; -- Node2
@@ -10194,6 +10204,9 @@ package Sinfo is
procedure Set_Names
(N : Node_Id; Val : List_Id); -- List2
+ procedure Set_Needs_Initialized_Actual
+ (N : Node_Id; Val : Boolean := True); -- Flag18
+
procedure Set_Next_Entity
(N : Node_Id; Val : Node_Id); -- Node2
@@ -12483,6 +12496,7 @@ package Sinfo is
pragma Inline (Must_Override);
pragma Inline (Name);
pragma Inline (Names);
+ pragma Inline (Needs_Initialized_Actual);
pragma Inline (Next_Entity);
pragma Inline (Next_Exit_Statement);
pragma Inline (Next_Implicit_With);
@@ -12812,6 +12826,7 @@ package Sinfo is
pragma Inline (Set_Must_Override);
pragma Inline (Set_Name);
pragma Inline (Set_Names);
+ pragma Inline (Set_Needs_Initialized_Actual);
pragma Inline (Set_Next_Entity);
pragma Inline (Set_Next_Exit_Statement);
pragma Inline (Set_Next_Implicit_With);
diff --git a/gcc/ada/sinput-l.adb b/gcc/ada/sinput-l.adb
index e2dbed3dfba..c084555cd93 100644
--- a/gcc/ada/sinput-l.adb
+++ b/gcc/ada/sinput-l.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -795,9 +795,106 @@ package body Sinput.L is
Prep_Buffer (Prep_Buffer_Last) := C;
end Put_Char_In_Prep_Buffer;
- -----------------------------------
- -- Source_File_Is_Pragma_No_Body --
- -----------------------------------
+ -------------------------
+ -- Source_File_Is_Body --
+ -------------------------
+
+ function Source_File_Is_Body (X : Source_File_Index) return Boolean is
+ Pcount : Natural;
+
+ begin
+ Initialize_Scanner (No_Unit, X);
+
+ -- Loop to look for subprogram or package body
+
+ loop
+ case Token is
+
+ -- PRAGMA, WITH, USE (which can appear before a body)
+
+ when Tok_Pragma | Tok_With | Tok_Use =>
+
+ -- We just want to skip any of these, do it by skipping to a
+ -- semicolon, but check for EOF, in case we have bad syntax.
+
+ loop
+ if Token = Tok_Semicolon then
+ Scan;
+ exit;
+ elsif Token = Tok_EOF then
+ return False;
+ else
+ Scan;
+ end if;
+ end loop;
+
+ -- PACKAGE
+
+ when Tok_Package =>
+ Scan; -- Past PACKAGE
+
+ -- We have a body if and only if BODY follows
+
+ return Token = Tok_Body;
+
+ -- FUNCTION or PROCEDURE
+
+ when Tok_Procedure | Tok_Function =>
+ Pcount := 0;
+
+ -- Loop through tokens following PROCEDURE or FUNCTION
+
+ loop
+ Scan;
+
+ case Token is
+
+ -- For parens, count paren level (note that paren level
+ -- can get greater than 1 if we have default parameters).
+
+ when Tok_Left_Paren =>
+ Pcount := Pcount + 1;
+
+ when Tok_Right_Paren =>
+ Pcount := Pcount - 1;
+
+ -- EOF means something weird, probably no body
+
+ when Tok_EOF =>
+ return False;
+
+ -- BEGIN or IS or END definitely means body is present
+
+ when Tok_Begin | Tok_Is | Tok_End =>
+ return True;
+
+ -- Semicolon means no body present if at outside any
+ -- parens. If within parens, ignore, since it could be
+ -- a parameter separator.
+
+ when Tok_Semicolon =>
+ if Pcount = 0 then
+ return False;
+ end if;
+
+ -- Skip anything else
+
+ when others =>
+ null;
+ end case;
+ end loop;
+
+ -- Anything else in main scan means we don't have a body
+
+ when others =>
+ return False;
+ end case;
+ end loop;
+ end Source_File_Is_Body;
+
+ ----------------------------
+ -- Source_File_Is_No_Body --
+ ----------------------------
function Source_File_Is_No_Body (X : Source_File_Index) return Boolean is
begin
@@ -826,27 +923,4 @@ package body Sinput.L is
return Token = Tok_EOF;
end Source_File_Is_No_Body;
- ----------------------------
- -- Source_File_Is_Subunit --
- ----------------------------
-
- function Source_File_Is_Subunit (X : Source_File_Index) return Boolean is
- begin
- Initialize_Scanner (No_Unit, X);
-
- -- We scan past junk to the first interesting compilation unit token, to
- -- see if it is SEPARATE. We ignore WITH keywords during this and also
- -- PRIVATE. The reason for ignoring PRIVATE is that it handles some
- -- error situations, and also to handle PRIVATE WITH in Ada 2005 mode.
-
- while Token = Tok_With
- or else Token = Tok_Private
- or else (Token not in Token_Class_Cunit and then Token /= Tok_EOF)
- loop
- Scan;
- end loop;
-
- return Token = Tok_Separate;
- end Source_File_Is_Subunit;
-
end Sinput.L;
diff --git a/gcc/ada/sinput-l.ads b/gcc/ada/sinput-l.ads
index a72237bab47..c1ac9c512fc 100644
--- a/gcc/ada/sinput-l.ads
+++ b/gcc/ada/sinput-l.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2008, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -64,19 +64,16 @@ package Sinput.L is
-- Called on completing the parsing of a source file. This call completes
-- the source file table entry for the current source file.
+ function Source_File_Is_Body (X : Source_File_Index) return Boolean;
+ -- Returns true if the designated source file contains a subprogram body
+ -- or a package body. This is a limited scan just to determine the answer
+ -- to this question..
+
function Source_File_Is_No_Body (X : Source_File_Index) return Boolean;
-- Returns true if the designated source file contains pragma No_Body;
-- and no other tokens. If the source file contains anything other than
-- this sequence of three tokens, then False is returned.
- function Source_File_Is_Subunit (X : Source_File_Index) return Boolean;
- -- This function determines if a source file represents a subunit. It
- -- works by scanning for the first compilation unit token, and returning
- -- True if it is the token SEPARATE. It will return False otherwise,
- -- meaning that the file cannot possibly be a legal subunit. This
- -- function does NOT do a complete parse of the file, or build a
- -- tree. It is used in the main driver in the check for bad bodies.
-
-------------------------------------------------
-- Subprograms for Dealing With Instantiations --
-------------------------------------------------
diff --git a/gcc/ada/stand.adb b/gcc/ada/stand.adb
index 3ce891e19fa..b2c6a3fa473 100644
--- a/gcc/ada/stand.adb
+++ b/gcc/ada/stand.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -29,6 +29,7 @@
-- --
------------------------------------------------------------------------------
+with Elists; use Elists;
with System; use System;
with Tree_IO; use Tree_IO;
@@ -46,9 +47,32 @@ package body Stand is
Tree_Read_Int (Int (Standard_Package_Node));
Tree_Read_Int (Int (Last_Standard_Node_Id));
Tree_Read_Int (Int (Last_Standard_List_Id));
+
+ Tree_Read_Int (Int (Boolean_Literals (False)));
+ Tree_Read_Int (Int (Boolean_Literals (True)));
+
Tree_Read_Int (Int (Standard_Void_Type));
Tree_Read_Int (Int (Standard_Exception_Type));
Tree_Read_Int (Int (Standard_A_String));
+ Tree_Read_Int (Int (Standard_A_Char));
+ Tree_Read_Int (Int (Standard_Debug_Renaming_Type));
+
+ -- Deal with Predefined_Float_Types, which is an Elist. We wrote the
+ -- entities out in sequence, terminated by an Empty entry.
+
+ declare
+ Elmt : Entity_Id;
+ begin
+ Predefined_Float_Types := New_Elmt_List;
+ loop
+ Tree_Read_Int (Int (Elmt));
+ exit when Elmt = Empty;
+ Append_Elmt (Elmt, Predefined_Float_Types);
+ end loop;
+ end;
+
+ -- Remainder of special entities
+
Tree_Read_Int (Int (Any_Id));
Tree_Read_Int (Int (Any_Type));
Tree_Read_Int (Int (Any_Access));
@@ -59,10 +83,12 @@ package body Stand is
Tree_Read_Int (Int (Any_Discrete));
Tree_Read_Int (Int (Any_Fixed));
Tree_Read_Int (Int (Any_Integer));
+ Tree_Read_Int (Int (Any_Modular));
Tree_Read_Int (Int (Any_Numeric));
Tree_Read_Int (Int (Any_Real));
Tree_Read_Int (Int (Any_Scalar));
Tree_Read_Int (Int (Any_String));
+ Tree_Read_Int (Int (Raise_Type));
Tree_Read_Int (Int (Universal_Integer));
Tree_Read_Int (Int (Universal_Real));
Tree_Read_Int (Int (Universal_Fixed));
@@ -70,12 +96,12 @@ package body Stand is
Tree_Read_Int (Int (Standard_Integer_16));
Tree_Read_Int (Int (Standard_Integer_32));
Tree_Read_Int (Int (Standard_Integer_64));
- Tree_Read_Int (Int (Standard_Unsigned_64));
Tree_Read_Int (Int (Standard_Short_Short_Unsigned));
Tree_Read_Int (Int (Standard_Short_Unsigned));
Tree_Read_Int (Int (Standard_Unsigned));
Tree_Read_Int (Int (Standard_Long_Unsigned));
Tree_Read_Int (Int (Standard_Long_Long_Unsigned));
+ Tree_Read_Int (Int (Standard_Unsigned_64));
Tree_Read_Int (Int (Abort_Signal));
Tree_Read_Int (Int (Standard_Op_Rotate_Left));
Tree_Read_Int (Int (Standard_Op_Rotate_Right));
@@ -96,9 +122,34 @@ package body Stand is
Tree_Write_Int (Int (Standard_Package_Node));
Tree_Write_Int (Int (Last_Standard_Node_Id));
Tree_Write_Int (Int (Last_Standard_List_Id));
+
+ Tree_Write_Int (Int (Boolean_Literals (False)));
+ Tree_Write_Int (Int (Boolean_Literals (True)));
+
Tree_Write_Int (Int (Standard_Void_Type));
Tree_Write_Int (Int (Standard_Exception_Type));
Tree_Write_Int (Int (Standard_A_String));
+ Tree_Write_Int (Int (Standard_A_Char));
+ Tree_Write_Int (Int (Standard_Debug_Renaming_Type));
+
+ -- Deal with Predefined_Float_Types, which is an Elist. Write the
+ -- entities out in sequence, terminated by an Empty entry.
+
+ declare
+ Elmt : Elmt_Id;
+
+ begin
+ Elmt := First_Elmt (Predefined_Float_Types);
+ while Present (Elmt) loop
+ Tree_Write_Int (Int (Node (Elmt)));
+ Next_Elmt (Elmt);
+ end loop;
+
+ Tree_Write_Int (Int (Empty));
+ end;
+
+ -- Remainder of special entries
+
Tree_Write_Int (Int (Any_Id));
Tree_Write_Int (Int (Any_Type));
Tree_Write_Int (Int (Any_Access));
@@ -109,10 +160,12 @@ package body Stand is
Tree_Write_Int (Int (Any_Discrete));
Tree_Write_Int (Int (Any_Fixed));
Tree_Write_Int (Int (Any_Integer));
+ Tree_Write_Int (Int (Any_Modular));
Tree_Write_Int (Int (Any_Numeric));
Tree_Write_Int (Int (Any_Real));
Tree_Write_Int (Int (Any_Scalar));
Tree_Write_Int (Int (Any_String));
+ Tree_Write_Int (Int (Raise_Type));
Tree_Write_Int (Int (Universal_Integer));
Tree_Write_Int (Int (Universal_Real));
Tree_Write_Int (Int (Universal_Fixed));
@@ -120,12 +173,12 @@ package body Stand is
Tree_Write_Int (Int (Standard_Integer_16));
Tree_Write_Int (Int (Standard_Integer_32));
Tree_Write_Int (Int (Standard_Integer_64));
- Tree_Write_Int (Int (Standard_Unsigned_64));
Tree_Write_Int (Int (Standard_Short_Short_Unsigned));
Tree_Write_Int (Int (Standard_Short_Unsigned));
Tree_Write_Int (Int (Standard_Unsigned));
Tree_Write_Int (Int (Standard_Long_Unsigned));
Tree_Write_Int (Int (Standard_Long_Long_Unsigned));
+ Tree_Write_Int (Int (Standard_Unsigned_64));
Tree_Write_Int (Int (Abort_Signal));
Tree_Write_Int (Int (Standard_Op_Rotate_Left));
Tree_Write_Int (Int (Standard_Op_Rotate_Right));
diff --git a/gcc/ada/stand.ads b/gcc/ada/stand.ads
index 325286e36c2..6bcd8cbeb75 100644
--- a/gcc/ada/stand.ads
+++ b/gcc/ada/stand.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -37,6 +37,11 @@ with Types; use Types;
package Stand is
+ -- Warning: the entities defined in this package are written out by the
+ -- Tree_Write routine, and read back in by the Tree_Read routine, so be
+ -- sure to modify these two routines if you add entities that are not
+ -- part of Standard_Entity.
+
type Standard_Entity_Type is (
-- This enumeration type contains an entry for each name in Standard
diff --git a/gcc/ada/tbuild.ads b/gcc/ada/tbuild.ads
index 16d6304d5eb..507dca41bf1 100644
--- a/gcc/ada/tbuild.ads
+++ b/gcc/ada/tbuild.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -205,8 +205,6 @@ package Tbuild is
-- captures the value of an expression (e.g. an aggregate). It should be
-- set whenever possible to point to the expression that is being captured.
-- This is provided to get better error messages, e.g. from CodePeer.
- --
- -- Make_Temp_Id would probably be a better name for this function???
function Make_Unsuppress_Block
(Loc : Source_Ptr;
diff --git a/gcc/ada/usage.adb b/gcc/ada/usage.adb
index 99fb652024e..4516bb2e289 100644
--- a/gcc/ada/usage.adb
+++ b/gcc/ada/usage.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -121,8 +121,8 @@ begin
Write_Eol;
-- Individual lines for switches. Write_Switch_Char outputs fourteen
- -- characters, so the remaining message is allowed to be a maximum
- -- of 65 characters to be comfortable in an 80 character window.
+ -- characters, so the remaining message is allowed to be a maximum of
+ -- 65 characters to be comfortable in an 80 character window.
-- Line for -gnata switch
@@ -494,16 +494,8 @@ begin
Write_Line (" .C* turn off warnings for unrepped components");
Write_Line (" d turn on warnings for implicit dereference");
Write_Line (" D* turn off warnings for implicit dereference");
-
- -- Switches -gnatw.d/w.D not available on VMS
-
- if not OpenVMS_On_Target then
- Write_Line
- (" .d turn on tagging of warnings with -gnatw switch");
- Write_Line
- (" .D* turn off tagging of warnings with -gnatw switch");
- end if;
-
+ Write_Line (" .d turn on tagging of warnings with -gnatw switch");
+ Write_Line (" .D* turn off tagging of warnings with -gnatw switch");
Write_Line (" e treat all warnings (but not info) as errors");
Write_Line (" .e turn on every optional info/warning " &
"(no exceptions)");
@@ -511,6 +503,7 @@ begin
Write_Line (" F* turn off warnings for unreferenced formal");
Write_Line (" g*+ turn on warnings for unrecognized pragma");
Write_Line (" G turn off warnings for unrecognized pragma");
+ Write_Line (" .g turn on GNAT warnings, same as Aao.sI.C.V.X");
Write_Line (" h turn on warnings for hiding declarations");
Write_Line (" H* turn off warnings for hiding declarations");
Write_Line (" .h turn on warnings for holes in records");
@@ -640,7 +633,7 @@ begin
Write_Line (" d check no DOS line terminators");
Write_Line (" e check end/exit labels present");
Write_Line (" f check no form feeds/vertical tabs in source");
- Write_Line (" g check standard GNAT style rules");
+ Write_Line (" g check standard GNAT style rules, same as ydISux");
Write_Line (" h check no horizontal tabs in source");
Write_Line (" i check if-then layout");
Write_Line (" I check mode in");
diff --git a/gcc/ada/warnsw.adb b/gcc/ada/warnsw.adb
index f07fdf92902..9691c10a0bc 100644
--- a/gcc/ada/warnsw.adb
+++ b/gcc/ada/warnsw.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1999-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1999-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -29,6 +29,65 @@ with Output; use Output;
package body Warnsw is
+ -- Local Subprograms
+
+ procedure All_Warnings (Setting : Boolean);
+ -- Sets all warnings off if Setting = False, and on if Setting = True
+
+ procedure WA_Warnings;
+ -- Turn on all warnings set by -gnatwa (also used by -gnatw.g)
+
+ ------------------
+ -- All_Warnings --
+ ------------------
+
+ procedure All_Warnings (Setting : Boolean) is
+ begin
+ Address_Clause_Overlay_Warnings := Setting;
+ Check_Unreferenced := Setting;
+ Check_Unreferenced_Formals := Setting;
+ Check_Withs := Setting;
+ Constant_Condition_Warnings := Setting;
+ Elab_Warnings := Setting;
+ Implementation_Unit_Warnings := Setting;
+ Ineffective_Inline_Warnings := Setting;
+ List_Body_Required_Info := Setting;
+ List_Inherited_Aspects := Setting;
+ Warn_On_Ada_2005_Compatibility := Setting;
+ Warn_On_Ada_2012_Compatibility := Setting;
+ Warn_On_All_Unread_Out_Parameters := Setting;
+ Warn_On_Assertion_Failure := Setting;
+ Warn_On_Assumed_Low_Bound := Setting;
+ Warn_On_Atomic_Synchronization := Setting;
+ Warn_On_Bad_Fixed_Value := Setting;
+ Warn_On_Biased_Representation := Setting;
+ Warn_On_Constant := Setting;
+ Warn_On_Deleted_Code := Setting;
+ Warn_On_Dereference := Setting;
+ Warn_On_Export_Import := Setting;
+ Warn_On_Hiding := Setting;
+ Warn_On_Modified_Unread := Setting;
+ Warn_On_No_Value_Assigned := Setting;
+ Warn_On_Non_Local_Exception := Setting;
+ Warn_On_Object_Renames_Function := Setting;
+ Warn_On_Obsolescent_Feature := Setting;
+ Warn_On_Overlap := Setting;
+ Warn_On_Overridden_Size := Setting;
+ Warn_On_Parameter_Order := Setting;
+ Warn_On_Questionable_Missing_Parens := Setting;
+ Warn_On_Record_Holes := Setting;
+ Warn_On_Redundant_Constructs := Setting;
+ Warn_On_Reverse_Bit_Order := Setting;
+ Warn_On_Standard_Redefinition := Setting;
+ Warn_On_Suspicious_Contract := Setting;
+ Warn_On_Suspicious_Modulus_Value := Setting;
+ Warn_On_Unchecked_Conversion := Setting;
+ Warn_On_Unordered_Enumeration_Type := Setting;
+ Warn_On_Unrecognized_Pragma := Setting;
+ Warn_On_Unrepped_Components := Setting;
+ Warn_On_Warnings_Off := Setting;
+ end All_Warnings;
+
----------------------
-- Restore_Warnings --
----------------------
@@ -57,6 +116,8 @@ package body Warnsw is
W.List_Body_Required_Info;
List_Inherited_Aspects :=
W.List_Inherited_Aspects;
+ No_Warn_On_Non_Local_Exception :=
+ W.No_Warn_On_Non_Local_Exception;
Warning_Doc_Switch :=
W.Warning_Doc_Switch;
Warn_On_Ada_2005_Compatibility :=
@@ -155,6 +216,8 @@ package body Warnsw is
List_Body_Required_Info;
W.List_Inherited_Aspects :=
List_Inherited_Aspects;
+ W.No_Warn_On_Non_Local_Exception :=
+ No_Warn_On_Non_Local_Exception;
W.Warning_Doc_Switch :=
Warning_Doc_Switch;
W.Warn_On_Ada_2005_Compatibility :=
@@ -221,7 +284,6 @@ package body Warnsw is
Warn_On_Unrepped_Components;
W.Warn_On_Warnings_Off :=
Warn_On_Warnings_Off;
-
return W;
end Save_Warnings;
@@ -257,48 +319,7 @@ package body Warnsw is
Warning_Doc_Switch := False;
when 'e' =>
- Address_Clause_Overlay_Warnings := True;
- Check_Unreferenced := True;
- Check_Unreferenced_Formals := True;
- Check_Withs := True;
- Constant_Condition_Warnings := True;
- Elab_Warnings := True;
- Implementation_Unit_Warnings := True;
- Ineffective_Inline_Warnings := True;
- List_Body_Required_Info := True;
- List_Inherited_Aspects := True;
- Warn_On_Ada_2005_Compatibility := True;
- Warn_On_Ada_2012_Compatibility := True;
- Warn_On_All_Unread_Out_Parameters := True;
- Warn_On_Assertion_Failure := True;
- Warn_On_Assumed_Low_Bound := True;
- Warn_On_Atomic_Synchronization := True;
- Warn_On_Bad_Fixed_Value := True;
- Warn_On_Biased_Representation := True;
- Warn_On_Constant := True;
- Warn_On_Deleted_Code := True;
- Warn_On_Dereference := True;
- Warn_On_Export_Import := True;
- Warn_On_Hiding := True;
- Warn_On_Modified_Unread := True;
- Warn_On_No_Value_Assigned := True;
- Warn_On_Non_Local_Exception := True;
- Warn_On_Object_Renames_Function := True;
- Warn_On_Obsolescent_Feature := True;
- Warn_On_Overlap := True;
- Warn_On_Overridden_Size := True;
- Warn_On_Parameter_Order := True;
- Warn_On_Questionable_Missing_Parens := True;
- Warn_On_Record_Holes := True;
- Warn_On_Redundant_Constructs := True;
- Warn_On_Reverse_Bit_Order := True;
- Warn_On_Standard_Redefinition := True;
- Warn_On_Suspicious_Contract := True;
- Warn_On_Unchecked_Conversion := True;
- Warn_On_Unordered_Enumeration_Type := True;
- Warn_On_Unrecognized_Pragma := True;
- Warn_On_Unrepped_Components := True;
- Warn_On_Warnings_Off := True;
+ All_Warnings (True);
when 'g' =>
Set_GNAT_Mode_Warnings;
@@ -417,48 +438,23 @@ package body Warnsw is
procedure Set_GNAT_Mode_Warnings is
begin
+ -- Set -gnatwa warnings and no others
+
+ All_Warnings (False);
+ WA_Warnings;
+
+ -- These warnings are added to the -gnatwa set
+
Address_Clause_Overlay_Warnings := True;
- Check_Unreferenced := True;
- Check_Unreferenced_Formals := True;
- Check_Withs := True;
- Constant_Condition_Warnings := True;
- Elab_Warnings := False;
+ Warn_On_Overridden_Size := True;
+
+ -- These warnings are removed from the -gnatwa set
+
Implementation_Unit_Warnings := False;
- Ineffective_Inline_Warnings := True;
- List_Body_Required_Info := False;
- List_Inherited_Aspects := False;
- Warning_Doc_Switch := False;
- Warn_On_Ada_2005_Compatibility := True;
- Warn_On_Ada_2012_Compatibility := True;
- Warn_On_All_Unread_Out_Parameters := False;
- Warn_On_Assertion_Failure := True;
- Warn_On_Assumed_Low_Bound := True;
- Warn_On_Atomic_Synchronization := False;
- Warn_On_Bad_Fixed_Value := True;
- Warn_On_Biased_Representation := True;
- Warn_On_Constant := True;
- Warn_On_Deleted_Code := False;
- Warn_On_Dereference := False;
- Warn_On_Export_Import := True;
- Warn_On_Hiding := False;
- Warn_On_Modified_Unread := True;
- Warn_On_No_Value_Assigned := True;
Warn_On_Non_Local_Exception := False;
- Warn_On_Object_Renames_Function := True;
- Warn_On_Obsolescent_Feature := True;
- Warn_On_Overlap := True;
- Warn_On_Overridden_Size := True;
- Warn_On_Parameter_Order := True;
- Warn_On_Questionable_Missing_Parens := True;
- Warn_On_Record_Holes := False;
- Warn_On_Redundant_Constructs := True;
+ No_Warn_On_Non_Local_Exception := True;
Warn_On_Reverse_Bit_Order := False;
- Warn_On_Suspicious_Contract := True;
- Warn_On_Unchecked_Conversion := True;
- Warn_On_Unordered_Enumeration_Type := False;
- Warn_On_Unrecognized_Pragma := True;
Warn_On_Unrepped_Components := False;
- Warn_On_Warnings_Off := False;
end Set_GNAT_Mode_Warnings;
------------------------
@@ -469,80 +465,10 @@ package body Warnsw is
begin
case C is
when 'a' =>
- Check_Unreferenced := True;
- Check_Unreferenced_Formals := True;
- Check_Withs := True;
- Constant_Condition_Warnings := True;
- Implementation_Unit_Warnings := True;
- Ineffective_Inline_Warnings := True;
- Warn_On_Ada_2005_Compatibility := True;
- Warn_On_Ada_2012_Compatibility := True;
- Warn_On_Assertion_Failure := True;
- Warn_On_Assumed_Low_Bound := True;
- Warn_On_Bad_Fixed_Value := True;
- Warn_On_Biased_Representation := True;
- Warn_On_Constant := True;
- Warn_On_Export_Import := True;
- Warn_On_Modified_Unread := True;
- Warn_On_No_Value_Assigned := True;
- Warn_On_Non_Local_Exception := True;
- Warn_On_Object_Renames_Function := True;
- Warn_On_Obsolescent_Feature := True;
- Warn_On_Overlap := True;
- Warn_On_Parameter_Order := True;
- Warn_On_Questionable_Missing_Parens := True;
- Warn_On_Redundant_Constructs := True;
- Warn_On_Reverse_Bit_Order := True;
- Warn_On_Suspicious_Contract := True;
- Warn_On_Unchecked_Conversion := True;
- Warn_On_Unrecognized_Pragma := True;
- Warn_On_Unrepped_Components := True;
+ WA_Warnings;
when 'A' =>
- Address_Clause_Overlay_Warnings := False;
- Check_Unreferenced := False;
- Check_Unreferenced_Formals := False;
- Check_Withs := False;
- Constant_Condition_Warnings := False;
- Elab_Warnings := False;
- Implementation_Unit_Warnings := False;
- Ineffective_Inline_Warnings := False;
- List_Body_Required_Info := False;
- List_Inherited_Aspects := False;
- Warning_Doc_Switch := False;
- Warn_On_Ada_2005_Compatibility := False;
- Warn_On_Ada_2012_Compatibility := False;
- Warn_On_All_Unread_Out_Parameters := False;
- Warn_On_Assertion_Failure := False;
- Warn_On_Assumed_Low_Bound := False;
- Warn_On_Bad_Fixed_Value := False;
- Warn_On_Biased_Representation := False;
- Warn_On_Constant := False;
- Warn_On_Deleted_Code := False;
- Warn_On_Dereference := False;
- Warn_On_Export_Import := False;
- Warn_On_Hiding := False;
- Warn_On_Modified_Unread := False;
- Warn_On_No_Value_Assigned := False;
- Warn_On_Non_Local_Exception := False;
- Warn_On_Object_Renames_Function := False;
- Warn_On_Obsolescent_Feature := False;
- Warn_On_Overlap := False;
- Warn_On_Overridden_Size := False;
- Warn_On_Parameter_Order := False;
- Warn_On_Record_Holes := False;
- Warn_On_Questionable_Missing_Parens := False;
- Warn_On_Redundant_Constructs := False;
- Warn_On_Reverse_Bit_Order := False;
- Warn_On_Standard_Redefinition := False;
- Warn_On_Suspicious_Contract := False;
- Warn_On_Suspicious_Modulus_Value := False;
- Warn_On_Unchecked_Conversion := False;
- Warn_On_Unordered_Enumeration_Type := False;
- Warn_On_Unrecognized_Pragma := False;
- Warn_On_Unrepped_Components := False;
- Warn_On_Warnings_Off := False;
-
+ All_Warnings (False);
No_Warn_On_Non_Local_Exception := True;
when 'b' =>
@@ -704,4 +630,40 @@ package body Warnsw is
return True;
end Set_Warning_Switch;
+ -----------------
+ -- WA_Warnings --
+ -----------------
+
+ procedure WA_Warnings is
+ begin
+ Check_Unreferenced := True;
+ Check_Unreferenced_Formals := True;
+ Check_Withs := True;
+ Constant_Condition_Warnings := True;
+ Implementation_Unit_Warnings := True;
+ Ineffective_Inline_Warnings := True;
+ Warn_On_Ada_2005_Compatibility := True;
+ Warn_On_Ada_2012_Compatibility := True;
+ Warn_On_Assertion_Failure := True;
+ Warn_On_Assumed_Low_Bound := True;
+ Warn_On_Bad_Fixed_Value := True;
+ Warn_On_Biased_Representation := True;
+ Warn_On_Constant := True;
+ Warn_On_Export_Import := True;
+ Warn_On_Modified_Unread := True;
+ Warn_On_No_Value_Assigned := True;
+ Warn_On_Non_Local_Exception := True;
+ Warn_On_Object_Renames_Function := True;
+ Warn_On_Obsolescent_Feature := True;
+ Warn_On_Overlap := True;
+ Warn_On_Parameter_Order := True;
+ Warn_On_Questionable_Missing_Parens := True;
+ Warn_On_Redundant_Constructs := True;
+ Warn_On_Reverse_Bit_Order := True;
+ Warn_On_Suspicious_Contract := True;
+ Warn_On_Unchecked_Conversion := True;
+ Warn_On_Unrecognized_Pragma := True;
+ Warn_On_Unrepped_Components := True;
+ end WA_Warnings;
+
end Warnsw;
diff --git a/gcc/ada/warnsw.ads b/gcc/ada/warnsw.ads
index fd6027b6e9e..89c5fb1ac52 100644
--- a/gcc/ada/warnsw.ads
+++ b/gcc/ada/warnsw.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1999-2013, Free Software Foundation, Inc. --
+-- Copyright (C) 1999-2014, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -71,6 +71,7 @@ package Warnsw is
Ineffective_Inline_Warnings : Boolean;
List_Body_Required_Info : Boolean;
List_Inherited_Aspects : Boolean;
+ No_Warn_On_Non_Local_Exception : Boolean;
Warning_Doc_Switch : Boolean;
Warn_On_Ada_2005_Compatibility : Boolean;
Warn_On_Ada_2012_Compatibility : Boolean;
@@ -99,6 +100,7 @@ package Warnsw is
Warn_On_Reverse_Bit_Order : Boolean;
Warn_On_Standard_Redefinition : Boolean;
Warn_On_Suspicious_Contract : Boolean;
+ Warn_On_Suspicious_Modulus_Value : Boolean;
Warn_On_Unchecked_Conversion : Boolean;
Warn_On_Unordered_Enumeration_Type : Boolean;
Warn_On_Unrecognized_Pragma : Boolean;
diff --git a/gcc/alias.c b/gcc/alias.c
index 5f50fc245c9..0246dd792f0 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -944,7 +944,7 @@ record_alias_subset (alias_set_type superset, alias_set_type subset)
{
/* Create an entry for the SUPERSET, so that we have a place to
attach the SUBSET. */
- superset_entry = ggc_alloc_cleared_alias_set_entry_d ();
+ superset_entry = ggc_cleared_alloc<alias_set_entry_d> ();
superset_entry->alias_set = superset;
superset_entry->children
= splay_tree_new_ggc (splay_tree_compare_ints,
diff --git a/gcc/alloc-pool.c b/gcc/alloc-pool.c
index 87fbd8556fb..1713011808f 100644
--- a/gcc/alloc-pool.c
+++ b/gcc/alloc-pool.c
@@ -43,7 +43,7 @@ typedef struct allocation_object_def
the allocated object may be even smaller than this structure.
We do not care about alignment for floating-point types. */
char *align_p;
- HOST_WIDEST_INT align_i;
+ int64_t align_i;
} u;
} allocation_object;
diff --git a/gcc/asan.c b/gcc/asan.c
index 118f9fccc29..5021338b855 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see
#include "ubsan.h"
#include "predict.h"
#include "params.h"
+#include "builtins.h"
/* AddressSanitizer finds out-of-bounds and use-after-free bugs
with <2x slowdown on average.
@@ -251,8 +252,8 @@ struct asan_mem_ref
/* The expression of the beginning of the memory region. */
tree start;
- /* The size of the access (can be 1, 2, 4, 8, 16 for now). */
- char access_size;
+ /* The size of the access. */
+ HOST_WIDE_INT access_size;
};
static alloc_pool asan_mem_ref_alloc_pool;
@@ -274,7 +275,7 @@ asan_mem_ref_get_alloc_pool ()
/* Initializes an instance of asan_mem_ref. */
static void
-asan_mem_ref_init (asan_mem_ref *ref, tree start, char access_size)
+asan_mem_ref_init (asan_mem_ref *ref, tree start, HOST_WIDE_INT access_size)
{
ref->start = start;
ref->access_size = access_size;
@@ -287,7 +288,7 @@ asan_mem_ref_init (asan_mem_ref *ref, tree start, char access_size)
access to the referenced memory. */
static asan_mem_ref*
-asan_mem_ref_new (tree start, char access_size)
+asan_mem_ref_new (tree start, HOST_WIDE_INT access_size)
{
asan_mem_ref *ref =
(asan_mem_ref *) pool_alloc (asan_mem_ref_get_alloc_pool ());
@@ -334,7 +335,7 @@ inline hashval_t
asan_mem_ref_hasher::hash (const asan_mem_ref *mem_ref)
{
hashval_t h = iterative_hash_expr (mem_ref->start, 0);
- h = iterative_hash_hashval_t (h, mem_ref->access_size);
+ h = iterative_hash_host_wide_int (mem_ref->access_size, h);
return h;
}
@@ -392,7 +393,7 @@ free_mem_ref_resources ()
/* Return true iff the memory reference REF has been instrumented. */
static bool
-has_mem_ref_been_instrumented (tree ref, char access_size)
+has_mem_ref_been_instrumented (tree ref, HOST_WIDE_INT access_size)
{
asan_mem_ref r;
asan_mem_ref_init (&r, ref, access_size);
@@ -480,7 +481,7 @@ get_mem_refs_of_builtin_call (const gimple call,
tree source0 = NULL_TREE, source1 = NULL_TREE,
dest = NULL_TREE, len = NULL_TREE;
bool is_store = true, got_reference_p = false;
- char access_size = 1;
+ HOST_WIDE_INT access_size = 1;
switch (DECL_FUNCTION_CODE (callee))
{
@@ -842,7 +843,7 @@ has_stmt_been_instrumented_p (gimple stmt)
/* Insert a memory reference into the hash table. */
static void
-update_mem_ref_hash_table (tree ref, char access_size)
+update_mem_ref_hash_table (tree ref, HOST_WIDE_INT access_size)
{
hash_table <asan_mem_ref_hasher> ht = get_mem_ref_hash_table ();
@@ -1315,20 +1316,23 @@ asan_protect_global (tree decl)
return true;
}
-/* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16}.
- IS_STORE is either 1 (for a store) or 0 (for a load).
- SIZE_IN_BYTES is one of 1, 2, 4, 8, 16. */
+/* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16,_n}.
+ IS_STORE is either 1 (for a store) or 0 (for a load). */
static tree
-report_error_func (bool is_store, int size_in_bytes)
+report_error_func (bool is_store, HOST_WIDE_INT size_in_bytes, bool slow_p)
{
- static enum built_in_function report[2][5]
+ static enum built_in_function report[2][6]
= { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
- BUILT_IN_ASAN_REPORT_LOAD16 },
+ BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
{ BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
- BUILT_IN_ASAN_REPORT_STORE16 } };
+ BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } };
+ if ((size_in_bytes & (size_in_bytes - 1)) != 0
+ || size_in_bytes > 16
+ || slow_p)
+ return builtin_decl_implicit (report[is_store][5]);
return builtin_decl_implicit (report[is_store][exact_log2 (size_in_bytes)]);
}
@@ -1450,6 +1454,47 @@ insert_if_then_before_iter (gimple cond,
gsi_insert_after (&cond_insert_point, cond, GSI_NEW_STMT);
}
+/* Build
+ (base_addr >> ASAN_SHADOW_SHIFT) + targetm.asan_shadow_offset (). */
+
+static tree
+build_shadow_mem_access (gimple_stmt_iterator *gsi, location_t location,
+ tree base_addr, tree shadow_ptr_type)
+{
+ tree t, uintptr_type = TREE_TYPE (base_addr);
+ tree shadow_type = TREE_TYPE (shadow_ptr_type);
+ gimple g;
+
+ t = build_int_cst (uintptr_type, ASAN_SHADOW_SHIFT);
+ g = gimple_build_assign_with_ops (RSHIFT_EXPR,
+ make_ssa_name (uintptr_type, NULL),
+ base_addr, t);
+ gimple_set_location (g, location);
+ gsi_insert_after (gsi, g, GSI_NEW_STMT);
+
+ t = build_int_cst (uintptr_type, targetm.asan_shadow_offset ());
+ g = gimple_build_assign_with_ops (PLUS_EXPR,
+ make_ssa_name (uintptr_type, NULL),
+ gimple_assign_lhs (g), t);
+ gimple_set_location (g, location);
+ gsi_insert_after (gsi, g, GSI_NEW_STMT);
+
+ g = gimple_build_assign_with_ops (NOP_EXPR,
+ make_ssa_name (shadow_ptr_type, NULL),
+ gimple_assign_lhs (g), NULL_TREE);
+ gimple_set_location (g, location);
+ gsi_insert_after (gsi, g, GSI_NEW_STMT);
+
+ t = build2 (MEM_REF, shadow_type, gimple_assign_lhs (g),
+ build_int_cst (shadow_ptr_type, 0));
+ g = gimple_build_assign_with_ops (MEM_REF,
+ make_ssa_name (shadow_type, NULL),
+ t, NULL_TREE);
+ gimple_set_location (g, location);
+ gsi_insert_after (gsi, g, GSI_NEW_STMT);
+ return gimple_assign_lhs (g);
+}
+
/* Instrument the memory access instruction BASE. Insert new
statements before or after ITER.
@@ -1457,8 +1502,7 @@ insert_if_then_before_iter (gimple cond,
SSA_NAME, or a non-SSA expression. LOCATION is the source code
location. IS_STORE is TRUE for a store, FALSE for a load.
BEFORE_P is TRUE for inserting the instrumentation code before
- ITER, FALSE for inserting it after ITER. SIZE_IN_BYTES is one of
- 1, 2, 4, 8, 16.
+ ITER, FALSE for inserting it after ITER.
If BEFORE_P is TRUE, *ITER is arranged to still point to the
statement it was pointing to prior to calling this function,
@@ -1466,7 +1510,8 @@ insert_if_then_before_iter (gimple cond,
static void
build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
- bool before_p, bool is_store, int size_in_bytes)
+ bool before_p, bool is_store, HOST_WIDE_INT size_in_bytes,
+ bool slow_p = false)
{
gimple_stmt_iterator gsi;
basic_block then_bb, else_bb;
@@ -1477,6 +1522,18 @@ build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
tree uintptr_type
= build_nonstandard_integer_type (TYPE_PRECISION (TREE_TYPE (base)), 1);
tree base_ssa = base;
+ HOST_WIDE_INT real_size_in_bytes = size_in_bytes;
+ tree sz_arg = NULL_TREE;
+
+ if (size_in_bytes == 1)
+ slow_p = false;
+ else if ((size_in_bytes & (size_in_bytes - 1)) != 0
+ || size_in_bytes > 16
+ || slow_p)
+ {
+ real_size_in_bytes = 1;
+ slow_p = true;
+ }
/* Get an iterator on the point where we can add the condition
statement for the instrumentation. */
@@ -1509,51 +1566,24 @@ build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
/* Build
(base_addr >> ASAN_SHADOW_SHIFT) + targetm.asan_shadow_offset (). */
+ shadow = build_shadow_mem_access (&gsi, location, base_addr,
+ shadow_ptr_type);
- t = build_int_cst (uintptr_type, ASAN_SHADOW_SHIFT);
- g = gimple_build_assign_with_ops (RSHIFT_EXPR,
- make_ssa_name (uintptr_type, NULL),
- base_addr, t);
- gimple_set_location (g, location);
- gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-
- t = build_int_cst (uintptr_type, targetm.asan_shadow_offset ());
- g = gimple_build_assign_with_ops (PLUS_EXPR,
- make_ssa_name (uintptr_type, NULL),
- gimple_assign_lhs (g), t);
- gimple_set_location (g, location);
- gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-
- g = gimple_build_assign_with_ops (NOP_EXPR,
- make_ssa_name (shadow_ptr_type, NULL),
- gimple_assign_lhs (g), NULL_TREE);
- gimple_set_location (g, location);
- gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-
- t = build2 (MEM_REF, shadow_type, gimple_assign_lhs (g),
- build_int_cst (shadow_ptr_type, 0));
- g = gimple_build_assign_with_ops (MEM_REF,
- make_ssa_name (shadow_type, NULL),
- t, NULL_TREE);
- gimple_set_location (g, location);
- gsi_insert_after (&gsi, g, GSI_NEW_STMT);
- shadow = gimple_assign_lhs (g);
-
- if (size_in_bytes < 8)
+ if (real_size_in_bytes < 8)
{
/* Slow path for 1, 2 and 4 byte accesses.
Test (shadow != 0)
- & ((base_addr & 7) + (size_in_bytes - 1)) >= shadow). */
+ & ((base_addr & 7) + (real_size_in_bytes - 1)) >= shadow). */
gimple_seq seq = NULL;
gimple shadow_test = build_assign (NE_EXPR, shadow, 0);
gimple_seq_add_stmt (&seq, shadow_test);
gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, base_addr, 7));
gimple_seq_add_stmt (&seq, build_type_cast (shadow_type,
gimple_seq_last (seq)));
- if (size_in_bytes > 1)
+ if (real_size_in_bytes > 1)
gimple_seq_add_stmt (&seq,
build_assign (PLUS_EXPR, gimple_seq_last (seq),
- size_in_bytes - 1));
+ real_size_in_bytes - 1));
gimple_seq_add_stmt (&seq, build_assign (GE_EXPR, gimple_seq_last (seq),
shadow));
gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
@@ -1561,6 +1591,39 @@ build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
t = gimple_assign_lhs (gimple_seq_last (seq));
gimple_seq_set_location (seq, location);
gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
+ /* For weird access sizes or misaligned, check first and last byte. */
+ if (slow_p)
+ {
+ g = gimple_build_assign_with_ops (PLUS_EXPR,
+ make_ssa_name (uintptr_type, NULL),
+ base_addr,
+ build_int_cst (uintptr_type,
+ size_in_bytes - 1));
+ gimple_set_location (g, location);
+ gsi_insert_after (&gsi, g, GSI_NEW_STMT);
+ tree base_end_addr = gimple_assign_lhs (g);
+
+ shadow = build_shadow_mem_access (&gsi, location, base_end_addr,
+ shadow_ptr_type);
+ seq = NULL;
+ shadow_test = build_assign (NE_EXPR, shadow, 0);
+ gimple_seq_add_stmt (&seq, shadow_test);
+ gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR,
+ base_end_addr, 7));
+ gimple_seq_add_stmt (&seq, build_type_cast (shadow_type,
+ gimple_seq_last (seq)));
+ gimple_seq_add_stmt (&seq, build_assign (GE_EXPR,
+ gimple_seq_last (seq),
+ shadow));
+ gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
+ gimple_seq_last (seq)));
+ gimple_seq_add_stmt (&seq, build_assign (BIT_IOR_EXPR, t,
+ gimple_seq_last (seq)));
+ t = gimple_assign_lhs (gimple_seq_last (seq));
+ gimple_seq_set_location (seq, location);
+ gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
+ sz_arg = build_int_cst (pointer_sized_int_node, size_in_bytes);
+ }
}
else
t = shadow;
@@ -1572,8 +1635,8 @@ build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
/* Generate call to the run-time library (e.g. __asan_report_load8). */
gsi = gsi_start_bb (then_bb);
- g = gimple_build_call (report_error_func (is_store, size_in_bytes),
- 1, base_addr);
+ g = gimple_build_call (report_error_func (is_store, size_in_bytes, slow_p),
+ sz_arg ? 2 : 1, base_addr, sz_arg);
gimple_set_location (g, location);
gsi_insert_after (&gsi, g, GSI_NEW_STMT);
@@ -1611,8 +1674,7 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t,
}
size_in_bytes = int_size_in_bytes (type);
- if ((size_in_bytes & (size_in_bytes - 1)) != 0
- || (unsigned HOST_WIDE_INT) size_in_bytes - 1 >= 16)
+ if (size_in_bytes <= 0)
return;
HOST_WIDE_INT bitsize, bitpos;
@@ -1621,7 +1683,8 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t,
int volatilep = 0, unsignedp = 0;
tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset,
&mode, &unsignedp, &volatilep, false);
- if (bitpos % (size_in_bytes * BITS_PER_UNIT)
+ if (((size_in_bytes & (size_in_bytes - 1)) == 0
+ && (bitpos % (size_in_bytes * BITS_PER_UNIT)))
|| bitsize != size_in_bytes * BITS_PER_UNIT)
{
if (TREE_CODE (t) == COMPONENT_REF
@@ -1634,6 +1697,8 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t,
}
return;
}
+ if (bitpos % BITS_PER_UNIT)
+ return;
if (TREE_CODE (inner) == VAR_DECL
&& offset == NULL_TREE
@@ -1666,8 +1731,31 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t,
base = build_fold_addr_expr (t);
if (!has_mem_ref_been_instrumented (base, size_in_bytes))
{
+ bool slow_p = false;
+ if (size_in_bytes > 1)
+ {
+ if ((size_in_bytes & (size_in_bytes - 1)) != 0
+ || size_in_bytes > 16)
+ slow_p = true;
+ else
+ {
+ unsigned int align = get_object_alignment (t);
+ if (align < size_in_bytes * BITS_PER_UNIT)
+ {
+ /* On non-strict alignment targets, if
+ 16-byte access is just 8-byte aligned,
+ this will result in misaligned shadow
+ memory 2 byte load, but otherwise can
+ be handled using one read. */
+ if (size_in_bytes != 16
+ || STRICT_ALIGNMENT
+ || align < 8 * BITS_PER_UNIT)
+ slow_p = true;
+ }
+ }
+ }
build_check_stmt (location, base, iter, /*before_p=*/true,
- is_store, size_in_bytes);
+ is_store, size_in_bytes, slow_p);
update_mem_ref_hash_table (base, size_in_bytes);
update_mem_ref_hash_table (t, size_in_bytes);
}
diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c
index 9581c71dedc..61b0caba8b8 100644
--- a/gcc/bb-reorder.c
+++ b/gcc/bb-reorder.c
@@ -99,6 +99,7 @@
#include "tree-pass.h"
#include "df.h"
#include "bb-reorder.h"
+#include "cgraph.h"
#include "except.h"
/* The number of rounds. In most cases there will only be 4 rounds, but
@@ -425,8 +426,7 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n)
/* Duplicate HEADER if it is a small block containing cond jump
in the end. */
if (any_condjump_p (BB_END (header)) && copy_bb_p (header, 0)
- && !find_reg_note (BB_END (header), REG_CROSSING_JUMP,
- NULL_RTX))
+ && !CROSSING_JUMP_P (BB_END (header)))
copy_bb (header, single_succ_edge (prev_bb), prev_bb, trace_n);
}
}
@@ -2194,10 +2194,10 @@ fix_crossing_unconditional_branches (void)
}
}
-/* Add REG_CROSSING_JUMP note to all crossing jump insns. */
+/* Update CROSSING_JUMP_P flags on all jump insns. */
static void
-add_reg_crossing_jump_notes (void)
+update_crossing_jump_flags (void)
{
basic_block bb;
edge e;
@@ -2205,12 +2205,15 @@ add_reg_crossing_jump_notes (void)
FOR_EACH_BB_FN (bb, cfun)
FOR_EACH_EDGE (e, ei, bb->succs)
- if ((e->flags & EDGE_CROSSING)
- && JUMP_P (BB_END (e->src))
- /* Some notes were added during fix_up_fall_thru_edges, via
- force_nonfallthru_and_redirect. */
- && !find_reg_note (BB_END (e->src), REG_CROSSING_JUMP, NULL_RTX))
- add_reg_note (BB_END (e->src), REG_CROSSING_JUMP, NULL_RTX);
+ if (e->flags & EDGE_CROSSING)
+ {
+ if (JUMP_P (BB_END (bb))
+ /* Some flags were added during fix_up_fall_thru_edges, via
+ force_nonfallthru_and_redirect. */
+ && !CROSSING_JUMP_P (BB_END (bb)))
+ CROSSING_JUMP_P (BB_END (bb)) = 1;
+ break;
+ }
}
/* Reorder basic blocks. The main entry point to this file. FLAGS is
@@ -2454,7 +2457,7 @@ pass_duplicate_computed_gotos::execute (function *fun)
continue;
/* Only consider blocks that can be duplicated. */
- if (find_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX)
+ if (CROSSING_JUMP_P (BB_END (bb))
|| !can_duplicate_block_p (bb))
continue;
@@ -2507,7 +2510,7 @@ pass_duplicate_computed_gotos::execute (function *fun)
/* Don't duplicate a partition crossing edge, which requires difficult
fixup. */
- if (find_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX))
+ if (JUMP_P (BB_END (bb)) && CROSSING_JUMP_P (BB_END (bb)))
continue;
new_bb = duplicate_block (single_succ (bb), single_succ_edge (bb), bb);
@@ -2667,7 +2670,7 @@ pass_partition_blocks::gate (function *fun)
/* See gate_handle_reorder_blocks. We should not partition if
we are going to omit the reordering. */
&& optimize_function_for_speed_p (fun)
- && !DECL_ONE_ONLY (current_function_decl)
+ && !DECL_COMDAT_GROUP (current_function_decl)
&& !user_defined_section_attribute);
}
@@ -2710,7 +2713,7 @@ pass_partition_blocks::execute (function *fun)
if (!HAS_LONG_UNCOND_BRANCH)
fix_crossing_unconditional_branches ();
- add_reg_crossing_jump_notes ();
+ update_crossing_jump_flags ();
/* Clear bb->aux fields that the above routines were using. */
clear_aux_for_blocks ();
diff --git a/gcc/bitmap.c b/gcc/bitmap.c
index c4d81581f14..4f0143316b7 100644
--- a/gcc/bitmap.c
+++ b/gcc/bitmap.c
@@ -34,11 +34,11 @@ struct bitmap_descriptor_d
const char *file;
int line;
int created;
- unsigned HOST_WIDEST_INT allocated;
- unsigned HOST_WIDEST_INT peak;
- unsigned HOST_WIDEST_INT current;
- unsigned HOST_WIDEST_INT nsearches;
- unsigned HOST_WIDEST_INT search_iter;
+ uint64_t allocated;
+ uint64_t peak;
+ uint64_t current;
+ uint64_t nsearches;
+ uint64_t search_iter;
};
typedef struct bitmap_descriptor_d *bitmap_descriptor;
@@ -244,7 +244,7 @@ bitmap_element_allocate (bitmap head)
/* Inner list was just a singleton. */
bitmap_ggc_free = element->prev;
else
- element = ggc_alloc_bitmap_element ();
+ element = ggc_alloc<bitmap_element> ();
}
if (GATHER_STATISTICS)
@@ -388,7 +388,7 @@ bitmap_gc_alloc_stat (ALONE_MEM_STAT_DECL)
{
bitmap map;
- map = ggc_alloc_bitmap_head ();
+ map = ggc_alloc<bitmap_head> ();
bitmap_initialize_stat (map, NULL PASS_MEM_STAT);
if (GATHER_STATISTICS)
@@ -2144,8 +2144,8 @@ bitmap_print (FILE *file, const_bitmap head, const char *prefix,
/* Used to accumulate statistics about bitmap sizes. */
struct output_info
{
- unsigned HOST_WIDEST_INT size;
- unsigned HOST_WIDEST_INT count;
+ uint64_t size;
+ uint64_t count;
};
/* Called via hash_table::traverse. Output bitmap descriptor pointed out by
@@ -2165,10 +2165,8 @@ print_statistics (bitmap_descriptor_d **slot, output_info *i)
sprintf (s, "%s:%i (%s)", s1, d->line, d->function);
s[41] = 0;
fprintf (stderr,
- "%-41s %9u"
- " %15"HOST_WIDEST_INT_PRINT"d %15"HOST_WIDEST_INT_PRINT"d"
- " %15"HOST_WIDEST_INT_PRINT"d"
- " %10"HOST_WIDEST_INT_PRINT"d %10"HOST_WIDEST_INT_PRINT"d\n",
+ "%-41s %9u %15"PRId64" %15"PRId64" %15"PRId64
+ " %10"PRId64" %10"PRId64"\n",
s, d->created,
d->allocated, d->peak, d->current,
d->nsearches, d->search_iter);
@@ -2201,7 +2199,7 @@ dump_bitmap_statistics (void)
bitmap_desc_hash.traverse <output_info *, print_statistics> (&info);
fprintf (stderr, "---------------------------------------------------------------------------------\n");
fprintf (stderr,
- "%-41s %9"HOST_WIDEST_INT_PRINT"d %15"HOST_WIDEST_INT_PRINT"d\n",
+ "%-41s %9"PRId64" %15"PRId64"\n",
"Total", info.count, info.size);
fprintf (stderr, "---------------------------------------------------------------------------------\n");
}
diff --git a/gcc/bt-load.c b/gcc/bt-load.c
index 757a3e79b57..f57d84d4707 100644
--- a/gcc/bt-load.c
+++ b/gcc/bt-load.c
@@ -1411,9 +1411,9 @@ migrate_btr_defs (enum reg_class btr_class, int allow_callee_save)
{
basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i);
fprintf (dump_file,
- "Basic block %d: count = " HOST_WIDEST_INT_PRINT_DEC
+ "Basic block %d: count = %" PRId64
" loop-depth = %d idom = %d\n",
- i, (HOST_WIDEST_INT) bb->count, bb_loop_depth (bb),
+ i, (int64_t) bb->count, bb_loop_depth (bb),
get_immediate_dominator (CDI_DOMINATORS, bb)->index);
}
}
diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index fba9c7ddd80..f09c33547b8 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -29,13 +29,7 @@ along with GCC; see the file COPYING3. If not see
DEF_FUNCTION_TYPE_0 (ENUM, RETURN)
DEF_FUNCTION_TYPE_1 (ENUM, RETURN, ARG1)
DEF_FUNCTION_TYPE_2 (ENUM, RETURN, ARG1, ARG2)
- DEF_FUNCTION_TYPE_3 (ENUM, RETURN, ARG1, ARG2, ARG3)
- DEF_FUNCTION_TYPE_4 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4)
- DEF_FUNCTION_TYPE_5 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5)
- DEF_FUNCTION_TYPE_6 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6)
- DEF_FUNCTION_TYPE_7 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7)
- DEF_FUNCTION_TYPE_8 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7,
- ARG8)
+ [...]
These macros describe function types. ENUM is as above. The
RETURN type is one of the enumerals already defined. ARG1, ARG2,
@@ -44,9 +38,7 @@ along with GCC; see the file COPYING3. If not see
DEF_FUNCTION_TYPE_VAR_0 (ENUM, RETURN)
DEF_FUNCTION_TYPE_VAR_1 (ENUM, RETURN, ARG1)
DEF_FUNCTION_TYPE_VAR_2 (ENUM, RETURN, ARG1, ARG2)
- DEF_FUNCTION_TYPE_VAR_3 (ENUM, RETURN, ARG1, ARG2, ARG3)
- DEF_FUNCTION_TYPE_VAR_4 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4)
- DEF_FUNCTION_TYPE_VAR_5 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5)
+ [...]
Similar, but for function types that take variable arguments.
For example:
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 140d6ba1a5b..2d3d867b0b2 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -259,31 +259,6 @@ is_builtin_fn (tree decl)
return TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl);
}
-/* By default we assume that c99 functions are present at the runtime,
- but sincos is not. */
-bool
-default_libc_has_function (enum function_class fn_class)
-{
- if (fn_class == function_c94
- || fn_class == function_c99_misc
- || fn_class == function_c99_math_complex)
- return true;
-
- return false;
-}
-
-bool
-gnu_libc_has_function (enum function_class fn_class ATTRIBUTE_UNUSED)
-{
- return true;
-}
-
-bool
-no_c99_libc_has_function (enum function_class fn_class ATTRIBUTE_UNUSED)
-{
- return false;
-}
-
/* Return true if NODE should be considered for inline expansion regardless
of the optimization level. This means whenever a function is invoked with
its "internal" name, which normally contains the prefix "__builtin". */
@@ -4690,29 +4665,6 @@ expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
return expand_copysign (op0, op1, target);
}
-/* Create a new constant string literal and return a char* pointer to it.
- The STRING_CST value is the LEN characters at STR. */
-tree
-build_string_literal (int len, const char *str)
-{
- tree t, elem, index, type;
-
- t = build_string (len, str);
- elem = build_type_variant (char_type_node, 1, 0);
- index = build_index_type (size_int (len - 1));
- type = build_array_type (elem, index);
- TREE_TYPE (t) = type;
- TREE_CONSTANT (t) = 1;
- TREE_READONLY (t) = 1;
- TREE_STATIC (t) = 1;
-
- type = build_pointer_type (elem);
- t = build1 (ADDR_EXPR, type,
- build4 (ARRAY_REF, elem,
- t, integer_zero_node, NULL_TREE, NULL_TREE));
- return t;
-}
-
/* Expand a call to __builtin___clear_cache. */
static rtx
@@ -11159,66 +11111,6 @@ fold_call_expr (location_t loc, tree exp, bool ignore)
return NULL_TREE;
}
-/* Conveniently construct a function call expression. FNDECL names the
- function to be called and N arguments are passed in the array
- ARGARRAY. */
-
-tree
-build_call_expr_loc_array (location_t loc, tree fndecl, int n, tree *argarray)
-{
- tree fntype = TREE_TYPE (fndecl);
- tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
-
- return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
-}
-
-/* Conveniently construct a function call expression. FNDECL names the
- function to be called and the arguments are passed in the vector
- VEC. */
-
-tree
-build_call_expr_loc_vec (location_t loc, tree fndecl, vec<tree, va_gc> *vec)
-{
- return build_call_expr_loc_array (loc, fndecl, vec_safe_length (vec),
- vec_safe_address (vec));
-}
-
-
-/* Conveniently construct a function call expression. FNDECL names the
- function to be called, N is the number of arguments, and the "..."
- parameters are the argument expressions. */
-
-tree
-build_call_expr_loc (location_t loc, tree fndecl, int n, ...)
-{
- va_list ap;
- tree *argarray = XALLOCAVEC (tree, n);
- int i;
-
- va_start (ap, n);
- for (i = 0; i < n; i++)
- argarray[i] = va_arg (ap, tree);
- va_end (ap);
- return build_call_expr_loc_array (loc, fndecl, n, argarray);
-}
-
-/* Like build_call_expr_loc (UNKNOWN_LOCATION, ...). Duplicated because
- varargs macros aren't supported by all bootstrap compilers. */
-
-tree
-build_call_expr (tree fndecl, int n, ...)
-{
- va_list ap;
- tree *argarray = XALLOCAVEC (tree, n);
- int i;
-
- va_start (ap, n);
- for (i = 0; i < n; i++)
- argarray[i] = va_arg (ap, tree);
- va_end (ap);
- return build_call_expr_loc_array (UNKNOWN_LOCATION, fndecl, n, argarray);
-}
-
/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
N arguments are passed in the array ARGARRAY. */
@@ -12281,7 +12173,7 @@ fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt,
/* Expand a call EXP to __builtin_object_size. */
-rtx
+static rtx
expand_builtin_object_size (tree exp)
{
tree ost;
@@ -12586,7 +12478,7 @@ maybe_emit_free_warning (tree exp)
/* Fold a call to __builtin_object_size with arguments PTR and OST,
if possible. */
-tree
+static tree
fold_builtin_object_size (tree ptr, tree ost)
{
unsigned HOST_WIDE_INT bytes;
diff --git a/gcc/builtins.def b/gcc/builtins.def
index d400ecb4e8f..cd823a3be49 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -176,7 +176,7 @@ along with GCC; see the file COPYING3. If not see
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
true, true, true, ATTRS, true, \
(flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_THREAD \
- | SANITIZE_UNDEFINED | SANITIZE_FLOAT_DIVIDE)))
+ | SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT)))
#undef DEF_CILKPLUS_BUILTIN
#define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
diff --git a/gcc/builtins.h b/gcc/builtins.h
index 5eb930369d4..8be990e8d8a 100644
--- a/gcc/builtins.h
+++ b/gcc/builtins.h
@@ -20,6 +20,8 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_BUILTINS_H
#define GCC_BUILTINS_H
+#include <mpc.h>
+
/* Target-dependent globals. */
struct target_builtins {
/* For each register that may be used for calling a function, this
@@ -44,6 +46,54 @@ extern struct target_builtins *this_target_builtins;
#define this_target_builtins (&default_target_builtins)
#endif
+/* Non-zero if __builtin_constant_p should be folded right away. */
+extern bool force_folding_builtin_constant_p;
+
+extern bool is_builtin_fn (tree);
+extern bool get_object_alignment_1 (tree, unsigned int *,
+ unsigned HOST_WIDE_INT *);
+extern unsigned int get_object_alignment (tree);
+extern bool get_pointer_alignment_1 (tree, unsigned int *,
+ unsigned HOST_WIDE_INT *);
+extern unsigned int get_pointer_alignment (tree);
+extern tree c_strlen (tree, int);
+extern void expand_builtin_setjmp_setup (rtx, rtx);
+extern void expand_builtin_setjmp_receiver (rtx);
+extern tree mathfn_built_in (tree, enum built_in_function fn);
+extern rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
+extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
+extern rtx expand_builtin_saveregs (void);
+extern tree std_build_builtin_va_list (void);
+extern tree std_fn_abi_va_list (tree);
+extern tree std_canonical_va_list_type (tree);
+extern void std_expand_builtin_va_start (tree, rtx);
+extern void expand_builtin_trap (void);
+extern rtx expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+extern enum built_in_function builtin_mathfn_code (const_tree);
+extern tree fold_builtin_expect (location_t, tree, tree, tree);
+extern tree fold_builtin_strcpy (location_t, tree, tree, tree, tree);
+extern tree fold_builtin_strncpy (location_t, tree, tree, tree, tree, tree);
+extern tree fold_fma (location_t, tree, tree, tree, tree);
+extern bool avoid_folding_inline_builtin (tree);
+extern tree fold_call_expr (location_t, tree, bool);
+extern tree fold_builtin_call_array (location_t, tree, tree, int, tree *);
extern bool validate_gimple_arglist (const_gimple, ...);
+extern rtx default_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+extern tree fold_builtin_strcat (location_t, tree, tree, tree);
+extern tree fold_builtin_fputs (location_t, tree, tree, bool, bool, tree);
+extern bool fold_builtin_next_arg (tree, bool);
+extern tree fold_builtin_memory_chk (location_t, tree, tree, tree, tree, tree,
+ tree, bool, enum built_in_function);
+extern tree fold_builtin_stxcpy_chk (location_t, tree, tree, tree, tree, tree,
+ bool, enum built_in_function);
+extern tree fold_builtin_stxncpy_chk (location_t, tree, tree, tree, tree, tree,
+ bool, enum built_in_function);
+extern tree gimple_fold_builtin_snprintf_chk (gimple, tree,
+ enum built_in_function);
+extern tree do_mpc_arg2 (tree, tree, tree, int, int (*)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t));
+extern tree fold_call_stmt (gimple, bool);
+extern void set_builtin_user_assembler_name (tree decl, const char *asmspec);
+extern bool is_simple_builtin (tree);
+extern bool is_inexpensive_builtin (tree);
#endif
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 4673a16b10c..675a66e9482 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,63 @@
+2014-05-22 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-common.h (c_omp_sharing_predetermined, c_omp_remap_decl):
+ Remove prototypes.
+ (record_types_used_by_current_var_decl): Move prototype to where
+ it belongs.
+
+ * c-common.c (DEF_FUNCTION_TYPE_0, DEF_FUNCTION_TYPE_6)
+ (DEF_FUNCTION_TYPE_7, DEF_FUNCTION_TYPE_8)
+ (DEF_FUNCTION_TYPE_VAR_5): Cosmetic fixes.
+
+2014-05-21 Richard Sandiford <rsandifo@linux.vnet.ibm.com>
+
+ * c-common.h (CTI_VOID_ZERO, void_zero_node): Delete.
+ * c-common.c (c_common_nodes_and_builtins): Don't initialize
+ void_zero_node.
+ * c-pretty-print.c (pp_c_void_constant): New function.
+ (c_pretty_printer::constant, c_pretty_printer::primary_expression)
+ (c_pretty_printer::expression): Handle VOID_CST.
+ * cilk.c (extract_free_variables): Likewise.
+ * c-ubsan.c (ubsan_instrument_division, ubsan_instrument_shift)
+ (ubsan_instrument_vla): Use void_node instead of void_zero_node.
+
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * c-common.h (sorted_fields_type): Remove variable_size GTY attribute.
+ * c-pragma.c (push_alignment): Adjust.
+ (handle_pragma_push_options): Likewise.
+
+2014-05-09 Marek Polacek <polacek@redhat.com>
+
+ PR c/50459
+ * c-common.c (check_user_alignment): Return -1 if alignment is error
+ node.
+ (handle_aligned_attribute): Don't call default_conversion on
+ FUNCTION_DECLs.
+ (handle_vector_size_attribute): Likewise.
+ (handle_tm_wrap_attribute): Handle case when wrap_decl is error node.
+ (handle_sentinel_attribute): Call default_conversion and allow even
+ integral types as an argument.
+
+2014-05-08 Marek Polacek <polacek@redhat.com>
+
+ PR c/61053
+ * c-common.c (min_align_of_type): New function factored out from...
+ (c_sizeof_or_alignof_type): ...here.
+ * c-common.h (min_align_of_type): Declare.
+
+2014-05-08 Marek Polacek <polacek@redhat.com>
+
+ PR c/61077
+ * c-common.c (check_main_parameter_types): Warn for _Atomic-qualified
+ parameter type of main.
+
+2014-05-07 DJ Delorie <dj@redhat.com>
+
+ * c-cppbuiltin.c (print_bits_of_hex): New.
+ (builtin_define_type_minmax): Print values using hex so as not to
+ require a pre-computed list of string values.
+
2014-05-06 Kenneth Zadeck <zadeck@naturalbridge.com>
Mike Stump <mikestump@comcast.net>
Richard Sandiford <rdsandiford@googlemail.com>
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 0afe2f5ab38..6ec14fc04ab 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -2193,6 +2193,20 @@ check_main_parameter_types (tree decl)
if (type == void_type_node || type == error_mark_node )
break;
+ tree t = type;
+ if (TYPE_ATOMIC (t))
+ pedwarn (input_location, OPT_Wmain,
+ "%<_Atomic%>-qualified parameter type %qT of %q+D",
+ type, decl);
+ while (POINTER_TYPE_P (t))
+ {
+ t = TREE_TYPE (t);
+ if (TYPE_ATOMIC (t))
+ pedwarn (input_location, OPT_Wmain,
+ "%<_Atomic%>-qualified parameter type %qT of %q+D",
+ type, decl);
+ }
+
++argct;
switch (argct)
{
@@ -4924,6 +4938,26 @@ c_common_get_alias_set (tree t)
return -1;
}
+/* Return the least alignment required for type TYPE. */
+
+unsigned int
+min_align_of_type (tree type)
+{
+ unsigned int align = TYPE_ALIGN (type);
+ align = MIN (align, BIGGEST_ALIGNMENT);
+#ifdef BIGGEST_FIELD_ALIGNMENT
+ align = MIN (align, BIGGEST_FIELD_ALIGNMENT);
+#endif
+ unsigned int field_align = align;
+#ifdef ADJUST_FIELD_ALIGN
+ tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
+ type);
+ field_align = ADJUST_FIELD_ALIGN (field, field_align);
+#endif
+ align = MIN (align, field_align);
+ return align / BITS_PER_UNIT;
+}
+
/* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where
the IS_SIZEOF parameter indicates which operator is being applied.
The COMPLAIN flag controls whether we should diagnose possibly
@@ -5002,21 +5036,7 @@ c_sizeof_or_alignof_type (location_t loc,
size_int (TYPE_PRECISION (char_type_node)
/ BITS_PER_UNIT));
else if (min_alignof)
- {
- unsigned int align = TYPE_ALIGN (type);
- align = MIN (align, BIGGEST_ALIGNMENT);
-#ifdef BIGGEST_FIELD_ALIGNMENT
- align = MIN (align, BIGGEST_FIELD_ALIGNMENT);
-#endif
- unsigned int field_align = align;
-#ifdef ADJUST_FIELD_ALIGN
- tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
- type);
- field_align = ADJUST_FIELD_ALIGN (field, field_align);
-#endif
- align = MIN (align, field_align);
- value = size_int (align / BITS_PER_UNIT);
- }
+ value = size_int (min_align_of_type (type));
else
value = size_int (TYPE_ALIGN_UNIT (type));
}
@@ -5108,15 +5128,18 @@ enum c_builtin_type
#define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
#define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
#define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME,
-#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) NAME,
-#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) NAME,
-#define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) NAME,
+#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6) NAME,
+#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7) NAME,
+#define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7, ARG8) NAME,
#define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
#define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
#define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
#define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
#define DEF_FUNCTION_TYPE_VAR_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
-#define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG6) \
+#define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
NAME,
#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
#include "builtin-types.def"
@@ -5234,12 +5257,15 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
#include "builtin-types.def"
#undef DEF_PRIMITIVE_TYPE
+#undef DEF_FUNCTION_TYPE_0
#undef DEF_FUNCTION_TYPE_1
#undef DEF_FUNCTION_TYPE_2
#undef DEF_FUNCTION_TYPE_3
#undef DEF_FUNCTION_TYPE_4
#undef DEF_FUNCTION_TYPE_5
#undef DEF_FUNCTION_TYPE_6
+#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
#undef DEF_FUNCTION_TYPE_VAR_2
@@ -5504,10 +5530,6 @@ c_common_nodes_and_builtins (void)
TYPE_NAME (void_type_node) = void_name;
}
- /* This node must not be shared. */
- void_zero_node = make_int_cst (1, 1);
- TREE_TYPE (void_zero_node) = void_type_node;
-
void_list_node = build_void_list_node ();
/* Make a type to be the domain of a few array types
@@ -7423,6 +7445,8 @@ check_user_alignment (const_tree align, bool allow_zero)
{
int i;
+ if (error_operand_p (align))
+ return -1;
if (TREE_CODE (align) != INTEGER_CST
|| !INTEGRAL_TYPE_P (TREE_TYPE (align)))
{
@@ -7544,7 +7568,8 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
if (args)
{
align_expr = TREE_VALUE (args);
- if (align_expr && TREE_CODE (align_expr) != IDENTIFIER_NODE)
+ if (align_expr && TREE_CODE (align_expr) != IDENTIFIER_NODE
+ && TREE_CODE (align_expr) != FUNCTION_DECL)
align_expr = default_conversion (align_expr);
}
else
@@ -8409,9 +8434,11 @@ handle_tm_wrap_attribute (tree *node, tree name, tree args,
else
{
tree wrap_decl = TREE_VALUE (args);
- if (TREE_CODE (wrap_decl) != IDENTIFIER_NODE
- && TREE_CODE (wrap_decl) != VAR_DECL
- && TREE_CODE (wrap_decl) != FUNCTION_DECL)
+ if (error_operand_p (wrap_decl))
+ ;
+ else if (TREE_CODE (wrap_decl) != IDENTIFIER_NODE
+ && TREE_CODE (wrap_decl) != VAR_DECL
+ && TREE_CODE (wrap_decl) != FUNCTION_DECL)
error ("%qE argument not an identifier", name);
else
{
@@ -8538,7 +8565,8 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
*no_add_attrs = true;
size = TREE_VALUE (args);
- if (size && TREE_CODE (size) != IDENTIFIER_NODE)
+ if (size && TREE_CODE (size) != IDENTIFIER_NODE
+ && TREE_CODE (size) != FUNCTION_DECL)
size = default_conversion (size);
if (!tree_fits_uhwi_p (size))
@@ -8950,8 +8978,12 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
if (args)
{
tree position = TREE_VALUE (args);
+ if (position && TREE_CODE (position) != IDENTIFIER_NODE
+ && TREE_CODE (position) != FUNCTION_DECL)
+ position = default_conversion (position);
- if (TREE_CODE (position) != INTEGER_CST)
+ if (TREE_CODE (position) != INTEGER_CST
+ || !INTEGRAL_TYPE_P (TREE_TYPE (position)))
{
warning (OPT_Wattributes,
"requested position is not an integer constant");
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 57b7dceefdc..0d34004e4ff 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -297,8 +297,6 @@ enum c_tree_index
CTI_C99_FUNCTION_NAME_DECL,
CTI_SAVED_FUNCTION_NAME_DECLS,
- CTI_VOID_ZERO,
-
CTI_NULL,
CTI_MAX
@@ -430,9 +428,6 @@ extern const unsigned int num_c_common_reswords;
#define c99_function_name_decl_node c_global_trees[CTI_C99_FUNCTION_NAME_DECL]
#define saved_function_name_decls c_global_trees[CTI_SAVED_FUNCTION_NAME_DECLS]
-/* A node for `((void) 0)'. */
-#define void_zero_node c_global_trees[CTI_VOID_ZERO]
-
/* The node for C++ `__null'. */
#define null_node c_global_trees[CTI_NULL]
@@ -440,7 +435,7 @@ extern GTY(()) tree c_global_trees[CTI_MAX];
/* In a RECORD_TYPE, a sorted array of the fields of the type, not a
tree for size reasons. */
-struct GTY((variable_size)) sorted_fields_type {
+struct GTY(()) sorted_fields_type {
int len;
tree GTY((length ("%h.len"))) elts[1];
};
@@ -758,6 +753,7 @@ extern tree c_wrap_maybe_const (tree, bool);
extern tree c_save_expr (tree);
extern tree c_common_truthvalue_conversion (location_t, tree);
extern void c_apply_type_quals_to_decl (int, tree);
+extern unsigned int min_align_of_type (tree);
extern tree c_sizeof_or_alignof_type (location_t, tree, bool, bool, int);
extern tree c_alignof_expr (location_t, tree);
/* Print an error message for invalid operands to arith operation CODE.
@@ -1004,6 +1000,7 @@ extern void warn_for_sign_compare (location_t,
extern void do_warn_double_promotion (tree, tree, tree, const char *,
location_t);
extern void set_underlying_type (tree);
+extern void record_types_used_by_current_var_decl (tree);
extern void record_locally_defined_typedef (tree);
extern void maybe_record_typedef_use (tree);
extern void maybe_warn_unused_local_typedefs (void);
@@ -1212,11 +1209,6 @@ extern tree c_omp_declare_simd_clauses_to_numbers (tree, tree);
extern void c_omp_declare_simd_clauses_to_decls (tree, tree);
extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
-/* Not in c-omp.c; provided by the front end. */
-extern bool c_omp_sharing_predetermined (tree);
-extern tree c_omp_remap_decl (tree, bool);
-extern void record_types_used_by_current_var_decl (tree);
-
/* Return next tree in the chain for chain_next walking of tree nodes. */
static inline tree
c_tree_chain_next (tree t)
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 2f2e7bae824..d07c9809eab 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -1288,6 +1288,50 @@ builtin_define_type_max (const char *macro, tree type)
builtin_define_type_minmax (NULL, macro, type);
}
+/* Given a value with COUNT LSBs set, fill BUF with a hexidecimal
+ representation of that value. For example, a COUNT of 10 would
+ return "0x3ff". */
+
+static void
+print_bits_of_hex (char *buf, int bufsz, int count)
+{
+ gcc_assert (bufsz > 3);
+ *buf++ = '0';
+ *buf++ = 'x';
+ bufsz -= 2;
+
+ gcc_assert (count > 0);
+
+ switch (count % 4) {
+ case 0:
+ break;
+ case 1:
+ *buf++ = '1';
+ bufsz --;
+ count -= 1;
+ break;
+ case 2:
+ *buf++ = '3';
+ bufsz --;
+ count -= 2;
+ break;
+ case 3:
+ *buf++ = '7';
+ bufsz --;
+ count -= 3;
+ break;
+ }
+ while (count >= 4)
+ {
+ gcc_assert (bufsz > 1);
+ *buf++ = 'f';
+ bufsz --;
+ count -= 4;
+ }
+ gcc_assert (bufsz > 0);
+ *buf++ = 0;
+}
+
/* Define MIN_MACRO (if not NULL) and MAX_MACRO for TYPE based on the
precision of the type. */
@@ -1295,32 +1339,17 @@ static void
builtin_define_type_minmax (const char *min_macro, const char *max_macro,
tree type)
{
- static const char *const values[]
- = { "127", "255",
- "32767", "65535",
- "2147483647", "4294967295",
- "9223372036854775807", "18446744073709551615",
- "170141183460469231731687303715884105727",
- "340282366920938463463374607431768211455" };
-
- const char *value, *suffix;
+#define PBOH_SZ (MAX_BITSIZE_MODE_ANY_INT/4+4)
+ char value[PBOH_SZ];
+
+ const char *suffix;
char *buf;
- size_t idx;
+ int bits;
- /* Pre-rendering the values mean we don't have to futz with printing a
- multi-word decimal value. There are also a very limited number of
- precisions that we support, so it's really a waste of time. */
- switch (TYPE_PRECISION (type))
- {
- case 8: idx = 0; break;
- case 16: idx = 2; break;
- case 32: idx = 4; break;
- case 64: idx = 6; break;
- case 128: idx = 8; break;
- default: gcc_unreachable ();
- }
+ bits = TYPE_PRECISION (type) + (TYPE_UNSIGNED (type) ? 0 : -1);
+
+ print_bits_of_hex (value, PBOH_SZ, bits);
- value = values[idx + TYPE_UNSIGNED (type)];
suffix = type_suffix (type);
buf = (char *) alloca (strlen (max_macro) + 1 + strlen (value)
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 9e2a00eb16e..7b016abad08 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -74,9 +74,7 @@ static void pop_alignment (tree);
static void
push_alignment (int alignment, tree id)
{
- align_stack * entry;
-
- entry = ggc_alloc_align_stack ();
+ align_stack * entry = ggc_alloc<align_stack> ();
entry->alignment = alignment;
entry->id = id;
@@ -911,7 +909,6 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
{
enum cpp_ttype token;
tree x = 0;
- opt_stack *p;
token = pragma_lex (&x);
if (token != CPP_EOF)
@@ -920,7 +917,7 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
return;
}
- p = ggc_alloc_opt_stack ();
+ opt_stack *p = ggc_alloc<opt_stack> ();
p->prev = options_stack;
options_stack = p;
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index 2e97d0147c5..9ac8cbaa2a9 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -906,6 +906,15 @@ pp_c_string_literal (c_pretty_printer *pp, tree s)
pp_doublequote (pp);
}
+/* Pretty-print a VOID_CST (void_node). */
+
+static void
+pp_c_void_constant (c_pretty_printer *pp)
+{
+ pp_c_type_cast (pp, void_type_node);
+ pp_string (pp, "0");
+}
+
/* Pretty-print an INTEGER literal. */
static void
@@ -1136,6 +1145,10 @@ c_pretty_printer::constant (tree e)
switch (code)
{
+ case VOID_CST:
+ pp_c_void_constant (this);
+ break;
+
case INTEGER_CST:
{
tree type = TREE_TYPE (e);
@@ -1241,6 +1254,7 @@ c_pretty_printer::primary_expression (tree e)
translate_string ("<return-value>");
break;
+ case VOID_CST:
case INTEGER_CST:
case REAL_CST:
case FIXED_CST:
@@ -2131,6 +2145,10 @@ c_pretty_printer::expression (tree e)
{
switch (TREE_CODE (e))
{
+ case VOID_CST:
+ pp_c_void_constant (this);
+ break;
+
case INTEGER_CST:
pp_c_integer_constant (this, e);
break;
diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c
index a0397925fe7..8d5b6856f87 100644
--- a/gcc/c-family/c-ubsan.c
+++ b/gcc/c-family/c-ubsan.c
@@ -95,7 +95,7 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
ubsan_encode_value (op1));
}
- t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);
+ t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
return t;
}
@@ -178,7 +178,7 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
ubsan_encode_value (op1));
}
- t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);
+ t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
return t;
}
@@ -207,7 +207,7 @@ ubsan_instrument_vla (location_t loc, tree size)
tt = builtin_decl_explicit (bcode);
tt = build_call_expr_loc (loc, tt, 2, data, ubsan_encode_value (size));
}
- t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);
+ t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
return t;
}
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 7aa9e23c10e..c586e659e0f 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -690,7 +690,7 @@ ObjC ObjC++ Var(warn_selector) Warning
Warn if a selector has multiple methods
Wshadow-ivar
-ObjC ObjC++ Var(warn_shadow_ivar) Init(1) Warning
+ObjC ObjC++ Var(warn_shadow_ivar) EnabledBy(Wshadow) Init(1) Warning
Warn if a local declaration hides an instance variable
Wsequence-point
diff --git a/gcc/c-family/cilk.c b/gcc/c-family/cilk.c
index a952902533a..8bdcdcfaad5 100644
--- a/gcc/c-family/cilk.c
+++ b/gcc/c-family/cilk.c
@@ -997,6 +997,7 @@ extract_free_variables (tree t, struct wrapper_data *wd,
{
case ERROR_MARK:
case IDENTIFIER_NODE:
+ case VOID_CST:
case INTEGER_CST:
case REAL_CST:
case FIXED_CST:
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 379b8d74946..536e07e38d9 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,127 @@
+2014-06-02 Andrew MacLeod <amacleod@redhat.com>
+
+ * c-decl.c: Include builtins.h.
+ * c-parser.c: Likewise.
+
+2014-05-27 Marek Polacek <polacek@redhat.com>
+
+ PR c/56724
+ * c-typeck.c (convert_arguments): Get location of a parameter. Change
+ error and warning calls to error_at and warning_at. Pass location of
+ a parameter to it. Call warning_at with OPT_Wtraditional_conversion.
+ (convert_for_assignment): Add parameter to WARN_FOR_ASSIGNMENT and
+ WARN_FOR_QUALIFIERS. Pass expr_loc to those.
+
+2014-05-26 Igor Zamyatin <igor.zamyatin@intel.com>
+
+ PR c/61191
+ * c-array-notation.c (fix_builtin_array_notation_fn): Check invalid
+ function parameters.
+
+2014-05-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * c-decl.c (merge_decls): Preserve symtab node pointers.
+ (duplicate_decls): Free new decl.
+
+2014-05-23 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-typeck.c (c_finish_omp_clauses): Remove duplicated variable
+ initialization.
+
+ * c-parser.c (c_parser_omp_target): Return bool values.
+
+2014-05-22 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_clause_thread_limit): Rename
+ num_teams_loc variable to num_thread_limit_loc.
+
+2014-05-21 Richard Sandiford <rsandifo@linux.vnet.ibm.com>
+
+ * c-array-notation.c (expand_array_notations): Use void_node
+ instead of void_zero_node.
+
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * c-decl.c (finish_struct): Adjust.
+ (finish_enum): Likewise.
+ (bind): Adjust.
+ (record_inline_static): Likewise.
+ (push_scope): Likewise.
+ (make_label): Likewise.
+ (lookup_label_for_goto): Likewise.
+ (finish_struct): Likewise.
+ (finish_enum): Likewise.
+ (store_parm_decls): Likewise.
+ (c_push_function_context): Likewise.
+ * c-lang.h: Remove usage of variable_size gty attribute.
+ * c-parser.c (c_parse_init): Adjust.
+ (c_parse_file): Likewise.
+
+2014-05-13 Marek Polacek <polacek@redhat.com>
+
+ PR c/61162
+ * c-typeck.c (convert_for_assignment): Pass location to
+ WARN_FOR_ASSIGNMENT instead of input_location.
+
+2014-05-10 Marek Polacek <polacek@redhat.com>
+
+ * c-parser.c (c_parser_declaration_or_fndef): Pass init_loc to
+ maybe_warn_string_init.
+ (c_parser_postfix_expression_after_paren_type): Pass type_loc to
+ maybe_warn_string_init.
+ * c-tree.h (maybe_warn_string_init): Update declaration.
+ * c-typeck.c (maybe_warn_string_init): Add location parameter.
+ Call pedwarn_init with loc instead of with input_location.
+ (digest_init): Pass init_loc to maybe_warn_string_init.
+ (pop_init_level): Call pedwarn_init with loc instead of with
+ input_location.
+ (set_init_index): Likewise.
+ (process_init_element): Likewise.
+
+2014-05-09 Marek Polacek <polacek@redhat.com>
+
+ PR c/61096
+ * c-parser.c (c_parser_braced_init): Pass brace_loc to push_init_level.
+ (c_parser_initelt): Pass location to set_init_label. Pass array index
+ location to set_init_index.
+ * c-tree.h (push_init_level): Update declaration.
+ (pop_init_level): Likewise.
+ (set_init_index): Likewise.
+ (set_init_label): Likewise.
+ * c-typeck.c (error_init): Add location parameter. Call error_at
+ instead of error.
+ (digest_init): Pass init_loc to error_init.
+ (really_start_incremental_init):
+ (push_init_level): Add location parameter. Pass loc to pop_init_level
+ and error_init.
+ (pop_init_level): Likewise.
+ (set_designator): Add location parameter. Pass loc to pop_init_level,
+ push_init_level, and error_init.
+ (set_init_index): Add location parameter. Pass loc to error_init and
+ set_designator.
+ (set_init_label): Likewise.
+ (output_init_element): Pass loc to error_init.
+ (process_init_element): Pass loc to error_init, pop_init_level,
+ pedwarn_init, and push_init_level.
+
+2014-05-09 Marek Polacek <polacek@redhat.com>
+
+ PR c/50459
+ * c-parser.c (c_parser_attributes): Parse the arguments as an
+ expression-list if the attribute takes identifier.
+
+2014-05-08 Marek Polacek <polacek@redhat.com>
+
+ PR c/61053
+ * c-decl.c (grokdeclarator): Use min_align_of_type instead of
+ TYPE_ALIGN_UNIT.
+
+2014-05-08 Marek Polacek <polacek@redhat.com>
+
+ PR c/61077
+ * c-decl.c (start_function): Warn for _Atomic-qualified return type
+ of main.
+
2014-05-06 Kenneth Zadeck <zadeck@naturalbridge.com>
Mike Stump <mikestump@comcast.net>
Richard Sandiford <rdsandiford@googlemail.com>
diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c
index 0ac6ba8e119..a0fe2fbbee8 100644
--- a/gcc/c/c-array-notation.c
+++ b/gcc/c/c-array-notation.c
@@ -229,6 +229,8 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
/* Fully fold any EXCESSIVE_PRECISION EXPR that can occur in the function
parameter. */
func_parm = c_fully_fold (func_parm, false, NULL);
+ if (func_parm == error_mark_node)
+ return error_mark_node;
location = EXPR_LOCATION (an_builtin_fn);
@@ -1279,7 +1281,7 @@ expand_array_notations (tree *tp, int *walk_subtrees, void *)
A[x:y:z];
A[x:y];
Replace those with just void zero node. */
- *tp = void_zero_node;
+ *tp = void_node;
default:
break;
}
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 3abf6b98574..dc8dbc2fb3c 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see
#include "plugin.h"
#include "c-family/c-ada-spec.h"
#include "cilk.h"
+#include "builtins.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@@ -638,7 +639,7 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible,
binding_freelist = b->prev;
}
else
- b = ggc_alloc_c_binding ();
+ b = ggc_alloc<c_binding> ();
b->shadowed = 0;
b->decl = decl;
@@ -755,7 +756,7 @@ void
record_inline_static (location_t loc, tree func, tree decl,
enum c_inline_static_type type)
{
- struct c_inline_static *csi = ggc_alloc_c_inline_static ();
+ c_inline_static *csi = ggc_alloc<c_inline_static> ();
csi->location = loc;
csi->function = func;
csi->static_decl = decl;
@@ -952,7 +953,7 @@ push_scope (void)
scope_freelist = scope->outer;
}
else
- scope = ggc_alloc_cleared_c_scope ();
+ scope = ggc_cleared_alloc<c_scope> ();
/* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes. */
if (current_scope)
@@ -2507,8 +2508,18 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
switch (TREE_CODE (olddecl))
{
case FUNCTION_DECL:
- case FIELD_DECL:
case VAR_DECL:
+ {
+ struct symtab_node *snode = olddecl->decl_with_vis.symtab_node;
+
+ memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
+ (char *) newdecl + sizeof (struct tree_decl_common),
+ tree_code_size (TREE_CODE (olddecl)) - sizeof (struct tree_decl_common));
+ olddecl->decl_with_vis.symtab_node = snode;
+ break;
+ }
+
+ case FIELD_DECL:
case PARM_DECL:
case LABEL_DECL:
case RESULT_DECL:
@@ -2561,6 +2572,9 @@ duplicate_decls (tree newdecl, tree olddecl)
}
merge_decls (newdecl, olddecl, newtype, oldtype);
+
+ /* The NEWDECL will no longer be needed. */
+ ggc_free (newdecl);
return true;
}
@@ -3084,12 +3098,10 @@ make_label (location_t location, tree name, bool defining,
struct c_label_vars **p_label_vars)
{
tree label = build_decl (location, LABEL_DECL, name, void_type_node);
- struct c_label_vars *label_vars;
-
DECL_CONTEXT (label) = current_function_decl;
DECL_MODE (label) = VOIDmode;
- label_vars = ggc_alloc_c_label_vars ();
+ c_label_vars *label_vars = ggc_alloc<c_label_vars> ();
label_vars->shadowed = NULL;
set_spot_bindings (&label_vars->label_bindings, defining);
label_vars->decls_in_scope = make_tree_vector ();
@@ -3185,9 +3197,8 @@ lookup_label_for_goto (location_t loc, tree name)
list for possible later warnings. */
if (label_vars->label_bindings.scope == NULL)
{
- struct c_goto_bindings *g;
+ c_goto_bindings *g = ggc_alloc<c_goto_bindings> ();
- g = ggc_alloc_c_goto_bindings ();
g->loc = loc;
set_spot_bindings (&g->goto_bindings, true);
vec_safe_push (label_vars->gotos, g);
@@ -5931,7 +5942,7 @@ grokdeclarator (const struct c_declarator *declarator,
else if (declspecs->align_log != -1)
{
alignas_align = 1U << declspecs->align_log;
- if (alignas_align < TYPE_ALIGN_UNIT (type))
+ if (alignas_align < min_align_of_type (type))
{
if (name)
error_at (loc, "%<_Alignas%> specifiers cannot reduce "
@@ -7423,8 +7434,8 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
ensure that this lives as long as the rest of the struct decl.
All decls in an inline function need to be saved. */
- space = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
- space2 = ggc_alloc_sorted_fields_type
+ space = ggc_cleared_alloc<struct lang_type> ();
+ space2 = (sorted_fields_type *) ggc_internal_alloc
(sizeof (struct sorted_fields_type) + len * sizeof (tree));
len = 0;
@@ -7705,7 +7716,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
/* Record the min/max values so that we can warn about bit-field
enumerations that are too small for the values. */
- lt = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+ lt = ggc_cleared_alloc<struct lang_type> ();
lt->enum_min = minnode;
lt->enum_max = maxnode;
TYPE_LANG_SPECIFIC (enumtype) = lt;
@@ -8045,6 +8056,9 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
!= integer_type_node)
pedwarn (loc, OPT_Wmain, "return type of %qD is not %<int%>", decl1);
+ else if (TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (decl1))))
+ pedwarn (loc, OPT_Wmain, "%<_Atomic%>-qualified return type of %qD",
+ decl1);
check_main_parameter_types (decl1);
@@ -8476,7 +8490,7 @@ store_parm_decls (void)
allocate_struct_function (fndecl, false);
if (warn_unused_local_typedefs)
- cfun->language = ggc_alloc_cleared_language_function ();
+ cfun->language = ggc_cleared_alloc<language_function> ();
/* Begin the statement tree for this function. */
DECL_SAVED_TREE (fndecl) = push_stmt_list ();
@@ -8800,7 +8814,7 @@ c_push_function_context (void)
/* cfun->language might have been already allocated by the use of
-Wunused-local-typedefs. In that case, just re-use it. */
if (p == NULL)
- cfun->language = p = ggc_alloc_cleared_language_function ();
+ cfun->language = p = ggc_cleared_alloc<language_function> ();
p->base.x_stmt_tree = c_stmt_tree;
c_stmt_tree.x_cur_stmt_list = vec_safe_copy (c_stmt_tree.x_cur_stmt_list);
diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
index 7fcf333b78f..e97490642e7 100644
--- a/gcc/c/c-lang.h
+++ b/gcc/c/c-lang.h
@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-common.h"
#include "ggc.h"
-struct GTY((variable_size)) lang_type {
+struct GTY(()) lang_type {
/* In a RECORD_TYPE, a sorted array of the fields of the type. */
struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields"))) s;
/* In an ENUMERAL_TYPE, the min and max values. */
@@ -35,7 +35,7 @@ struct GTY((variable_size)) lang_type {
tree objc_info;
};
-struct GTY((variable_size)) lang_decl {
+struct GTY(()) lang_decl {
char dummy;
};
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 6e8f33bdac1..1d9780edf4e 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "plugin.h"
#include "omp-low.h"
+#include "builtins.h"
/* Initialization routine for this file. */
@@ -90,7 +91,7 @@ c_parse_init (void)
if (!c_dialect_objc ())
mask |= D_OBJC | D_CXX_OBJC;
- ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
+ ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
for (i = 0; i < num_c_common_reswords; i++)
{
/* If a keyword is disabled, do not enter it into the table
@@ -1777,9 +1778,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
}
if (d != error_mark_node)
{
- maybe_warn_string_init (TREE_TYPE (d), init);
+ maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
finish_decl (d, init_loc, init.value,
- init.original_type, asm_name);
+ init.original_type, asm_name);
}
}
else
@@ -3955,11 +3956,16 @@ c_parser_attributes (c_parser *parser)
In objective-c the identifier may be a classname. */
if (c_parser_next_token_is (parser, CPP_NAME)
&& (c_parser_peek_token (parser)->id_kind == C_ID_ID
- || (c_dialect_objc ()
- && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
+ || (c_dialect_objc ()
+ && c_parser_peek_token (parser)->id_kind
+ == C_ID_CLASSNAME))
&& ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
|| (c_parser_peek_2nd_token (parser)->type
- == CPP_CLOSE_PAREN)))
+ == CPP_CLOSE_PAREN))
+ && (attribute_takes_identifier_p (attr_name)
+ || (c_dialect_objc ()
+ && c_parser_peek_token (parser)->id_kind
+ == C_ID_CLASSNAME)))
{
tree arg1 = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
@@ -4138,7 +4144,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
c_parser_consume_token (parser);
if (nested_p)
- push_init_level (0, &braced_init_obstack);
+ push_init_level (brace_loc, 0, &braced_init_obstack);
else
really_start_incremental_init (type);
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
@@ -4168,12 +4174,12 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
- pop_init_level (0, &braced_init_obstack);
+ pop_init_level (brace_loc, 0, &braced_init_obstack);
obstack_free (&braced_init_obstack, NULL);
return ret;
}
c_parser_consume_token (parser);
- ret = pop_init_level (0, &braced_init_obstack);
+ ret = pop_init_level (brace_loc, 0, &braced_init_obstack);
obstack_free (&braced_init_obstack, NULL);
return ret;
}
@@ -4190,7 +4196,8 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
&& c_parser_peek_2nd_token (parser)->type == CPP_COLON)
{
/* Old-style structure member designator. */
- set_init_label (c_parser_peek_token (parser)->value,
+ set_init_label (c_parser_peek_token (parser)->location,
+ c_parser_peek_token (parser)->value,
braced_init_obstack);
/* Use the colon as the error location. */
pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_Wpedantic,
@@ -4219,7 +4226,7 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_NAME))
{
- set_init_label (c_parser_peek_token (parser)->value,
+ set_init_label (des_loc, c_parser_peek_token (parser)->value,
braced_init_obstack);
c_parser_consume_token (parser);
}
@@ -4240,6 +4247,7 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
{
tree first, second;
location_t ellipsis_loc = UNKNOWN_LOCATION; /* Quiet warning. */
+ location_t array_index_loc = UNKNOWN_LOCATION;
/* ??? Following the old parser, [ objc-receiver
objc-message-args ] is accepted as an initializer,
being distinguished from a designator by what follows
@@ -4317,6 +4325,7 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
return;
}
c_parser_consume_token (parser);
+ array_index_loc = c_parser_peek_token (parser)->location;
first = c_parser_expr_no_commas (parser, NULL).value;
mark_exp_read (first);
array_desig_after_first:
@@ -4332,7 +4341,8 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
{
c_parser_consume_token (parser);
- set_init_index (first, second, braced_init_obstack);
+ set_init_index (array_index_loc, first, second,
+ braced_init_obstack);
if (second)
pedwarn (ellipsis_loc, OPT_Wpedantic,
"ISO C forbids specifying range of elements to initialize");
@@ -7590,7 +7600,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
}
init = c_parser_braced_init (parser, type, false);
finish_init ();
- maybe_warn_string_init (type, init);
+ maybe_warn_string_init (type_loc, type, init);
if (type != error_mark_node
&& !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
@@ -10444,7 +10454,7 @@ c_parser_omp_clause_num_teams (c_parser *parser, tree list)
static tree
c_parser_omp_clause_thread_limit (c_parser *parser, tree list)
{
- location_t num_teams_loc = c_parser_peek_token (parser)->location;
+ location_t num_thread_limit_loc = c_parser_peek_token (parser)->location;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
location_t expr_loc = c_parser_peek_token (parser)->location;
@@ -10474,7 +10484,7 @@ c_parser_omp_clause_thread_limit (c_parser *parser, tree list)
check_no_duplicate_clause (list, OMP_CLAUSE_THREAD_LIMIT,
"thread_limit");
- c = build_omp_clause (num_teams_loc, OMP_CLAUSE_THREAD_LIMIT);
+ c = build_omp_clause (num_thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
OMP_CLAUSE_CHAIN (c) = list;
list = c;
@@ -12711,15 +12721,19 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context)
c_parser_consume_token (parser);
strcpy (p_name, "#pragma omp target");
if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_teams (loc, parser, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses);
+ {
+ tree stmt = c_parser_omp_teams (loc, parser, p_name,
+ OMP_TARGET_CLAUSE_MASK,
+ cclauses);
+ return stmt != NULL_TREE;
+ }
keep_next_level ();
tree block = c_begin_compound_stmt (true);
tree ret = c_parser_omp_teams (loc, parser, p_name,
OMP_TARGET_CLAUSE_MASK, cclauses);
block = c_end_compound_stmt (loc, block, true);
- if (ret == NULL)
- return ret;
+ if (ret == NULL_TREE)
+ return false;
tree stmt = make_node (OMP_TARGET);
TREE_TYPE (stmt) = void_type_node;
OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
@@ -12730,7 +12744,7 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context)
else if (!flag_openmp) /* flag_openmp_simd */
{
c_parser_skip_to_pragma_eol (parser);
- return NULL_TREE;
+ return false;
}
else if (strcmp (p, "data") == 0)
{
@@ -14052,7 +14066,7 @@ c_parse_file (void)
if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
c_parser_pragma_pch_preprocess (&tparser);
- the_parser = ggc_alloc_c_parser ();
+ the_parser = ggc_alloc<c_parser> ();
*the_parser = tparser;
if (tparser.tokens == &tparser.tokens_buf[0])
the_parser->tokens = &the_parser->tokens_buf[0];
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index a6e73279125..e7dcb355e9c 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -602,14 +602,14 @@ extern tree build_compound_expr (location_t, tree, tree);
extern tree c_cast_expr (location_t, struct c_type_name *, tree);
extern tree build_c_cast (location_t, tree, tree);
extern void store_init_value (location_t, tree, tree, tree);
-extern void maybe_warn_string_init (tree, struct c_expr);
+extern void maybe_warn_string_init (location_t, tree, struct c_expr);
extern void start_init (tree, tree, int);
extern void finish_init (void);
extern void really_start_incremental_init (tree);
-extern void push_init_level (int, struct obstack *);
-extern struct c_expr pop_init_level (int, struct obstack *);
-extern void set_init_index (tree, tree, struct obstack *);
-extern void set_init_label (tree, struct obstack *);
+extern void push_init_level (location_t, int, struct obstack *);
+extern struct c_expr pop_init_level (location_t, int, struct obstack *);
+extern void set_init_index (location_t, tree, tree, struct obstack *);
+extern void set_init_label (location_t, tree, struct obstack *);
extern void process_init_element (location_t, struct c_expr, bool,
struct obstack *);
extern tree build_compound_literal (location_t, tree, tree, bool);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 7d2df6b1d12..6ca584bf38c 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -106,7 +106,7 @@ static tree digest_init (location_t, tree, tree, tree, bool, bool, int);
static void output_init_element (location_t, tree, tree, bool, tree, tree, int,
bool, struct obstack *);
static void output_pending_init_elements (int, struct obstack *);
-static int set_designator (int, struct obstack *);
+static int set_designator (location_t, int, struct obstack *);
static void push_range_stack (tree, struct obstack *);
static void add_pending_init (location_t, tree, tree, tree, bool,
struct obstack *);
@@ -3072,6 +3072,12 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
bool excess_precision = false;
bool npc;
tree parmval;
+ /* Some __atomic_* builtins have additional hidden argument at
+ position 0. */
+ location_t ploc
+ = !arg_loc.is_empty () && values->length () == arg_loc.length ()
+ ? expansion_point_location_if_in_system_header (arg_loc[parmnum])
+ : input_location;
if (type == void_type_node)
{
@@ -3114,7 +3120,8 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
{
- error ("type of formal parameter %d is incomplete", parmnum + 1);
+ error_at (ploc, "type of formal parameter %d is incomplete",
+ parmnum + 1);
parmval = val;
}
else
@@ -3129,34 +3136,40 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
if (INTEGRAL_TYPE_P (type)
&& TREE_CODE (valtype) == REAL_TYPE)
- warning (0, "passing argument %d of %qE as integer "
- "rather than floating due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE as integer rather "
+ "than floating due to prototype",
+ argnum, rname);
if (INTEGRAL_TYPE_P (type)
&& TREE_CODE (valtype) == COMPLEX_TYPE)
- warning (0, "passing argument %d of %qE as integer "
- "rather than complex due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE as integer rather "
+ "than complex due to prototype",
+ argnum, rname);
else if (TREE_CODE (type) == COMPLEX_TYPE
&& TREE_CODE (valtype) == REAL_TYPE)
- warning (0, "passing argument %d of %qE as complex "
- "rather than floating due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE as complex rather "
+ "than floating due to prototype",
+ argnum, rname);
else if (TREE_CODE (type) == REAL_TYPE
&& INTEGRAL_TYPE_P (valtype))
- warning (0, "passing argument %d of %qE as floating "
- "rather than integer due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE as floating rather "
+ "than integer due to prototype",
+ argnum, rname);
else if (TREE_CODE (type) == COMPLEX_TYPE
&& INTEGRAL_TYPE_P (valtype))
- warning (0, "passing argument %d of %qE as complex "
- "rather than integer due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE as complex rather "
+ "than integer due to prototype",
+ argnum, rname);
else if (TREE_CODE (type) == REAL_TYPE
&& TREE_CODE (valtype) == COMPLEX_TYPE)
- warning (0, "passing argument %d of %qE as floating "
- "rather than complex due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE as floating rather "
+ "than complex due to prototype",
+ argnum, rname);
/* ??? At some point, messages should be written about
conversions between complex types, but that's too messy
to do now. */
@@ -3167,9 +3180,10 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
since without a prototype it would be `double'. */
if (formal_prec == TYPE_PRECISION (float_type_node)
&& type != dfloat32_type_node)
- warning (0, "passing argument %d of %qE as %<float%> "
- "rather than %<double%> due to prototype",
- argnum, rname);
+ warning_at (ploc, 0,
+ "passing argument %d of %qE as %<float%> "
+ "rather than %<double%> due to prototype",
+ argnum, rname);
/* Warn if mismatch between argument and prototype
for decimal float types. Warn of conversions with
@@ -3192,9 +3206,10 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
|| (type == dfloat64_type_node
&& (valtype
!= dfloat32_type_node))))
- warning (0, "passing argument %d of %qE as %qT "
- "rather than %qT due to prototype",
- argnum, rname, type, valtype);
+ warning_at (ploc, 0,
+ "passing argument %d of %qE as %qT "
+ "rather than %qT due to prototype",
+ argnum, rname, type, valtype);
}
/* Detect integer changing in width or signedness.
@@ -3213,10 +3228,10 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
and the actual arg is that enum type. */
;
else if (formal_prec != TYPE_PRECISION (type1))
- warning (OPT_Wtraditional_conversion,
- "passing argument %d of %qE "
- "with different width due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE "
+ "with different width due to prototype",
+ argnum, rname);
else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
;
/* Don't complain if the formal parameter type
@@ -3237,14 +3252,15 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
&& TYPE_UNSIGNED (valtype))
;
else if (TYPE_UNSIGNED (type))
- warning (OPT_Wtraditional_conversion,
- "passing argument %d of %qE "
- "as unsigned due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE "
+ "as unsigned due to prototype",
+ argnum, rname);
else
- warning (OPT_Wtraditional_conversion,
- "passing argument %d of %qE "
- "as signed due to prototype", argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE "
+ "as signed due to prototype",
+ argnum, rname);
}
}
@@ -3253,13 +3269,7 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
if (excess_precision)
val = build1 (EXCESS_PRECISION_EXPR, valtype, val);
origtype = (!origtypes) ? NULL_TREE : (*origtypes)[parmnum];
- bool arg_loc_ok = !arg_loc.is_empty ()
- /* Some __atomic_* builtins have additional
- hidden argument at position 0. */
- && values->length () == arg_loc.length ();
- parmval = convert_for_assignment (loc,
- arg_loc_ok ? arg_loc[parmnum]
- : UNKNOWN_LOCATION, type,
+ parmval = convert_for_assignment (loc, ploc, type,
val, origtype, ic_argpass,
npc, fundecl, function,
parmnum + 1);
@@ -3283,10 +3293,10 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
{
/* Convert `float' to `double'. */
if (warn_double_promotion && !c_inhibit_evaluation_warnings)
- warning_at (arg_loc[parmnum], OPT_Wdouble_promotion,
- "implicit conversion from %qT to %qT when passing "
- "argument to function",
- valtype, double_type_node);
+ warning_at (ploc, OPT_Wdouble_promotion,
+ "implicit conversion from %qT to %qT when passing "
+ "argument to function",
+ valtype, double_type_node);
parmval = convert (double_type_node, val);
}
}
@@ -5545,15 +5555,15 @@ convert_to_anonymous_field (location_t location, tree type, tree rhs)
The component name is taken from the spelling stack. */
static void
-error_init (const char *gmsgid)
+error_init (location_t loc, const char *gmsgid)
{
char *ofwhat;
/* The gmsgid may be a format string with %< and %>. */
- error (gmsgid);
+ error_at (loc, gmsgid);
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
- error ("(near initialization for %qs)", ofwhat);
+ error_at (loc, "(near initialization for %qs)", ofwhat);
}
/* Issue a pedantic warning for a bad initializer component. OPT is
@@ -5596,13 +5606,13 @@ warning_init (location_t loc, int opt, const char *gmsgid)
object of type TYPE. */
void
-maybe_warn_string_init (tree type, struct c_expr expr)
+maybe_warn_string_init (location_t loc, tree type, struct c_expr expr)
{
if (pedantic
&& TREE_CODE (type) == ARRAY_TYPE
&& TREE_CODE (expr.value) == STRING_CST
&& expr.original_code != STRING_CST)
- pedwarn_init (input_location, OPT_Wpedantic,
+ pedwarn_init (loc, OPT_Wpedantic,
"array initialized from parenthesized string constant");
}
@@ -5657,14 +5667,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
/* This macro is used to emit diagnostics to ensure that all format
strings are complete sentences, visible to gettext and checked at
compile time. */
-#define WARN_FOR_ASSIGNMENT(LOCATION, OPT, AR, AS, IN, RE) \
+#define WARN_FOR_ASSIGNMENT(LOCATION, PLOC, OPT, AR, AS, IN, RE) \
do { \
switch (errtype) \
{ \
case ic_argpass: \
- if (pedwarn (LOCATION, OPT, AR, parmnum, rname)) \
+ if (pedwarn (PLOC, OPT, AR, parmnum, rname)) \
inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
- ? DECL_SOURCE_LOCATION (fundecl) : LOCATION, \
+ ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \
"expected %qT but argument is of type %qT", \
type, rhstype); \
break; \
@@ -5675,7 +5685,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
pedwarn_init (LOCATION, OPT, IN); \
break; \
case ic_return: \
- pedwarn (LOCATION, OPT, RE); \
+ pedwarn (LOCATION, OPT, RE); \
break; \
default: \
gcc_unreachable (); \
@@ -5687,25 +5697,25 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
compile time. It is the same as WARN_FOR_ASSIGNMENT but with an
extra parameter to enumerate qualifiers. */
-#define WARN_FOR_QUALIFIERS(LOCATION, OPT, AR, AS, IN, RE, QUALS) \
+#define WARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
do { \
switch (errtype) \
{ \
case ic_argpass: \
- if (pedwarn (LOCATION, OPT, AR, parmnum, rname, QUALS)) \
+ if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS)) \
inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
- ? DECL_SOURCE_LOCATION (fundecl) : LOCATION, \
+ ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \
"expected %qT but argument is of type %qT", \
type, rhstype); \
break; \
case ic_assign: \
- pedwarn (LOCATION, OPT, AS, QUALS); \
+ pedwarn (LOCATION, OPT, AS, QUALS); \
break; \
case ic_init: \
- pedwarn (LOCATION, OPT, IN, QUALS); \
+ pedwarn (LOCATION, OPT, IN, QUALS); \
break; \
case ic_return: \
- pedwarn (LOCATION, OPT, RE, QUALS); \
+ pedwarn (LOCATION, OPT, RE, QUALS); \
break; \
default: \
gcc_unreachable (); \
@@ -5754,7 +5764,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
&& TREE_CODE (type) == ENUMERAL_TYPE
&& TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type))
{
- WARN_FOR_ASSIGNMENT (input_location, OPT_Wc___compat,
+ WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wc___compat,
G_("enum conversion when passing argument "
"%d of %qE is invalid in C++"),
G_("enum conversion in assignment is "
@@ -5917,7 +5927,8 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
vice-versa. */
if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
- WARN_FOR_QUALIFIERS (location, OPT_Wdiscarded_qualifiers,
+ WARN_FOR_QUALIFIERS (location, expr_loc,
+ OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE "
"makes %q#v qualified function "
"pointer from unqualified"),
@@ -5933,7 +5944,8 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
}
else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
- WARN_FOR_QUALIFIERS (location, OPT_Wdiscarded_qualifiers,
+ WARN_FOR_QUALIFIERS (location, expr_loc,
+ OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE discards "
"%qv qualifier from pointer target type"),
G_("assignment discards %qv qualifier "
@@ -6095,7 +6107,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
(VOID_TYPE_P (ttr)
&& !null_pointer_constant
&& TREE_CODE (ttl) == FUNCTION_TYPE)))
- WARN_FOR_ASSIGNMENT (location, OPT_Wpedantic,
+ WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpedantic,
G_("ISO C forbids passing argument %d of "
"%qE between function pointer "
"and %<void *%>"),
@@ -6114,7 +6126,8 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
& ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
{
- WARN_FOR_QUALIFIERS (location, OPT_Wdiscarded_qualifiers,
+ WARN_FOR_QUALIFIERS (location, expr_loc,
+ OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE discards "
"%qv qualifier from pointer target type"),
G_("assignment discards %qv qualifier "
@@ -6132,7 +6145,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
;
/* If there is a mismatch, do warn. */
else if (warn_pointer_sign)
- WARN_FOR_ASSIGNMENT (location, OPT_Wpointer_sign,
+ WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpointer_sign,
G_("pointer targets in passing argument "
"%d of %qE differ in signedness"),
G_("pointer targets in assignment "
@@ -6151,7 +6164,8 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
where an ordinary one is wanted, but not vice-versa. */
if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
- WARN_FOR_QUALIFIERS (location, OPT_Wdiscarded_qualifiers,
+ WARN_FOR_QUALIFIERS (location, expr_loc,
+ OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE makes "
"%q#v qualified function pointer "
"from unqualified"),
@@ -6167,7 +6181,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
else
/* Avoid warning about the volatile ObjC EH puts on decls. */
if (!objc_ok)
- WARN_FOR_ASSIGNMENT (location, 0,
+ WARN_FOR_ASSIGNMENT (location, expr_loc, 0,
G_("passing argument %d of %qE from "
"incompatible pointer type"),
G_("assignment from incompatible pointer type"),
@@ -6190,7 +6204,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
or one that results from arithmetic, even including
a cast to integer type. */
if (!null_pointer_constant)
- WARN_FOR_ASSIGNMENT (location, 0,
+ WARN_FOR_ASSIGNMENT (location, expr_loc, 0,
G_("passing argument %d of %qE makes "
"pointer from integer without a cast"),
G_("assignment makes pointer from integer "
@@ -6204,7 +6218,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
}
else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
{
- WARN_FOR_ASSIGNMENT (location, 0,
+ WARN_FOR_ASSIGNMENT (location, expr_loc, 0,
G_("passing argument %d of %qE makes integer "
"from pointer without a cast"),
G_("assignment makes integer from pointer "
@@ -6541,7 +6555,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
expr.value = inside_init;
expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
expr.original_type = NULL;
- maybe_warn_string_init (type, expr);
+ maybe_warn_string_init (init_loc, type, expr);
if (TYPE_DOMAIN (type) && !TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
pedwarn_init (init_loc, OPT_Wpedantic,
@@ -6555,7 +6569,8 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
{
if (typ2 != char_type_node)
{
- error_init ("char-array initialized from wide string");
+ error_init (init_loc, "char-array initialized from wide "
+ "string");
return error_mark_node;
}
}
@@ -6563,14 +6578,14 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
{
if (typ2 == char_type_node)
{
- error_init ("wide character array initialized from non-wide "
- "string");
+ error_init (init_loc, "wide character array initialized "
+ "from non-wide string");
return error_mark_node;
}
else if (!comptypes(typ1, typ2))
{
- error_init ("wide character array initialized from "
- "incompatible wide string");
+ error_init (init_loc, "wide character array initialized "
+ "from incompatible wide string");
return error_mark_node;
}
}
@@ -6603,7 +6618,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
}
else if (INTEGRAL_TYPE_P (typ1))
{
- error_init ("array of inappropriate type initialized "
+ error_init (init_loc, "array of inappropriate type initialized "
"from string constant");
return error_mark_node;
}
@@ -6671,7 +6686,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
(init_loc, inside_init);
else
{
- error_init ("invalid use of non-lvalue array");
+ error_init (init_loc, "invalid use of non-lvalue array");
return error_mark_node;
}
}
@@ -6697,7 +6712,8 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
&& TREE_CODE (inside_init) != CONSTRUCTOR)
{
- error_init ("array initialized from non-constant array expression");
+ error_init (init_loc, "array initialized from non-constant array "
+ "expression");
return error_mark_node;
}
@@ -6711,7 +6727,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
= valid_compound_expr_initializer (inside_init,
TREE_TYPE (inside_init));
if (inside_init == error_mark_node)
- error_init ("initializer element is not constant");
+ error_init (init_loc, "initializer element is not constant");
else
pedwarn_init (init_loc, OPT_Wpedantic,
"initializer element is not constant");
@@ -6722,7 +6738,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
&& !initializer_constant_valid_p (inside_init,
TREE_TYPE (inside_init)))
{
- error_init ("initializer element is not constant");
+ error_init (init_loc, "initializer element is not constant");
inside_init = error_mark_node;
}
else if (require_constant && !maybe_const)
@@ -6762,14 +6778,15 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
;
else if (require_constant && !TREE_CONSTANT (inside_init))
{
- error_init ("initializer element is not constant");
+ error_init (init_loc, "initializer element is not constant");
inside_init = error_mark_node;
}
else if (require_constant
&& !initializer_constant_valid_p (inside_init,
TREE_TYPE (inside_init)))
{
- error_init ("initializer element is not computable at load time");
+ error_init (init_loc, "initializer element is not computable at "
+ "load time");
inside_init = error_mark_node;
}
else if (require_constant && !maybe_const)
@@ -6783,11 +6800,11 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
{
- error_init ("variable-sized object may not be initialized");
+ error_init (init_loc, "variable-sized object may not be initialized");
return error_mark_node;
}
- error_init ("invalid initializer");
+ error_init (init_loc, "invalid initializer");
return error_mark_node;
}
@@ -7165,7 +7182,8 @@ really_start_incremental_init (tree type)
IMPLICIT is 1 (or 2 if the push is because of designator list). */
void
-push_init_level (int implicit, struct obstack * braced_init_obstack)
+push_init_level (location_t loc, int implicit,
+ struct obstack *braced_init_obstack)
{
struct constructor_stack *p;
tree value = NULL_TREE;
@@ -7184,14 +7202,14 @@ push_init_level (int implicit, struct obstack * braced_init_obstack)
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
process_init_element (input_location,
- pop_init_level (1, braced_init_obstack),
+ pop_init_level (loc, 1, braced_init_obstack),
true, braced_init_obstack);
else if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& constructor_max_index
&& tree_int_cst_lt (constructor_max_index,
constructor_index))
process_init_element (input_location,
- pop_init_level (1, braced_init_obstack),
+ pop_init_level (loc, 1, braced_init_obstack),
true, braced_init_obstack);
else
break;
@@ -7281,7 +7299,7 @@ push_init_level (int implicit, struct obstack * braced_init_obstack)
if (constructor_type == 0)
{
- error_init ("extra brace group at end of initializer");
+ error_init (loc, "extra brace group at end of initializer");
constructor_fields = 0;
constructor_unfilled_fields = 0;
return;
@@ -7382,7 +7400,8 @@ push_init_level (int implicit, struct obstack * braced_init_obstack)
Otherwise, return a CONSTRUCTOR expression as the value. */
struct c_expr
-pop_init_level (int implicit, struct obstack * braced_init_obstack)
+pop_init_level (location_t loc, int implicit,
+ struct obstack *braced_init_obstack)
{
struct constructor_stack *p;
struct c_expr ret;
@@ -7396,7 +7415,7 @@ pop_init_level (int implicit, struct obstack * braced_init_obstack)
pop any inner levels that didn't have explicit braces. */
while (constructor_stack->implicit)
process_init_element (input_location,
- pop_init_level (1, braced_init_obstack),
+ pop_init_level (loc, 1, braced_init_obstack),
true, braced_init_obstack);
gcc_assert (!constructor_range_stack);
}
@@ -7423,9 +7442,9 @@ pop_init_level (int implicit, struct obstack * braced_init_obstack)
gcc_assert (!TYPE_SIZE (constructor_type));
if (constructor_depth > 2)
- error_init ("initialization of flexible array member in a nested context");
+ error_init (loc, "initialization of flexible array member in a nested context");
else
- pedwarn_init (input_location, OPT_Wpedantic,
+ pedwarn_init (loc, OPT_Wpedantic,
"initialization of a flexible array member");
/* We have already issued an error message for the existence
@@ -7485,12 +7504,12 @@ pop_init_level (int implicit, struct obstack * braced_init_obstack)
if (vec_safe_is_empty (constructor_elements))
{
if (!constructor_erroneous)
- error_init ("empty scalar initializer");
+ error_init (loc, "empty scalar initializer");
ret.value = error_mark_node;
}
else if (vec_safe_length (constructor_elements) != 1)
{
- error_init ("extra elements in scalar initializer");
+ error_init (loc, "extra elements in scalar initializer");
ret.value = (*constructor_elements)[0].value;
}
else
@@ -7553,7 +7572,8 @@ pop_init_level (int implicit, struct obstack * braced_init_obstack)
ARRAY argument is nonzero for array ranges. Returns zero for success. */
static int
-set_designator (int array, struct obstack * braced_init_obstack)
+set_designator (location_t loc, int array,
+ struct obstack *braced_init_obstack)
{
tree subtype;
enum tree_code subcode;
@@ -7576,7 +7596,7 @@ set_designator (int array, struct obstack * braced_init_obstack)
braces. */
while (constructor_stack->implicit)
process_init_element (input_location,
- pop_init_level (1, braced_init_obstack),
+ pop_init_level (loc, 1, braced_init_obstack),
true, braced_init_obstack);
constructor_designated = 1;
return 0;
@@ -7600,17 +7620,17 @@ set_designator (int array, struct obstack * braced_init_obstack)
subcode = TREE_CODE (subtype);
if (array && subcode != ARRAY_TYPE)
{
- error_init ("array index in non-array initializer");
+ error_init (loc, "array index in non-array initializer");
return 1;
}
else if (!array && subcode != RECORD_TYPE && subcode != UNION_TYPE)
{
- error_init ("field name not in record or union initializer");
+ error_init (loc, "field name not in record or union initializer");
return 1;
}
constructor_designated = 1;
- push_init_level (2, braced_init_obstack);
+ push_init_level (loc, 2, braced_init_obstack);
return 0;
}
@@ -7643,10 +7663,10 @@ push_range_stack (tree range_end, struct obstack * braced_init_obstack)
of indices, running from FIRST through LAST. */
void
-set_init_index (tree first, tree last,
- struct obstack * braced_init_obstack)
+set_init_index (location_t loc, tree first, tree last,
+ struct obstack *braced_init_obstack)
{
- if (set_designator (1, braced_init_obstack))
+ if (set_designator (loc, 1, braced_init_obstack))
return;
designator_erroneous = 1;
@@ -7654,7 +7674,7 @@ set_init_index (tree first, tree last,
if (!INTEGRAL_TYPE_P (TREE_TYPE (first))
|| (last && !INTEGRAL_TYPE_P (TREE_TYPE (last))))
{
- error_init ("array index in initializer not of integer type");
+ error_init (loc, "array index in initializer not of integer type");
return;
}
@@ -7662,7 +7682,7 @@ set_init_index (tree first, tree last,
{
first = c_fully_fold (first, false, NULL);
if (TREE_CODE (first) == INTEGER_CST)
- pedwarn_init (input_location, OPT_Wpedantic,
+ pedwarn_init (loc, OPT_Wpedantic,
"array index in initializer is not "
"an integer constant expression");
}
@@ -7671,22 +7691,22 @@ set_init_index (tree first, tree last,
{
last = c_fully_fold (last, false, NULL);
if (TREE_CODE (last) == INTEGER_CST)
- pedwarn_init (input_location, OPT_Wpedantic,
+ pedwarn_init (loc, OPT_Wpedantic,
"array index in initializer is not "
"an integer constant expression");
}
if (TREE_CODE (first) != INTEGER_CST)
- error_init ("nonconstant array index in initializer");
+ error_init (loc, "nonconstant array index in initializer");
else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
- error_init ("nonconstant array index in initializer");
+ error_init (loc, "nonconstant array index in initializer");
else if (TREE_CODE (constructor_type) != ARRAY_TYPE)
- error_init ("array index in non-array initializer");
+ error_init (loc, "array index in non-array initializer");
else if (tree_int_cst_sgn (first) == -1)
- error_init ("array index in initializer exceeds array bounds");
+ error_init (loc, "array index in initializer exceeds array bounds");
else if (constructor_max_index
&& tree_int_cst_lt (constructor_max_index, first))
- error_init ("array index in initializer exceeds array bounds");
+ error_init (loc, "array index in initializer exceeds array bounds");
else
{
constant_expression_warning (first);
@@ -7705,7 +7725,7 @@ set_init_index (tree first, tree last,
last = 0;
else if (tree_int_cst_lt (last, first))
{
- error_init ("empty index range in initializer");
+ error_init (loc, "empty index range in initializer");
last = 0;
}
else
@@ -7714,7 +7734,8 @@ set_init_index (tree first, tree last,
if (constructor_max_index != 0
&& tree_int_cst_lt (constructor_max_index, last))
{
- error_init ("array index range in initializer exceeds array bounds");
+ error_init (loc, "array index range in initializer exceeds "
+ "array bounds");
last = 0;
}
}
@@ -7730,11 +7751,12 @@ set_init_index (tree first, tree last,
/* Within a struct initializer, specify the next field to be initialized. */
void
-set_init_label (tree fieldname, struct obstack * braced_init_obstack)
+set_init_label (location_t loc, tree fieldname,
+ struct obstack *braced_init_obstack)
{
tree field;
- if (set_designator (0, braced_init_obstack))
+ if (set_designator (loc, 0, braced_init_obstack))
return;
designator_erroneous = 1;
@@ -7742,7 +7764,7 @@ set_init_label (tree fieldname, struct obstack * braced_init_obstack)
if (TREE_CODE (constructor_type) != RECORD_TYPE
&& TREE_CODE (constructor_type) != UNION_TYPE)
{
- error_init ("field name not in record or union initializer");
+ error_init (loc, "field name not in record or union initializer");
return;
}
@@ -7761,7 +7783,7 @@ set_init_label (tree fieldname, struct obstack * braced_init_obstack)
field = TREE_CHAIN (field);
if (field)
{
- if (set_designator (0, braced_init_obstack))
+ if (set_designator (loc, 0, braced_init_obstack))
return;
}
}
@@ -8261,7 +8283,7 @@ output_init_element (location_t loc, tree value, tree origtype,
{
if (require_constant_value)
{
- error_init ("initializer element is not constant");
+ error_init (loc, "initializer element is not constant");
value = error_mark_node;
}
else if (require_constant_elements)
@@ -8582,14 +8604,14 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
&& integer_zerop (constructor_unfilled_index))
{
if (constructor_stack->replacement_value.value)
- error_init ("excess elements in char array initializer");
+ error_init (loc, "excess elements in char array initializer");
constructor_stack->replacement_value = value;
return;
}
if (constructor_stack->replacement_value.value != 0)
{
- error_init ("excess elements in struct initializer");
+ error_init (loc, "excess elements in struct initializer");
return;
}
@@ -8605,14 +8627,16 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
- process_init_element (loc, pop_init_level (1, braced_init_obstack),
+ process_init_element (loc,
+ pop_init_level (loc, 1, braced_init_obstack),
true, braced_init_obstack);
else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
|| TREE_CODE (constructor_type) == VECTOR_TYPE)
&& constructor_max_index
&& tree_int_cst_lt (constructor_max_index,
constructor_index))
- process_init_element (loc, pop_init_level (1, braced_init_obstack),
+ process_init_element (loc,
+ pop_init_level (loc, 1, braced_init_obstack),
true, braced_init_obstack);
else
break;
@@ -8649,8 +8673,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
if (constructor_fields == 0)
{
- pedwarn_init (input_location, 0,
- "excess elements in struct initializer");
+ pedwarn_init (loc, 0, "excess elements in struct initializer");
break;
}
@@ -8665,7 +8688,8 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
&& TYPE_SIZE (fieldtype) == NULL_TREE
&& DECL_CHAIN (constructor_fields) == NULL_TREE)
{
- error_init ("non-static initialization of a flexible array member");
+ error_init (loc, "non-static initialization of a flexible "
+ "array member");
break;
}
@@ -8683,7 +8707,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
&& (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
|| fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
{
- push_init_level (1, braced_init_obstack);
+ push_init_level (loc, 1, braced_init_obstack);
continue;
}
@@ -8735,7 +8759,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
if (constructor_fields == 0)
{
- pedwarn_init (input_location, 0,
+ pedwarn_init (loc, 0,
"excess elements in union initializer");
break;
}
@@ -8775,7 +8799,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
&& (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
|| fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
{
- push_init_level (1, braced_init_obstack);
+ push_init_level (loc, 1, braced_init_obstack);
continue;
}
@@ -8817,7 +8841,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
&& (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
|| eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
{
- push_init_level (1, braced_init_obstack);
+ push_init_level (loc, 1, braced_init_obstack);
continue;
}
@@ -8825,7 +8849,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
&& (tree_int_cst_lt (constructor_max_index, constructor_index)
|| integer_all_onesp (constructor_max_index)))
{
- pedwarn_init (input_location, 0,
+ pedwarn_init (loc, 0,
"excess elements in array initializer");
break;
}
@@ -8859,7 +8883,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
always have a fixed size derived from their type. */
if (tree_int_cst_lt (constructor_max_index, constructor_index))
{
- pedwarn_init (input_location, 0,
+ pedwarn_init (loc, 0,
"excess elements in vector initializer");
break;
}
@@ -8891,7 +8915,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
else if (constructor_type != error_mark_node
&& constructor_fields == 0)
{
- pedwarn_init (input_location, 0,
+ pedwarn_init (loc, 0,
"excess elements in scalar initializer");
break;
}
@@ -8918,7 +8942,8 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
{
gcc_assert (constructor_stack->implicit);
process_init_element (loc,
- pop_init_level (1, braced_init_obstack),
+ pop_init_level (loc, 1,
+ braced_init_obstack),
true, braced_init_obstack);
}
for (p = range_stack;
@@ -8927,7 +8952,8 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
{
gcc_assert (constructor_stack->implicit);
process_init_element (loc,
- pop_init_level (1, braced_init_obstack),
+ pop_init_level (loc, 1,
+ braced_init_obstack),
true, braced_init_obstack);
}
@@ -8948,7 +8974,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
p = p->next;
if (!p)
break;
- push_init_level (2, braced_init_obstack);
+ push_init_level (loc, 2, braced_init_obstack);
p->stack = constructor_stack;
if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
p->index = p->range_start;
@@ -9401,7 +9427,7 @@ do_case (location_t loc, tree low_value, tree high_value)
{
low_value = c_fully_fold (low_value, false, NULL);
if (TREE_CODE (low_value) == INTEGER_CST)
- pedwarn (input_location, OPT_Wpedantic,
+ pedwarn (loc, OPT_Wpedantic,
"case label is not an integer constant expression");
}
@@ -11750,7 +11776,7 @@ c_finish_omp_clauses (tree clauses)
{
bitmap_head generic_head, firstprivate_head, lastprivate_head;
bitmap_head aligned_head;
- tree c, t, *pc = &clauses;
+ tree c, t, *pc;
bool branch_seen = false;
bool copyprivate_seen = false;
tree *nowait_clause = NULL;
diff --git a/gcc/caller-save.c b/gcc/caller-save.c
index 59917a856d2..64fd66c0759 100644
--- a/gcc/caller-save.c
+++ b/gcc/caller-save.c
@@ -265,8 +265,8 @@ init_caller_save (void)
savepat = gen_rtx_SET (VOIDmode, test_mem, test_reg);
restpat = gen_rtx_SET (VOIDmode, test_reg, test_mem);
- saveinsn = gen_rtx_INSN (VOIDmode, 0, 0, 0, 0, savepat, 0, -1, 0);
- restinsn = gen_rtx_INSN (VOIDmode, 0, 0, 0, 0, restpat, 0, -1, 0);
+ saveinsn = gen_rtx_INSN (VOIDmode, 0, 0, 0, savepat, 0, -1, 0);
+ restinsn = gen_rtx_INSN (VOIDmode, 0, 0, 0, restpat, 0, -1, 0);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
for (j = 1; j <= MOVE_MAX_WORDS; j++)
@@ -441,7 +441,7 @@ setup_save_areas (void)
freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn));
REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
&chain->live_throughout);
- COPY_HARD_REG_SET (used_regs, call_used_reg_set);
+ get_call_reg_set_usage (insn, &used_regs, call_used_reg_set);
/* Record all registers set in this call insn. These don't
need to be saved. N.B. the call insn might set a subreg
@@ -525,7 +525,7 @@ setup_save_areas (void)
REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
&chain->live_throughout);
- COPY_HARD_REG_SET (used_regs, call_used_reg_set);
+ get_call_reg_set_usage (insn, &used_regs, call_used_reg_set);
/* Record all registers set in this call insn. These don't
need to be saved. N.B. the call insn might set a subreg
@@ -804,6 +804,7 @@ save_call_clobbered_regs (void)
{
unsigned regno;
HARD_REG_SET hard_regs_to_save;
+ HARD_REG_SET call_def_reg_set;
reg_set_iterator rsi;
rtx cheap;
@@ -854,7 +855,9 @@ save_call_clobbered_regs (void)
AND_COMPL_HARD_REG_SET (hard_regs_to_save, call_fixed_reg_set);
AND_COMPL_HARD_REG_SET (hard_regs_to_save, this_insn_sets);
AND_COMPL_HARD_REG_SET (hard_regs_to_save, hard_regs_saved);
- AND_HARD_REG_SET (hard_regs_to_save, call_used_reg_set);
+ get_call_reg_set_usage (insn, &call_def_reg_set,
+ call_used_reg_set);
+ AND_HARD_REG_SET (hard_regs_to_save, call_def_reg_set);
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
diff --git a/gcc/cfg.c b/gcc/cfg.c
index 3b6349aec49..f5af1084d34 100644
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -68,13 +68,13 @@ void
init_flow (struct function *the_fun)
{
if (!the_fun->cfg)
- the_fun->cfg = ggc_alloc_cleared_control_flow_graph ();
+ the_fun->cfg = ggc_cleared_alloc<control_flow_graph> ();
n_edges_for_fn (the_fun) = 0;
ENTRY_BLOCK_PTR_FOR_FN (the_fun)
- = ggc_alloc_cleared_basic_block_def ();
+ = ggc_cleared_alloc<basic_block_def> ();
ENTRY_BLOCK_PTR_FOR_FN (the_fun)->index = ENTRY_BLOCK;
EXIT_BLOCK_PTR_FOR_FN (the_fun)
- = ggc_alloc_cleared_basic_block_def ();
+ = ggc_cleared_alloc<basic_block_def> ();
EXIT_BLOCK_PTR_FOR_FN (the_fun)->index = EXIT_BLOCK;
ENTRY_BLOCK_PTR_FOR_FN (the_fun)->next_bb
= EXIT_BLOCK_PTR_FOR_FN (the_fun);
@@ -123,7 +123,7 @@ basic_block
alloc_block (void)
{
basic_block bb;
- bb = ggc_alloc_cleared_basic_block_def ();
+ bb = ggc_cleared_alloc<basic_block_def> ();
return bb;
}
@@ -261,7 +261,7 @@ edge
unchecked_make_edge (basic_block src, basic_block dst, int flags)
{
edge e;
- e = ggc_alloc_cleared_edge_def ();
+ e = ggc_cleared_alloc<edge_def> ();
n_edges_for_fn (cfun)++;
e->src = src;
@@ -486,7 +486,7 @@ dump_edge_info (FILE *file, edge e, int flags, int do_succ)
if (e->count && do_details)
{
fputs (" count:", file);
- fprintf (file, HOST_WIDEST_INT_PRINT_DEC, e->count);
+ fprintf (file, "%"PRId64, e->count);
}
if (e->flags && do_details)
@@ -734,8 +734,8 @@ dump_bb_info (FILE *outf, basic_block bb, int indent, int flags,
if (flags & TDF_DETAILS)
{
struct function *fun = DECL_STRUCT_FUNCTION (current_function_decl);
- fprintf (outf, ", count " HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) bb->count);
+ fprintf (outf, ", count " "%"PRId64,
+ (int64_t) bb->count);
fprintf (outf, ", freq %i", bb->frequency);
if (maybe_hot_bb_p (fun, bb))
fputs (", maybe hot", outf);
@@ -961,7 +961,7 @@ scale_bbs_frequencies_int (basic_block *bbs, int nbbs, int num, int den)
/* numbers smaller than this value are safe to multiply without getting
64bit overflow. */
-#define MAX_SAFE_MULTIPLIER (1 << (sizeof (HOST_WIDEST_INT) * 4 - 1))
+#define MAX_SAFE_MULTIPLIER (1 << (sizeof (int64_t) * 4 - 1))
/* Multiply all frequencies of basic blocks in array BBS of length NBBS
by NUM/DEN, in gcov_type arithmetic. More accurate than previous
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index caa4c5f0a27..7c24a6d7dde 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -419,13 +419,14 @@ try_forward_edges (int mode, basic_block b)
partition boundaries). See the comments at the top of
bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
- if (find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX))
+ if (JUMP_P (BB_END (b)) && CROSSING_JUMP_P (BB_END (b)))
return false;
for (ei = ei_start (b->succs); (e = ei_safe_edge (ei)); )
{
basic_block target, first;
- int counter, goto_locus;
+ location_t goto_locus;
+ int counter;
bool threaded = false;
int nthreaded_edges = 0;
bool may_thread = first_pass || (b->flags & BB_MODIFIED) != 0;
@@ -456,7 +457,8 @@ try_forward_edges (int mode, basic_block b)
details. */
if (first != EXIT_BLOCK_PTR_FOR_FN (cfun)
- && find_reg_note (BB_END (first), REG_CROSSING_JUMP, NULL_RTX))
+ && JUMP_P (BB_END (first))
+ && CROSSING_JUMP_P (BB_END (first)))
return changed;
while (counter < n_basic_blocks_for_fn (cfun))
@@ -477,8 +479,8 @@ try_forward_edges (int mode, basic_block b)
{
/* When not optimizing, ensure that edges or forwarder
blocks with different locus are not optimized out. */
- int new_locus = single_succ_edge (target)->goto_locus;
- int locus = goto_locus;
+ location_t new_locus = single_succ_edge (target)->goto_locus;
+ location_t locus = goto_locus;
if (new_locus != UNKNOWN_LOCATION
&& locus != UNKNOWN_LOCATION
@@ -2796,7 +2798,7 @@ try_optimize_cfg (int mode)
if (single_succ_p (b)
&& single_succ (b) != EXIT_BLOCK_PTR_FOR_FN (cfun)
&& onlyjump_p (BB_END (b))
- && !find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)
+ && !CROSSING_JUMP_P (BB_END (b))
&& try_redirect_by_replacing_jump (single_succ_edge (b),
single_succ (b),
(mode & CLEANUP_CFGLAYOUT) != 0))
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index b57fac17eae..8b0e466a52f 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -73,6 +73,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-address.h"
#include "recog.h"
#include "output.h"
+#include "builtins.h"
/* Some systems use __main in a way incompatible with its use in gcc, in these
cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
@@ -1611,6 +1612,52 @@ record_or_union_type_has_array_p (const_tree tree_type)
return 0;
}
+/* Check if the current function has local referenced variables that
+ have their addresses taken, contain an array, or are arrays. */
+
+static bool
+stack_protect_decl_p ()
+{
+ unsigned i;
+ tree var;
+
+ FOR_EACH_LOCAL_DECL (cfun, i, var)
+ if (!is_global_var (var))
+ {
+ tree var_type = TREE_TYPE (var);
+ if (TREE_CODE (var) == VAR_DECL
+ && (TREE_CODE (var_type) == ARRAY_TYPE
+ || TREE_ADDRESSABLE (var)
+ || (RECORD_OR_UNION_TYPE_P (var_type)
+ && record_or_union_type_has_array_p (var_type))))
+ return true;
+ }
+ return false;
+}
+
+/* Check if the current function has calls that use a return slot. */
+
+static bool
+stack_protect_return_slot_p ()
+{
+ basic_block bb;
+
+ FOR_ALL_BB_FN (bb, cfun)
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ /* This assumes that calls to internal-only functions never
+ use a return slot. */
+ if (is_gimple_call (stmt)
+ && !gimple_call_internal_p (stmt)
+ && aggregate_value_p (TREE_TYPE (gimple_call_fntype (stmt)),
+ gimple_call_fndecl (stmt)))
+ return true;
+ }
+ return false;
+}
+
/* Expand all variables used in the function. */
static rtx
@@ -1683,22 +1730,8 @@ expand_used_vars (void)
pointer_map_destroy (ssa_name_decls);
if (flag_stack_protect == SPCT_FLAG_STRONG)
- FOR_EACH_LOCAL_DECL (cfun, i, var)
- if (!is_global_var (var))
- {
- tree var_type = TREE_TYPE (var);
- /* Examine local referenced variables that have their addresses taken,
- contain an array, or are arrays. */
- if (TREE_CODE (var) == VAR_DECL
- && (TREE_CODE (var_type) == ARRAY_TYPE
- || TREE_ADDRESSABLE (var)
- || (RECORD_OR_UNION_TYPE_P (var_type)
- && record_or_union_type_has_array_p (var_type))))
- {
- gen_stack_protect_signal = true;
- break;
- }
- }
+ gen_stack_protect_signal
+ = stack_protect_decl_p () || stack_protect_return_slot_p ();
/* At this point all variables on the local_decls with TREE_USED
set are not associated with any block scope. Lay them out. */
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
index bc1634aac87..90bc6cf1e9f 100644
--- a/gcc/cfghooks.c
+++ b/gcc/cfghooks.c
@@ -310,7 +310,7 @@ dump_bb_for_graph (pretty_printer *pp, basic_block bb)
internal_error ("%s does not support dump_bb_for_graph",
cfg_hooks->name);
if (bb->count)
- pp_printf (pp, "COUNT:" HOST_WIDEST_INT_PRINT_DEC, bb->count);
+ pp_printf (pp, "COUNT:" "%"PRId64, bb->count);
pp_printf (pp, " FREQ:%i |", bb->frequency);
pp_write_text_to_stream (pp);
if (!(dump_flags & TDF_SLIM))
@@ -833,6 +833,9 @@ make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge),
fallthru = split_block_after_labels (bb);
dummy = fallthru->src;
+ dummy->count = 0;
+ dummy->frequency = 0;
+ fallthru->count = 0;
bb = fallthru->dest;
/* Redirect back edges we want to keep. */
@@ -842,20 +845,13 @@ make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge),
if (redirect_edge_p (e))
{
+ dummy->frequency += EDGE_FREQUENCY (e);
+ dummy->count += e->count;
+ fallthru->count += e->count;
ei_next (&ei);
continue;
}
- dummy->frequency -= EDGE_FREQUENCY (e);
- dummy->count -= e->count;
- if (dummy->frequency < 0)
- dummy->frequency = 0;
- if (dummy->count < 0)
- dummy->count = 0;
- fallthru->count -= e->count;
- if (fallthru->count < 0)
- fallthru->count = 0;
-
e_src = e->src;
jump = redirect_edge_and_branch_force (e, bb);
if (jump != NULL)
@@ -969,7 +965,7 @@ tidy_fallthru_edges (void)
s = single_succ_edge (b);
if (! (s->flags & EDGE_COMPLEX)
&& s->dest == c
- && !find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX))
+ && !(JUMP_P (BB_END (b)) && CROSSING_JUMP_P (BB_END (b))))
tidy_fallthru_edge (s);
}
}
diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
index 91e8800560b..73f79ef368c 100644
--- a/gcc/cfgloop.c
+++ b/gcc/cfgloop.c
@@ -331,9 +331,9 @@ flow_loop_tree_node_remove (struct loop *loop)
struct loop *
alloc_loop (void)
{
- struct loop *loop = ggc_alloc_cleared_loop ();
+ struct loop *loop = ggc_cleared_alloc<struct loop> ();
- loop->exits = ggc_alloc_cleared_loop_exit ();
+ loop->exits = ggc_cleared_alloc<loop_exit> ();
loop->exits->next = loop->exits->prev = loop->exits;
loop->can_be_parallel = false;
loop->nb_iterations_upper_bound = 0;
@@ -415,7 +415,7 @@ flow_loops_find (struct loops *loops)
if (!loops)
{
- loops = ggc_alloc_cleared_loops ();
+ loops = ggc_cleared_alloc<struct loops> ();
init_loops_structure (cfun, loops, 1);
}
@@ -1029,7 +1029,7 @@ rescan_loop_exit (edge e, bool new_edge, bool removed)
aloop != cloop;
aloop = loop_outer (aloop))
{
- exit = ggc_alloc_loop_exit ();
+ exit = ggc_alloc<loop_exit> ();
exit->e = e;
exit->next = aloop->exits->next;
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index 62a656ae57f..7d2c1de219d 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -400,7 +400,7 @@ struct GTY(()) niter_desc
bool const_iter;
/* Number of iterations if constant. */
- unsigned HOST_WIDEST_INT niter;
+ uint64_t niter;
/* Assumptions under that the rest of the information is valid. */
rtx assumptions;
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 5dd27d2795b..49faf2e0e63 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -889,7 +889,7 @@ rtl_merge_blocks (basic_block a, basic_block b)
BB_HEAD (b) = b_empty ? NULL_RTX : b_head;
delete_insn_chain (del_first, del_last, true);
- /* When not optimizing CFG and the edge is the only place in RTL which holds
+ /* When not optimizing and the edge is the only place in RTL which holds
some unique locus, emit a nop with that locus in between. */
if (!optimize)
{
@@ -1325,8 +1325,6 @@ redirect_branch_edge (edge e, basic_block target)
static void
fixup_partition_crossing (edge e)
{
- rtx note;
-
if (e->src == ENTRY_BLOCK_PTR_FOR_FN (cfun) || e->dest
== EXIT_BLOCK_PTR_FOR_FN (cfun))
return;
@@ -1337,10 +1335,9 @@ fixup_partition_crossing (edge e)
if (BB_PARTITION (e->src) != BB_PARTITION (e->dest))
{
e->flags |= EDGE_CROSSING;
- note = find_reg_note (BB_END (e->src), REG_CROSSING_JUMP, NULL_RTX);
if (JUMP_P (BB_END (e->src))
- && !note)
- add_reg_note (BB_END (e->src), REG_CROSSING_JUMP, NULL_RTX);
+ && !CROSSING_JUMP_P (BB_END (e->src)))
+ CROSSING_JUMP_P (BB_END (e->src)) = 1;
}
else if (BB_PARTITION (e->src) == BB_PARTITION (e->dest))
{
@@ -1348,8 +1345,7 @@ fixup_partition_crossing (edge e)
/* Remove the section crossing note from jump at end of
src if it exists, and if no other successors are
still crossing. */
- note = find_reg_note (BB_END (e->src), REG_CROSSING_JUMP, NULL_RTX);
- if (note)
+ if (JUMP_P (BB_END (e->src)) && CROSSING_JUMP_P (BB_END (e->src)))
{
bool has_crossing_succ = false;
edge e2;
@@ -1361,7 +1357,7 @@ fixup_partition_crossing (edge e)
break;
}
if (!has_crossing_succ)
- remove_note (BB_END (e->src), note);
+ CROSSING_JUMP_P (BB_END (e->src)) = 0;
}
}
}
@@ -2460,8 +2456,7 @@ rtl_verify_edges (void)
e->src->index);
err = 1;
}
- if (JUMP_P (BB_END (bb))
- && !find_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX))
+ if (JUMP_P (BB_END (bb)) && !CROSSING_JUMP_P (BB_END (bb)))
{
error ("No region crossing jump at section boundary in bb %i",
bb->index);
@@ -2496,7 +2491,8 @@ rtl_verify_edges (void)
}
if (!has_crossing_edge
- && find_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX))
+ && JUMP_P (BB_END (bb))
+ && CROSSING_JUMP_P (BB_END (bb)))
{
print_rtl_with_bb (stderr, get_insns (), TDF_RTL | TDF_BLOCKS | TDF_DETAILS);
error ("Region crossing jump across same section in bb %i",
@@ -4217,14 +4213,14 @@ cfg_layout_initialize (unsigned int flags)
rtx x;
basic_block bb;
- /* Once bb reordering is complete, cfg layout mode should not be re-entered.
- Entering cfg layout mode will perform optimizations on the cfg that
- could affect the bb layout negatively or even require fixups. An
- example of the latter is if edge forwarding performed when optimizing
- the cfg layout required moving a block from the hot to the cold section
- under -freorder-blocks-and-partition. This would create an illegal
- partitioning unless some manual fixup was performed. */
- gcc_assert (!crtl->bb_reorder_complete);
+ /* Once bb partitioning is complete, cfg layout mode should not be
+ re-entered. Entering cfg layout mode may require fixups. As an
+ example, if edge forwarding performed when optimizing the cfg
+ layout required moving a block from the hot to the cold
+ section. This would create an illegal partitioning unless some
+ manual fixup was performed. */
+ gcc_assert (!(crtl->bb_reorder_complete
+ && flag_reorder_blocks_and_partition));
initialize_original_copy_tables ();
@@ -4564,7 +4560,7 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
try_redirect_by_replacing_jump (EDGE_SUCC (a, 0), b, true);
gcc_assert (!JUMP_P (BB_END (a)));
- /* When not optimizing CFG and the edge is the only place in RTL which holds
+ /* When not optimizing and the edge is the only place in RTL which holds
some unique locus, emit a nop with that locus in between. */
if (!optimize)
emit_nop_for_unique_locus_between (a, b);
@@ -4954,7 +4950,7 @@ init_rtl_bb_info (basic_block bb)
{
gcc_assert (!bb->il.x.rtl);
bb->il.x.head_ = NULL;
- bb->il.x.rtl = ggc_alloc_cleared_rtl_bb_info ();
+ bb->il.x.rtl = ggc_cleared_alloc<rtl_bb_info> ();
}
/* Returns true if it is possible to remove edge E by redirecting
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index ce0d0574be7..7c68dcfa48a 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -198,7 +198,7 @@ insert_new_cgraph_node_version (struct cgraph_node *node)
void **slot;
version_info_node = NULL;
- version_info_node = ggc_alloc_cleared_cgraph_function_version_info ();
+ version_info_node = ggc_cleared_alloc<cgraph_function_version_info> ();
version_info_node->this_node = node;
if (cgraph_fnver_htab == NULL)
@@ -507,7 +507,7 @@ cgraph_allocate_node (void)
}
else
{
- node = ggc_alloc_cleared_cgraph_node ();
+ node = ggc_cleared_alloc<cgraph_node> ();
node->uid = cgraph_max_uid++;
}
@@ -565,7 +565,7 @@ cgraph_get_create_node (tree decl)
first_clone->clone_of = node;
node->clones = first_clone;
symtab_prevail_in_asm_name_hash (node);
- symtab_insert_node_to_hashtable (node);
+ node->decl->decl_with_vis.symtab_node = node;
if (dump_file)
fprintf (dump_file, "Introduced new external node "
"(%s/%i) and turned into root of the clone tree.\n",
@@ -865,7 +865,7 @@ cgraph_create_edge_1 (struct cgraph_node *caller, struct cgraph_node *callee,
}
else
{
- edge = ggc_alloc_cgraph_edge ();
+ edge = ggc_alloc<struct cgraph_edge> ();
edge->uid = cgraph_edge_max_uid++;
}
@@ -938,7 +938,7 @@ cgraph_allocate_init_indirect_info (void)
{
struct cgraph_indirect_call_info *ii;
- ii = ggc_alloc_cleared_cgraph_indirect_call_info ();
+ ii = ggc_cleared_alloc<cgraph_indirect_call_info> ();
ii->param_index = -1;
return ii;
}
@@ -1378,12 +1378,12 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
if (dump_file)
fprintf (dump_file,
"Expanding speculative call of %s/%i -> %s/%i count:"
- HOST_WIDEST_INT_PRINT_DEC"\n",
+ "%"PRId64"\n",
xstrdup (e->caller->name ()),
e->caller->order,
xstrdup (e->callee->name ()),
e->callee->order,
- (HOST_WIDEST_INT)e->count);
+ (int64_t)e->count);
gcc_assert (e2->speculative);
push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
new_stmt = gimple_ic (e->call_stmt, cgraph (ref->referred),
@@ -1976,8 +1976,8 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf (f, " First run: %i\n", node->tp_first_run);
fprintf (f, " Function flags:");
if (node->count)
- fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x",
- (HOST_WIDEST_INT)node->count);
+ fprintf (f, " executed %"PRId64"x",
+ (int64_t)node->count);
if (node->origin)
fprintf (f, " nested in: %s", node->origin->asm_name ());
if (gimple_has_body_p (node->decl))
@@ -2028,8 +2028,8 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf (f, "%s/%i ", edge->caller->asm_name (),
edge->caller->order);
if (edge->count)
- fprintf (f, "("HOST_WIDEST_INT_PRINT_DEC"x) ",
- (HOST_WIDEST_INT)edge->count);
+ fprintf (f, "(%"PRId64"x) ",
+ (int64_t)edge->count);
if (edge->frequency)
fprintf (f, "(%.2f per call) ",
edge->frequency / (double)CGRAPH_FREQ_BASE);
@@ -2055,8 +2055,8 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
if (edge->indirect_inlining_edge)
fprintf (f, "(indirect_inlining) ");
if (edge->count)
- fprintf (f, "("HOST_WIDEST_INT_PRINT_DEC"x) ",
- (HOST_WIDEST_INT)edge->count);
+ fprintf (f, "(%"PRId64"x) ",
+ (int64_t)edge->count);
if (edge->frequency)
fprintf (f, "(%.2f per call) ",
edge->frequency / (double)CGRAPH_FREQ_BASE);
@@ -2268,6 +2268,7 @@ cgraph_make_node_local_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
node->externally_visible = false;
node->forced_by_abi = false;
node->local.local = true;
+ node->set_comdat_group (NULL);
node->unique_name = (node->resolution == LDPR_PREVAILING_DEF_IRONLY
|| node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
node->resolution = LDPR_PREVAILING_DEF_IRONLY;
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 7c144a7e70e..c7047de011d 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -76,6 +76,8 @@ public:
/* Set once the definition was analyzed. The list of references and
other properties are built during analysis. */
unsigned analyzed : 1;
+ /* Set for write-only variables. */
+ unsigned writeonly : 1;
/*** Visibility and linkage flags. ***/
@@ -139,6 +141,25 @@ public:
/* Circular list of nodes in the same comdat group if non-NULL. */
symtab_node *same_comdat_group;
+ /* Return comdat group. */
+ tree get_comdat_group ()
+ {
+ return comdat_group_;
+ }
+
+ tree get_comdat_group_id ()
+ {
+ if (comdat_group_ && TREE_CODE (comdat_group_) != IDENTIFIER_NODE)
+ comdat_group_ = DECL_ASSEMBLER_NAME (comdat_group_);
+ return comdat_group_;
+ }
+
+ /* Set comdat group. */
+ void set_comdat_group (tree group)
+ {
+ comdat_group_ = group;
+ }
+
/* Vectors of referring and referenced entities. */
struct ipa_ref_list ref_list;
@@ -151,6 +172,9 @@ public:
struct lto_file_decl_data * lto_file_data;
PTR GTY ((skip)) aux;
+
+ /* Comdat group the symbol is in. Can be private if GGC allowed that. */
+ tree comdat_group_;
};
enum availability
@@ -238,6 +262,13 @@ struct GTY(()) cgraph_global_info {
struct GTY(()) cgraph_rtl_info {
unsigned int preferred_incoming_stack_boundary;
+
+ /* Call unsaved hard registers really used by the corresponding
+ function (including ones used by functions called by the
+ function). */
+ HARD_REG_SET function_used_regs;
+ /* Set if function_used_regs is valid. */
+ unsigned function_used_regs_valid: 1;
};
/* Represent which DECL tree (or reference to such tree)
@@ -731,10 +762,9 @@ enum symbol_partitioning_class
/* In symtab.c */
void symtab_register_node (symtab_node *);
void symtab_unregister_node (symtab_node *);
+void symtab_remove_from_same_comdat_group (symtab_node *);
void symtab_remove_node (symtab_node *);
-symtab_node *symtab_get_node (const_tree);
symtab_node *symtab_node_for_asm (const_tree asmname);
-void symtab_insert_node_to_hashtable (symtab_node *);
void symtab_add_to_same_comdat_group (symtab_node *, symtab_node *);
void symtab_dissolve_same_comdat_group_list (symtab_node *node);
void dump_symtab (FILE *);
@@ -955,6 +985,10 @@ void free_varpool_node_set (varpool_node_set);
void ipa_discover_readonly_nonaddressable_vars (void);
bool varpool_externally_visible_p (varpool_node *);
+/* In ipa-visibility.c */
+bool cgraph_local_node_p (struct cgraph_node *);
+
+
/* In predict.c */
bool cgraph_maybe_hot_edge_p (struct cgraph_edge *e);
bool cgraph_optimize_for_size_p (struct cgraph_node *);
@@ -994,6 +1028,28 @@ void varpool_remove_initializer (varpool_node *);
/* In cgraph.c */
extern void change_decl_assembler_name (tree, tree);
+/* Return symbol table node associated with DECL, if any,
+ and NULL otherwise. */
+
+static inline symtab_node *
+symtab_get_node (const_tree decl)
+{
+#ifdef ENABLE_CHECKING
+ /* Check that we are called for sane type of object - functions
+ and static or external variables. */
+ gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL
+ || (TREE_CODE (decl) == VAR_DECL
+ && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
+ || in_lto_p)));
+ /* Check that the mapping is sane - perhaps this check can go away,
+ but at the moment frontends tends to corrupt the mapping by calling
+ memcpy/memset on the tree nodes. */
+ gcc_checking_assert (!decl->decl_with_vis.symtab_node
+ || decl->decl_with_vis.symtab_node->decl == decl);
+#endif
+ return decl->decl_with_vis.symtab_node;
+}
+
/* Return callgraph node for given symbol and check it is a function. */
static inline struct cgraph_node *
cgraph (symtab_node *node)
@@ -1030,6 +1086,35 @@ varpool_get_node (const_tree decl)
#define FOR_EACH_SYMBOL(node) \
for ((node) = symtab_nodes; (node); (node) = (node)->next)
+/* Return first static symbol with definition. */
+static inline symtab_node *
+symtab_first_defined_symbol (void)
+{
+ symtab_node *node;
+
+ for (node = symtab_nodes; node; node = node->next)
+ if (node->definition)
+ return node;
+
+ return NULL;
+}
+
+/* Return next reachable static symbol with initializer after NODE. */
+static inline symtab_node *
+symtab_next_defined_symbol (symtab_node *node)
+{
+ symtab_node *node1 = node->next;
+
+ for (; node1; node1 = node1->next)
+ if (node1->definition)
+ return node1;
+
+ return NULL;
+}
+/* Walk all symbols with definitions in current unit. */
+#define FOR_EACH_DEFINED_SYMBOL(node) \
+ for ((node) = symtab_first_defined_symbol (); (node); \
+ (node) = symtab_next_defined_symbol (node))
/* Return first variable. */
static inline varpool_node *
@@ -1058,7 +1143,7 @@ varpool_next_variable (varpool_node *node)
(node); \
(node) = varpool_next_variable ((node)))
-/* Return first reachable static variable with initializer. */
+/* Return first static variable with initializer. */
static inline varpool_node *
varpool_first_static_initializer (void)
{
@@ -1072,7 +1157,7 @@ varpool_first_static_initializer (void)
return NULL;
}
-/* Return next reachable static variable with initializer after NODE. */
+/* Return next static variable with initializer after NODE. */
static inline varpool_node *
varpool_next_static_initializer (varpool_node *node)
{
@@ -1091,7 +1176,7 @@ varpool_next_static_initializer (varpool_node *node)
for ((node) = varpool_first_static_initializer (); (node); \
(node) = varpool_next_static_initializer (node))
-/* Return first reachable static variable with initializer. */
+/* Return first static variable with definition. */
static inline varpool_node *
varpool_first_defined_variable (void)
{
@@ -1105,7 +1190,7 @@ varpool_first_defined_variable (void)
return NULL;
}
-/* Return next reachable static variable with initializer after NODE. */
+/* Return next static variable with definition after NODE. */
static inline varpool_node *
varpool_next_defined_variable (varpool_node *node)
{
@@ -1524,7 +1609,7 @@ static inline bool
symtab_can_be_discarded (symtab_node *node)
{
return (DECL_EXTERNAL (node->decl)
- || (DECL_ONE_ONLY (node->decl)
+ || (node->get_comdat_group ()
&& node->resolution != LDPR_PREVAILING_DEF
&& node->resolution != LDPR_PREVAILING_DEF_IRONLY
&& node->resolution != LDPR_PREVAILING_DEF_IRONLY_EXP));
@@ -1545,6 +1630,17 @@ symtab_comdat_local_p (symtab_node *node)
static inline bool
symtab_in_same_comdat_p (symtab_node *one, symtab_node *two)
{
- return DECL_COMDAT_GROUP (one->decl) == DECL_COMDAT_GROUP (two->decl);
+ if (cgraph_node *cn = dyn_cast <cgraph_node *> (one))
+ {
+ if (cn->global.inlined_to)
+ one = cn->global.inlined_to;
+ }
+ if (cgraph_node *cn = dyn_cast <cgraph_node *> (two))
+ {
+ if (cn->global.inlined_to)
+ two = cn->global.inlined_to;
+ }
+
+ return one->get_comdat_group () == two->get_comdat_group ();
}
#endif /* GCC_CGRAPH_H */
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 48b5379f216..4387b99f3af 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -146,7 +146,7 @@ cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n,
if (e->indirect_info)
{
new_edge->indirect_info
- = ggc_alloc_cleared_cgraph_indirect_call_info ();
+ = ggc_cleared_alloc<cgraph_indirect_call_info> ();
*new_edge->indirect_info = *e->indirect_info;
}
}
@@ -283,7 +283,6 @@ static void
set_new_clone_decl_and_node_flags (cgraph_node *new_node)
{
DECL_EXTERNAL (new_node->decl) = 0;
- DECL_COMDAT_GROUP (new_node->decl) = 0;
TREE_PUBLIC (new_node->decl) = 0;
DECL_COMDAT (new_node->decl) = 0;
DECL_WEAK (new_node->decl) = 0;
@@ -558,7 +557,7 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
that is not weak also.
??? We cannot use COMDAT linkage because there is no
ABI support for this. */
- if (DECL_ONE_ONLY (old_decl))
+ if (old_node->get_comdat_group ())
DECL_SECTION_NAME (new_node->decl) = NULL;
set_new_clone_decl_and_node_flags (new_node);
new_node->clone.tree_map = tree_map;
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index d06ce3217fd..e19b0a25c1d 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -210,6 +210,7 @@ along with GCC; see the file COPYING3. If not see
#include "pass_manager.h"
#include "tree-nested.h"
#include "gimplify.h"
+#include "dbgcnt.h"
/* Queue of cgraph nodes scheduled to be added into cgraph. This is a
secondary queue used during optimization to accommodate passes that
@@ -498,7 +499,7 @@ cgraph_add_new_function (tree fndecl, bool lowered)
break;
case CGRAPH_STATE_CONSTRUCTION:
/* Just enqueue function to be processed at nearest occurrence. */
- node = cgraph_create_node (fndecl);
+ node = cgraph_get_create_node (fndecl);
if (lowered)
node->lowered = true;
if (!cgraph_new_nodes)
@@ -570,7 +571,7 @@ add_asm_node (tree asm_str)
{
struct asm_node *node;
- node = ggc_alloc_cleared_asm_node ();
+ node = ggc_cleared_alloc<asm_node> ();
node->asm_str = asm_str;
node->order = symtab_order++;
node->next = NULL;
@@ -886,7 +887,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
make the edge direct. */
if (final)
{
- if (targets.length () <= 1)
+ if (targets.length () <= 1 && dbg_cnt (devirt))
{
cgraph_node *target;
if (targets.length () == 1)
@@ -903,6 +904,14 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
edge->call_stmt, 0,
TDF_SLIM);
}
+ if (dump_enabled_p ())
+ {
+ location_t locus = gimple_location (edge->call_stmt);
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, locus,
+ "devirtualizing call in %s to %s\n",
+ edge->caller->name (), target->name ());
+ }
+
cgraph_make_edge_direct (edge, target);
cgraph_redirect_edge_call_stmt_to_callee (edge);
if (cgraph_dump_file)
@@ -965,6 +974,8 @@ analyze_functions (void)
node != first_analyzed
&& node != first_analyzed_var; node = node->next)
{
+ /* Convert COMDAT group designators to IDENTIFIER_NODEs. */
+ node->get_comdat_group_id ();
if (decide_is_symbol_needed (node))
{
enqueue_node (node);
@@ -984,7 +995,7 @@ analyze_functions (void)
first_analyzed_var = varpool_first_variable ();
first_analyzed = cgraph_first_function ();
- if (changed && dump_file)
+ if (changed && cgraph_dump_file)
fprintf (cgraph_dump_file, "\n");
/* Lower representation, build callgraph edges and references for all trivially
@@ -1337,7 +1348,7 @@ init_lowered_empty_function (tree decl, bool in_ssa)
cfun->curr_properties |= (PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_any
| PROP_cfg | PROP_loops);
- set_loops_for_fn (cfun, ggc_alloc_cleared_loops ());
+ set_loops_for_fn (cfun, ggc_cleared_alloc<loops> ());
init_loops_structure (cfun, loops_for_fn (cfun), 1);
loops_for_fn (cfun)->state |= LOOPS_MAY_HAVE_MULTIPLE_LATCHES;
diff --git a/gcc/collect2.c b/gcc/collect2.c
index f0ab6b8c8f1..ec8f7332ea0 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -848,6 +848,8 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst,
fork_execute ("ld", lto_ld_argv);
post_ld_pass (false);
}
+ else
+ post_ld_pass (true);
}
/* Main program. */
diff --git a/gcc/combine.c b/gcc/combine.c
index a2f42c58ccd..72bde7a2694 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -2739,9 +2739,10 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p,
never appear in the insn stream so giving it the same INSN_UID
as I2 will not cause a problem. */
- i1 = gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2,
- BLOCK_FOR_INSN (i2), XVECEXP (PATTERN (i2), 0, 1),
- INSN_LOCATION (i2), -1, NULL_RTX);
+ i1 = gen_rtx_INSN (VOIDmode, NULL_RTX, i2, BLOCK_FOR_INSN (i2),
+ XVECEXP (PATTERN (i2), 0, 1), INSN_LOCATION (i2),
+ -1, NULL_RTX);
+ INSN_UID (i1) = INSN_UID (i2);
SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0));
SUBST (XEXP (SET_SRC (PATTERN (i2)), 0),
@@ -10348,9 +10349,10 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
/* (ashift (plus foo C) N) is (plus (ashift foo N) C'). */
if (code == ASHIFT
&& CONST_INT_P (XEXP (varop, 1))
- && (new_rtx = simplify_const_binary_operation (ASHIFT, result_mode,
- XEXP (varop, 1),
- GEN_INT (count))) != 0
+ && (new_rtx = simplify_const_binary_operation
+ (ASHIFT, result_mode,
+ gen_int_mode (INTVAL (XEXP (varop, 1)), result_mode),
+ GEN_INT (count))) != 0
&& CONST_INT_P (new_rtx)
&& merge_outer_ops (&outer_op, &outer_const, PLUS,
INTVAL (new_rtx), result_mode, &complement_p))
@@ -10367,9 +10369,10 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
if (code == LSHIFTRT
&& CONST_INT_P (XEXP (varop, 1))
&& mode_signbit_p (result_mode, XEXP (varop, 1))
- && (new_rtx = simplify_const_binary_operation (code, result_mode,
- XEXP (varop, 1),
- GEN_INT (count))) != 0
+ && (new_rtx = simplify_const_binary_operation
+ (code, result_mode,
+ gen_int_mode (INTVAL (XEXP (varop, 1)), result_mode),
+ GEN_INT (count))) != 0
&& CONST_INT_P (new_rtx)
&& merge_outer_ops (&outer_op, &outer_const, XOR,
INTVAL (new_rtx), result_mode, &complement_p))
diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index a6ab5552cce..3012783d24a 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -70,6 +70,11 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA_RDSEED_SET OPTION_MASK_ISA_RDSEED
#define OPTION_MASK_ISA_ADX_SET OPTION_MASK_ISA_ADX
#define OPTION_MASK_ISA_PREFETCHWT1_SET OPTION_MASK_ISA_PREFETCHWT1
+#define OPTION_MASK_ISA_CLFLUSHOPT_SET OPTION_MASK_ISA_CLFLUSHOPT
+#define OPTION_MASK_ISA_XSAVES_SET \
+ (OPTION_MASK_ISA_XSAVES | OPTION_MASK_ISA_XSAVE)
+#define OPTION_MASK_ISA_XSAVEC_SET \
+ (OPTION_MASK_ISA_XSAVEC | OPTION_MASK_ISA_XSAVE)
/* SSE4 includes both SSE4.1 and SSE4.2. -msse4 should be the same
as -msse4.2. */
@@ -156,6 +161,9 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA_RDSEED_UNSET OPTION_MASK_ISA_RDSEED
#define OPTION_MASK_ISA_ADX_UNSET OPTION_MASK_ISA_ADX
#define OPTION_MASK_ISA_PREFETCHWT1_UNSET OPTION_MASK_ISA_PREFETCHWT1
+#define OPTION_MASK_ISA_CLFLUSHOPT_UNSET OPTION_MASK_ISA_CLFLUSHOPT
+#define OPTION_MASK_ISA_XSAVEC_UNSET OPTION_MASK_ISA_XSAVEC
+#define OPTION_MASK_ISA_XSAVES_UNSET OPTION_MASK_ISA_XSAVES
/* SSE4 includes both SSE4.1 and SSE4.2. -mno-sse4 should the same
as -mno-sse4.1. */
@@ -720,6 +728,32 @@ ix86_handle_option (struct gcc_options *opts,
}
return true;
+ case OPT_mxsavec:
+ if (value)
+ {
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_XSAVEC_SET;
+ opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_XSAVEC_SET;
+ }
+ else
+ {
+ opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_XSAVEC_UNSET;
+ opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_XSAVEC_UNSET;
+ }
+ return true;
+
+ case OPT_mxsaves:
+ if (value)
+ {
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_XSAVES_SET;
+ opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_XSAVES_SET;
+ }
+ else
+ {
+ opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_XSAVES_UNSET;
+ opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_XSAVES_UNSET;
+ }
+ return true;
+
case OPT_mrdseed:
if (value)
{
@@ -772,6 +806,19 @@ ix86_handle_option (struct gcc_options *opts,
}
return true;
+ case OPT_mclflushopt:
+ if (value)
+ {
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_CLFLUSHOPT_SET;
+ opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_CLFLUSHOPT_SET;
+ }
+ else
+ {
+ opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_CLFLUSHOPT_UNSET;
+ opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_CLFLUSHOPT_UNSET;
+ }
+ return true;
+
/* Comes from final.c -- no real reason to change it. */
#define MAX_CODE_ALIGN 16
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 50338f7651c..c3f3ea6646c 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -164,13 +164,6 @@
# gas Set to yes or no depending on whether the target
# system normally uses GNU as.
#
-# need_64bit_hwint Set to yes if HOST_WIDE_INT must be 64 bits wide
-# for this target. This is true if this target
-# supports "long" or "wchar_t" wider than 32 bits,
-# or BITS_PER_WORD is wider than 32 bits.
-# The setting made here must match the one made in
-# other locations such as libcpp/configure.ac
-#
# configure_default_options
# Set to an initializer for configure_default_options
# in configargs.h, based on --with-cpu et cetera.
@@ -233,7 +226,6 @@ gnu_ld="$gnu_ld_flag"
default_use_cxa_atexit=no
default_gnu_indirect_function=no
target_gtfiles=
-need_64bit_hwint=yes
need_64bit_isa=
native_system_header_dir=/usr/include
target_type_format_char='@'
@@ -310,14 +302,12 @@ m32c*-*-*)
;;
aarch64*-*-*)
cpu_type=aarch64
- need_64bit_hwint=yes
extra_headers="arm_neon.h"
extra_objs="aarch64-builtins.o aarch-common.o"
target_has_targetm_common=yes
;;
alpha*-*-*)
cpu_type=alpha
- need_64bit_hwint=yes
extra_options="${extra_options} g.opt"
;;
am33_2.0-*-linux*)
@@ -333,7 +323,6 @@ arm*-*-*)
target_type_format_char='%'
c_target_objs="arm-c.o"
cxx_target_objs="arm-c.o"
- need_64bit_hwint=yes
extra_options="${extra_options} arm/arm-tables.opt"
;;
avr-*-*)
@@ -363,7 +352,6 @@ i[34567]86-*-*)
cpu_type=i386
c_target_objs="i386-c.o"
cxx_target_objs="i386-c.o"
- need_64bit_hwint=yes
extra_options="${extra_options} fused-madd.opt"
extra_headers="cpuid.h mmintrin.h mm3dnow.h xmmintrin.h emmintrin.h
pmmintrin.h tmmintrin.h ammintrin.h smmintrin.h
@@ -375,7 +363,8 @@ i[34567]86-*-*)
rtmintrin.h xtestintrin.h rdseedintrin.h prfchwintrin.h
adxintrin.h fxsrintrin.h xsaveintrin.h xsaveoptintrin.h
avx512cdintrin.h avx512erintrin.h avx512pfintrin.h
- shaintrin.h"
+ shaintrin.h clflushoptintrin.h xsavecintrin.h
+ xsavesintrin.h"
;;
x86_64-*-*)
cpu_type=i386
@@ -392,12 +381,11 @@ x86_64-*-*)
rtmintrin.h xtestintrin.h rdseedintrin.h prfchwintrin.h
adxintrin.h fxsrintrin.h xsaveintrin.h xsaveoptintrin.h
avx512cdintrin.h avx512erintrin.h avx512pfintrin.h
- shaintrin.h"
- need_64bit_hwint=yes
+ shaintrin.h clflushoptintrin.h xsavecintrin.h
+ xsavesintrin.h"
;;
ia64-*-*)
extra_headers=ia64intrin.h
- need_64bit_hwint=yes
extra_options="${extra_options} g.opt fused-madd.opt"
;;
hppa*-*-*)
@@ -420,7 +408,6 @@ microblaze*-*-*)
;;
mips*-*-*)
cpu_type=mips
- need_64bit_hwint=yes
extra_headers="loongson.h"
extra_options="${extra_options} g.opt mips/mips-tables.opt"
;;
@@ -438,7 +425,6 @@ picochip-*-*)
powerpc*-*-*)
cpu_type=rs6000
extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h htmintrin.h htmxlintrin.h"
- need_64bit_hwint=yes
case x$with_cpu in
xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[345678]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|Xe6500)
cpu_is_64bit=yes
@@ -447,7 +433,6 @@ powerpc*-*-*)
extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
;;
rs6000*-*-*)
- need_64bit_hwint=yes
extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
;;
score*-*-*)
@@ -459,22 +444,18 @@ sparc*-*-*)
c_target_objs="sparc-c.o"
cxx_target_objs="sparc-c.o"
extra_headers="visintrin.h"
- need_64bit_hwint=yes
;;
spu*-*-*)
cpu_type=spu
- need_64bit_hwint=yes
;;
s390*-*-*)
cpu_type=s390
- need_64bit_hwint=yes
extra_options="${extra_options} fused-madd.opt"
extra_headers="s390intrin.h htmintrin.h htmxlintrin.h"
;;
# Note the 'l'; we need to be able to match e.g. "shle" or "shl".
sh[123456789lbe]*-*-* | sh-*-*)
cpu_type=sh
- need_64bit_hwint=yes
extra_options="${extra_options} fused-madd.opt"
extra_objs="${extra_objs} sh_treg_combine.o sh-mem.o sh_optimize_sett_clrt.o"
;;
@@ -491,11 +472,9 @@ xtensa*-*-*)
;;
tilegx*-*-*)
cpu_type=tilegx
- need_64bit_hwint=yes
;;
tilepro*-*-*)
cpu_type=tilepro
- need_64bit_hwint=yes
;;
esac
@@ -642,6 +621,26 @@ case ${target} in
"" | yes | posix) thread_file='posix' ;;
esac
;;
+*-*-dragonfly*)
+ gas=yes
+ gnu_ld=yes
+ tmake_file="t-slibgcc"
+ case ${enable_threads} in
+ "" | yes | posix)
+ thread_file='posix'
+ ;;
+ no | single)
+ # Let these non-posix thread selections fall through if requested
+ ;;
+ *)
+ echo 'Unknown thread configuration for DragonFly BSD'
+ exit 1
+ ;;
+ esac
+ extra_options="$extra_options rpath.opt dragonfly.opt"
+ default_use_cxa_atexit=yes
+ use_gcc_stdint=wrap
+ ;;
*-*-freebsd*)
# This is the generic ELF configuration of FreeBSD. Later
# machine-specific sections may refine and add to this
@@ -683,7 +682,6 @@ case ${target} in
*)
default_use_cxa_atexit=yes;;
esac
- # need_64bit_hwint=yes # system compiler has this for all arch!
use_gcc_stdint=wrap
;;
*-*-linux* | frv-*-*linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu | *-*-gnu* | *-*-kopensolaris*-gnu)
@@ -1184,7 +1182,6 @@ hppa*64*-*-linux*)
glibc-stdint.h pa/pa-linux.h pa/pa64-regs.h pa/pa-64.h \
pa/pa64-linux.h"
gas=yes gnu_ld=yes
- need_64bit_hwint=yes
;;
hppa*-*-linux*)
target_cpu_default="MASK_PA_11|MASK_NO_SPACE_REGS"
@@ -1259,7 +1256,6 @@ hppa*64*-*-hpux11*)
esac
extra_options="${extra_options} pa/pa-hpux.opt \
pa/pa-hpux1010.opt pa/pa64-hpux.opt hpux11.opt"
- need_64bit_hwint=yes
tmake_file="t-slibgcc"
case x${enable_threads} in
x | xyes | xposix )
@@ -1345,6 +1341,14 @@ x86_64-*-rdos*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h i386/rdos.h i386/rdos64.h"
tmake_file="i386/t-i386elf t-svr4"
;;
+i[34567]86-*-dragonfly*)
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h dragonfly.h dragonfly-stdint.h i386/dragonfly.h"
+ tmake_file="${tmake_file} i386/t-crtstuff"
+ ;;
+x86_64-*-dragonfly*)
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h dragonfly.h dragonfly-stdint.h i386/x86-64.h i386/dragonfly.h"
+ tmake_file="${tmake_file} i386/t-crtstuff"
+ ;;
i[34567]86-*-freebsd*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ${fbsd_tm_file} i386/freebsd.h"
;;
@@ -2092,7 +2096,6 @@ mipstx39-*-elf* | mipstx39el-*-elf*)
;;
mmix-knuth-mmixware)
tm_file="${tm_file} newlib-stdint.h"
- need_64bit_hwint=yes
use_gcc_stdint=wrap
;;
mn10300-*-*)
@@ -2310,7 +2313,7 @@ powerpc-wrs-vxworks|powerpc-wrs-vxworksae)
extra_headers=ppc-asm.h
case ${target} in
*-vxworksae*)
- tm_file="${tm_file} vx-common.h vxworksae.h rs6000/vxworks.h rs6000/e500.h"
+ tm_file="${tm_file} vx-common.h vxworksae.h rs6000/vxworks.h rs6000/e500.h rs6000/vxworksae.h"
tmake_file="${tmake_file} rs6000/t-vxworksae"
;;
*-vxworks*)
@@ -4085,6 +4088,8 @@ case ${target} in
;;
i[34567]86-*-mingw* | x86_64-*-mingw*)
;;
+ i[34567]86-*-dragonfly* | x86_64-*-dragonfly*)
+ ;;
i[34567]86-*-freebsd* | x86_64-*-freebsd*)
;;
ia64*-*-linux*)
diff --git a/gcc/config.in b/gcc/config.in
index c0ba36ea98b..2313307117c 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1260,6 +1260,13 @@
#endif
+/* Define if the linker supports clearing hardware capabilities via mapfile.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_CLEARCAP
+#endif
+
+
/* Define if your linker supports --demangle option. */
#ifndef USED_FOR_TARGET
#undef HAVE_LD_DEMANGLE
@@ -1655,12 +1662,6 @@
#endif
-/* Define to 1 if the system has the type `__int64'. */
-#ifndef USED_FOR_TARGET
-#undef HAVE___INT64
-#endif
-
-
/* Define if cloog is in use. */
#ifndef USED_FOR_TARGET
#undef HAVE_cloog
@@ -1729,12 +1730,6 @@
#endif
-/* Define to 1 if HOST_WIDE_INT must be 64 bits wide (see hwint.h). */
-#ifndef USED_FOR_TARGET
-#undef NEED_64BIT_HOST_WIDE_INT
-#endif
-
-
/* Define to the address where bug reports for this package should be sent. */
#ifndef USED_FOR_TARGET
#undef PACKAGE_BUGREPORT
@@ -1813,12 +1808,6 @@
#endif
-/* The size of `__int64', as computed by sizeof. */
-#ifndef USED_FOR_TARGET
-#undef SIZEOF___INT64
-#endif
-
-
/* Define to 1 if you have the ANSI C header files. */
#ifndef USED_FOR_TARGET
#undef STDC_HEADERS
@@ -1872,8 +1861,8 @@
#endif
-/* Define to 1 if the 'long long' (or '__int64') is wider than 'long' but
- still efficiently supported by the host hardware. */
+/* Define to 1 if the 'long long' type is wider than 'long' but still
+ efficiently supported by the host hardware. */
#ifndef USED_FOR_TARGET
#undef USE_LONG_LONG_FOR_WIDEST_FAST_INT
#endif
diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index a3019828a93..ca14d51715d 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -169,6 +169,10 @@ aarch64_types_binop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
= { qualifier_none, qualifier_none, qualifier_maybe_immediate };
#define TYPES_BINOP (aarch64_types_binop_qualifiers)
static enum aarch64_type_qualifiers
+aarch64_types_binopv_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+ = { qualifier_void, qualifier_none, qualifier_none };
+#define TYPES_BINOPV (aarch64_types_binopv_qualifiers)
+static enum aarch64_type_qualifiers
aarch64_types_binopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
= { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned };
#define TYPES_BINOPU (aarch64_types_binopu_qualifiers)
@@ -394,6 +398,12 @@ static aarch64_simd_builtin_datum aarch64_simd_builtin_data[] = {
enum aarch64_builtins
{
AARCH64_BUILTIN_MIN,
+
+ AARCH64_BUILTIN_GET_FPCR,
+ AARCH64_BUILTIN_SET_FPCR,
+ AARCH64_BUILTIN_GET_FPSR,
+ AARCH64_BUILTIN_SET_FPSR,
+
AARCH64_SIMD_BUILTIN_BASE,
#include "aarch64-simd-builtins.def"
AARCH64_SIMD_BUILTIN_MAX = AARCH64_SIMD_BUILTIN_BASE
@@ -775,6 +785,24 @@ aarch64_init_simd_builtins (void)
void
aarch64_init_builtins (void)
{
+ tree ftype_set_fpr
+ = build_function_type_list (void_type_node, unsigned_type_node, NULL);
+ tree ftype_get_fpr
+ = build_function_type_list (unsigned_type_node, NULL);
+
+ aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR]
+ = add_builtin_function ("__builtin_aarch64_get_fpcr", ftype_get_fpr,
+ AARCH64_BUILTIN_GET_FPCR, BUILT_IN_MD, NULL, NULL_TREE);
+ aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR]
+ = add_builtin_function ("__builtin_aarch64_set_fpcr", ftype_set_fpr,
+ AARCH64_BUILTIN_SET_FPCR, BUILT_IN_MD, NULL, NULL_TREE);
+ aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR]
+ = add_builtin_function ("__builtin_aarch64_get_fpsr", ftype_get_fpr,
+ AARCH64_BUILTIN_GET_FPSR, BUILT_IN_MD, NULL, NULL_TREE);
+ aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR]
+ = add_builtin_function ("__builtin_aarch64_set_fpsr", ftype_set_fpr,
+ AARCH64_BUILTIN_SET_FPSR, BUILT_IN_MD, NULL, NULL_TREE);
+
if (TARGET_SIMD)
aarch64_init_simd_builtins ();
}
@@ -987,6 +1015,36 @@ aarch64_expand_builtin (tree exp,
{
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
int fcode = DECL_FUNCTION_CODE (fndecl);
+ int icode;
+ rtx pat, op0;
+ tree arg0;
+
+ switch (fcode)
+ {
+ case AARCH64_BUILTIN_GET_FPCR:
+ case AARCH64_BUILTIN_SET_FPCR:
+ case AARCH64_BUILTIN_GET_FPSR:
+ case AARCH64_BUILTIN_SET_FPSR:
+ if ((fcode == AARCH64_BUILTIN_GET_FPCR)
+ || (fcode == AARCH64_BUILTIN_GET_FPSR))
+ {
+ icode = (fcode == AARCH64_BUILTIN_GET_FPSR) ?
+ CODE_FOR_get_fpsr : CODE_FOR_get_fpcr;
+ target = gen_reg_rtx (SImode);
+ pat = GEN_FCN (icode) (target);
+ }
+ else
+ {
+ target = NULL_RTX;
+ icode = (fcode == AARCH64_BUILTIN_SET_FPSR) ?
+ CODE_FOR_set_fpsr : CODE_FOR_set_fpcr;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ op0 = expand_normal (arg0);
+ pat = GEN_FCN (icode) (op0);
+ }
+ emit_insn (pat);
+ return target;
+ }
if (fcode >= AARCH64_SIMD_BUILTIN_BASE)
return aarch64_simd_expand_builtin (fcode, exp, target);
@@ -1260,6 +1318,106 @@ aarch64_gimple_fold_builtin (gimple_stmt_iterator *gsi)
return changed;
}
+void
+aarch64_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
+{
+ const unsigned AARCH64_FE_INVALID = 1;
+ const unsigned AARCH64_FE_DIVBYZERO = 2;
+ const unsigned AARCH64_FE_OVERFLOW = 4;
+ const unsigned AARCH64_FE_UNDERFLOW = 8;
+ const unsigned AARCH64_FE_INEXACT = 16;
+ const unsigned HOST_WIDE_INT AARCH64_FE_ALL_EXCEPT = (AARCH64_FE_INVALID
+ | AARCH64_FE_DIVBYZERO
+ | AARCH64_FE_OVERFLOW
+ | AARCH64_FE_UNDERFLOW
+ | AARCH64_FE_INEXACT);
+ const unsigned HOST_WIDE_INT AARCH64_FE_EXCEPT_SHIFT = 8;
+ tree fenv_cr, fenv_sr, get_fpcr, set_fpcr, mask_cr, mask_sr;
+ tree ld_fenv_cr, ld_fenv_sr, masked_fenv_cr, masked_fenv_sr, hold_fnclex_cr;
+ tree hold_fnclex_sr, new_fenv_var, reload_fenv, restore_fnenv, get_fpsr, set_fpsr;
+ tree update_call, atomic_feraiseexcept, hold_fnclex, masked_fenv, ld_fenv;
+
+ /* Generate the equivalence of :
+ unsigned int fenv_cr;
+ fenv_cr = __builtin_aarch64_get_fpcr ();
+
+ unsigned int fenv_sr;
+ fenv_sr = __builtin_aarch64_get_fpsr ();
+
+ Now set all exceptions to non-stop
+ unsigned int mask_cr
+ = ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT);
+ unsigned int masked_cr;
+ masked_cr = fenv_cr & mask_cr;
+
+ And clear all exception flags
+ unsigned int maske_sr = ~AARCH64_FE_ALL_EXCEPT;
+ unsigned int masked_cr;
+ masked_sr = fenv_sr & mask_sr;
+
+ __builtin_aarch64_set_cr (masked_cr);
+ __builtin_aarch64_set_sr (masked_sr); */
+
+ fenv_cr = create_tmp_var (unsigned_type_node, NULL);
+ fenv_sr = create_tmp_var (unsigned_type_node, NULL);
+
+ get_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR];
+ set_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR];
+ get_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR];
+ set_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR];
+
+ mask_cr = build_int_cst (unsigned_type_node,
+ ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT));
+ mask_sr = build_int_cst (unsigned_type_node,
+ ~(AARCH64_FE_ALL_EXCEPT));
+
+ ld_fenv_cr = build2 (MODIFY_EXPR, unsigned_type_node,
+ fenv_cr, build_call_expr (get_fpcr, 0));
+ ld_fenv_sr = build2 (MODIFY_EXPR, unsigned_type_node,
+ fenv_sr, build_call_expr (get_fpsr, 0));
+
+ masked_fenv_cr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_cr, mask_cr);
+ masked_fenv_sr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_sr, mask_sr);
+
+ hold_fnclex_cr = build_call_expr (set_fpcr, 1, masked_fenv_cr);
+ hold_fnclex_sr = build_call_expr (set_fpsr, 1, masked_fenv_sr);
+
+ hold_fnclex = build2 (COMPOUND_EXPR, void_type_node, hold_fnclex_cr,
+ hold_fnclex_sr);
+ masked_fenv = build2 (COMPOUND_EXPR, void_type_node, masked_fenv_cr,
+ masked_fenv_sr);
+ ld_fenv = build2 (COMPOUND_EXPR, void_type_node, ld_fenv_cr, ld_fenv_sr);
+
+ *hold = build2 (COMPOUND_EXPR, void_type_node,
+ build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv),
+ hold_fnclex);
+
+ /* Store the value of masked_fenv to clear the exceptions:
+ __builtin_aarch64_set_fpsr (masked_fenv_sr); */
+
+ *clear = build_call_expr (set_fpsr, 1, masked_fenv_sr);
+
+ /* Generate the equivalent of :
+ unsigned int new_fenv_var;
+ new_fenv_var = __builtin_aarch64_get_fpsr ();
+
+ __builtin_aarch64_set_fpsr (fenv_sr);
+
+ __atomic_feraiseexcept (new_fenv_var); */
+
+ new_fenv_var = create_tmp_var (unsigned_type_node, NULL);
+ reload_fenv = build2 (MODIFY_EXPR, unsigned_type_node,
+ new_fenv_var, build_call_expr (get_fpsr, 0));
+ restore_fnenv = build_call_expr (set_fpsr, 1, fenv_sr);
+ atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
+ update_call = build_call_expr (atomic_feraiseexcept, 1,
+ fold_convert (integer_type_node, new_fenv_var));
+ *update = build2 (COMPOUND_EXPR, void_type_node,
+ build2 (COMPOUND_EXPR, void_type_node,
+ reload_fenv, restore_fnenv), update_call);
+}
+
+
#undef AARCH64_CHECK_BUILTIN_MODE
#undef AARCH64_FIND_FRINT_VARIANT
#undef BUILTIN_DX
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 04cbc780da2..68d488d2fd9 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -108,9 +108,22 @@ enum aarch64_symbol_type
cost models and vectors for address cost calculations, register
move costs and memory move costs. */
+/* Scaled addressing modes can vary cost depending on the mode of the
+ value to be loaded/stored. QImode values cannot use scaled
+ addressing modes. */
+
+struct scale_addr_mode_cost
+{
+ const int hi;
+ const int si;
+ const int di;
+ const int ti;
+};
+
/* Additional cost for addresses. */
struct cpu_addrcost_table
{
+ const struct scale_addr_mode_cost addr_scale_costs;
const int pre_modify;
const int post_modify;
const int register_offset;
@@ -202,6 +215,8 @@ enum aarch64_symbol_type aarch64_classify_symbol (rtx,
enum aarch64_symbol_type aarch64_classify_tls_symbol (rtx);
enum reg_class aarch64_regno_regclass (unsigned);
int aarch64_asm_preferred_eh_data_format (int, int);
+enum machine_mode aarch64_hard_regno_caller_save_mode (unsigned, unsigned,
+ enum machine_mode);
int aarch64_hard_regno_mode_ok (unsigned, enum machine_mode);
int aarch64_hard_regno_nregs (unsigned, enum machine_mode);
int aarch64_simd_attr_length_move (rtx);
@@ -291,4 +306,5 @@ extern void aarch64_split_combinev16qi (rtx operands[3]);
extern void aarch64_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel);
extern bool
aarch64_expand_vec_perm_const (rtx target, rtx op0, rtx op1, rtx sel);
+void aarch64_atomic_assign_expand_fenv (tree *, tree *, tree *);
#endif /* GCC_AARCH64_PROTOS_H */
diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def b/gcc/config/aarch64/aarch64-simd-builtins.def
index 339e8f86a4b..b5d9965cbcb 100644
--- a/gcc/config/aarch64/aarch64-simd-builtins.def
+++ b/gcc/config/aarch64/aarch64-simd-builtins.def
@@ -410,3 +410,6 @@
/* Implemented by aarch64_crypto_pmull<mode>. */
VAR1 (BINOPP, crypto_pmull, 0, di)
VAR1 (BINOPP, crypto_pmull, 0, v2di)
+
+ /* Meta-op to check lane bounds of immediate in aarch64_expand_builtin. */
+ VAR1 (BINOPV, im_lane_bound, 0, si)
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index 108bc8d8893..c239677a581 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -4167,6 +4167,35 @@
[(set_attr "type" "neon_permute<q>")]
)
+;; Note immediate (third) operand is lane index not byte index.
+(define_insn "aarch64_ext<mode>"
+ [(set (match_operand:VALL 0 "register_operand" "=w")
+ (unspec:VALL [(match_operand:VALL 1 "register_operand" "w")
+ (match_operand:VALL 2 "register_operand" "w")
+ (match_operand:SI 3 "immediate_operand" "i")]
+ UNSPEC_EXT))]
+ "TARGET_SIMD"
+{
+ operands[3] = GEN_INT (INTVAL (operands[3])
+ * GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)));
+ return "ext\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>, #%3";
+}
+ [(set_attr "type" "neon_ext<q>")]
+)
+
+;; This exists solely to check the arguments to the corresponding __builtin.
+;; Used where we want an error for out-of-range indices which would otherwise
+;; be silently wrapped (e.g. the mask to a __builtin_shuffle).
+(define_expand "aarch64_im_lane_boundsi"
+ [(match_operand:SI 0 "immediate_operand" "i")
+ (match_operand:SI 1 "immediate_operand" "i")]
+ "TARGET_SIMD"
+{
+ aarch64_simd_lane_bounds (operands[0], 0, INTVAL (operands[1]));
+ DONE;
+}
+)
+
(define_insn "aarch64_st2<mode>_dreg"
[(set (match_operand:TI 0 "aarch64_simd_struct_operand" "=Utv")
(unspec:TI [(match_operand:OI 1 "register_operand" "w")
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 6a6fb032647..bb33304a2fd 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -63,6 +63,8 @@
#include "cfgloop.h"
#include "tree-vectorizer.h"
#include "config/arm/aarch-cost-tables.h"
+#include "dumpfile.h"
+#include "builtins.h"
/* Defined for convenience. */
#define POINTER_BYTES (POINTER_SIZE / BITS_PER_UNIT)
@@ -141,6 +143,7 @@ static bool aarch64_const_vec_all_same_int_p (rtx,
static bool aarch64_vectorize_vec_perm_const_ok (enum machine_mode vmode,
const unsigned char *sel);
+static int aarch64_address_cost (rtx, enum machine_mode, addr_space_t, bool);
/* The processor for which instructions should be scheduled. */
enum aarch64_processor aarch64_tune = cortexa53;
@@ -171,6 +174,15 @@ __extension__
#endif
static const struct cpu_addrcost_table generic_addrcost_table =
{
+#if HAVE_DESIGNATED_INITIALIZERS
+ .addr_scale_costs =
+#endif
+ {
+ NAMED_PARAM (qi, 0),
+ NAMED_PARAM (hi, 0),
+ NAMED_PARAM (si, 0),
+ NAMED_PARAM (ti, 0),
+ },
NAMED_PARAM (pre_modify, 0),
NAMED_PARAM (post_modify, 0),
NAMED_PARAM (register_offset, 0),
@@ -181,6 +193,27 @@ static const struct cpu_addrcost_table generic_addrcost_table =
#if HAVE_DESIGNATED_INITIALIZERS && GCC_VERSION >= 2007
__extension__
#endif
+static const struct cpu_addrcost_table cortexa57_addrcost_table =
+{
+#if HAVE_DESIGNATED_INITIALIZERS
+ .addr_scale_costs =
+#endif
+ {
+ NAMED_PARAM (qi, 0),
+ NAMED_PARAM (hi, 1),
+ NAMED_PARAM (si, 0),
+ NAMED_PARAM (ti, 1),
+ },
+ NAMED_PARAM (pre_modify, 0),
+ NAMED_PARAM (post_modify, 0),
+ NAMED_PARAM (register_offset, 0),
+ NAMED_PARAM (register_extend, 0),
+ NAMED_PARAM (imm_offset, 0),
+};
+
+#if HAVE_DESIGNATED_INITIALIZERS && GCC_VERSION >= 2007
+__extension__
+#endif
static const struct cpu_regmove_cost generic_regmove_cost =
{
NAMED_PARAM (GP2GP, 1),
@@ -212,6 +245,26 @@ static const struct cpu_vector_cost generic_vector_cost =
NAMED_PARAM (cond_not_taken_branch_cost, 1)
};
+/* Generic costs for vector insn classes. */
+#if HAVE_DESIGNATED_INITIALIZERS && GCC_VERSION >= 2007
+__extension__
+#endif
+static const struct cpu_vector_cost cortexa57_vector_cost =
+{
+ NAMED_PARAM (scalar_stmt_cost, 1),
+ NAMED_PARAM (scalar_load_cost, 4),
+ NAMED_PARAM (scalar_store_cost, 1),
+ NAMED_PARAM (vec_stmt_cost, 3),
+ NAMED_PARAM (vec_to_scalar_cost, 8),
+ NAMED_PARAM (scalar_to_vec_cost, 8),
+ NAMED_PARAM (vec_align_load_cost, 5),
+ NAMED_PARAM (vec_unalign_load_cost, 5),
+ NAMED_PARAM (vec_unalign_store_cost, 1),
+ NAMED_PARAM (vec_store_cost, 1),
+ NAMED_PARAM (cond_taken_branch_cost, 1),
+ NAMED_PARAM (cond_not_taken_branch_cost, 1)
+};
+
#if HAVE_DESIGNATED_INITIALIZERS && GCC_VERSION >= 2007
__extension__
#endif
@@ -238,9 +291,9 @@ static const struct tune_params cortexa53_tunings =
static const struct tune_params cortexa57_tunings =
{
&cortexa57_extra_costs,
- &generic_addrcost_table,
+ &cortexa57_addrcost_table,
&generic_regmove_cost,
- &generic_vector_cost,
+ &cortexa57_vector_cost,
NAMED_PARAM (memmov_cost, 4),
NAMED_PARAM (issue_rate, 3)
};
@@ -424,6 +477,24 @@ aarch64_hard_regno_mode_ok (unsigned regno, enum machine_mode mode)
return 0;
}
+/* Implement HARD_REGNO_CALLER_SAVE_MODE. */
+enum machine_mode
+aarch64_hard_regno_caller_save_mode (unsigned regno, unsigned nregs,
+ enum machine_mode mode)
+{
+ /* Handle modes that fit within single registers. */
+ if (nregs == 1 && GET_MODE_SIZE (mode) <= 16)
+ {
+ if (GET_MODE_SIZE (mode) >= 4)
+ return mode;
+ else
+ return SImode;
+ }
+ /* Fall back to generic for multi-reg and very large modes. */
+ else
+ return choose_hard_reg_mode (regno, nregs, false);
+}
+
/* Return true if calls to DECL should be treated as
long-calls (ie called via a register). */
static bool
@@ -444,7 +515,7 @@ aarch64_is_long_call_p (rtx sym)
represent an expression that matches an extend operation. The
operands represent the paramters from
- (extract (mult (reg) (mult_imm)) (extract_imm) (const_int 0)). */
+ (extract:MODE (mult (reg) (MULT_IMM)) (EXTRACT_IMM) (const_int 0)). */
bool
aarch64_is_extend_from_extract (enum machine_mode mode, rtx mult_imm,
rtx extract_imm)
@@ -1198,18 +1269,10 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
}
static bool
-aarch64_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
+aarch64_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
+ tree exp ATTRIBUTE_UNUSED)
{
- /* Indirect calls are not currently supported. */
- if (decl == NULL)
- return false;
-
- /* Cannot tail-call to long-calls, since these are outside of the
- range of a branch instruction (we could handle this if we added
- support for indirect tail-calls. */
- if (aarch64_decl_is_long_call_p (decl))
- return false;
-
+ /* Currently, always true. */
return true;
}
@@ -2478,12 +2541,22 @@ aarch64_final_eh_return_addr (void)
- 2 * UNITS_PER_WORD));
}
-/* Output code to build up a constant in a register. */
-static void
-aarch64_build_constant (int regnum, HOST_WIDE_INT val)
+/* Possibly output code to build up a constant in a register. For
+ the benefit of the costs infrastructure, returns the number of
+ instructions which would be emitted. GENERATE inhibits or
+ enables code generation. */
+
+static int
+aarch64_build_constant (int regnum, HOST_WIDE_INT val, bool generate)
{
+ int insns = 0;
+
if (aarch64_bitmask_imm (val, DImode))
- emit_move_insn (gen_rtx_REG (Pmode, regnum), GEN_INT (val));
+ {
+ if (generate)
+ emit_move_insn (gen_rtx_REG (Pmode, regnum), GEN_INT (val));
+ insns = 1;
+ }
else
{
int i;
@@ -2514,15 +2587,19 @@ aarch64_build_constant (int regnum, HOST_WIDE_INT val)
the same. */
if (ncount < zcount)
{
- emit_move_insn (gen_rtx_REG (Pmode, regnum),
- GEN_INT (val | ~(HOST_WIDE_INT) 0xffff));
+ if (generate)
+ emit_move_insn (gen_rtx_REG (Pmode, regnum),
+ GEN_INT (val | ~(HOST_WIDE_INT) 0xffff));
tval = 0xffff;
+ insns++;
}
else
{
- emit_move_insn (gen_rtx_REG (Pmode, regnum),
- GEN_INT (val & 0xffff));
+ if (generate)
+ emit_move_insn (gen_rtx_REG (Pmode, regnum),
+ GEN_INT (val & 0xffff));
tval = 0;
+ insns++;
}
val >>= 16;
@@ -2530,11 +2607,17 @@ aarch64_build_constant (int regnum, HOST_WIDE_INT val)
for (i = 16; i < 64; i += 16)
{
if ((val & 0xffff) != tval)
- emit_insn (gen_insv_immdi (gen_rtx_REG (Pmode, regnum),
- GEN_INT (i), GEN_INT (val & 0xffff)));
+ {
+ if (generate)
+ emit_insn (gen_insv_immdi (gen_rtx_REG (Pmode, regnum),
+ GEN_INT (i),
+ GEN_INT (val & 0xffff)));
+ insns++;
+ }
val >>= 16;
}
}
+ return insns;
}
static void
@@ -2549,7 +2632,7 @@ aarch64_add_constant (int regnum, int scratchreg, HOST_WIDE_INT delta)
if (mdelta >= 4096 * 4096)
{
- aarch64_build_constant (scratchreg, delta);
+ (void) aarch64_build_constant (scratchreg, delta, true);
emit_insn (gen_add3_insn (this_rtx, this_rtx, scratch_rtx));
}
else if (mdelta > 0)
@@ -2623,7 +2706,7 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
addr = plus_constant (Pmode, temp0, vcall_offset);
else
{
- aarch64_build_constant (IP1_REGNUM, vcall_offset);
+ (void) aarch64_build_constant (IP1_REGNUM, vcall_offset, true);
addr = gen_rtx_PLUS (Pmode, temp0, temp1);
}
@@ -3983,7 +4066,7 @@ enum reg_class
aarch64_regno_regclass (unsigned regno)
{
if (GP_REGNUM_P (regno))
- return CORE_REGS;
+ return GENERAL_REGS;
if (regno == SP_REGNUM)
return STACK_REG;
@@ -4134,12 +4217,12 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
/* A TFmode or TImode memory access should be handled via an FP_REGS
because AArch64 has richer addressing modes for LDR/STR instructions
than LDP/STP instructions. */
- if (!TARGET_GENERAL_REGS_ONLY && rclass == CORE_REGS
+ if (!TARGET_GENERAL_REGS_ONLY && rclass == GENERAL_REGS
&& GET_MODE_SIZE (mode) == 16 && MEM_P (x))
return FP_REGS;
if (rclass == FP_REGS && (mode == TImode || mode == TFmode) && CONSTANT_P(x))
- return CORE_REGS;
+ return GENERAL_REGS;
return NO_REGS;
}
@@ -4270,7 +4353,7 @@ aarch64_class_max_nregs (reg_class_t regclass, enum machine_mode mode)
{
switch (regclass)
{
- case CORE_REGS:
+ case CALLER_SAVE_REGS:
case POINTER_REGS:
case GENERAL_REGS:
case ALL_REGS:
@@ -4489,18 +4572,19 @@ aarch64_strip_shift (rtx x)
return x;
}
-/* Helper function for rtx cost calculation. Strip a shift or extend
+/* Helper function for rtx cost calculation. Strip an extend
expression from X. Returns the inner operand if successful, or the
original expression on failure. We deal with a number of possible
canonicalization variations here. */
static rtx
-aarch64_strip_shift_or_extend (rtx x)
+aarch64_strip_extend (rtx x)
{
rtx op = x;
/* Zero and sign extraction of a widened value. */
if ((GET_CODE (op) == ZERO_EXTRACT || GET_CODE (op) == SIGN_EXTRACT)
&& XEXP (op, 2) == const0_rtx
+ && GET_CODE (XEXP (op, 0)) == MULT
&& aarch64_is_extend_from_extract (GET_MODE (op), XEXP (XEXP (op, 0), 1),
XEXP (op, 1)))
return XEXP (XEXP (op, 0), 0);
@@ -4529,7 +4613,240 @@ aarch64_strip_shift_or_extend (rtx x)
if (op != x)
return op;
- return aarch64_strip_shift (x);
+ return x;
+}
+
+/* Helper function for rtx cost calculation. Calculate the cost of
+ a MULT, which may be part of a multiply-accumulate rtx. Return
+ the calculated cost of the expression, recursing manually in to
+ operands where needed. */
+
+static int
+aarch64_rtx_mult_cost (rtx x, int code, int outer, bool speed)
+{
+ rtx op0, op1;
+ const struct cpu_cost_table *extra_cost
+ = aarch64_tune_params->insn_extra_cost;
+ int cost = 0;
+ bool maybe_fma = (outer == PLUS || outer == MINUS);
+ enum machine_mode mode = GET_MODE (x);
+
+ gcc_checking_assert (code == MULT);
+
+ op0 = XEXP (x, 0);
+ op1 = XEXP (x, 1);
+
+ if (VECTOR_MODE_P (mode))
+ mode = GET_MODE_INNER (mode);
+
+ /* Integer multiply/fma. */
+ if (GET_MODE_CLASS (mode) == MODE_INT)
+ {
+ /* The multiply will be canonicalized as a shift, cost it as such. */
+ if (CONST_INT_P (op1)
+ && exact_log2 (INTVAL (op1)) > 0)
+ {
+ if (speed)
+ {
+ if (maybe_fma)
+ /* ADD (shifted register). */
+ cost += extra_cost->alu.arith_shift;
+ else
+ /* LSL (immediate). */
+ cost += extra_cost->alu.shift;
+ }
+
+ cost += rtx_cost (op0, GET_CODE (op0), 0, speed);
+
+ return cost;
+ }
+
+ /* Integer multiplies or FMAs have zero/sign extending variants. */
+ if ((GET_CODE (op0) == ZERO_EXTEND
+ && GET_CODE (op1) == ZERO_EXTEND)
+ || (GET_CODE (op0) == SIGN_EXTEND
+ && GET_CODE (op1) == SIGN_EXTEND))
+ {
+ cost += rtx_cost (XEXP (op0, 0), MULT, 0, speed)
+ + rtx_cost (XEXP (op1, 0), MULT, 1, speed);
+
+ if (speed)
+ {
+ if (maybe_fma)
+ /* MADD/SMADDL/UMADDL. */
+ cost += extra_cost->mult[0].extend_add;
+ else
+ /* MUL/SMULL/UMULL. */
+ cost += extra_cost->mult[0].extend;
+ }
+
+ return cost;
+ }
+
+ /* This is either an integer multiply or an FMA. In both cases
+ we want to recurse and cost the operands. */
+ cost += rtx_cost (op0, MULT, 0, speed)
+ + rtx_cost (op1, MULT, 1, speed);
+
+ if (speed)
+ {
+ if (maybe_fma)
+ /* MADD. */
+ cost += extra_cost->mult[mode == DImode].add;
+ else
+ /* MUL. */
+ cost += extra_cost->mult[mode == DImode].simple;
+ }
+
+ return cost;
+ }
+ else
+ {
+ if (speed)
+ {
+ /* Floating-point FMA/FMUL can also support negations of the
+ operands. */
+ if (GET_CODE (op0) == NEG)
+ op0 = XEXP (op0, 0);
+ if (GET_CODE (op1) == NEG)
+ op1 = XEXP (op1, 0);
+
+ if (maybe_fma)
+ /* FMADD/FNMADD/FNMSUB/FMSUB. */
+ cost += extra_cost->fp[mode == DFmode].fma;
+ else
+ /* FMUL/FNMUL. */
+ cost += extra_cost->fp[mode == DFmode].mult;
+ }
+
+ cost += rtx_cost (op0, MULT, 0, speed)
+ + rtx_cost (op1, MULT, 1, speed);
+ return cost;
+ }
+}
+
+static int
+aarch64_address_cost (rtx x,
+ enum machine_mode mode,
+ addr_space_t as ATTRIBUTE_UNUSED,
+ bool speed)
+{
+ enum rtx_code c = GET_CODE (x);
+ const struct cpu_addrcost_table *addr_cost = aarch64_tune_params->addr_cost;
+ struct aarch64_address_info info;
+ int cost = 0;
+ info.shift = 0;
+
+ if (!aarch64_classify_address (&info, x, mode, c, false))
+ {
+ if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF)
+ {
+ /* This is a CONST or SYMBOL ref which will be split
+ in a different way depending on the code model in use.
+ Cost it through the generic infrastructure. */
+ int cost_symbol_ref = rtx_cost (x, MEM, 1, speed);
+ /* Divide through by the cost of one instruction to
+ bring it to the same units as the address costs. */
+ cost_symbol_ref /= COSTS_N_INSNS (1);
+ /* The cost is then the cost of preparing the address,
+ followed by an immediate (possibly 0) offset. */
+ return cost_symbol_ref + addr_cost->imm_offset;
+ }
+ else
+ {
+ /* This is most likely a jump table from a case
+ statement. */
+ return addr_cost->register_offset;
+ }
+ }
+
+ switch (info.type)
+ {
+ case ADDRESS_LO_SUM:
+ case ADDRESS_SYMBOLIC:
+ case ADDRESS_REG_IMM:
+ cost += addr_cost->imm_offset;
+ break;
+
+ case ADDRESS_REG_WB:
+ if (c == PRE_INC || c == PRE_DEC || c == PRE_MODIFY)
+ cost += addr_cost->pre_modify;
+ else if (c == POST_INC || c == POST_DEC || c == POST_MODIFY)
+ cost += addr_cost->post_modify;
+ else
+ gcc_unreachable ();
+
+ break;
+
+ case ADDRESS_REG_REG:
+ cost += addr_cost->register_offset;
+ break;
+
+ case ADDRESS_REG_UXTW:
+ case ADDRESS_REG_SXTW:
+ cost += addr_cost->register_extend;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+
+ if (info.shift > 0)
+ {
+ /* For the sake of calculating the cost of the shifted register
+ component, we can treat same sized modes in the same way. */
+ switch (GET_MODE_BITSIZE (mode))
+ {
+ case 16:
+ cost += addr_cost->addr_scale_costs.hi;
+ break;
+
+ case 32:
+ cost += addr_cost->addr_scale_costs.si;
+ break;
+
+ case 64:
+ cost += addr_cost->addr_scale_costs.di;
+ break;
+
+ /* We can't tell, or this is a 128-bit vector. */
+ default:
+ cost += addr_cost->addr_scale_costs.ti;
+ break;
+ }
+ }
+
+ return cost;
+}
+
+/* Return true if the RTX X in mode MODE is a zero or sign extract
+ usable in an ADD or SUB (extended register) instruction. */
+static bool
+aarch64_rtx_arith_op_extract_p (rtx x, enum machine_mode mode)
+{
+ /* Catch add with a sign extract.
+ This is add_<optab><mode>_multp2. */
+ if (GET_CODE (x) == SIGN_EXTRACT
+ || GET_CODE (x) == ZERO_EXTRACT)
+ {
+ rtx op0 = XEXP (x, 0);
+ rtx op1 = XEXP (x, 1);
+ rtx op2 = XEXP (x, 2);
+
+ if (GET_CODE (op0) == MULT
+ && CONST_INT_P (op1)
+ && op2 == const0_rtx
+ && CONST_INT_P (XEXP (op0, 1))
+ && aarch64_is_extend_from_extract (mode,
+ XEXP (op0, 1),
+ op1))
+ {
+ return true;
+ }
+ }
+
+ return false;
}
/* Calculate the cost of calculating X, storing it in *COST. Result
@@ -4538,13 +4855,31 @@ static bool
aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
int param ATTRIBUTE_UNUSED, int *cost, bool speed)
{
- rtx op0, op1;
+ rtx op0, op1, op2;
const struct cpu_cost_table *extra_cost
= aarch64_tune_params->insn_extra_cost;
+ enum machine_mode mode = GET_MODE (x);
+
+ /* By default, assume that everything has equivalent cost to the
+ cheapest instruction. Any additional costs are applied as a delta
+ above this default. */
+ *cost = COSTS_N_INSNS (1);
+
+ /* TODO: The cost infrastructure currently does not handle
+ vector operations. Assume that all vector operations
+ are equally expensive. */
+ if (VECTOR_MODE_P (mode))
+ {
+ if (speed)
+ *cost += extra_cost->vect.alu;
+ return true;
+ }
switch (code)
{
case SET:
+ /* The cost depends entirely on the operands to SET. */
+ *cost = 0;
op0 = SET_DEST (x);
op1 = SET_SRC (x);
@@ -4552,25 +4887,47 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
{
case MEM:
if (speed)
- *cost += extra_cost->ldst.store;
+ {
+ rtx address = XEXP (op0, 0);
+ if (GET_MODE_CLASS (mode) == MODE_INT)
+ *cost += extra_cost->ldst.store;
+ else if (mode == SFmode)
+ *cost += extra_cost->ldst.storef;
+ else if (mode == DFmode)
+ *cost += extra_cost->ldst.stored;
+
+ *cost +=
+ COSTS_N_INSNS (aarch64_address_cost (address, mode,
+ 0, speed));
+ }
- if (op1 != const0_rtx)
- *cost += rtx_cost (op1, SET, 1, speed);
+ *cost += rtx_cost (op1, SET, 1, speed);
return true;
case SUBREG:
if (! REG_P (SUBREG_REG (op0)))
*cost += rtx_cost (SUBREG_REG (op0), SET, 0, speed);
+
/* Fall through. */
case REG:
- /* Cost is just the cost of the RHS of the set. */
- *cost += rtx_cost (op1, SET, 1, true);
+ /* const0_rtx is in general free, but we will use an
+ instruction to set a register to 0. */
+ if (REG_P (op1) || op1 == const0_rtx)
+ {
+ /* The cost is 1 per register copied. */
+ int n_minus_1 = (GET_MODE_SIZE (GET_MODE (op0)) - 1)
+ / UNITS_PER_WORD;
+ *cost = COSTS_N_INSNS (n_minus_1 + 1);
+ }
+ else
+ /* Cost is just the cost of the RHS of the set. */
+ *cost += rtx_cost (op1, SET, 1, speed);
return true;
- case ZERO_EXTRACT: /* Bit-field insertion. */
+ case ZERO_EXTRACT:
case SIGN_EXTRACT:
- /* Strip any redundant widening of the RHS to meet the width of
- the target. */
+ /* Bit-field insertion. Strip any redundant widening of
+ the RHS to meet the width of the target. */
if (GET_CODE (op1) == SUBREG)
op1 = SUBREG_REG (op1);
if ((GET_CODE (op1) == ZERO_EXTEND
@@ -4579,24 +4936,138 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
&& (GET_MODE_BITSIZE (GET_MODE (XEXP (op1, 0)))
>= INTVAL (XEXP (op0, 1))))
op1 = XEXP (op1, 0);
- *cost += rtx_cost (op1, SET, 1, speed);
+
+ if (CONST_INT_P (op1))
+ {
+ /* MOV immediate is assumed to always be cheap. */
+ *cost = COSTS_N_INSNS (1);
+ }
+ else
+ {
+ /* BFM. */
+ if (speed)
+ *cost += extra_cost->alu.bfi;
+ *cost += rtx_cost (op1, (enum rtx_code) code, 1, speed);
+ }
+
return true;
default:
+ /* We can't make sense of this, assume default cost. */
+ *cost = COSTS_N_INSNS (1);
break;
}
return false;
+ case CONST_INT:
+ /* If an instruction can incorporate a constant within the
+ instruction, the instruction's expression avoids calling
+ rtx_cost() on the constant. If rtx_cost() is called on a
+ constant, then it is usually because the constant must be
+ moved into a register by one or more instructions.
+
+ The exception is constant 0, which can be expressed
+ as XZR/WZR and is therefore free. The exception to this is
+ if we have (set (reg) (const0_rtx)) in which case we must cost
+ the move. However, we can catch that when we cost the SET, so
+ we don't need to consider that here. */
+ if (x == const0_rtx)
+ *cost = 0;
+ else
+ {
+ /* To an approximation, building any other constant is
+ proportionally expensive to the number of instructions
+ required to build that constant. This is true whether we
+ are compiling for SPEED or otherwise. */
+ *cost = COSTS_N_INSNS (aarch64_build_constant (0,
+ INTVAL (x),
+ false));
+ }
+ return true;
+
+ case CONST_DOUBLE:
+ if (speed)
+ {
+ /* mov[df,sf]_aarch64. */
+ if (aarch64_float_const_representable_p (x))
+ /* FMOV (scalar immediate). */
+ *cost += extra_cost->fp[mode == DFmode].fpconst;
+ else if (!aarch64_float_const_zero_rtx_p (x))
+ {
+ /* This will be a load from memory. */
+ if (mode == DFmode)
+ *cost += extra_cost->ldst.loadd;
+ else
+ *cost += extra_cost->ldst.loadf;
+ }
+ else
+ /* Otherwise this is +0.0. We get this using MOVI d0, #0
+ or MOV v0.s[0], wzr - neither of which are modeled by the
+ cost tables. Just use the default cost. */
+ {
+ }
+ }
+
+ return true;
+
case MEM:
if (speed)
- *cost += extra_cost->ldst.load;
+ {
+ /* For loads we want the base cost of a load, plus an
+ approximation for the additional cost of the addressing
+ mode. */
+ rtx address = XEXP (x, 0);
+ if (GET_MODE_CLASS (mode) == MODE_INT)
+ *cost += extra_cost->ldst.load;
+ else if (mode == SFmode)
+ *cost += extra_cost->ldst.loadf;
+ else if (mode == DFmode)
+ *cost += extra_cost->ldst.loadd;
+
+ *cost +=
+ COSTS_N_INSNS (aarch64_address_cost (address, mode,
+ 0, speed));
+ }
return true;
case NEG:
- op0 = CONST0_RTX (GET_MODE (x));
- op1 = XEXP (x, 0);
- goto cost_minus;
+ op0 = XEXP (x, 0);
+
+ if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
+ {
+ if (GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMPARE
+ || GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMM_COMPARE)
+ {
+ /* CSETM. */
+ *cost += rtx_cost (XEXP (op0, 0), NEG, 0, speed);
+ return true;
+ }
+
+ /* Cost this as SUB wzr, X. */
+ op0 = CONST0_RTX (GET_MODE (x));
+ op1 = XEXP (x, 0);
+ goto cost_minus;
+ }
+
+ if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+ {
+ /* Support (neg(fma...)) as a single instruction only if
+ sign of zeros is unimportant. This matches the decision
+ making in aarch64.md. */
+ if (GET_CODE (op0) == FMA && !HONOR_SIGNED_ZEROS (GET_MODE (op0)))
+ {
+ /* FNMADD. */
+ *cost = rtx_cost (op0, NEG, 0, speed);
+ return true;
+ }
+ if (speed)
+ /* FNEG. */
+ *cost += extra_cost->fp[mode == DFmode].neg;
+ return false;
+ }
+
+ return false;
case COMPARE:
op0 = XEXP (x, 0);
@@ -4609,94 +5080,208 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
goto cost_logic;
}
- /* Comparisons can work if the order is swapped.
- Canonicalization puts the more complex operation first, but
- we want it in op1. */
- if (! (REG_P (op0)
- || (GET_CODE (op0) == SUBREG && REG_P (SUBREG_REG (op0)))))
- {
- op0 = XEXP (x, 1);
- op1 = XEXP (x, 0);
- }
- goto cost_minus;
+ if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
+ {
+ /* TODO: A write to the CC flags possibly costs extra, this
+ needs encoding in the cost tables. */
+
+ /* CC_ZESWPmode supports zero extend for free. */
+ if (GET_MODE (x) == CC_ZESWPmode && GET_CODE (op0) == ZERO_EXTEND)
+ op0 = XEXP (op0, 0);
+
+ /* ANDS. */
+ if (GET_CODE (op0) == AND)
+ {
+ x = op0;
+ goto cost_logic;
+ }
+
+ if (GET_CODE (op0) == PLUS)
+ {
+ /* ADDS (and CMN alias). */
+ x = op0;
+ goto cost_plus;
+ }
+
+ if (GET_CODE (op0) == MINUS)
+ {
+ /* SUBS. */
+ x = op0;
+ goto cost_minus;
+ }
+
+ if (GET_CODE (op1) == NEG)
+ {
+ /* CMN. */
+ if (speed)
+ *cost += extra_cost->alu.arith;
+
+ *cost += rtx_cost (op0, COMPARE, 0, speed);
+ *cost += rtx_cost (XEXP (op1, 0), NEG, 1, speed);
+ return true;
+ }
+
+ /* CMP.
+
+ Compare can freely swap the order of operands, and
+ canonicalization puts the more complex operation first.
+ But the integer MINUS logic expects the shift/extend
+ operation in op1. */
+ if (! (REG_P (op0)
+ || (GET_CODE (op0) == SUBREG && REG_P (SUBREG_REG (op0)))))
+ {
+ op0 = XEXP (x, 1);
+ op1 = XEXP (x, 0);
+ }
+ goto cost_minus;
+ }
+
+ if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
+ {
+ /* FCMP. */
+ if (speed)
+ *cost += extra_cost->fp[mode == DFmode].compare;
+
+ if (CONST_DOUBLE_P (op1) && aarch64_float_const_zero_rtx_p (op1))
+ {
+ /* FCMP supports constant 0.0 for no extra cost. */
+ return true;
+ }
+ return false;
+ }
+
+ return false;
case MINUS:
- op0 = XEXP (x, 0);
- op1 = XEXP (x, 1);
+ {
+ op0 = XEXP (x, 0);
+ op1 = XEXP (x, 1);
+
+cost_minus:
+ /* Detect valid immediates. */
+ if ((GET_MODE_CLASS (mode) == MODE_INT
+ || (GET_MODE_CLASS (mode) == MODE_CC
+ && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT))
+ && CONST_INT_P (op1)
+ && aarch64_uimm12_shift (INTVAL (op1)))
+ {
+ *cost += rtx_cost (op0, MINUS, 0, speed);
- cost_minus:
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
- || (GET_MODE_CLASS (GET_MODE (x)) == MODE_CC
- && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT))
- {
- if (op0 != const0_rtx)
+ if (speed)
+ /* SUB(S) (immediate). */
+ *cost += extra_cost->alu.arith;
+ return true;
+
+ }
+
+ /* Look for SUB (extended register). */
+ if (aarch64_rtx_arith_op_extract_p (op1, mode))
+ {
+ if (speed)
+ *cost += extra_cost->alu.arith_shift;
+
+ *cost += rtx_cost (XEXP (XEXP (op1, 0), 0),
+ (enum rtx_code) GET_CODE (op1),
+ 0, speed);
+ return true;
+ }
+
+ rtx new_op1 = aarch64_strip_extend (op1);
+
+ /* Cost this as an FMA-alike operation. */
+ if ((GET_CODE (new_op1) == MULT
+ || GET_CODE (new_op1) == ASHIFT)
+ && code != COMPARE)
+ {
+ *cost += aarch64_rtx_mult_cost (new_op1, MULT,
+ (enum rtx_code) code,
+ speed);
*cost += rtx_cost (op0, MINUS, 0, speed);
+ return true;
+ }
- if (CONST_INT_P (op1))
- {
- if (!aarch64_uimm12_shift (INTVAL (op1)))
- *cost += rtx_cost (op1, MINUS, 1, speed);
- }
- else
- {
- op1 = aarch64_strip_shift_or_extend (op1);
- *cost += rtx_cost (op1, MINUS, 1, speed);
- }
- return true;
- }
+ *cost += rtx_cost (new_op1, MINUS, 1, speed);
- return false;
+ if (speed)
+ {
+ if (GET_MODE_CLASS (mode) == MODE_INT)
+ /* SUB(S). */
+ *cost += extra_cost->alu.arith;
+ else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ /* FSUB. */
+ *cost += extra_cost->fp[mode == DFmode].addsub;
+ }
+ return true;
+ }
case PLUS:
- op0 = XEXP (x, 0);
- op1 = XEXP (x, 1);
+ {
+ rtx new_op0;
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
- {
- if (CONST_INT_P (op1) && aarch64_uimm12_shift (INTVAL (op1)))
- {
- *cost += rtx_cost (op0, PLUS, 0, speed);
- }
- else
- {
- rtx new_op0 = aarch64_strip_shift_or_extend (op0);
+ op0 = XEXP (x, 0);
+ op1 = XEXP (x, 1);
- if (new_op0 == op0
- && GET_CODE (op0) == MULT)
- {
- if ((GET_CODE (XEXP (op0, 0)) == ZERO_EXTEND
- && GET_CODE (XEXP (op0, 1)) == ZERO_EXTEND)
- || (GET_CODE (XEXP (op0, 0)) == SIGN_EXTEND
- && GET_CODE (XEXP (op0, 1)) == SIGN_EXTEND))
- {
- *cost += (rtx_cost (XEXP (XEXP (op0, 0), 0), MULT, 0,
- speed)
- + rtx_cost (XEXP (XEXP (op0, 1), 0), MULT, 1,
- speed)
- + rtx_cost (op1, PLUS, 1, speed));
- if (speed)
- *cost +=
- extra_cost->mult[GET_MODE (x) == DImode].extend_add;
- return true;
- }
+cost_plus:
+ if (GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMPARE
+ || GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMM_COMPARE)
+ {
+ /* CSINC. */
+ *cost += rtx_cost (XEXP (op0, 0), PLUS, 0, speed);
+ *cost += rtx_cost (op1, PLUS, 1, speed);
+ return true;
+ }
- *cost += (rtx_cost (XEXP (op0, 0), MULT, 0, speed)
- + rtx_cost (XEXP (op0, 1), MULT, 1, speed)
- + rtx_cost (op1, PLUS, 1, speed));
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && CONST_INT_P (op1)
+ && aarch64_uimm12_shift (INTVAL (op1)))
+ {
+ *cost += rtx_cost (op0, PLUS, 0, speed);
- if (speed)
- *cost += extra_cost->mult[GET_MODE (x) == DImode].add;
+ if (speed)
+ /* ADD (immediate). */
+ *cost += extra_cost->alu.arith;
+ return true;
+ }
- return true;
- }
+ /* Look for ADD (extended register). */
+ if (aarch64_rtx_arith_op_extract_p (op0, mode))
+ {
+ if (speed)
+ *cost += extra_cost->alu.arith_shift;
- *cost += (rtx_cost (new_op0, PLUS, 0, speed)
- + rtx_cost (op1, PLUS, 1, speed));
- }
- return true;
- }
+ *cost += rtx_cost (XEXP (XEXP (op0, 0), 0),
+ (enum rtx_code) GET_CODE (op0),
+ 0, speed);
+ return true;
+ }
- return false;
+ /* Strip any extend, leave shifts behind as we will
+ cost them through mult_cost. */
+ new_op0 = aarch64_strip_extend (op0);
+
+ if (GET_CODE (new_op0) == MULT
+ || GET_CODE (new_op0) == ASHIFT)
+ {
+ *cost += aarch64_rtx_mult_cost (new_op0, MULT, PLUS,
+ speed);
+ *cost += rtx_cost (op1, PLUS, 1, speed);
+ return true;
+ }
+
+ *cost += (rtx_cost (new_op0, PLUS, 0, speed)
+ + rtx_cost (op1, PLUS, 1, speed));
+
+ if (speed)
+ {
+ if (GET_MODE_CLASS (mode) == MODE_INT)
+ /* ADD. */
+ *cost += extra_cost->alu.arith;
+ else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ /* FADD. */
+ *cost += extra_cost->fp[mode == DFmode].addsub;
+ }
+ return true;
+ }
case BSWAP:
*cost = COSTS_N_INSNS (1);
@@ -4723,117 +5308,252 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
op0 = XEXP (x, 0);
op1 = XEXP (x, 1);
+ if (code == AND
+ && GET_CODE (op0) == MULT
+ && CONST_INT_P (XEXP (op0, 1))
+ && CONST_INT_P (op1)
+ && aarch64_uxt_size (exact_log2 (INTVAL (XEXP (op0, 1))),
+ INTVAL (op1)) != 0)
+ {
+ /* This is a UBFM/SBFM. */
+ *cost += rtx_cost (XEXP (op0, 0), ZERO_EXTRACT, 0, speed);
+ if (speed)
+ *cost += extra_cost->alu.bfx;
+ return true;
+ }
+
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
{
+ /* We possibly get the immediate for free, this is not
+ modelled. */
if (CONST_INT_P (op1)
&& aarch64_bitmask_imm (INTVAL (op1), GET_MODE (x)))
{
- *cost += rtx_cost (op0, AND, 0, speed);
+ *cost += rtx_cost (op0, (enum rtx_code) code, 0, speed);
+
+ if (speed)
+ *cost += extra_cost->alu.logical;
+
+ return true;
}
else
{
+ rtx new_op0 = op0;
+
+ /* Handle ORN, EON, or BIC. */
if (GET_CODE (op0) == NOT)
op0 = XEXP (op0, 0);
- op0 = aarch64_strip_shift (op0);
- *cost += (rtx_cost (op0, AND, 0, speed)
- + rtx_cost (op1, AND, 1, speed));
+
+ new_op0 = aarch64_strip_shift (op0);
+
+ /* If we had a shift on op0 then this is a logical-shift-
+ by-register/immediate operation. Otherwise, this is just
+ a logical operation. */
+ if (speed)
+ {
+ if (new_op0 != op0)
+ {
+ /* Shift by immediate. */
+ if (CONST_INT_P (XEXP (op0, 1)))
+ *cost += extra_cost->alu.log_shift;
+ else
+ *cost += extra_cost->alu.log_shift_reg;
+ }
+ else
+ *cost += extra_cost->alu.logical;
+ }
+
+ /* In both cases we want to cost both operands. */
+ *cost += rtx_cost (new_op0, (enum rtx_code) code, 0, speed)
+ + rtx_cost (op1, (enum rtx_code) code, 1, speed);
+
+ return true;
}
- return true;
}
return false;
+ case NOT:
+ /* MVN. */
+ if (speed)
+ *cost += extra_cost->alu.logical;
+
+ /* The logical instruction could have the shifted register form,
+ but the cost is the same if the shift is processed as a separate
+ instruction, so we don't bother with it here. */
+ return false;
+
case ZERO_EXTEND:
- if ((GET_MODE (x) == DImode
- && GET_MODE (XEXP (x, 0)) == SImode)
- || GET_CODE (XEXP (x, 0)) == MEM)
+
+ op0 = XEXP (x, 0);
+ /* If a value is written in SI mode, then zero extended to DI
+ mode, the operation will in general be free as a write to
+ a 'w' register implicitly zeroes the upper bits of an 'x'
+ register. However, if this is
+
+ (set (reg) (zero_extend (reg)))
+
+ we must cost the explicit register move. */
+ if (mode == DImode
+ && GET_MODE (op0) == SImode
+ && outer == SET)
+ {
+ int op_cost = rtx_cost (XEXP (x, 0), ZERO_EXTEND, 0, speed);
+
+ if (!op_cost && speed)
+ /* MOV. */
+ *cost += extra_cost->alu.extend;
+ else
+ /* Free, the cost is that of the SI mode operation. */
+ *cost = op_cost;
+
+ return true;
+ }
+ else if (MEM_P (XEXP (x, 0)))
{
- *cost += rtx_cost (XEXP (x, 0), ZERO_EXTEND, 0, speed);
+ /* All loads can zero extend to any size for free. */
+ *cost = rtx_cost (XEXP (x, 0), ZERO_EXTEND, param, speed);
return true;
}
+
+ /* UXTB/UXTH. */
+ if (speed)
+ *cost += extra_cost->alu.extend;
+
return false;
case SIGN_EXTEND:
- if (GET_CODE (XEXP (x, 0)) == MEM)
+ if (MEM_P (XEXP (x, 0)))
{
- *cost += rtx_cost (XEXP (x, 0), SIGN_EXTEND, 0, speed);
+ /* LDRSH. */
+ if (speed)
+ {
+ rtx address = XEXP (XEXP (x, 0), 0);
+ *cost += extra_cost->ldst.load_sign_extend;
+
+ *cost +=
+ COSTS_N_INSNS (aarch64_address_cost (address, mode,
+ 0, speed));
+ }
return true;
}
+
+ if (speed)
+ *cost += extra_cost->alu.extend;
return false;
- case ROTATE:
- if (!CONST_INT_P (XEXP (x, 1)))
- *cost += COSTS_N_INSNS (2);
- /* Fall through. */
- case ROTATERT:
- case LSHIFTRT:
case ASHIFT:
- case ASHIFTRT:
-
- /* Shifting by a register often takes an extra cycle. */
- if (speed && !CONST_INT_P (XEXP (x, 1)))
- *cost += extra_cost->alu.arith_shift_reg;
+ op0 = XEXP (x, 0);
+ op1 = XEXP (x, 1);
- *cost += rtx_cost (XEXP (x, 0), ASHIFT, 0, speed);
- return true;
+ if (CONST_INT_P (op1))
+ {
+ /* LSL (immediate), UBMF, UBFIZ and friends. These are all
+ aliases. */
+ if (speed)
+ *cost += extra_cost->alu.shift;
- case HIGH:
- if (!CONSTANT_P (XEXP (x, 0)))
- *cost += rtx_cost (XEXP (x, 0), HIGH, 0, speed);
- return true;
+ /* We can incorporate zero/sign extend for free. */
+ if (GET_CODE (op0) == ZERO_EXTEND
+ || GET_CODE (op0) == SIGN_EXTEND)
+ op0 = XEXP (op0, 0);
- case LO_SUM:
- if (!CONSTANT_P (XEXP (x, 1)))
- *cost += rtx_cost (XEXP (x, 1), LO_SUM, 1, speed);
- *cost += rtx_cost (XEXP (x, 0), LO_SUM, 0, speed);
- return true;
+ *cost += rtx_cost (op0, ASHIFT, 0, speed);
+ return true;
+ }
+ else
+ {
+ /* LSLV. */
+ if (speed)
+ *cost += extra_cost->alu.shift_reg;
- case ZERO_EXTRACT:
- case SIGN_EXTRACT:
- *cost += rtx_cost (XEXP (x, 0), ZERO_EXTRACT, 0, speed);
- return true;
+ return false; /* All arguments need to be in registers. */
+ }
- case MULT:
+ case ROTATE:
+ case ROTATERT:
+ case LSHIFTRT:
+ case ASHIFTRT:
op0 = XEXP (x, 0);
op1 = XEXP (x, 1);
- *cost = COSTS_N_INSNS (1);
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
+ if (CONST_INT_P (op1))
{
- if (CONST_INT_P (op1)
- && exact_log2 (INTVAL (op1)) > 0)
- {
- *cost += rtx_cost (op0, ASHIFT, 0, speed);
- return true;
- }
+ /* ASR (immediate) and friends. */
+ if (speed)
+ *cost += extra_cost->alu.shift;
- if ((GET_CODE (op0) == ZERO_EXTEND
- && GET_CODE (op1) == ZERO_EXTEND)
- || (GET_CODE (op0) == SIGN_EXTEND
- && GET_CODE (op1) == SIGN_EXTEND))
- {
- *cost += (rtx_cost (XEXP (op0, 0), MULT, 0, speed)
- + rtx_cost (XEXP (op1, 0), MULT, 1, speed));
- if (speed)
- *cost += extra_cost->mult[GET_MODE (x) == DImode].extend;
- return true;
- }
+ *cost += rtx_cost (op0, (enum rtx_code) code, 0, speed);
+ return true;
+ }
+ else
+ {
+ /* ASR (register) and friends. */
if (speed)
- *cost += extra_cost->mult[GET_MODE (x) == DImode].simple;
+ *cost += extra_cost->alu.shift_reg;
+
+ return false; /* All arguments need to be in registers. */
}
- else if (speed)
+
+ case SYMBOL_REF:
+
+ if (aarch64_cmodel == AARCH64_CMODEL_LARGE)
{
- if (GET_MODE (x) == DFmode)
- *cost += extra_cost->fp[1].mult;
- else if (GET_MODE (x) == SFmode)
- *cost += extra_cost->fp[0].mult;
+ /* LDR. */
+ if (speed)
+ *cost += extra_cost->ldst.load;
+ }
+ else if (aarch64_cmodel == AARCH64_CMODEL_SMALL
+ || aarch64_cmodel == AARCH64_CMODEL_SMALL_PIC)
+ {
+ /* ADRP, followed by ADD. */
+ *cost += COSTS_N_INSNS (1);
+ if (speed)
+ *cost += 2 * extra_cost->alu.arith;
+ }
+ else if (aarch64_cmodel == AARCH64_CMODEL_TINY
+ || aarch64_cmodel == AARCH64_CMODEL_TINY_PIC)
+ {
+ /* ADR. */
+ if (speed)
+ *cost += extra_cost->alu.arith;
}
- return false; /* All arguments need to be in registers. */
+ if (flag_pic)
+ {
+ /* One extra load instruction, after accessing the GOT. */
+ *cost += COSTS_N_INSNS (1);
+ if (speed)
+ *cost += extra_cost->ldst.load;
+ }
+ return true;
+
+ case HIGH:
+ case LO_SUM:
+ /* ADRP/ADD (immediate). */
+ if (speed)
+ *cost += extra_cost->alu.arith;
+ return true;
+
+ case ZERO_EXTRACT:
+ case SIGN_EXTRACT:
+ /* UBFX/SBFX. */
+ if (speed)
+ *cost += extra_cost->alu.bfx;
+
+ /* We can trust that the immediates used will be correct (there
+ are no by-register forms), so we need only cost op0. */
+ *cost += rtx_cost (XEXP (x, 0), (enum rtx_code) code, 0, speed);
+ return true;
+
+ case MULT:
+ *cost += aarch64_rtx_mult_cost (x, MULT, 0, speed);
+ /* aarch64_rtx_mult_cost always handles recursion to its
+ operands. */
+ return true;
case MOD:
case UMOD:
- *cost = COSTS_N_INSNS (2);
if (speed)
{
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
@@ -4850,53 +5570,237 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED,
case DIV:
case UDIV:
- *cost = COSTS_N_INSNS (1);
+ case SQRT:
if (speed)
{
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
- *cost += extra_cost->mult[GET_MODE (x) == DImode].idiv;
- else if (GET_MODE (x) == DFmode)
- *cost += extra_cost->fp[1].div;
- else if (GET_MODE (x) == SFmode)
- *cost += extra_cost->fp[0].div;
+ if (GET_MODE_CLASS (mode) == MODE_INT)
+ /* There is no integer SQRT, so only DIV and UDIV can get
+ here. */
+ *cost += extra_cost->mult[mode == DImode].idiv;
+ else
+ *cost += extra_cost->fp[mode == DFmode].div;
}
return false; /* All arguments need to be in registers. */
+ case IF_THEN_ELSE:
+ op2 = XEXP (x, 2);
+ op0 = XEXP (x, 0);
+ op1 = XEXP (x, 1);
+
+ if (GET_CODE (op1) == PC || GET_CODE (op2) == PC)
+ {
+ /* Conditional branch. */
+ if (GET_MODE_CLASS (GET_MODE (XEXP (op0, 0))) == MODE_CC)
+ return true;
+ else
+ {
+ if (GET_CODE (op0) == NE
+ || GET_CODE (op0) == EQ)
+ {
+ rtx inner = XEXP (op0, 0);
+ rtx comparator = XEXP (op0, 1);
+
+ if (comparator == const0_rtx)
+ {
+ /* TBZ/TBNZ/CBZ/CBNZ. */
+ if (GET_CODE (inner) == ZERO_EXTRACT)
+ /* TBZ/TBNZ. */
+ *cost += rtx_cost (XEXP (inner, 0), ZERO_EXTRACT,
+ 0, speed);
+ else
+ /* CBZ/CBNZ. */
+ *cost += rtx_cost (inner, GET_CODE (op0), 0, speed);
+
+ return true;
+ }
+ }
+ else if (GET_CODE (op0) == LT
+ || GET_CODE (op0) == GE)
+ {
+ rtx comparator = XEXP (op0, 1);
+
+ /* TBZ/TBNZ. */
+ if (comparator == const0_rtx)
+ return true;
+ }
+ }
+ }
+ else if (GET_MODE_CLASS (GET_MODE (XEXP (op0, 0))) == MODE_CC)
+ {
+ /* It's a conditional operation based on the status flags,
+ so it must be some flavor of CSEL. */
+
+ /* CSNEG, CSINV, and CSINC are handled for free as part of CSEL. */
+ if (GET_CODE (op1) == NEG
+ || GET_CODE (op1) == NOT
+ || (GET_CODE (op1) == PLUS && XEXP (op1, 1) == const1_rtx))
+ op1 = XEXP (op1, 0);
+
+ *cost += rtx_cost (op1, IF_THEN_ELSE, 1, speed);
+ *cost += rtx_cost (op2, IF_THEN_ELSE, 2, speed);
+ return true;
+ }
+
+ /* We don't know what this is, cost all operands. */
+ return false;
+
+ case EQ:
+ case NE:
+ case GT:
+ case GTU:
+ case LT:
+ case LTU:
+ case GE:
+ case GEU:
+ case LE:
+ case LEU:
+
+ return false; /* All arguments must be in registers. */
+
+ case FMA:
+ op0 = XEXP (x, 0);
+ op1 = XEXP (x, 1);
+ op2 = XEXP (x, 2);
+
+ if (speed)
+ *cost += extra_cost->fp[mode == DFmode].fma;
+
+ /* FMSUB, FNMADD, and FNMSUB are free. */
+ if (GET_CODE (op0) == NEG)
+ op0 = XEXP (op0, 0);
+
+ if (GET_CODE (op2) == NEG)
+ op2 = XEXP (op2, 0);
+
+ /* aarch64_fnma4_elt_to_64v2df has the NEG as operand 1,
+ and the by-element operand as operand 0. */
+ if (GET_CODE (op1) == NEG)
+ op1 = XEXP (op1, 0);
+
+ /* Catch vector-by-element operations. The by-element operand can
+ either be (vec_duplicate (vec_select (x))) or just
+ (vec_select (x)), depending on whether we are multiplying by
+ a vector or a scalar.
+
+ Canonicalization is not very good in these cases, FMA4 will put the
+ by-element operand as operand 0, FNMA4 will have it as operand 1. */
+ if (GET_CODE (op0) == VEC_DUPLICATE)
+ op0 = XEXP (op0, 0);
+ else if (GET_CODE (op1) == VEC_DUPLICATE)
+ op1 = XEXP (op1, 0);
+
+ if (GET_CODE (op0) == VEC_SELECT)
+ op0 = XEXP (op0, 0);
+ else if (GET_CODE (op1) == VEC_SELECT)
+ op1 = XEXP (op1, 0);
+
+ /* If the remaining parameters are not registers,
+ get the cost to put them into registers. */
+ *cost += rtx_cost (op0, FMA, 0, speed);
+ *cost += rtx_cost (op1, FMA, 1, speed);
+ *cost += rtx_cost (op2, FMA, 2, speed);
+ return true;
+
+ case FLOAT_EXTEND:
+ if (speed)
+ *cost += extra_cost->fp[mode == DFmode].widen;
+ return false;
+
+ case FLOAT_TRUNCATE:
+ if (speed)
+ *cost += extra_cost->fp[mode == DFmode].narrow;
+ return false;
+
+ case ABS:
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ /* FABS and FNEG are analogous. */
+ if (speed)
+ *cost += extra_cost->fp[mode == DFmode].neg;
+ }
+ else
+ {
+ /* Integer ABS will either be split to
+ two arithmetic instructions, or will be an ABS
+ (scalar), which we don't model. */
+ *cost = COSTS_N_INSNS (2);
+ if (speed)
+ *cost += 2 * extra_cost->alu.arith;
+ }
+ return false;
+
+ case SMAX:
+ case SMIN:
+ if (speed)
+ {
+ /* FMAXNM/FMINNM/FMAX/FMIN.
+ TODO: This may not be accurate for all implementations, but
+ we do not model this in the cost tables. */
+ *cost += extra_cost->fp[mode == DFmode].addsub;
+ }
+ return false;
+
+ case TRUNCATE:
+
+ /* Decompose <su>muldi3_highpart. */
+ if (/* (truncate:DI */
+ mode == DImode
+ /* (lshiftrt:TI */
+ && GET_MODE (XEXP (x, 0)) == TImode
+ && GET_CODE (XEXP (x, 0)) == LSHIFTRT
+ /* (mult:TI */
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
+ /* (ANY_EXTEND:TI (reg:DI))
+ (ANY_EXTEND:TI (reg:DI))) */
+ && ((GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND
+ && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == ZERO_EXTEND)
+ || (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND
+ && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == SIGN_EXTEND))
+ && GET_MODE (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 0)) == DImode
+ && GET_MODE (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 1), 0)) == DImode
+ /* (const_int 64) */
+ && CONST_INT_P (XEXP (XEXP (x, 0), 1))
+ && UINTVAL (XEXP (XEXP (x, 0), 1)) == 64)
+ {
+ /* UMULH/SMULH. */
+ if (speed)
+ *cost += extra_cost->mult[mode == DImode].extend;
+ *cost += rtx_cost (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 0),
+ MULT, 0, speed);
+ *cost += rtx_cost (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 1), 0),
+ MULT, 1, speed);
+ return true;
+ }
+
+ /* Fall through. */
default:
- break;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "\nFailed to cost RTX. Assuming default cost.\n");
+
+ return true;
}
return false;
}
-static int
-aarch64_address_cost (rtx x ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- addr_space_t as ATTRIBUTE_UNUSED, bool speed ATTRIBUTE_UNUSED)
+/* Wrapper around aarch64_rtx_costs, dumps the partial, or total cost
+ calculated for X. This cost is stored in *COST. Returns true
+ if the total cost of X was calculated. */
+static bool
+aarch64_rtx_costs_wrapper (rtx x, int code, int outer,
+ int param, int *cost, bool speed)
{
- enum rtx_code c = GET_CODE (x);
- const struct cpu_addrcost_table *addr_cost = aarch64_tune_params->addr_cost;
-
- if (c == PRE_INC || c == PRE_DEC || c == PRE_MODIFY)
- return addr_cost->pre_modify;
-
- if (c == POST_INC || c == POST_DEC || c == POST_MODIFY)
- return addr_cost->post_modify;
+ bool result = aarch64_rtx_costs (x, code, outer, param, cost, speed);
- if (c == PLUS)
+ if (dump_file && (dump_flags & TDF_DETAILS))
{
- if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- return addr_cost->imm_offset;
- else if (GET_CODE (XEXP (x, 0)) == MULT
- || GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
- || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)
- return addr_cost->register_extend;
-
- return addr_cost->register_offset;
+ print_rtl_single (dump_file, x);
+ fprintf (dump_file, "\n%s cost: %d (%s)\n",
+ speed ? "Hot" : "Cold",
+ *cost, result ? "final" : "partial");
}
- else if (c == MEM || c == LABEL_REF || c == SYMBOL_REF)
- return addr_cost->imm_offset;
- return 0;
+ return result;
}
static int
@@ -5324,7 +6228,7 @@ static struct machine_function *
aarch64_init_machine_status (void)
{
struct machine_function *machine;
- machine = ggc_alloc_cleared_machine_function ();
+ machine = ggc_cleared_alloc<machine_function> ();
return machine;
}
@@ -7563,6 +8467,9 @@ aarch64_float_const_representable_p (rtx x)
if (!CONST_DOUBLE_P (x))
return false;
+ if (GET_MODE (x) == VOIDmode)
+ return false;
+
REAL_VALUE_FROM_CONST_DOUBLE (r, x);
/* We cannot represent infinities, NaNs or +/-zero. We won't
@@ -8087,6 +8994,70 @@ aarch64_evpc_zip (struct expand_vec_perm_d *d)
return true;
}
+/* Recognize patterns for the EXT insn. */
+
+static bool
+aarch64_evpc_ext (struct expand_vec_perm_d *d)
+{
+ unsigned int i, nelt = d->nelt;
+ rtx (*gen) (rtx, rtx, rtx, rtx);
+ rtx offset;
+
+ unsigned int location = d->perm[0]; /* Always < nelt. */
+
+ /* Check if the extracted indices are increasing by one. */
+ for (i = 1; i < nelt; i++)
+ {
+ unsigned int required = location + i;
+ if (d->one_vector_p)
+ {
+ /* We'll pass the same vector in twice, so allow indices to wrap. */
+ required &= (nelt - 1);
+ }
+ if (d->perm[i] != required)
+ return false;
+ }
+
+ /* The mid-end handles masks that just return one of the input vectors. */
+ gcc_assert (location != 0);
+
+ switch (d->vmode)
+ {
+ case V16QImode: gen = gen_aarch64_extv16qi; break;
+ case V8QImode: gen = gen_aarch64_extv8qi; break;
+ case V4HImode: gen = gen_aarch64_extv4hi; break;
+ case V8HImode: gen = gen_aarch64_extv8hi; break;
+ case V2SImode: gen = gen_aarch64_extv2si; break;
+ case V4SImode: gen = gen_aarch64_extv4si; break;
+ case V2SFmode: gen = gen_aarch64_extv2sf; break;
+ case V4SFmode: gen = gen_aarch64_extv4sf; break;
+ case V2DImode: gen = gen_aarch64_extv2di; break;
+ case V2DFmode: gen = gen_aarch64_extv2df; break;
+ default:
+ return false;
+ }
+
+ /* Success! */
+ if (d->testing_p)
+ return true;
+
+ if (BYTES_BIG_ENDIAN)
+ {
+ /* After setup, we want the high elements of the first vector (stored
+ at the LSB end of the register), and the low elements of the second
+ vector (stored at the MSB end of the register). So swap. */
+ rtx temp = d->op0;
+ d->op0 = d->op1;
+ d->op1 = temp;
+ /* location != 0 (above), so safe to assume (nelt - location) < nelt. */
+ location = nelt - location;
+ }
+
+ offset = GEN_INT (location);
+ emit_insn (gen (d->target, d->op0, d->op1, offset));
+ return true;
+}
+
static bool
aarch64_evpc_dup (struct expand_vec_perm_d *d)
{
@@ -8191,7 +9162,9 @@ aarch64_expand_vec_perm_const_1 (struct expand_vec_perm_d *d)
if (TARGET_SIMD)
{
- if (aarch64_evpc_zip (d))
+ if (aarch64_evpc_ext (d))
+ return true;
+ else if (aarch64_evpc_zip (d))
return true;
else if (aarch64_evpc_uzp (d))
return true;
@@ -8539,7 +9512,7 @@ aarch64_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
#define TARGET_RETURN_IN_MSB aarch64_return_in_msb
#undef TARGET_RTX_COSTS
-#define TARGET_RTX_COSTS aarch64_rtx_costs
+#define TARGET_RTX_COSTS aarch64_rtx_costs_wrapper
#undef TARGET_SCHED_ISSUE_RATE
#define TARGET_SCHED_ISSUE_RATE aarch64_sched_issue_rate
@@ -8577,6 +9550,10 @@ aarch64_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
#define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES \
aarch64_autovectorize_vector_sizes
+#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
+#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV \
+ aarch64_atomic_assign_expand_fenv
+
/* Section anchor support. */
#undef TARGET_MIN_ANCHOR_OFFSET
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index c9b30d01865..ced5a5e9252 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -408,7 +408,7 @@ extern unsigned long aarch64_tune_flags;
enum reg_class
{
NO_REGS,
- CORE_REGS,
+ CALLER_SAVE_REGS,
GENERAL_REGS,
STACK_REG,
POINTER_REGS,
@@ -423,7 +423,7 @@ enum reg_class
#define REG_CLASS_NAMES \
{ \
"NO_REGS", \
- "CORE_REGS", \
+ "CALLER_SAVE_REGS", \
"GENERAL_REGS", \
"STACK_REG", \
"POINTER_REGS", \
@@ -435,7 +435,7 @@ enum reg_class
#define REG_CLASS_CONTENTS \
{ \
{ 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
- { 0x7fffffff, 0x00000000, 0x00000003 }, /* CORE_REGS */ \
+ { 0x0007ffff, 0x00000000, 0x00000000 }, /* CALLER_SAVE_REGS */ \
{ 0x7fffffff, 0x00000000, 0x00000003 }, /* GENERAL_REGS */ \
{ 0x80000000, 0x00000000, 0x00000000 }, /* STACK_REG */ \
{ 0xffffffff, 0x00000000, 0x00000003 }, /* POINTER_REGS */ \
@@ -446,7 +446,7 @@ enum reg_class
#define REGNO_REG_CLASS(REGNO) aarch64_regno_regclass (REGNO)
-#define INDEX_REG_CLASS CORE_REGS
+#define INDEX_REG_CLASS GENERAL_REGS
#define BASE_REG_CLASS POINTER_REGS
/* Register pairs used to eliminate unneeded registers that point into
@@ -824,6 +824,11 @@ do { \
#define SHIFT_COUNT_TRUNCATED !TARGET_SIMD
+/* Choose appropriate mode for caller saves, so we do the minimum
+ required size of load/store. */
+#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
+ aarch64_hard_regno_caller_save_mode ((REGNO), (NREGS), (MODE))
+
/* Callee only saves lower 64-bits of a 128-bit register. Tell the
compiler the callee clobbers the top 64-bits when restoring the
bottom 64-bits. */
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 266d7873a5a..6e605c19f0a 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -112,6 +112,10 @@
(define_c_enum "unspecv" [
UNSPECV_EH_RETURN ; Represent EH_RETURN
+ UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
+ UNSPECV_SET_FPCR ; Represent assign of FPCR content.
+ UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
+ UNSPECV_SET_FPSR ; Represent assign of FPSR content.
]
)
@@ -519,6 +523,10 @@
(use (match_operand 2 "" ""))])]
""
{
+ if (!REG_P (XEXP (operands[0], 0))
+ && (GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF))
+ XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0));
+
if (operands[2] == NULL_RTX)
operands[2] = const0_rtx;
}
@@ -532,31 +540,38 @@
(use (match_operand 3 "" ""))])]
""
{
+ if (!REG_P (XEXP (operands[1], 0))
+ && (GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF))
+ XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
+
if (operands[3] == NULL_RTX)
operands[3] = const0_rtx;
}
)
(define_insn "*sibcall_insn"
- [(call (mem:DI (match_operand:DI 0 "" "X"))
+ [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
(match_operand 1 "" ""))
(return)
(use (match_operand 2 "" ""))]
- "GET_CODE (operands[0]) == SYMBOL_REF"
- "b\\t%a0"
- [(set_attr "type" "branch")]
-
+ "SIBLING_CALL_P (insn)"
+ "@
+ br\\t%0
+ b\\t%a0"
+ [(set_attr "type" "branch, branch")]
)
(define_insn "*sibcall_value_insn"
[(set (match_operand 0 "" "")
- (call (mem:DI (match_operand 1 "" "X"))
+ (call (mem:DI (match_operand 1 "aarch64_call_insn_operand" "Ucs, Usf"))
(match_operand 2 "" "")))
(return)
(use (match_operand 3 "" ""))]
- "GET_CODE (operands[1]) == SYMBOL_REF"
- "b\\t%a1"
- [(set_attr "type" "branch")]
+ "SIBLING_CALL_P (insn)"
+ "@
+ br\\t%1
+ b\\t%a1"
+ [(set_attr "type" "branch, branch")]
)
;; Call subroutine returning any type.
@@ -3844,7 +3859,7 @@
UNSPEC_SP_SET))
(set (match_scratch:PTR 2 "=&r") (const_int 0))]
""
- "ldr\\t%x2, %1\;str\\t%x2, %0\;mov\t%x2,0"
+ "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
[(set_attr "length" "12")
(set_attr "type" "multiple")])
@@ -3854,11 +3869,11 @@
(match_operand 2)]
""
{
-
- rtx result = gen_reg_rtx (Pmode);
-
+ rtx result;
enum machine_mode mode = GET_MODE (operands[0]);
+ result = gen_reg_rtx(mode);
+
emit_insn ((mode == DImode
? gen_stack_protect_test_di
: gen_stack_protect_test_si) (result,
@@ -3881,10 +3896,41 @@
UNSPEC_SP_TEST))
(clobber (match_scratch:PTR 3 "=&r"))]
""
- "ldr\t%x3, %x1\;ldr\t%x0, %x2\;eor\t%x0, %x3, %x0"
+ "ldr\t%<w>3, %x1\;ldr\t%<w>0, %x2\;eor\t%<w>0, %<w>3, %<w>0"
[(set_attr "length" "12")
(set_attr "type" "multiple")])
+;; Write Floating-point Control Register.
+(define_insn "set_fpcr"
+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
+ ""
+ "msr\\tfpcr, %0"
+ [(set_attr "type" "mrs")])
+
+;; Read Floating-point Control Register.
+(define_insn "get_fpcr"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
+ ""
+ "mrs\\t%0, fpcr"
+ [(set_attr "type" "mrs")])
+
+;; Write Floating-point Status Register.
+(define_insn "set_fpsr"
+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
+ ""
+ "msr\\tfpsr, %0"
+ [(set_attr "type" "mrs")])
+
+;; Read Floating-point Status Register.
+(define_insn "get_fpsr"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
+ ""
+ "mrs\\t%0, fpsr"
+ [(set_attr "type" "mrs")])
+
+
;; AdvSIMD Stuff
(include "aarch64-simd.md")
diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
index 5ef189129c4..c4b5731996c 100644
--- a/gcc/config/aarch64/arm_neon.h
+++ b/gcc/config/aarch64/arm_neon.h
@@ -5661,318 +5661,6 @@ vcvtxd_f32_f64 (float64_t a)
return result;
}
-#define vext_f32(a, b, c) \
- __extension__ \
- ({ \
- float32x2_t b_ = (b); \
- float32x2_t a_ = (a); \
- float32x2_t result; \
- __asm__ ("ext %0.8b, %1.8b, %2.8b, #%3*4" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vext_f64(a, b, c) \
- __extension__ \
- ({ \
- float64x1_t b_ = (b); \
- float64x1_t a_ = (a); \
- float64x1_t result; \
- __asm__ ("ext %0.8b, %1.8b, %2.8b, #%3*8" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vext_p8(a, b, c) \
- __extension__ \
- ({ \
- poly8x8_t b_ = (b); \
- poly8x8_t a_ = (a); \
- poly8x8_t result; \
- __asm__ ("ext %0.8b,%1.8b,%2.8b,%3" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vext_p16(a, b, c) \
- __extension__ \
- ({ \
- poly16x4_t b_ = (b); \
- poly16x4_t a_ = (a); \
- poly16x4_t result; \
- __asm__ ("ext %0.8b, %1.8b, %2.8b, #%3*2" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vext_s8(a, b, c) \
- __extension__ \
- ({ \
- int8x8_t b_ = (b); \
- int8x8_t a_ = (a); \
- int8x8_t result; \
- __asm__ ("ext %0.8b,%1.8b,%2.8b,%3" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vext_s16(a, b, c) \
- __extension__ \
- ({ \
- int16x4_t b_ = (b); \
- int16x4_t a_ = (a); \
- int16x4_t result; \
- __asm__ ("ext %0.8b, %1.8b, %2.8b, #%3*2" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vext_s32(a, b, c) \
- __extension__ \
- ({ \
- int32x2_t b_ = (b); \
- int32x2_t a_ = (a); \
- int32x2_t result; \
- __asm__ ("ext %0.8b, %1.8b, %2.8b, #%3*4" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vext_s64(a, b, c) \
- __extension__ \
- ({ \
- int64x1_t b_ = (b); \
- int64x1_t a_ = (a); \
- int64x1_t result; \
- __asm__ ("ext %0.8b, %1.8b, %2.8b, #%3*8" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vext_u8(a, b, c) \
- __extension__ \
- ({ \
- uint8x8_t b_ = (b); \
- uint8x8_t a_ = (a); \
- uint8x8_t result; \
- __asm__ ("ext %0.8b,%1.8b,%2.8b,%3" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vext_u16(a, b, c) \
- __extension__ \
- ({ \
- uint16x4_t b_ = (b); \
- uint16x4_t a_ = (a); \
- uint16x4_t result; \
- __asm__ ("ext %0.8b, %1.8b, %2.8b, #%3*2" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vext_u32(a, b, c) \
- __extension__ \
- ({ \
- uint32x2_t b_ = (b); \
- uint32x2_t a_ = (a); \
- uint32x2_t result; \
- __asm__ ("ext %0.8b, %1.8b, %2.8b, #%3*4" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vext_u64(a, b, c) \
- __extension__ \
- ({ \
- uint64x1_t b_ = (b); \
- uint64x1_t a_ = (a); \
- uint64x1_t result; \
- __asm__ ("ext %0.8b, %1.8b, %2.8b, #%3*8" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vextq_f32(a, b, c) \
- __extension__ \
- ({ \
- float32x4_t b_ = (b); \
- float32x4_t a_ = (a); \
- float32x4_t result; \
- __asm__ ("ext %0.16b, %1.16b, %2.16b, #%3*4" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vextq_f64(a, b, c) \
- __extension__ \
- ({ \
- float64x2_t b_ = (b); \
- float64x2_t a_ = (a); \
- float64x2_t result; \
- __asm__ ("ext %0.16b, %1.16b, %2.16b, #%3*8" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vextq_p8(a, b, c) \
- __extension__ \
- ({ \
- poly8x16_t b_ = (b); \
- poly8x16_t a_ = (a); \
- poly8x16_t result; \
- __asm__ ("ext %0.16b, %1.16b, %2.16b, #%3" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vextq_p16(a, b, c) \
- __extension__ \
- ({ \
- poly16x8_t b_ = (b); \
- poly16x8_t a_ = (a); \
- poly16x8_t result; \
- __asm__ ("ext %0.16b, %1.16b, %2.16b, #%3*2" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vextq_s8(a, b, c) \
- __extension__ \
- ({ \
- int8x16_t b_ = (b); \
- int8x16_t a_ = (a); \
- int8x16_t result; \
- __asm__ ("ext %0.16b, %1.16b, %2.16b, #%3" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vextq_s16(a, b, c) \
- __extension__ \
- ({ \
- int16x8_t b_ = (b); \
- int16x8_t a_ = (a); \
- int16x8_t result; \
- __asm__ ("ext %0.16b, %1.16b, %2.16b, #%3*2" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vextq_s32(a, b, c) \
- __extension__ \
- ({ \
- int32x4_t b_ = (b); \
- int32x4_t a_ = (a); \
- int32x4_t result; \
- __asm__ ("ext %0.16b, %1.16b, %2.16b, #%3*4" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vextq_s64(a, b, c) \
- __extension__ \
- ({ \
- int64x2_t b_ = (b); \
- int64x2_t a_ = (a); \
- int64x2_t result; \
- __asm__ ("ext %0.16b, %1.16b, %2.16b, #%3*8" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vextq_u8(a, b, c) \
- __extension__ \
- ({ \
- uint8x16_t b_ = (b); \
- uint8x16_t a_ = (a); \
- uint8x16_t result; \
- __asm__ ("ext %0.16b, %1.16b, %2.16b, #%3" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vextq_u16(a, b, c) \
- __extension__ \
- ({ \
- uint16x8_t b_ = (b); \
- uint16x8_t a_ = (a); \
- uint16x8_t result; \
- __asm__ ("ext %0.16b, %1.16b, %2.16b, #%3*2" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vextq_u32(a, b, c) \
- __extension__ \
- ({ \
- uint32x4_t b_ = (b); \
- uint32x4_t a_ = (a); \
- uint32x4_t result; \
- __asm__ ("ext %0.16b, %1.16b, %2.16b, #%3*4" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
-#define vextq_u64(a, b, c) \
- __extension__ \
- ({ \
- uint64x2_t b_ = (b); \
- uint64x2_t a_ = (a); \
- uint64x2_t result; \
- __asm__ ("ext %0.16b, %1.16b, %2.16b, #%3*8" \
- : "=w"(result) \
- : "w"(a_), "w"(b_), "i"(c) \
- : /* No clobbers */); \
- result; \
- })
-
__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
vfma_f32 (float32x2_t a, float32x2_t b, float32x2_t c)
{
@@ -10358,7 +10046,7 @@ vqdmulh_n_s16 (int16x4_t a, int16_t b)
int16x4_t result;
__asm__ ("sqdmulh %0.4h,%1.4h,%2.h[0]"
: "=w"(result)
- : "w"(a), "w"(b)
+ : "w"(a), "x"(b)
: /* No clobbers */);
return result;
}
@@ -10380,7 +10068,7 @@ vqdmulhq_n_s16 (int16x8_t a, int16_t b)
int16x8_t result;
__asm__ ("sqdmulh %0.8h,%1.8h,%2.h[0]"
: "=w"(result)
- : "w"(a), "w"(b)
+ : "w"(a), "x"(b)
: /* No clobbers */);
return result;
}
@@ -17444,6 +17132,292 @@ vdupd_laneq_u64 (uint64x2_t __a, const int __b)
return __aarch64_vgetq_lane_u64 (__a, __b);
}
+/* vext */
+
+__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
+vext_f32 (float32x2_t __a, float32x2_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 2);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint32x2_t) {2-__c, 3-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint32x2_t) {__c, __c+1});
+#endif
+}
+
+__extension__ static __inline float64x1_t __attribute__ ((__always_inline__))
+vext_f64 (float64x1_t __a, float64x1_t __b, __const int __c)
+{
+ /* The only possible index to the assembler instruction returns element 0. */
+ __builtin_aarch64_im_lane_boundsi (__c, 1);
+ return __a;
+}
+__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
+vext_p8 (poly8x8_t __a, poly8x8_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 8);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint8x8_t)
+ {8-__c, 9-__c, 10-__c, 11-__c, 12-__c, 13-__c, 14-__c, 15-__c});
+#else
+ return __builtin_shuffle (__a, __b,
+ (uint8x8_t) {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7});
+#endif
+}
+
+__extension__ static __inline poly16x4_t __attribute__ ((__always_inline__))
+vext_p16 (poly16x4_t __a, poly16x4_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 4);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a,
+ (uint16x4_t) {4-__c, 5-__c, 6-__c, 7-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint16x4_t) {__c, __c+1, __c+2, __c+3});
+#endif
+}
+
+__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
+vext_s8 (int8x8_t __a, int8x8_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 8);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint8x8_t)
+ {8-__c, 9-__c, 10-__c, 11-__c, 12-__c, 13-__c, 14-__c, 15-__c});
+#else
+ return __builtin_shuffle (__a, __b,
+ (uint8x8_t) {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7});
+#endif
+}
+
+__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
+vext_s16 (int16x4_t __a, int16x4_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 4);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a,
+ (uint16x4_t) {4-__c, 5-__c, 6-__c, 7-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint16x4_t) {__c, __c+1, __c+2, __c+3});
+#endif
+}
+
+__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
+vext_s32 (int32x2_t __a, int32x2_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 2);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint32x2_t) {2-__c, 3-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint32x2_t) {__c, __c+1});
+#endif
+}
+
+__extension__ static __inline int64x1_t __attribute__ ((__always_inline__))
+vext_s64 (int64x1_t __a, int64x1_t __b, __const int __c)
+{
+ /* The only possible index to the assembler instruction returns element 0. */
+ __builtin_aarch64_im_lane_boundsi (__c, 1);
+ return __a;
+}
+
+__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
+vext_u8 (uint8x8_t __a, uint8x8_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 8);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint8x8_t)
+ {8-__c, 9-__c, 10-__c, 11-__c, 12-__c, 13-__c, 14-__c, 15-__c});
+#else
+ return __builtin_shuffle (__a, __b,
+ (uint8x8_t) {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7});
+#endif
+}
+
+__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
+vext_u16 (uint16x4_t __a, uint16x4_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 4);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a,
+ (uint16x4_t) {4-__c, 5-__c, 6-__c, 7-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint16x4_t) {__c, __c+1, __c+2, __c+3});
+#endif
+}
+
+__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
+vext_u32 (uint32x2_t __a, uint32x2_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 2);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint32x2_t) {2-__c, 3-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint32x2_t) {__c, __c+1});
+#endif
+}
+
+__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
+vext_u64 (uint64x1_t __a, uint64x1_t __b, __const int __c)
+{
+ /* The only possible index to the assembler instruction returns element 0. */
+ __builtin_aarch64_im_lane_boundsi (__c, 1);
+ return __a;
+}
+
+__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
+vextq_f32 (float32x4_t __a, float32x4_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 4);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a,
+ (uint32x4_t) {4-__c, 5-__c, 6-__c, 7-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint32x4_t) {__c, __c+1, __c+2, __c+3});
+#endif
+}
+
+__extension__ static __inline float64x2_t __attribute__ ((__always_inline__))
+vextq_f64 (float64x2_t __a, float64x2_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 2);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint64x2_t) {2-__c, 3-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint64x2_t) {__c, __c+1});
+#endif
+}
+
+__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
+vextq_p8 (poly8x16_t __a, poly8x16_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 16);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint8x16_t)
+ {16-__c, 17-__c, 18-__c, 19-__c, 20-__c, 21-__c, 22-__c, 23-__c,
+ 24-__c, 25-__c, 26-__c, 27-__c, 28-__c, 29-__c, 30-__c, 31-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint8x16_t)
+ {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
+ __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15});
+#endif
+}
+
+__extension__ static __inline poly16x8_t __attribute__ ((__always_inline__))
+vextq_p16 (poly16x8_t __a, poly16x8_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 8);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint16x8_t)
+ {8-__c, 9-__c, 10-__c, 11-__c, 12-__c, 13-__c, 14-__c, 15-__c});
+#else
+ return __builtin_shuffle (__a, __b,
+ (uint16x8_t) {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7});
+#endif
+}
+
+__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
+vextq_s8 (int8x16_t __a, int8x16_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 16);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint8x16_t)
+ {16-__c, 17-__c, 18-__c, 19-__c, 20-__c, 21-__c, 22-__c, 23-__c,
+ 24-__c, 25-__c, 26-__c, 27-__c, 28-__c, 29-__c, 30-__c, 31-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint8x16_t)
+ {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
+ __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15});
+#endif
+}
+
+__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
+vextq_s16 (int16x8_t __a, int16x8_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 8);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint16x8_t)
+ {8-__c, 9-__c, 10-__c, 11-__c, 12-__c, 13-__c, 14-__c, 15-__c});
+#else
+ return __builtin_shuffle (__a, __b,
+ (uint16x8_t) {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7});
+#endif
+}
+
+__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
+vextq_s32 (int32x4_t __a, int32x4_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 4);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a,
+ (uint32x4_t) {4-__c, 5-__c, 6-__c, 7-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint32x4_t) {__c, __c+1, __c+2, __c+3});
+#endif
+}
+
+__extension__ static __inline int64x2_t __attribute__ ((__always_inline__))
+vextq_s64 (int64x2_t __a, int64x2_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 2);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint64x2_t) {2-__c, 3-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint64x2_t) {__c, __c+1});
+#endif
+}
+
+__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
+vextq_u8 (uint8x16_t __a, uint8x16_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 16);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint8x16_t)
+ {16-__c, 17-__c, 18-__c, 19-__c, 20-__c, 21-__c, 22-__c, 23-__c,
+ 24-__c, 25-__c, 26-__c, 27-__c, 28-__c, 29-__c, 30-__c, 31-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint8x16_t)
+ {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7,
+ __c+8, __c+9, __c+10, __c+11, __c+12, __c+13, __c+14, __c+15});
+#endif
+}
+
+__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
+vextq_u16 (uint16x8_t __a, uint16x8_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 8);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint16x8_t)
+ {8-__c, 9-__c, 10-__c, 11-__c, 12-__c, 13-__c, 14-__c, 15-__c});
+#else
+ return __builtin_shuffle (__a, __b,
+ (uint16x8_t) {__c, __c+1, __c+2, __c+3, __c+4, __c+5, __c+6, __c+7});
+#endif
+}
+
+__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
+vextq_u32 (uint32x4_t __a, uint32x4_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 4);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a,
+ (uint32x4_t) {4-__c, 5-__c, 6-__c, 7-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint32x4_t) {__c, __c+1, __c+2, __c+3});
+#endif
+}
+
+__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__))
+vextq_u64 (uint64x2_t __a, uint64x2_t __b, __const int __c)
+{
+ __builtin_aarch64_im_lane_boundsi (__c, 2);
+#ifdef __AARCH64EB__
+ return __builtin_shuffle (__b, __a, (uint64x2_t) {2-__c, 3-__c});
+#else
+ return __builtin_shuffle (__a, __b, (uint64x2_t) {__c, __c+1});
+#endif
+}
+
/* vfma_lane */
__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
index 12ab570c05e..807d0b172c8 100644
--- a/gcc/config/aarch64/constraints.md
+++ b/gcc/config/aarch64/constraints.md
@@ -21,6 +21,9 @@
(define_register_constraint "k" "STACK_REG"
"@internal The stack register.")
+(define_register_constraint "Ucs" "CALLER_SAVE_REGS"
+ "@internal The caller save registers.")
+
(define_register_constraint "w" "FP_REGS"
"Floating point and SIMD vector registers.")
@@ -92,6 +95,10 @@
(and (match_code "const_int")
(match_test "(unsigned HOST_WIDE_INT) ival < 64")))
+(define_constraint "Usf"
+ "@internal Usf is a symbol reference."
+ (match_code "symbol_ref"))
+
(define_constraint "UsM"
"@internal
A constraint that matches the immediate constant -1."
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index c537c3780ee..05611f4cd61 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -270,6 +270,7 @@
UNSPEC_UZP2 ; Used in vector permute patterns.
UNSPEC_TRN1 ; Used in vector permute patterns.
UNSPEC_TRN2 ; Used in vector permute patterns.
+ UNSPEC_EXT ; Used in aarch64-simd.md.
UNSPEC_AESE ; Used in aarch64-simd.md.
UNSPEC_AESD ; Used in aarch64-simd.md.
UNSPEC_AESMC ; Used in aarch64-simd.md.
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index c8e27d8715d..2702a3c8d83 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -26,6 +26,10 @@
&& GET_MODE_CLASS (GET_MODE (op)) == MODE_CC"))))
)
+(define_predicate "aarch64_call_insn_operand"
+ (ior (match_code "symbol_ref")
+ (match_operand 0 "register_operand")))
+
(define_predicate "aarch64_simd_register"
(and (match_code "reg")
(ior (match_test "REGNO_REG_CLASS (REGNO (op)) == FP_LO_REGS")
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index df4cc1b1c91..77ba003add5 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-expr.h"
#include "is-a.h"
#include "gimple.h"
+#include "gimple-iterator.h"
#include "gimplify.h"
#include "gimple-ssa.h"
#include "stringpool.h"
@@ -72,6 +73,7 @@ along with GCC; see the file COPYING3. If not see
#include "libfuncs.h"
#include "opts.h"
#include "params.h"
+#include "builtins.h"
/* Specify which cpu to schedule for. */
enum processor_type alpha_tune;
@@ -4747,7 +4749,7 @@ struct GTY(()) machine_function
static struct machine_function *
alpha_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* Support for frame based VMS condition handlers. */
@@ -5449,22 +5451,23 @@ print_operand_address (FILE *file, rtx addr)
offset = INTVAL (addr);
break;
-#if TARGET_ABI_OPEN_VMS
case SYMBOL_REF:
+ gcc_assert(TARGET_ABI_OPEN_VMS || this_is_asm_operands);
fprintf (file, "%s", XSTR (addr, 0));
return;
case CONST:
+ gcc_assert(TARGET_ABI_OPEN_VMS || this_is_asm_operands);
gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF);
fprintf (file, "%s+" HOST_WIDE_INT_PRINT_DEC,
XSTR (XEXP (XEXP (addr, 0), 0), 0),
INTVAL (XEXP (XEXP (addr, 0), 1)));
return;
-
-#endif
+
default:
- gcc_unreachable ();
+ output_operand_lossage ("invalid operand address");
+ return;
}
fprintf (file, HOST_WIDE_INT_PRINT_DEC "($%d)", offset, basereg);
@@ -7042,9 +7045,6 @@ alpha_fold_builtin (tree fndecl, int n_args, tree *op,
case ALPHA_BUILTIN_MSKQH:
return alpha_fold_builtin_mskxx (op, opint, op_const, 0xff, true);
- case ALPHA_BUILTIN_UMULH:
- return fold_build2 (MULT_HIGHPART_EXPR, alpha_dimode_u, op[0], op[1]);
-
case ALPHA_BUILTIN_ZAP:
opint[1] ^= 0xff;
/* FALLTHRU */
@@ -7094,6 +7094,49 @@ alpha_fold_builtin (tree fndecl, int n_args, tree *op,
return NULL;
}
}
+
+bool
+alpha_gimple_fold_builtin (gimple_stmt_iterator *gsi)
+{
+ bool changed = false;
+ gimple stmt = gsi_stmt (*gsi);
+ tree call = gimple_call_fn (stmt);
+ gimple new_stmt = NULL;
+
+ if (call)
+ {
+ tree fndecl = gimple_call_fndecl (stmt);
+
+ if (fndecl)
+ {
+ tree arg0, arg1;
+
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case ALPHA_BUILTIN_UMULH:
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+
+ new_stmt
+ = gimple_build_assign_with_ops (MULT_HIGHPART_EXPR,
+ gimple_call_lhs (stmt),
+ arg0,
+ arg1);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (new_stmt)
+ {
+ gsi_replace (gsi, new_stmt, true);
+ changed = true;
+ }
+
+ return changed;
+}
/* This page contains routines that are used to determine what the function
prologue and epilogue code will do and write them out. */
@@ -9535,7 +9578,7 @@ alpha_use_linkage (rtx func, bool lflag, bool rflag)
linksym = (char *) alloca (buf_len);
snprintf (linksym, buf_len, "$%d..%s..lk", cfun->funcdef_no, name);
- al = ggc_alloc_alpha_links ();
+ al = ggc_alloc<alpha_links> ();
al->func = func;
al->linkage = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (linksym));
@@ -9790,6 +9833,8 @@ alpha_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
#define TARGET_EXPAND_BUILTIN alpha_expand_builtin
#undef TARGET_FOLD_BUILTIN
#define TARGET_FOLD_BUILTIN alpha_fold_builtin
+#undef TARGET_GIMPLE_FOLD_BUILTIN
+#define TARGET_GIMPLE_FOLD_BUILTIN alpha_gimple_fold_builtin
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL alpha_function_ok_for_sibcall
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 795b4df3fbf..34ff1f0062f 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -4764,7 +4764,7 @@
"operands[4] = gen_rtx_SYMBOL_REF (Pmode, \"OTS$MOVE\");")
(define_insn "*movmemdi_1"
- [(set (match_operand:BLK 0 "memory_operand" "=m,=m")
+ [(set (match_operand:BLK 0 "memory_operand" "=m,m")
(match_operand:BLK 1 "memory_operand" "m,m"))
(use (match_operand:DI 2 "nonmemory_operand" "r,i"))
(use (match_operand:DI 3 "immediate_operand"))
@@ -4831,7 +4831,7 @@
})
(define_insn "*clrmemdi_1"
- [(set (match_operand:BLK 0 "memory_operand" "=m,=m")
+ [(set (match_operand:BLK 0 "memory_operand" "=m,m")
(const_int 0))
(use (match_operand:DI 1 "nonmemory_operand" "r,i"))
(use (match_operand:DI 2 "immediate_operand"))
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 113395bd5de..0aa43c2ce2e 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -66,6 +66,7 @@ along with GCC; see the file COPYING3. If not see
#include "context.h"
#include "pass_manager.h"
#include "wide-int.h"
+#include "builtins.h"
/* Which cpu we're compiling for (A5, ARC600, ARC601, ARC700). */
static const char *arc_cpu_string = "";
@@ -750,7 +751,7 @@ arc_init (void)
error ("-mmul32x16 supported only for ARC600 or ARC601");
if (!TARGET_DPFP && TARGET_DPFP_DISABLE_LRSR)
- error ("-mno-dpfp-lrsr suppforted only with -mdpfp");
+ error ("-mno-dpfp-lrsr supported only with -mdpfp");
/* FPX-1. No fast and compact together. */
if ((TARGET_DPFP_FAST_SET && TARGET_DPFP_COMPACT_SET)
@@ -6051,7 +6052,7 @@ arc_reorg (void)
continue;
/* Now check if the jump is beyond the s9 range. */
- if (find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX))
+ if (CROSSING_JUMP_P (insn))
continue;
offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
@@ -8722,7 +8723,7 @@ static struct machine_function *
arc_init_machine_status (void)
{
struct machine_function *machine;
- machine = ggc_alloc_cleared_machine_function ();
+ machine = ggc_cleared_alloc<machine_function> ();
machine->fn_type = ARC_FUNCTION_UNKNOWN;
machine->force_short_suffix = -1;
@@ -9206,7 +9207,7 @@ arc_decl_pretend_args (tree decl)
/* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
- -D_PROFILE_USE; delay branch scheduling then follows a REG_CROSSING_JUMP
+ -D_PROFILE_USE; delay branch scheduling then follows a crossing jump
to redirect two breqs. */
static bool
@@ -9216,7 +9217,7 @@ arc_can_follow_jump (const_rtx follower, const_rtx followee)
union { const_rtx c; rtx r; } u;
u.c = follower;
- if (find_reg_note (followee, REG_CROSSING_JUMP, NULL_RTX))
+ if (CROSSING_JUMP_P (followee))
switch (get_attr_type (u.r))
{
case TYPE_BRCC:
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 80f6e338a10..2f93d7cd2be 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -1698,7 +1698,7 @@
(define_insn "mulsi_600"
[(set (match_operand:SI 2 "mlo_operand" "")
- (mult:SI (match_operand:SI 0 "register_operand" "Rcq#q,c,c,%c")
+ (mult:SI (match_operand:SI 0 "register_operand" "%Rcq#q,c,c,c")
(match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,I,Cal")))
(clobber (match_operand:SI 3 "mhi_operand" ""))]
"TARGET_MUL64_SET"
@@ -1750,7 +1750,7 @@
(define_insn "mulsidi_600"
[(set (reg:DI MUL64_OUT_REG)
(mult:DI (sign_extend:DI
- (match_operand:SI 0 "register_operand" "Rcq#q,c,c,%c"))
+ (match_operand:SI 0 "register_operand" "%Rcq#q,c,c,c"))
(sign_extend:DI
; assembler issue for "I", see mulsi_600
; (match_operand:SI 1 "register_operand" "Rcq#q,cL,I,Cal"))))]
@@ -1766,7 +1766,7 @@
(define_insn "umulsidi_600"
[(set (reg:DI MUL64_OUT_REG)
(mult:DI (zero_extend:DI
- (match_operand:SI 0 "register_operand" "c,c,%c"))
+ (match_operand:SI 0 "register_operand" "%c,c,c"))
(sign_extend:DI
; assembler issue for "I", see mulsi_600
; (match_operand:SI 1 "register_operand" "cL,I,Cal"))))]
@@ -3480,7 +3480,7 @@
(define_insn "jump_i"
[(set (pc) (label_ref (match_operand 0 "" "")))]
- "!TARGET_LONG_CALLS_SET || !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
+ "!TARGET_LONG_CALLS_SET || !CROSSING_JUMP_P (insn)"
"b%!%* %^%l0%&"
[(set_attr "type" "uncond_branch")
(set (attr "iscompact")
@@ -3496,7 +3496,7 @@
(eq_attr "delay_slot_filled" "yes")
(const_int 4)
- (match_test "find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)")
+ (match_test "CROSSING_JUMP_P (insn)")
(const_int 4)
(ior (lt (minus (match_dup 0) (pc)) (const_int -512))
@@ -4134,7 +4134,7 @@
;; FIXME: an intrinsic for multiply is daft. Can we remove this?
(define_insn "mul64"
- [(unspec [(match_operand:SI 0 "general_operand" "q,r,r,%r")
+ [(unspec [(match_operand:SI 0 "general_operand" "%q,r,r,r")
(match_operand:SI 1 "general_operand" "q,rL,I,Cal")]
UNSPEC_MUL64)]
"TARGET_MUL64_SET"
@@ -4589,7 +4589,7 @@
"(reload_completed
|| (TARGET_EARLY_CBRANCHSI
&& brcc_nolimm_operator (operands[0], VOIDmode)))
- && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
+ && !CROSSING_JUMP_P (insn)"
"*
switch (get_attr_length (insn))
{
@@ -4653,7 +4653,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))
(clobber (reg:CC_ZN CC_REG))]
- "!find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
+ "!CROSSING_JUMP_P (insn)"
{
switch (get_attr_length (insn))
{
@@ -4693,7 +4693,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))
(clobber (reg:CC_ZN CC_REG))]
- "!find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
+ "!CROSSING_JUMP_P (insn)"
"#"
""
[(parallel
diff --git a/gcc/config/arm/aout.h b/gcc/config/arm/aout.h
index 51d32a9d461..c8f4e45c623 100644
--- a/gcc/config/arm/aout.h
+++ b/gcc/config/arm/aout.h
@@ -14,8 +14,13 @@
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef ASM_APP_ON
diff --git a/gcc/config/arm/arm-cores.def b/gcc/config/arm/arm-cores.def
index 5bbc76ac269..a830a83baeb 100644
--- a/gcc/config/arm/arm-cores.def
+++ b/gcc/config/arm/arm-cores.def
@@ -14,8 +14,13 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* Before using #include to read this file, define a macro:
diff --git a/gcc/config/arm/arm-opts.h b/gcc/config/arm/arm-opts.h
index a8393975a61..21902940e4f 100644
--- a/gcc/config/arm/arm-opts.h
+++ b/gcc/config/arm/arm-opts.h
@@ -13,8 +13,13 @@
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef ARM_OPTS_H
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 1e44080d601..98a8d891f23 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -50,6 +50,7 @@
#include "except.h"
#include "tm_p.h"
#include "target.h"
+#include "sched-int.h"
#include "target-def.h"
#include "debug.h"
#include "langhooks.h"
@@ -59,6 +60,8 @@
#include "params.h"
#include "opts.h"
#include "dumpfile.h"
+#include "gimple-expr.h"
+#include "builtins.h"
/* Forward definitions of types. */
typedef struct minipool_node Mnode;
@@ -94,6 +97,7 @@ static int thumb_far_jump_used_p (void);
static bool thumb_force_lr_save (void);
static unsigned arm_size_return_regs (void);
static bool arm_assemble_integer (rtx, unsigned int, int);
+static void arm_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update);
static void arm_print_operand (FILE *, rtx, int);
static void arm_print_operand_address (FILE *, rtx);
static bool arm_print_operand_punct_valid_p (unsigned char code);
@@ -585,6 +589,9 @@ static const struct attribute_spec arm_attribute_table[] =
#undef TARGET_MANGLE_TYPE
#define TARGET_MANGLE_TYPE arm_mangle_type
+#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
+#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV arm_atomic_assign_expand_fenv
+
#undef TARGET_BUILD_BUILTIN_VA_LIST
#define TARGET_BUILD_BUILTIN_VA_LIST arm_build_builtin_va_list
#undef TARGET_EXPAND_BUILTIN_VA_START
@@ -2944,7 +2951,7 @@ arm_option_override (void)
prefer_neon_for_64bits = true;
/* Use the alternative scheduling-pressure algorithm by default. */
- maybe_set_param_value (PARAM_SCHED_PRESSURE_ALGORITHM, 2,
+ maybe_set_param_value (PARAM_SCHED_PRESSURE_ALGORITHM, SCHED_PRESSURE_MODEL,
global_options.x_param_values,
global_options_set.x_param_values);
@@ -6153,7 +6160,7 @@ arm_function_in_section_p (tree decl, section *section)
if (!DECL_SECTION_NAME (decl))
{
/* Make sure that we will not create a unique section for DECL. */
- if (flag_function_sections || DECL_ONE_ONLY (decl))
+ if (flag_function_sections || DECL_COMDAT_GROUP (decl))
return false;
}
@@ -16934,7 +16941,7 @@ thumb1_reorg (void)
rtx prev, insn = BB_END (bb);
bool insn_clobbered = false;
- while (insn != BB_HEAD (bb) && DEBUG_INSN_P (insn))
+ while (insn != BB_HEAD (bb) && !NONDEBUG_INSN_P (insn))
insn = PREV_INSN (insn);
/* Find the last cbranchsi4_insn in basic block BB. */
@@ -21270,7 +21277,15 @@ arm_print_condition (FILE *stream)
}
-/* If CODE is 'd', then the X is a condition operand and the instruction
+/* Globally reserved letters: acln
+ Puncutation letters currently used: @_|?().!#
+ Lower case letters currently used: bcdefhimpqtvwxyz
+ Upper case letters currently used: ABCDFGHJKLMNOPQRSTU
+ Letters previously used, but now deprecated/obsolete: sVWXYZ.
+
+ Note that the global reservation for 'c' is only for CONSTANT_ADDRESS_P.
+
+ If CODE is 'd', then the X is a condition operand and the instruction
should only be executed if the condition is true.
if CODE is 'D', then the X is a condition operand and the instruction
should only be executed if the condition is false: however, if the mode
@@ -21410,6 +21425,19 @@ arm_print_operand (FILE *stream, rtx x, int code)
}
return;
+ case 'b':
+ /* Print the log2 of a CONST_INT. */
+ {
+ HOST_WIDE_INT val;
+
+ if (!CONST_INT_P (x)
+ || (val = exact_log2 (INTVAL (x) & 0xffffffff)) < 0)
+ output_operand_lossage ("Unsupported operand for code '%c'", code);
+ else
+ fprintf (stream, "#" HOST_WIDE_INT_PRINT_DEC, val);
+ }
+ return;
+
case 'L':
/* The low 16 bits of an immediate constant. */
fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL(x) & 0xffff);
@@ -23064,6 +23092,7 @@ typedef enum {
NEON_BINOP,
NEON_TERNOP,
NEON_UNOP,
+ NEON_BSWAP,
NEON_GETLANE,
NEON_SETLANE,
NEON_CREATE,
@@ -23085,7 +23114,6 @@ typedef enum {
NEON_FLOAT_NARROW,
NEON_FIXCONV,
NEON_SELECT,
- NEON_RESULTPAIR,
NEON_REINTERP,
NEON_VTBL,
NEON_VTBX,
@@ -23454,6 +23482,9 @@ enum arm_builtins
ARM_BUILTIN_CRC32CH,
ARM_BUILTIN_CRC32CW,
+ ARM_BUILTIN_GET_FPSCR,
+ ARM_BUILTIN_SET_FPSCR,
+
#undef CRYPTO1
#undef CRYPTO2
#undef CRYPTO3
@@ -23531,14 +23562,19 @@ arm_init_neon_builtins (void)
tree V8QI_type_node;
tree V4HI_type_node;
+ tree V4UHI_type_node;
tree V4HF_type_node;
tree V2SI_type_node;
+ tree V2USI_type_node;
tree V2SF_type_node;
tree V16QI_type_node;
tree V8HI_type_node;
+ tree V8UHI_type_node;
tree V4SI_type_node;
+ tree V4USI_type_node;
tree V4SF_type_node;
tree V2DI_type_node;
+ tree V2UDI_type_node;
tree intUQI_type_node;
tree intUHI_type_node;
@@ -23550,27 +23586,6 @@ arm_init_neon_builtins (void)
tree intCI_type_node;
tree intXI_type_node;
- tree V8QI_pointer_node;
- tree V4HI_pointer_node;
- tree V2SI_pointer_node;
- tree V2SF_pointer_node;
- tree V16QI_pointer_node;
- tree V8HI_pointer_node;
- tree V4SI_pointer_node;
- tree V4SF_pointer_node;
- tree V2DI_pointer_node;
-
- tree void_ftype_pv8qi_v8qi_v8qi;
- tree void_ftype_pv4hi_v4hi_v4hi;
- tree void_ftype_pv2si_v2si_v2si;
- tree void_ftype_pv2sf_v2sf_v2sf;
- tree void_ftype_pdi_di_di;
- tree void_ftype_pv16qi_v16qi_v16qi;
- tree void_ftype_pv8hi_v8hi_v8hi;
- tree void_ftype_pv4si_v4si_v4si;
- tree void_ftype_pv4sf_v4sf_v4sf;
- tree void_ftype_pv2di_v2di_v2di;
-
tree reinterp_ftype_dreg[NUM_DREG_TYPES][NUM_DREG_TYPES];
tree reinterp_ftype_qreg[NUM_QREG_TYPES][NUM_QREG_TYPES];
tree dreg_types[NUM_DREG_TYPES], qreg_types[NUM_QREG_TYPES];
@@ -23634,16 +23649,26 @@ arm_init_neon_builtins (void)
const_intDI_pointer_node = build_pointer_type (const_intDI_node);
const_float_pointer_node = build_pointer_type (const_float_node);
+ /* Unsigned integer types for various mode sizes. */
+ intUQI_type_node = make_unsigned_type (GET_MODE_PRECISION (QImode));
+ intUHI_type_node = make_unsigned_type (GET_MODE_PRECISION (HImode));
+ intUSI_type_node = make_unsigned_type (GET_MODE_PRECISION (SImode));
+ intUDI_type_node = make_unsigned_type (GET_MODE_PRECISION (DImode));
+ neon_intUTI_type_node = make_unsigned_type (GET_MODE_PRECISION (TImode));
/* Now create vector types based on our NEON element types. */
/* 64-bit vectors. */
V8QI_type_node =
build_vector_type_for_mode (neon_intQI_type_node, V8QImode);
V4HI_type_node =
build_vector_type_for_mode (neon_intHI_type_node, V4HImode);
+ V4UHI_type_node =
+ build_vector_type_for_mode (intUHI_type_node, V4HImode);
V4HF_type_node =
build_vector_type_for_mode (neon_floatHF_type_node, V4HFmode);
V2SI_type_node =
build_vector_type_for_mode (neon_intSI_type_node, V2SImode);
+ V2USI_type_node =
+ build_vector_type_for_mode (intUSI_type_node, V2SImode);
V2SF_type_node =
build_vector_type_for_mode (neon_float_type_node, V2SFmode);
/* 128-bit vectors. */
@@ -23651,19 +23676,18 @@ arm_init_neon_builtins (void)
build_vector_type_for_mode (neon_intQI_type_node, V16QImode);
V8HI_type_node =
build_vector_type_for_mode (neon_intHI_type_node, V8HImode);
+ V8UHI_type_node =
+ build_vector_type_for_mode (intUHI_type_node, V8HImode);
V4SI_type_node =
build_vector_type_for_mode (neon_intSI_type_node, V4SImode);
+ V4USI_type_node =
+ build_vector_type_for_mode (intUSI_type_node, V4SImode);
V4SF_type_node =
build_vector_type_for_mode (neon_float_type_node, V4SFmode);
V2DI_type_node =
build_vector_type_for_mode (neon_intDI_type_node, V2DImode);
-
- /* Unsigned integer types for various mode sizes. */
- intUQI_type_node = make_unsigned_type (GET_MODE_PRECISION (QImode));
- intUHI_type_node = make_unsigned_type (GET_MODE_PRECISION (HImode));
- intUSI_type_node = make_unsigned_type (GET_MODE_PRECISION (SImode));
- intUDI_type_node = make_unsigned_type (GET_MODE_PRECISION (DImode));
- neon_intUTI_type_node = make_unsigned_type (GET_MODE_PRECISION (TImode));
+ V2UDI_type_node =
+ build_vector_type_for_mode (intUDI_type_node, V2DImode);
(*lang_hooks.types.register_builtin_type) (intUQI_type_node,
@@ -23696,53 +23720,8 @@ arm_init_neon_builtins (void)
(*lang_hooks.types.register_builtin_type) (intXI_type_node,
"__builtin_neon_xi");
- /* Pointers to vector types. */
- V8QI_pointer_node = build_pointer_type (V8QI_type_node);
- V4HI_pointer_node = build_pointer_type (V4HI_type_node);
- V2SI_pointer_node = build_pointer_type (V2SI_type_node);
- V2SF_pointer_node = build_pointer_type (V2SF_type_node);
- V16QI_pointer_node = build_pointer_type (V16QI_type_node);
- V8HI_pointer_node = build_pointer_type (V8HI_type_node);
- V4SI_pointer_node = build_pointer_type (V4SI_type_node);
- V4SF_pointer_node = build_pointer_type (V4SF_type_node);
- V2DI_pointer_node = build_pointer_type (V2DI_type_node);
-
- /* Operations which return results as pairs. */
- void_ftype_pv8qi_v8qi_v8qi =
- build_function_type_list (void_type_node, V8QI_pointer_node, V8QI_type_node,
- V8QI_type_node, NULL);
- void_ftype_pv4hi_v4hi_v4hi =
- build_function_type_list (void_type_node, V4HI_pointer_node, V4HI_type_node,
- V4HI_type_node, NULL);
- void_ftype_pv2si_v2si_v2si =
- build_function_type_list (void_type_node, V2SI_pointer_node, V2SI_type_node,
- V2SI_type_node, NULL);
- void_ftype_pv2sf_v2sf_v2sf =
- build_function_type_list (void_type_node, V2SF_pointer_node, V2SF_type_node,
- V2SF_type_node, NULL);
- void_ftype_pdi_di_di =
- build_function_type_list (void_type_node, intDI_pointer_node,
- neon_intDI_type_node, neon_intDI_type_node, NULL);
- void_ftype_pv16qi_v16qi_v16qi =
- build_function_type_list (void_type_node, V16QI_pointer_node,
- V16QI_type_node, V16QI_type_node, NULL);
- void_ftype_pv8hi_v8hi_v8hi =
- build_function_type_list (void_type_node, V8HI_pointer_node, V8HI_type_node,
- V8HI_type_node, NULL);
- void_ftype_pv4si_v4si_v4si =
- build_function_type_list (void_type_node, V4SI_pointer_node, V4SI_type_node,
- V4SI_type_node, NULL);
- void_ftype_pv4sf_v4sf_v4sf =
- build_function_type_list (void_type_node, V4SF_pointer_node, V4SF_type_node,
- V4SF_type_node, NULL);
- void_ftype_pv2di_v2di_v2di =
- build_function_type_list (void_type_node, V2DI_pointer_node, V2DI_type_node,
- V2DI_type_node, NULL);
-
if (TARGET_CRYPTO && TARGET_HARD_FLOAT)
{
- tree V4USI_type_node =
- build_vector_type_for_mode (intUSI_type_node, V4SImode);
tree V16UQI_type_node =
build_vector_type_for_mode (intUQI_type_node, V16QImode);
@@ -24028,25 +24007,6 @@ arm_init_neon_builtins (void)
}
break;
- case NEON_RESULTPAIR:
- {
- switch (insn_data[d->code].operand[1].mode)
- {
- case V8QImode: ftype = void_ftype_pv8qi_v8qi_v8qi; break;
- case V4HImode: ftype = void_ftype_pv4hi_v4hi_v4hi; break;
- case V2SImode: ftype = void_ftype_pv2si_v2si_v2si; break;
- case V2SFmode: ftype = void_ftype_pv2sf_v2sf_v2sf; break;
- case DImode: ftype = void_ftype_pdi_di_di; break;
- case V16QImode: ftype = void_ftype_pv16qi_v16qi_v16qi; break;
- case V8HImode: ftype = void_ftype_pv8hi_v8hi_v8hi; break;
- case V4SImode: ftype = void_ftype_pv4si_v4si_v4si; break;
- case V4SFmode: ftype = void_ftype_pv4sf_v4sf_v4sf; break;
- case V2DImode: ftype = void_ftype_pv2di_v2di_v2di; break;
- default: gcc_unreachable ();
- }
- }
- break;
-
case NEON_REINTERP:
{
/* We iterate over NUM_DREG_TYPES doubleword types,
@@ -24106,6 +24066,31 @@ arm_init_neon_builtins (void)
ftype = build_function_type_list (return_type, eltype, NULL);
break;
}
+ case NEON_BSWAP:
+ {
+ tree eltype = NULL_TREE;
+ switch (insn_data[d->code].operand[1].mode)
+ {
+ case V4HImode:
+ eltype = V4UHI_type_node;
+ break;
+ case V8HImode:
+ eltype = V8UHI_type_node;
+ break;
+ case V2SImode:
+ eltype = V2USI_type_node;
+ break;
+ case V4SImode:
+ eltype = V4USI_type_node;
+ break;
+ case V2DImode:
+ eltype = V2UDI_type_node;
+ break;
+ default: gcc_unreachable ();
+ }
+ ftype = build_function_type_list (eltype, eltype, NULL);
+ break;
+ }
default:
gcc_unreachable ();
}
@@ -24252,6 +24237,15 @@ static const struct builtin_description bdesc_2arg[] =
IWMMXT_BUILTIN2 (iwmmxt_wmacuz, WMACUZ)
IWMMXT_BUILTIN2 (iwmmxt_wmacsz, WMACSZ)
+
+#define FP_BUILTIN(L, U) \
+ {0, CODE_FOR_##L, "__builtin_arm_"#L, ARM_BUILTIN_##U, \
+ UNKNOWN, 0},
+
+ FP_BUILTIN (set_fpscr, GET_FPSCR)
+ FP_BUILTIN (get_fpscr, SET_FPSCR)
+#undef FP_BUILTIN
+
#define CRC32_BUILTIN(L, U) \
{0, CODE_FOR_##L, "__builtin_arm_"#L, ARM_BUILTIN_##U, \
UNKNOWN, 0},
@@ -24766,6 +24760,21 @@ arm_init_builtins (void)
if (TARGET_CRC32)
arm_init_crc32_builtins ();
+
+ if (TARGET_VFP)
+ {
+ tree ftype_set_fpscr
+ = build_function_type_list (void_type_node, unsigned_type_node, NULL);
+ tree ftype_get_fpscr
+ = build_function_type_list (unsigned_type_node, NULL);
+
+ arm_builtin_decls[ARM_BUILTIN_GET_FPSCR]
+ = add_builtin_function ("__builtin_arm_ldfscr", ftype_get_fpscr,
+ ARM_BUILTIN_GET_FPSCR, BUILT_IN_MD, NULL, NULL_TREE);
+ arm_builtin_decls[ARM_BUILTIN_SET_FPSCR]
+ = add_builtin_function ("__builtin_arm_stfscr", ftype_set_fpscr,
+ ARM_BUILTIN_SET_FPSCR, BUILT_IN_MD, NULL, NULL_TREE);
+ }
}
/* Return the ARM builtin for CODE. */
@@ -25280,6 +25289,7 @@ arm_expand_neon_builtin (int fcode, tree exp, rtx target)
case NEON_SPLIT:
case NEON_FLOAT_WIDEN:
case NEON_FLOAT_NARROW:
+ case NEON_BSWAP:
case NEON_REINTERP:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_STOP);
@@ -25289,11 +25299,6 @@ arm_expand_neon_builtin (int fcode, tree exp, rtx target)
return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_STOP);
- case NEON_RESULTPAIR:
- return arm_expand_neon_args (target, icode, 0, type_mode, exp, fcode,
- NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG,
- NEON_ARG_STOP);
-
case NEON_LANEMUL:
case NEON_LANEMULL:
case NEON_LANEMULH:
@@ -25355,24 +25360,6 @@ neon_reinterpret (rtx dest, rtx src)
emit_move_insn (dest, gen_lowpart (GET_MODE (dest), src));
}
-/* Emit code to place a Neon pair result in memory locations (with equal
- registers). */
-void
-neon_emit_pair_result_insn (enum machine_mode mode,
- rtx (*intfn) (rtx, rtx, rtx, rtx), rtx destaddr,
- rtx op1, rtx op2)
-{
- rtx mem = gen_rtx_MEM (mode, destaddr);
- rtx tmp1 = gen_reg_rtx (mode);
- rtx tmp2 = gen_reg_rtx (mode);
-
- emit_insn (intfn (tmp1, op1, op2, tmp2));
-
- emit_move_insn (mem, tmp1);
- mem = adjust_address (mem, mode, GET_MODE_SIZE (mode));
- emit_move_insn (mem, tmp2);
-}
-
/* Set up OPERANDS for a register copy from SRC to DEST, taking care
not to early-clobber SRC registers in the process.
@@ -25493,6 +25480,25 @@ arm_expand_builtin (tree exp,
switch (fcode)
{
+ case ARM_BUILTIN_GET_FPSCR:
+ case ARM_BUILTIN_SET_FPSCR:
+ if (fcode == ARM_BUILTIN_GET_FPSCR)
+ {
+ icode = CODE_FOR_get_fpscr;
+ target = gen_reg_rtx (SImode);
+ pat = GEN_FCN (icode) (target);
+ }
+ else
+ {
+ target = NULL_RTX;
+ icode = CODE_FOR_set_fpscr;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ op0 = expand_normal (arg0);
+ pat = GEN_FCN (icode) (op0);
+ }
+ emit_insn (pat);
+ return target;
+
case ARM_BUILTIN_TEXTRMSB:
case ARM_BUILTIN_TEXTRMUB:
case ARM_BUILTIN_TEXTRMSH:
@@ -26816,7 +26822,7 @@ static struct machine_function *
arm_init_machine_status (void)
{
struct machine_function *machine;
- machine = ggc_alloc_cleared_machine_function ();
+ machine = ggc_cleared_alloc<machine_function> ();
#if ARM_FT_UNKNOWN != 0
machine->func_type = ARM_FT_UNKNOWN;
@@ -29783,8 +29789,7 @@ arm_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in)
int in_n, out_n;
if (TREE_CODE (type_out) != VECTOR_TYPE
- || TREE_CODE (type_in) != VECTOR_TYPE
- || !(TARGET_NEON && TARGET_FPU_ARMV8 && flag_unsafe_math_optimizations))
+ || TREE_CODE (type_in) != VECTOR_TYPE)
return NULL_TREE;
out_mode = TYPE_MODE (TREE_TYPE (type_out));
@@ -29796,7 +29801,13 @@ arm_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in)
decl of the vectorized builtin for the appropriate vector mode.
NULL_TREE is returned if no such builtin is available. */
#undef ARM_CHECK_BUILTIN_MODE
-#define ARM_CHECK_BUILTIN_MODE(C) \
+#define ARM_CHECK_BUILTIN_MODE(C) \
+ (TARGET_NEON && TARGET_FPU_ARMV8 \
+ && flag_unsafe_math_optimizations \
+ && ARM_CHECK_BUILTIN_MODE_1 (C))
+
+#undef ARM_CHECK_BUILTIN_MODE_1
+#define ARM_CHECK_BUILTIN_MODE_1(C) \
(out_mode == SFmode && out_n == C \
&& in_mode == SFmode && in_n == C)
@@ -29821,6 +29832,30 @@ arm_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in)
return ARM_FIND_VRINT_VARIANT (vrintz);
case BUILT_IN_ROUNDF:
return ARM_FIND_VRINT_VARIANT (vrinta);
+#undef ARM_CHECK_BUILTIN_MODE
+#define ARM_CHECK_BUILTIN_MODE(C, N) \
+ (out_mode == N##Imode && out_n == C \
+ && in_mode == N##Imode && in_n == C)
+ case BUILT_IN_BSWAP16:
+ if (ARM_CHECK_BUILTIN_MODE (4, H))
+ return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv4hi, false);
+ else if (ARM_CHECK_BUILTIN_MODE (8, H))
+ return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv8hi, false);
+ else
+ return NULL_TREE;
+ case BUILT_IN_BSWAP32:
+ if (ARM_CHECK_BUILTIN_MODE (2, S))
+ return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv2si, false);
+ else if (ARM_CHECK_BUILTIN_MODE (4, S))
+ return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv4si, false);
+ else
+ return NULL_TREE;
+ case BUILT_IN_BSWAP64:
+ if (ARM_CHECK_BUILTIN_MODE (2, D))
+ return arm_builtin_decl (ARM_BUILTIN_NEON_bswapv2di, false);
+ else
+ return NULL_TREE;
+
default:
return NULL_TREE;
}
@@ -31400,4 +31435,73 @@ arm_const_not_ok_for_debug_p (rtx p)
return false;
}
+static void
+arm_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
+{
+ const unsigned ARM_FE_INVALID = 1;
+ const unsigned ARM_FE_DIVBYZERO = 2;
+ const unsigned ARM_FE_OVERFLOW = 4;
+ const unsigned ARM_FE_UNDERFLOW = 8;
+ const unsigned ARM_FE_INEXACT = 16;
+ const unsigned HOST_WIDE_INT ARM_FE_ALL_EXCEPT = (ARM_FE_INVALID
+ | ARM_FE_DIVBYZERO
+ | ARM_FE_OVERFLOW
+ | ARM_FE_UNDERFLOW
+ | ARM_FE_INEXACT);
+ const unsigned HOST_WIDE_INT ARM_FE_EXCEPT_SHIFT = 8;
+ tree fenv_var, get_fpscr, set_fpscr, mask, ld_fenv, masked_fenv;
+ tree new_fenv_var, reload_fenv, restore_fnenv;
+ tree update_call, atomic_feraiseexcept, hold_fnclex;
+
+ if (!TARGET_VFP)
+ return;
+
+ /* Generate the equivalent of :
+ unsigned int fenv_var;
+ fenv_var = __builtin_arm_get_fpscr ();
+
+ unsigned int masked_fenv;
+ masked_fenv = fenv_var & mask;
+
+ __builtin_arm_set_fpscr (masked_fenv); */
+
+ fenv_var = create_tmp_var (unsigned_type_node, NULL);
+ get_fpscr = arm_builtin_decls[ARM_BUILTIN_GET_FPSCR];
+ set_fpscr = arm_builtin_decls[ARM_BUILTIN_SET_FPSCR];
+ mask = build_int_cst (unsigned_type_node,
+ ~((ARM_FE_ALL_EXCEPT << ARM_FE_EXCEPT_SHIFT)
+ | ARM_FE_ALL_EXCEPT));
+ ld_fenv = build2 (MODIFY_EXPR, unsigned_type_node,
+ fenv_var, build_call_expr (get_fpscr, 0));
+ masked_fenv = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_var, mask);
+ hold_fnclex = build_call_expr (set_fpscr, 1, masked_fenv);
+ *hold = build2 (COMPOUND_EXPR, void_type_node,
+ build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv),
+ hold_fnclex);
+
+ /* Store the value of masked_fenv to clear the exceptions:
+ __builtin_arm_set_fpscr (masked_fenv); */
+
+ *clear = build_call_expr (set_fpscr, 1, masked_fenv);
+
+ /* Generate the equivalent of :
+ unsigned int new_fenv_var;
+ new_fenv_var = __builtin_arm_get_fpscr ();
+
+ __builtin_arm_set_fpscr (fenv_var);
+
+ __atomic_feraiseexcept (new_fenv_var); */
+
+ new_fenv_var = create_tmp_var (unsigned_type_node, NULL);
+ reload_fenv = build2 (MODIFY_EXPR, unsigned_type_node, new_fenv_var,
+ build_call_expr (get_fpscr, 0));
+ restore_fnenv = build_call_expr (set_fpscr, 1, fenv_var);
+ atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
+ update_call = build_call_expr (atomic_feraiseexcept, 1,
+ fold_convert (integer_type_node, new_fenv_var));
+ *update = build2 (COMPOUND_EXPR, void_type_node,
+ build2 (COMPOUND_EXPR, void_type_node,
+ reload_fenv, restore_fnenv), update_call);
+}
+
#include "gt-arm.h"
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 96f3efeb246..c32502694e4 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -17,8 +17,13 @@
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_ARM_H
@@ -2390,5 +2395,5 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#endif
#define DRIVER_SELF_SPECS MCPU_MTUNE_NATIVE_SPECS
-
+#define TARGET_SUPPORTS_WIDE_INT 1
#endif /* ! GCC_ARM_H */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 97753ce1e98..bec889a954f 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -200,17 +200,9 @@
(const_string "yes")]
(const_string "no")))
-; Allows an insn to disable certain alternatives for reasons other than
-; arch support.
-(define_attr "insn_enabled" "no,yes"
- (const_string "yes"))
-
; Enable all alternatives that are both arch_enabled and insn_enabled.
(define_attr "enabled" "no,yes"
- (cond [(eq_attr "insn_enabled" "no")
- (const_string "no")
-
- (and (eq_attr "predicable_short_it" "no")
+ (cond [(and (eq_attr "predicable_short_it" "no")
(and (eq_attr "predicated" "yes")
(match_test "arm_restrict_it")))
(const_string "no")
@@ -3169,7 +3161,7 @@
(define_insn_and_split "*xordi3_insn"
[(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
- (xor:DI (match_operand:DI 1 "s_register_operand" "w ,%0,r ,0 ,r ,w")
+ (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
(match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
"TARGET_32BIT && !TARGET_IWMMXT"
{
@@ -5998,7 +5990,7 @@
(define_split
[(set (match_operand:ANY64 0 "arm_general_register_operand" "")
- (match_operand:ANY64 1 "const_double_operand" ""))]
+ (match_operand:ANY64 1 "immediate_operand" ""))]
"TARGET_32BIT
&& reload_completed
&& (arm_const_double_inline_cost (operands[1])
@@ -8371,8 +8363,8 @@
(define_insn_and_split "*arm_cmpdi_unsigned"
[(set (reg:CC_CZ CC_REGNUM)
- (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r")
- (match_operand:DI 1 "arm_di_operand" "Py,r,rDi")))]
+ (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
+ (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
"TARGET_32BIT"
"#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
@@ -8392,9 +8384,9 @@
operands[1] = gen_lowpart (SImode, operands[1]);
}
[(set_attr "conds" "set")
- (set_attr "enabled_for_depr_it" "yes,yes,no")
- (set_attr "arch" "t2,t2,*")
- (set_attr "length" "6,6,8")
+ (set_attr "enabled_for_depr_it" "yes,yes,no,*")
+ (set_attr "arch" "t2,t2,t2,a")
+ (set_attr "length" "6,6,10,8")
(set_attr "type" "multiple")]
)
@@ -9876,37 +9868,34 @@
;; Patterns to allow combination of arithmetic, cond code and shifts
-(define_insn "*arith_shiftsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
- (match_operator:SI 1 "shiftable_operator"
- [(match_operator:SI 3 "shift_operator"
- [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
- (match_operand:SI 5 "shift_amount_operand" "M,M,M,r")])
- (match_operand:SI 2 "s_register_operand" "rk,rk,r,rk")]))]
+(define_insn "*<arith_shift_insn>_multsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (shiftable_ops:SI
+ (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
+ (match_operand:SI 3 "power_of_two_operand" ""))
+ (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
"TARGET_32BIT"
- "%i1%?\\t%0, %2, %4%S3"
+ "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
[(set_attr "predicable" "yes")
+ (set_attr "predicable_short_it" "no")
+ (set_attr "shift" "4")
+ (set_attr "arch" "a,t2")
+ (set_attr "type" "alu_shift_imm")])
+
+(define_insn "*<arith_shift_insn>_shiftsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
+ (shiftable_ops:SI
+ (match_operator:SI 2 "shift_nomul_operator"
+ [(match_operand:SI 3 "s_register_operand" "r,r,r")
+ (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
+ (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
+ "TARGET_32BIT && GET_CODE (operands[3]) != MULT"
+ "<arith_shift_insn>%?\\t%0, %1, %3%S2"
+ [(set_attr "predicable" "yes")
+ (set_attr "predicable_short_it" "no")
(set_attr "shift" "4")
- (set_attr "arch" "a,t2,t2,a")
- ;; Thumb2 doesn't allow the stack pointer to be used for
- ;; operand1 for all operations other than add and sub. In this case
- ;; the minus operation is a candidate for an rsub and hence needs
- ;; to be disabled.
- ;; We have to make sure to disable the fourth alternative if
- ;; the shift_operator is MULT, since otherwise the insn will
- ;; also match a multiply_accumulate pattern and validate_change
- ;; will allow a replacement of the constant with a register
- ;; despite the checks done in shift_operator.
- (set_attr_alternative "insn_enabled"
- [(const_string "yes")
- (if_then_else
- (match_operand:SI 1 "add_operator" "")
- (const_string "yes") (const_string "no"))
- (const_string "yes")
- (if_then_else
- (match_operand:SI 3 "mult_operator" "")
- (const_string "no") (const_string "yes"))])
- (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_imm,alu_shift_reg")])
+ (set_attr "arch" "a,t2,a")
+ (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
(define_split
[(set (match_operand:SI 0 "s_register_operand" "")
diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h
index 37a6e611b48..af2d3b34e37 100644
--- a/gcc/config/arm/arm_neon.h
+++ b/gcc/config/arm/arm_neon.h
@@ -1,5 +1,4 @@
-/* ARM NEON intrinsics include file. This file is generated automatically
- using neon-gen.ml. Please do not edit manually.
+/* ARM NEON intrinsics include file.
Copyright (C) 2006-2014 Free Software Foundation, Inc.
Contributed by CodeSourcery.
@@ -453,114 +452,121 @@ typedef struct poly64x2x4_t
} poly64x2x4_t;
#endif
-
-
+/* vadd */
__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
vadd_s8 (int8x8_t __a, int8x8_t __b)
{
- return (int8x8_t)__builtin_neon_vaddv8qi (__a, __b, 1);
+ return __a + __b;
}
__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
vadd_s16 (int16x4_t __a, int16x4_t __b)
{
- return (int16x4_t)__builtin_neon_vaddv4hi (__a, __b, 1);
+ return __a + __b;
}
__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
vadd_s32 (int32x2_t __a, int32x2_t __b)
{
- return (int32x2_t)__builtin_neon_vaddv2si (__a, __b, 1);
+ return __a + __b;
}
__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
vadd_f32 (float32x2_t __a, float32x2_t __b)
{
- return (float32x2_t)__builtin_neon_vaddv2sf (__a, __b, 3);
+#ifdef __FAST_MATH__
+ return __a + __b;
+#else
+ return (float32x2_t) __builtin_neon_vaddv2sf (__a, __b, 3);
+#endif
}
__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
vadd_u8 (uint8x8_t __a, uint8x8_t __b)
{
- return (uint8x8_t)__builtin_neon_vaddv8qi ((int8x8_t) __a, (int8x8_t) __b, 0);
+ return __a + __b;
}
__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
vadd_u16 (uint16x4_t __a, uint16x4_t __b)
{
- return (uint16x4_t)__builtin_neon_vaddv4hi ((int16x4_t) __a, (int16x4_t) __b, 0);
+ return __a + __b;
}
__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
vadd_u32 (uint32x2_t __a, uint32x2_t __b)
{
- return (uint32x2_t)__builtin_neon_vaddv2si ((int32x2_t) __a, (int32x2_t) __b, 0);
+ return __a + __b;
}
__extension__ static __inline int64x1_t __attribute__ ((__always_inline__))
vadd_s64 (int64x1_t __a, int64x1_t __b)
{
- return (int64x1_t)__builtin_neon_vadddi (__a, __b, 1);
+ return __a + __b;
}
__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
vadd_u64 (uint64x1_t __a, uint64x1_t __b)
{
- return (uint64x1_t)__builtin_neon_vadddi ((int64x1_t) __a, (int64x1_t) __b, 0);
+ return __a + __b;
}
__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
vaddq_s8 (int8x16_t __a, int8x16_t __b)
{
- return (int8x16_t)__builtin_neon_vaddv16qi (__a, __b, 1);
+ return __a + __b;
}
__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
vaddq_s16 (int16x8_t __a, int16x8_t __b)
{
- return (int16x8_t)__builtin_neon_vaddv8hi (__a, __b, 1);
+ return __a + __b;
}
__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
vaddq_s32 (int32x4_t __a, int32x4_t __b)
{
- return (int32x4_t)__builtin_neon_vaddv4si (__a, __b, 1);
+ return __a + __b;
}
__extension__ static __inline int64x2_t __attribute__ ((__always_inline__))
vaddq_s64 (int64x2_t __a, int64x2_t __b)
{
- return (int64x2_t)__builtin_neon_vaddv2di (__a, __b, 1);
+ return __a + __b;
}
__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
vaddq_f32 (float32x4_t __a, float32x4_t __b)
{
- return (float32x4_t)__builtin_neon_vaddv4sf (__a, __b, 3);
+#ifdef __FAST_MATH
+ return __a + __b;
+#else
+ return (float32x4_t) __builtin_neon_vaddv4sf (__a, __b, 3);
+#endif
}
__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
vaddq_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return (uint8x16_t)__builtin_neon_vaddv16qi ((int8x16_t) __a, (int8x16_t) __b, 0);
+ return __a + __b;
}
__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
vaddq_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return (uint16x8_t)__builtin_neon_vaddv8hi ((int16x8_t) __a, (int16x8_t) __b, 0);
+ return __a + __b;
}
__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
vaddq_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return (uint32x4_t)__builtin_neon_vaddv4si ((int32x4_t) __a, (int32x4_t) __b, 0);
+ return __a + __b;
}
__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__))
vaddq_u64 (uint64x2_t __a, uint64x2_t __b)
{
- return (uint64x2_t)__builtin_neon_vaddv2di ((int64x2_t) __a, (int64x2_t) __b, 0);
+ return __a + __b;
}
__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
@@ -950,91 +956,100 @@ vraddhn_u64 (uint64x2_t __a, uint64x2_t __b)
__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
vmul_s8 (int8x8_t __a, int8x8_t __b)
{
- return (int8x8_t)__builtin_neon_vmulv8qi (__a, __b, 1);
+ return __a * __b;
}
__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
vmul_s16 (int16x4_t __a, int16x4_t __b)
{
- return (int16x4_t)__builtin_neon_vmulv4hi (__a, __b, 1);
+ return __a * __b;
}
__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
vmul_s32 (int32x2_t __a, int32x2_t __b)
{
- return (int32x2_t)__builtin_neon_vmulv2si (__a, __b, 1);
+ return __a * __b;
}
__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
vmul_f32 (float32x2_t __a, float32x2_t __b)
{
- return (float32x2_t)__builtin_neon_vmulv2sf (__a, __b, 3);
+#ifdef __FAST_MATH
+ return __a * __b;
+#else
+ return (float32x2_t) __builtin_neon_vmulv2sf (__a, __b, 3);
+#endif
+
}
__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
vmul_u8 (uint8x8_t __a, uint8x8_t __b)
{
- return (uint8x8_t)__builtin_neon_vmulv8qi ((int8x8_t) __a, (int8x8_t) __b, 0);
+ return __a * __b;
}
__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
vmul_u16 (uint16x4_t __a, uint16x4_t __b)
{
- return (uint16x4_t)__builtin_neon_vmulv4hi ((int16x4_t) __a, (int16x4_t) __b, 0);
+ return __a * __b;
}
__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
vmul_u32 (uint32x2_t __a, uint32x2_t __b)
{
- return (uint32x2_t)__builtin_neon_vmulv2si ((int32x2_t) __a, (int32x2_t) __b, 0);
-}
-
-__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
-vmul_p8 (poly8x8_t __a, poly8x8_t __b)
-{
- return (poly8x8_t)__builtin_neon_vmulv8qi ((int8x8_t) __a, (int8x8_t) __b, 2);
+ return __a * __b;
}
__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
vmulq_s8 (int8x16_t __a, int8x16_t __b)
{
- return (int8x16_t)__builtin_neon_vmulv16qi (__a, __b, 1);
+ return __a * __b;
}
__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
vmulq_s16 (int16x8_t __a, int16x8_t __b)
{
- return (int16x8_t)__builtin_neon_vmulv8hi (__a, __b, 1);
+ return __a * __b;
}
__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
vmulq_s32 (int32x4_t __a, int32x4_t __b)
{
- return (int32x4_t)__builtin_neon_vmulv4si (__a, __b, 1);
+ return __a * __b;
}
__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
vmulq_f32 (float32x4_t __a, float32x4_t __b)
{
- return (float32x4_t)__builtin_neon_vmulv4sf (__a, __b, 3);
+#ifdef __FAST_MATH
+ return __a * __b;
+#else
+ return (float32x4_t) __builtin_neon_vmulv4sf (__a, __b, 3);
+#endif
}
__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
vmulq_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return (uint8x16_t)__builtin_neon_vmulv16qi ((int8x16_t) __a, (int8x16_t) __b, 0);
+ return __a * __b;
}
__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
vmulq_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return (uint16x8_t)__builtin_neon_vmulv8hi ((int16x8_t) __a, (int16x8_t) __b, 0);
+ return __a * __b;
}
__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
vmulq_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return (uint32x4_t)__builtin_neon_vmulv4si ((int32x4_t) __a, (int32x4_t) __b, 0);
+ return __a * __b;
+}
+
+__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
+vmul_p8 (poly8x8_t __a, poly8x8_t __b)
+{
+ return (poly8x8_t)__builtin_neon_vmulv8qi ((int8x8_t) __a, (int8x8_t) __b, 2);
}
__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
@@ -1521,112 +1536,121 @@ vrndq_f32 (float32x4_t __a)
}
#endif
+
__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
vsub_s8 (int8x8_t __a, int8x8_t __b)
{
- return (int8x8_t)__builtin_neon_vsubv8qi (__a, __b, 1);
+ return __a - __b;
}
__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
vsub_s16 (int16x4_t __a, int16x4_t __b)
{
- return (int16x4_t)__builtin_neon_vsubv4hi (__a, __b, 1);
+ return __a - __b;
}
__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
vsub_s32 (int32x2_t __a, int32x2_t __b)
{
- return (int32x2_t)__builtin_neon_vsubv2si (__a, __b, 1);
+ return __a - __b;
}
__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
vsub_f32 (float32x2_t __a, float32x2_t __b)
{
- return (float32x2_t)__builtin_neon_vsubv2sf (__a, __b, 3);
+#ifdef __FAST_MATH
+ return __a - __b;
+#else
+ return (float32x2_t) __builtin_neon_vsubv2sf (__a, __b, 3);
+#endif
}
__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
vsub_u8 (uint8x8_t __a, uint8x8_t __b)
{
- return (uint8x8_t)__builtin_neon_vsubv8qi ((int8x8_t) __a, (int8x8_t) __b, 0);
+ return __a - __b;
}
__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
vsub_u16 (uint16x4_t __a, uint16x4_t __b)
{
- return (uint16x4_t)__builtin_neon_vsubv4hi ((int16x4_t) __a, (int16x4_t) __b, 0);
+ return __a - __b;
}
__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
vsub_u32 (uint32x2_t __a, uint32x2_t __b)
{
- return (uint32x2_t)__builtin_neon_vsubv2si ((int32x2_t) __a, (int32x2_t) __b, 0);
+ return __a - __b;
}
__extension__ static __inline int64x1_t __attribute__ ((__always_inline__))
vsub_s64 (int64x1_t __a, int64x1_t __b)
{
- return (int64x1_t)__builtin_neon_vsubdi (__a, __b, 1);
+ return __a - __b;
}
__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
vsub_u64 (uint64x1_t __a, uint64x1_t __b)
{
- return (uint64x1_t)__builtin_neon_vsubdi ((int64x1_t) __a, (int64x1_t) __b, 0);
+ return __a - __b;
}
__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
vsubq_s8 (int8x16_t __a, int8x16_t __b)
{
- return (int8x16_t)__builtin_neon_vsubv16qi (__a, __b, 1);
+ return __a - __b;
}
__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
vsubq_s16 (int16x8_t __a, int16x8_t __b)
{
- return (int16x8_t)__builtin_neon_vsubv8hi (__a, __b, 1);
+ return __a - __b;
}
__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
vsubq_s32 (int32x4_t __a, int32x4_t __b)
{
- return (int32x4_t)__builtin_neon_vsubv4si (__a, __b, 1);
+ return __a - __b;
}
__extension__ static __inline int64x2_t __attribute__ ((__always_inline__))
vsubq_s64 (int64x2_t __a, int64x2_t __b)
{
- return (int64x2_t)__builtin_neon_vsubv2di (__a, __b, 1);
+ return __a - __b;
}
__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
vsubq_f32 (float32x4_t __a, float32x4_t __b)
{
- return (float32x4_t)__builtin_neon_vsubv4sf (__a, __b, 3);
+#ifdef __FAST_MATH
+ return __a - __b;
+#else
+ return (float32x4_t) __builtin_neon_vsubv4sf (__a, __b, 3);
+#endif
}
__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
vsubq_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return (uint8x16_t)__builtin_neon_vsubv16qi ((int8x16_t) __a, (int8x16_t) __b, 0);
+ return __a - __b;
}
__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
vsubq_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return (uint16x8_t)__builtin_neon_vsubv8hi ((int16x8_t) __a, (int16x8_t) __b, 0);
+ return __a - __b;
}
__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
vsubq_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return (uint32x4_t)__builtin_neon_vsubv4si ((int32x4_t) __a, (int32x4_t) __b, 0);
+ return __a - __b;
}
__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__))
vsubq_u64 (uint64x2_t __a, uint64x2_t __b)
{
- return (uint64x2_t)__builtin_neon_vsubv2di ((int64x2_t) __a, (int64x2_t) __b, 0);
+ return __a - __b;
}
__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
@@ -10907,484 +10931,483 @@ vst4q_lane_p16 (poly16_t * __a, poly16x8x4_t __b, const int __c)
__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
vand_s8 (int8x8_t __a, int8x8_t __b)
{
- return (int8x8_t)__builtin_neon_vandv8qi (__a, __b, 1);
+ return __a & __b;
}
__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
vand_s16 (int16x4_t __a, int16x4_t __b)
{
- return (int16x4_t)__builtin_neon_vandv4hi (__a, __b, 1);
+ return __a & __b;
}
__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
vand_s32 (int32x2_t __a, int32x2_t __b)
{
- return (int32x2_t)__builtin_neon_vandv2si (__a, __b, 1);
+ return __a & __b;
}
__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
vand_u8 (uint8x8_t __a, uint8x8_t __b)
{
- return (uint8x8_t)__builtin_neon_vandv8qi ((int8x8_t) __a, (int8x8_t) __b, 0);
+ return __a & __b;
}
__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
vand_u16 (uint16x4_t __a, uint16x4_t __b)
{
- return (uint16x4_t)__builtin_neon_vandv4hi ((int16x4_t) __a, (int16x4_t) __b, 0);
+ return __a & __b;
}
__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
vand_u32 (uint32x2_t __a, uint32x2_t __b)
{
- return (uint32x2_t)__builtin_neon_vandv2si ((int32x2_t) __a, (int32x2_t) __b, 0);
+ return __a & __b;
}
__extension__ static __inline int64x1_t __attribute__ ((__always_inline__))
vand_s64 (int64x1_t __a, int64x1_t __b)
{
- return (int64x1_t)__builtin_neon_vanddi (__a, __b, 1);
+ return __a & __b;
}
__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
vand_u64 (uint64x1_t __a, uint64x1_t __b)
{
- return (uint64x1_t)__builtin_neon_vanddi ((int64x1_t) __a, (int64x1_t) __b, 0);
+ return __a & __b;
}
__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
vandq_s8 (int8x16_t __a, int8x16_t __b)
{
- return (int8x16_t)__builtin_neon_vandv16qi (__a, __b, 1);
+ return __a & __b;
}
__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
vandq_s16 (int16x8_t __a, int16x8_t __b)
{
- return (int16x8_t)__builtin_neon_vandv8hi (__a, __b, 1);
+ return __a & __b;
}
__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
vandq_s32 (int32x4_t __a, int32x4_t __b)
{
- return (int32x4_t)__builtin_neon_vandv4si (__a, __b, 1);
+ return __a & __b;
}
__extension__ static __inline int64x2_t __attribute__ ((__always_inline__))
vandq_s64 (int64x2_t __a, int64x2_t __b)
{
- return (int64x2_t)__builtin_neon_vandv2di (__a, __b, 1);
+ return __a & __b;
}
__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
vandq_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return (uint8x16_t)__builtin_neon_vandv16qi ((int8x16_t) __a, (int8x16_t) __b, 0);
+ return __a & __b;
}
__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
vandq_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return (uint16x8_t)__builtin_neon_vandv8hi ((int16x8_t) __a, (int16x8_t) __b, 0);
+ return __a & __b;
}
__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
vandq_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return (uint32x4_t)__builtin_neon_vandv4si ((int32x4_t) __a, (int32x4_t) __b, 0);
+ return __a & __b;
}
__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__))
vandq_u64 (uint64x2_t __a, uint64x2_t __b)
{
- return (uint64x2_t)__builtin_neon_vandv2di ((int64x2_t) __a, (int64x2_t) __b, 0);
+ return __a & __b;
}
__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
vorr_s8 (int8x8_t __a, int8x8_t __b)
{
- return (int8x8_t)__builtin_neon_vorrv8qi (__a, __b, 1);
+ return __a | __b;
}
__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
vorr_s16 (int16x4_t __a, int16x4_t __b)
{
- return (int16x4_t)__builtin_neon_vorrv4hi (__a, __b, 1);
+ return __a | __b;
}
__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
vorr_s32 (int32x2_t __a, int32x2_t __b)
{
- return (int32x2_t)__builtin_neon_vorrv2si (__a, __b, 1);
+ return __a | __b;
}
__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
vorr_u8 (uint8x8_t __a, uint8x8_t __b)
{
- return (uint8x8_t)__builtin_neon_vorrv8qi ((int8x8_t) __a, (int8x8_t) __b, 0);
+ return __a | __b;
}
__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
vorr_u16 (uint16x4_t __a, uint16x4_t __b)
{
- return (uint16x4_t)__builtin_neon_vorrv4hi ((int16x4_t) __a, (int16x4_t) __b, 0);
+ return __a | __b;
}
__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
vorr_u32 (uint32x2_t __a, uint32x2_t __b)
{
- return (uint32x2_t)__builtin_neon_vorrv2si ((int32x2_t) __a, (int32x2_t) __b, 0);
+ return __a | __b;
}
__extension__ static __inline int64x1_t __attribute__ ((__always_inline__))
vorr_s64 (int64x1_t __a, int64x1_t __b)
{
- return (int64x1_t)__builtin_neon_vorrdi (__a, __b, 1);
+ return __a | __b;
}
__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
vorr_u64 (uint64x1_t __a, uint64x1_t __b)
{
- return (uint64x1_t)__builtin_neon_vorrdi ((int64x1_t) __a, (int64x1_t) __b, 0);
+ return __a | __b;
}
__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
vorrq_s8 (int8x16_t __a, int8x16_t __b)
{
- return (int8x16_t)__builtin_neon_vorrv16qi (__a, __b, 1);
+ return __a | __b;
}
__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
vorrq_s16 (int16x8_t __a, int16x8_t __b)
{
- return (int16x8_t)__builtin_neon_vorrv8hi (__a, __b, 1);
+ return __a | __b;
}
__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
vorrq_s32 (int32x4_t __a, int32x4_t __b)
{
- return (int32x4_t)__builtin_neon_vorrv4si (__a, __b, 1);
+ return __a | __b;
}
__extension__ static __inline int64x2_t __attribute__ ((__always_inline__))
vorrq_s64 (int64x2_t __a, int64x2_t __b)
{
- return (int64x2_t)__builtin_neon_vorrv2di (__a, __b, 1);
+ return __a | __b;
}
__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
vorrq_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return (uint8x16_t)__builtin_neon_vorrv16qi ((int8x16_t) __a, (int8x16_t) __b, 0);
+ return __a | __b;
}
__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
vorrq_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return (uint16x8_t)__builtin_neon_vorrv8hi ((int16x8_t) __a, (int16x8_t) __b, 0);
+ return __a | __b;
}
__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
vorrq_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return (uint32x4_t)__builtin_neon_vorrv4si ((int32x4_t) __a, (int32x4_t) __b, 0);
+ return __a | __b;
}
__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__))
vorrq_u64 (uint64x2_t __a, uint64x2_t __b)
{
- return (uint64x2_t)__builtin_neon_vorrv2di ((int64x2_t) __a, (int64x2_t) __b, 0);
+ return __a | __b;
}
__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
veor_s8 (int8x8_t __a, int8x8_t __b)
{
- return (int8x8_t)__builtin_neon_veorv8qi (__a, __b, 1);
+ return __a ^ __b;
}
__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
veor_s16 (int16x4_t __a, int16x4_t __b)
{
- return (int16x4_t)__builtin_neon_veorv4hi (__a, __b, 1);
+ return __a ^ __b;
}
__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
veor_s32 (int32x2_t __a, int32x2_t __b)
{
- return (int32x2_t)__builtin_neon_veorv2si (__a, __b, 1);
+ return __a ^ __b;
}
__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
veor_u8 (uint8x8_t __a, uint8x8_t __b)
{
- return (uint8x8_t)__builtin_neon_veorv8qi ((int8x8_t) __a, (int8x8_t) __b, 0);
+ return __a ^ __b;
}
__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
veor_u16 (uint16x4_t __a, uint16x4_t __b)
{
- return (uint16x4_t)__builtin_neon_veorv4hi ((int16x4_t) __a, (int16x4_t) __b, 0);
+ return __a ^ __b;
}
__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
veor_u32 (uint32x2_t __a, uint32x2_t __b)
{
- return (uint32x2_t)__builtin_neon_veorv2si ((int32x2_t) __a, (int32x2_t) __b, 0);
+ return __a ^ __b;
}
__extension__ static __inline int64x1_t __attribute__ ((__always_inline__))
veor_s64 (int64x1_t __a, int64x1_t __b)
{
- return (int64x1_t)__builtin_neon_veordi (__a, __b, 1);
+ return __a ^ __b;
}
__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
veor_u64 (uint64x1_t __a, uint64x1_t __b)
{
- return (uint64x1_t)__builtin_neon_veordi ((int64x1_t) __a, (int64x1_t) __b, 0);
+ return __a ^ __b;
}
__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
veorq_s8 (int8x16_t __a, int8x16_t __b)
{
- return (int8x16_t)__builtin_neon_veorv16qi (__a, __b, 1);
+ return __a ^ __b;
}
__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
veorq_s16 (int16x8_t __a, int16x8_t __b)
{
- return (int16x8_t)__builtin_neon_veorv8hi (__a, __b, 1);
+ return __a ^ __b;
}
__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
veorq_s32 (int32x4_t __a, int32x4_t __b)
{
- return (int32x4_t)__builtin_neon_veorv4si (__a, __b, 1);
+ return __a ^ __b;
}
__extension__ static __inline int64x2_t __attribute__ ((__always_inline__))
veorq_s64 (int64x2_t __a, int64x2_t __b)
{
- return (int64x2_t)__builtin_neon_veorv2di (__a, __b, 1);
+ return __a ^ __b;
}
__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
veorq_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return (uint8x16_t)__builtin_neon_veorv16qi ((int8x16_t) __a, (int8x16_t) __b, 0);
+ return __a ^ __b;
}
__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
veorq_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return (uint16x8_t)__builtin_neon_veorv8hi ((int16x8_t) __a, (int16x8_t) __b, 0);
+ return __a ^ __b;
}
__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
veorq_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return (uint32x4_t)__builtin_neon_veorv4si ((int32x4_t) __a, (int32x4_t) __b, 0);
+ return __a ^ __b;
}
__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__))
veorq_u64 (uint64x2_t __a, uint64x2_t __b)
{
- return (uint64x2_t)__builtin_neon_veorv2di ((int64x2_t) __a, (int64x2_t) __b, 0);
+ return __a ^ __b;
}
__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
vbic_s8 (int8x8_t __a, int8x8_t __b)
{
- return (int8x8_t)__builtin_neon_vbicv8qi (__a, __b, 1);
+ return __a & ~__b;
}
__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
vbic_s16 (int16x4_t __a, int16x4_t __b)
{
- return (int16x4_t)__builtin_neon_vbicv4hi (__a, __b, 1);
+ return __a & ~__b;
}
__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
vbic_s32 (int32x2_t __a, int32x2_t __b)
{
- return (int32x2_t)__builtin_neon_vbicv2si (__a, __b, 1);
+ return __a & ~__b;
}
__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
vbic_u8 (uint8x8_t __a, uint8x8_t __b)
{
- return (uint8x8_t)__builtin_neon_vbicv8qi ((int8x8_t) __a, (int8x8_t) __b, 0);
+ return __a & ~__b;
}
__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
vbic_u16 (uint16x4_t __a, uint16x4_t __b)
{
- return (uint16x4_t)__builtin_neon_vbicv4hi ((int16x4_t) __a, (int16x4_t) __b, 0);
+ return __a & ~__b;
}
__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
vbic_u32 (uint32x2_t __a, uint32x2_t __b)
{
- return (uint32x2_t)__builtin_neon_vbicv2si ((int32x2_t) __a, (int32x2_t) __b, 0);
+ return __a & ~__b;
}
__extension__ static __inline int64x1_t __attribute__ ((__always_inline__))
vbic_s64 (int64x1_t __a, int64x1_t __b)
{
- return (int64x1_t)__builtin_neon_vbicdi (__a, __b, 1);
+ return __a & ~__b;
}
__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
vbic_u64 (uint64x1_t __a, uint64x1_t __b)
{
- return (uint64x1_t)__builtin_neon_vbicdi ((int64x1_t) __a, (int64x1_t) __b, 0);
+ return __a & ~__b;
}
__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
vbicq_s8 (int8x16_t __a, int8x16_t __b)
{
- return (int8x16_t)__builtin_neon_vbicv16qi (__a, __b, 1);
+ return __a & ~__b;
}
__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
vbicq_s16 (int16x8_t __a, int16x8_t __b)
{
- return (int16x8_t)__builtin_neon_vbicv8hi (__a, __b, 1);
+ return __a & ~__b;
}
__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
vbicq_s32 (int32x4_t __a, int32x4_t __b)
{
- return (int32x4_t)__builtin_neon_vbicv4si (__a, __b, 1);
+ return __a & ~__b;
}
__extension__ static __inline int64x2_t __attribute__ ((__always_inline__))
vbicq_s64 (int64x2_t __a, int64x2_t __b)
{
- return (int64x2_t)__builtin_neon_vbicv2di (__a, __b, 1);
+ return __a & ~__b;
}
__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
vbicq_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return (uint8x16_t)__builtin_neon_vbicv16qi ((int8x16_t) __a, (int8x16_t) __b, 0);
+ return __a & ~__b;
}
__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
vbicq_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return (uint16x8_t)__builtin_neon_vbicv8hi ((int16x8_t) __a, (int16x8_t) __b, 0);
+ return __a & ~__b;
}
__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
vbicq_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return (uint32x4_t)__builtin_neon_vbicv4si ((int32x4_t) __a, (int32x4_t) __b, 0);
+ return __a & ~__b;
}
__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__))
vbicq_u64 (uint64x2_t __a, uint64x2_t __b)
{
- return (uint64x2_t)__builtin_neon_vbicv2di ((int64x2_t) __a, (int64x2_t) __b, 0);
+ return __a & ~__b;
}
__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
vorn_s8 (int8x8_t __a, int8x8_t __b)
{
- return (int8x8_t)__builtin_neon_vornv8qi (__a, __b, 1);
+ return __a | ~__b;
}
__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
vorn_s16 (int16x4_t __a, int16x4_t __b)
{
- return (int16x4_t)__builtin_neon_vornv4hi (__a, __b, 1);
+ return __a | ~__b;
}
__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
vorn_s32 (int32x2_t __a, int32x2_t __b)
{
- return (int32x2_t)__builtin_neon_vornv2si (__a, __b, 1);
+ return __a | ~__b;
}
__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
vorn_u8 (uint8x8_t __a, uint8x8_t __b)
{
- return (uint8x8_t)__builtin_neon_vornv8qi ((int8x8_t) __a, (int8x8_t) __b, 0);
+ return __a | ~__b;
}
__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
vorn_u16 (uint16x4_t __a, uint16x4_t __b)
{
- return (uint16x4_t)__builtin_neon_vornv4hi ((int16x4_t) __a, (int16x4_t) __b, 0);
+ return __a | ~__b;
}
__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
vorn_u32 (uint32x2_t __a, uint32x2_t __b)
{
- return (uint32x2_t)__builtin_neon_vornv2si ((int32x2_t) __a, (int32x2_t) __b, 0);
+ return __a | ~__b;
}
__extension__ static __inline int64x1_t __attribute__ ((__always_inline__))
vorn_s64 (int64x1_t __a, int64x1_t __b)
{
- return (int64x1_t)__builtin_neon_vorndi (__a, __b, 1);
+ return __a | ~__b;
}
__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
vorn_u64 (uint64x1_t __a, uint64x1_t __b)
{
- return (uint64x1_t)__builtin_neon_vorndi ((int64x1_t) __a, (int64x1_t) __b, 0);
+ return __a | ~__b;
}
__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
vornq_s8 (int8x16_t __a, int8x16_t __b)
{
- return (int8x16_t)__builtin_neon_vornv16qi (__a, __b, 1);
+ return __a | ~__b;
}
__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
vornq_s16 (int16x8_t __a, int16x8_t __b)
{
- return (int16x8_t)__builtin_neon_vornv8hi (__a, __b, 1);
+ return __a | ~__b;
}
__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
vornq_s32 (int32x4_t __a, int32x4_t __b)
{
- return (int32x4_t)__builtin_neon_vornv4si (__a, __b, 1);
+ return __a | ~__b;
}
__extension__ static __inline int64x2_t __attribute__ ((__always_inline__))
vornq_s64 (int64x2_t __a, int64x2_t __b)
{
- return (int64x2_t)__builtin_neon_vornv2di (__a, __b, 1);
+ return __a | ~__b;
}
__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
vornq_u8 (uint8x16_t __a, uint8x16_t __b)
{
- return (uint8x16_t)__builtin_neon_vornv16qi ((int8x16_t) __a, (int8x16_t) __b, 0);
+ return __a | ~__b;
}
__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
vornq_u16 (uint16x8_t __a, uint16x8_t __b)
{
- return (uint16x8_t)__builtin_neon_vornv8hi ((int16x8_t) __a, (int16x8_t) __b, 0);
+ return __a | ~__b;
}
__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
vornq_u32 (uint32x4_t __a, uint32x4_t __b)
{
- return (uint32x4_t)__builtin_neon_vornv4si ((int32x4_t) __a, (int32x4_t) __b, 0);
+ return __a | ~__b;
}
__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__))
vornq_u64 (uint64x2_t __a, uint64x2_t __b)
{
- return (uint64x2_t)__builtin_neon_vornv2di ((int64x2_t) __a, (int64x2_t) __b, 0);
+ return __a | ~__b;
}
-
__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
vreinterpret_p8_p16 (poly16x4_t __a)
{
diff --git a/gcc/config/arm/arm_neon_builtins.def b/gcc/config/arm/arm_neon_builtins.def
index a00951ab65b..f4531f36e7a 100644
--- a/gcc/config/arm/arm_neon_builtins.def
+++ b/gcc/config/arm/arm_neon_builtins.def
@@ -18,8 +18,7 @@
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-VAR10 (BINOP, vadd,
- v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di),
+VAR2 (BINOP, vadd, v2sf, v4sf),
VAR3 (BINOP, vaddl, v8qi, v4hi, v2si),
VAR3 (BINOP, vaddw, v8qi, v4hi, v2si),
VAR6 (BINOP, vhadd, v8qi, v4hi, v2si, v16qi, v8hi, v4si),
@@ -54,7 +53,7 @@ VAR8 (SHIFTIMM, vqshl_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di),
VAR8 (SHIFTIMM, vqshlu_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di),
VAR3 (SHIFTIMM, vshll_n, v8qi, v4hi, v2si),
VAR8 (SHIFTACC, vsra_n, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di),
-VAR10 (BINOP, vsub, v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di),
+VAR2 (BINOP, vsub, v2sf, v4sf),
VAR3 (BINOP, vsubl, v8qi, v4hi, v2si),
VAR3 (BINOP, vsubw, v8qi, v4hi, v2si),
VAR8 (BINOP, vqsub, v8qi, v4hi, v2si, di, v16qi, v8hi, v4si, v2di),
@@ -89,6 +88,7 @@ VAR8 (UNOP, vneg, v8qi, v4hi, v2si, v2sf, v16qi, v8hi, v4si, v4sf),
VAR6 (UNOP, vqneg, v8qi, v4hi, v2si, v16qi, v8hi, v4si),
VAR6 (UNOP, vcls, v8qi, v4hi, v2si, v16qi, v8hi, v4si),
VAR6 (UNOP, vclz, v8qi, v4hi, v2si, v16qi, v8hi, v4si),
+VAR5 (BSWAP, bswap, v4hi, v8hi, v2si, v4si, v2di),
VAR2 (UNOP, vcnt, v8qi, v16qi),
VAR4 (UNOP, vrecpe, v2si, v2sf, v4si, v4sf),
VAR4 (UNOP, vrsqrte, v2si, v2sf, v4si, v4sf),
@@ -149,9 +149,6 @@ VAR1 (VTBX, vtbx1, v8qi),
VAR1 (VTBX, vtbx2, v8qi),
VAR1 (VTBX, vtbx3, v8qi),
VAR1 (VTBX, vtbx4, v8qi),
-VAR8 (RESULTPAIR, vtrn, v8qi, v4hi, v2si, v2sf, v16qi, v8hi, v4si, v4sf),
-VAR8 (RESULTPAIR, vzip, v8qi, v4hi, v2si, v2sf, v16qi, v8hi, v4si, v4sf),
-VAR8 (RESULTPAIR, vuzp, v8qi, v4hi, v2si, v2sf, v16qi, v8hi, v4si, v4sf),
VAR5 (REINTERP, vreinterpretv8qi, v8qi, v4hi, v2si, v2sf, di),
VAR5 (REINTERP, vreinterpretv4hi, v8qi, v4hi, v2si, v2sf, di),
VAR5 (REINTERP, vreinterpretv2si, v8qi, v4hi, v2si, v2sf, di),
@@ -199,14 +196,4 @@ VAR5 (LOADSTRUCT, vld4_dup, v8qi, v4hi, v2si, v2sf, di),
VAR9 (STORESTRUCT, vst4,
v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf),
VAR7 (STORESTRUCTLANE, vst4_lane,
- v8qi, v4hi, v2si, v2sf, v8hi, v4si, v4sf),
-VAR10 (LOGICBINOP, vand,
- v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di),
-VAR10 (LOGICBINOP, vorr,
- v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di),
-VAR10 (BINOP, veor,
- v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di),
-VAR10 (LOGICBINOP, vbic,
- v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di),
-VAR10 (LOGICBINOP, vorn,
- v8qi, v4hi, v2si, v2sf, di, v16qi, v8hi, v4si, v4sf, v2di)
+ v8qi, v4hi, v2si, v2sf, v8hi, v4si, v4sf)
diff --git a/gcc/config/arm/bpabi.h b/gcc/config/arm/bpabi.h
index bc223f8e300..7a576ac466c 100644
--- a/gcc/config/arm/bpabi.h
+++ b/gcc/config/arm/bpabi.h
@@ -14,8 +14,13 @@
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* Use the AAPCS ABI by default. */
diff --git a/gcc/config/arm/elf.h b/gcc/config/arm/elf.h
index 2ac8c8d048c..f14c766935f 100644
--- a/gcc/config/arm/elf.h
+++ b/gcc/config/arm/elf.h
@@ -16,8 +16,13 @@
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef OBJECT_FORMAT_ELF
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index aebab934049..6fe6eef2736 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -116,6 +116,9 @@
;; Vector modes including 64-bit integer elements, but no floats.
(define_mode_iterator VDQIX [V8QI V16QI V4HI V8HI V2SI V4SI DI V2DI])
+;; Vector modes for H, S and D types.
+(define_mode_iterator VDQHSD [V4HI V8HI V2SI V4SI V2DI])
+
;; Vector modes for float->int conversions.
(define_mode_iterator VCVTF [V2SF V4SF])
@@ -191,6 +194,20 @@
;; Right shifts
(define_code_iterator rshifts [ashiftrt lshiftrt])
+;; Binary operators whose second operand can be shifted.
+(define_code_iterator shiftable_ops [plus minus ior xor and])
+
+;; plus and minus are the only shiftable_ops for which Thumb2 allows
+;; a stack pointer opoerand. The minus operation is a candidate for an rsub
+;; and hence only plus is supported.
+(define_code_attr t2_binop0
+ [(plus "rk") (minus "r") (ior "r") (xor "r") (and "r")])
+
+;; The instruction to use when a shiftable_ops has a shift operation as
+;; its first operand.
+(define_code_attr arith_shift_insn
+ [(plus "add") (minus "rsb") (ior "orr") (xor "eor") (and "and")])
+
;;----------------------------------------------------------------------------
;; Int iterators
;;----------------------------------------------------------------------------
diff --git a/gcc/config/arm/linux-elf.h b/gcc/config/arm/linux-elf.h
index 5dc3328e839..2bf361a4929 100644
--- a/gcc/config/arm/linux-elf.h
+++ b/gcc/config/arm/linux-elf.h
@@ -14,8 +14,13 @@
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* elfos.h should have already been included. Now just override
diff --git a/gcc/config/arm/linux-gas.h b/gcc/config/arm/linux-gas.h
index 52a739c2674..1dd043782eb 100644
--- a/gcc/config/arm/linux-gas.h
+++ b/gcc/config/arm/linux-gas.h
@@ -15,8 +15,13 @@
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* This is how we tell the assembler that a symbol is weak.
diff --git a/gcc/config/arm/neon-docgen.ml b/gcc/config/arm/neon-docgen.ml
deleted file mode 100644
index 5788a533e19..00000000000
--- a/gcc/config/arm/neon-docgen.ml
+++ /dev/null
@@ -1,424 +0,0 @@
-(* ARM NEON documentation generator.
-
- Copyright (C) 2006-2014 Free Software Foundation, Inc.
- Contributed by CodeSourcery.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>.
-
- This is an O'Caml program. The O'Caml compiler is available from:
-
- http://caml.inria.fr/
-
- Or from your favourite OS's friendly packaging system. Tested with version
- 3.09.2, though other versions will probably work too.
-
- Compile with:
- ocamlc -c neon.ml
- ocamlc -o neon-docgen neon.cmo neon-docgen.ml
-
- Run with:
- /path/to/neon-docgen /path/to/gcc/doc/arm-neon-intrinsics.texi
-*)
-
-open Neon
-
-(* The combined "ops" and "reinterp" table. *)
-let ops_reinterp = reinterp @ ops
-
-(* Helper functions for extracting things from the "ops" table. *)
-let single_opcode desired_opcode () =
- List.fold_left (fun got_so_far ->
- fun row ->
- match row with
- (opcode, _, _, _, _, _) ->
- if opcode = desired_opcode then row :: got_so_far
- else got_so_far
- ) [] ops_reinterp
-
-let multiple_opcodes desired_opcodes () =
- List.fold_left (fun got_so_far ->
- fun desired_opcode ->
- (single_opcode desired_opcode ()) @ got_so_far)
- [] desired_opcodes
-
-let ldx_opcode number () =
- List.fold_left (fun got_so_far ->
- fun row ->
- match row with
- (opcode, _, _, _, _, _) ->
- match opcode with
- Vldx n | Vldx_lane n | Vldx_dup n when n = number ->
- row :: got_so_far
- | _ -> got_so_far
- ) [] ops_reinterp
-
-let stx_opcode number () =
- List.fold_left (fun got_so_far ->
- fun row ->
- match row with
- (opcode, _, _, _, _, _) ->
- match opcode with
- Vstx n | Vstx_lane n when n = number ->
- row :: got_so_far
- | _ -> got_so_far
- ) [] ops_reinterp
-
-let tbl_opcode () =
- List.fold_left (fun got_so_far ->
- fun row ->
- match row with
- (opcode, _, _, _, _, _) ->
- match opcode with
- Vtbl _ -> row :: got_so_far
- | _ -> got_so_far
- ) [] ops_reinterp
-
-let tbx_opcode () =
- List.fold_left (fun got_so_far ->
- fun row ->
- match row with
- (opcode, _, _, _, _, _) ->
- match opcode with
- Vtbx _ -> row :: got_so_far
- | _ -> got_so_far
- ) [] ops_reinterp
-
-(* The groups of intrinsics. *)
-let intrinsic_groups =
- [ "Addition", single_opcode Vadd;
- "Multiplication", single_opcode Vmul;
- "Multiply-accumulate", single_opcode Vmla;
- "Multiply-subtract", single_opcode Vmls;
- "Fused-multiply-accumulate", single_opcode Vfma;
- "Fused-multiply-subtract", single_opcode Vfms;
- "Round to integral (to nearest, ties to even)", single_opcode Vrintn;
- "Round to integral (to nearest, ties away from zero)", single_opcode Vrinta;
- "Round to integral (towards +Inf)", single_opcode Vrintp;
- "Round to integral (towards -Inf)", single_opcode Vrintm;
- "Round to integral (towards 0)", single_opcode Vrintz;
- "Subtraction", single_opcode Vsub;
- "Comparison (equal-to)", single_opcode Vceq;
- "Comparison (greater-than-or-equal-to)", single_opcode Vcge;
- "Comparison (less-than-or-equal-to)", single_opcode Vcle;
- "Comparison (greater-than)", single_opcode Vcgt;
- "Comparison (less-than)", single_opcode Vclt;
- "Comparison (absolute greater-than-or-equal-to)", single_opcode Vcage;
- "Comparison (absolute less-than-or-equal-to)", single_opcode Vcale;
- "Comparison (absolute greater-than)", single_opcode Vcagt;
- "Comparison (absolute less-than)", single_opcode Vcalt;
- "Test bits", single_opcode Vtst;
- "Absolute difference", single_opcode Vabd;
- "Absolute difference and accumulate", single_opcode Vaba;
- "Maximum", single_opcode Vmax;
- "Minimum", single_opcode Vmin;
- "Pairwise add", single_opcode Vpadd;
- "Pairwise add, single_opcode widen and accumulate", single_opcode Vpada;
- "Folding maximum", single_opcode Vpmax;
- "Folding minimum", single_opcode Vpmin;
- "Reciprocal step", multiple_opcodes [Vrecps; Vrsqrts];
- "Vector shift left", single_opcode Vshl;
- "Vector shift left by constant", single_opcode Vshl_n;
- "Vector shift right by constant", single_opcode Vshr_n;
- "Vector shift right by constant and accumulate", single_opcode Vsra_n;
- "Vector shift right and insert", single_opcode Vsri;
- "Vector shift left and insert", single_opcode Vsli;
- "Absolute value", single_opcode Vabs;
- "Negation", single_opcode Vneg;
- "Bitwise not", single_opcode Vmvn;
- "Count leading sign bits", single_opcode Vcls;
- "Count leading zeros", single_opcode Vclz;
- "Count number of set bits", single_opcode Vcnt;
- "Reciprocal estimate", single_opcode Vrecpe;
- "Reciprocal square-root estimate", single_opcode Vrsqrte;
- "Get lanes from a vector", single_opcode Vget_lane;
- "Set lanes in a vector", single_opcode Vset_lane;
- "Create vector from literal bit pattern", single_opcode Vcreate;
- "Set all lanes to the same value",
- multiple_opcodes [Vdup_n; Vmov_n; Vdup_lane];
- "Combining vectors", single_opcode Vcombine;
- "Splitting vectors", multiple_opcodes [Vget_high; Vget_low];
- "Conversions", multiple_opcodes [Vcvt; Vcvt_n];
- "Move, single_opcode narrowing", single_opcode Vmovn;
- "Move, single_opcode long", single_opcode Vmovl;
- "Table lookup", tbl_opcode;
- "Extended table lookup", tbx_opcode;
- "Multiply, lane", single_opcode Vmul_lane;
- "Long multiply, lane", single_opcode Vmull_lane;
- "Saturating doubling long multiply, lane", single_opcode Vqdmull_lane;
- "Saturating doubling multiply high, lane", single_opcode Vqdmulh_lane;
- "Multiply-accumulate, lane", single_opcode Vmla_lane;
- "Multiply-subtract, lane", single_opcode Vmls_lane;
- "Vector multiply by scalar", single_opcode Vmul_n;
- "Vector long multiply by scalar", single_opcode Vmull_n;
- "Vector saturating doubling long multiply by scalar",
- single_opcode Vqdmull_n;
- "Vector saturating doubling multiply high by scalar",
- single_opcode Vqdmulh_n;
- "Vector multiply-accumulate by scalar", single_opcode Vmla_n;
- "Vector multiply-subtract by scalar", single_opcode Vmls_n;
- "Vector extract", single_opcode Vext;
- "Reverse elements", multiple_opcodes [Vrev64; Vrev32; Vrev16];
- "Bit selection", single_opcode Vbsl;
- "Transpose elements", single_opcode Vtrn;
- "Zip elements", single_opcode Vzip;
- "Unzip elements", single_opcode Vuzp;
- "Element/structure loads, VLD1 variants", ldx_opcode 1;
- "Element/structure stores, VST1 variants", stx_opcode 1;
- "Element/structure loads, VLD2 variants", ldx_opcode 2;
- "Element/structure stores, VST2 variants", stx_opcode 2;
- "Element/structure loads, VLD3 variants", ldx_opcode 3;
- "Element/structure stores, VST3 variants", stx_opcode 3;
- "Element/structure loads, VLD4 variants", ldx_opcode 4;
- "Element/structure stores, VST4 variants", stx_opcode 4;
- "Logical operations (AND)", single_opcode Vand;
- "Logical operations (OR)", single_opcode Vorr;
- "Logical operations (exclusive OR)", single_opcode Veor;
- "Logical operations (AND-NOT)", single_opcode Vbic;
- "Logical operations (OR-NOT)", single_opcode Vorn;
- "Reinterpret casts", single_opcode Vreinterp ]
-
-(* Given an intrinsic shape, produce a string to document the corresponding
- operand shapes. *)
-let rec analyze_shape shape =
- let rec n_things n thing =
- match n with
- 0 -> []
- | n -> thing :: (n_things (n - 1) thing)
- in
- let rec analyze_shape_elt reg_no elt =
- match elt with
- Dreg -> "@var{d" ^ (string_of_int reg_no) ^ "}"
- | Qreg -> "@var{q" ^ (string_of_int reg_no) ^ "}"
- | Corereg -> "@var{r" ^ (string_of_int reg_no) ^ "}"
- | Immed -> "#@var{0}"
- | VecArray (1, elt) ->
- let elt_regexp = analyze_shape_elt 0 elt in
- "@{" ^ elt_regexp ^ "@}"
- | VecArray (n, elt) ->
- let rec f m =
- match m with
- 0 -> []
- | m -> (analyze_shape_elt (m - 1) elt) :: (f (m - 1))
- in
- let ops = List.rev (f n) in
- "@{" ^ (commas (fun x -> x) ops "") ^ "@}"
- | (PtrTo elt | CstPtrTo elt) ->
- "[" ^ (analyze_shape_elt reg_no elt) ^ "]"
- | Element_of_dreg -> (analyze_shape_elt reg_no Dreg) ^ "[@var{0}]"
- | Element_of_qreg -> (analyze_shape_elt reg_no Qreg) ^ "[@var{0}]"
- | All_elements_of_dreg -> (analyze_shape_elt reg_no Dreg) ^ "[]"
- | Alternatives alts -> (analyze_shape_elt reg_no (List.hd alts))
- in
- match shape with
- All (n, elt) -> commas (analyze_shape_elt 0) (n_things n elt) ""
- | Long -> (analyze_shape_elt 0 Qreg) ^ ", " ^ (analyze_shape_elt 0 Dreg) ^
- ", " ^ (analyze_shape_elt 0 Dreg)
- | Long_noreg elt -> (analyze_shape_elt 0 elt) ^ ", " ^
- (analyze_shape_elt 0 elt)
- | Wide -> (analyze_shape_elt 0 Qreg) ^ ", " ^ (analyze_shape_elt 0 Qreg) ^
- ", " ^ (analyze_shape_elt 0 Dreg)
- | Wide_noreg elt -> analyze_shape (Long_noreg elt)
- | Narrow -> (analyze_shape_elt 0 Dreg) ^ ", " ^ (analyze_shape_elt 0 Qreg) ^
- ", " ^ (analyze_shape_elt 0 Qreg)
- | Use_operands elts -> commas (analyze_shape_elt 0) (Array.to_list elts) ""
- | By_scalar Dreg ->
- analyze_shape (Use_operands [| Dreg; Dreg; Element_of_dreg |])
- | By_scalar Qreg ->
- analyze_shape (Use_operands [| Qreg; Qreg; Element_of_dreg |])
- | By_scalar _ -> assert false
- | Wide_lane ->
- analyze_shape (Use_operands [| Qreg; Dreg; Element_of_dreg |])
- | Wide_scalar ->
- analyze_shape (Use_operands [| Qreg; Dreg; Element_of_dreg |])
- | Pair_result elt ->
- let elt_regexp = analyze_shape_elt 0 elt in
- let elt_regexp' = analyze_shape_elt 1 elt in
- elt_regexp ^ ", " ^ elt_regexp'
- | Unary_scalar _ -> "FIXME Unary_scalar"
- | Binary_imm elt -> analyze_shape (Use_operands [| elt; elt; Immed |])
- | Narrow_imm -> analyze_shape (Use_operands [| Dreg; Qreg; Immed |])
- | Long_imm -> analyze_shape (Use_operands [| Qreg; Dreg; Immed |])
-
-(* Document a single intrinsic. *)
-let describe_intrinsic first chan
- (elt_ty, (_, features, shape, name, munge, _)) =
- let c_arity, new_elt_ty = munge shape elt_ty in
- let c_types = strings_of_arity c_arity in
- Printf.fprintf chan "@itemize @bullet\n";
- let item_code = if first then "@item" else "@itemx" in
- Printf.fprintf chan "%s %s %s_%s (" item_code (List.hd c_types)
- (intrinsic_name name) (string_of_elt elt_ty);
- Printf.fprintf chan "%s)\n" (commas (fun ty -> ty) (List.tl c_types) "");
- if not (List.exists (fun feature -> feature = No_op) features) then
- begin
- let print_one_insn name =
- Printf.fprintf chan "@code{";
- let no_suffix = (new_elt_ty = NoElts) in
- let name_with_suffix =
- if no_suffix then name
- else name ^ "." ^ (string_of_elt_dots new_elt_ty)
- in
- let possible_operands = analyze_all_shapes features shape
- analyze_shape
- in
- let rec print_one_possible_operand op =
- Printf.fprintf chan "%s %s}" name_with_suffix op
- in
- (* If the intrinsic expands to multiple instructions, we assume
- they are all of the same form. *)
- print_one_possible_operand (List.hd possible_operands)
- in
- let rec print_insns names =
- match names with
- [] -> ()
- | [name] -> print_one_insn name
- | name::names -> (print_one_insn name;
- Printf.fprintf chan " @emph{or} ";
- print_insns names)
- in
- let insn_names = get_insn_names features name in
- Printf.fprintf chan "@*@emph{Form of expected instruction(s):} ";
- print_insns insn_names;
- Printf.fprintf chan "\n"
- end;
- Printf.fprintf chan "@end itemize\n";
- Printf.fprintf chan "\n\n"
-
-(* Document a group of intrinsics. *)
-let document_group chan (group_title, group_extractor) =
- (* Extract the rows in question from the ops table and then turn them
- into a list of intrinsics. *)
- let intrinsics =
- List.fold_left (fun got_so_far ->
- fun row ->
- match row with
- (_, _, _, _, _, elt_tys) ->
- List.fold_left (fun got_so_far' ->
- fun elt_ty ->
- (elt_ty, row) :: got_so_far')
- got_so_far elt_tys
- ) [] (group_extractor ())
- in
- (* Emit the title for this group. *)
- Printf.fprintf chan "@subsubsection %s\n\n" group_title;
- (* Emit a description of each intrinsic. *)
- List.iter (describe_intrinsic true chan) intrinsics;
- (* Close this group. *)
- Printf.fprintf chan "\n\n"
-
-let gnu_header chan =
- List.iter (fun s -> Printf.fprintf chan "%s\n" s) [
- "@c Copyright (C) 2006-2014 Free Software Foundation, Inc.";
- "@c This is part of the GCC manual.";
- "@c For copying conditions, see the file gcc.texi.";
- "";
- "@c This file is generated automatically using gcc/config/arm/neon-docgen.ml";
- "@c Please do not edit manually."]
-
-let crypto_doc =
-"
-@itemize @bullet
-@item poly128_t vldrq_p128(poly128_t const *)
-@end itemize
-
-@itemize @bullet
-@item void vstrq_p128(poly128_t *, poly128_t)
-@end itemize
-
-@itemize @bullet
-@item uint64x1_t vceq_p64 (poly64x1_t, poly64x1_t)
-@end itemize
-
-@itemize @bullet
-@item uint64x1_t vtst_p64 (poly64x1_t, poly64x1_t)
-@end itemize
-
-@itemize @bullet
-@item uint32_t vsha1h_u32 (uint32_t)
-@*@emph{Form of expected instruction(s):} @code{sha1h.32 @var{q0}, @var{q1}}
-@end itemize
-
-@itemize @bullet
-@item uint32x4_t vsha1cq_u32 (uint32x4_t, uint32_t, uint32x4_t)
-@*@emph{Form of expected instruction(s):} @code{sha1c.32 @var{q0}, @var{q1}, @var{q2}}
-@end itemize
-
-@itemize @bullet
-@item uint32x4_t vsha1pq_u32 (uint32x4_t, uint32_t, uint32x4_t)
-@*@emph{Form of expected instruction(s):} @code{sha1p.32 @var{q0}, @var{q1}, @var{q2}}
-@end itemize
-
-@itemize @bullet
-@item uint32x4_t vsha1mq_u32 (uint32x4_t, uint32_t, uint32x4_t)
-@*@emph{Form of expected instruction(s):} @code{sha1m.32 @var{q0}, @var{q1}, @var{q2}}
-@end itemize
-
-@itemize @bullet
-@item uint32x4_t vsha1su0q_u32 (uint32x4_t, uint32x4_t, uint32x4_t)
-@*@emph{Form of expected instruction(s):} @code{sha1su0.32 @var{q0}, @var{q1}, @var{q2}}
-@end itemize
-
-@itemize @bullet
-@item uint32x4_t vsha1su1q_u32 (uint32x4_t, uint32x4_t)
-@*@emph{Form of expected instruction(s):} @code{sha1su1.32 @var{q0}, @var{q1}, @var{q2}}
-@end itemize
-
-@itemize @bullet
-@item uint32x4_t vsha256hq_u32 (uint32x4_t, uint32x4_t, uint32x4_t)
-@*@emph{Form of expected instruction(s):} @code{sha256h.32 @var{q0}, @var{q1}, @var{q2}}
-@end itemize
-
-@itemize @bullet
-@item uint32x4_t vsha256h2q_u32 (uint32x4_t, uint32x4_t, uint32x4_t)
-@*@emph{Form of expected instruction(s):} @code{sha256h2.32 @var{q0}, @var{q1}, @var{q2}}
-@end itemize
-
-@itemize @bullet
-@item uint32x4_t vsha256su0q_u32 (uint32x4_t, uint32x4_t)
-@*@emph{Form of expected instruction(s):} @code{sha256su0.32 @var{q0}, @var{q1}}
-@end itemize
-
-@itemize @bullet
-@item uint32x4_t vsha256su1q_u32 (uint32x4_t, uint32x4_t, uint32x4_t)
-@*@emph{Form of expected instruction(s):} @code{sha256su1.32 @var{q0}, @var{q1}, @var{q2}}
-@end itemize
-
-@itemize @bullet
-@item poly128_t vmull_p64 (poly64_t a, poly64_t b)
-@*@emph{Form of expected instruction(s):} @code{vmull.p64 @var{q0}, @var{d1}, @var{d2}}
-@end itemize
-
-@itemize @bullet
-@item poly128_t vmull_high_p64 (poly64x2_t a, poly64x2_t b)
-@*@emph{Form of expected instruction(s):} @code{vmull.p64 @var{q0}, @var{d1}, @var{d2}}
-@end itemize
-"
-
-(* Program entry point. *)
-let _ =
- if Array.length Sys.argv <> 2 then
- failwith "Usage: neon-docgen <output filename>"
- else
- let file = Sys.argv.(1) in
- try
- let chan = open_out file in
- gnu_header chan;
- List.iter (document_group chan) intrinsic_groups;
- Printf.fprintf chan "%s\n" crypto_doc;
- close_out chan
- with Sys_error sys ->
- failwith ("Could not create output file " ^ file ^ ": " ^ sys)
diff --git a/gcc/config/arm/neon-gen.ml b/gcc/config/arm/neon-gen.ml
deleted file mode 100644
index f3dd86b0ace..00000000000
--- a/gcc/config/arm/neon-gen.ml
+++ /dev/null
@@ -1,520 +0,0 @@
-(* Auto-generate ARM Neon intrinsics header file.
- Copyright (C) 2006-2014 Free Software Foundation, Inc.
- Contributed by CodeSourcery.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>.
-
- This is an O'Caml program. The O'Caml compiler is available from:
-
- http://caml.inria.fr/
-
- Or from your favourite OS's friendly packaging system. Tested with version
- 3.09.2, though other versions will probably work too.
-
- Compile with:
- ocamlc -c neon.ml
- ocamlc -o neon-gen neon.cmo neon-gen.ml
-
- Run with:
- ./neon-gen > arm_neon.h
-*)
-
-open Neon
-
-(* The format codes used in the following functions are documented at:
- http://caml.inria.fr/pub/docs/manual-ocaml/libref/Format.html\
- #6_printflikefunctionsforprettyprinting
- (one line, remove the backslash.)
-*)
-
-(* Following functions can be used to approximate GNU indentation style. *)
-let start_function () =
- Format.printf "@[<v 0>";
- ref 0
-
-let end_function nesting =
- match !nesting with
- 0 -> Format.printf "@;@;@]"
- | _ -> failwith ("Bad nesting (ending function at level "
- ^ (string_of_int !nesting) ^ ")")
-
-let open_braceblock nesting =
- begin match !nesting with
- 0 -> Format.printf "@,@<0>{@[<v 2>@,"
- | _ -> Format.printf "@,@[<v 2> @<0>{@[<v 2>@,"
- end;
- incr nesting
-
-let close_braceblock nesting =
- decr nesting;
- match !nesting with
- 0 -> Format.printf "@]@,@<0>}"
- | _ -> Format.printf "@]@,@<0>}@]"
-
-let print_function arity fnname body =
- let ffmt = start_function () in
- Format.printf "__extension__ static __inline ";
- let inl = "__attribute__ ((__always_inline__))" in
- begin match arity with
- Arity0 ret ->
- Format.printf "%s %s@,%s (void)" (string_of_vectype ret) inl fnname
- | Arity1 (ret, arg0) ->
- Format.printf "%s %s@,%s (%s __a)" (string_of_vectype ret) inl fnname
- (string_of_vectype arg0)
- | Arity2 (ret, arg0, arg1) ->
- Format.printf "%s %s@,%s (%s __a, %s __b)"
- (string_of_vectype ret) inl fnname (string_of_vectype arg0)
- (string_of_vectype arg1)
- | Arity3 (ret, arg0, arg1, arg2) ->
- Format.printf "%s %s@,%s (%s __a, %s __b, %s __c)"
- (string_of_vectype ret) inl fnname (string_of_vectype arg0)
- (string_of_vectype arg1) (string_of_vectype arg2)
- | Arity4 (ret, arg0, arg1, arg2, arg3) ->
- Format.printf "%s %s@,%s (%s __a, %s __b, %s __c, %s __d)"
- (string_of_vectype ret) inl fnname (string_of_vectype arg0)
- (string_of_vectype arg1) (string_of_vectype arg2)
- (string_of_vectype arg3)
- end;
- open_braceblock ffmt;
- let rec print_lines = function
- [] -> ()
- | "" :: lines -> print_lines lines
- | [line] -> Format.printf "%s" line
- | line::lines -> Format.printf "%s@," line ; print_lines lines in
- print_lines body;
- close_braceblock ffmt;
- end_function ffmt
-
-let union_string num elts base =
- let itype = inttype_for_array num elts in
- let iname = string_of_inttype itype
- and sname = string_of_vectype (T_arrayof (num, elts)) in
- Printf.sprintf "union { %s __i; %s __o; } %s" sname iname base
-
-let rec signed_ctype = function
- T_uint8x8 | T_poly8x8 -> T_int8x8
- | T_uint8x16 | T_poly8x16 -> T_int8x16
- | T_uint16x4 | T_poly16x4 -> T_int16x4
- | T_uint16x8 | T_poly16x8 -> T_int16x8
- | T_uint32x2 -> T_int32x2
- | T_uint32x4 -> T_int32x4
- | T_uint64x1 -> T_int64x1
- | T_uint64x2 -> T_int64x2
- | T_poly64x2 -> T_int64x2
- (* Cast to types defined by mode in arm.c, not random types pulled in from
- the <stdint.h> header in use. This fixes incompatible pointer errors when
- compiling with C++. *)
- | T_uint8 | T_int8 -> T_intQI
- | T_uint16 | T_int16 -> T_intHI
- | T_uint32 | T_int32 -> T_intSI
- | T_uint64 | T_int64 -> T_intDI
- | T_float16 -> T_floatHF
- | T_float32 -> T_floatSF
- | T_poly8 -> T_intQI
- | T_poly16 -> T_intHI
- | T_poly64 -> T_intDI
- | T_poly128 -> T_intTI
- | T_arrayof (n, elt) -> T_arrayof (n, signed_ctype elt)
- | T_ptrto elt -> T_ptrto (signed_ctype elt)
- | T_const elt -> T_const (signed_ctype elt)
- | x -> x
-
-let add_cast ctype cval =
- let stype = signed_ctype ctype in
- if ctype <> stype then
- Printf.sprintf "(%s) %s" (string_of_vectype stype) cval
- else
- cval
-
-let cast_for_return to_ty = "(" ^ (string_of_vectype to_ty) ^ ")"
-
-(* Return a tuple of a list of declarations to go at the start of the function,
- and a list of statements needed to return THING. *)
-let return arity thing =
- match arity with
- Arity0 (ret) | Arity1 (ret, _) | Arity2 (ret, _, _) | Arity3 (ret, _, _, _)
- | Arity4 (ret, _, _, _, _) ->
- begin match ret with
- T_arrayof (num, vec) ->
- let uname = union_string num vec "__rv" in
- [uname ^ ";"], ["__rv.__o = " ^ thing ^ ";"; "return __rv.__i;"]
- | T_void ->
- [], [thing ^ ";"]
- | _ ->
- [], ["return " ^ (cast_for_return ret) ^ thing ^ ";"]
- end
-
-let mask_shape_for_shuffle = function
- All (num, reg) -> All (num, reg)
- | Pair_result reg -> All (2, reg)
- | _ -> failwith "mask_for_shuffle"
-
-let mask_elems shuffle shape elttype part =
- let elem_size = elt_width elttype in
- let num_elems =
- match regmap shape 0 with
- Dreg -> 64 / elem_size
- | Qreg -> 128 / elem_size
- | _ -> failwith "mask_elems" in
- shuffle elem_size num_elems part
-
-(* Return a tuple of a list of declarations 0and a list of statements needed
- to implement an intrinsic using __builtin_shuffle. SHUFFLE is a function
- which returns a list of elements suitable for using as a mask. *)
-
-let shuffle_fn shuffle shape arity elttype =
- let mshape = mask_shape_for_shuffle shape in
- let masktype = type_for_elt mshape (unsigned_of_elt elttype) 0 in
- let masktype_str = string_of_vectype masktype in
- let shuffle_res = type_for_elt mshape elttype 0 in
- let shuffle_res_str = string_of_vectype shuffle_res in
- match arity with
- Arity0 (ret) | Arity1 (ret, _) | Arity2 (ret, _, _) | Arity3 (ret, _, _, _)
- | Arity4 (ret, _, _, _, _) ->
- begin match ret with
- T_arrayof (num, vec) ->
- let elems1 = mask_elems shuffle mshape elttype `lo
- and elems2 = mask_elems shuffle mshape elttype `hi in
- let mask1 = (String.concat ", " (List.map string_of_int elems1))
- and mask2 = (String.concat ", " (List.map string_of_int elems2)) in
- let shuf1 = Printf.sprintf
- "__rv.val[0] = (%s) __builtin_shuffle (__a, __b, (%s) { %s });"
- shuffle_res_str masktype_str mask1
- and shuf2 = Printf.sprintf
- "__rv.val[1] = (%s) __builtin_shuffle (__a, __b, (%s) { %s });"
- shuffle_res_str masktype_str mask2 in
- [Printf.sprintf "%s __rv;" (string_of_vectype ret);],
- [shuf1; shuf2; "return __rv;"]
- | _ ->
- let elems = mask_elems shuffle mshape elttype `lo in
- let mask = (String.concat ", " (List.map string_of_int elems)) in
- let shuf = Printf.sprintf
- "return (%s) __builtin_shuffle (__a, (%s) { %s });" shuffle_res_str masktype_str mask in
- [""],
- [shuf]
- end
-
-let rec element_type ctype =
- match ctype with
- T_arrayof (_, v) -> element_type v
- | _ -> ctype
-
-let params ps =
- let pdecls = ref [] in
- let ptype t p =
- match t with
- T_arrayof (num, elts) ->
- let uname = union_string num elts (p ^ "u") in
- let decl = Printf.sprintf "%s = { %s };" uname p in
- pdecls := decl :: !pdecls;
- p ^ "u.__o"
- | _ -> add_cast t p in
- let plist = match ps with
- Arity0 _ -> []
- | Arity1 (_, t1) -> [ptype t1 "__a"]
- | Arity2 (_, t1, t2) -> [ptype t1 "__a"; ptype t2 "__b"]
- | Arity3 (_, t1, t2, t3) -> [ptype t1 "__a"; ptype t2 "__b"; ptype t3 "__c"]
- | Arity4 (_, t1, t2, t3, t4) ->
- [ptype t1 "__a"; ptype t2 "__b"; ptype t3 "__c"; ptype t4 "__d"] in
- !pdecls, plist
-
-let modify_params features plist =
- let is_flipped =
- List.exists (function Flipped _ -> true | _ -> false) features in
- if is_flipped then
- match plist with
- [ a; b ] -> [ b; a ]
- | _ ->
- failwith ("Don't know how to flip args " ^ (String.concat ", " plist))
- else
- plist
-
-(* !!! Decide whether to add an extra information word based on the shape
- form. *)
-let extra_word shape features paramlist bits =
- let use_word =
- match shape with
- All _ | Long | Long_noreg _ | Wide | Wide_noreg _ | Narrow
- | By_scalar _ | Wide_scalar | Wide_lane | Binary_imm _ | Long_imm
- | Narrow_imm -> true
- | _ -> List.mem InfoWord features
- in
- if use_word then
- paramlist @ [string_of_int bits]
- else
- paramlist
-
-(* Bit 0 represents signed (1) vs unsigned (0), or float (1) vs poly (0).
- Bit 1 represents floats & polynomials (1), or ordinary integers (0).
- Bit 2 represents rounding (1) vs none (0). *)
-let infoword_value elttype features =
- let bits01 =
- match elt_class elttype with
- Signed | ConvClass (Signed, _) | ConvClass (_, Signed) -> 0b001
- | Poly -> 0b010
- | Float -> 0b011
- | _ -> 0b000
- and rounding_bit = if List.mem Rounding features then 0b100 else 0b000 in
- bits01 lor rounding_bit
-
-(* "Cast" type operations will throw an exception in mode_of_elt (actually in
- elt_width, called from there). Deal with that here, and generate a suffix
- with multiple modes (<to><from>). *)
-let rec mode_suffix elttype shape =
- try
- let mode = mode_of_elt elttype shape in
- string_of_mode mode
- with MixedMode (dst, src) ->
- let dstmode = mode_of_elt ~argpos:0 dst shape
- and srcmode = mode_of_elt ~argpos:1 src shape in
- string_of_mode dstmode ^ string_of_mode srcmode
-
-let get_shuffle features =
- try
- match List.find (function Use_shuffle _ -> true | _ -> false) features with
- Use_shuffle fn -> Some fn
- | _ -> None
- with Not_found -> None
-
-let print_feature_test_start features =
- try
- match List.find (fun feature ->
- match feature with Requires_feature _ -> true
- | Requires_arch _ -> true
- | Requires_FP_bit _ -> true
- | _ -> false)
- features with
- Requires_feature feature ->
- Format.printf "#ifdef __ARM_FEATURE_%s@\n" feature
- | Requires_arch arch ->
- Format.printf "#if __ARM_ARCH >= %d@\n" arch
- | Requires_FP_bit bit ->
- Format.printf "#if ((__ARM_FP & 0x%X) != 0)@\n"
- (1 lsl bit)
- | _ -> assert false
- with Not_found -> assert true
-
-let print_feature_test_end features =
- let feature =
- List.exists (function Requires_feature _ -> true
- | Requires_arch _ -> true
- | Requires_FP_bit _ -> true
- | _ -> false) features in
- if feature then Format.printf "#endif@\n"
-
-
-let print_variant opcode features shape name (ctype, asmtype, elttype) =
- let bits = infoword_value elttype features in
- let modesuf = mode_suffix elttype shape in
- let pdecls, paramlist = params ctype in
- let rdecls, stmts =
- match get_shuffle features with
- Some shuffle -> shuffle_fn shuffle shape ctype elttype
- | None ->
- let paramlist' = modify_params features paramlist in
- let paramlist'' = extra_word shape features paramlist' bits in
- let parstr = String.concat ", " paramlist'' in
- let builtin = Printf.sprintf "__builtin_neon_%s%s (%s)"
- (builtin_name features name) modesuf parstr in
- return ctype builtin in
- let body = pdecls @ rdecls @ stmts
- and fnname = (intrinsic_name name) ^ "_" ^ (string_of_elt elttype) in
- begin
- print_feature_test_start features;
- print_function ctype fnname body;
- print_feature_test_end features;
- end
-
-(* When this function processes the element types in the ops table, it rewrites
- them in a list of tuples (a,b,c):
- a : C type as an "arity", e.g. Arity1 (T_poly8x8, T_poly8x8)
- b : Asm type : a single, processed element type, e.g. P16. This is the
- type which should be attached to the asm opcode.
- c : Variant type : the unprocessed type for this variant (e.g. in add
- instructions which don't care about the sign, b might be i16 and c
- might be s16.)
-*)
-
-let print_op (opcode, features, shape, name, munge, types) =
- let sorted_types = List.sort compare types in
- let munged_types = List.map
- (fun elt -> let c, asm = munge shape elt in c, asm, elt) sorted_types in
- List.iter
- (fun variant -> print_variant opcode features shape name variant)
- munged_types
-
-let print_ops ops =
- List.iter print_op ops
-
-(* Output type definitions. Table entries are:
- cbase : "C" name for the type.
- abase : "ARM" base name for the type (i.e. int in int8x8_t).
- esize : element size.
- enum : element count.
- alevel: architecture level at which available.
-*)
-
-type fpulevel = CRYPTO | ALL
-
-let deftypes () =
- let typeinfo = [
- (* Doubleword vector types. *)
- "__builtin_neon_qi", "int", 8, 8, ALL;
- "__builtin_neon_hi", "int", 16, 4, ALL;
- "__builtin_neon_si", "int", 32, 2, ALL;
- "__builtin_neon_di", "int", 64, 1, ALL;
- "__builtin_neon_hf", "float", 16, 4, ALL;
- "__builtin_neon_sf", "float", 32, 2, ALL;
- "__builtin_neon_poly8", "poly", 8, 8, ALL;
- "__builtin_neon_poly16", "poly", 16, 4, ALL;
- "__builtin_neon_poly64", "poly", 64, 1, CRYPTO;
- "__builtin_neon_uqi", "uint", 8, 8, ALL;
- "__builtin_neon_uhi", "uint", 16, 4, ALL;
- "__builtin_neon_usi", "uint", 32, 2, ALL;
- "__builtin_neon_udi", "uint", 64, 1, ALL;
-
- (* Quadword vector types. *)
- "__builtin_neon_qi", "int", 8, 16, ALL;
- "__builtin_neon_hi", "int", 16, 8, ALL;
- "__builtin_neon_si", "int", 32, 4, ALL;
- "__builtin_neon_di", "int", 64, 2, ALL;
- "__builtin_neon_sf", "float", 32, 4, ALL;
- "__builtin_neon_poly8", "poly", 8, 16, ALL;
- "__builtin_neon_poly16", "poly", 16, 8, ALL;
- "__builtin_neon_poly64", "poly", 64, 2, CRYPTO;
- "__builtin_neon_uqi", "uint", 8, 16, ALL;
- "__builtin_neon_uhi", "uint", 16, 8, ALL;
- "__builtin_neon_usi", "uint", 32, 4, ALL;
- "__builtin_neon_udi", "uint", 64, 2, ALL
- ] in
- List.iter
- (fun (cbase, abase, esize, enum, fpulevel) ->
- let attr =
- match enum with
- 1 -> ""
- | _ -> Printf.sprintf "\t__attribute__ ((__vector_size__ (%d)))"
- (esize * enum / 8) in
- if fpulevel == CRYPTO then
- Format.printf "#ifdef __ARM_FEATURE_CRYPTO\n";
- Format.printf "typedef %s %s%dx%d_t%s;@\n" cbase abase esize enum attr;
- if fpulevel == CRYPTO then
- Format.printf "#endif\n";)
- typeinfo;
- Format.print_newline ();
- (* Extra types not in <stdint.h>. *)
- Format.printf "typedef float float32_t;\n";
- Format.printf "typedef __builtin_neon_poly8 poly8_t;\n";
- Format.printf "typedef __builtin_neon_poly16 poly16_t;\n";
- Format.printf "#ifdef __ARM_FEATURE_CRYPTO\n";
- Format.printf "typedef __builtin_neon_poly64 poly64_t;\n";
- Format.printf "typedef __builtin_neon_poly128 poly128_t;\n";
- Format.printf "#endif\n"
-
-(* Output structs containing arrays, for load & store instructions etc.
- poly128_t is deliberately not included here because it has no array types
- defined for it. *)
-
-let arrtypes () =
- let typeinfo = [
- "int", 8, ALL; "int", 16, ALL;
- "int", 32, ALL; "int", 64, ALL;
- "uint", 8, ALL; "uint", 16, ALL;
- "uint", 32, ALL; "uint", 64, ALL;
- "float", 32, ALL; "poly", 8, ALL;
- "poly", 16, ALL; "poly", 64, CRYPTO
- ] in
- let writestruct elname elsize regsize arrsize fpulevel =
- let elnum = regsize / elsize in
- let structname =
- Printf.sprintf "%s%dx%dx%d_t" elname elsize elnum arrsize in
- let sfmt = start_function () in
- Format.printf "%stypedef struct %s"
- (if fpulevel == CRYPTO then "#ifdef __ARM_FEATURE_CRYPTO\n" else "") structname;
- open_braceblock sfmt;
- Format.printf "%s%dx%d_t val[%d];" elname elsize elnum arrsize;
- close_braceblock sfmt;
- Format.printf " %s;%s" structname (if fpulevel == CRYPTO then "\n#endif\n" else "");
- end_function sfmt;
- in
- for n = 2 to 4 do
- List.iter
- (fun (elname, elsize, alevel) ->
- writestruct elname elsize 64 n alevel;
- writestruct elname elsize 128 n alevel)
- typeinfo
- done
-
-let print_lines = List.iter (fun s -> Format.printf "%s@\n" s)
-
-(* Do it. *)
-
-let _ =
- print_lines [
-"/* ARM NEON intrinsics include file. This file is generated automatically";
-" using neon-gen.ml. Please do not edit manually.";
-"";
-" Copyright (C) 2006-2014 Free Software Foundation, Inc.";
-" Contributed by CodeSourcery.";
-"";
-" This file is part of GCC.";
-"";
-" GCC is free software; you can redistribute it and/or modify it";
-" under the terms of the GNU General Public License as published";
-" by the Free Software Foundation; either version 3, or (at your";
-" option) any later version.";
-"";
-" GCC is distributed in the hope that it will be useful, but WITHOUT";
-" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY";
-" or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public";
-" License for more details.";
-"";
-" Under Section 7 of GPL version 3, you are granted additional";
-" permissions described in the GCC Runtime Library Exception, version";
-" 3.1, as published by the Free Software Foundation.";
-"";
-" You should have received a copy of the GNU General Public License and";
-" a copy of the GCC Runtime Library Exception along with this program;";
-" see the files COPYING3 and COPYING.RUNTIME respectively. If not, see";
-" <http://www.gnu.org/licenses/>. */";
-"";
-"#ifndef _GCC_ARM_NEON_H";
-"#define _GCC_ARM_NEON_H 1";
-"";
-"#ifndef __ARM_NEON__";
-"#error You must enable NEON instructions (e.g. -mfloat-abi=softfp -mfpu=neon) to use arm_neon.h";
-"#else";
-"";
-"#ifdef __cplusplus";
-"extern \"C\" {";
-"#endif";
-"";
-"#include <stdint.h>";
-""];
- deftypes ();
- arrtypes ();
- Format.print_newline ();
- print_ops ops;
- Format.print_newline ();
- print_ops reinterp;
- print_ops reinterpq;
- Format.printf "%s" crypto_intrinsics;
- print_lines [
-"#ifdef __cplusplus";
-"}";
-"#endif";
-"#endif";
-"#endif"]
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index aad420ce785..1fc4dcd8275 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -728,7 +728,7 @@
;; Compare to *anddi_notdi_di.
(define_insn "bicdi3_neon"
- [(set (match_operand:DI 0 "s_register_operand" "=w,?=&r,?&r")
+ [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r")
(and:DI (not:DI (match_operand:DI 2 "s_register_operand" "w,r,0"))
(match_operand:DI 1 "s_register_operand" "w,0,r")))]
"TARGET_NEON"
@@ -1842,9 +1842,9 @@
; good for plain vadd, vaddq.
(define_expand "neon_vadd<mode>"
- [(match_operand:VDQX 0 "s_register_operand" "=w")
- (match_operand:VDQX 1 "s_register_operand" "w")
- (match_operand:VDQX 2 "s_register_operand" "w")
+ [(match_operand:VCVTF 0 "s_register_operand" "=w")
+ (match_operand:VCVTF 1 "s_register_operand" "w")
+ (match_operand:VCVTF 2 "s_register_operand" "w")
(match_operand:SI 3 "immediate_operand" "i")]
"TARGET_NEON"
{
@@ -1869,9 +1869,9 @@
; Used for intrinsics when flag_unsafe_math_optimizations is false.
(define_insn "neon_vadd<mode>_unspec"
- [(set (match_operand:VDQX 0 "s_register_operand" "=w")
- (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
- (match_operand:VDQX 2 "s_register_operand" "w")]
+ [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
+ (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
+ (match_operand:VCVTF 2 "s_register_operand" "w")]
UNSPEC_VADD))]
"TARGET_NEON"
"vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
@@ -2132,9 +2132,9 @@
)
(define_expand "neon_vsub<mode>"
- [(match_operand:VDQX 0 "s_register_operand" "=w")
- (match_operand:VDQX 1 "s_register_operand" "w")
- (match_operand:VDQX 2 "s_register_operand" "w")
+ [(match_operand:VCVTF 0 "s_register_operand" "=w")
+ (match_operand:VCVTF 1 "s_register_operand" "w")
+ (match_operand:VCVTF 2 "s_register_operand" "w")
(match_operand:SI 3 "immediate_operand" "i")]
"TARGET_NEON"
{
@@ -2149,9 +2149,9 @@
; Used for intrinsics when flag_unsafe_math_optimizations is false.
(define_insn "neon_vsub<mode>_unspec"
- [(set (match_operand:VDQX 0 "s_register_operand" "=w")
- (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")
- (match_operand:VDQX 2 "s_register_operand" "w")]
+ [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
+ (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
+ (match_operand:VCVTF 2 "s_register_operand" "w")]
UNSPEC_VSUB))]
"TARGET_NEON"
"vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
@@ -2547,6 +2547,14 @@
[(set_attr "type" "neon_qabs<q>")]
)
+(define_insn "neon_bswap<mode>"
+ [(set (match_operand:VDQHSD 0 "register_operand" "=w")
+ (bswap:VDQHSD (match_operand:VDQHSD 1 "register_operand" "w")))]
+ "TARGET_NEON"
+ "vrev<V_sz_elem>.8\\t%<V_reg>0, %<V_reg>1"
+ [(set_attr "type" "neon_rev<q>")]
+)
+
(define_expand "neon_vneg<mode>"
[(match_operand:VDQW 0 "s_register_operand" "")
(match_operand:VDQW 1 "s_register_operand" "")
@@ -4140,17 +4148,6 @@
[(set_attr "type" "neon_permute<q>")]
)
-(define_expand "neon_vtrn<mode>"
- [(match_operand:SI 0 "s_register_operand" "r")
- (match_operand:VDQW 1 "s_register_operand" "w")
- (match_operand:VDQW 2 "s_register_operand" "w")]
- "TARGET_NEON"
-{
- neon_emit_pair_result_insn (<MODE>mode, gen_neon_vtrn<mode>_internal,
- operands[0], operands[1], operands[2]);
- DONE;
-})
-
(define_expand "neon_vzip<mode>_internal"
[(parallel
[(set (match_operand:VDQW 0 "s_register_operand" "")
@@ -4177,17 +4174,6 @@
[(set_attr "type" "neon_zip<q>")]
)
-(define_expand "neon_vzip<mode>"
- [(match_operand:SI 0 "s_register_operand" "r")
- (match_operand:VDQW 1 "s_register_operand" "w")
- (match_operand:VDQW 2 "s_register_operand" "w")]
- "TARGET_NEON"
-{
- neon_emit_pair_result_insn (<MODE>mode, gen_neon_vzip<mode>_internal,
- operands[0], operands[1], operands[2]);
- DONE;
-})
-
(define_expand "neon_vuzp<mode>_internal"
[(parallel
[(set (match_operand:VDQW 0 "s_register_operand" "")
@@ -4214,17 +4200,6 @@
[(set_attr "type" "neon_zip<q>")]
)
-(define_expand "neon_vuzp<mode>"
- [(match_operand:SI 0 "s_register_operand" "r")
- (match_operand:VDQW 1 "s_register_operand" "w")
- (match_operand:VDQW 2 "s_register_operand" "w")]
- "TARGET_NEON"
-{
- neon_emit_pair_result_insn (<MODE>mode, gen_neon_vuzp<mode>_internal,
- operands[0], operands[1], operands[2]);
- DONE;
-})
-
(define_expand "neon_vreinterpretv8qi<mode>"
[(match_operand:V8QI 0 "s_register_operand" "")
(match_operand:VDX 1 "s_register_operand" "")]
@@ -5357,61 +5332,6 @@
[(set_attr "type" "neon_store4_4reg<q>")]
)
-(define_expand "neon_vand<mode>"
- [(match_operand:VDQX 0 "s_register_operand" "")
- (match_operand:VDQX 1 "s_register_operand" "")
- (match_operand:VDQX 2 "neon_inv_logic_op2" "")
- (match_operand:SI 3 "immediate_operand" "")]
- "TARGET_NEON"
-{
- emit_insn (gen_and<mode>3 (operands[0], operands[1], operands[2]));
- DONE;
-})
-
-(define_expand "neon_vorr<mode>"
- [(match_operand:VDQX 0 "s_register_operand" "")
- (match_operand:VDQX 1 "s_register_operand" "")
- (match_operand:VDQX 2 "neon_logic_op2" "")
- (match_operand:SI 3 "immediate_operand" "")]
- "TARGET_NEON"
-{
- emit_insn (gen_ior<mode>3 (operands[0], operands[1], operands[2]));
- DONE;
-})
-
-(define_expand "neon_veor<mode>"
- [(match_operand:VDQX 0 "s_register_operand" "")
- (match_operand:VDQX 1 "s_register_operand" "")
- (match_operand:VDQX 2 "s_register_operand" "")
- (match_operand:SI 3 "immediate_operand" "")]
- "TARGET_NEON"
-{
- emit_insn (gen_xor<mode>3 (operands[0], operands[1], operands[2]));
- DONE;
-})
-
-(define_expand "neon_vbic<mode>"
- [(match_operand:VDQX 0 "s_register_operand" "")
- (match_operand:VDQX 1 "s_register_operand" "")
- (match_operand:VDQX 2 "neon_logic_op2" "")
- (match_operand:SI 3 "immediate_operand" "")]
- "TARGET_NEON"
-{
- emit_insn (gen_bic<mode>3_neon (operands[0], operands[1], operands[2]));
- DONE;
-})
-
-(define_expand "neon_vorn<mode>"
- [(match_operand:VDQX 0 "s_register_operand" "")
- (match_operand:VDQX 1 "s_register_operand" "")
- (match_operand:VDQX 2 "neon_inv_logic_op2" "")
- (match_operand:SI 3 "immediate_operand" "")]
- "TARGET_NEON"
-{
- emit_insn (gen_orn<mode>3_neon (operands[0], operands[1], operands[2]));
- DONE;
-})
-
(define_insn "neon_vec_unpack<US>_lo_<mode>"
[(set (match_operand:<V_unpack> 0 "register_operand" "=w")
(SE:<V_unpack> (vec_select:<V_HALF>
diff --git a/gcc/config/arm/netbsd-elf.h b/gcc/config/arm/netbsd-elf.h
index 9deda96791f..645551fdf82 100644
--- a/gcc/config/arm/netbsd-elf.h
+++ b/gcc/config/arm/netbsd-elf.h
@@ -14,8 +14,13 @@
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* Run-time Target Specification. */
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index d74fcb31bc7..032808c5a62 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -291,6 +291,15 @@
|| ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1))) < 32")))
(match_test "mode == GET_MODE (op)")))
+(define_special_predicate "shift_nomul_operator"
+ (and (ior (and (match_code "rotate")
+ (match_test "CONST_INT_P (XEXP (op, 1))
+ && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1))) < 32"))
+ (and (match_code "ashift,ashiftrt,lshiftrt,rotatert")
+ (match_test "!CONST_INT_P (XEXP (op, 1))
+ || ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1))) < 32")))
+ (match_test "mode == GET_MODE (op)")))
+
;; True for shift operators which can be used with saturation instructions.
(define_special_predicate "sat_shift_operator"
(and (ior (and (match_code "mult")
diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
index 10bc8b1c530..6ea08105fd1 100644
--- a/gcc/config/arm/thumb2.md
+++ b/gcc/config/arm/thumb2.md
@@ -329,7 +329,7 @@
movw%?\\t%0, %L1\\t%@ movhi
str%(h%)\\t%1, %0\\t%@ movhi
ldr%(h%)\\t%0, %1\\t%@ movhi"
- [(set_attr "type" "mov_reg,mov_imm,mov_imm,mov_reg,store1,load1")
+ [(set_attr "type" "mov_reg,mov_imm,mov_imm,mov_imm,store1,load1")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "yes,no,yes,no,no,no")
(set_attr "length" "2,4,2,4,4,4")
diff --git a/gcc/config/arm/uclinux-eabi.h b/gcc/config/arm/uclinux-eabi.h
index b5055ce40bc..4d57d138805 100644
--- a/gcc/config/arm/uclinux-eabi.h
+++ b/gcc/config/arm/uclinux-eabi.h
@@ -14,8 +14,13 @@
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* Override settings that are different to the uclinux-elf or
diff --git a/gcc/config/arm/uclinux-elf.h b/gcc/config/arm/uclinux-elf.h
index 5cd4fe52799..43edba70c64 100644
--- a/gcc/config/arm/uclinux-elf.h
+++ b/gcc/config/arm/uclinux-elf.h
@@ -14,8 +14,13 @@
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* We don't want a PLT. */
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 8caa953bcb9..147cb802d41 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -143,6 +143,8 @@
VUNSPEC_SLX ; Represent a store-register-release-exclusive.
VUNSPEC_LDA ; Represent a store-register-acquire.
VUNSPEC_STL ; Represent a store-register-release.
+ VUNSPEC_GET_FPSCR ; Represent fetch of FPSCR content.
+ VUNSPEC_SET_FPSCR ; Represent assign of FPSCR content.
])
;; Enumerators for NEON unspecs.
diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
index e1a48eeea82..a8b27bcf986 100644
--- a/gcc/config/arm/vfp.md
+++ b/gcc/config/arm/vfp.md
@@ -100,7 +100,7 @@
"
[(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no,no,no,no,no,no")
- (set_attr "type" "mov_reg,mov_reg,mov_reg,mvn_reg,mov_reg,load1,load1,store1,store1,f_mcr,f_mrc,fmov,f_loads,f_stores")
+ (set_attr "type" "mov_reg,mov_reg,mov_reg,mvn_reg,mov_imm,load1,load1,store1,store1,f_mcr,f_mrc,fmov,f_loads,f_stores")
(set_attr "length" "2,4,2,4,4,4,4,4,4,4,4,4,4,4")
(set_attr "pool_range" "*,*,*,*,*,1018,4094,*,*,*,*,*,1018,*")
(set_attr "neg_pool_range" "*,*,*,*,*, 0, 0,*,*,*,*,*,1008,*")]
@@ -1322,6 +1322,22 @@
(set_attr "conds" "unconditional")]
)
+;; Write Floating-point Status and Control Register.
+(define_insn "set_fpscr"
+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_SET_FPSCR)]
+ "TARGET_VFP"
+ "mcr\\tp10, 7, %0, cr1, cr0, 0\\t @SET_FPSCR"
+ [(set_attr "type" "mrs")])
+
+;; Read Floating-point Status and Control Register.
+(define_insn "get_fpscr"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(const_int 0)] VUNSPEC_GET_FPSCR))]
+ "TARGET_VFP"
+ "mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR"
+ [(set_attr "type" "mrs")])
+
+
;; Unimplemented insns:
;; fldm*
;; fstm*
diff --git a/gcc/config/arm/vxworks.h b/gcc/config/arm/vxworks.h
index 8bef16bc49f..faf84724d72 100644
--- a/gcc/config/arm/vxworks.h
+++ b/gcc/config/arm/vxworks.h
@@ -17,8 +17,13 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
diff --git a/gcc/config/avr/avr-fixed.md b/gcc/config/avr/avr-fixed.md
index 1652415b1d0..9c8489edd8e 100644
--- a/gcc/config/avr/avr-fixed.md
+++ b/gcc/config/avr/avr-fixed.md
@@ -430,8 +430,8 @@
}
// Input and output of the libgcc function
- const unsigned int regno_in[] = { -1, 22, 22, -1, 18 };
- const unsigned int regno_out[] = { -1, 24, 24, -1, 22 };
+ const unsigned int regno_in[] = { -1U, 22, 22, -1U, 18 };
+ const unsigned int regno_out[] = { -1U, 24, 24, -1U, 22 };
operands[3] = gen_rtx_REG (<MODE>mode, regno_out[(size_t) GET_MODE_SIZE (<MODE>mode)]);
operands[4] = gen_rtx_REG (<MODE>mode, regno_in[(size_t) GET_MODE_SIZE (<MODE>mode)]);
diff --git a/gcc/config/avr/avr-mcus.def b/gcc/config/avr/avr-mcus.def
index 483a3032173..4fc27166b8a 100644
--- a/gcc/config/avr/avr-mcus.def
+++ b/gcc/config/avr/avr-mcus.def
@@ -72,7 +72,6 @@ AVR_MCU ("at90c8534", ARCH_AVR2, AVR_ISA_NONE, "__AVR_AT90C8534__",
AVR_MCU ("at90s8535", ARCH_AVR2, AVR_ISA_NONE, "__AVR_AT90S8535__", 0x0060, 1, "s8535")
/* Classic + MOVW, <= 8K. */
AVR_MCU ("avr25", ARCH_AVR25, AVR_ISA_NONE, NULL, 0x0060, 1, "tn85")
-AVR_MCU ("ata6289", ARCH_AVR25, AVR_ISA_NONE, "__AVR_ATA6289__", 0x0100, 1, "a6289")
AVR_MCU ("ata5272", ARCH_AVR25, AVR_ISA_NONE, "__AVR_ATA5272__", 0x0100, 1, "a5272")
AVR_MCU ("attiny13", ARCH_AVR25, AVR_SHORT_SP, "__AVR_ATtiny13__", 0x0060, 1, "tn13")
AVR_MCU ("attiny13a", ARCH_AVR25, AVR_SHORT_SP, "__AVR_ATtiny13A__", 0x0060, 1, "tn13a")
@@ -121,6 +120,7 @@ AVR_MCU ("attiny1634", ARCH_AVR35, AVR_ISA_NONE, "__AVR_ATtiny1634__",
AVR_MCU ("avr4", ARCH_AVR4, AVR_ISA_NONE, NULL, 0x0060, 1, "m8")
AVR_MCU ("ata6285", ARCH_AVR4, AVR_ISA_NONE, "__AVR_ATA6285__", 0x0100, 1, "a6285")
AVR_MCU ("ata6286", ARCH_AVR4, AVR_ISA_NONE, "__AVR_ATA6286__", 0x0100, 1, "a6286")
+AVR_MCU ("ata6289", ARCH_AVR4, AVR_ISA_NONE, "__AVR_ATA6289__", 0x0100, 1, "a6289")
AVR_MCU ("atmega8", ARCH_AVR4, AVR_ISA_NONE, "__AVR_ATmega8__", 0x0060, 1, "m8")
AVR_MCU ("atmega8a", ARCH_AVR4, AVR_ISA_NONE, "__AVR_ATmega8A__", 0x0060, 1, "m8a")
AVR_MCU ("atmega48", ARCH_AVR4, AVR_ISA_NONE, "__AVR_ATmega48__", 0x0100, 1, "m48")
diff --git a/gcc/config/avr/avr-tables.opt b/gcc/config/avr/avr-tables.opt
index b5c6d829050..a05a48e17d2 100644
--- a/gcc/config/avr/avr-tables.opt
+++ b/gcc/config/avr/avr-tables.opt
@@ -66,139 +66,139 @@ EnumValue
Enum(avr_mcu) String(avr25) Value(13)
EnumValue
-Enum(avr_mcu) String(ata6289) Value(14)
+Enum(avr_mcu) String(ata5272) Value(14)
EnumValue
-Enum(avr_mcu) String(ata5272) Value(15)
+Enum(avr_mcu) String(attiny13) Value(15)
EnumValue
-Enum(avr_mcu) String(attiny13) Value(16)
+Enum(avr_mcu) String(attiny13a) Value(16)
EnumValue
-Enum(avr_mcu) String(attiny13a) Value(17)
+Enum(avr_mcu) String(attiny2313) Value(17)
EnumValue
-Enum(avr_mcu) String(attiny2313) Value(18)
+Enum(avr_mcu) String(attiny2313a) Value(18)
EnumValue
-Enum(avr_mcu) String(attiny2313a) Value(19)
+Enum(avr_mcu) String(attiny24) Value(19)
EnumValue
-Enum(avr_mcu) String(attiny24) Value(20)
+Enum(avr_mcu) String(attiny24a) Value(20)
EnumValue
-Enum(avr_mcu) String(attiny24a) Value(21)
+Enum(avr_mcu) String(attiny4313) Value(21)
EnumValue
-Enum(avr_mcu) String(attiny4313) Value(22)
+Enum(avr_mcu) String(attiny44) Value(22)
EnumValue
-Enum(avr_mcu) String(attiny44) Value(23)
+Enum(avr_mcu) String(attiny44a) Value(23)
EnumValue
-Enum(avr_mcu) String(attiny44a) Value(24)
+Enum(avr_mcu) String(attiny84) Value(24)
EnumValue
-Enum(avr_mcu) String(attiny84) Value(25)
+Enum(avr_mcu) String(attiny84a) Value(25)
EnumValue
-Enum(avr_mcu) String(attiny84a) Value(26)
+Enum(avr_mcu) String(attiny25) Value(26)
EnumValue
-Enum(avr_mcu) String(attiny25) Value(27)
+Enum(avr_mcu) String(attiny45) Value(27)
EnumValue
-Enum(avr_mcu) String(attiny45) Value(28)
+Enum(avr_mcu) String(attiny85) Value(28)
EnumValue
-Enum(avr_mcu) String(attiny85) Value(29)
+Enum(avr_mcu) String(attiny261) Value(29)
EnumValue
-Enum(avr_mcu) String(attiny261) Value(30)
+Enum(avr_mcu) String(attiny261a) Value(30)
EnumValue
-Enum(avr_mcu) String(attiny261a) Value(31)
+Enum(avr_mcu) String(attiny461) Value(31)
EnumValue
-Enum(avr_mcu) String(attiny461) Value(32)
+Enum(avr_mcu) String(attiny461a) Value(32)
EnumValue
-Enum(avr_mcu) String(attiny461a) Value(33)
+Enum(avr_mcu) String(attiny861) Value(33)
EnumValue
-Enum(avr_mcu) String(attiny861) Value(34)
+Enum(avr_mcu) String(attiny861a) Value(34)
EnumValue
-Enum(avr_mcu) String(attiny861a) Value(35)
+Enum(avr_mcu) String(attiny43u) Value(35)
EnumValue
-Enum(avr_mcu) String(attiny43u) Value(36)
+Enum(avr_mcu) String(attiny87) Value(36)
EnumValue
-Enum(avr_mcu) String(attiny87) Value(37)
+Enum(avr_mcu) String(attiny48) Value(37)
EnumValue
-Enum(avr_mcu) String(attiny48) Value(38)
+Enum(avr_mcu) String(attiny88) Value(38)
EnumValue
-Enum(avr_mcu) String(attiny88) Value(39)
+Enum(avr_mcu) String(at86rf401) Value(39)
EnumValue
-Enum(avr_mcu) String(at86rf401) Value(40)
+Enum(avr_mcu) String(avr3) Value(40)
EnumValue
-Enum(avr_mcu) String(avr3) Value(41)
+Enum(avr_mcu) String(at43usb355) Value(41)
EnumValue
-Enum(avr_mcu) String(at43usb355) Value(42)
+Enum(avr_mcu) String(at76c711) Value(42)
EnumValue
-Enum(avr_mcu) String(at76c711) Value(43)
+Enum(avr_mcu) String(avr31) Value(43)
EnumValue
-Enum(avr_mcu) String(avr31) Value(44)
+Enum(avr_mcu) String(atmega103) Value(44)
EnumValue
-Enum(avr_mcu) String(atmega103) Value(45)
+Enum(avr_mcu) String(at43usb320) Value(45)
EnumValue
-Enum(avr_mcu) String(at43usb320) Value(46)
+Enum(avr_mcu) String(avr35) Value(46)
EnumValue
-Enum(avr_mcu) String(avr35) Value(47)
+Enum(avr_mcu) String(ata5505) Value(47)
EnumValue
-Enum(avr_mcu) String(ata5505) Value(48)
+Enum(avr_mcu) String(at90usb82) Value(48)
EnumValue
-Enum(avr_mcu) String(at90usb82) Value(49)
+Enum(avr_mcu) String(at90usb162) Value(49)
EnumValue
-Enum(avr_mcu) String(at90usb162) Value(50)
+Enum(avr_mcu) String(atmega8u2) Value(50)
EnumValue
-Enum(avr_mcu) String(atmega8u2) Value(51)
+Enum(avr_mcu) String(atmega16u2) Value(51)
EnumValue
-Enum(avr_mcu) String(atmega16u2) Value(52)
+Enum(avr_mcu) String(atmega32u2) Value(52)
EnumValue
-Enum(avr_mcu) String(atmega32u2) Value(53)
+Enum(avr_mcu) String(attiny167) Value(53)
EnumValue
-Enum(avr_mcu) String(attiny167) Value(54)
+Enum(avr_mcu) String(attiny1634) Value(54)
EnumValue
-Enum(avr_mcu) String(attiny1634) Value(55)
+Enum(avr_mcu) String(avr4) Value(55)
EnumValue
-Enum(avr_mcu) String(avr4) Value(56)
+Enum(avr_mcu) String(ata6285) Value(56)
EnumValue
-Enum(avr_mcu) String(ata6285) Value(57)
+Enum(avr_mcu) String(ata6286) Value(57)
EnumValue
-Enum(avr_mcu) String(ata6286) Value(58)
+Enum(avr_mcu) String(ata6289) Value(58)
EnumValue
Enum(avr_mcu) String(atmega8) Value(59)
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 2edc78ac041..9285ccd1148 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -51,6 +51,7 @@
#include "target-def.h"
#include "params.h"
#include "df.h"
+#include "builtins.h"
/* Maximal allowed offset for an address in the LD command */
#define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
@@ -359,7 +360,7 @@ avr_option_override (void)
static struct machine_function *
avr_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
@@ -2359,6 +2360,12 @@ avr_notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
}
break;
+ case CC_SET_VZN:
+ /* Insn like INC, DEC, NEG that set Z,N,V. We currently don't make use
+ of this combination, cf. also PR61055. */
+ CC_STATUS_INIT;
+ break;
+
case CC_SET_CZN:
/* Insn sets the Z,N,C flags of CC to recog_operand[0].
The V flag may or may not be known but that's ok because
@@ -3993,7 +4000,7 @@ avr_out_store_psi (rtx insn, rtx *op, int *plen)
"std Y+61,%A1" CR_TAB
"std Y+62,%B1" CR_TAB
"std Y+63,%C1" CR_TAB
- "sbiw r28,%o0-60", op, plen, -5);
+ "sbiw r28,%o0-61", op, plen, -5);
return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
"sbci r29,hi8(-%o0)" CR_TAB
@@ -6290,7 +6297,7 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
if (REG_P (xop[2]))
{
- *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_SET_N;
+ *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_CLOBBER;
for (i = 0; i < n_bytes; i++)
{
@@ -6399,7 +6406,7 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
op, plen, 1);
if (n_bytes == 2 && PLUS == code)
- *pcc = CC_SET_ZN;
+ *pcc = CC_SET_CZN;
}
i++;
@@ -6422,6 +6429,7 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
{
avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
op, plen, 1);
+ *pcc = CC_CLOBBER;
break;
}
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index 78434ec5e0d..9d34983e497 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -251,18 +251,18 @@ enum reg_class {
#define REG_CLASS_CONTENTS { \
{0x00000000,0x00000000}, /* NO_REGS */ \
{0x00000001,0x00000000}, /* R0_REG */ \
- {3 << REG_X,0x00000000}, /* POINTER_X_REGS, r26 - r27 */ \
- {3 << REG_Y,0x00000000}, /* POINTER_Y_REGS, r28 - r29 */ \
- {3 << REG_Z,0x00000000}, /* POINTER_Z_REGS, r30 - r31 */ \
+ {3u << REG_X,0x00000000}, /* POINTER_X_REGS, r26 - r27 */ \
+ {3u << REG_Y,0x00000000}, /* POINTER_Y_REGS, r28 - r29 */ \
+ {3u << REG_Z,0x00000000}, /* POINTER_Z_REGS, r30 - r31 */ \
{0x00000000,0x00000003}, /* STACK_REG, STACK */ \
- {(3 << REG_Y) | (3 << REG_Z), \
+ {(3u << REG_Y) | (3u << REG_Z), \
0x00000000}, /* BASE_POINTER_REGS, r28 - r31 */ \
- {(3 << REG_X) | (3 << REG_Y) | (3 << REG_Z), \
+ {(3u << REG_X) | (3u << REG_Y) | (3u << REG_Z), \
0x00000000}, /* POINTER_REGS, r26 - r31 */ \
- {(3 << REG_X) | (3 << REG_Y) | (3 << REG_Z) | (3 << REG_W), \
+ {(3u << REG_X) | (3u << REG_Y) | (3u << REG_Z) | (3u << REG_W), \
0x00000000}, /* ADDW_REGS, r24 - r31 */ \
{0x00ff0000,0x00000000}, /* SIMPLE_LD_REGS r16 - r23 */ \
- {(3 << REG_X)|(3 << REG_Y)|(3 << REG_Z)|(3 << REG_W)|(0xff << 16), \
+ {(3u << REG_X)|(3u << REG_Y)|(3u << REG_Z)|(3u << REG_W)|(0xffu << 16),\
0x00000000}, /* LD_REGS, r16 - r31 */ \
{0x0000ffff,0x00000000}, /* NO_LD_REGS r0 - r15 */ \
{0xffffffff,0x00000000}, /* GENERAL_REGS, r0 - r31 */ \
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index d7baa4a8383..2c59bf3f93b 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -90,7 +90,7 @@
(include "constraints.md")
;; Condition code settings.
-(define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber,
+(define_attr "cc" "none,set_czn,set_zn,set_vzn,set_n,compare,clobber,
plus,ldi"
(const_string "none"))
@@ -1098,7 +1098,7 @@
inc %0\;inc %0
dec %0\;dec %0"
[(set_attr "length" "1,1,1,1,2,2")
- (set_attr "cc" "set_czn,set_czn,set_zn,set_zn,set_zn,set_zn")])
+ (set_attr "cc" "set_czn,set_czn,set_vzn,set_vzn,set_vzn,set_vzn")])
;; "addhi3"
;; "addhq3" "adduhq3"
@@ -1369,7 +1369,7 @@
dec %0\;dec %0
inc %0\;inc %0"
[(set_attr "length" "1,1,1,1,2,2")
- (set_attr "cc" "set_czn,set_czn,set_zn,set_zn,set_zn,set_zn")])
+ (set_attr "cc" "set_czn,set_czn,set_vzn,set_vzn,set_vzn,set_vzn")])
;; "subhi3"
;; "subhq3" "subuhq3"
@@ -3992,7 +3992,7 @@
""
"neg %0"
[(set_attr "length" "1")
- (set_attr "cc" "set_zn")])
+ (set_attr "cc" "set_vzn")])
(define_insn "*negqihi2"
[(set (match_operand:HI 0 "register_operand" "=r")
diff --git a/gcc/config/avr/t-multilib b/gcc/config/avr/t-multilib
index 301f86496cc..138e3a870c0 100644
--- a/gcc/config/avr/t-multilib
+++ b/gcc/config/avr/t-multilib
@@ -52,7 +52,6 @@ MULTILIB_MATCHES = \
mmcu?avr2=mmcu?at90s8515 \
mmcu?avr2=mmcu?at90c8534 \
mmcu?avr2=mmcu?at90s8535 \
- mmcu?avr25=mmcu?ata6289 \
mmcu?avr25=mmcu?ata5272 \
mmcu?avr25=mmcu?attiny13 \
mmcu?avr25=mmcu?attiny13a \
@@ -93,6 +92,7 @@ MULTILIB_MATCHES = \
mmcu?avr35=mmcu?attiny1634 \
mmcu?avr4=mmcu?ata6285 \
mmcu?avr4=mmcu?ata6286 \
+ mmcu?avr4=mmcu?ata6289 \
mmcu?avr4=mmcu?atmega8 \
mmcu?avr4=mmcu?atmega8a \
mmcu?avr4=mmcu?atmega48 \
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 84b2d01c730..35408eb68cf 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -59,6 +59,7 @@
#include "hw-doloop.h"
#include "opts.h"
#include "dumpfile.h"
+#include "builtins.h"
/* A C structure for machine-specific, per-function data.
This is added to the cfun structure. */
@@ -2317,7 +2318,7 @@ bfin_class_likely_spilled_p (reg_class_t rclass)
static struct machine_function *
bfin_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* Implement the TARGET_OPTION_OVERRIDE hook. */
@@ -2588,7 +2589,7 @@ split_load_immediate (rtx operands[])
&& (D_REGNO_P (regno)
|| (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
{
- emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
+ emit_insn (gen_movsi (operands[0], gen_int_mode (shifted, SImode)));
emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
return 1;
}
@@ -2602,13 +2603,15 @@ split_load_immediate (rtx operands[])
if (log2constp (val & 0xFFFF0000))
{
emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
- emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
+ emit_insn (gen_iorsi3 (operands[0], operands[0],
+ gen_int_mode (val & 0xFFFF0000, SImode)));
return 1;
}
else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
{
emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
- emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
+ emit_insn (gen_andsi3 (operands[0], operands[0],
+ gen_int_mode (val | 0xFFFF, SImode)));
}
}
@@ -2617,7 +2620,9 @@ split_load_immediate (rtx operands[])
if (tmp >= -64 && tmp <= 63)
{
emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
- emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
+ emit_insn (gen_movstricthi_high (operands[0],
+ gen_int_mode (val & -65536,
+ SImode)));
return 1;
}
@@ -2645,7 +2650,7 @@ split_load_immediate (rtx operands[])
{
/* If optimizing for size, generate a sequence that has more instructions
but is shorter. */
- emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
+ emit_insn (gen_movsi (operands[0], gen_int_mode (shifted_compl, SImode)));
emit_insn (gen_ashlsi3 (operands[0], operands[0],
GEN_INT (num_compl_zero)));
emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index 9ba10df73c6..f0d8cbb42fd 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -57,6 +57,7 @@
#include "regrename.h"
#include "dumpfile.h"
#include "gimple-expr.h"
+#include "builtins.h"
/* Table of supported architecture variants. */
typedef struct
@@ -205,7 +206,7 @@ unsigned const dbx_register_map[FIRST_PSEUDO_REGISTER] =
static struct machine_function *
c6x_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* Implement TARGET_OPTION_OVERRIDE. */
@@ -985,7 +986,7 @@ c6x_elf_unique_section (tree decl, int reloc)
{
const char *prefix = NULL;
/* We only need to use .gnu.linkonce if we don't have COMDAT groups. */
- bool one_only = DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP;
+ bool one_only = DECL_COMDAT_GROUP (decl) && !HAVE_COMDAT_GROUP;
if (c6x_in_small_data_p (decl))
{
@@ -1202,7 +1203,7 @@ c6x_function_in_section_p (tree decl, section *section)
if (!DECL_SECTION_NAME (decl))
{
/* Make sure that we will not create a unique section for DECL. */
- if (flag_function_sections || DECL_ONE_ONLY (decl))
+ if (flag_function_sections || DECL_COMDAT_GROUP (decl))
return false;
}
diff --git a/gcc/config/cr16/cr16.c b/gcc/config/cr16/cr16.c
index f5a444bec48..e9bfc8917f0 100644
--- a/gcc/config/cr16/cr16.c
+++ b/gcc/config/cr16/cr16.c
@@ -45,6 +45,7 @@
#include "target.h"
#include "target-def.h"
#include "df.h"
+#include "builtins.h"
/* Definitions. */
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 209f127a6ca..cbed2df8ead 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "df.h"
#include "opts.h"
#include "cgraph.h"
+#include "builtins.h"
/* Usable when we have an amount to add or subtract, and want the
optimal size of the insn. */
@@ -2808,7 +2809,7 @@ cris_init_expanders (void)
static struct machine_function *
cris_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* Split a 2 word move (DI or presumably DF) into component parts.
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index 3c50e24edf2..a2c87491d21 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h"
#include "gimplify.h"
#include "lto-streamer.h"
+#include "lto-section-names.h"
/* Darwin supports a feature called fix-and-continue, which is used
for rapid turn around debugging. When code is compiled with the
@@ -561,7 +562,7 @@ machopic_indirection_name (rtx sym_ref, bool stub_p)
}
else
{
- p = ggc_alloc_machopic_indirection ();
+ p = ggc_alloc<machopic_indirection> ();
p->symbol = sym_ref;
p->ptr_name = xstrdup (buffer);
p->stub_p = stub_p;
@@ -1521,7 +1522,7 @@ machopic_select_section (tree decl,
one = DECL_P (decl)
&& TREE_CODE (decl) == VAR_DECL
- && DECL_ONE_ONLY (decl);
+ && DECL_COMDAT_GROUP (decl);
ro = TREE_READONLY (decl) || TREE_CONSTANT (decl) ;
@@ -1898,9 +1899,6 @@ typedef struct GTY (()) darwin_lto_section_e {
static GTY (()) vec<darwin_lto_section_e, va_gc> *lto_section_names;
-/* Segment for LTO data. */
-#define LTO_SEGMENT_NAME "__GNU_LTO"
-
/* Section wrapper scheme (used here to wrap the unlimited number of LTO
sections into three Mach-O ones).
NOTE: These names MUST be kept in sync with those in
@@ -3499,7 +3497,7 @@ darwin_build_constant_cfstring (tree str)
}
}
- *loc = desc = ggc_alloc_cleared_cfstring_descriptor ();
+ *loc = desc = ggc_cleared_alloc<cfstring_descriptor> ();
desc->literal = str;
/* isa *. */
@@ -3586,7 +3584,7 @@ darwin_enter_string_into_cfstring_table (tree str)
if (!*loc)
{
- *loc = ggc_alloc_cleared_cfstring_descriptor ();
+ *loc = ggc_cleared_alloc<cfstring_descriptor> ();
((struct cfstring_descriptor *)*loc)->literal = str;
}
}
diff --git a/gcc/config/dbx.h b/gcc/config/dbx.h
index 1b68bcd9a93..8173bb06cf9 100644
--- a/gcc/config/dbx.h
+++ b/gcc/config/dbx.h
@@ -13,8 +13,13 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* This file causes gcc to prefer using DBX (stabs) debugging
diff --git a/gcc/config/dragonfly-stdint.h b/gcc/config/dragonfly-stdint.h
new file mode 100644
index 00000000000..f0bb30f3a5b
--- /dev/null
+++ b/gcc/config/dragonfly-stdint.h
@@ -0,0 +1,56 @@
+/* Definitions for <stdint.h> types for DragonFly systems.
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ Contributed by John Marino <gnugcc@marino.st>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#define SIG_ATOMIC_TYPE "int"
+
+#define INT8_TYPE "signed char"
+#define INT16_TYPE "short int"
+#define INT32_TYPE "int"
+#define INT64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT8_TYPE "unsigned char"
+#define UINT16_TYPE "short unsigned int"
+#define UINT32_TYPE "unsigned int"
+#define UINT64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INT_LEAST8_TYPE INT8_TYPE
+#define INT_LEAST16_TYPE INT16_TYPE
+#define INT_LEAST32_TYPE INT32_TYPE
+#define INT_LEAST64_TYPE INT64_TYPE
+#define UINT_LEAST8_TYPE UINT8_TYPE
+#define UINT_LEAST16_TYPE UINT16_TYPE
+#define UINT_LEAST32_TYPE UINT32_TYPE
+#define UINT_LEAST64_TYPE UINT64_TYPE
+
+#define INT_FAST8_TYPE INT32_TYPE
+#define INT_FAST16_TYPE INT32_TYPE
+#define INT_FAST32_TYPE INT32_TYPE
+#define INT_FAST64_TYPE INT64_TYPE
+#define UINT_FAST8_TYPE UINT32_TYPE
+#define UINT_FAST16_TYPE UINT32_TYPE
+#define UINT_FAST32_TYPE UINT32_TYPE
+#define UINT_FAST64_TYPE UINT64_TYPE
+
+#define INTPTR_TYPE (LONG_TYPE_SIZE == 64 ? INT64_TYPE : INT32_TYPE)
+#define UINTPTR_TYPE (LONG_TYPE_SIZE == 64 ? UINT64_TYPE : UINT32_TYPE)
diff --git a/gcc/config/dragonfly.h b/gcc/config/dragonfly.h
new file mode 100644
index 00000000000..115c25d3b99
--- /dev/null
+++ b/gcc/config/dragonfly.h
@@ -0,0 +1,129 @@
+/* Base configuration file for all DragonFly targets.
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ Contributed by John Marino <gnugcc@marino.st>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("unix"); \
+ builtin_define ("__DragonFly__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=bsd"); \
+ builtin_assert ("system=DragonFly"); \
+ } \
+ while (0)
+
+#undef CPP_SPEC
+#define CPP_SPEC \
+ "%(cpp_cpu) %(cpp_arch) %{posix:-D_POSIX_SOURCE}"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shared: \
+ %{pg:gcrt1.o%s} \
+ %{!pg: \
+ %{p:gcrt1.o%s} \
+ %{!p: \
+ %{profile: gcrt1.o%s} \
+ %{!profile: \
+ %{pie: Scrt1.o%s;:crt1.o%s}}}}} \
+ crti.o%s \
+ %{shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
+
+#undef LIB_SPEC
+#define LIB_SPEC \
+ "%{pthread:-lpthread} -lc"
+
+#if defined(HAVE_LD_EH_FRAME_HDR)
+#define LINK_EH_SPEC "--eh-frame-hdr"
+#endif
+
+/* Provide a LINK_SPEC appropriate for DragonFly. Here we provide support
+ for the special GCC options -static and -shared, which allow us to
+ link things in one of these three modes by applying the appropriate
+ combinations of options at link-time.
+
+ When the -shared link option is used a final link is not being
+ done. */
+
+#define DFBSD_LINK_SPEC \
+ "%{p:%nconsider using '-pg' instead of '-p' with gprof(1)} \
+ %{v:-V} \
+ %{assert*} %{R*} %{rpath*} %{defsym*} \
+ %{shared:-Bshareable %{h*} %{soname*}} \
+ %{!shared: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ -dynamic-linker %(dfbsd_dynamic_linker) \
+ } \
+ %{static:-Bstatic} \
+ } \
+ %{!static:--hash-style=gnu} \
+ %{symbolic:-Bsymbolic}"
+
+#undef LINK_SPEC
+#define LINK_SPEC DFBSD_LINK_SPEC
+
+#define DFBSD_DYNAMIC_LINKER "/usr/libexec/ld-elf.so.2"
+
+
+/* Use --as-needed -lgcc_s for eh support. */
+#ifdef HAVE_LD_AS_NEEDED
+#define USE_LD_AS_NEEDED 1
+#endif
+
+/************************[ Target stuff ]***********************************/
+
+/* All DragonFly Architectures support the ELF object file format. */
+#undef OBJECT_FORMAT_ELF
+#define OBJECT_FORMAT_ELF
+
+/* Don't assume anything about the header files. */
+#undef NO_IMPLICIT_EXTERN_C
+#define NO_IMPLICIT_EXTERN_C 1
+
+/* Follow DragonFly's standard headers (<machine/stdint.h>, etc...). */
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+
+#undef WINT_TYPE
+#define WINT_TYPE "int"
+
+/* Code generation parameters. */
+
+/* Use periods rather than dollar signs in special g++ assembler names.
+ This ensures the configuration knows our system correctly so we can link
+ with libraries compiled with the native cc. */
+#undef NO_DOLLAR_IN_LABEL
+
+/* Used by libgcc2.c. We support file locking with fcntl / F_SETLKW.
+ This enables the test coverage code to use file locking when exiting a
+ program, which avoids race conditions if the program has forked. */
+#define TARGET_POSIX_IO
diff --git a/gcc/config/dragonfly.opt b/gcc/config/dragonfly.opt
new file mode 100644
index 00000000000..c87828d1c6d
--- /dev/null
+++ b/gcc/config/dragonfly.opt
@@ -0,0 +1,64 @@
+; DragonFly BSD options.
+
+; Copyright (C) 2014 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 3, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3. If not see
+; <http://www.gnu.org/licenses/>.
+
+; See the GCC internals manual (options.texi) for a description of this file's format.
+
+; Please try to keep this file in ASCII collating order.
+
+assert
+Driver Separate
+
+assert=
+Driver JoinedOrMissing
+
+defsym
+Driver Separate
+
+defsym=
+Driver JoinedOrMissing
+
+posix
+Driver
+
+profile
+Driver
+
+pthread
+Driver
+
+rdynamic
+Driver
+
+rpath-link
+Driver Separate
+
+rpath-link=
+Driver JoinedOrMissing
+
+rpath=
+Driver JoinedOrMissing
+
+soname
+Driver Separate
+
+soname=
+Driver JoinedOrMissing
+
+; This comment is to ensure we retain the blank line above.
diff --git a/gcc/config/epiphany/epiphany-protos.h b/gcc/config/epiphany/epiphany-protos.h
index 9121e0c3c97..bfa48021443 100644
--- a/gcc/config/epiphany/epiphany-protos.h
+++ b/gcc/config/epiphany/epiphany-protos.h
@@ -45,9 +45,7 @@ extern void emit_set_fp_mode (int entity, int mode, HARD_REG_SET regs_live);
extern void epiphany_insert_mode_switch_use (rtx insn, int, int);
extern void epiphany_expand_set_fp_mode (rtx *operands);
extern int epiphany_mode_needed (int entity, rtx insn);
-extern int epiphany_mode_entry_exit (int entity, bool);
extern int epiphany_mode_after (int entity, int last_mode, rtx insn);
-extern int epiphany_mode_priority_to_mode (int entity, unsigned priority);
extern bool epiphany_epilogue_uses (int regno);
extern bool epiphany_optimize_mode_switching (int entity);
extern bool epiphany_is_interrupt_p (tree);
diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c
index ebe6f05302d..5a4d89e4ebc 100644
--- a/gcc/config/epiphany/epiphany.c
+++ b/gcc/config/epiphany/epiphany.c
@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h" /* for current_pass */
#include "context.h"
#include "pass_manager.h"
+#include "builtins.h"
/* Which cpu we're compiling for. */
int epiphany_cpu_type;
@@ -152,6 +153,20 @@ static rtx frame_insn (rtx);
/* We further restrict the minimum to be a multiple of eight. */
#define TARGET_MIN_ANCHOR_OFFSET (optimize_size ? 0 : -2040)
+/* Mode switching hooks. */
+
+#define TARGET_MODE_EMIT emit_set_fp_mode
+
+#define TARGET_MODE_NEEDED epiphany_mode_needed
+
+#define TARGET_MODE_PRIORITY epiphany_mode_priority
+
+#define TARGET_MODE_ENTRY epiphany_mode_entry
+
+#define TARGET_MODE_EXIT epiphany_mode_exit
+
+#define TARGET_MODE_AFTER epiphany_mode_after
+
#include "target-def.h"
#undef TARGET_ASM_ALIGNED_HI_OP
@@ -968,7 +983,7 @@ epiphany_init_machine_status (void)
/* Reset state info for each function. */
current_frame_info = zero_frame_info;
- machine = ggc_alloc_cleared_machine_function_t ();
+ machine = ggc_cleared_alloc<machine_function_t> ();
return machine;
}
@@ -2319,8 +2334,8 @@ epiphany_optimize_mode_switching (int entity)
gcc_unreachable ();
}
-int
-epiphany_mode_priority_to_mode (int entity, unsigned priority)
+static int
+epiphany_mode_priority (int entity, int priority)
{
if (entity == EPIPHANY_MSW_ENTITY_AND || entity == EPIPHANY_MSW_ENTITY_OR
|| entity== EPIPHANY_MSW_ENTITY_CONFIG)
@@ -2428,7 +2443,7 @@ epiphany_mode_needed (int entity, rtx insn)
}
}
-int
+static int
epiphany_mode_entry_exit (int entity, bool exit)
{
int normal_mode = epiphany_normal_fp_mode ;
@@ -2515,6 +2530,18 @@ epiphany_mode_after (int entity, int last_mode, rtx insn)
return last_mode;
}
+static int
+epiphany_mode_entry (int entity)
+{
+ return epiphany_mode_entry_exit (entity, false);
+}
+
+static int
+epiphany_mode_exit (int entity)
+{
+ return epiphany_mode_entry_exit (entity, true);
+}
+
void
emit_set_fp_mode (int entity, int mode, HARD_REG_SET regs_live ATTRIBUTE_UNUSED)
{
diff --git a/gcc/config/epiphany/epiphany.h b/gcc/config/epiphany/epiphany.h
index 1ca92e07b9e..f64652e4895 100644
--- a/gcc/config/epiphany/epiphany.h
+++ b/gcc/config/epiphany/epiphany.h
@@ -899,19 +899,6 @@ enum epiphany_function_type
{ 2, 2, 2, \
FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE }
-#define MODE_NEEDED(ENTITY, INSN) epiphany_mode_needed((ENTITY), (INSN))
-
-#define MODE_PRIORITY_TO_MODE(ENTITY, N) \
- (epiphany_mode_priority_to_mode ((ENTITY), (N)))
-
-#define EMIT_MODE_SET(ENTITY, MODE, HARD_REGS_LIVE) \
- emit_set_fp_mode ((ENTITY), (MODE), (HARD_REGS_LIVE))
-
-#define MODE_ENTRY(ENTITY) (epiphany_mode_entry_exit ((ENTITY), false))
-#define MODE_EXIT(ENTITY) (epiphany_mode_entry_exit ((ENTITY), true))
-#define MODE_AFTER(ENTITY, LAST_MODE, INSN) \
- (epiphany_mode_after ((ENTITY), (LAST_MODE), (INSN)))
-
#define TARGET_INSERT_MODE_SWITCH_USE epiphany_insert_mode_switch_use
/* Mode switching entities. */
diff --git a/gcc/config/epiphany/mode-switch-use.c b/gcc/config/epiphany/mode-switch-use.c
index 9617041a310..cc80d103c55 100644
--- a/gcc/config/epiphany/mode-switch-use.c
+++ b/gcc/config/epiphany/mode-switch-use.c
@@ -58,7 +58,7 @@ insert_uses (void)
{
if (!INSN_P (insn))
continue;
- mode = MODE_NEEDED (e, insn);
+ mode = epiphany_mode_needed (e, insn);
if (mode == no_mode)
continue;
if (target_insert_mode_switch_use)
diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c
index 65084f69c1d..37759cc7bd4 100644
--- a/gcc/config/fr30/fr30.c
+++ b/gcc/config/fr30/fr30.c
@@ -45,6 +45,7 @@
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
+#include "builtins.h"
/*}}}*/
/*{{{ Function Prologues & Epilogues */
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index f2dadc3d9ba..fda2c1fd857 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "df.h"
#include "dumpfile.h"
+#include "builtins.h"
#ifndef FRV_INLINE
#define FRV_INLINE inline
@@ -7009,7 +7010,7 @@ frv_assemble_integer (rtx value, unsigned int size, int aligned_p)
static struct machine_function *
frv_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* Implement TARGET_SCHED_ISSUE_RATE. */
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index e7ed03a6628..a0ff81b20b1 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "target-def.h"
#include "df.h"
+#include "builtins.h"
/* Classifies a h8300_src_operand or h8300_dst_operand.
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index e20ed35fea4..bc592dcfaf3 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -3589,7 +3589,7 @@
[(set_attr "cc" "clobber")])
(define_insn_and_split "*cmpstz"
- [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU,+WU")
+ [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU,WU")
(const_int 1)
(match_operand:QI 1 "immediate_operand" "n,n"))
(match_operator:QI 2 "eqne_operator"
diff --git a/gcc/config/i386/clflushoptintrin.h b/gcc/config/i386/clflushoptintrin.h
new file mode 100644
index 00000000000..026561242ab
--- /dev/null
+++ b/gcc/config/i386/clflushoptintrin.h
@@ -0,0 +1,49 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#if !defined _X86INTRIN_H_INCLUDED
+# error "Never use <clflushoptintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef _CLFLUSHOPTINTRIN_H_INCLUDED
+#define _CLFLUSHOPTINTRIN_H_INCLUDED
+
+#ifndef __CLFLUSHOPT__
+#pragma GCC push_options
+#pragma GCC target("clflushopt")
+#define __DISABLE_CLFLUSHOPT__
+#endif /* __CLFLUSHOPT__ */
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_clflushopt (void *__A)
+{
+ __builtin_ia32_clflushopt (__A);
+}
+
+#ifdef __DISABLE_CLFLUSHOPT__
+#undef __DISABLE_CLFLUSHOPT__
+#pragma GCC pop_options
+#endif /* __DISABLE_CLFLUSHOPT__ */
+
+#endif /* _CLFLUSHOPTINTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 567e705646a..8e0a58355ec 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -18,8 +18,8 @@
;; <http://www.gnu.org/licenses/>.
;;; Unused letters:
-;;; B H
-;;; h j
+;;; H
+;;; h j w z
;; Integer register constraints.
;; It is not necessary to define 'r' here.
@@ -91,6 +91,9 @@
(define_register_constraint "x" "TARGET_SSE ? SSE_REGS : NO_REGS"
"Any SSE register.")
+(define_register_constraint "v" "TARGET_SSE ? ALL_SSE_REGS : NO_REGS"
+ "Any EVEX encodable SSE register (@code{%xmm0-%xmm31}).")
+
;; We use the Y prefix to denote any number of conditional register sets:
;; z First SSE register.
;; i SSE2 inter-unit moves to SSE register enabled
@@ -144,18 +147,25 @@
"(ix86_fpmath & FPMATH_387) ? FLOAT_REGS : NO_REGS"
"@internal Any x87 register when 80387 FP arithmetic is enabled.")
-(define_register_constraint "v" "TARGET_SSE ? ALL_SSE_REGS : NO_REGS"
- "Any EVEX encodable SSE register (@code{%xmm0-%xmm31}).")
+;; We use the B prefix to denote any number of internal operands:
+;; s Sibcall memory operand, not valid for TARGET_X32
+;; w Call memory operand, not valid for TARGET_X32
+;; z Constant call address operand.
-(define_constraint "z"
- "@internal Constant call address operand."
- (match_operand 0 "constant_call_address_operand"))
+(define_constraint "Bs"
+ "@internal Sibcall memory operand."
+ (and (not (match_test "TARGET_X32"))
+ (match_operand 0 "sibcall_memory_operand")))
-(define_constraint "w"
+(define_constraint "Bw"
"@internal Call memory operand."
(and (not (match_test "TARGET_X32"))
(match_operand 0 "memory_operand")))
+(define_constraint "Bz"
+ "@internal Constant call address operand."
+ (match_operand 0 "constant_call_address_operand"))
+
;; Integer constant constraints.
(define_constraint "I"
"Integer constant in the range 0 @dots{} 31, for 32-bit shifts."
diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
index 8c323ae3a70..7ac22a1683d 100644
--- a/gcc/config/i386/cpuid.h
+++ b/gcc/config/i386/cpuid.h
@@ -75,6 +75,7 @@
#define bit_AVX512F (1 << 16)
#define bit_RDSEED (1 << 18)
#define bit_ADX (1 << 19)
+#define bit_CLFLUSHOPT (1 << 23)
#define bit_AVX512PF (1 << 26)
#define bit_AVX512ER (1 << 27)
#define bit_AVX512CD (1 << 28)
@@ -85,6 +86,8 @@
/* Extended State Enumeration Sub-leaf (%eax == 13, %ecx == 1) */
#define bit_XSAVEOPT (1 << 0)
+#define bit_XSAVEC (1 << 1)
+#define bit_XSAVES (1 << 3)
/* Signatures for different CPU implementations as returned in uses
of cpuid with level 0. */
diff --git a/gcc/config/i386/dragonfly.h b/gcc/config/i386/dragonfly.h
new file mode 100644
index 00000000000..71362d58e32
--- /dev/null
+++ b/gcc/config/i386/dragonfly.h
@@ -0,0 +1,104 @@
+/* Definitions for Intel 386 running DragonFly with ELF format
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ Contributed by John Marino <gnugcc@marino.st>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+
+/* Override the default comment-starter of "/". */
+#undef ASM_COMMENT_START
+#define ASM_COMMENT_START "#"
+
+#undef ASM_APP_ON
+#define ASM_APP_ON "#APP\n"
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF "#NO_APP\n"
+
+#undef DBX_REGISTER_NUMBER
+#define DBX_REGISTER_NUMBER(n) \
+ (TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n])
+
+#undef NO_PROFILE_COUNTERS
+#define NO_PROFILE_COUNTERS 1
+
+/* Tell final.c that we don't need a label passed to mcount. */
+
+#undef MCOUNT_NAME
+#define MCOUNT_NAME ".mcount"
+
+/* Make gcc agree with <machine/ansi.h>. */
+
+#undef SIZE_TYPE
+#define SIZE_TYPE (TARGET_64BIT ? "long unsigned int" : "unsigned int")
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int")
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE (TARGET_64BIT ? 32 : BITS_PER_WORD)
+
+#undef SUBTARGET_EXTRA_SPECS /* i386.h bogusly defines it. */
+#define SUBTARGET_EXTRA_SPECS \
+ { "dfbsd_dynamic_linker", DFBSD_DYNAMIC_LINKER }
+
+/* A C statement to output to the stdio stream FILE an assembler
+ command to advance the location counter to a multiple of 1<<LOG
+ bytes if it is within MAX_SKIP bytes.
+
+ This is used to align code labels according to Intel recommendations. */
+
+#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
+#undef ASM_OUTPUT_MAX_SKIP_ALIGN
+#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE, LOG, MAX_SKIP) \
+ if ((LOG) != 0) { \
+ if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
+ else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
+ }
+#endif
+
+/* Don't default to pcc-struct-return, we want to retain compatibility with
+ older gcc versions AND pcc-struct-return is nonreentrant.
+ (even though the SVR4 ABI for the i386 says that records and unions are
+ returned in memory). */
+
+#undef DEFAULT_PCC_STRUCT_RETURN
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* DragonFly sets the rounding precision of the FPU to 53 bits. Let the
+ compiler get the contents of <float.h> and std::numeric_limits correct. */
+#undef TARGET_96_ROUND_53_LONG_DOUBLE
+#define TARGET_96_ROUND_53_LONG_DOUBLE (!TARGET_64BIT)
+
+/* Put all *tf routines in libgcc. */
+#undef LIBGCC2_HAS_TF_MODE
+#define LIBGCC2_HAS_TF_MODE 1
+#define LIBGCC2_TF_CEXT q
+#define TF_SIZE 113
+
+/* Static stack checking is supported by means of probes. */
+#define STACK_CHECK_STATIC_BUILTIN 1
+
+/* Support for i386 was removed from DragonFly in 2007 */
+#define SUBTARGET32_DEFAULT_CPU "i486"
+
+#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 1f5a11c9c08..3e8a995f285 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -410,6 +410,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
unsigned int has_osxsave = 0, has_fxsr = 0, has_xsave = 0, has_xsaveopt = 0;
unsigned int has_avx512er = 0, has_avx512pf = 0, has_avx512cd = 0;
unsigned int has_avx512f = 0, has_sha = 0, has_prefetchwt1 = 0;
+ unsigned int has_clflushopt = 0, has_xsavec = 0, has_xsaves = 0;
bool arch;
@@ -486,6 +487,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
has_avx512pf = ebx & bit_AVX512PF;
has_avx512cd = ebx & bit_AVX512CD;
has_sha = ebx & bit_SHA;
+ has_clflushopt = ebx & bit_CLFLUSHOPT;
has_prefetchwt1 = ecx & bit_PREFETCHWT1;
}
@@ -495,6 +497,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
__cpuid_count (13, 1, eax, ebx, ecx, edx);
has_xsaveopt = eax & bit_XSAVEOPT;
+ has_xsavec = eax & bit_XSAVEC;
+ has_xsaves = eax & bit_XSAVES;
}
/* Check cpuid level of extended features. */
@@ -541,6 +545,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
has_xop = 0;
has_xsave = 0;
has_xsaveopt = 0;
+ has_xsaves = 0;
+ has_xsavec = 0;
}
if (!arch)
@@ -886,6 +892,9 @@ const char *host_detect_local_cpu (int argc, const char **argv)
const char *avx512cd = has_avx512cd ? " -mavx512cd" : " -mno-avx512cd";
const char *avx512pf = has_avx512pf ? " -mavx512pf" : " -mno-avx512pf";
const char *prefetchwt1 = has_prefetchwt1 ? " -mprefetchwt1" : " -mno-prefetchwt1";
+ const char *clflushopt = has_clflushopt ? " -mclflushopt" : " -mno-clflushopt";
+ const char *xsavec = has_xsavec ? " -mxsavec" : " -mno-xsavec";
+ const char *xsaves = has_xsaves ? " -mxsaves" : " -mno-xsaves";
options = concat (options, mmx, mmx3dnow, sse, sse2, sse3, ssse3,
sse4a, cx16, sahf, movbe, aes, sha, pclmul,
@@ -893,7 +902,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
tbm, avx, avx2, sse4_2, sse4_1, lzcnt, rtm,
hle, rdrnd, f16c, fsgsbase, rdseed, prfchw, adx,
fxsr, xsave, xsaveopt, avx512f, avx512er,
- avx512cd, avx512pf, prefetchwt1, NULL);
+ avx512cd, avx512pf, prefetchwt1, clflushopt,
+ xsavec, xsaves, NULL);
}
done:
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index 2c31dc8062d..2c05cec0c4b 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -393,6 +393,12 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
def_or_undef (parse_in, "__SSE_MATH__");
if ((fpmath & FPMATH_SSE) && (isa_flag & OPTION_MASK_ISA_SSE2))
def_or_undef (parse_in, "__SSE2_MATH__");
+ if (isa_flag & OPTION_MASK_ISA_CLFLUSHOPT)
+ def_or_undef (parse_in, "__CLFLUSHOPT__");
+ if (isa_flag & OPTION_MASK_ISA_XSAVEC)
+ def_or_undef (parse_in, "__XSAVEC__");
+ if (isa_flag & OPTION_MASK_ISA_XSAVES)
+ def_or_undef (parse_in, "__XSAVES__");
}
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 6e329788088..39462bd6211 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -166,17 +166,8 @@ extern bool ix86_secondary_memory_needed (enum reg_class, enum reg_class,
extern bool ix86_cannot_change_mode_class (enum machine_mode,
enum machine_mode, enum reg_class);
-extern int ix86_mode_needed (int, rtx);
-extern int ix86_mode_after (int, int, rtx);
-extern int ix86_mode_entry (int);
-extern int ix86_mode_exit (int);
-
extern bool ix86_libc_has_function (enum function_class fn_class);
-#ifdef HARD_CONST
-extern void ix86_emit_mode_set (int, int, HARD_REG_SET);
-#endif
-
extern void x86_order_regs_for_local_alloc (void);
extern void x86_function_profiler (FILE *, int);
extern void x86_emit_floatuns (rtx [2]);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 01ad5e50193..84f79dd1d7f 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -83,6 +83,8 @@ along with GCC; see the file COPYING3. If not see
#include "pass_manager.h"
#include "target-globals.h"
#include "tree-vectorizer.h"
+#include "shrink-wrap.h"
+#include "builtins.h"
static rtx legitimize_dllimport_symbol (rtx, bool);
static rtx legitimize_pe_coff_extern_decl (rtx, bool);
@@ -2625,6 +2627,9 @@ ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch,
{ "-mxsave", OPTION_MASK_ISA_XSAVE },
{ "-mxsaveopt", OPTION_MASK_ISA_XSAVEOPT },
{ "-mprefetchwt1", OPTION_MASK_ISA_PREFETCHWT1 },
+ { "-mclflushopt", OPTION_MASK_ISA_CLFLUSHOPT },
+ { "-mxsavec", OPTION_MASK_ISA_XSAVEC },
+ { "-mxsaves", OPTION_MASK_ISA_XSAVES },
};
/* Flag options. */
@@ -3116,6 +3121,9 @@ ix86_option_override_internal (bool main_args_p,
#define PTA_AVX512CD (HOST_WIDE_INT_1 << 43)
#define PTA_SHA (HOST_WIDE_INT_1 << 45)
#define PTA_PREFETCHWT1 (HOST_WIDE_INT_1 << 46)
+#define PTA_CLFLUSHOPT (HOST_WIDE_INT_1 << 47)
+#define PTA_XSAVEC (HOST_WIDE_INT_1 << 48)
+#define PTA_XSAVES (HOST_WIDE_INT_1 << 49)
#define PTA_CORE2 \
(PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_SSSE3 \
@@ -3130,7 +3138,7 @@ ix86_option_override_internal (bool main_args_p,
(PTA_SANDYBRIDGE | PTA_FSGSBASE | PTA_RDRND | PTA_F16C)
#define PTA_HASWELL \
(PTA_IVYBRIDGE | PTA_AVX2 | PTA_BMI | PTA_BMI2 | PTA_LZCNT \
- | PTA_FMA | PTA_MOVBE | PTA_RTM | PTA_HLE)
+ | PTA_FMA | PTA_MOVBE | PTA_HLE)
#define PTA_BROADWELL \
(PTA_HASWELL | PTA_ADX | PTA_PRFCHW | PTA_RDSEED)
#define PTA_BONNELL \
@@ -3673,6 +3681,15 @@ ix86_option_override_internal (bool main_args_p,
if (processor_alias_table[i].flags & PTA_PREFETCHWT1
&& !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_PREFETCHWT1))
opts->x_ix86_isa_flags |= OPTION_MASK_ISA_PREFETCHWT1;
+ if (processor_alias_table[i].flags & PTA_CLFLUSHOPT
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_CLFLUSHOPT))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_CLFLUSHOPT;
+ if (processor_alias_table[i].flags & PTA_XSAVEC
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_XSAVEC))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_XSAVEC;
+ if (processor_alias_table[i].flags & PTA_XSAVES
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_XSAVES))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_XSAVES;
if (processor_alias_table[i].flags & (PTA_PREFETCH_SSE | PTA_SSE))
x86_prefetch_sse = true;
@@ -4556,6 +4573,9 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[],
IX86_ATTR_ISA ("xsave", OPT_mxsave),
IX86_ATTR_ISA ("xsaveopt", OPT_mxsaveopt),
IX86_ATTR_ISA ("prefetchwt1", OPT_mprefetchwt1),
+ IX86_ATTR_ISA ("clflushopt", OPT_mclflushopt),
+ IX86_ATTR_ISA ("xsavec", OPT_mxsavec),
+ IX86_ATTR_ISA ("xsaves", OPT_mxsaves),
/* enum options */
IX86_ATTR_ENUM ("fpmath=", OPT_mfpmath_),
@@ -5128,7 +5148,7 @@ x86_64_elf_unique_section (tree decl, int reloc)
{
const char *prefix = NULL;
/* We only need to use .gnu.linkonce if we don't have COMDAT groups. */
- bool one_only = DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP;
+ bool one_only = DECL_COMDAT_GROUP (decl) && !HAVE_COMDAT_GROUP;
switch (categorize_decl_for_section (decl, reloc))
{
@@ -9164,7 +9184,7 @@ ix86_code_end (void)
#endif
if (USE_HIDDEN_LINKONCE)
{
- DECL_COMDAT_GROUP (decl) = DECL_ASSEMBLER_NAME (decl);
+ cgraph_create_node (decl)->set_comdat_group (DECL_ASSEMBLER_NAME (decl));
targetm.asm_out.unique_section (decl, 0);
switch_to_section (get_named_section (decl, NULL, 0));
@@ -9486,20 +9506,30 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
frame->nregs = ix86_nsaved_regs ();
frame->nsseregs = ix86_nsaved_sseregs ();
- stack_alignment_needed = crtl->stack_alignment_needed / BITS_PER_UNIT;
- preferred_alignment = crtl->preferred_stack_boundary / BITS_PER_UNIT;
-
/* 64-bit MS ABI seem to require stack alignment to be always 16 except for
function prologues and leaf. */
- if ((TARGET_64BIT_MS_ABI && preferred_alignment < 16)
+ if ((TARGET_64BIT_MS_ABI && crtl->preferred_stack_boundary < 128)
&& (!crtl->is_leaf || cfun->calls_alloca != 0
|| ix86_current_function_calls_tls_descriptor))
{
- preferred_alignment = 16;
- stack_alignment_needed = 16;
crtl->preferred_stack_boundary = 128;
crtl->stack_alignment_needed = 128;
}
+ /* preferred_stack_boundary is never updated for call
+ expanded from tls descriptor. Update it here. We don't update it in
+ expand stage because according to the comments before
+ ix86_current_function_calls_tls_descriptor, tls calls may be optimized
+ away. */
+ else if (ix86_current_function_calls_tls_descriptor
+ && crtl->preferred_stack_boundary < PREFERRED_STACK_BOUNDARY)
+ {
+ crtl->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
+ if (crtl->stack_alignment_needed < PREFERRED_STACK_BOUNDARY)
+ crtl->stack_alignment_needed = PREFERRED_STACK_BOUNDARY;
+ }
+
+ stack_alignment_needed = crtl->stack_alignment_needed / BITS_PER_UNIT;
+ preferred_alignment = crtl->preferred_stack_boundary / BITS_PER_UNIT;
gcc_assert (!size || stack_alignment_needed);
gcc_assert (preferred_alignment >= STACK_BOUNDARY / BITS_PER_UNIT);
@@ -11815,7 +11845,7 @@ split_stack_prologue_scratch_regno (void)
if (regparm >= 2)
{
sorry ("-fsplit-stack does not support 2 register "
- " parameters for a nested function");
+ "parameters for a nested function");
return INVALID_REGNUM;
}
return DX_REG;
@@ -13644,7 +13674,7 @@ get_dllimport_decl (tree decl, bool beimport)
if (h)
return h->to;
- *loc = h = ggc_alloc_tree_map ();
+ *loc = h = ggc_alloc<tree_map> ();
h->hash = in.hash;
h->base.from = decl;
h->to = to = build_decl (DECL_SOURCE_LOCATION (decl),
@@ -16137,7 +16167,7 @@ ix86_i387_mode_needed (int entity, rtx insn)
/* Return mode that entity must be switched into
prior to the execution of insn. */
-int
+static int
ix86_mode_needed (int entity, rtx insn)
{
switch (entity)
@@ -16235,7 +16265,7 @@ ix86_avx_u128_mode_entry (void)
/* Return a mode that ENTITY is assumed to be
switched to at function entry. */
-int
+static int
ix86_mode_entry (int entity)
{
switch (entity)
@@ -16268,7 +16298,7 @@ ix86_avx_u128_mode_exit (void)
/* Return a mode that ENTITY is assumed to be
switched to at function exit. */
-int
+static int
ix86_mode_exit (int entity)
{
switch (entity)
@@ -16285,6 +16315,12 @@ ix86_mode_exit (int entity)
}
}
+static int
+ix86_mode_priority (int entity ATTRIBUTE_UNUSED, int n)
+{
+ return n;
+}
+
/* Output code to initialize control word copies used by trunc?f?i and
rounding patterns. CURRENT_MODE is set to current control word,
while NEW_MODE is set to new control word. */
@@ -16400,7 +16436,11 @@ ix86_avx_emit_vzeroupper (HARD_REG_SET regs_live)
/* Generate one or more insns to set ENTITY to MODE. */
-void
+/* Generate one or more insns to set ENTITY to MODE. HARD_REG_LIVE
+ is the set of hard registers live at the point where the insn(s)
+ are to be inserted. */
+
+static void
ix86_emit_mode_set (int entity, int mode, HARD_REG_SET regs_live)
{
switch (entity)
@@ -21502,7 +21542,7 @@ ix86_expand_vec_perm (rtx operands[])
t1 = gen_reg_rtx (V32QImode);
t2 = gen_reg_rtx (V32QImode);
t3 = gen_reg_rtx (V32QImode);
- vt2 = GEN_INT (128);
+ vt2 = GEN_INT (-128);
for (i = 0; i < 32; i++)
vec[i] = vt2;
vt = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, vec));
@@ -24146,8 +24186,13 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
align = MEM_ALIGN (dst) / BITS_PER_UNIT;
if (CONST_INT_P (count_exp))
- min_size = max_size = probable_max_size = count = expected_size
- = INTVAL (count_exp);
+ {
+ min_size = max_size = probable_max_size = count = expected_size
+ = INTVAL (count_exp);
+ /* When COUNT is 0, there is nothing to do. */
+ if (!count)
+ return true;
+ }
else
{
if (min_size_exp)
@@ -24156,7 +24201,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
max_size = INTVAL (max_size_exp);
if (probable_max_size_exp)
probable_max_size = INTVAL (probable_max_size_exp);
- if (CONST_INT_P (expected_size_exp) && count == 0)
+ if (CONST_INT_P (expected_size_exp))
expected_size = INTVAL (expected_size_exp);
}
@@ -24991,7 +25036,7 @@ ix86_init_machine_status (void)
{
struct machine_function *f;
- f = ggc_alloc_cleared_machine_function ();
+ f = ggc_cleared_alloc<machine_function> ();
f->use_fast_prologue_epilogue_nregs = -1;
f->call_abi = ix86_abi;
@@ -25015,7 +25060,7 @@ assign_386_stack_local (enum machine_mode mode, enum ix86_stack_slot n)
if (s->mode == mode && s->n == n)
return validize_mem (copy_rtx (s->rtl));
- s = ggc_alloc_stack_local_entry ();
+ s = ggc_alloc<stack_local_entry> ();
s->n = n;
s->mode = mode;
s->rtl = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
@@ -26228,13 +26273,17 @@ ix86_dependencies_evaluation_hook (rtx head, rtx tail)
{
edge e;
edge_iterator ei;
- /* Assume that region is SCC, i.e. all immediate predecessors
- of non-head block are in the same region. */
+
+ /* Regions are SCCs with the exception of selective
+ scheduling with pipelining of outer blocks enabled.
+ So also check that immediate predecessors of a non-head
+ block are in the same region. */
FOR_EACH_EDGE (e, ei, bb->preds)
{
/* Avoid creating of loop-carried dependencies through
- using topological odering in region. */
- if (BLOCK_TO_BB (bb->index) > BLOCK_TO_BB (e->src->index))
+ using topological ordering in the region. */
+ if (rgn == CONTAINING_RGN (e->src->index)
+ && BLOCK_TO_BB (bb->index) > BLOCK_TO_BB (e->src->index))
add_dependee_for_func_arg (first_arg, e->src);
}
}
@@ -26335,7 +26384,7 @@ static int min_insn_size (rtx);
static void
core2i7_first_cycle_multipass_filter_ready_try
(const_ix86_first_cycle_multipass_data_t data,
- char *ready_try, int n_ready, bool first_cycle_insn_p)
+ signed char *ready_try, int n_ready, bool first_cycle_insn_p)
{
while (n_ready--)
{
@@ -26367,7 +26416,8 @@ core2i7_first_cycle_multipass_filter_ready_try
/* Prepare for a new round of multipass lookahead scheduling. */
static void
-core2i7_first_cycle_multipass_begin (void *_data, char *ready_try, int n_ready,
+core2i7_first_cycle_multipass_begin (void *_data,
+ signed char *ready_try, int n_ready,
bool first_cycle_insn_p)
{
ix86_first_cycle_multipass_data_t data
@@ -26388,7 +26438,8 @@ core2i7_first_cycle_multipass_begin (void *_data, char *ready_try, int n_ready,
/* INSN is being issued in current solution. Account for its impact on
the decoder model. */
static void
-core2i7_first_cycle_multipass_issue (void *_data, char *ready_try, int n_ready,
+core2i7_first_cycle_multipass_issue (void *_data,
+ signed char *ready_try, int n_ready,
rtx insn, const void *_prev_data)
{
ix86_first_cycle_multipass_data_t data
@@ -26426,7 +26477,7 @@ core2i7_first_cycle_multipass_issue (void *_data, char *ready_try, int n_ready,
/* Revert the effect on ready_try. */
static void
core2i7_first_cycle_multipass_backtrack (const void *_data,
- char *ready_try,
+ signed char *ready_try,
int n_ready ATTRIBUTE_UNUSED)
{
const_ix86_first_cycle_multipass_data_t data
@@ -27281,6 +27332,14 @@ enum ix86_builtins
IX86_BUILTIN_XSAVEOPT,
IX86_BUILTIN_XSAVEOPT64,
+ IX86_BUILTIN_XSAVEC,
+ IX86_BUILTIN_XSAVEC64,
+
+ IX86_BUILTIN_XSAVES,
+ IX86_BUILTIN_XRSTORS,
+ IX86_BUILTIN_XSAVES64,
+ IX86_BUILTIN_XRSTORS64,
+
/* 3DNow! Original */
IX86_BUILTIN_FEMMS,
IX86_BUILTIN_PAVGUSB,
@@ -28476,6 +28535,9 @@ enum ix86_builtins
IX86_BUILTIN_SHA256MSG2,
IX86_BUILTIN_SHA256RNDS2,
+ /* CLFLUSHOPT instructions. */
+ IX86_BUILTIN_CLFLUSHOPT,
+
/* TFmode support builtins. */
IX86_BUILTIN_INFQ,
IX86_BUILTIN_HUGE_VALQ,
@@ -28935,18 +28997,24 @@ static const struct builtin_description bdesc_special_args[] =
/* 3DNow! */
{ OPTION_MASK_ISA_3DNOW, CODE_FOR_mmx_femms, "__builtin_ia32_femms", IX86_BUILTIN_FEMMS, UNKNOWN, (int) VOID_FTYPE_VOID },
- /* FXSR, XSAVE and XSAVEOPT */
+ /* FXSR, XSAVE, XSAVEOPT, XSAVEC and XSAVES. */
{ OPTION_MASK_ISA_FXSR, CODE_FOR_nothing, "__builtin_ia32_fxsave", IX86_BUILTIN_FXSAVE, UNKNOWN, (int) VOID_FTYPE_PVOID },
{ OPTION_MASK_ISA_FXSR, CODE_FOR_nothing, "__builtin_ia32_fxrstor", IX86_BUILTIN_FXRSTOR, UNKNOWN, (int) VOID_FTYPE_PVOID },
{ OPTION_MASK_ISA_XSAVE, CODE_FOR_nothing, "__builtin_ia32_xsave", IX86_BUILTIN_XSAVE, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
{ OPTION_MASK_ISA_XSAVE, CODE_FOR_nothing, "__builtin_ia32_xrstor", IX86_BUILTIN_XRSTOR, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
{ OPTION_MASK_ISA_XSAVEOPT, CODE_FOR_nothing, "__builtin_ia32_xsaveopt", IX86_BUILTIN_XSAVEOPT, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
+ { OPTION_MASK_ISA_XSAVES, CODE_FOR_nothing, "__builtin_ia32_xsaves", IX86_BUILTIN_XSAVES, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
+ { OPTION_MASK_ISA_XSAVES, CODE_FOR_nothing, "__builtin_ia32_xrstors", IX86_BUILTIN_XRSTORS, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
+ { OPTION_MASK_ISA_XSAVEC, CODE_FOR_nothing, "__builtin_ia32_xsavec", IX86_BUILTIN_XSAVEC, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
{ OPTION_MASK_ISA_FXSR | OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_fxsave64", IX86_BUILTIN_FXSAVE64, UNKNOWN, (int) VOID_FTYPE_PVOID },
{ OPTION_MASK_ISA_FXSR | OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_fxrstor64", IX86_BUILTIN_FXRSTOR64, UNKNOWN, (int) VOID_FTYPE_PVOID },
{ OPTION_MASK_ISA_XSAVE | OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_xsave64", IX86_BUILTIN_XSAVE64, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
{ OPTION_MASK_ISA_XSAVE | OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_xrstor64", IX86_BUILTIN_XRSTOR64, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
{ OPTION_MASK_ISA_XSAVEOPT | OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_xsaveopt64", IX86_BUILTIN_XSAVEOPT64, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
+ { OPTION_MASK_ISA_XSAVES | OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_xsaves64", IX86_BUILTIN_XSAVES64, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
+ { OPTION_MASK_ISA_XSAVES | OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_xrstors64", IX86_BUILTIN_XRSTORS64, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
+ { OPTION_MASK_ISA_XSAVEC | OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_xsavec64", IX86_BUILTIN_XSAVEC64, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 },
/* SSE */
{ OPTION_MASK_ISA_SSE, CODE_FOR_sse_storeups, "__builtin_ia32_storeups", IX86_BUILTIN_STOREUPS, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V4SF },
@@ -31124,6 +31192,9 @@ ix86_init_mmx_sse_builtins (void)
def_builtin (OPTION_MASK_ISA_64BIT, "__builtin_ia32_writeeflags_u64",
VOID_FTYPE_UINT64, IX86_BUILTIN_WRITE_FLAGS);
+ /* CLFLUSHOPT. */
+ def_builtin (OPTION_MASK_ISA_CLFLUSHOPT, "__builtin_ia32_clflushopt",
+ VOID_FTYPE_PCVOID, IX86_BUILTIN_CLFLUSHOPT);
/* Add FMA4 multi-arg argument instructions */
for (i = 0, d = bdesc_multi_arg; i < ARRAY_SIZE (bdesc_multi_arg); i++, d++)
@@ -35056,6 +35127,16 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
emit_insn (gen_sse2_clflush (op0));
return 0;
+ case IX86_BUILTIN_CLFLUSHOPT:
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ op0 = expand_normal (arg0);
+ icode = CODE_FOR_clflushopt;
+ if (!insn_data[icode].operand[0].predicate (op0, Pmode))
+ op0 = ix86_zero_extend_to_Pmode (op0);
+
+ emit_insn (gen_clflushopt (op0));
+ return 0;
+
case IX86_BUILTIN_MONITOR:
arg0 = CALL_EXPR_ARG (exp, 0);
arg1 = CALL_EXPR_ARG (exp, 1);
@@ -35247,6 +35328,12 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
case IX86_BUILTIN_XRSTOR64:
case IX86_BUILTIN_XSAVEOPT:
case IX86_BUILTIN_XSAVEOPT64:
+ case IX86_BUILTIN_XSAVES:
+ case IX86_BUILTIN_XRSTORS:
+ case IX86_BUILTIN_XSAVES64:
+ case IX86_BUILTIN_XRSTORS64:
+ case IX86_BUILTIN_XSAVEC:
+ case IX86_BUILTIN_XSAVEC64:
arg0 = CALL_EXPR_ARG (exp, 0);
arg1 = CALL_EXPR_ARG (exp, 1);
op0 = expand_normal (arg0);
@@ -35285,6 +35372,24 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
case IX86_BUILTIN_XSAVEOPT64:
icode = CODE_FOR_xsaveopt64;
break;
+ case IX86_BUILTIN_XSAVES:
+ icode = CODE_FOR_xsaves_rex64;
+ break;
+ case IX86_BUILTIN_XRSTORS:
+ icode = CODE_FOR_xrstors_rex64;
+ break;
+ case IX86_BUILTIN_XSAVES64:
+ icode = CODE_FOR_xsaves64;
+ break;
+ case IX86_BUILTIN_XRSTORS64:
+ icode = CODE_FOR_xrstors64;
+ break;
+ case IX86_BUILTIN_XSAVEC:
+ icode = CODE_FOR_xsavec_rex64;
+ break;
+ case IX86_BUILTIN_XSAVEC64:
+ icode = CODE_FOR_xsavec64;
+ break;
default:
gcc_unreachable ();
}
@@ -35306,6 +35411,15 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
case IX86_BUILTIN_XSAVEOPT:
icode = CODE_FOR_xsaveopt;
break;
+ case IX86_BUILTIN_XSAVES:
+ icode = CODE_FOR_xsaves;
+ break;
+ case IX86_BUILTIN_XRSTORS:
+ icode = CODE_FOR_xrstors;
+ break;
+ case IX86_BUILTIN_XSAVEC:
+ icode = CODE_FOR_xsavec;
+ break;
default:
gcc_unreachable ();
}
@@ -37790,10 +37904,10 @@ ix86_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
else if (TARGET_64BIT && !x86_64_zext_immediate_operand (x, VOIDmode))
*total = 2;
else if (flag_pic && SYMBOLIC_CONST (x)
- && (!TARGET_64BIT
- || (!GET_CODE (x) != LABEL_REF
- && (GET_CODE (x) != SYMBOL_REF
- || !SYMBOL_REF_LOCAL_P (x)))))
+ && !(TARGET_64BIT
+ && (GET_CODE (x) == LABEL_REF
+ || (GET_CODE (x) == SYMBOL_REF
+ && SYMBOL_REF_LOCAL_P (x)))))
*total = 1;
else
*total = 0;
@@ -38780,7 +38894,16 @@ x86_output_mi_thunk (FILE *file,
For our purposes here, we can get away with (ab)using a jump pattern,
because we're going to do no optimization. */
if (MEM_P (fnaddr))
- emit_jump_insn (gen_indirect_jump (fnaddr));
+ {
+ if (sibcall_insn_operand (fnaddr, word_mode))
+ {
+ tmp = gen_rtx_CALL (VOIDmode, fnaddr, const0_rtx);
+ tmp = emit_call_insn (tmp);
+ SIBLING_CALL_P (tmp) = 1;
+ }
+ else
+ emit_jump_insn (gen_indirect_jump (fnaddr));
+ }
else
{
if (ix86_cmodel == CM_LARGE_PIC && SYMBOLIC_CONST (fnaddr))
@@ -47141,6 +47264,27 @@ ix86_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
#define TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P \
ix86_float_exceptions_rounding_supported_p
+#undef TARGET_MODE_EMIT
+#define TARGET_MODE_EMIT ix86_emit_mode_set
+
+#undef TARGET_MODE_NEEDED
+#define TARGET_MODE_NEEDED ix86_mode_needed
+
+#undef TARGET_MODE_AFTER
+#define TARGET_MODE_AFTER ix86_mode_after
+
+#undef TARGET_MODE_ENTRY
+#define TARGET_MODE_ENTRY ix86_mode_entry
+
+#undef TARGET_MODE_EXIT
+#define TARGET_MODE_EXIT ix86_mode_exit
+
+#undef TARGET_MODE_PRIORITY
+#define TARGET_MODE_PRIORITY ix86_mode_priority
+
+#undef TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS
+#define TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS true
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-i386.h"
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 1a884d86c35..a4009d3a83b 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -104,6 +104,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define TARGET_AES_P(x) TARGET_ISA_AES_P(x)
#define TARGET_SHA TARGET_ISA_SHA
#define TARGET_SHA_P(x) TARGET_ISA_SHA_P(x)
+#define TARGET_CLFLUSHOPT TARGET_ISA_CLFLUSHOPT
+#define TARGET_CLFLUSHOPT_P(x) TARGET_ISA_CLFLUSHOPT_P(x)
+#define TARGET_XSAVEC TARGET_ISA_XSAVEC
+#define TARGET_XSAVEC_P(x) TARGET_ISA_XSAVEC_P(x)
+#define TARGET_XSAVES TARGET_ISA_XSAVES
+#define TARGET_XSAVES_P(x) TARGET_ISA_XSAVES_P(x)
#define TARGET_PCLMUL TARGET_ISA_PCLMUL
#define TARGET_PCLMUL_P(x) TARGET_ISA_PCLMUL_P(x)
#define TARGET_CMPXCHG16B TARGET_ISA_CX16
@@ -2312,43 +2318,6 @@ enum avx_u128_state
#define NUM_MODES_FOR_MODE_SWITCHING \
{ AVX_U128_ANY, I387_CW_ANY, I387_CW_ANY, I387_CW_ANY, I387_CW_ANY }
-/* ENTITY is an integer specifying a mode-switched entity. If
- `OPTIMIZE_MODE_SWITCHING' is defined, you must define this macro to
- return an integer value not larger than the corresponding element
- in `NUM_MODES_FOR_MODE_SWITCHING', to denote the mode that ENTITY
- must be switched into prior to the execution of INSN. */
-
-#define MODE_NEEDED(ENTITY, I) ix86_mode_needed ((ENTITY), (I))
-
-/* If this macro is defined, it is evaluated for every INSN during
- mode switching. It determines the mode that an insn results in (if
- different from the incoming mode). */
-
-#define MODE_AFTER(ENTITY, MODE, I) ix86_mode_after ((ENTITY), (MODE), (I))
-
-/* If this macro is defined, it is evaluated for every ENTITY that
- needs mode switching. It should evaluate to an integer, which is
- a mode that ENTITY is assumed to be switched to at function entry. */
-
-#define MODE_ENTRY(ENTITY) ix86_mode_entry (ENTITY)
-
-/* If this macro is defined, it is evaluated for every ENTITY that
- needs mode switching. It should evaluate to an integer, which is
- a mode that ENTITY is assumed to be switched to at function exit. */
-
-#define MODE_EXIT(ENTITY) ix86_mode_exit (ENTITY)
-
-/* This macro specifies the order in which modes for ENTITY are
- processed. 0 is the highest priority. */
-
-#define MODE_PRIORITY_TO_MODE(ENTITY, N) (N)
-
-/* Generate one or more insns to set ENTITY to MODE. HARD_REG_LIVE
- is the set of hard registers live at the point where the insn(s)
- are to be inserted. */
-
-#define EMIT_MODE_SET(ENTITY, MODE, HARD_REGS_LIVE) \
- ix86_emit_mode_set ((ENTITY), (MODE), (HARD_REGS_LIVE))
/* Avoid renaming of stack registers, as doing so in combination with
scheduling just increases amount of live registers at time and in
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index fde0a93e68f..f7716a82381 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -213,6 +213,12 @@
UNSPECV_XRSTOR64
UNSPECV_XSAVEOPT
UNSPECV_XSAVEOPT64
+ UNSPECV_XSAVES
+ UNSPECV_XRSTORS
+ UNSPECV_XSAVES64
+ UNSPECV_XRSTORS64
+ UNSPECV_XSAVEC
+ UNSPECV_XSAVEC64
;; For atomic compound assignments.
UNSPECV_FNSTENV
@@ -233,6 +239,9 @@
UNSPECV_XTEST
UNSPECV_NLGR
+
+ ;; For CLFLUSHOPT support
+ UNSPECV_CLFLUSHOPT
])
;; Constants to represent rounding modes in the ROUND instruction
@@ -11173,7 +11182,7 @@
})
(define_insn "*indirect_jump"
- [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))]
+ [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))]
""
"jmp\t%A0"
[(set_attr "type" "ibr")
@@ -11221,7 +11230,7 @@
})
(define_insn "*tablejump_1"
- [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))
+ [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))
(use (label_ref (match_operand 1)))]
""
"jmp\t%A0"
@@ -11351,7 +11360,7 @@
})
(define_insn "*call"
- [(call (mem:QI (match_operand:W 0 "call_insn_operand" "<c>zw"))
+ [(call (mem:QI (match_operand:W 0 "call_insn_operand" "<c>BwBz"))
(match_operand 1))]
"!SIBLING_CALL_P (insn)"
"* return ix86_output_call_insn (insn, operands[0]);"
@@ -11359,7 +11368,7 @@
(define_insn "*call_rex64_ms_sysv"
[(match_parallel 2 "call_rex64_ms_sysv_operation"
- [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rzw"))
+ [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rBwBz"))
(match_operand 1))
(unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)])]
"TARGET_64BIT && !SIBLING_CALL_P (insn)"
@@ -11367,7 +11376,7 @@
[(set_attr "type" "call")])
(define_insn "*sibcall"
- [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "Uz"))
+ [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "UBsBz"))
(match_operand 1))]
"SIBLING_CALL_P (insn)"
"* return ix86_output_call_insn (insn, operands[0]);"
@@ -11387,7 +11396,7 @@
})
(define_insn "*call_pop"
- [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lzm"))
+ [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lmBz"))
(match_operand 1))
(set (reg:SI SP_REG)
(plus:SI (reg:SI SP_REG)
@@ -11397,7 +11406,7 @@
[(set_attr "type" "call")])
(define_insn "*sibcall_pop"
- [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "Uz"))
+ [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "UBsBz"))
(match_operand 1))
(set (reg:SI SP_REG)
(plus:SI (reg:SI SP_REG)
@@ -11434,7 +11443,7 @@
(define_insn "*call_value"
[(set (match_operand 0)
- (call (mem:QI (match_operand:W 1 "call_insn_operand" "<c>zw"))
+ (call (mem:QI (match_operand:W 1 "call_insn_operand" "<c>BwBz"))
(match_operand 2)))]
"!SIBLING_CALL_P (insn)"
"* return ix86_output_call_insn (insn, operands[1]);"
@@ -11442,7 +11451,7 @@
(define_insn "*sibcall_value"
[(set (match_operand 0)
- (call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "Uz"))
+ (call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "UBsBz"))
(match_operand 2)))]
"SIBLING_CALL_P (insn)"
"* return ix86_output_call_insn (insn, operands[1]);"
@@ -11451,7 +11460,7 @@
(define_insn "*call_value_rex64_ms_sysv"
[(match_parallel 3 "call_rex64_ms_sysv_operation"
[(set (match_operand 0)
- (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rzw"))
+ (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rBwBz"))
(match_operand 2)))
(unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)])]
"TARGET_64BIT && !SIBLING_CALL_P (insn)"
@@ -11474,7 +11483,7 @@
(define_insn "*call_value_pop"
[(set (match_operand 0)
- (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lzm"))
+ (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lmBz"))
(match_operand 2)))
(set (reg:SI SP_REG)
(plus:SI (reg:SI SP_REG)
@@ -11485,7 +11494,7 @@
(define_insn "*sibcall_value_pop"
[(set (match_operand 0)
- (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "Uz"))
+ (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "UBsBz"))
(match_operand 2)))
(set (reg:SI SP_REG)
(plus:SI (reg:SI SP_REG)
@@ -12530,7 +12539,8 @@
(unspec:SI
[(match_operand:SI 1 "register_operand" "b")
(match_operand 2 "tls_symbolic_operand")
- (match_operand 3 "constant_call_address_operand" "z")]
+ (match_operand 3 "constant_call_address_operand" "Bz")
+ (reg:SI SP_REG)]
UNSPEC_TLS_GD))
(clobber (match_scratch:SI 4 "=d"))
(clobber (match_scratch:SI 5 "=c"))
@@ -12555,16 +12565,19 @@
[(set (match_operand:SI 0 "register_operand")
(unspec:SI [(match_operand:SI 2 "register_operand")
(match_operand 1 "tls_symbolic_operand")
- (match_operand 3 "constant_call_address_operand")]
+ (match_operand 3 "constant_call_address_operand")
+ (reg:SI SP_REG)]
UNSPEC_TLS_GD))
(clobber (match_scratch:SI 4))
(clobber (match_scratch:SI 5))
- (clobber (reg:CC FLAGS_REG))])])
+ (clobber (reg:CC FLAGS_REG))])]
+ ""
+ "ix86_tls_descriptor_calls_expanded_in_cfun = true;")
(define_insn "*tls_global_dynamic_64_<mode>"
[(set (match_operand:P 0 "register_operand" "=a")
(call:P
- (mem:QI (match_operand 2 "constant_call_address_operand" "z"))
+ (mem:QI (match_operand 2 "constant_call_address_operand" "Bz"))
(match_operand 3)))
(unspec:P [(match_operand 1 "tls_symbolic_operand")]
UNSPEC_TLS_GD)]
@@ -12614,13 +12627,15 @@
(const_int 0)))
(unspec:P [(match_operand 1 "tls_symbolic_operand")]
UNSPEC_TLS_GD)])]
- "TARGET_64BIT")
+ "TARGET_64BIT"
+ "ix86_tls_descriptor_calls_expanded_in_cfun = true;")
(define_insn "*tls_local_dynamic_base_32_gnu"
[(set (match_operand:SI 0 "register_operand" "=a")
(unspec:SI
[(match_operand:SI 1 "register_operand" "b")
- (match_operand 2 "constant_call_address_operand" "z")]
+ (match_operand 2 "constant_call_address_operand" "Bz")
+ (reg:SI SP_REG)]
UNSPEC_TLS_LD_BASE))
(clobber (match_scratch:SI 3 "=d"))
(clobber (match_scratch:SI 4 "=c"))
@@ -12646,16 +12661,19 @@
[(set (match_operand:SI 0 "register_operand")
(unspec:SI
[(match_operand:SI 1 "register_operand")
- (match_operand 2 "constant_call_address_operand")]
+ (match_operand 2 "constant_call_address_operand")
+ (reg:SI SP_REG)]
UNSPEC_TLS_LD_BASE))
(clobber (match_scratch:SI 3))
(clobber (match_scratch:SI 4))
- (clobber (reg:CC FLAGS_REG))])])
+ (clobber (reg:CC FLAGS_REG))])]
+ ""
+ "ix86_tls_descriptor_calls_expanded_in_cfun = true;")
(define_insn "*tls_local_dynamic_base_64_<mode>"
[(set (match_operand:P 0 "register_operand" "=a")
(call:P
- (mem:QI (match_operand 1 "constant_call_address_operand" "z"))
+ (mem:QI (match_operand 1 "constant_call_address_operand" "Bz"))
(match_operand 2)))
(unspec:P [(const_int 0)] UNSPEC_TLS_LD_BASE)]
"TARGET_64BIT"
@@ -12697,7 +12715,8 @@
(mem:QI (match_operand 1))
(const_int 0)))
(unspec:P [(const_int 0)] UNSPEC_TLS_LD_BASE)])]
- "TARGET_64BIT")
+ "TARGET_64BIT"
+ "ix86_tls_descriptor_calls_expanded_in_cfun = true;")
;; Local dynamic of a single variable is a lose. Show combine how
;; to convert that back to global dynamic.
@@ -12706,7 +12725,8 @@
[(set (match_operand:SI 0 "register_operand" "=a")
(plus:SI
(unspec:SI [(match_operand:SI 1 "register_operand" "b")
- (match_operand 2 "constant_call_address_operand" "z")]
+ (match_operand 2 "constant_call_address_operand" "Bz")
+ (reg:SI SP_REG)]
UNSPEC_TLS_LD_BASE)
(const:SI (unspec:SI
[(match_operand 3 "tls_symbolic_operand")]
@@ -12719,7 +12739,8 @@
""
[(parallel
[(set (match_dup 0)
- (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 2)]
+ (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 2)
+ (reg:SI SP_REG)]
UNSPEC_TLS_GD))
(clobber (match_dup 4))
(clobber (match_dup 5))
@@ -17786,17 +17807,39 @@
(define_int_iterator ANY_XSAVE
[UNSPECV_XSAVE
- (UNSPECV_XSAVEOPT "TARGET_XSAVEOPT")])
+ (UNSPECV_XSAVEOPT "TARGET_XSAVEOPT")
+ (UNSPECV_XSAVEC "TARGET_XSAVEC")
+ (UNSPECV_XSAVES "TARGET_XSAVES")])
(define_int_iterator ANY_XSAVE64
[UNSPECV_XSAVE64
- (UNSPECV_XSAVEOPT64 "TARGET_XSAVEOPT")])
+ (UNSPECV_XSAVEOPT64 "TARGET_XSAVEOPT")
+ (UNSPECV_XSAVEC64 "TARGET_XSAVEC")
+ (UNSPECV_XSAVES64 "TARGET_XSAVES")])
(define_int_attr xsave
[(UNSPECV_XSAVE "xsave")
(UNSPECV_XSAVE64 "xsave64")
(UNSPECV_XSAVEOPT "xsaveopt")
- (UNSPECV_XSAVEOPT64 "xsaveopt64")])
+ (UNSPECV_XSAVEOPT64 "xsaveopt64")
+ (UNSPECV_XSAVEC "xsavec")
+ (UNSPECV_XSAVEC64 "xsavec64")
+ (UNSPECV_XSAVES "xsaves")
+ (UNSPECV_XSAVES64 "xsaves64")])
+
+(define_int_iterator ANY_XRSTOR
+ [UNSPECV_XRSTOR
+ (UNSPECV_XRSTORS "TARGET_XSAVES")])
+
+(define_int_iterator ANY_XRSTOR64
+ [UNSPECV_XRSTOR64
+ (UNSPECV_XRSTORS64 "TARGET_XSAVES")])
+
+(define_int_attr xrstor
+ [(UNSPECV_XRSTOR "xrstor")
+ (UNSPECV_XRSTOR64 "xrstor")
+ (UNSPECV_XRSTORS "xrstors")
+ (UNSPECV_XRSTORS64 "xrstors")])
(define_insn "<xsave>"
[(set (match_operand:BLK 0 "memory_operand" "=m")
@@ -17836,39 +17879,39 @@
(set (attr "length")
(symbol_ref "ix86_attr_length_address_default (insn) + 4"))])
-(define_insn "xrstor"
+(define_insn "<xrstor>"
[(unspec_volatile:BLK
[(match_operand:BLK 0 "memory_operand" "m")
(match_operand:DI 1 "register_operand" "A")]
- UNSPECV_XRSTOR)]
+ ANY_XRSTOR)]
"!TARGET_64BIT && TARGET_XSAVE"
- "xrstor\t%0"
+ "<xrstor>\t%0"
[(set_attr "type" "other")
(set_attr "memory" "load")
(set (attr "length")
(symbol_ref "ix86_attr_length_address_default (insn) + 3"))])
-(define_insn "xrstor_rex64"
+(define_insn "<xrstor>_rex64"
[(unspec_volatile:BLK
[(match_operand:BLK 0 "memory_operand" "m")
(match_operand:SI 1 "register_operand" "a")
(match_operand:SI 2 "register_operand" "d")]
- UNSPECV_XRSTOR)]
+ ANY_XRSTOR)]
"TARGET_64BIT && TARGET_XSAVE"
- "xrstor\t%0"
+ "<xrstor>\t%0"
[(set_attr "type" "other")
(set_attr "memory" "load")
(set (attr "length")
(symbol_ref "ix86_attr_length_address_default (insn) + 3"))])
-(define_insn "xrstor64"
+(define_insn "<xrstor>64"
[(unspec_volatile:BLK
[(match_operand:BLK 0 "memory_operand" "m")
(match_operand:SI 1 "register_operand" "a")
(match_operand:SI 2 "register_operand" "d")]
- UNSPECV_XRSTOR64)]
+ ANY_XRSTOR64)]
"TARGET_64BIT && TARGET_XSAVE"
- "xrstor64\t%0"
+ "<xrstor>64\t%0"
[(set_attr "type" "other")
(set_attr "memory" "load")
(set (attr "length")
@@ -18166,6 +18209,15 @@
[(set_attr "type" "other")
(set_attr "length" "3")])
+(define_insn "clflushopt"
+ [(unspec_volatile [(match_operand 0 "address_operand" "p")]
+ UNSPECV_CLFLUSHOPT)]
+ "TARGET_CLFLUSHOPT"
+ "clflushopt\t%a0"
+ [(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "fence")
+ (set_attr "memory" "unknown")])
+
(include "mmx.md")
(include "sse.md")
(include "sync.md")
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 0f463a23820..dc1302c5a01 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -697,6 +697,10 @@ madx
Target Report Mask(ISA_ADX) Var(ix86_isa_flags) Save
Support flag-preserving add-carry instructions
+mclflushopt
+Target Report Mask(ISA_CLFLUSHOPT) Var(ix86_isa_flags) Save
+Support CLFLUSHOPT instructions
+
mfxsr
Target Report Mask(ISA_FXSR) Var(ix86_isa_flags) Save
Support FXSAVE and FXRSTOR instructions
@@ -709,6 +713,14 @@ mxsaveopt
Target Report Mask(ISA_XSAVEOPT) Var(ix86_isa_flags) Save
Support XSAVEOPT instruction
+mxsavec
+Target Report Mask(ISA_XSAVEC) Var(ix86_isa_flags) Save
+Support XSAVEC instructions
+
+mxsaves
+Target Report Mask(ISA_XSAVES) Var(ix86_isa_flags) Save
+Support XSAVES and XRSTORS instructions
+
mtbm
Target Report Mask(ISA_TBM) Var(ix86_isa_flags) Save
Support TBM built-in functions and code generation
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 2ef1384246e..efc3a090d08 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -71,6 +71,12 @@
return ANY_QI_REG_P (op);
})
+(define_predicate "sibcall_memory_operand"
+ (match_operand 0 "memory_operand")
+{
+ return CONSTANT_P (XEXP (op, 0));
+})
+
;; Match an SI or HImode register for a zero_extract.
(define_special_predicate "ext_register_operand"
(match_operand 0 "register_operand")
@@ -600,7 +606,9 @@
(define_special_predicate "sibcall_insn_operand"
(ior (match_test "constant_call_address_operand
(op, mode == VOIDmode ? mode : Pmode)")
- (match_operand 0 "register_no_elim_operand")))
+ (match_operand 0 "register_no_elim_operand")
+ (and (not (match_test "TARGET_X32"))
+ (match_operand 0 "sibcall_memory_operand"))))
;; Return true if OP is a call from MS ABI to SYSV ABI function.
(define_predicate "call_rex64_ms_sysv_operation"
diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c
index bcfd48a03dc..de607179715 100644
--- a/gcc/config/i386/winnt.c
+++ b/gcc/config/i386/winnt.c
@@ -49,6 +49,8 @@ along with GCC; see the file COPYING3. If not see
#include "is-a.h"
#include "gimple.h"
#include "lto-streamer.h"
+#include "lto-section-names.h"
+#include "builtins.h"
/* i386/PE specific attribute support.
@@ -649,7 +651,7 @@ i386_pe_record_external_function (tree decl, const char *name)
{
struct extern_list *p;
- p = ggc_alloc_extern_list ();
+ p = ggc_alloc<extern_list> ();
p->next = extern_head;
p->decl = decl;
p->name = name;
@@ -700,7 +702,7 @@ i386_pe_maybe_record_exported_symbol (tree decl, const char *name, int is_data)
gcc_assert (TREE_PUBLIC (decl));
- p = ggc_alloc_export_list ();
+ p = ggc_alloc<export_list> ();
p->next = export_head;
p->name = name;
p->is_data = is_data;
@@ -724,7 +726,7 @@ i386_pe_record_stub (const char *name)
p = p->next;
}
- p = ggc_alloc_stub_list ();
+ p = ggc_alloc<stub_list> ();
p->next = stub_head;
p->name = name;
stub_head = p;
diff --git a/gcc/config/i386/x86intrin.h b/gcc/config/i386/x86intrin.h
index 80e9e6f33de..c84ab88c8c0 100644
--- a/gcc/config/i386/x86intrin.h
+++ b/gcc/config/i386/x86intrin.h
@@ -75,4 +75,10 @@
#include <adxintrin.h>
+#include <clflushoptintrin.h>
+
+#include <xsavesintrin.h>
+
+#include <xsavecintrin.h>
+
#endif /* _X86INTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/xmmintrin.h b/gcc/config/i386/xmmintrin.h
index a3824e73fc2..ec572348c38 100644
--- a/gcc/config/i386/xmmintrin.h
+++ b/gcc/config/i386/xmmintrin.h
@@ -1231,15 +1231,6 @@ _mm_sfence (void)
__builtin_ia32_sfence ();
}
-/* The execution of the next instruction is delayed by an implementation
- specific amount of time. The instruction does not modify the
- architectural state. */
-extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_mm_pause (void)
-{
- __builtin_ia32_pause ();
-}
-
/* Transpose the 4x4 matrix composed of row[0-3]. */
#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3) \
do { \
@@ -1262,4 +1253,15 @@ do { \
#pragma GCC pop_options
#endif /* __DISABLE_SSE__ */
+/* The execution of the next instruction is delayed by an implementation
+ specific amount of time. The instruction does not modify the
+ architectural state. This is after the pop_options pragma because
+ it does not require SSE support in the processor--the encoding is a
+ nop on processors that do not support it. */
+extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_pause (void)
+{
+ __builtin_ia32_pause ();
+}
+
#endif /* _XMMINTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/xsavecintrin.h b/gcc/config/i386/xsavecintrin.h
new file mode 100644
index 00000000000..99fadd5988e
--- /dev/null
+++ b/gcc/config/i386/xsavecintrin.h
@@ -0,0 +1,58 @@
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#if !defined _X86INTRIN_H_INCLUDED
+# error "Never use <xsavecintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef _XSAVECINTRIN_H_INCLUDED
+#define _XSAVECINTRIN_H_INCLUDED
+
+#ifndef __XSAVEC__
+#pragma GCC push_options
+#pragma GCC target("xsavec")
+#define __DISABLE_XSAVEC__
+#endif /* __XSAVEC__ */
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_xsavec (void *__P, long long __M)
+{
+ __builtin_ia32_xsavec (__P, __M);
+}
+
+#ifdef __x86_64__
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_xsavec64 (void *__P, long long __M)
+{
+ __builtin_ia32_xsavec64 (__P, __M);
+}
+#endif
+
+#ifdef __DISABLE_XSAVEC__
+#undef __DISABLE_XSAVEC__
+#pragma GCC pop_options
+#endif /* __DISABLE_XSAVEC__ */
+
+#endif /* _XSAVECINTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/xsavesintrin.h b/gcc/config/i386/xsavesintrin.h
new file mode 100644
index 00000000000..a08a81ae82d
--- /dev/null
+++ b/gcc/config/i386/xsavesintrin.h
@@ -0,0 +1,72 @@
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#if !defined _X86INTRIN_H_INCLUDED
+# error "Never use <xsavesintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef _XSAVESINTRIN_H_INCLUDED
+#define _XSAVESINTRIN_H_INCLUDED
+
+#ifndef __XSAVES__
+#pragma GCC push_options
+#pragma GCC target("xsaves")
+#define __DISABLE_XSAVES__
+#endif /* __XSAVES__ */
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_xsaves (void *__P, long long __M)
+{
+ __builtin_ia32_xsaves (__P, __M);
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_xrstors (void *__P, long long __M)
+{
+ __builtin_ia32_xrstors (__P, __M);
+}
+
+#ifdef __x86_64__
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_xrstors64 (void *__P, long long __M)
+{
+ __builtin_ia32_xrstors64 (__P, __M);
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_xsaves64 (void *__P, long long __M)
+{
+ __builtin_ia32_xsaves64 (__P, __M);
+}
+#endif
+
+#ifdef __DISABLE_XSAVES__
+#undef __DISABLE_XSAVES__
+#pragma GCC pop_options
+#endif /* __DISABLE_XSAVES__ */
+
+#endif /* _XSAVESINTRIN_H_INCLUDED */
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 41adc4adc96..cb9a9ca8af8 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -74,6 +74,7 @@ along with GCC; see the file COPYING3. If not see
#include "reload.h"
#include "opts.h"
#include "dumpfile.h"
+#include "builtins.h"
/* This is used for communication between ASM_OUTPUT_LABEL and
ASM_OUTPUT_LABELREF. */
@@ -169,8 +170,7 @@ static int ia64_first_cycle_multipass_dfa_lookahead (void);
static void ia64_dependencies_evaluation_hook (rtx, rtx);
static void ia64_init_dfa_pre_cycle_insn (void);
static rtx ia64_dfa_pre_cycle_insn (void);
-static int ia64_first_cycle_multipass_dfa_lookahead_guard (rtx);
-static bool ia64_first_cycle_multipass_dfa_lookahead_guard_spec (const_rtx);
+static int ia64_first_cycle_multipass_dfa_lookahead_guard (rtx, int);
static int ia64_dfa_new_cycle (FILE *, int, rtx, int, int, int *);
static void ia64_h_i_d_extended (void);
static void * ia64_alloc_sched_context (void);
@@ -496,10 +496,6 @@ static const struct attribute_spec ia64_attribute_table[] =
#undef TARGET_SCHED_GEN_SPEC_CHECK
#define TARGET_SCHED_GEN_SPEC_CHECK ia64_gen_spec_check
-#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC
-#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC\
- ia64_first_cycle_multipass_dfa_lookahead_guard_spec
-
#undef TARGET_SCHED_SKIP_RTX_P
#define TARGET_SCHED_SKIP_RTX_P ia64_skip_rtx_p
@@ -6046,7 +6042,7 @@ void ia64_init_expanders (void)
static struct machine_function *
ia64_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
static enum attr_itanium_class ia64_safe_itanium_class (rtx);
@@ -7531,32 +7527,30 @@ ia64_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
return 1;
}
-/* We are choosing insn from the ready queue. Return nonzero if INSN
+/* We are choosing insn from the ready queue. Return zero if INSN
can be chosen. */
static int
-ia64_first_cycle_multipass_dfa_lookahead_guard (rtx insn)
+ia64_first_cycle_multipass_dfa_lookahead_guard (rtx insn, int ready_index)
{
gcc_assert (insn && INSN_P (insn));
- return ((!reload_completed
- || !safe_group_barrier_needed (insn))
- && ia64_first_cycle_multipass_dfa_lookahead_guard_spec (insn)
- && (!mflag_sched_mem_insns_hard_limit
- || !is_load_p (insn)
- || mem_ops_in_group[current_cycle % 4] < ia64_max_memory_insns));
-}
-/* We are choosing insn from the ready queue. Return nonzero if INSN
- can be chosen. */
+ /* Size of ALAT is 32. As far as we perform conservative
+ data speculation, we keep ALAT half-empty. */
+ if (pending_data_specs >= 16 && (TODO_SPEC (insn) & BEGIN_DATA))
+ return ready_index == 0 ? -1 : 1;
-static bool
-ia64_first_cycle_multipass_dfa_lookahead_guard_spec (const_rtx insn)
-{
- gcc_assert (insn && INSN_P (insn));
- /* Size of ALAT is 32. As far as we perform conservative data speculation,
- we keep ALAT half-empty. */
- return (pending_data_specs < 16
- || !(TODO_SPEC (insn) & BEGIN_DATA));
+ if (ready_index == 0)
+ return 0;
+
+ if ((!reload_completed
+ || !safe_group_barrier_needed (insn))
+ && (!mflag_sched_mem_insns_hard_limit
+ || !is_load_p (insn)
+ || mem_ops_in_group[current_cycle % 4] < ia64_max_memory_insns))
+ return 0;
+
+ return 1;
}
/* The following variable value is pseudo-insn used by the DFA insn
@@ -7943,17 +7937,9 @@ ia64_set_sched_flags (spec_info_t spec_info)
spec_info->flags = 0;
- if ((mask & DATA_SPEC) && mflag_sched_prefer_non_data_spec_insns)
- spec_info->flags |= PREFER_NON_DATA_SPEC;
-
- if (mask & CONTROL_SPEC)
- {
- if (mflag_sched_prefer_non_control_spec_insns)
- spec_info->flags |= PREFER_NON_CONTROL_SPEC;
-
- if (sel_sched_p () && mflag_sel_sched_dont_check_control_spec)
- spec_info->flags |= SEL_SCHED_SPEC_DONT_CHECK_CONTROL;
- }
+ if ((mask & CONTROL_SPEC)
+ && sel_sched_p () && mflag_sel_sched_dont_check_control_spec)
+ spec_info->flags |= SEL_SCHED_SPEC_DONT_CHECK_CONTROL;
if (sched_verbose >= 1)
spec_info->dump = sched_dump;
diff --git a/gcc/config/ia64/ia64.opt b/gcc/config/ia64/ia64.opt
index 0fd43922685..60577a1528d 100644
--- a/gcc/config/ia64/ia64.opt
+++ b/gcc/config/ia64/ia64.opt
@@ -164,12 +164,10 @@ Target Report Var(mflag_sched_spec_control_ldc) Init(0)
Use simple data speculation check for control speculation
msched-prefer-non-data-spec-insns
-Target Report Var(mflag_sched_prefer_non_data_spec_insns) Init(0)
-If set, data speculative instructions will be chosen for schedule only if there are no other choices at the moment
+Target Ignore Warn(switch %qs is no longer supported)
msched-prefer-non-control-spec-insns
-Target Report Var(mflag_sched_prefer_non_control_spec_insns) Init(0)
-If set, control speculative instructions will be chosen for schedule only if there are no other choices at the moment
+Target Ignore Warn(switch %qs is no longer supported)
msched-count-spec-in-critical-path
Target Report Var(mflag_sched_count_spec_in_critical_path) Init(0)
diff --git a/gcc/config/initfini-array.h b/gcc/config/initfini-array.h
index f7ae836e6d3..67e66f6f2ea 100644
--- a/gcc/config/initfini-array.h
+++ b/gcc/config/initfini-array.h
@@ -14,8 +14,13 @@
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_INITFINI_ARRAY_SUPPORT
diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c
index ed7aecbd469..49896e8a198 100644
--- a/gcc/config/iq2000/iq2000.c
+++ b/gcc/config/iq2000/iq2000.c
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
#include "target-def.h"
#include "langhooks.h"
#include "df.h"
+#include "builtins.h"
/* Enumeration for all of the relational tests, so that we can build
arrays indexed by the test type, and not worry about the order
@@ -1424,7 +1425,7 @@ iq2000_va_start (tree valist, rtx nextarg)
static struct machine_function *
iq2000_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* Detect any conflicts in the switches. */
diff --git a/gcc/config/iq2000/iq2000.md b/gcc/config/iq2000/iq2000.md
index f7c7b34e13d..96ba555f8d2 100644
--- a/gcc/config/iq2000/iq2000.md
+++ b/gcc/config/iq2000/iq2000.md
@@ -260,7 +260,7 @@
"")
(define_insn "addsi3_internal"
- [(set (match_operand:SI 0 "register_operand" "=d,=d")
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
(plus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ,dJ")
(match_operand:SI 2 "arith_operand" "d,I")))]
""
@@ -286,7 +286,7 @@
"")
(define_insn "subsi3_internal"
- [(set (match_operand:SI 0 "register_operand" "=d,=d")
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
(minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ,dJ")
(match_operand:SI 2 "arith_operand" "d,I")))]
""
@@ -1229,7 +1229,7 @@
(set_attr "mode" "SI")])
(define_insn "sgt_si"
- [(set (match_operand:SI 0 "register_operand" "=d,=d")
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
(gt:SI (match_operand:SI 1 "register_operand" "d,d")
(match_operand:SI 2 "reg_or_0_operand" "d,J")))]
""
@@ -1240,7 +1240,7 @@
(set_attr "mode" "SI,SI")])
(define_insn "slt_si"
- [(set (match_operand:SI 0 "register_operand" "=d,=d")
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
(lt:SI (match_operand:SI 1 "register_operand" "d,d")
(match_operand:SI 2 "arith_operand" "d,I")))]
""
@@ -1273,7 +1273,7 @@
(set_attr "mode" "SI")])
(define_insn "sltu_si"
- [(set (match_operand:SI 0 "register_operand" "=d,=d")
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
(ltu:SI (match_operand:SI 1 "register_operand" "d,d")
(match_operand:SI 2 "arith_operand" "d,I")))]
""
diff --git a/gcc/config/lm32/lm32.c b/gcc/config/lm32/lm32.c
index 4f6aba1e764..fe3dcf4057f 100644
--- a/gcc/config/lm32/lm32.c
+++ b/gcc/config/lm32/lm32.c
@@ -50,6 +50,7 @@
#include "langhooks.h"
#include "tm-constrs.h"
#include "df.h"
+#include "builtins.h"
struct lm32_frame_info
{
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index 837c22b2d77..0d7dcee1bc9 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -61,6 +61,7 @@
#include "gimple.h"
#include "df.h"
#include "tm-constrs.h"
+#include "builtins.h"
/* Prototypes */
@@ -460,7 +461,7 @@ m32c_override_options_after_change (void)
static struct machine_function *
m32c_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* Implements INIT_EXPANDERS. We just set up to call the above
@@ -3075,7 +3076,7 @@ m32c_note_pragma_address (const char *varname, unsigned address)
if (!*slot)
{
- *slot = ggc_alloc_pragma_entry ();
+ *slot = ggc_alloc<pragma_entry> ();
(*slot)->varname = ggc_strdup (varname);
}
(*slot)->address = address;
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index 2b84b0ff1eb..71ce534e802 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -46,6 +46,7 @@
#include "target-def.h"
#include "tm-constrs.h"
#include "opts.h"
+#include "builtins.h"
/* Array of valid operand punctuation characters. */
static char m32r_punct_chars[256];
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 7f7d668478b..90ffeb497ad 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see
#include "ggc.h"
#include "opts.h"
#include "optabs.h"
+#include "builtins.h"
enum reg_class regno_reg_class[] =
{
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 72c11f592db..d088764fab6 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -5954,15 +5954,15 @@
(define_insn "beq0_di"
[(set (pc)
- (if_then_else (eq (match_operand:DI 0 "general_operand" "d*ao,<>")
+ (if_then_else (eq (match_operand:DI 0 "general_operand" "d*a,o,<>")
(const_int 0))
- (label_ref (match_operand 1 "" ","))
+ (label_ref (match_operand 1 "" ",,"))
(pc)))
- (clobber (match_scratch:SI 2 "=d,d"))]
+ (clobber (match_scratch:SI 2 "=d,&d,d"))]
""
{
CC_STATUS_INIT;
- if (which_alternative == 1)
+ if (which_alternative == 2)
return "move%.l %0,%2\;or%.l %0,%2\;jeq %l1";
if ((cc_prev_status.value1
&& rtx_equal_p (cc_prev_status.value1, operands[0]))
@@ -5999,11 +5999,11 @@
(define_insn "bne0_di"
[(set (pc)
- (if_then_else (ne (match_operand:DI 0 "general_operand" "do,*a")
+ (if_then_else (ne (match_operand:DI 0 "general_operand" "d,o,*a")
(const_int 0))
- (label_ref (match_operand 1 "" ","))
+ (label_ref (match_operand 1 "" ",,"))
(pc)))
- (clobber (match_scratch:SI 2 "=d,X"))]
+ (clobber (match_scratch:SI 2 "=d,&d,X"))]
""
{
if ((cc_prev_status.value1
diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c
index b2ac47e03fe..717591e4324 100644
--- a/gcc/config/mcore/mcore.c
+++ b/gcc/config/mcore/mcore.c
@@ -46,6 +46,7 @@
#include "target.h"
#include "target-def.h"
#include "df.h"
+#include "builtins.h"
/* For dumping information about frame sizes. */
char * mcore_current_function_name = 0;
diff --git a/gcc/config/mep/mep.c b/gcc/config/mep/mep.c
index 858136b988c..558883c47c3 100644
--- a/gcc/config/mep/mep.c
+++ b/gcc/config/mep/mep.c
@@ -65,6 +65,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify.h"
#include "opts.h"
#include "dumpfile.h"
+#include "builtins.h"
/* Structure of this file:
@@ -2225,7 +2226,7 @@ mep_register_move_cost (enum machine_mode mode, enum reg_class from, enum reg_cl
static struct machine_function *
mep_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
static rtx
@@ -4099,7 +4100,7 @@ mep_note_pragma_flag (const char *funcname, int flag)
if (!*slot)
{
- *slot = ggc_alloc_pragma_entry ();
+ *slot = ggc_alloc<pragma_entry> ();
(*slot)->flag = 0;
(*slot)->used = 0;
(*slot)->funcname = ggc_strdup (funcname);
@@ -4532,7 +4533,7 @@ mep_select_section (tree decl, int reloc ATTRIBUTE_UNUSED,
else
encoding = 0;
- if (flag_function_sections || DECL_ONE_ONLY (decl))
+ if (flag_function_sections || DECL_COMDAT_GROUP (decl))
mep_unique_section (decl, 0);
else if (lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
{
@@ -4651,7 +4652,7 @@ mep_unique_section (tree decl, int reloc)
name += 3;
}
- prefix = prefixes[sec][DECL_ONE_ONLY(decl)];
+ prefix = prefixes[sec][DECL_COMDAT_GROUP(decl) != NULL];
len = strlen (name) + strlen (prefix);
string = (char *) alloca (len + 1);
diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
index b03e9e126c0..f3cc0991ae0 100644
--- a/gcc/config/microblaze/microblaze-protos.h
+++ b/gcc/config/microblaze/microblaze-protos.h
@@ -40,10 +40,12 @@ extern void print_operand_address (FILE *, rtx);
extern void init_cumulative_args (CUMULATIVE_ARGS *,tree, rtx);
extern bool microblaze_legitimate_address_p (enum machine_mode, rtx, bool);
extern int microblaze_is_interrupt_variant (void);
+extern int microblaze_is_break_handler (void);
+extern int microblaze_break_function_p (tree func);
extern rtx microblaze_return_addr (int, rtx);
extern int simple_memory_operand (rtx, enum machine_mode);
extern int double_memory_operand (rtx, enum machine_mode);
-
+extern void microblaze_order_regs_for_local_alloc (void);
extern int microblaze_regno_ok_for_base_p (int, int);
extern HOST_WIDE_INT microblaze_initial_elimination_offset (int, int);
extern void microblaze_declare_object (FILE *, const char *, const char *,
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index ba8109bc123..cf2dc74cccc 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -51,6 +51,7 @@
#include "optabs.h"
#include "diagnostic-core.h"
#include "cgraph.h"
+#include "builtins.h"
#define MICROBLAZE_VERSION_COMPARE(VA,VB) strcasecmp (VA, VB)
@@ -209,6 +210,7 @@ enum reg_class microblaze_regno_to_class[] =
and epilogue and use appropriate interrupt return.
save_volatiles - Similar to interrupt handler, but use normal return. */
int interrupt_handler;
+int break_handler;
int fast_interrupt;
int save_volatiles;
@@ -217,6 +219,8 @@ const struct attribute_spec microblaze_attribute_table[] = {
affects_type_identity */
{"interrupt_handler", 0, 0, true, false, false, NULL,
false },
+ {"break_handler", 0, 0, true, false, false, NULL,
+ false },
{"fast_interrupt", 0, 0, true, false, false, NULL,
false },
{"save_volatiles" , 0, 0, true, false, false, NULL,
@@ -1866,7 +1870,18 @@ microblaze_fast_interrupt_function_p (tree func)
a = lookup_attribute ("fast_interrupt", DECL_ATTRIBUTES (func));
return a != NULL_TREE;
}
+int
+microblaze_break_function_p (tree func)
+{
+ tree a;
+ if (!func)
+ return 0;
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ return 0;
+ a = lookup_attribute ("break_handler", DECL_ATTRIBUTES (func));
+ return a != NULL_TREE;
+}
/* Return true if FUNC is an interrupt function which uses
normal return, indicated by the "save_volatiles" attribute. */
@@ -1891,6 +1906,11 @@ microblaze_is_interrupt_variant (void)
{
return (interrupt_handler || fast_interrupt);
}
+int
+microblaze_is_break_handler (void)
+{
+ return break_handler;
+}
/* Determine of register must be saved/restored in call. */
static int
@@ -1994,9 +2014,14 @@ compute_frame_size (HOST_WIDE_INT size)
interrupt_handler =
microblaze_interrupt_function_p (current_function_decl);
+ break_handler =
+ microblaze_break_function_p (current_function_decl);
+
fast_interrupt =
microblaze_fast_interrupt_function_p (current_function_decl);
save_volatiles = microblaze_save_volatiles (current_function_decl);
+ if (break_handler)
+ interrupt_handler = break_handler;
gp_reg_size = 0;
mask = 0;
@@ -2641,9 +2666,11 @@ microblaze_function_prologue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
{
fputs ("\t.ent\t", file);
if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname))
- fputs ("_interrupt_handler", file);
+ fputs ("_interrupt_handler", file);
+ else if (break_handler && strcmp (BREAK_HANDLER_NAME, fnname))
+ fputs ("_break_handler", file);
else if (fast_interrupt && strcmp (FAST_INTERRUPT_NAME, fnname))
- fputs ("_fast_interrupt", file);
+ fputs ("_fast_interrupt", file);
else
assemble_name (file, fnname);
fputs ("\n", file);
@@ -2656,7 +2683,8 @@ microblaze_function_prologue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname))
fputs ("_interrupt_handler:\n", file);
-
+ if (break_handler && strcmp (BREAK_HANDLER_NAME, fnname))
+ fputs ("_break_handler:\n", file);
if (!flag_inhibit_size_directive)
{
/* .frame FRAMEREG, FRAMESIZE, RETREG. */
@@ -2791,6 +2819,7 @@ microblaze_expand_prologue (void)
if (flag_stack_usage_info)
current_function_static_stack_size = fsiz;
+
/* If this function is a varargs function, store any registers that
would normally hold arguments ($5 - $10) on the stack. */
if (((TYPE_ARG_TYPES (fntype) != 0
@@ -2892,8 +2921,10 @@ microblaze_function_epilogue (FILE * file ATTRIBUTE_UNUSED,
if (!flag_inhibit_size_directive)
{
fputs ("\t.end\t", file);
- if (interrupt_handler)
+ if (interrupt_handler && !break_handler)
fputs ("_interrupt_handler", file);
+ else if (break_handler)
+ fputs ("_break_handler", file);
else
assemble_name (file, fnname);
fputs ("\n", file);
@@ -3007,6 +3038,8 @@ microblaze_globalize_label (FILE * stream, const char *name)
{
if (interrupt_handler && strcmp (name, INTERRUPT_HANDLER_NAME))
fputs (INTERRUPT_HANDLER_NAME, stream);
+ else if (break_handler && strcmp (name, BREAK_HANDLER_NAME))
+ fputs (BREAK_HANDLER_NAME, stream);
else if (fast_interrupt && strcmp (name, FAST_INTERRUPT_NAME))
fputs (FAST_INTERRUPT_NAME, stream);
fputs ("\n\t.globl\t", stream);
diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h
index 58d8895a319..edb7d8aaab8 100644
--- a/gcc/config/microblaze/microblaze.h
+++ b/gcc/config/microblaze/microblaze.h
@@ -263,7 +263,6 @@ extern enum pipeline_type microblaze_pipe;
1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1, 1, 1 \
}
-
#define GP_REG_FIRST 0
#define GP_REG_LAST 31
#define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1)
@@ -763,6 +762,10 @@ extern int fast_interrupt;
extern int save_volatiles;
#define INTERRUPT_HANDLER_NAME "_interrupt_handler"
+/* The function name for the function tagged with attribute break_handler
+ has been set in the RTL as _break_handler. This function name is used
+ in the generation of directives .ent .end and .global. */
+#define BREAK_HANDLER_NAME "_break_handler"
#define FAST_INTERRUPT_NAME "_fast_interrupt"
/* The following #defines are used in the headers files. Always retain these. */
diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
index 815d6b5d706..7945d96b794 100644
--- a/gcc/config/microblaze/microblaze.md
+++ b/gcc/config/microblaze/microblaze.md
@@ -1945,8 +1945,10 @@
(define_insn "*<optab>"
[(any_return)]
""
- {
- if (microblaze_is_interrupt_variant ())
+ {
+ if (microblaze_is_break_handler ())
+ return "rtbd\tr16, 8\;%#";
+ else if (microblaze_is_interrupt_variant ())
return "rtid\tr14, 0\;%#";
else
return "rtsd\tr15, 8\;%#";
@@ -1962,8 +1964,10 @@
[(any_return)
(use (match_operand:SI 0 "register_operand" ""))]
""
- {
- if (microblaze_is_interrupt_variant ())
+ {
+ if (microblaze_is_break_handler ())
+ return "rtbd\tr16,8\;%#";
+ else if (microblaze_is_interrupt_variant ())
return "rtid\tr14,0 \;%#";
else
return "rtsd\tr15,8 \;%#";
@@ -2068,8 +2072,14 @@
register rtx target2 = gen_rtx_REG (Pmode,
GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
if (GET_CODE (target) == SYMBOL_REF) {
- gen_rtx_CLOBBER (VOIDmode, target2);
- return "brlid\tr15,%0\;%#";
+ if (microblaze_break_function_p (SYMBOL_REF_DECL (target))) {
+ gen_rtx_CLOBBER (VOIDmode, target2);
+ return "brki\tr16,%0\;%#";
+ }
+ else {
+ gen_rtx_CLOBBER (VOIDmode, target2);
+ return "brlid\tr15,%0\;%#";
+ }
} else if (GET_CODE (target) == CONST_INT)
return "la\t%@,r0,%0\;brald\tr15,%@\;%#";
else if (GET_CODE (target) == REG)
@@ -2173,13 +2183,15 @@
if (GET_CODE (target) == SYMBOL_REF)
{
gen_rtx_CLOBBER (VOIDmode,target2);
- if (SYMBOL_REF_FLAGS (target) & SYMBOL_FLAG_FUNCTION)
+ if (microblaze_break_function_p (SYMBOL_REF_DECL (target)))
+ return "brki\tr16,%1\;%#";
+ else if (SYMBOL_REF_FLAGS (target) & SYMBOL_FLAG_FUNCTION)
{
return "brlid\tr15,%1\;%#";
}
else
{
- return "bralid\tr15,%1\;%#";
+ return "bralid\tr15,%1\;%#";
}
}
else if (GET_CODE (target) == CONST_INT)
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 35844ad275a..0d6bbf16ad1 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -71,6 +71,8 @@ along with GCC; see the file COPYING3. If not see
#include "opts.h"
#include "tree-pass.h"
#include "context.h"
+#include "cgraph.h"
+#include "builtins.h"
/* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */
#define UNSPEC_ADDRESS_P(X) \
@@ -1241,7 +1243,7 @@ mflip_mips16_use_mips16_p (tree decl)
if (!entry)
{
mips16_flipper = !mips16_flipper;
- entry = ggc_alloc_mflip_mips16_entry ();
+ entry = ggc_alloc<mflip_mips16_entry> ();
entry->name = name;
entry->mips16_p = mips16_flipper ? !base_is_mips16 : base_is_mips16;
*slot = entry;
@@ -2847,6 +2849,15 @@ mips_emit_call_insn (rtx pattern, rtx orig_addr, rtx addr, bool lazy_p)
gen_rtx_REG (Pmode, GOT_VERSION_REGNUM));
emit_insn (gen_update_got_version ());
}
+
+ if (TARGET_MIPS16
+ && TARGET_EXPLICIT_RELOCS
+ && TARGET_CALL_CLOBBERED_GP)
+ {
+ rtx post_call_tmp_reg = gen_rtx_REG (word_mode, POST_CALL_TMP_REG);
+ clobber_reg (&CALL_INSN_FUNCTION_USAGE (insn), post_call_tmp_reg);
+ }
+
return insn;
}
@@ -6275,7 +6286,7 @@ mips_start_unique_function (const char *name)
TREE_PUBLIC (decl) = 1;
TREE_STATIC (decl) = 1;
- DECL_COMDAT_GROUP (decl) = DECL_ASSEMBLER_NAME (decl);
+ cgraph_create_node (decl)->set_comdat_group (DECL_ASSEMBLER_NAME (decl));
targetm.asm_out.unique_section (decl, 0);
switch_to_section (get_named_section (decl, NULL, 0));
@@ -6451,7 +6462,7 @@ mips16_local_alias (rtx func)
SYMBOL_REF_FLAGS (local) = SYMBOL_REF_FLAGS (func) | SYMBOL_FLAG_LOCAL;
/* Create a new structure to represent the mapping. */
- alias = ggc_alloc_mips16_local_alias ();
+ alias = ggc_alloc<struct mips16_local_alias> ();
alias->func = func;
alias->local = local;
*slot = alias;
@@ -7103,10 +7114,8 @@ mips_split_call (rtx insn, rtx call_pattern)
{
emit_call_insn (call_pattern);
if (!find_reg_note (insn, REG_NORETURN, 0))
- /* Pick a temporary register that is suitable for both MIPS16 and
- non-MIPS16 code. $4 and $5 are used for returning complex double
- values in soft-float code, so $6 is the first suitable candidate. */
- mips_restore_gp_from_cprestore_slot (gen_rtx_REG (Pmode, GP_ARG_FIRST + 2));
+ mips_restore_gp_from_cprestore_slot (gen_rtx_REG (Pmode,
+ POST_CALL_TMP_REG));
}
/* Return true if a call to DECL may need to use JALX. */
@@ -8469,7 +8478,7 @@ mips_function_rodata_section (tree decl)
if (decl && DECL_SECTION_NAME (decl))
{
const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
- if (DECL_ONE_ONLY (decl) && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
+ if (DECL_COMDAT_GROUP (decl) && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
{
char *rname = ASTRDUP (name);
rname[14] = 'd';
@@ -16829,7 +16838,7 @@ mips_set_current_function (tree fndecl)
static struct machine_function *
mips_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* Return the processor associated with the given ISA level, or null
@@ -19142,6 +19151,9 @@ mips_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV mips_atomic_assign_expand_fenv
+#undef TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS
+#define TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS true
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-mips.h"
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 6200ffc4e2c..933e053d6a6 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -2175,6 +2175,13 @@ enum reg_class
#define FP_ARG_FIRST (FP_REG_FIRST + 12)
#define FP_ARG_LAST (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
+/* Temporary register that is used when restoring $gp after a call. $4 and $5
+ are used for returning complex double values in soft-float code, so $6 is the
+ first suitable candidate for TARGET_MIPS16. For !TARGET_MIPS16 we can use
+ $gp itself as the temporary. */
+#define POST_CALL_TMP_REG \
+ (TARGET_MIPS16 ? GP_ARG_FIRST + 2 : PIC_OFFSET_TABLE_REGNUM)
+
/* 1 if N is a possible register number for function argument passing.
We have no FP argument registers when soft-float. When FP registers
are 32 bits, we can't directly reference the odd numbered ones. */
diff --git a/gcc/config/mmix/mmix-protos.h b/gcc/config/mmix/mmix-protos.h
index d738a1a0846..32d53f559c5 100644
--- a/gcc/config/mmix/mmix-protos.h
+++ b/gcc/config/mmix/mmix-protos.h
@@ -39,9 +39,9 @@ extern void mmix_asm_output_reg_push (FILE *, int);
extern void mmix_asm_output_reg_pop (FILE *, int);
extern void mmix_asm_output_skip (FILE *, int);
extern void mmix_asm_output_align (FILE *, int);
-extern HOST_WIDEST_INT mmix_intval (const_rtx);
-extern int mmix_shiftable_wyde_value (unsigned HOST_WIDEST_INT);
-extern void mmix_output_register_setting (FILE *, int, HOST_WIDEST_INT, int);
+extern int64_t mmix_intval (const_rtx);
+extern int mmix_shiftable_wyde_value (uint64_t);
+extern void mmix_output_register_setting (FILE *, int, int64_t, int);
extern int mmix_opposite_regno (int, int);
extern int mmix_local_regno (int);
extern unsigned mmix_dbx_register_number (unsigned);
diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c
index 2616dd54a92..e0b8ce76f09 100644
--- a/gcc/config/mmix/mmix.c
+++ b/gcc/config/mmix/mmix.c
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see
#include "target-def.h"
#include "df.h"
#include "tm-constrs.h"
+#include "builtins.h"
/* First some local helper definitions. */
#define MMIX_FIRST_GLOBAL_REGNUM 32
@@ -117,10 +118,10 @@ static int mmix_output_destination_register;
static void mmix_option_override (void);
static void mmix_asm_output_source_filename (FILE *, const char *);
static void mmix_output_shiftvalue_op_from_str
- (FILE *, const char *, HOST_WIDEST_INT);
-static void mmix_output_shifted_value (FILE *, HOST_WIDEST_INT);
+ (FILE *, const char *, int64_t);
+static void mmix_output_shifted_value (FILE *, int64_t);
static void mmix_output_condition (FILE *, const_rtx, int);
-static void mmix_output_octa (FILE *, HOST_WIDEST_INT, int);
+static void mmix_output_octa (FILE *, int64_t, int);
static bool mmix_assemble_integer (rtx, unsigned int, int);
static struct machine_function *mmix_init_machine_status (void);
static void mmix_encode_section_info (tree, rtx, int);
@@ -313,7 +314,7 @@ mmix_init_expanders (void)
static struct machine_function *
mmix_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* DATA_ABI_ALIGNMENT.
@@ -1588,25 +1589,25 @@ mmix_print_operand (FILE *stream, rtx x, int code)
output. */
case 'A':
mmix_output_shiftvalue_op_from_str (stream, "ANDN",
- ~(unsigned HOST_WIDEST_INT)
+ ~(uint64_t)
mmix_intval (x));
return;
case 'i':
mmix_output_shiftvalue_op_from_str (stream, "INC",
- (unsigned HOST_WIDEST_INT)
+ (uint64_t)
mmix_intval (x));
return;
case 'o':
mmix_output_shiftvalue_op_from_str (stream, "OR",
- (unsigned HOST_WIDEST_INT)
+ (uint64_t)
mmix_intval (x));
return;
case 's':
mmix_output_shiftvalue_op_from_str (stream, "SET",
- (unsigned HOST_WIDEST_INT)
+ (uint64_t)
mmix_intval (x));
return;
@@ -1628,8 +1629,8 @@ mmix_print_operand (FILE *stream, rtx x, int code)
fatal_insn ("MMIX Internal: Bad value for 'm', not a CONST_INT",
x);
}
- fprintf (stream, HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) (mmix_intval (x) - 1));
+ fprintf (stream, "%"PRId64,
+ (int64_t) (mmix_intval (x) - 1));
return;
case 'p':
@@ -1667,11 +1668,11 @@ mmix_print_operand (FILE *stream, rtx x, int code)
return;
case 'v':
- mmix_output_shifted_value (stream, (HOST_WIDEST_INT) mmix_intval (x));
+ mmix_output_shifted_value (stream, (int64_t) mmix_intval (x));
return;
case 'V':
- mmix_output_shifted_value (stream, (HOST_WIDEST_INT) ~mmix_intval (x));
+ mmix_output_shifted_value (stream, (int64_t) ~mmix_intval (x));
return;
case 'W':
@@ -2294,37 +2295,37 @@ mmix_expand_epilogue (void)
void
mmix_output_register_setting (FILE *stream,
int regno,
- HOST_WIDEST_INT value,
+ int64_t value,
int do_begin_end)
{
if (do_begin_end)
fprintf (stream, "\t");
if (insn_const_int_ok_for_constraint (value, CONSTRAINT_K))
- fprintf (stream, "NEGU %s,0," HOST_WIDEST_INT_PRINT_DEC, reg_names[regno], -value);
- else if (mmix_shiftable_wyde_value ((unsigned HOST_WIDEST_INT) value))
+ fprintf (stream, "NEGU %s,0,%"PRId64, reg_names[regno], -value);
+ else if (mmix_shiftable_wyde_value ((uint64_t) value))
{
/* First, the one-insn cases. */
mmix_output_shiftvalue_op_from_str (stream, "SET",
- (unsigned HOST_WIDEST_INT)
+ (uint64_t)
value);
fprintf (stream, " %s,", reg_names[regno]);
- mmix_output_shifted_value (stream, (unsigned HOST_WIDEST_INT) value);
+ mmix_output_shifted_value (stream, (uint64_t) value);
}
- else if (mmix_shiftable_wyde_value (-(unsigned HOST_WIDEST_INT) value))
+ else if (mmix_shiftable_wyde_value (-(uint64_t) value))
{
/* We do this to get a bit more legible assembly code. The next
alternative is mostly redundant with this. */
mmix_output_shiftvalue_op_from_str (stream, "SET",
- -(unsigned HOST_WIDEST_INT)
+ -(uint64_t)
value);
fprintf (stream, " %s,", reg_names[regno]);
- mmix_output_shifted_value (stream, -(unsigned HOST_WIDEST_INT) value);
+ mmix_output_shifted_value (stream, -(uint64_t) value);
fprintf (stream, "\n\tNEGU %s,0,%s", reg_names[regno],
reg_names[regno]);
}
- else if (mmix_shiftable_wyde_value (~(unsigned HOST_WIDEST_INT) value))
+ else if (mmix_shiftable_wyde_value (~(uint64_t) value))
{
/* Slightly more expensive, the two-insn cases. */
@@ -2335,10 +2336,10 @@ mmix_output_register_setting (FILE *stream,
anyone else cares). */
mmix_output_shiftvalue_op_from_str (stream, "SET",
- ~(unsigned HOST_WIDEST_INT)
+ ~(uint64_t)
value);
fprintf (stream, " %s,", reg_names[regno]);
- mmix_output_shifted_value (stream, ~(unsigned HOST_WIDEST_INT) value);
+ mmix_output_shifted_value (stream, ~(uint64_t) value);
fprintf (stream, "\n\tNOR %s,%s,0", reg_names[regno],
reg_names[regno]);
}
@@ -2350,7 +2351,7 @@ mmix_output_register_setting (FILE *stream,
const char *line_begin = "";
int insns = 0;
int i;
- HOST_WIDEST_INT tmpvalue = value;
+ int64_t tmpvalue = value;
/* Compute the number of insns needed to output this constant. */
for (i = 0; i < 4 && tmpvalue != 0; i++)
@@ -2405,7 +2406,7 @@ mmix_output_register_setting (FILE *stream,
else return 0. */
int
-mmix_shiftable_wyde_value (unsigned HOST_WIDEST_INT value)
+mmix_shiftable_wyde_value (uint64_t value)
{
/* Shift by 16 bits per group, stop when we've found two groups with
nonzero bits. */
@@ -2487,7 +2488,7 @@ mmix_emit_sp_add (HOST_WIDE_INT offset)
static void
mmix_output_shiftvalue_op_from_str (FILE *stream,
const char *mainop,
- HOST_WIDEST_INT value)
+ int64_t value)
{
static const char *const op_part[] = {"L", "ML", "MH", "H"};
int i;
@@ -2495,7 +2496,7 @@ mmix_output_shiftvalue_op_from_str (FILE *stream,
if (! mmix_shiftable_wyde_value (value))
{
char s[sizeof ("0xffffffffffffffff")];
- sprintf (s, HOST_WIDEST_INT_PRINT_HEX, value);
+ sprintf (s, "%#"PRIx64, value);
internal_error ("MMIX Internal: %s is not a shiftable int", s);
}
@@ -2518,26 +2519,26 @@ mmix_output_shiftvalue_op_from_str (FILE *stream,
/* Print a 64-bit value, optionally prefixed by assembly pseudo. */
static void
-mmix_output_octa (FILE *stream, HOST_WIDEST_INT value, int do_begin_end)
+mmix_output_octa (FILE *stream, int64_t value, int do_begin_end)
{
if (do_begin_end)
fprintf (stream, "\tOCTA ");
/* Provide a few alternative output formats depending on the number, to
improve legibility of assembler output. */
- if ((value < (HOST_WIDEST_INT) 0 && value > (HOST_WIDEST_INT) -10000)
- || (value >= (HOST_WIDEST_INT) 0 && value <= (HOST_WIDEST_INT) 16384))
+ if ((value < (int64_t) 0 && value > (int64_t) -10000)
+ || (value >= (int64_t) 0 && value <= (int64_t) 16384))
fprintf (stream, "%d", (int) value);
- else if (value > (HOST_WIDEST_INT) 0
- && value < ((HOST_WIDEST_INT) 1 << 31) * 2)
+ else if (value > (int64_t) 0
+ && value < ((int64_t) 1 << 31) * 2)
fprintf (stream, "#%x", (unsigned int) value);
- else if (sizeof (HOST_WIDE_INT) == sizeof (HOST_WIDEST_INT))
+ else if (sizeof (HOST_WIDE_INT) == sizeof (int64_t))
/* We need to avoid the not-so-universal "0x" prefix; we need the
pure hex-digits together with the mmixal "#" hex prefix. */
fprintf (stream, "#" HOST_WIDE_INT_PRINT_HEX_PURE,
(HOST_WIDE_INT) value);
else /* Need to avoid the hex output; there's no ...WIDEST...HEX_PURE. */
- fprintf (stream, HOST_WIDEST_INT_PRINT_UNSIGNED, value);
+ fprintf (stream, "%"PRIu64, value);
if (do_begin_end)
fprintf (stream, "\n");
@@ -2547,14 +2548,14 @@ mmix_output_octa (FILE *stream, HOST_WIDEST_INT value, int do_begin_end)
be output with an operand). */
static void
-mmix_output_shifted_value (FILE *stream, HOST_WIDEST_INT value)
+mmix_output_shifted_value (FILE *stream, int64_t value)
{
int i;
if (! mmix_shiftable_wyde_value (value))
{
char s[16+2+1];
- sprintf (s, HOST_WIDEST_INT_PRINT_HEX, value);
+ sprintf (s, "%#"PRIx64, value);
internal_error ("MMIX Internal: %s is not a shiftable int", s);
}
@@ -2687,10 +2688,10 @@ mmix_output_condition (FILE *stream, const_rtx x, int reversed)
/* Return the bit-value for a const_int or const_double. */
-HOST_WIDEST_INT
+int64_t
mmix_intval (const_rtx x)
{
- unsigned HOST_WIDEST_INT retval;
+ uint64_t retval;
if (GET_CODE (x) == CONST_INT)
return INTVAL (x);
@@ -2699,22 +2700,7 @@ mmix_intval (const_rtx x)
gcc-2.7.2 is broken. I still want people to be able to use it for
cross-compilation to MMIX. */
if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == VOIDmode)
- {
- if (sizeof (HOST_WIDE_INT) < sizeof (HOST_WIDEST_INT))
- {
- retval = (unsigned) CONST_DOUBLE_LOW (x) / 2;
- retval *= 2;
- retval |= CONST_DOUBLE_LOW (x) & 1;
-
- retval |=
- (unsigned HOST_WIDEST_INT) CONST_DOUBLE_HIGH (x)
- << (HOST_BITS_PER_LONG)/2 << (HOST_BITS_PER_LONG)/2;
- }
- else
- retval = CONST_DOUBLE_HIGH (x);
-
- return retval;
- }
+ return CONST_DOUBLE_HIGH (x);
if (GET_CODE (x) == CONST_DOUBLE)
{
@@ -2733,9 +2719,9 @@ mmix_intval (const_rtx x)
sign-extended to unsigned long long(!) when they're of
different size (usually 32-bit hosts). */
return
- ((unsigned HOST_WIDEST_INT) (unsigned long) bits[0]
- << (unsigned HOST_WIDEST_INT) 32U)
- | (unsigned HOST_WIDEST_INT) (unsigned long) bits[1];
+ ((uint64_t) (unsigned long) bits[0]
+ << (uint64_t) 32U)
+ | (uint64_t) (unsigned long) bits[1];
}
else if (GET_MODE (x) == SFmode)
{
diff --git a/gcc/config/mmix/mmix.md b/gcc/config/mmix/mmix.md
index 3c74b664f67..306d632e998 100644
--- a/gcc/config/mmix/mmix.md
+++ b/gcc/config/mmix/mmix.md
@@ -1168,7 +1168,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
}
else
{
- HOST_WIDEST_INT offs = INTVAL (XEXP (operands[1], 1));
+ int64_t offs = INTVAL (XEXP (operands[1], 1));
offs += MMIX_fp_rO_OFFSET;
if (insn_const_int_ok_for_constraint (offs, CONSTRAINT_I))
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index eb000776750..d229ca9638b 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -49,6 +49,7 @@
#include "opts.h"
#include "cfgloop.h"
#include "dumpfile.h"
+#include "builtins.h"
/* This is used in the am33_2.0-linux-gnu port, in which global symbol
names are not prefixed by underscores, to tell whether to prefix a
diff --git a/gcc/config/moxie/moxie.c b/gcc/config/moxie/moxie.c
index b646a432bb2..1e289068179 100644
--- a/gcc/config/moxie/moxie.c
+++ b/gcc/config/moxie/moxie.c
@@ -49,6 +49,7 @@
#include "tm_p.h"
#include "langhooks.h"
#include "df.h"
+#include "builtins.h"
#define LOSE_AND_RETURN(msgid, x) \
do \
@@ -229,7 +230,7 @@ struct GTY(()) machine_function
static struct machine_function *
moxie_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 1ec96526efd..52195c90a7e 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -51,6 +51,7 @@
#include "msp430-protos.h"
#include "dumpfile.h"
#include "opts.h"
+#include "builtins.h"
static void msp430_compute_frame_info (void);
@@ -90,7 +91,7 @@ msp430_init_machine_status (void)
{
struct machine_function *m;
- m = ggc_alloc_cleared_machine_function ();
+ m = ggc_cleared_alloc<machine_function> ();
return m;
}
@@ -730,6 +731,97 @@ msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED)
{
return Pmode;
}
+
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
+
+#include "gimplify.h"
+#include "gimple-expr.h"
+
+static tree
+msp430_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
+ gimple_seq *post_p)
+{
+ tree addr, t, type_size, rounded_size, valist_tmp;
+ unsigned HOST_WIDE_INT align, boundary;
+ bool indirect;
+
+ indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+ if (indirect)
+ type = build_pointer_type (type);
+
+ align = PARM_BOUNDARY / BITS_PER_UNIT;
+ boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
+
+ /* When we align parameter on stack for caller, if the parameter
+ alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
+ aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
+ here with caller. */
+ if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
+ boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
+
+ boundary /= BITS_PER_UNIT;
+
+ /* Hoist the valist value into a temporary for the moment. */
+ valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
+
+ /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
+ requires greater alignment, we must perform dynamic alignment. */
+ if (boundary > align
+ && !integer_zerop (TYPE_SIZE (type)))
+ {
+ /* FIXME: This is where this function diverts from targhooks.c:
+ std_gimplify_va_arg_expr(). It works, but I do not know why... */
+ if (! POINTER_TYPE_P (type))
+ {
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
+ fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
+ gimplify_and_add (t, pre_p);
+
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
+ fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
+ valist_tmp,
+ build_int_cst (TREE_TYPE (valist), -boundary)));
+ gimplify_and_add (t, pre_p);
+ }
+ }
+ else
+ boundary = align;
+
+ /* If the actual alignment is less than the alignment of the type,
+ adjust the type accordingly so that we don't assume strict alignment
+ when dereferencing the pointer. */
+ boundary *= BITS_PER_UNIT;
+ if (boundary < TYPE_ALIGN (type))
+ {
+ type = build_variant_type_copy (type);
+ TYPE_ALIGN (type) = boundary;
+ }
+
+ /* Compute the rounded size of the type. */
+ type_size = size_in_bytes (type);
+ rounded_size = round_up (type_size, align);
+
+ /* Reduce rounded_size so it's sharable with the postqueue. */
+ gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
+
+ /* Get AP. */
+ addr = valist_tmp;
+
+ /* Compute new value for AP. */
+ t = fold_build_pointer_plus (valist_tmp, rounded_size);
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
+ gimplify_and_add (t, pre_p);
+
+ addr = fold_convert (build_pointer_type (type), addr);
+
+ if (indirect)
+ addr = build_va_arg_indirect_ref (addr);
+
+ addr = build_va_arg_indirect_ref (addr);
+
+ return addr;
+}
/* Addressing Modes */
@@ -1194,6 +1286,7 @@ enum msp430_builtin
{
MSP430_BUILTIN_BIC_SR,
MSP430_BUILTIN_BIS_SR,
+ MSP430_BUILTIN_DELAY_CYCLES,
MSP430_BUILTIN_max
};
@@ -1203,6 +1296,7 @@ static void
msp430_init_builtins (void)
{
tree void_ftype_int = build_function_type_list (void_type_node, integer_type_node, NULL);
+ tree void_ftype_longlong = build_function_type_list (void_type_node, long_long_integer_type_node, NULL);
msp430_builtins[MSP430_BUILTIN_BIC_SR] =
add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int,
@@ -1211,6 +1305,10 @@ msp430_init_builtins (void)
msp430_builtins[MSP430_BUILTIN_BIS_SR] =
add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int,
MSP430_BUILTIN_BIS_SR, BUILT_IN_MD, NULL, NULL_TREE);
+
+ msp430_builtins[MSP430_BUILTIN_DELAY_CYCLES] =
+ add_builtin_function ( "__delay_cycles", void_ftype_longlong,
+ MSP430_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL, NULL_TREE);
}
static tree
@@ -1220,12 +1318,126 @@ msp430_builtin_decl (unsigned code, bool initialize ATTRIBUTE_UNUSED)
{
case MSP430_BUILTIN_BIC_SR:
case MSP430_BUILTIN_BIS_SR:
+ case MSP430_BUILTIN_DELAY_CYCLES:
return msp430_builtins[code];
default:
return error_mark_node;
}
}
+/* These constants are really register reads, which are faster than
+ regular constants. */
+static int
+cg_magic_constant (HOST_WIDE_INT c)
+{
+ switch (c)
+ {
+ case 0xffff:
+ case -1:
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static rtx
+msp430_expand_delay_cycles (rtx arg)
+{
+ HOST_WIDE_INT i, c, n;
+ /* extra cycles for MSP430X instructions */
+#define CYCX(M,X) (msp430x ? (X) : (M))
+
+ if (GET_CODE (arg) != CONST_INT)
+ {
+ error ("__delay_cycles() only takes constant arguments");
+ return NULL_RTX;
+ }
+
+ c = INTVAL (arg);
+
+ if (HOST_BITS_PER_WIDE_INT > 32)
+ {
+ if (c < 0)
+ {
+ error ("__delay_cycles only takes non-negative cycle counts.");
+ return NULL_RTX;
+ }
+ }
+
+ emit_insn (gen_delay_cycles_start (arg));
+
+ /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
+ if (c > 3 * 0xffff + CYCX (7, 10))
+ {
+ n = c;
+ /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
+ if (c >= 0x10000 * 7 + CYCX (14, 16))
+ {
+ i = 0x10000;
+ c -= CYCX (14, 16) + 7 * 0x10000;
+ i += c / 4;
+ c %= 4;
+ if ((unsigned long long) i > 0xffffffffULL)
+ {
+ error ("__delay_cycles is limited to 32-bit loop counts.");
+ return NULL_RTX;
+ }
+ }
+ else
+ {
+ i = (c - CYCX (14, 16)) / 7;
+ c -= CYCX (14, 16) + i * 7;
+ }
+
+ if (cg_magic_constant (i & 0xffff))
+ c ++;
+ if (cg_magic_constant ((i >> 16) & 0xffff))
+ c ++;
+
+ if (msp430x)
+ emit_insn (gen_delay_cycles_32x (GEN_INT (i), GEN_INT (n - c)));
+ else
+ emit_insn (gen_delay_cycles_32 (GEN_INT (i), GEN_INT (n - c)));
+ }
+
+ /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
+ if (c > 12)
+ {
+ n = c;
+ i = (c - CYCX (7, 10)) / 3;
+ c -= CYCX (7, 10) + i * 3;
+
+ if (cg_magic_constant (i))
+ c ++;
+
+ if (msp430x)
+ emit_insn (gen_delay_cycles_16x (GEN_INT (i), GEN_INT (n - c)));
+ else
+ emit_insn (gen_delay_cycles_16 (GEN_INT (i), GEN_INT (n - c)));
+ }
+
+ while (c > 1)
+ {
+ emit_insn (gen_delay_cycles_2 ());
+ c -= 2;
+ }
+
+ if (c)
+ {
+ emit_insn (gen_delay_cycles_1 ());
+ c -= 1;
+ }
+
+ emit_insn (gen_delay_cycles_end (arg));
+
+ return NULL_RTX;
+}
+
static rtx
msp430_expand_builtin (tree exp,
rtx target ATTRIBUTE_UNUSED,
@@ -1237,6 +1449,9 @@ msp430_expand_builtin (tree exp,
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
+ if (fcode == MSP430_BUILTIN_DELAY_CYCLES)
+ return msp430_expand_delay_cycles (arg1);
+
if (! msp430_is_interrupt_func ())
{
error ("MSP430 builtin functions only work inside interrupt handlers");
@@ -2185,8 +2400,32 @@ msp430_print_operand (FILE * file, rtx op, int letter)
msp430_print_operand_addr (file, addr);
break;
- case CONST_INT:
case CONST:
+ if (GET_CODE (XEXP (op, 0)) == ZERO_EXTRACT)
+ {
+ op = XEXP (op, 0);
+ switch (INTVAL (XEXP (op, 2)))
+ {
+ case 0:
+ fprintf (file, "#lo (");
+ msp430_print_operand_raw (file, XEXP (op, 0));
+ fprintf (file, ")");
+ break;
+
+ case 16:
+ fprintf (file, "#hi (");
+ msp430_print_operand_raw (file, XEXP (op, 0));
+ fprintf (file, ")");
+ break;
+
+ default:
+ output_operand_lossage ("invalid zero extract");
+ break;
+ }
+ break;
+ }
+ /* Fall through. */
+ case CONST_INT:
case SYMBOL_REF:
case LABEL_REF:
if (letter == 0)
diff --git a/gcc/config/msp430/msp430.h b/gcc/config/msp430/msp430.h
index 65d6ad66df2..044e558a3d4 100644
--- a/gcc/config/msp430/msp430.h
+++ b/gcc/config/msp430/msp430.h
@@ -55,8 +55,8 @@ extern bool msp430x;
"%{mcpu=*:-mcpu=%*}%{!mcpu=*:%{mmcu=*:-mmcu=%*}} " /* Pass the CPU type on to the assembler. */ \
"%{mrelax=-mQ} " /* Pass the relax option on to the assembler. */ \
"%{mlarge:-ml} " /* Tell the assembler if we are building for the LARGE pointer model. */ \
- "%{!msim:-md} %{msim:%{mlarge:-md}}" /* Copy data from ROM to RAM if necessary. */ \
- "%{ffunction-sections:-gdwarf-sections}" /* If function sections are being created then create DWARF line number sections as well. */
+ "%{!msim:-md} %{msim:%{mlarge:-md}} " /* Copy data from ROM to RAM if necessary. */ \
+ "%{ffunction-sections:-gdwarf-sections} " /* If function sections are being created then create DWARF line number sections as well. */
/* Enable linker section garbage collection by default, unless we
are creating a relocatable binary (gc does not work) or debugging
diff --git a/gcc/config/msp430/msp430.md b/gcc/config/msp430/msp430.md
index 74a98b48019..d2cc0d63170 100644
--- a/gcc/config/msp430/msp430.md
+++ b/gcc/config/msp430/msp430.md
@@ -47,6 +47,15 @@
UNS_BIS_SR
UNS_REFSYM_NEED_EXIT
+
+ UNS_DELAY_32
+ UNS_DELAY_32X
+ UNS_DELAY_16
+ UNS_DELAY_16X
+ UNS_DELAY_2
+ UNS_DELAY_1
+ UNS_DELAY_START
+ UNS_DELAY_END
])
(include "predicates.md")
@@ -362,8 +371,8 @@
; halves.
(define_split
[(set (match_operand:SI 0 "msp430_nonsubreg_operand")
- (plus:SI (match_operand:SI 1 "nonimmediate_operand")
- (match_operand:SI 2 "general_operand")))
+ (plus:SI (match_operand:SI 1 "msp430_nonsubreg_operand")
+ (match_operand:SI 2 "msp430_nonsubreg_or_imm_operand")))
]
""
[(parallel [(set (match_operand:HI 3 "nonimmediate_operand" "=&rm")
@@ -609,9 +618,15 @@
; when the PSI value is negative..
;
; Note: using PUSHM.A #1 is two bytes smaller than using PUSHX.A....
+;
+; Note: We use a + constraint on operand 0 as otherwise GCC gets confused
+; about extending a single PSI mode register into a pair of SImode registers
+; with the same starting register. It thinks that the upper register of
+; the pair is unused and so it can clobber it. Try compiling 20050826-2.c
+; at -O2 to see this.
(define_insn "zero_extendpsisi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
+ [(set (match_operand:SI 0 "register_operand" "+r")
(zero_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
""
"*
@@ -1311,12 +1326,96 @@
""
"*
if (REGNO (operands[0]) != REGNO (operands[1]))
- return \"MOV.W\t%1, %0 { SUB.W\t#0, %0 { AND.W\t%2, %0\";
+ return \"MOV.W\t%1, %0 { INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\";
else
- return \"SUB.W\t#0, %0 { AND.W\t%2, %0\";
+ return \"INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\";
"
)
+(define_insn "delay_cycles_start"
+ [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
+ UNS_DELAY_START)]
+ ""
+ "; Begin %J0 cycle delay"
+ )
+
+(define_insn "delay_cycles_end"
+ [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
+ UNS_DELAY_END)]
+ ""
+ "; End %J0 cycle delay"
+ )
+
+(define_insn "delay_cycles_32"
+ [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
+ (match_operand 1 "immediate_operand" "i")
+ ] UNS_DELAY_32)]
+ ""
+ "PUSH r13
+ PUSH r14
+ MOV.W %A0, r13
+ MOV.W %B0, r14
+1: SUB.W #1, r13
+ SUBC.W #0, r14
+ JNE 1b
+ TST.W r13
+ JNE 1b
+ POP r14
+ POP r13"
+ )
+
+(define_insn "delay_cycles_32x"
+ [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
+ (match_operand 1 "immediate_operand" "i")
+ ] UNS_DELAY_32X)]
+ ""
+ "PUSHM.A #2,r13
+ MOV.W %A0, r13
+ MOV.W %B0, r14
+1: SUB.W #1, r13
+ SUBC.W #0, r14
+ JNE 1b
+ TST.W r13
+ JNE 1b
+ POPM.A #2,r13"
+ )
+
+(define_insn "delay_cycles_16"
+ [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
+ (match_operand 1 "immediate_operand" "i")
+ ] UNS_DELAY_16)]
+ ""
+ "PUSH r13
+ MOV.W %0, r13
+1: SUB.W #1, r13
+ JNE 1b
+ POP r13"
+ )
+
+(define_insn "delay_cycles_16x"
+ [(unspec_volatile [(match_operand 0 "immediate_operand" "i")
+ (match_operand 1 "immediate_operand" "i")
+ ] UNS_DELAY_16X)]
+ ""
+ "PUSHM.A #1,r13
+ MOV.W %0, r13
+1: SUB.W #1, r13
+ JNE 1b
+ POPM.A #1,r13"
+ )
+
+(define_insn "delay_cycles_2"
+ [(unspec_volatile [(const_int 0) ] UNS_DELAY_2)]
+ ""
+ "JMP .+2"
+ )
+
+(define_insn "delay_cycles_1"
+ [(unspec_volatile [(const_int 0) ] UNS_DELAY_1)]
+ ""
+ "NOP"
+ )
+
(define_insn "mulhisi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
diff --git a/gcc/config/msp430/predicates.md b/gcc/config/msp430/predicates.md
index 9a8e2da0aa1..94a628cd5c4 100644
--- a/gcc/config/msp430/predicates.md
+++ b/gcc/config/msp430/predicates.md
@@ -73,6 +73,10 @@
(define_predicate "msp430_nonsubreg_operand"
(match_code "reg,mem"))
+(define_predicate "msp430_nonsubreg_or_imm_operand"
+ (ior (match_operand 0 "msp430_nonsubreg_operand")
+ (match_operand 0 "immediate_operand")))
+
; TRUE for constants which are bit positions for zero_extract
(define_predicate "msp430_bitpos"
(and (match_code "const_int")
diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
index 6e5595c09f5..8516221b25d 100644
--- a/gcc/config/nds32/nds32.c
+++ b/gcc/config/nds32/nds32.c
@@ -50,6 +50,7 @@
#include "target-def.h"
#include "langhooks.h" /* For add_builtin_function(). */
#include "ggc.h"
+#include "builtins.h"
/* ------------------------------------------------------------------------ */
@@ -131,7 +132,7 @@ static struct machine_function *
nds32_init_machine_status (void)
{
struct machine_function *machine;
- machine = ggc_alloc_cleared_machine_function ();
+ machine = ggc_cleared_alloc<machine_function> ();
/* Initially assume this function needs prologue/epilogue. */
machine->naked_p = 0;
diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md
index 0402cadd6b2..da3a97a538f 100644
--- a/gcc/config/nds32/nds32.md
+++ b/gcc/config/nds32/nds32.md
@@ -261,7 +261,7 @@
(define_insn "add<mode>3"
[(set (match_operand:QIHISI 0 "register_operand" "= d, l, d, l, d, l, k, l, r, r")
- (plus:QIHISI (match_operand:QIHISI 1 "register_operand" " 0, l, 0, l, %0, l, 0, k, r, r")
+ (plus:QIHISI (match_operand:QIHISI 1 "register_operand" "% 0, l, 0, l, 0, l, 0, k, r, r")
(match_operand:QIHISI 2 "nds32_rimm15s_operand" " In05, In03, Iu05, Iu03, r, l, Is10, Iu06, Is15, r")))]
""
{
@@ -382,9 +382,9 @@
;; Multiplication instructions.
(define_insn "mulsi3"
- [(set (match_operand:SI 0 "register_operand" "= w, r")
- (mult:SI (match_operand:SI 1 "register_operand" " %0, r")
- (match_operand:SI 2 "register_operand" " w, r")))]
+ [(set (match_operand:SI 0 "register_operand" "=w, r")
+ (mult:SI (match_operand:SI 1 "register_operand" "%0, r")
+ (match_operand:SI 2 "register_operand" " w, r")))]
""
"@
mul33\t%0, %2
@@ -489,9 +489,9 @@
)
(define_insn "andsi3"
- [(set (match_operand:SI 0 "register_operand" "= w, r, l, l, l, l, l, l, r, r, r, r, r")
- (and:SI (match_operand:SI 1 "register_operand" " %0, r, l, l, l, l, 0, 0, r, r, r, r, r")
- (match_operand:SI 2 "general_operand" " w, r, Izeb, Izeh, Ixls, Ix11, Ibms, Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))]
+ [(set (match_operand:SI 0 "register_operand" "=w, r, l, l, l, l, l, l, r, r, r, r, r")
+ (and:SI (match_operand:SI 1 "register_operand" "%0, r, l, l, l, l, 0, 0, r, r, r, r, r")
+ (match_operand:SI 2 "general_operand" " w, r, Izeb, Izeh, Ixls, Ix11, Ibms, Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))]
""
{
HOST_WIDE_INT mask = INTVAL (operands[2]);
@@ -585,9 +585,9 @@
;; For V3/V3M ISA, we have 'or33' instruction.
;; So we can identify 'or Rt3,Rt3,Ra3' case and set its length to be 2.
(define_insn "iorsi3"
- [(set (match_operand:SI 0 "register_operand" "= w, r, r, r")
- (ior:SI (match_operand:SI 1 "register_operand" " %0, r, r, r")
- (match_operand:SI 2 "general_operand" " w, r, Iu15, Ie15")))]
+ [(set (match_operand:SI 0 "register_operand" "=w, r, r, r")
+ (ior:SI (match_operand:SI 1 "register_operand" "%0, r, r, r")
+ (match_operand:SI 2 "general_operand" " w, r, Iu15, Ie15")))]
""
{
int one_position;
@@ -645,9 +645,9 @@
;; For V3/V3M ISA, we have 'xor33' instruction.
;; So we can identify 'xor Rt3,Rt3,Ra3' case and set its length to be 2.
(define_insn "xorsi3"
- [(set (match_operand:SI 0 "register_operand" "= w, r, r, r")
- (xor:SI (match_operand:SI 1 "register_operand" " %0, r, r, r")
- (match_operand:SI 2 "general_operand" " w, r, Iu15, It15")))]
+ [(set (match_operand:SI 0 "register_operand" "=w, r, r, r")
+ (xor:SI (match_operand:SI 1 "register_operand" "%0, r, r, r")
+ (match_operand:SI 2 "general_operand" " w, r, Iu15, It15")))]
""
{
int one_position;
diff --git a/gcc/config/newlib-stdint.h b/gcc/config/newlib-stdint.h
index f4a78a54492..47445e42d94 100644
--- a/gcc/config/newlib-stdint.h
+++ b/gcc/config/newlib-stdint.h
@@ -13,8 +13,13 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* newlib uses 32-bit long in certain cases for all non-SPU
diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
index 548a8d27471..ff3536d1c21 100644
--- a/gcc/config/nios2/nios2.c
+++ b/gcc/config/nios2/nios2.c
@@ -986,7 +986,7 @@ nios2_handle_custom_fpu_insn_option (int fpu_insn_index)
static struct machine_function *
nios2_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* Implement TARGET_OPTION_OVERRIDE. */
diff --git a/gcc/config/nios2/nios2.md b/gcc/config/nios2/nios2.md
index e3a803c59b5..4057feb7ddc 100644
--- a/gcc/config/nios2/nios2.md
+++ b/gcc/config/nios2/nios2.md
@@ -877,8 +877,8 @@
[(set_attr "type" "control")
(set (attr "length")
(if_then_else
- (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
- (le (minus (match_dup 1) (pc)) (const_int 32764)))
+ (and (ge (minus (match_dup 3) (pc)) (const_int -32768))
+ (le (minus (match_dup 3) (pc)) (const_int 32764)))
(const_int 4) (const_int 8)))])
;; Floating point comparisons
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 871e4e5c6e8..fe3881e8092 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "df.h"
#include "opts.h"
+#include "builtins.h"
/* Return nonzero if there is a bypass for the output of
OUT_INSN and the fp store IN_INSN. */
@@ -668,7 +669,7 @@ pa_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
static struct machine_function *
pa_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* If FROM is a probable pointer register, mark TO as a probable
@@ -5583,7 +5584,7 @@ pa_get_deferred_plabel (rtx symbol)
tree id;
if (deferred_plabels == 0)
- deferred_plabels = ggc_alloc_deferred_plabel ();
+ deferred_plabels = ggc_alloc<deferred_plabel> ();
else
deferred_plabels = GGC_RESIZEVEC (struct deferred_plabel,
deferred_plabels,
diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c
index 677160aac3d..f10d28a2560 100644
--- a/gcc/config/pdp11/pdp11.c
+++ b/gcc/config/pdp11/pdp11.c
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see
#include "df.h"
#include "opts.h"
#include "dbxout.h"
+#include "builtins.h"
/* this is the current value returned by the macro FIRST_PARM_OFFSET
defined in tm.h */
diff --git a/gcc/config/picochip/picochip.c b/gcc/config/picochip/picochip.c
index 8738564d3fc..6433acb49d5 100644
--- a/gcc/config/picochip/picochip.c
+++ b/gcc/config/picochip/picochip.c
@@ -65,6 +65,7 @@ along with GCC; see the file COPYING3. If not, see
#include "libfuncs.h" /* For memcpy_libfuncs, etc. */
#include "df.h" /* For df_regs_ever_live_df_regs_ever_live_pp, etc. */
#include "dbxout.h"
+#include "builtins.h"
/* Target AE ISA information. */
diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c
index 0731491a23f..b9e6d00ad73 100644
--- a/gcc/config/rl78/rl78.c
+++ b/gcc/config/rl78/rl78.c
@@ -55,6 +55,7 @@
#include "context.h"
#include "tm-constrs.h" /* for satisfies_constraint_*(). */
#include "insn-flags.h" /* for gen_*(). */
+#include "builtins.h"
static inline bool is_interrupt_func (const_tree decl);
static inline bool is_brk_interrupt_func (const_tree decl);
@@ -111,7 +112,7 @@ rl78_init_machine_status (void)
{
struct machine_function *m;
- m = ggc_alloc_cleared_machine_function ();
+ m = ggc_cleared_alloc<machine_function> ();
m->virt_insns_ok = 1;
return m;
diff --git a/gcc/config/rs6000/40x.md b/gcc/config/rs6000/40x.md
index b2a83b163f7..b29e06a02f3 100644
--- a/gcc/config/rs6000/40x.md
+++ b/gcc/config/rs6000/40x.md
@@ -26,19 +26,19 @@
;; In-order execution
;; Max issue two insns/cycle (includes one branch)
(define_insn_reservation "ppc403-load" 2
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
- load_l,store_c,sync")
+ (and (eq_attr "type" "load,load_l,store_c,sync")
(eq_attr "cpu" "ppc403,ppc405"))
"iu_40x")
(define_insn_reservation "ppc403-store" 2
- (and (eq_attr "type" "store,store_ux,store_u")
+ (and (eq_attr "type" "store")
(eq_attr "cpu" "ppc403,ppc405"))
"iu_40x")
(define_insn_reservation "ppc403-integer" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,shift,trap,\
- var_shift_rotate,cntlz,exts,isel")
+ (and (ior (eq_attr "type" "integer,insert,trap,cntlz,exts,isel")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no")))
(eq_attr "cpu" "ppc403,ppc405"))
"iu_40x")
@@ -53,33 +53,38 @@
"iu_40x,iu_40x,iu_40x")
(define_insn_reservation "ppc403-compare" 3
- (and (eq_attr "type" "cmp,fast_compare,compare,delayed_compare,\
- var_delayed_compare")
+ (and (ior (eq_attr "type" "cmp,compare")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "ppc403,ppc405"))
"iu_40x,nothing,bpu_40x")
(define_insn_reservation "ppc403-imul" 4
- (and (eq_attr "type" "imul,imul2,imul3,imul_compare")
+ (and (eq_attr "type" "mul")
(eq_attr "cpu" "ppc403"))
"iu_40x*4")
(define_insn_reservation "ppc405-imul" 5
- (and (eq_attr "type" "imul,imul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "32")
(eq_attr "cpu" "ppc405"))
"iu_40x*4")
(define_insn_reservation "ppc405-imul2" 3
- (and (eq_attr "type" "imul2")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "16")
(eq_attr "cpu" "ppc405"))
"iu_40x*2")
(define_insn_reservation "ppc405-imul3" 2
- (and (eq_attr "type" "imul3")
+ (and (ior (eq_attr "type" "halfmul")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "8")))
(eq_attr "cpu" "ppc405"))
"iu_40x")
(define_insn_reservation "ppc403-idiv" 33
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
(eq_attr "cpu" "ppc403,ppc405"))
"iu_40x*33")
@@ -114,7 +119,6 @@
"bpu_40x")
(define_insn_reservation "ppc405-float" 11
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,\
- fpcompare,fp,dmul,sdiv,ddiv")
+ (and (eq_attr "type" "fpload,fpstore,fpcompare,fp,dmul,sdiv,ddiv")
(eq_attr "cpu" "ppc405"))
"fpu_405*10")
diff --git a/gcc/config/rs6000/440.md b/gcc/config/rs6000/440.md
index 7ca209b683e..f956bd65aac 100644
--- a/gcc/config/rs6000/440.md
+++ b/gcc/config/rs6000/440.md
@@ -33,29 +33,29 @@
(define_insn_reservation "ppc440-load" 3
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
- load_l,store_c,sync")
+ (and (eq_attr "type" "load,load_l,store_c,sync")
(eq_attr "cpu" "ppc440"))
"ppc440_issue,ppc440_l_pipe")
(define_insn_reservation "ppc440-store" 3
- (and (eq_attr "type" "store,store_ux,store_u")
+ (and (eq_attr "type" "store")
(eq_attr "cpu" "ppc440"))
"ppc440_issue,ppc440_l_pipe")
(define_insn_reservation "ppc440-fpload" 4
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "ppc440"))
"ppc440_issue,ppc440_l_pipe")
(define_insn_reservation "ppc440-fpstore" 3
- (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "fpstore")
(eq_attr "cpu" "ppc440"))
"ppc440_issue,ppc440_l_pipe")
(define_insn_reservation "ppc440-integer" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,shift,\
- trap,var_shift_rotate,cntlz,exts,isel")
+ (and (ior (eq_attr "type" "integer,insert,trap,cntlz,exts,isel")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no")))
(eq_attr "cpu" "ppc440"))
"ppc440_issue,ppc440_i_pipe|ppc440_j_pipe")
@@ -72,17 +72,20 @@
ppc440_i_pipe|ppc440_j_pipe,ppc440_i_pipe|ppc440_j_pipe")
(define_insn_reservation "ppc440-imul" 3
- (and (eq_attr "type" "imul,imul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "32")
(eq_attr "cpu" "ppc440"))
"ppc440_issue,ppc440_i_pipe")
(define_insn_reservation "ppc440-imul2" 2
- (and (eq_attr "type" "imul2,imul3")
+ (and (ior (eq_attr "type" "halfmul")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "8,16")))
(eq_attr "cpu" "ppc440"))
"ppc440_issue,ppc440_i_pipe")
(define_insn_reservation "ppc440-idiv" 34
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
(eq_attr "cpu" "ppc440"))
"ppc440_issue,ppc440_i_pipe*33")
@@ -92,7 +95,9 @@
"ppc440_issue,ppc440_i_pipe")
(define_insn_reservation "ppc440-compare" 2
- (and (eq_attr "type" "cmp,fast_compare,compare,cr_logical,delayed_cr,mfcr")
+ (and (ior (eq_attr "type" "cmp,compare,cr_logical,delayed_cr,mfcr")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "ppc440"))
"ppc440_issue,ppc440_i_pipe")
diff --git a/gcc/config/rs6000/476.md b/gcc/config/rs6000/476.md
index 3921bbd9808..4c879f467ac 100644
--- a/gcc/config/rs6000/476.md
+++ b/gcc/config/rs6000/476.md
@@ -39,32 +39,33 @@
(define_reservation "ppc476_issue3" "ppc476_issue_0+ppc476_issue_1+ppc476_issue_2")
(define_insn_reservation "ppc476-load" 4
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
- load_l,store_c,sync")
+ (and (eq_attr "type" "load,load_l,store_c,sync")
(eq_attr "cpu" "ppc476"))
"ppc476_issue,\
ppc476_lj_pipe")
(define_insn_reservation "ppc476-store" 4
- (and (eq_attr "type" "store,store_ux,store_u")
+ (and (eq_attr "type" "store")
(eq_attr "cpu" "ppc476"))
"ppc476_issue,\
ppc476_lj_pipe")
(define_insn_reservation "ppc476-fpload" 4
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "ppc476"))
"ppc476_issue,\
ppc476_lj_pipe")
(define_insn_reservation "ppc476-fpstore" 4
- (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "fpstore")
(eq_attr "cpu" "ppc476"))
"ppc476_issue,\
ppc476_lj_pipe")
(define_insn_reservation "ppc476-simple-integer" 1
- (and (eq_attr "type" "integer,insert_word,var_shift_rotate,exts,shift")
+ (and (ior (eq_attr "type" "integer,insert,exts")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no")))
(eq_attr "cpu" "ppc476"))
"ppc476_issue,\
ppc476_i_pipe|ppc476_lj_pipe")
@@ -76,20 +77,21 @@
ppc476_i_pipe")
(define_insn_reservation "ppc476-compare" 4
- (and (eq_attr "type" "compare,delayed_compare,fast_compare,mfcr,mfcrf,\
- mtcr,mfjmpr,mtjmpr,var_delayed_compare")
+ (and (ior (eq_attr "type" "compare,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "ppc476"))
"ppc476_issue,\
ppc476_i_pipe")
(define_insn_reservation "ppc476-imul" 4
- (and (eq_attr "type" "imul,imul_compare,imul2,imul3")
+ (and (eq_attr "type" "mul,halfmul")
(eq_attr "cpu" "ppc476"))
"ppc476_issue,\
ppc476_i_pipe")
(define_insn_reservation "ppc476-idiv" 11
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
(eq_attr "cpu" "ppc476"))
"ppc476_issue,\
ppc476_i_pipe*11")
diff --git a/gcc/config/rs6000/601.md b/gcc/config/rs6000/601.md
index d2f6825e569..e8207a8ecf7 100644
--- a/gcc/config/rs6000/601.md
+++ b/gcc/config/rs6000/601.md
@@ -25,29 +25,29 @@
;; PPC601 32-bit IU, FPU, BPU
(define_insn_reservation "ppc601-load" 2
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
- load_l,store_c,sync")
+ (and (eq_attr "type" "load,load_l,store_c,sync")
(eq_attr "cpu" "ppc601"))
"iu_ppc601")
(define_insn_reservation "ppc601-store" 2
- (and (eq_attr "type" "store,store_ux,store_u")
+ (and (eq_attr "type" "store")
(eq_attr "cpu" "ppc601"))
"iu_ppc601")
(define_insn_reservation "ppc601-fpload" 3
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "ppc601"))
"iu_ppc601")
(define_insn_reservation "ppc601-fpstore" 3
- (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "fpstore")
(eq_attr "cpu" "ppc601"))
"iu_ppc601+fpu_ppc601")
(define_insn_reservation "ppc601-integer" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,shift,\
- trap,var_shift_rotate,cntlz,exts,isel")
+ (and (ior (eq_attr "type" "integer,add,insert,trap,cntlz,exts,isel")
+ (and (eq_attr "type" "shift")
+ (eq_attr "dot" "no")))
(eq_attr "cpu" "ppc601"))
"iu_ppc601")
@@ -62,20 +62,21 @@
"iu_ppc601,iu_ppc601,iu_ppc601")
(define_insn_reservation "ppc601-imul" 5
- (and (eq_attr "type" "imul,imul2,imul3,imul_compare")
+ (and (eq_attr "type" "mul")
(eq_attr "cpu" "ppc601"))
"iu_ppc601*5")
(define_insn_reservation "ppc601-idiv" 36
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
(eq_attr "cpu" "ppc601"))
"iu_ppc601*36")
; compare executes on integer unit, but feeds insns which
; execute on the branch unit.
(define_insn_reservation "ppc601-compare" 3
- (and (eq_attr "type" "cmp,compare,delayed_compare,\
- var_delayed_compare")
+ (and (ior (eq_attr "type" "cmp,compare")
+ (and (eq_attr "type" "shift")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "ppc601"))
"iu_ppc601,nothing,bpu_ppc601")
diff --git a/gcc/config/rs6000/603.md b/gcc/config/rs6000/603.md
index 1b4141c14c8..871957aa560 100644
--- a/gcc/config/rs6000/603.md
+++ b/gcc/config/rs6000/603.md
@@ -38,17 +38,17 @@
;; CR insns get executed in the SRU. Not modelled.
(define_insn_reservation "ppc603-load" 2
- (and (eq_attr "type" "load,load_ext,load_ux,load_u,load_l")
+ (and (eq_attr "type" "load,load_l")
(eq_attr "cpu" "ppc603"))
"lsu_603")
(define_insn_reservation "ppc603-store" 2
- (and (eq_attr "type" "store,store_ux,store_u,fpstore,fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "store,fpstore")
(eq_attr "cpu" "ppc603"))
"lsu_603*2")
(define_insn_reservation "ppc603-fpload" 2
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "ppc603"))
"lsu_603")
@@ -58,8 +58,9 @@
"lsu_603")
(define_insn_reservation "ppc603-integer" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,shift,trap,\
- var_shift_rotate,cntlz,exts,isel")
+ (and (ior (eq_attr "type" "integer,insert,trap,cntlz,exts,isel")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no")))
(eq_attr "cpu" "ppc603"))
"iu_603")
@@ -75,23 +76,26 @@
; This takes 2 or 3 cycles
(define_insn_reservation "ppc603-imul" 3
- (and (eq_attr "type" "imul,imul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "32")
(eq_attr "cpu" "ppc603"))
"iu_603*2")
(define_insn_reservation "ppc603-imul2" 2
- (and (eq_attr "type" "imul2,imul3")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "8,16")
(eq_attr "cpu" "ppc603"))
"iu_603*2")
(define_insn_reservation "ppc603-idiv" 37
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
(eq_attr "cpu" "ppc603"))
"iu_603*37")
(define_insn_reservation "ppc603-compare" 3
- (and (eq_attr "type" "cmp,fast_compare,compare,delayed_compare,\
- var_delayed_compare")
+ (and (ior (eq_attr "type" "cmp,compare")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "ppc603"))
"iu_603,nothing,bpu_603")
diff --git a/gcc/config/rs6000/6xx.md b/gcc/config/rs6000/6xx.md
index 65e06674ac1..9d6ba050063 100644
--- a/gcc/config/rs6000/6xx.md
+++ b/gcc/config/rs6000/6xx.md
@@ -48,17 +48,17 @@
;; Four insns can be dispatched per cycle.
(define_insn_reservation "ppc604-load" 2
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u")
+ (and (eq_attr "type" "load")
(eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
"lsu_6xx")
(define_insn_reservation "ppc604-fpload" 3
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
"lsu_6xx")
(define_insn_reservation "ppc604-store" 3
- (and (eq_attr "type" "store,fpstore,store_ux,store_u,fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "store,fpstore")
(eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
"lsu_6xx")
@@ -73,8 +73,9 @@
"lsu_6xx")
(define_insn_reservation "ppc604-integer" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,shift,trap,\
- var_shift_rotate,cntlz,exts,isel")
+ (and (ior (eq_attr "type" "integer,insert,trap,cntlz,exts,isel")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no")))
(eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
"iu1_6xx|iu2_6xx")
@@ -89,58 +90,66 @@
"iu1_6xx|iu2_6xx,iu1_6xx|iu2_6xx,iu1_6xx|iu2_6xx")
(define_insn_reservation "ppc604-imul" 4
- (and (eq_attr "type" "imul,imul2,imul3,imul_compare")
+ (and (eq_attr "type" "mul")
(eq_attr "cpu" "ppc604"))
"mciu_6xx*2")
(define_insn_reservation "ppc604e-imul" 2
- (and (eq_attr "type" "imul,imul2,imul3,imul_compare")
+ (and (eq_attr "type" "mul")
(eq_attr "cpu" "ppc604e"))
"mciu_6xx")
(define_insn_reservation "ppc620-imul" 5
- (and (eq_attr "type" "imul,imul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "32")
(eq_attr "cpu" "ppc620,ppc630"))
"mciu_6xx*3")
(define_insn_reservation "ppc620-imul2" 4
- (and (eq_attr "type" "imul2")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "16")
(eq_attr "cpu" "ppc620,ppc630"))
"mciu_6xx*3")
(define_insn_reservation "ppc620-imul3" 3
- (and (eq_attr "type" "imul3")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "8")
(eq_attr "cpu" "ppc620,ppc630"))
"mciu_6xx*3")
(define_insn_reservation "ppc620-lmul" 7
- (and (eq_attr "type" "lmul,lmul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "64")
(eq_attr "cpu" "ppc620,ppc630"))
"mciu_6xx*5")
(define_insn_reservation "ppc604-idiv" 20
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
(eq_attr "cpu" "ppc604,ppc604e"))
"mciu_6xx*19")
(define_insn_reservation "ppc620-idiv" 37
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "32")
(eq_attr "cpu" "ppc620"))
"mciu_6xx*36")
(define_insn_reservation "ppc630-idiv" 21
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "32")
(eq_attr "cpu" "ppc630"))
"mciu_6xx*20")
(define_insn_reservation "ppc620-ldiv" 37
- (and (eq_attr "type" "ldiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "64")
(eq_attr "cpu" "ppc620,ppc630"))
"mciu_6xx*36")
(define_insn_reservation "ppc604-compare" 3
- (and (eq_attr "type" "cmp,fast_compare,compare,delayed_compare,\
- var_delayed_compare")
+ (and (ior (eq_attr "type" "cmp,compare")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
"(iu1_6xx|iu2_6xx)")
diff --git a/gcc/config/rs6000/7450.md b/gcc/config/rs6000/7450.md
index 7a9bbdd5f89..4271efaa10b 100644
--- a/gcc/config/rs6000/7450.md
+++ b/gcc/config/rs6000/7450.md
@@ -43,23 +43,22 @@
(define_reservation "ppc7450_vec_du" "vdu1_7450|vdu2_7450")
(define_insn_reservation "ppc7450-load" 3
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,\
- load_ux,load_u,vecload")
+ (and (eq_attr "type" "load,vecload")
(eq_attr "cpu" "ppc7450"))
"ppc7450_du,lsu_7450")
(define_insn_reservation "ppc7450-store" 3
- (and (eq_attr "type" "store,store_ux,store_u,vecstore")
+ (and (eq_attr "type" "store,vecstore")
(eq_attr "cpu" "ppc7450"))
"ppc7450_du,lsu_7450")
(define_insn_reservation "ppc7450-fpload" 4
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "ppc7450"))
"ppc7450_du,lsu_7450")
(define_insn_reservation "ppc7450-fpstore" 3
- (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "fpstore")
(eq_attr "cpu" "ppc7450"))
"ppc7450_du,lsu_7450*3")
@@ -74,8 +73,9 @@
"ppc7450_du,lsu_7450")
(define_insn_reservation "ppc7450-integer" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,shift,\
- trap,var_shift_rotate,cntlz,exts,isel")
+ (and (ior (eq_attr "type" "integer,insert,trap,cntlz,exts,isel")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no")))
(eq_attr "cpu" "ppc7450"))
"ppc7450_du,iu1_7450|iu2_7450|iu3_7450")
@@ -91,23 +91,26 @@
iu1_7450|iu2_7450|iu3_7450,iu1_7450|iu2_7450|iu3_7450")
(define_insn_reservation "ppc7450-imul" 4
- (and (eq_attr "type" "imul,imul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "32")
(eq_attr "cpu" "ppc7450"))
"ppc7450_du,mciu_7450*2")
(define_insn_reservation "ppc7450-imul2" 3
- (and (eq_attr "type" "imul2,imul3")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "8,16")
(eq_attr "cpu" "ppc7450"))
"ppc7450_du,mciu_7450")
(define_insn_reservation "ppc7450-idiv" 23
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
(eq_attr "cpu" "ppc7450"))
"ppc7450_du,mciu_7450*23")
(define_insn_reservation "ppc7450-compare" 2
- (and (eq_attr "type" "cmp,fast_compare,compare,delayed_compare,\
- var_delayed_compare")
+ (and (ior (eq_attr "type" "cmp,compare")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "ppc7450"))
"ppc7450_du,(iu1_7450|iu2_7450|iu3_7450)")
diff --git a/gcc/config/rs6000/7xx.md b/gcc/config/rs6000/7xx.md
index 30c2d26484f..aba4a770ec3 100644
--- a/gcc/config/rs6000/7xx.md
+++ b/gcc/config/rs6000/7xx.md
@@ -46,15 +46,12 @@
(define_reservation "ppc7400_vec_du" "vdu_7xx")
(define_insn_reservation "ppc750-load" 2
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,\
- load_ux,load_u,fpload,fpload_ux,fpload_u,\
- vecload,load_l")
+ (and (eq_attr "type" "load,fpload,vecload,load_l")
(eq_attr "cpu" "ppc750,ppc7400"))
"ppc750_du,lsu_7xx")
(define_insn_reservation "ppc750-store" 2
- (and (eq_attr "type" "store,store_ux,store_u,\
- fpstore,fpstore_ux,fpstore_u,vecstore")
+ (and (eq_attr "type" "store,fpstore,vecstore")
(eq_attr "cpu" "ppc750,ppc7400"))
"ppc750_du,lsu_7xx")
@@ -64,8 +61,9 @@
"ppc750_du,lsu_7xx")
(define_insn_reservation "ppc750-integer" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,shift,\
- trap,var_shift_rotate,cntlz,exts,isel")
+ (and (ior (eq_attr "type" "integer,insert,trap,cntlz,exts,isel")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no")))
(eq_attr "cpu" "ppc750,ppc7400"))
"ppc750_du,iu1_7xx|iu2_7xx")
@@ -80,28 +78,32 @@
"ppc750_du,iu1_7xx|iu2_7xx,iu1_7xx|iu2_7xx,iu1_7xx|iu2_7xx")
(define_insn_reservation "ppc750-imul" 4
- (and (eq_attr "type" "imul,imul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "32")
(eq_attr "cpu" "ppc750,ppc7400"))
"ppc750_du,iu1_7xx*4")
(define_insn_reservation "ppc750-imul2" 3
- (and (eq_attr "type" "imul2")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "16")
(eq_attr "cpu" "ppc750,ppc7400"))
"ppc750_du,iu1_7xx*2")
(define_insn_reservation "ppc750-imul3" 2
- (and (eq_attr "type" "imul3")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "8")
(eq_attr "cpu" "ppc750,ppc7400"))
"ppc750_du,iu1_7xx")
(define_insn_reservation "ppc750-idiv" 19
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
(eq_attr "cpu" "ppc750,ppc7400"))
"ppc750_du,iu1_7xx*19")
(define_insn_reservation "ppc750-compare" 2
- (and (eq_attr "type" "cmp,fast_compare,compare,delayed_compare,\
- var_delayed_compare")
+ (and (ior (eq_attr "type" "cmp,compare")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "ppc750,ppc7400"))
"ppc750_du,(iu1_7xx|iu2_7xx)")
diff --git a/gcc/config/rs6000/8540.md b/gcc/config/rs6000/8540.md
index 7913bcdd15c..90a3d27d4d9 100644
--- a/gcc/config/rs6000/8540.md
+++ b/gcc/config/rs6000/8540.md
@@ -84,9 +84,8 @@
;; Simple SU insns
(define_insn_reservation "ppc8540_su" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,cmp,compare,\
- delayed_compare,var_delayed_compare,fast_compare,\
- shift,trap,var_shift_rotate,cntlz,exts,isel")
+ (and (eq_attr "type" "integer,add,logical,insert,cmp,compare,\
+ shift,trap,cntlz,exts,isel")
(eq_attr "cpu" "ppc8540,ppc8548"))
"ppc8540_decode,ppc8540_issue+ppc8540_su_stage0+ppc8540_retire")
@@ -111,7 +110,7 @@
;; Multiply
(define_insn_reservation "ppc8540_multiply" 4
- (and (eq_attr "type" "imul,imul2,imul3,imul_compare")
+ (and (eq_attr "type" "mul")
(eq_attr "cpu" "ppc8540,ppc8548"))
"ppc8540_decode,ppc8540_issue+ppc8540_mu_stage0,ppc8540_mu_stage1,\
ppc8540_mu_stage2,ppc8540_mu_stage3+ppc8540_retire")
@@ -121,7 +120,7 @@
;; reservation of miu_stage3 here because we use the average latency
;; time.
(define_insn_reservation "ppc8540_divide" 14
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
(eq_attr "cpu" "ppc8540,ppc8548"))
"ppc8540_decode,ppc8540_issue+ppc8540_mu_stage0+ppc8540_mu_div,\
ppc8540_mu_div*13")
@@ -152,14 +151,13 @@
;; Loads
(define_insn_reservation "ppc8540_load" 3
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
- load_l,sync")
+ (and (eq_attr "type" "load,load_l,sync")
(eq_attr "cpu" "ppc8540,ppc8548"))
"ppc8540_decode,ppc8540_issue+ppc8540_lsu,nothing,ppc8540_retire")
;; Stores.
(define_insn_reservation "ppc8540_store" 3
- (and (eq_attr "type" "store,store_ux,store_u,store_c")
+ (and (eq_attr "type" "store,store_c")
(eq_attr "cpu" "ppc8540,ppc8548"))
"ppc8540_decode,ppc8540_issue+ppc8540_lsu,nothing,ppc8540_retire")
diff --git a/gcc/config/rs6000/a2.md b/gcc/config/rs6000/a2.md
index b511688987b..52dbbd4735d 100644
--- a/gcc/config/rs6000/a2.md
+++ b/gcc/config/rs6000/a2.md
@@ -48,30 +48,34 @@
;; D.4.8
(define_insn_reservation "ppca2-imul" 1
- (and (eq_attr "type" "imul,imul2,imul3,imul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "8,16,32")
(eq_attr "cpu" "ppca2"))
"nothing")
;; FIXME: latency and multiplier reservation for 64-bit multiply?
(define_insn_reservation "ppca2-lmul" 6
- (and (eq_attr "type" "lmul,lmul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "64")
(eq_attr "cpu" "ppca2"))
"mult*3")
;; D.4.9
(define_insn_reservation "ppca2-idiv" 32
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "32")
(eq_attr "cpu" "ppca2"))
"mult*32")
(define_insn_reservation "ppca2-ldiv" 65
- (and (eq_attr "type" "ldiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "64")
(eq_attr "cpu" "ppca2"))
"mult*65")
;; D.4.13
(define_insn_reservation "ppca2-load" 5
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u")
+ (and (eq_attr "type" "load")
(eq_attr "cpu" "ppca2"))
"nothing")
@@ -83,13 +87,13 @@
;; D.8.4
(define_insn_reservation "ppca2-fp-load" 6
- (and (eq_attr "type" "fpload,fpload_u,fpload_ux")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "ppca2"))
"axu")
;; D.8.5
(define_insn_reservation "ppca2-fp-store" 2
- (and (eq_attr "type" "fpstore,fpstore_u,fpstore_ux")
+ (and (eq_attr "type" "fpstore")
(eq_attr "cpu" "ppca2"))
"axu")
diff --git a/gcc/config/rs6000/cell.md b/gcc/config/rs6000/cell.md
index 642d5af71e9..b37cdba0055 100644
--- a/gcc/config/rs6000/cell.md
+++ b/gcc/config/rs6000/cell.md
@@ -92,32 +92,39 @@
;; these instr are not simulated
(define_insn_reservation "cell-load" 2
(and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "no")
(eq_attr "cpu" "cell"))
"slot01,lsu_cell")
;; ldux, ldu, lbzux, lbzu, hardware breaks it down to two instrs,
;; if with 32bytes alignment, CMC
(define_insn_reservation "cell-load-ux" 2
- (and (eq_attr "type" "load_ux,load_u")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "cell"))
"slot01,fxu_cell+lsu_cell")
;; lha, lhax, lhau, lhaux, lwa, lwax, lwaux, MC, latency unknown
;; 11/7, 11/8, 11/12
(define_insn_reservation "cell-load-ext" 2
- (and (eq_attr "type" "load_ext,load_ext_u,load_ext_ux")
- (eq_attr "cpu" "cell"))
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "cpu" "cell"))
"slot01,fxu_cell+lsu_cell")
;;lfs,lfsx,lfd,lfdx, 1 cycle
(define_insn_reservation "cell-fpload" 1
(and (eq_attr "type" "fpload")
+ (eq_attr "update" "no")
(eq_attr "cpu" "cell"))
"vsu2_cell+lsu_cell+slot01")
;; lfsu,lfsux,lfdu,lfdux 1cycle(fpr) 2 cycle(gpr)
(define_insn_reservation "cell-fpload-update" 1
- (and (eq_attr "type" "fpload,fpload_u,fpload_ux")
+ (and (eq_attr "type" "fpload")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "cell"))
"fxu_cell+vsu2_cell+lsu_cell+slot01")
@@ -129,22 +136,26 @@
;;st? stw(MC)
(define_insn_reservation "cell-store" 1
(and (eq_attr "type" "store")
+ (eq_attr "update" "no")
(eq_attr "cpu" "cell"))
"lsu_cell+slot01")
;;stdux, stdu, (hardware breaks into store and add) 2 for update reg
(define_insn_reservation "cell-store-update" 1
- (and (eq_attr "type" "store_ux,store_u")
+ (and (eq_attr "type" "store")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "cell"))
"fxu_cell+lsu_cell+slot01")
(define_insn_reservation "cell-fpstore" 1
(and (eq_attr "type" "fpstore")
+ (eq_attr "update" "no")
(eq_attr "cpu" "cell"))
"vsu2_cell+lsu_cell+slot01")
(define_insn_reservation "cell-fpstore-update" 1
- (and (eq_attr "type" "fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "fpstore")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "cell"))
"vsu2_cell+fxu_cell+lsu_cell+slot01")
@@ -155,8 +166,11 @@
;; Integer latency is 2 cycles
(define_insn_reservation "cell-integer" 2
- (and (eq_attr "type" "integer,insert_dword,shift,trap,\
- var_shift_rotate,cntlz,exts,isel")
+ (and (ior (eq_attr "type" "integer,trap,cntlz,exts,isel")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no"))
+ (and (eq_attr "type" "insert")
+ (eq_attr "size" "64")))
(eq_attr "cpu" "cell"))
"slot01,fxu_cell")
@@ -174,7 +188,8 @@
;; rlwimi, alter cr0
(define_insn_reservation "cell-insert" 2
- (and (eq_attr "type" "insert_word")
+ (and (eq_attr "type" "insert")
+ (eq_attr "size" "32")
(eq_attr "cpu" "cell"))
"slot01,fxu_cell")
@@ -186,51 +201,62 @@
;; add, addo, sub, subo, alter cr0, rldcli, rlwinm
(define_insn_reservation "cell-fast-cmp" 2
- (and (and (eq_attr "type" "fast_compare,delayed_compare,compare,\
- var_delayed_compare")
- (eq_attr "cpu" "cell"))
- (eq_attr "cell_micro" "not"))
+ (and (ior (eq_attr "type" "compare")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "yes")))
+ (eq_attr "cpu" "cell")
+ (eq_attr "cell_micro" "not"))
"slot01,fxu_cell")
(define_insn_reservation "cell-cmp-microcoded" 9
- (and (and (eq_attr "type" "fast_compare,delayed_compare,compare,\
- var_delayed_compare")
- (eq_attr "cpu" "cell"))
- (eq_attr "cell_micro" "always"))
+ (and (ior (eq_attr "type" "compare")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "yes")))
+ (eq_attr "cpu" "cell")
+ (eq_attr "cell_micro" "always"))
"slot0+slot1,fxu_cell,fxu_cell*7")
;; mulld
(define_insn_reservation "cell-lmul" 15
- (and (eq_attr "type" "lmul")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "no")
+ (eq_attr "size" "64")
(eq_attr "cpu" "cell"))
"slot1,nonpipeline,nonpipeline*13")
;; mulld. is microcoded
(define_insn_reservation "cell-lmul-cmp" 22
- (and (eq_attr "type" "lmul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "yes")
+ (eq_attr "size" "64")
(eq_attr "cpu" "cell"))
"slot0+slot1,nonpipeline,nonpipeline*20")
;; mulli, 6 cycles
(define_insn_reservation "cell-imul23" 6
- (and (eq_attr "type" "imul2,imul3")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "8,16")
(eq_attr "cpu" "cell"))
"slot1,nonpipeline,nonpipeline*4")
;; mullw, 9
(define_insn_reservation "cell-imul" 9
- (and (eq_attr "type" "imul")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "no")
+ (eq_attr "size" "32")
(eq_attr "cpu" "cell"))
"slot1,nonpipeline,nonpipeline*7")
;; divide
(define_insn_reservation "cell-idiv" 32
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "32")
(eq_attr "cpu" "cell"))
"slot1,nonpipeline,nonpipeline*30")
(define_insn_reservation "cell-ldiv" 64
- (and (eq_attr "type" "ldiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "64")
(eq_attr "cpu" "cell"))
"slot1,nonpipeline,nonpipeline*62")
diff --git a/gcc/config/rs6000/dfp.md b/gcc/config/rs6000/dfp.md
index 40e27e77d23..63ae541225e 100644
--- a/gcc/config/rs6000/dfp.md
+++ b/gcc/config/rs6000/dfp.md
@@ -37,14 +37,7 @@
|| gpc_reg_operand (operands[1], SDmode))
&& TARGET_HARD_FLOAT && TARGET_FPRS"
"stfd%U0%X0 %1,%0"
- [(set (attr "type")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_u")
- (const_string "fpstore"))))
+ [(set_attr "type" "fpstore")
(set_attr "length" "4")])
(define_insn "movsd_load"
@@ -55,14 +48,7 @@
|| gpc_reg_operand (operands[1], DDmode))
&& TARGET_HARD_FLOAT && TARGET_FPRS"
"lfd%U1%X1 %0,%1"
- [(set (attr "type")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_u")
- (const_string "fpload"))))
+ [(set_attr "type" "fpload")
(set_attr "length" "4")])
;; Hardware support for decimal floating point operations.
diff --git a/gcc/config/rs6000/e300c2c3.md b/gcc/config/rs6000/e300c2c3.md
index 80b84f5f296..f80ef30df3d 100644
--- a/gcc/config/rs6000/e300c2c3.md
+++ b/gcc/config/rs6000/e300c2c3.md
@@ -83,14 +83,18 @@
;; Compares can be executed either one of the IU or SRU
(define_insn_reservation "ppce300c3_cmp" 1
- (and (eq_attr "type" "cmp,compare,delayed_compare,fast_compare")
+ (and (ior (eq_attr "type" "cmp,compare")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "yes")))
(ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3")))
"ppce300c3_decode,ppce300c3_issue+(ppce300c3_iu_stage0|ppce300c3_sru_stage0) \
+ppce300c3_retire")
;; Other one cycle IU insns
(define_insn_reservation "ppce300c3_iu" 1
- (and (eq_attr "type" "integer,insert_word,isel")
+ (and (ior (eq_attr "type" "integer,insert,isel")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no")))
(ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3")))
"ppce300c3_decode,ppce300c3_issue+ppce300c3_iu_stage0+ppce300c3_retire")
@@ -102,7 +106,7 @@
;; Multiply is non-pipelined but can be executed in any IU
(define_insn_reservation "ppce300c3_multiply" 2
- (and (eq_attr "type" "imul,imul2,imul3,imul_compare")
+ (and (eq_attr "type" "mul")
(ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3")))
"ppce300c3_decode,ppce300c3_issue+ppce300c3_iu_stage0, \
ppce300c3_iu_stage0+ppce300c3_retire")
@@ -110,7 +114,7 @@
;; Divide. We use the average latency time here. We omit reserving a
;; retire unit because of the result automata will be huge.
(define_insn_reservation "ppce300c3_divide" 20
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
(ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3")))
"ppce300c3_decode,ppce300c3_issue+ppce300c3_iu_stage0+ppce300c3_mu_div,\
ppce300c3_mu_div*19")
@@ -168,22 +172,22 @@
;; Loads
(define_insn_reservation "ppce300c3_load" 2
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u")
+ (and (eq_attr "type" "load")
(ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3")))
"ppce300c3_decode,ppce300c3_issue+ppce300c3_lsu,ppce300c3_retire")
(define_insn_reservation "ppce300c3_fpload" 2
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "ppce300c3"))
"ppce300c3_decode,ppce300c3_issue+ppce300c3_lsu,ppce300c3_retire")
;; Stores.
(define_insn_reservation "ppce300c3_store" 2
- (and (eq_attr "type" "store,store_ux,store_u")
+ (and (eq_attr "type" "store")
(ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3")))
"ppce300c3_decode,ppce300c3_issue+ppce300c3_lsu,ppce300c3_retire")
(define_insn_reservation "ppce300c3_fpstore" 2
- (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "fpstore")
(eq_attr "cpu" "ppce300c3"))
"ppce300c3_decode,ppce300c3_issue+ppce300c3_lsu,ppce300c3_retire")
diff --git a/gcc/config/rs6000/e500mc.md b/gcc/config/rs6000/e500mc.md
index 14056f7d642..2af7eb4e37a 100644
--- a/gcc/config/rs6000/e500mc.md
+++ b/gcc/config/rs6000/e500mc.md
@@ -70,9 +70,8 @@
;; Simple SU insns.
(define_insn_reservation "e500mc_su" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,cmp,compare,\
- delayed_compare,var_delayed_compare,fast_compare,\
- shift,trap,var_shift_rotate,cntlz,exts,isel")
+ (and (eq_attr "type" "integer,add,logical,insert,cmp,compare,\
+ shift,trap,cntlz,exts,isel")
(eq_attr "cpu" "ppce500mc"))
"e500mc_decode,e500mc_issue+e500mc_su_stage0+e500mc_retire")
@@ -91,14 +90,14 @@
;; Multiply.
(define_insn_reservation "e500mc_multiply" 4
- (and (eq_attr "type" "imul,imul2,imul3,imul_compare")
+ (and (eq_attr "type" "mul")
(eq_attr "cpu" "ppce500mc"))
"e500mc_decode,e500mc_issue+e500mc_mu_stage0,e500mc_mu_stage1,\
e500mc_mu_stage2,e500mc_mu_stage3+e500mc_retire")
;; Divide. We use the average latency time here.
(define_insn_reservation "e500mc_divide" 14
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
(eq_attr "cpu" "ppce500mc"))
"e500mc_decode,e500mc_issue+e500mc_mu_stage0+e500mc_mu_div,\
e500mc_mu_div*13")
@@ -141,24 +140,23 @@
;; Loads.
(define_insn_reservation "e500mc_load" 3
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
- load_l,sync")
+ (and (eq_attr "type" "load,load_l,sync")
(eq_attr "cpu" "ppce500mc"))
"e500mc_decode,e500mc_issue+e500mc_lsu,nothing,e500mc_retire")
(define_insn_reservation "e500mc_fpload" 4
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "ppce500mc"))
"e500mc_decode,e500mc_issue+e500mc_lsu,nothing*2,e500mc_retire")
;; Stores.
(define_insn_reservation "e500mc_store" 3
- (and (eq_attr "type" "store,store_ux,store_u,store_c")
+ (and (eq_attr "type" "store,store_c")
(eq_attr "cpu" "ppce500mc"))
"e500mc_decode,e500mc_issue+e500mc_lsu,nothing,e500mc_retire")
(define_insn_reservation "e500mc_fpstore" 3
- (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "fpstore")
(eq_attr "cpu" "ppce500mc"))
"e500mc_decode,e500mc_issue+e500mc_lsu,nothing,e500mc_retire")
diff --git a/gcc/config/rs6000/e500mc64.md b/gcc/config/rs6000/e500mc64.md
index 9c29a31e958..45823347ab9 100644
--- a/gcc/config/rs6000/e500mc64.md
+++ b/gcc/config/rs6000/e500mc64.md
@@ -69,18 +69,28 @@
;; Simple SU insns.
(define_insn_reservation "e500mc64_su" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,delayed_compare,\
- shift,cntlz,exts")
+ (and (ior (eq_attr "type" "integer,insert,cntlz,exts")
+ (and (eq_attr "type" "add,logical")
+ (eq_attr "dot" "no"))
+ (and (eq_attr "type" "shift")
+ (eq_attr "dot" "no")
+ (eq_attr "var_shift" "no")))
(eq_attr "cpu" "ppce500mc64"))
"e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
(define_insn_reservation "e500mc64_su2" 2
- (and (eq_attr "type" "cmp,compare,delayed_compare,fast_compare,trap")
+ (and (ior (eq_attr "type" "cmp,compare,trap")
+ (and (eq_attr "type" "add,logical")
+ (eq_attr "dot" "yes"))
+ (and (eq_attr "type" "shift")
+ (eq_attr "dot" "yes")
+ (eq_attr "var_shift" "no")))
(eq_attr "cpu" "ppce500mc64"))
"e500mc64_decode,e500mc64_issue+e500mc64_su_stage0,e500mc64_retire")
(define_insn_reservation "e500mc64_delayed" 2
- (and (eq_attr "type" "var_shift_rotate,var_delayed_compare")
+ (and (eq_attr "type" "shift")
+ (eq_attr "var_shift" "yes")
(eq_attr "cpu" "ppce500mc64"))
"e500mc64_decode,e500mc64_issue+e500mc64_su_stage0,e500mc64_retire")
@@ -99,14 +109,14 @@
;; Multiply.
(define_insn_reservation "e500mc64_multiply" 4
- (and (eq_attr "type" "imul,imul2,imul3,imul_compare")
+ (and (eq_attr "type" "mul")
(eq_attr "cpu" "ppce500mc64"))
"e500mc64_decode,e500mc64_issue+e500mc64_mu_stage0,e500mc64_mu_stage1,\
e500mc64_mu_stage2,e500mc64_mu_stage3+e500mc64_retire")
;; Divide. We use the average latency time here.
(define_insn_reservation "e500mc64_divide" 14
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
(eq_attr "cpu" "ppce500mc64"))
"e500mc64_decode,e500mc64_issue+e500mc64_mu_stage0+e500mc64_mu_div,\
e500mc64_mu_div*13")
@@ -149,24 +159,23 @@
;; Loads.
(define_insn_reservation "e500mc64_load" 3
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
- load_l,sync")
+ (and (eq_attr "type" "load,load_l,sync")
(eq_attr "cpu" "ppce500mc64"))
"e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing,e500mc64_retire")
(define_insn_reservation "e500mc64_fpload" 4
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "ppce500mc64"))
"e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing*2,e500mc64_retire")
;; Stores.
(define_insn_reservation "e500mc64_store" 3
- (and (eq_attr "type" "store,store_ux,store_u,store_c")
+ (and (eq_attr "type" "store,store_c")
(eq_attr "cpu" "ppce500mc64"))
"e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing,e500mc64_retire")
(define_insn_reservation "e500mc64_fpstore" 3
- (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "fpstore")
(eq_attr "cpu" "ppce500mc64"))
"e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing,e500mc64_retire")
diff --git a/gcc/config/rs6000/e5500.md b/gcc/config/rs6000/e5500.md
index b2547a03a41..8d784e0e4de 100644
--- a/gcc/config/rs6000/e5500.md
+++ b/gcc/config/rs6000/e5500.md
@@ -56,18 +56,27 @@
;; SFX.
(define_insn_reservation "e5500_sfx" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,delayed_compare,\
- shift,cntlz,exts")
+ (and (ior (eq_attr "type" "integer,insert,cntlz,exts")
+ (and (eq_attr "type" "add,logical")
+ (eq_attr "dot" "no"))
+ (and (eq_attr "type" "shift")
+ (eq_attr "var_shift" "no")))
(eq_attr "cpu" "ppce5500"))
"e5500_decode,e5500_sfx")
(define_insn_reservation "e5500_sfx2" 2
- (and (eq_attr "type" "cmp,compare,fast_compare,trap")
+ (and (ior (eq_attr "type" "cmp,compare,trap")
+ (and (eq_attr "type" "add,logical")
+ (eq_attr "dot" "yes"))
+ (and (eq_attr "type" "shift")
+ (eq_attr "dot" "yes")
+ (eq_attr "var_shift" "no")))
(eq_attr "cpu" "ppce5500"))
"e5500_decode,e5500_sfx")
(define_insn_reservation "e5500_delayed" 2
- (and (eq_attr "type" "var_shift_rotate,var_delayed_compare")
+ (and (eq_attr "type" "shift")
+ (eq_attr "var_shift" "yes")
(eq_attr "cpu" "ppce5500"))
"e5500_decode,e5500_sfx*2")
@@ -101,49 +110,54 @@
;; CFX - Multiply.
(define_insn_reservation "e5500_multiply" 4
- (and (eq_attr "type" "imul")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "no")
+ (eq_attr "size" "32")
(eq_attr "cpu" "ppce5500"))
"e5500_decode,e5500_cfx_stage0,e5500_cfx_stage1")
(define_insn_reservation "e5500_multiply_i" 5
- (and (eq_attr "type" "imul2,imul3,imul_compare")
+ (and (eq_attr "type" "mul")
+ (ior (eq_attr "dot" "yes")
+ (eq_attr "size" "8,16"))
(eq_attr "cpu" "ppce5500"))
"e5500_decode,e5500_cfx_stage0,\
e5500_cfx_stage0+e5500_cfx_stage1,e5500_cfx_stage1")
;; CFX - Divide.
(define_insn_reservation "e5500_divide" 16
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "32")
(eq_attr "cpu" "ppce5500"))
"e5500_decode,e5500_cfx_stage0+e5500_cfx_div,\
e5500_cfx_div*15")
(define_insn_reservation "e5500_divide_d" 26
- (and (eq_attr "type" "ldiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "64")
(eq_attr "cpu" "ppce5500"))
"e5500_decode,e5500_cfx_stage0+e5500_cfx_div,\
e5500_cfx_div*25")
;; LSU - Loads.
(define_insn_reservation "e5500_load" 3
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
- load_l,sync")
+ (and (eq_attr "type" "load,load_l,sync")
(eq_attr "cpu" "ppce5500"))
"e5500_decode,e5500_lsu")
(define_insn_reservation "e5500_fpload" 4
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "ppce5500"))
"e5500_decode,e5500_lsu")
;; LSU - Stores.
(define_insn_reservation "e5500_store" 3
- (and (eq_attr "type" "store,store_ux,store_u,store_c")
+ (and (eq_attr "type" "store,store_c")
(eq_attr "cpu" "ppce5500"))
"e5500_decode,e5500_lsu")
(define_insn_reservation "e5500_fpstore" 3
- (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "fpstore")
(eq_attr "cpu" "ppce5500"))
"e5500_decode,e5500_lsu")
diff --git a/gcc/config/rs6000/e6500.md b/gcc/config/rs6000/e6500.md
index 2ed550b9264..a013a945b07 100644
--- a/gcc/config/rs6000/e6500.md
+++ b/gcc/config/rs6000/e6500.md
@@ -59,18 +59,28 @@
;; SFX.
(define_insn_reservation "e6500_sfx" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,delayed_compare,\
- shift,cntlz,exts")
+ (and (ior (eq_attr "type" "integer,insert,cntlz,exts")
+ (and (eq_attr "type" "add,logical")
+ (eq_attr "dot" "no"))
+ (and (eq_attr "type" "shift")
+ (eq_attr "dot" "no")
+ (eq_attr "var_shift" "no")))
(eq_attr "cpu" "ppce6500"))
"e6500_decode,e6500_sfx")
(define_insn_reservation "e6500_sfx2" 2
- (and (eq_attr "type" "cmp,compare,fast_compare,trap")
+ (and (ior (eq_attr "type" "cmp,compare,trap")
+ (and (eq_attr "type" "add,logical")
+ (eq_attr "dot" "yes"))
+ (and (eq_attr "type" "shift")
+ (eq_attr "dot" "yes")
+ (eq_attr "var_shift" "no")))
(eq_attr "cpu" "ppce6500"))
"e6500_decode,e6500_sfx")
(define_insn_reservation "e6500_delayed" 2
- (and (eq_attr "type" "var_shift_rotate,var_delayed_compare")
+ (and (eq_attr "type" "shift")
+ (eq_attr "var_shift" "yes")
(eq_attr "cpu" "ppce6500"))
"e6500_decode,e6500_sfx*2")
@@ -104,38 +114,43 @@
;; CFX - Multiply.
(define_insn_reservation "e6500_multiply" 4
- (and (eq_attr "type" "imul")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "no")
+ (eq_attr "size" "32")
(eq_attr "cpu" "ppce6500"))
"e6500_decode,e6500_cfx_stage0,e6500_cfx_stage1")
(define_insn_reservation "e6500_multiply_i" 5
- (and (eq_attr "type" "imul2,imul3,imul_compare")
+ (and (eq_attr "type" "mul")
+ (ior (eq_attr "dot" "yes")
+ (eq_attr "size" "8,16"))
(eq_attr "cpu" "ppce6500"))
"e6500_decode,e6500_cfx_stage0,\
e6500_cfx_stage0+e6500_cfx_stage1,e6500_cfx_stage1")
;; CFX - Divide.
(define_insn_reservation "e6500_divide" 16
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "32")
(eq_attr "cpu" "ppce6500"))
"e6500_decode,e6500_cfx_stage0+e6500_cfx_div,\
e6500_cfx_div*15")
(define_insn_reservation "e6500_divide_d" 26
- (and (eq_attr "type" "ldiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "64")
(eq_attr "cpu" "ppce6500"))
"e6500_decode,e6500_cfx_stage0+e6500_cfx_div,\
e6500_cfx_div*25")
;; LSU - Loads.
(define_insn_reservation "e6500_load" 3
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
- load_l,sync")
+ (and (eq_attr "type" "load,load_l,sync")
(eq_attr "cpu" "ppce6500"))
"e6500_decode,e6500_lsu")
(define_insn_reservation "e6500_fpload" 4
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "ppce6500"))
"e6500_decode,e6500_lsu")
@@ -146,12 +161,12 @@
;; LSU - Stores.
(define_insn_reservation "e6500_store" 3
- (and (eq_attr "type" "store,store_ux,store_u,store_c")
+ (and (eq_attr "type" "store,store_c")
(eq_attr "cpu" "ppce6500"))
"e6500_decode,e6500_lsu")
(define_insn_reservation "e6500_fpstore" 3
- (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "fpstore")
(eq_attr "cpu" "ppce6500"))
"e6500_decode,e6500_lsu")
diff --git a/gcc/config/rs6000/htm.md b/gcc/config/rs6000/htm.md
index 9dbb499ce21..ca7f7fdf4fb 100644
--- a/gcc/config/rs6000/htm.md
+++ b/gcc/config/rs6000/htm.md
@@ -179,7 +179,7 @@
(const_int 0)]
UNSPECV_HTM_TABORTWCI))
(set (subreg:CC (match_dup 2) 0) (match_dup 1))
- (set (match_dup 3) (lshiftrt:SI (match_dup 2) (const_int 24)))
+ (set (match_dup 3) (lshiftrt:SI (match_dup 2) (const_int 28)))
(parallel [(set (match_operand:SI 0 "int_reg_operand" "")
(and:SI (match_dup 3) (const_int 15)))
(clobber (scratch:CC))])]
diff --git a/gcc/config/rs6000/htmxlintrin.h b/gcc/config/rs6000/htmxlintrin.h
index 38dc066d30e..bf7fe3a75ab 100644
--- a/gcc/config/rs6000/htmxlintrin.h
+++ b/gcc/config/rs6000/htmxlintrin.h
@@ -46,12 +46,17 @@ extern "C" {
typedef char TM_buff_type[16];
+/* Compatibility macro with s390. This macro can be used to determine
+ whether a transaction was successfully started from the __TM_begin()
+ and __TM_simple_begin() intrinsic functions below. */
+#define _HTM_TBEGIN_STARTED 1
+
extern __inline long
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
__TM_simple_begin (void)
{
if (__builtin_expect (__builtin_tbegin (0), 1))
- return 1;
+ return _HTM_TBEGIN_STARTED;
return 0;
}
@@ -61,7 +66,7 @@ __TM_begin (void* const TM_buff)
{
*_TEXASRL_PTR (TM_buff) = 0;
if (__builtin_expect (__builtin_tbegin (0), 1))
- return 1;
+ return _HTM_TBEGIN_STARTED;
#ifdef __powerpc64__
*_TEXASR_PTR (TM_buff) = __builtin_get_texasr ();
#else
diff --git a/gcc/config/rs6000/mpc.md b/gcc/config/rs6000/mpc.md
index 65cc5a4a3b9..2f11a861499 100644
--- a/gcc/config/rs6000/mpc.md
+++ b/gcc/config/rs6000/mpc.md
@@ -26,24 +26,24 @@
;; 505/801/821/823
(define_insn_reservation "mpccore-load" 2
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
- load_l,store_c,sync")
+ (and (eq_attr "type" "load,load_l,store_c,sync")
(eq_attr "cpu" "mpccore"))
"lsu_mpc")
(define_insn_reservation "mpccore-store" 2
- (and (eq_attr "type" "store,store_ux,store_u,fpstore,fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "store,fpstore")
(eq_attr "cpu" "mpccore"))
"lsu_mpc")
(define_insn_reservation "mpccore-fpload" 2
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "mpccore"))
"lsu_mpc")
(define_insn_reservation "mpccore-integer" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,shift,trap,\
- var_shift_rotate,cntlz,exts,isel")
+ (and (ior (eq_attr "type" "integer,insert,trap,cntlz,exts,isel")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no")))
(eq_attr "cpu" "mpccore"))
"iu_mpc")
@@ -58,19 +58,20 @@
"iu_mpc,iu_mpc,iu_mpc")
(define_insn_reservation "mpccore-imul" 2
- (and (eq_attr "type" "imul,imul2,imul3,imul_compare")
+ (and (eq_attr "type" "mul")
(eq_attr "cpu" "mpccore"))
"mciu_mpc")
; Divide latency varies greatly from 2-11, use 6 as average
(define_insn_reservation "mpccore-idiv" 6
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
(eq_attr "cpu" "mpccore"))
"mciu_mpc*6")
(define_insn_reservation "mpccore-compare" 3
- (and (eq_attr "type" "cmp,fast_compare,compare,delayed_compare,\
- var_delayed_compare")
+ (and (ior (eq_attr "type" "cmp,compare")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "mpccore"))
"iu_mpc,nothing,bpu_mpc")
diff --git a/gcc/config/rs6000/power4.md b/gcc/config/rs6000/power4.md
index 196f40c261e..e46914e6521 100644
--- a/gcc/config/rs6000/power4.md
+++ b/gcc/config/rs6000/power4.md
@@ -77,11 +77,15 @@
; Load/store
(define_insn_reservation "power4-load" 4 ; 3
(and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power4"))
"lsq_power4")
(define_insn_reservation "power4-load-ext" 5
- (and (eq_attr "type" "load_ext")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power4"))
"(du1_power4+du2_power4,lsu1_power4\
|du2_power4+du3_power4,lsu2_power4\
@@ -90,35 +94,49 @@
(iu2_power4|iu1_power4)")
(define_insn_reservation "power4-load-ext-update" 5
- (and (eq_attr "type" "load_ext_u")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "no")
(eq_attr "cpu" "power4"))
"du1_power4+du2_power4+du3_power4+du4_power4,\
lsu1_power4+iu2_power4,nothing,nothing,iu2_power4")
(define_insn_reservation "power4-load-ext-update-indexed" 5
- (and (eq_attr "type" "load_ext_ux")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "yes")
(eq_attr "cpu" "power4"))
"du1_power4+du2_power4+du3_power4+du4_power4,\
iu1_power4,lsu2_power4+iu1_power4,nothing,nothing,iu2_power4")
(define_insn_reservation "power4-load-update-indexed" 3
- (and (eq_attr "type" "load_ux")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "yes")
(eq_attr "cpu" "power4"))
"du1_power4+du2_power4+du3_power4+du4_power4,\
iu1_power4,lsu2_power4+iu2_power4")
(define_insn_reservation "power4-load-update" 4 ; 3
- (and (eq_attr "type" "load_u")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "no")
(eq_attr "cpu" "power4"))
"lsuq_power4")
(define_insn_reservation "power4-fpload" 6 ; 5
(and (eq_attr "type" "fpload")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power4"))
"lsq_power4")
(define_insn_reservation "power4-fpload-update" 6 ; 5
- (and (eq_attr "type" "fpload_u,fpload_ux")
+ (and (eq_attr "type" "fpload")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "power4"))
"lsuq_power4")
@@ -129,6 +147,7 @@
(define_insn_reservation "power4-store" 12
(and (eq_attr "type" "store")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power4"))
"((du1_power4,lsu1_power4)\
|(du2_power4,lsu2_power4)\
@@ -137,7 +156,9 @@
(iu1_power4|iu2_power4)")
(define_insn_reservation "power4-store-update" 12
- (and (eq_attr "type" "store_u")
+ (and (eq_attr "type" "store")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "no")
(eq_attr "cpu" "power4"))
"((du1_power4+du2_power4,lsu1_power4)\
|(du2_power4+du3_power4,lsu2_power4)\
@@ -147,13 +168,16 @@
|(nothing,iu2_power4,iu1_power4))")
(define_insn_reservation "power4-store-update-indexed" 12
- (and (eq_attr "type" "store_ux")
+ (and (eq_attr "type" "store")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "yes")
(eq_attr "cpu" "power4"))
"du1_power4+du2_power4+du3_power4+du4_power4,\
iu1_power4,lsu2_power4+iu2_power4,iu2_power4")
(define_insn_reservation "power4-fpstore" 12
(and (eq_attr "type" "fpstore")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power4"))
"((du1_power4,lsu1_power4)\
|(du2_power4,lsu2_power4)\
@@ -162,7 +186,8 @@
(fpu1_power4|fpu2_power4)")
(define_insn_reservation "power4-fpstore-update" 12
- (and (eq_attr "type" "fpstore_u,fpstore_ux")
+ (and (eq_attr "type" "fpstore")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "power4"))
"((du1_power4+du2_power4,lsu1_power4)\
|(du2_power4+du3_power4,lsu2_power4)\
@@ -185,8 +210,11 @@
; Integer latency is 2 cycles
(define_insn_reservation "power4-integer" 2
- (and (eq_attr "type" "integer,insert_dword,shift,trap,\
- var_shift_rotate,cntlz,exts,isel")
+ (and (ior (eq_attr "type" "integer,trap,cntlz,exts,isel")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no"))
+ (and (eq_attr "type" "insert")
+ (eq_attr "size" "64")))
(eq_attr "cpu" "power4"))
"iq_power4")
@@ -213,7 +241,8 @@
|(iu1_power4,nothing,iu1_power4,nothing,iu2_power4))")
(define_insn_reservation "power4-insert" 4
- (and (eq_attr "type" "insert_word")
+ (and (eq_attr "type" "insert")
+ (eq_attr "size" "32")
(eq_attr "cpu" "power4"))
"(du1_power4+du2_power4|du2_power4+du3_power4|du3_power4+du4_power4),\
((iu1_power4,nothing,iu2_power4)\
@@ -221,12 +250,16 @@
|(iu2_power4,nothing,iu1_power4))")
(define_insn_reservation "power4-cmp" 3
- (and (eq_attr "type" "cmp,fast_compare")
+ (and (ior (eq_attr "type" "cmp")
+ (and (eq_attr "type" "add,logical")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "power4"))
"iq_power4")
(define_insn_reservation "power4-compare" 2
- (and (eq_attr "type" "compare,delayed_compare,var_delayed_compare")
+ (and (ior (eq_attr "type" "compare")
+ (and (eq_attr "type" "shift")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "power4"))
"(du1_power4+du2_power4|du2_power4+du3_power4|du3_power4+du4_power4),\
((iu1_power4,iu2_power4)\
@@ -236,7 +269,9 @@
(define_bypass 4 "power4-compare" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf")
(define_insn_reservation "power4-lmul-cmp" 7
- (and (eq_attr "type" "lmul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "yes")
+ (eq_attr "size" "64")
(eq_attr "cpu" "power4"))
"(du1_power4+du2_power4|du2_power4+du3_power4|du3_power4+du4_power4),\
((iu1_power4*6,iu2_power4)\
@@ -246,7 +281,9 @@
(define_bypass 10 "power4-lmul-cmp" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf")
(define_insn_reservation "power4-imul-cmp" 5
- (and (eq_attr "type" "imul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "yes")
+ (eq_attr "size" "32")
(eq_attr "cpu" "power4"))
"(du1_power4+du2_power4|du2_power4+du3_power4|du3_power4+du4_power4),\
((iu1_power4*4,iu2_power4)\
@@ -256,19 +293,24 @@
(define_bypass 8 "power4-imul-cmp" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf")
(define_insn_reservation "power4-lmul" 7
- (and (eq_attr "type" "lmul")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "no")
+ (eq_attr "size" "64")
(eq_attr "cpu" "power4"))
"(du1_power4|du2_power4|du3_power4|du4_power4),\
(iu1_power4*6|iu2_power4*6)")
(define_insn_reservation "power4-imul" 5
- (and (eq_attr "type" "imul")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "no")
+ (eq_attr "size" "32")
(eq_attr "cpu" "power4"))
"(du1_power4|du2_power4|du3_power4|du4_power4),\
(iu1_power4*4|iu2_power4*4)")
(define_insn_reservation "power4-imul3" 4
- (and (eq_attr "type" "imul2,imul3")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "8,16")
(eq_attr "cpu" "power4"))
"(du1_power4|du2_power4|du3_power4|du4_power4),\
(iu1_power4*3|iu2_power4*3)")
@@ -277,12 +319,14 @@
; SPR move only executes in first IU.
; Integer division only executes in second IU.
(define_insn_reservation "power4-idiv" 36
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "32")
(eq_attr "cpu" "power4"))
"du1_power4+du2_power4,iu2_power4*35")
(define_insn_reservation "power4-ldiv" 68
- (and (eq_attr "type" "ldiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "64")
(eq_attr "cpu" "power4"))
"du1_power4+du2_power4,iu2_power4*67")
diff --git a/gcc/config/rs6000/power5.md b/gcc/config/rs6000/power5.md
index fcd7e8e84ae..198db827f8c 100644
--- a/gcc/config/rs6000/power5.md
+++ b/gcc/config/rs6000/power5.md
@@ -57,49 +57,68 @@
; Load/store
(define_insn_reservation "power5-load" 4 ; 3
(and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power5"))
"lsq_power5")
(define_insn_reservation "power5-load-ext" 5
- (and (eq_attr "type" "load_ext")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5,lsu1_power5,nothing,nothing,iu2_power5")
(define_insn_reservation "power5-load-ext-update" 5
- (and (eq_attr "type" "load_ext_u")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "no")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5+du3_power5+du4_power5,\
lsu1_power5+iu2_power5,nothing,nothing,iu2_power5")
(define_insn_reservation "power5-load-ext-update-indexed" 5
- (and (eq_attr "type" "load_ext_ux")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "yes")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5+du3_power5+du4_power5,\
iu1_power5,lsu2_power5+iu1_power5,nothing,nothing,iu2_power5")
(define_insn_reservation "power5-load-update-indexed" 3
- (and (eq_attr "type" "load_ux")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "yes")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5+du3_power5+du4_power5,\
iu1_power5,lsu2_power5+iu2_power5")
(define_insn_reservation "power5-load-update" 4 ; 3
- (and (eq_attr "type" "load_u")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "no")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5,lsu1_power5+iu2_power5")
(define_insn_reservation "power5-fpload" 6 ; 5
(and (eq_attr "type" "fpload")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power5"))
"lsq_power5")
(define_insn_reservation "power5-fpload-update" 6 ; 5
- (and (eq_attr "type" "fpload_u,fpload_ux")
+ (and (eq_attr "type" "fpload")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5,lsu1_power5+iu2_power5")
(define_insn_reservation "power5-store" 12
(and (eq_attr "type" "store")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power5"))
"((du1_power5,lsu1_power5)\
|(du2_power5,lsu2_power5)\
@@ -108,18 +127,23 @@
(iu1_power5|iu2_power5)")
(define_insn_reservation "power5-store-update" 12
- (and (eq_attr "type" "store_u")
+ (and (eq_attr "type" "store")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "no")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5,lsu1_power5+iu2_power5,iu1_power5")
(define_insn_reservation "power5-store-update-indexed" 12
- (and (eq_attr "type" "store_ux")
+ (and (eq_attr "type" "store")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "yes")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5+du3_power5+du4_power5,\
iu1_power5,lsu2_power5+iu2_power5,iu2_power5")
(define_insn_reservation "power5-fpstore" 12
(and (eq_attr "type" "fpstore")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power5"))
"((du1_power5,lsu1_power5)\
|(du2_power5,lsu2_power5)\
@@ -128,7 +152,8 @@
(fpu1_power5|fpu2_power5)")
(define_insn_reservation "power5-fpstore-update" 12
- (and (eq_attr "type" "fpstore_u,fpstore_ux")
+ (and (eq_attr "type" "fpstore")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5,lsu1_power5+iu2_power5,fpu1_power5")
@@ -141,8 +166,11 @@
; Integer latency is 2 cycles
(define_insn_reservation "power5-integer" 2
- (and (eq_attr "type" "integer,insert_dword,shift,trap,\
- var_shift_rotate,cntlz,exts,isel,popcnt")
+ (and (ior (eq_attr "type" "integer,trap,cntlz,exts,isel,popcnt")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no"))
+ (and (eq_attr "type" "insert")
+ (eq_attr "size" "64")))
(eq_attr "cpu" "power5"))
"iq_power5")
@@ -169,48 +197,62 @@
|(iu1_power5,nothing,iu2_power5,nothing,iu2_power5))")
(define_insn_reservation "power5-insert" 4
- (and (eq_attr "type" "insert_word")
+ (and (eq_attr "type" "insert")
+ (eq_attr "size" "32")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5,iu1_power5,nothing,iu2_power5")
(define_insn_reservation "power5-cmp" 3
- (and (eq_attr "type" "cmp,fast_compare")
+ (and (ior (eq_attr "type" "cmp")
+ (and (eq_attr "type" "add,logical")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "power5"))
"iq_power5")
(define_insn_reservation "power5-compare" 2
- (and (eq_attr "type" "compare,delayed_compare,var_delayed_compare")
+ (and (ior (eq_attr "type" "compare")
+ (and (eq_attr "type" "shift")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5,iu1_power5,iu2_power5")
(define_bypass 4 "power5-compare" "power5-branch,power5-crlogical,power5-delayedcr,power5-mfcr,power5-mfcrf")
(define_insn_reservation "power5-lmul-cmp" 7
- (and (eq_attr "type" "lmul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "yes")
+ (eq_attr "size" "64")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5,iu1_power5*6,iu2_power5")
(define_bypass 10 "power5-lmul-cmp" "power5-branch,power5-crlogical,power5-delayedcr,power5-mfcr,power5-mfcrf")
(define_insn_reservation "power5-imul-cmp" 5
- (and (eq_attr "type" "imul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "yes")
+ (eq_attr "size" "32")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5,iu1_power5*4,iu2_power5")
(define_bypass 8 "power5-imul-cmp" "power5-branch,power5-crlogical,power5-delayedcr,power5-mfcr,power5-mfcrf")
(define_insn_reservation "power5-lmul" 7
- (and (eq_attr "type" "lmul")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "no")
+ (eq_attr "size" "64")
(eq_attr "cpu" "power5"))
"(du1_power5|du2_power5|du3_power5|du4_power5),(iu1_power5*6|iu2_power5*6)")
(define_insn_reservation "power5-imul" 5
- (and (eq_attr "type" "imul")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "no")
+ (eq_attr "size" "32")
(eq_attr "cpu" "power5"))
"(du1_power5|du2_power5|du3_power5|du4_power5),(iu1_power5*4|iu2_power5*4)")
(define_insn_reservation "power5-imul3" 4
- (and (eq_attr "type" "imul2,imul3")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "8,16")
(eq_attr "cpu" "power5"))
"(du1_power5|du2_power5|du3_power5|du4_power5),(iu1_power5*3|iu2_power5*3)")
@@ -218,12 +260,14 @@
; SPR move only executes in first IU.
; Integer division only executes in second IU.
(define_insn_reservation "power5-idiv" 36
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "32")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5,iu2_power5*35")
(define_insn_reservation "power5-ldiv" 68
- (and (eq_attr "type" "ldiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "64")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5,iu2_power5*67")
diff --git a/gcc/config/rs6000/power6.md b/gcc/config/rs6000/power6.md
index 4ed721eef16..e4a82a21c64 100644
--- a/gcc/config/rs6000/power6.md
+++ b/gcc/config/rs6000/power6.md
@@ -92,6 +92,8 @@
; that is read/written by a subsequent fixed point op.
(define_insn_reservation "power6-load" 2 ; fx
(and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power6"))
"LSU_power6")
@@ -109,7 +111,9 @@
"store_data_bypass_p")
(define_insn_reservation "power6-load-ext" 4 ; fx
- (and (eq_attr "type" "load_ext")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power6"))
"LSU_power6")
@@ -127,57 +131,78 @@
"store_data_bypass_p")
(define_insn_reservation "power6-load-update" 2 ; fx
- (and (eq_attr "type" "load_u")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "no")
(eq_attr "cpu" "power6"))
"LSX_power6")
(define_insn_reservation "power6-load-update-indexed" 2 ; fx
- (and (eq_attr "type" "load_ux")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "yes")
(eq_attr "cpu" "power6"))
"LSX_power6")
(define_insn_reservation "power6-load-ext-update" 4 ; fx
- (and (eq_attr "type" "load_ext_u")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "no")
(eq_attr "cpu" "power6"))
"LSX_power6")
(define_insn_reservation "power6-load-ext-update-indexed" 4 ; fx
- (and (eq_attr "type" "load_ext_ux")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "yes")
(eq_attr "cpu" "power6"))
"LSX_power6")
(define_insn_reservation "power6-fpload" 1
(and (eq_attr "type" "fpload")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power6"))
"LSU_power6")
(define_insn_reservation "power6-fpload-update" 1
- (and (eq_attr "type" "fpload_u,fpload_ux")
+ (and (eq_attr "type" "fpload")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "power6"))
"LSX_power6")
(define_insn_reservation "power6-store" 14
(and (eq_attr "type" "store")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power6"))
"LSU_power6")
(define_insn_reservation "power6-store-update" 14
- (and (eq_attr "type" "store_u")
+ (and (eq_attr "type" "store")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "no")
(eq_attr "cpu" "power6"))
"LSX_power6")
(define_insn_reservation "power6-store-update-indexed" 14
- (and (eq_attr "type" "store_ux")
+ (and (eq_attr "type" "store")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "yes")
(eq_attr "cpu" "power6"))
"LX2_power6")
(define_insn_reservation "power6-fpstore" 14
(and (eq_attr "type" "fpstore")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power6"))
"LSF_power6")
(define_insn_reservation "power6-fpstore-update" 14
- (and (eq_attr "type" "fpstore_u,fpstore_ux")
+ (and (eq_attr "type" "fpstore")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "power6"))
"XLF_power6")
@@ -197,7 +222,9 @@
"LSU_power6")
(define_insn_reservation "power6-integer" 1
- (and (eq_attr "type" "integer")
+ (and (ior (eq_attr "type" "integer")
+ (and (eq_attr "type" "add,logical")
+ (eq_attr "dot" "no")))
(eq_attr "cpu" "power6"))
"FXU_power6")
@@ -213,6 +240,8 @@
(define_insn_reservation "power6-shift" 1
(and (eq_attr "type" "shift")
+ (eq_attr "var_shift" "no")
+ (eq_attr "dot" "no")
(eq_attr "cpu" "power6"))
"FXU_power6")
@@ -222,12 +251,14 @@
"FXU_power6")
(define_insn_reservation "power6-insert" 1
- (and (eq_attr "type" "insert_word")
+ (and (eq_attr "type" "insert")
+ (eq_attr "size" "32")
(eq_attr "cpu" "power6"))
"FX2_power6")
(define_insn_reservation "power6-insert-dword" 1
- (and (eq_attr "type" "insert_dword")
+ (and (eq_attr "type" "insert")
+ (eq_attr "size" "64")
(eq_attr "cpu" "power6"))
"FX2_power6")
@@ -260,7 +291,9 @@
"store_data_bypass_p")
(define_insn_reservation "power6-var-rotate" 4
- (and (eq_attr "type" "var_shift_rotate")
+ (and (eq_attr "type" "shift")
+ (eq_attr "var_shift" "yes")
+ (eq_attr "dot" "no")
(eq_attr "cpu" "power6"))
"FXU_power6")
@@ -305,7 +338,8 @@
"FXU_power6")
(define_insn_reservation "power6-fast-compare" 1
- (and (eq_attr "type" "fast_compare")
+ (and (eq_attr "type" "add,logical")
+ (eq_attr "dot" "yes")
(eq_attr "cpu" "power6"))
"FXU_power6")
@@ -322,41 +356,54 @@
"store_data_bypass_p")
(define_insn_reservation "power6-delayed-compare" 2 ; N/A
- (and (eq_attr "type" "delayed_compare")
+ (and (eq_attr "type" "shift")
+ (eq_attr "var_shift" "no")
+ (eq_attr "dot" "yes")
(eq_attr "cpu" "power6"))
"FXU_power6")
(define_insn_reservation "power6-var-delayed-compare" 4
- (and (eq_attr "type" "var_delayed_compare")
+ (and (eq_attr "type" "shift")
+ (eq_attr "var_shift" "yes")
+ (eq_attr "dot" "yes")
(eq_attr "cpu" "power6"))
"FXU_power6")
(define_insn_reservation "power6-lmul-cmp" 16
- (and (eq_attr "type" "lmul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "yes")
+ (eq_attr "size" "64")
(eq_attr "cpu" "power6"))
"(iu1_power6*16+iu2_power6*16+fpu1_power6*16)\
|(iu1_power6*16+iu2_power6*16+fpu2_power6*16)");
(define_insn_reservation "power6-imul-cmp" 16
- (and (eq_attr "type" "imul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "yes")
+ (eq_attr "size" "32")
(eq_attr "cpu" "power6"))
"(iu1_power6*16+iu2_power6*16+fpu1_power6*16)\
|(iu1_power6*16+iu2_power6*16+fpu2_power6*16)");
(define_insn_reservation "power6-lmul" 16
- (and (eq_attr "type" "lmul")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "no")
+ (eq_attr "size" "64")
(eq_attr "cpu" "power6"))
"(iu1_power6*16+iu2_power6*16+fpu1_power6*16)\
|(iu1_power6*16+iu2_power6*16+fpu2_power6*16)");
(define_insn_reservation "power6-imul" 16
- (and (eq_attr "type" "imul")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "no")
+ (eq_attr "size" "32")
(eq_attr "cpu" "power6"))
"(iu1_power6*16+iu2_power6*16+fpu1_power6*16)\
|(iu1_power6*16+iu2_power6*16+fpu2_power6*16)");
(define_insn_reservation "power6-imul3" 16
- (and (eq_attr "type" "imul2,imul3")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "8,16")
(eq_attr "cpu" "power6"))
"(iu1_power6*16+iu2_power6*16+fpu1_power6*16)\
|(iu1_power6*16+iu2_power6*16+fpu2_power6*16)");
@@ -374,7 +421,8 @@
"store_data_bypass_p")
(define_insn_reservation "power6-idiv" 44
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "32")
(eq_attr "cpu" "power6"))
"(iu1_power6*44+iu2_power6*44+fpu1_power6*44)\
|(iu1_power6*44+iu2_power6*44+fpu2_power6*44)");
@@ -389,7 +437,8 @@
; "store_data_bypass_p")
(define_insn_reservation "power6-ldiv" 56
- (and (eq_attr "type" "ldiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "64")
(eq_attr "cpu" "power6"))
"(iu1_power6*56+iu2_power6*56+fpu1_power6*56)\
|(iu1_power6*56+iu2_power6*56+fpu2_power6*56)");
diff --git a/gcc/config/rs6000/power7.md b/gcc/config/rs6000/power7.md
index 3578c97ead4..b2a0cafe99c 100644
--- a/gcc/config/rs6000/power7.md
+++ b/gcc/config/rs6000/power7.md
@@ -58,66 +58,91 @@
; LS Unit
(define_insn_reservation "power7-load" 2
(and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power7"))
"DU_power7,LSU_power7")
(define_insn_reservation "power7-load-ext" 3
- (and (eq_attr "type" "load_ext")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power7"))
"DU2F_power7,LSU_power7,FXU_power7")
(define_insn_reservation "power7-load-update" 2
- (and (eq_attr "type" "load_u")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "no")
(eq_attr "cpu" "power7"))
"DU2F_power7,LSU_power7+FXU_power7")
(define_insn_reservation "power7-load-update-indexed" 3
- (and (eq_attr "type" "load_ux")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "yes")
(eq_attr "cpu" "power7"))
"DU4_power7,FXU_power7,LSU_power7+FXU_power7")
(define_insn_reservation "power7-load-ext-update" 4
- (and (eq_attr "type" "load_ext_u")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "no")
(eq_attr "cpu" "power7"))
"DU2F_power7,LSU_power7+FXU_power7,FXU_power7")
(define_insn_reservation "power7-load-ext-update-indexed" 4
- (and (eq_attr "type" "load_ext_ux")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "yes")
(eq_attr "cpu" "power7"))
"DU4_power7,FXU_power7,LSU_power7+FXU_power7,FXU_power7")
(define_insn_reservation "power7-fpload" 3
(and (eq_attr "type" "fpload")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power7"))
"DU_power7,LSU_power7")
(define_insn_reservation "power7-fpload-update" 3
- (and (eq_attr "type" "fpload_u,fpload_ux")
+ (and (eq_attr "type" "fpload")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "power7"))
"DU2F_power7,LSU_power7+FXU_power7")
(define_insn_reservation "power7-store" 6 ; store-forwarding latency
(and (eq_attr "type" "store")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power7"))
"DU_power7,LSU_power7+FXU_power7")
(define_insn_reservation "power7-store-update" 6
- (and (eq_attr "type" "store_u")
+ (and (eq_attr "type" "store")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "no")
(eq_attr "cpu" "power7"))
"DU2F_power7,LSU_power7+FXU_power7,FXU_power7")
(define_insn_reservation "power7-store-update-indexed" 6
- (and (eq_attr "type" "store_ux")
+ (and (eq_attr "type" "store")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "yes")
(eq_attr "cpu" "power7"))
"DU4_power7,LSU_power7+FXU_power7,FXU_power7")
(define_insn_reservation "power7-fpstore" 6
(and (eq_attr "type" "fpstore")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power7"))
"DU_power7,LSU_power7+VSU_power7")
(define_insn_reservation "power7-fpstore-update" 6
- (and (eq_attr "type" "fpstore_u,fpstore_ux")
+ (and (eq_attr "type" "fpstore")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "power7"))
"DU_power7,LSU_power7+VSU_power7+FXU_power7")
@@ -149,8 +174,9 @@
; FX Unit
(define_insn_reservation "power7-integer" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,shift,trap,\
- var_shift_rotate,exts,isel,popcnt")
+ (and (ior (eq_attr "type" "integer,insert,trap,exts,isel,popcnt")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no")))
(eq_attr "cpu" "power7"))
"DU_power7,FXU_power7")
@@ -170,34 +196,42 @@
"DU_power7+DU_power7+DU_power7,FXU_power7,FXU_power7,FXU_power7")
(define_insn_reservation "power7-cmp" 1
- (and (eq_attr "type" "cmp,fast_compare")
+ (and (ior (eq_attr "type" "cmp")
+ (and (eq_attr "type" "add,logical")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "power7"))
"DU_power7,FXU_power7")
(define_insn_reservation "power7-compare" 2
- (and (eq_attr "type" "compare,delayed_compare,var_delayed_compare")
+ (and (ior (eq_attr "type" "compare")
+ (and (eq_attr "type" "shift")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "power7"))
"DU2F_power7,FXU_power7,FXU_power7")
(define_bypass 3 "power7-cmp,power7-compare" "power7-crlogical,power7-delayedcr")
(define_insn_reservation "power7-mul" 4
- (and (eq_attr "type" "imul,imul2,imul3,lmul")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "no")
(eq_attr "cpu" "power7"))
"DU_power7,FXU_power7")
(define_insn_reservation "power7-mul-compare" 5
- (and (eq_attr "type" "imul_compare,lmul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "yes")
(eq_attr "cpu" "power7"))
"DU2F_power7,FXU_power7,nothing*3,FXU_power7")
(define_insn_reservation "power7-idiv" 36
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "32")
(eq_attr "cpu" "power7"))
"DU2F_power7,iu1_power7*36|iu2_power7*36")
(define_insn_reservation "power7-ldiv" 68
- (and (eq_attr "type" "ldiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "64")
(eq_attr "cpu" "power7"))
"DU2F_power7,iu1_power7*68|iu2_power7*68")
diff --git a/gcc/config/rs6000/power8.md b/gcc/config/rs6000/power8.md
index b6bb853e18c..c7c0aa982cf 100644
--- a/gcc/config/rs6000/power8.md
+++ b/gcc/config/rs6000/power8.md
@@ -80,51 +80,68 @@
; LS Unit
(define_insn_reservation "power8-load" 3
(and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power8"))
"DU_any_power8,LU_or_LSU_power8")
(define_insn_reservation "power8-load-update" 3
- (and (eq_attr "type" "load_u,load_ux")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "no")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "power8"))
"DU_cracked_power8,LU_or_LSU_power8+FXU_power8")
(define_insn_reservation "power8-load-ext" 3
- (and (eq_attr "type" "load_ext")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power8"))
"DU_cracked_power8,LU_or_LSU_power8,FXU_power8")
(define_insn_reservation "power8-load-ext-update" 3
- (and (eq_attr "type" "load_ext_u,load_ext_ux")
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "power8"))
"DU_both_power8,LU_or_LSU_power8+FXU_power8,FXU_power8")
(define_insn_reservation "power8-fpload" 5
- (and (eq_attr "type" "fpload,vecload")
+ (and (ior (eq_attr "type" "vecload")
+ (and (eq_attr "type" "fpload")
+ (eq_attr "update" "no")))
(eq_attr "cpu" "power8"))
"DU_any_power8,LU_power8")
(define_insn_reservation "power8-fpload-update" 5
- (and (eq_attr "type" "fpload_u,fpload_ux")
+ (and (eq_attr "type" "fpload")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "power8"))
"DU_cracked_power8,LU_power8+FXU_power8")
(define_insn_reservation "power8-store" 5 ; store-forwarding latency
- (and (eq_attr "type" "store,store_u")
+ (and (eq_attr "type" "store")
+ (not (and (eq_attr "update" "yes")
+ (eq_attr "indexed" "yes")))
(eq_attr "cpu" "power8"))
"DU_any_power8,LSU_power8+LU_power8")
(define_insn_reservation "power8-store-update-indexed" 5
- (and (eq_attr "type" "store_ux")
+ (and (eq_attr "type" "store")
+ (eq_attr "update" "yes")
+ (eq_attr "indexed" "yes")
(eq_attr "cpu" "power8"))
"DU_cracked_power8,LSU_power8+LU_power8")
(define_insn_reservation "power8-fpstore" 5
(and (eq_attr "type" "fpstore")
+ (eq_attr "update" "no")
(eq_attr "cpu" "power8"))
"DU_any_power8,LSU_power8+VSU_power8")
(define_insn_reservation "power8-fpstore-update" 5
- (and (eq_attr "type" "fpstore_u,fpstore_ux")
+ (and (eq_attr "type" "fpstore")
+ (eq_attr "update" "yes")
(eq_attr "cpu" "power8"))
"DU_any_power8,LSU_power8+VSU_power8")
@@ -151,8 +168,9 @@
; FX Unit
(define_insn_reservation "power8-1cyc" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,shift,trap,\
- var_shift_rotate,exts,isel")
+ (and (ior (eq_attr "type" "integer,insert,trap,exts,isel")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no")))
(eq_attr "cpu" "power8"))
"DU_any_power8,FXU_power8")
@@ -187,17 +205,19 @@
(eq_attr "cpu" "power8"))
"DU_any_power8,FXU_power8")
-; fast_compare : add./and./nor./etc
+; add/logical with dot : add./and./nor./etc
(define_insn_reservation "power8-fast-compare" 2
- (and (eq_attr "type" "fast_compare")
+ (and (eq_attr "type" "add,logical")
+ (eq_attr "dot" "yes")
(eq_attr "cpu" "power8"))
"DU_any_power8,FXU_power8")
; compare : rldicl./exts./etc
-; delayed_compare : rlwinm./slwi./etc
-; var_delayed_compare : rlwnm./slw./etc
+; shift with dot : rlwinm./slwi./rlwnm./slw./etc
(define_insn_reservation "power8-compare" 2
- (and (eq_attr "type" "compare,delayed_compare,var_delayed_compare")
+ (and (ior (eq_attr "type" "compare")
+ (and (eq_attr "type" "shift")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "power8"))
"DU_cracked_power8,FXU_power8,FXU_power8")
@@ -211,12 +231,14 @@
"power8-crlogical,power8-mfcr,power8-mfcrf,power8-branch")
(define_insn_reservation "power8-mul" 4
- (and (eq_attr "type" "imul,imul2,imul3,lmul")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "no")
(eq_attr "cpu" "power8"))
"DU_any_power8,FXU_power8")
(define_insn_reservation "power8-mul-compare" 4
- (and (eq_attr "type" "imul_compare,lmul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "dot" "yes")
(eq_attr "cpu" "power8"))
"DU_cracked_power8,FXU_power8")
@@ -231,12 +253,14 @@
; FXU divides are not pipelined
(define_insn_reservation "power8-idiv" 37
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "32")
(eq_attr "cpu" "power8"))
"DU_any_power8,fxu0_power8*37|fxu1_power8*37")
(define_insn_reservation "power8-ldiv" 68
- (and (eq_attr "type" "ldiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "64")
(eq_attr "cpu" "power8"))
"DU_any_power8,fxu0_power8*68|fxu1_power8*68")
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 47050c3d03e..f538b422e8e 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -743,13 +743,12 @@
|| GET_CODE (XEXP (op, 0)) == PRE_DEC
|| GET_CODE (XEXP (op, 0)) == PRE_MODIFY))"))
-;; Return 1 if the operand is a MEM with an update-indexed-form address. Note
-;; that PRE_INC/PRE_DEC will always be non-indexed (i.e. non X-form) since the
-;; increment is based on the mode size and will therefor always be a const.
-(define_special_predicate "update_indexed_address_mem"
+;; Return 1 if the operand is a MEM with an indexed-form address.
+(define_special_predicate "indexed_address_mem"
(match_test "(MEM_P (op)
- && GET_CODE (XEXP (op, 0)) == PRE_MODIFY
- && indexed_address (XEXP (XEXP (op, 0), 1), mode))"))
+ && (indexed_address (XEXP (op, 0), mode)
+ || (GET_CODE (XEXP (op, 0)) == PRE_MODIFY
+ && indexed_address (XEXP (XEXP (op, 0), 1), mode))))"))
;; Used for the destination of the fix_truncdfsi2 expander.
;; If stfiwx will be used, the result goes to memory; otherwise,
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 69bb26331f3..bbcc1df471b 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -114,7 +114,7 @@ extern void rs6000_emit_cbranch (enum machine_mode, rtx[]);
extern char * output_cbranch (rtx, const char *, int, rtx);
extern char * output_e500_flip_gt_bit (rtx, rtx);
extern const char * output_probe_stack_range (rtx, rtx);
-extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int);
+extern bool rs6000_emit_set_const (rtx, rtx);
extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx);
extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index e4a68347f57..4dcbaf83153 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -79,6 +79,7 @@
#include "dumpfile.h"
#include "cgraph.h"
#include "target-globals.h"
+#include "builtins.h"
#if TARGET_XCOFF
#include "xcoffout.h" /* get declarations of xcoff_*_section_name */
#endif
@@ -1068,7 +1069,7 @@ static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *);
static tree rs6000_builtin_vectorized_libmass (tree, tree, tree);
-static rtx rs6000_emit_set_long_const (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
+static void rs6000_emit_set_long_const (rtx, HOST_WIDE_INT);
static int rs6000_memory_move_cost (enum machine_mode, reg_class_t, bool);
static bool rs6000_debug_rtx_costs (rtx, int, int, int, int *, bool);
static int rs6000_debug_address_cost (rtx, enum machine_mode, addr_space_t,
@@ -6124,7 +6125,8 @@ mem_operand_gpr (rtx op, enum machine_mode mode)
return false;
extra = GET_MODE_SIZE (mode) - UNITS_PER_WORD;
- gcc_assert (extra >= 0);
+ if (extra < 0)
+ extra = 0;
if (GET_CODE (addr) == LO_SUM)
/* For lo_sum addresses, we must allow any offset except one that
@@ -6803,6 +6805,16 @@ rs6000_output_dwarf_dtprel (FILE *file, int size, rtx x)
fputs ("@dtprel+0x8000", file);
}
+/* Return true if X is a symbol that refers to real (rather than emulated)
+ TLS. */
+
+static bool
+rs6000_real_tls_symbol_ref_p (rtx x)
+{
+ return (GET_CODE (x) == SYMBOL_REF
+ && SYMBOL_REF_TLS_MODEL (x) >= TLS_MODEL_REAL);
+}
+
/* In the name of slightly smaller debug output, and to cater to
general assembler lossage, recognize various UNSPEC sequences
and turn them back into a direct symbol reference. */
@@ -6860,7 +6872,7 @@ rs6000_delegitimize_address (rtx orig_x)
if (TARGET_XCOFF
&& GET_CODE (y) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (y)
- && SYMBOL_REF_TLS_MODEL (get_pool_constant (y)) >= TLS_MODEL_REAL)
+ && rs6000_real_tls_symbol_ref_p (get_pool_constant (y)))
return orig_x;
#endif
@@ -7838,53 +7850,50 @@ rs6000_conditional_register_usage (void)
}
-/* Try to output insns to set TARGET equal to the constant C if it can
- be done in less than N insns. Do all computations in MODE.
- Returns the place where the output has been placed if it can be
- done and the insns have been emitted. If it would take more than N
- insns, zero is returned and no insns and emitted. */
+/* Output insns to set DEST equal to the constant SOURCE as a series of
+ lis, ori and shl instructions and return TRUE. */
-rtx
-rs6000_emit_set_const (rtx dest, enum machine_mode mode,
- rtx source, int n ATTRIBUTE_UNUSED)
+bool
+rs6000_emit_set_const (rtx dest, rtx source)
{
- rtx result, insn, set;
- HOST_WIDE_INT c0, c1;
+ enum machine_mode mode = GET_MODE (dest);
+ rtx temp, insn, set;
+ HOST_WIDE_INT c;
+ gcc_checking_assert (CONST_INT_P (source));
+ c = INTVAL (source);
switch (mode)
{
- case QImode:
+ case QImode:
case HImode:
- if (dest == NULL)
- dest = gen_reg_rtx (mode);
emit_insn (gen_rtx_SET (VOIDmode, dest, source));
- return dest;
+ return true;
case SImode:
- result = !can_create_pseudo_p () ? dest : gen_reg_rtx (SImode);
+ temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (SImode);
- emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (result),
- GEN_INT (INTVAL (source)
- & (~ (HOST_WIDE_INT) 0xffff))));
+ emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (temp),
+ GEN_INT (c & ~(HOST_WIDE_INT) 0xffff)));
emit_insn (gen_rtx_SET (VOIDmode, dest,
- gen_rtx_IOR (SImode, copy_rtx (result),
- GEN_INT (INTVAL (source) & 0xffff))));
- result = dest;
+ gen_rtx_IOR (SImode, copy_rtx (temp),
+ GEN_INT (c & 0xffff))));
break;
case DImode:
- switch (GET_CODE (source))
+ if (!TARGET_POWERPC64)
{
- case CONST_INT:
- c0 = INTVAL (source);
- c1 = -(c0 < 0);
- break;
+ rtx hi, lo;
- default:
- gcc_unreachable ();
+ hi = operand_subword_force (copy_rtx (dest), WORDS_BIG_ENDIAN == 0,
+ DImode);
+ lo = operand_subword_force (dest, WORDS_BIG_ENDIAN != 0,
+ DImode);
+ emit_move_insn (hi, GEN_INT (c >> 32));
+ c = ((c & 0xffffffff) ^ 0x80000000) - 0x80000000;
+ emit_move_insn (lo, GEN_INT (c));
}
-
- result = rs6000_emit_set_long_const (dest, c0, c1);
+ else
+ rs6000_emit_set_long_const (dest, c);
break;
default:
@@ -7894,107 +7903,103 @@ rs6000_emit_set_const (rtx dest, enum machine_mode mode,
insn = get_last_insn ();
set = single_set (insn);
if (! CONSTANT_P (SET_SRC (set)))
- set_unique_reg_note (insn, REG_EQUAL, source);
+ set_unique_reg_note (insn, REG_EQUAL, GEN_INT (c));
- return result;
+ return true;
}
-/* Having failed to find a 3 insn sequence in rs6000_emit_set_const,
- fall back to a straight forward decomposition. We do this to avoid
- exponential run times encountered when looking for longer sequences
- with rs6000_emit_set_const. */
-static rtx
-rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
-{
- if (!TARGET_POWERPC64)
- {
- rtx operand1, operand2;
+/* Subroutine of rs6000_emit_set_const, handling PowerPC64 DImode.
+ Output insns to set DEST equal to the constant C as a series of
+ lis, ori and shl instructions. */
- operand1 = operand_subword_force (dest, WORDS_BIG_ENDIAN == 0,
- DImode);
- operand2 = operand_subword_force (copy_rtx (dest), WORDS_BIG_ENDIAN != 0,
- DImode);
- emit_move_insn (operand1, GEN_INT (c1));
- emit_move_insn (operand2, GEN_INT (c2));
+static void
+rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c)
+{
+ rtx temp;
+ HOST_WIDE_INT ud1, ud2, ud3, ud4;
+
+ ud1 = c & 0xffff;
+ c = c >> 16;
+ ud2 = c & 0xffff;
+ c = c >> 16;
+ ud3 = c & 0xffff;
+ c = c >> 16;
+ ud4 = c & 0xffff;
+
+ if ((ud4 == 0xffff && ud3 == 0xffff && ud2 == 0xffff && (ud1 & 0x8000))
+ || (ud4 == 0 && ud3 == 0 && ud2 == 0 && ! (ud1 & 0x8000)))
+ emit_move_insn (dest, GEN_INT ((ud1 ^ 0x8000) - 0x8000));
+
+ else if ((ud4 == 0xffff && ud3 == 0xffff && (ud2 & 0x8000))
+ || (ud4 == 0 && ud3 == 0 && ! (ud2 & 0x8000)))
+ {
+ temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode);
+
+ emit_move_insn (ud1 != 0 ? copy_rtx (temp) : dest,
+ GEN_INT (((ud2 << 16) ^ 0x80000000) - 0x80000000));
+ if (ud1 != 0)
+ emit_move_insn (dest,
+ gen_rtx_IOR (DImode, copy_rtx (temp),
+ GEN_INT (ud1)));
+ }
+ else if (ud3 == 0 && ud4 == 0)
+ {
+ temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode);
+
+ gcc_assert (ud2 & 0x8000);
+ emit_move_insn (copy_rtx (temp),
+ GEN_INT (((ud2 << 16) ^ 0x80000000) - 0x80000000));
+ if (ud1 != 0)
+ emit_move_insn (copy_rtx (temp),
+ gen_rtx_IOR (DImode, copy_rtx (temp),
+ GEN_INT (ud1)));
+ emit_move_insn (dest,
+ gen_rtx_ZERO_EXTEND (DImode,
+ gen_lowpart (SImode,
+ copy_rtx (temp))));
+ }
+ else if ((ud4 == 0xffff && (ud3 & 0x8000))
+ || (ud4 == 0 && ! (ud3 & 0x8000)))
+ {
+ temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode);
+
+ emit_move_insn (copy_rtx (temp),
+ GEN_INT (((ud3 << 16) ^ 0x80000000) - 0x80000000));
+ if (ud2 != 0)
+ emit_move_insn (copy_rtx (temp),
+ gen_rtx_IOR (DImode, copy_rtx (temp),
+ GEN_INT (ud2)));
+ emit_move_insn (ud1 != 0 ? copy_rtx (temp) : dest,
+ gen_rtx_ASHIFT (DImode, copy_rtx (temp),
+ GEN_INT (16)));
+ if (ud1 != 0)
+ emit_move_insn (dest,
+ gen_rtx_IOR (DImode, copy_rtx (temp),
+ GEN_INT (ud1)));
}
else
{
- HOST_WIDE_INT ud1, ud2, ud3, ud4;
-
- ud1 = c1 & 0xffff;
- ud2 = (c1 & 0xffff0000) >> 16;
- c2 = c1 >> 32;
- ud3 = c2 & 0xffff;
- ud4 = (c2 & 0xffff0000) >> 16;
-
- if ((ud4 == 0xffff && ud3 == 0xffff && ud2 == 0xffff && (ud1 & 0x8000))
- || (ud4 == 0 && ud3 == 0 && ud2 == 0 && ! (ud1 & 0x8000)))
- emit_move_insn (dest, GEN_INT ((ud1 ^ 0x8000) - 0x8000));
-
- else if ((ud4 == 0xffff && ud3 == 0xffff && (ud2 & 0x8000))
- || (ud4 == 0 && ud3 == 0 && ! (ud2 & 0x8000)))
- {
- emit_move_insn (dest, GEN_INT (((ud2 << 16) ^ 0x80000000)
- - 0x80000000));
- if (ud1 != 0)
- emit_move_insn (copy_rtx (dest),
- gen_rtx_IOR (DImode, copy_rtx (dest),
- GEN_INT (ud1)));
- }
- else if (ud3 == 0 && ud4 == 0)
- {
- gcc_assert (ud2 & 0x8000);
- emit_move_insn (dest, GEN_INT (((ud2 << 16) ^ 0x80000000)
- - 0x80000000));
- if (ud1 != 0)
- emit_move_insn (copy_rtx (dest),
- gen_rtx_IOR (DImode, copy_rtx (dest),
- GEN_INT (ud1)));
- emit_move_insn (copy_rtx (dest),
- gen_rtx_ZERO_EXTEND (DImode,
- gen_lowpart (SImode,
- copy_rtx (dest))));
- }
- else if ((ud4 == 0xffff && (ud3 & 0x8000))
- || (ud4 == 0 && ! (ud3 & 0x8000)))
- {
- emit_move_insn (dest, GEN_INT (((ud3 << 16) ^ 0x80000000)
- - 0x80000000));
- if (ud2 != 0)
- emit_move_insn (copy_rtx (dest),
- gen_rtx_IOR (DImode, copy_rtx (dest),
- GEN_INT (ud2)));
- emit_move_insn (copy_rtx (dest),
- gen_rtx_ASHIFT (DImode, copy_rtx (dest),
- GEN_INT (16)));
- if (ud1 != 0)
- emit_move_insn (copy_rtx (dest),
- gen_rtx_IOR (DImode, copy_rtx (dest),
- GEN_INT (ud1)));
- }
- else
- {
- emit_move_insn (dest, GEN_INT (((ud4 << 16) ^ 0x80000000)
- - 0x80000000));
- if (ud3 != 0)
- emit_move_insn (copy_rtx (dest),
- gen_rtx_IOR (DImode, copy_rtx (dest),
- GEN_INT (ud3)));
-
- emit_move_insn (copy_rtx (dest),
- gen_rtx_ASHIFT (DImode, copy_rtx (dest),
- GEN_INT (32)));
- if (ud2 != 0)
- emit_move_insn (copy_rtx (dest),
- gen_rtx_IOR (DImode, copy_rtx (dest),
- GEN_INT (ud2 << 16)));
- if (ud1 != 0)
- emit_move_insn (copy_rtx (dest),
- gen_rtx_IOR (DImode, copy_rtx (dest),
- GEN_INT (ud1)));
- }
+ temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode);
+
+ emit_move_insn (copy_rtx (temp),
+ GEN_INT (((ud4 << 16) ^ 0x80000000) - 0x80000000));
+ if (ud3 != 0)
+ emit_move_insn (copy_rtx (temp),
+ gen_rtx_IOR (DImode, copy_rtx (temp),
+ GEN_INT (ud3)));
+
+ emit_move_insn (ud2 != 0 || ud1 != 0 ? copy_rtx (temp) : dest,
+ gen_rtx_ASHIFT (DImode, copy_rtx (temp),
+ GEN_INT (32)));
+ if (ud2 != 0)
+ emit_move_insn (ud1 != 0 ? copy_rtx (temp) : dest,
+ gen_rtx_IOR (DImode, copy_rtx (temp),
+ GEN_INT (ud2 << 16)));
+ if (ud1 != 0)
+ emit_move_insn (dest,
+ gen_rtx_IOR (DImode, copy_rtx (temp),
+ GEN_INT (ud1)));
}
- return dest;
}
/* Helper for the following. Get rid of [r+r] memory refs
@@ -15093,7 +15098,7 @@ builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0,
found = htab_find_slot (builtin_hash_table, &h, INSERT);
if (*found == NULL)
{
- h2 = ggc_alloc_builtin_hash_struct ();
+ h2 = ggc_alloc<builtin_hash_struct> ();
*h2 = h;
*found = (void *)h2;
@@ -15443,7 +15448,7 @@ expand_block_clear (rtx operands[])
load zero and three to do clearing. */
if (TARGET_ALTIVEC && align >= 128)
clear_step = 16;
- else if (TARGET_POWERPC64 && align >= 32)
+ else if (TARGET_POWERPC64 && (align >= 64 || !STRICT_ALIGNMENT))
clear_step = 8;
else if (TARGET_SPE && align >= 64)
clear_step = 8;
@@ -15471,12 +15476,27 @@ expand_block_clear (rtx operands[])
mode = V2SImode;
}
else if (bytes >= 8 && TARGET_POWERPC64
- /* 64-bit loads and stores require word-aligned
- displacements. */
- && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32)))
+ && (align >= 64 || !STRICT_ALIGNMENT))
{
clear_bytes = 8;
mode = DImode;
+ if (offset == 0 && align < 64)
+ {
+ rtx addr;
+
+ /* If the address form is reg+offset with offset not a
+ multiple of four, reload into reg indirect form here
+ rather than waiting for reload. This way we get one
+ reload, not one per store. */
+ addr = XEXP (orig_dest, 0);
+ if ((GET_CODE (addr) == PLUS || GET_CODE (addr) == LO_SUM)
+ && GET_CODE (XEXP (addr, 1)) == CONST_INT
+ && (INTVAL (XEXP (addr, 1)) & 3) != 0)
+ {
+ addr = copy_addr_to_reg (addr);
+ orig_dest = replace_equiv_address (orig_dest, addr);
+ }
+ }
}
else if (bytes >= 4 && (align >= 32 || !STRICT_ALIGNMENT))
{ /* move 4 bytes */
@@ -15604,13 +15624,36 @@ expand_block_move (rtx operands[])
gen_func.movmemsi = gen_movmemsi_4reg;
}
else if (bytes >= 8 && TARGET_POWERPC64
- /* 64-bit loads and stores require word-aligned
- displacements. */
- && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32)))
+ && (align >= 64 || !STRICT_ALIGNMENT))
{
move_bytes = 8;
mode = DImode;
gen_func.mov = gen_movdi;
+ if (offset == 0 && align < 64)
+ {
+ rtx addr;
+
+ /* If the address form is reg+offset with offset not a
+ multiple of four, reload into reg indirect form here
+ rather than waiting for reload. This way we get one
+ reload, not one per load and/or store. */
+ addr = XEXP (orig_dest, 0);
+ if ((GET_CODE (addr) == PLUS || GET_CODE (addr) == LO_SUM)
+ && GET_CODE (XEXP (addr, 1)) == CONST_INT
+ && (INTVAL (XEXP (addr, 1)) & 3) != 0)
+ {
+ addr = copy_addr_to_reg (addr);
+ orig_dest = replace_equiv_address (orig_dest, addr);
+ }
+ addr = XEXP (orig_src, 0);
+ if ((GET_CODE (addr) == PLUS || GET_CODE (addr) == LO_SUM)
+ && GET_CODE (XEXP (addr, 1)) == CONST_INT
+ && (INTVAL (XEXP (addr, 1)) & 3) != 0)
+ {
+ addr = copy_addr_to_reg (addr);
+ orig_src = replace_equiv_address (orig_src, addr);
+ }
+ }
}
else if (TARGET_STRING && bytes > 4 && !TARGET_POWERPC64)
{ /* move up to 8 bytes at a time */
@@ -17587,7 +17630,7 @@ static struct machine_function *
rs6000_init_machine_status (void)
{
stack_info.reload_completed = 0;
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
#define INT_P(X) (GET_CODE (X) == CONST_INT && GET_MODE (X) == VOIDmode)
@@ -25411,7 +25454,7 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
toc_hash_table = htab_create_ggc (1021, toc_hash_function,
toc_hash_eq, NULL);
- h = ggc_alloc_toc_hash_struct ();
+ h = ggc_alloc<toc_hash_struct> ();
h->key = x;
h->key_mode = mode;
h->labelno = labelno;
@@ -26139,24 +26182,28 @@ rs6000_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
{
case TYPE_CMP:
case TYPE_COMPARE:
- case TYPE_DELAYED_COMPARE:
- case TYPE_IMUL_COMPARE:
- case TYPE_LMUL_COMPARE:
case TYPE_FPCOMPARE:
case TYPE_CR_LOGICAL:
case TYPE_DELAYED_CR:
return cost + 2;
+ case TYPE_MUL:
+ if (get_attr_dot (dep_insn) == DOT_YES)
+ return cost + 2;
+ else
+ break;
+ case TYPE_SHIFT:
+ if (get_attr_dot (dep_insn) == DOT_YES
+ && get_attr_var_shift (dep_insn) == VAR_SHIFT_NO)
+ return cost + 2;
+ else
+ break;
default:
break;
}
break;
case TYPE_STORE:
- case TYPE_STORE_U:
- case TYPE_STORE_UX:
case TYPE_FPSTORE:
- case TYPE_FPSTORE_U:
- case TYPE_FPSTORE_UX:
if ((rs6000_cpu == PROCESSOR_POWER6)
&& recog_memoized (dep_insn)
&& (INSN_CODE (dep_insn) >= 0))
@@ -26173,63 +26220,50 @@ rs6000_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
switch (get_attr_type (dep_insn))
{
case TYPE_LOAD:
- case TYPE_LOAD_U:
- case TYPE_LOAD_UX:
case TYPE_CNTLZ:
{
if (! store_data_bypass_p (dep_insn, insn))
- return 4;
+ return get_attr_sign_extend (dep_insn)
+ == SIGN_EXTEND_YES ? 6 : 4;
break;
}
- case TYPE_LOAD_EXT:
- case TYPE_LOAD_EXT_U:
- case TYPE_LOAD_EXT_UX:
- case TYPE_VAR_SHIFT_ROTATE:
- case TYPE_VAR_DELAYED_COMPARE:
+ case TYPE_SHIFT:
{
if (! store_data_bypass_p (dep_insn, insn))
- return 6;
+ return get_attr_var_shift (dep_insn) == VAR_SHIFT_YES ?
+ 6 : 3;
break;
}
case TYPE_INTEGER:
+ case TYPE_ADD:
+ case TYPE_LOGICAL:
case TYPE_COMPARE:
- case TYPE_FAST_COMPARE:
case TYPE_EXTS:
- case TYPE_SHIFT:
- case TYPE_INSERT_WORD:
- case TYPE_INSERT_DWORD:
- case TYPE_FPLOAD_U:
- case TYPE_FPLOAD_UX:
- case TYPE_STORE_U:
- case TYPE_STORE_UX:
- case TYPE_FPSTORE_U:
- case TYPE_FPSTORE_UX:
+ case TYPE_INSERT:
{
if (! store_data_bypass_p (dep_insn, insn))
return 3;
break;
}
- case TYPE_IMUL:
- case TYPE_IMUL2:
- case TYPE_IMUL3:
- case TYPE_LMUL:
- case TYPE_IMUL_COMPARE:
- case TYPE_LMUL_COMPARE:
+ case TYPE_STORE:
+ case TYPE_FPLOAD:
+ case TYPE_FPSTORE:
{
- if (! store_data_bypass_p (dep_insn, insn))
- return 17;
+ if (get_attr_update (dep_insn) == UPDATE_YES
+ && ! store_data_bypass_p (dep_insn, insn))
+ return 3;
break;
}
- case TYPE_IDIV:
+ case TYPE_MUL:
{
if (! store_data_bypass_p (dep_insn, insn))
- return 45;
+ return 17;
break;
}
- case TYPE_LDIV:
+ case TYPE_DIV:
{
if (! store_data_bypass_p (dep_insn, insn))
- return 57;
+ return get_attr_size (dep_insn) == SIZE_32 ? 45 : 57;
break;
}
default:
@@ -26239,11 +26273,6 @@ rs6000_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
break;
case TYPE_LOAD:
- case TYPE_LOAD_U:
- case TYPE_LOAD_UX:
- case TYPE_LOAD_EXT:
- case TYPE_LOAD_EXT_U:
- case TYPE_LOAD_EXT_UX:
if ((rs6000_cpu == PROCESSOR_POWER6)
&& recog_memoized (dep_insn)
&& (INSN_CODE (dep_insn) >= 0))
@@ -26255,63 +26284,50 @@ rs6000_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
switch (get_attr_type (dep_insn))
{
case TYPE_LOAD:
- case TYPE_LOAD_U:
- case TYPE_LOAD_UX:
case TYPE_CNTLZ:
{
if (set_to_load_agen (dep_insn, insn))
- return 4;
+ return get_attr_sign_extend (dep_insn)
+ == SIGN_EXTEND_YES ? 6 : 4;
break;
}
- case TYPE_LOAD_EXT:
- case TYPE_LOAD_EXT_U:
- case TYPE_LOAD_EXT_UX:
- case TYPE_VAR_SHIFT_ROTATE:
- case TYPE_VAR_DELAYED_COMPARE:
+ case TYPE_SHIFT:
{
if (set_to_load_agen (dep_insn, insn))
- return 6;
+ return get_attr_var_shift (dep_insn) == VAR_SHIFT_YES ?
+ 6 : 3;
break;
- }
+ }
case TYPE_INTEGER:
+ case TYPE_ADD:
+ case TYPE_LOGICAL:
case TYPE_COMPARE:
- case TYPE_FAST_COMPARE:
case TYPE_EXTS:
- case TYPE_SHIFT:
- case TYPE_INSERT_WORD:
- case TYPE_INSERT_DWORD:
- case TYPE_FPLOAD_U:
- case TYPE_FPLOAD_UX:
- case TYPE_STORE_U:
- case TYPE_STORE_UX:
- case TYPE_FPSTORE_U:
- case TYPE_FPSTORE_UX:
+ case TYPE_INSERT:
{
if (set_to_load_agen (dep_insn, insn))
return 3;
break;
}
- case TYPE_IMUL:
- case TYPE_IMUL2:
- case TYPE_IMUL3:
- case TYPE_LMUL:
- case TYPE_IMUL_COMPARE:
- case TYPE_LMUL_COMPARE:
+ case TYPE_STORE:
+ case TYPE_FPLOAD:
+ case TYPE_FPSTORE:
{
- if (set_to_load_agen (dep_insn, insn))
- return 17;
+ if (get_attr_update (dep_insn) == UPDATE_YES
+ && set_to_load_agen (dep_insn, insn))
+ return 3;
break;
}
- case TYPE_IDIV:
+ case TYPE_MUL:
{
if (set_to_load_agen (dep_insn, insn))
- return 45;
+ return 17;
break;
}
- case TYPE_LDIV:
+ case TYPE_DIV:
{
if (set_to_load_agen (dep_insn, insn))
- return 57;
+ return get_attr_size (dep_insn) == SIZE_32 ? 45 : 57;
break;
}
default:
@@ -26322,6 +26338,7 @@ rs6000_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
case TYPE_FPLOAD:
if ((rs6000_cpu == PROCESSOR_POWER6)
+ && get_attr_update (insn) == UPDATE_NO
&& recog_memoized (dep_insn)
&& (INSN_CODE (dep_insn) >= 0)
&& (get_attr_type (dep_insn) == TYPE_MFFGPR))
@@ -26351,7 +26368,8 @@ rs6000_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
return 1;
break;
case TYPE_FPLOAD:
- if (get_attr_type (dep_insn) == TYPE_MFFGPR)
+ if (get_attr_update (insn) == UPDATE_NO
+ && get_attr_type (dep_insn) == TYPE_MFFGPR)
return 2;
break;
default:
@@ -26417,10 +26435,12 @@ is_microcoded_insn (rtx insn)
&& (rs6000_cpu == PROCESSOR_POWER4 || rs6000_cpu == PROCESSOR_POWER5))
{
enum attr_type type = get_attr_type (insn);
- if (type == TYPE_LOAD_EXT_U
- || type == TYPE_LOAD_EXT_UX
- || type == TYPE_LOAD_UX
- || type == TYPE_STORE_UX
+ if ((type == TYPE_LOAD
+ && get_attr_update (insn) == UPDATE_YES
+ && get_attr_sign_extend (insn) == SIGN_EXTEND_YES)
+ || ((type == TYPE_LOAD || type == TYPE_STORE)
+ && get_attr_update (insn) == UPDATE_YES
+ && get_attr_indexed (insn) == INDEXED_YES)
|| type == TYPE_MFCR)
return true;
}
@@ -26443,14 +26463,28 @@ is_cracked_insn (rtx insn)
&& (rs6000_cpu == PROCESSOR_POWER4 || rs6000_cpu == PROCESSOR_POWER5))
{
enum attr_type type = get_attr_type (insn);
- if (type == TYPE_LOAD_U || type == TYPE_STORE_U
- || type == TYPE_FPLOAD_U || type == TYPE_FPSTORE_U
- || type == TYPE_FPLOAD_UX || type == TYPE_FPSTORE_UX
- || type == TYPE_LOAD_EXT || type == TYPE_DELAYED_CR
- || type == TYPE_COMPARE || type == TYPE_DELAYED_COMPARE
- || type == TYPE_IMUL_COMPARE || type == TYPE_LMUL_COMPARE
- || type == TYPE_IDIV || type == TYPE_LDIV
- || type == TYPE_INSERT_WORD)
+ if ((type == TYPE_LOAD
+ && get_attr_sign_extend (insn) == SIGN_EXTEND_YES
+ && get_attr_update (insn) == UPDATE_NO)
+ || (type == TYPE_LOAD
+ && get_attr_sign_extend (insn) == SIGN_EXTEND_NO
+ && get_attr_update (insn) == UPDATE_YES
+ && get_attr_indexed (insn) == INDEXED_NO)
+ || (type == TYPE_STORE
+ && get_attr_update (insn) == UPDATE_YES
+ && get_attr_indexed (insn) == INDEXED_NO)
+ || ((type == TYPE_FPLOAD || type == TYPE_FPSTORE)
+ && get_attr_update (insn) == UPDATE_YES)
+ || type == TYPE_DELAYED_CR
+ || type == TYPE_COMPARE
+ || (type == TYPE_SHIFT
+ && get_attr_dot (insn) == DOT_YES
+ && get_attr_var_shift (insn) == VAR_SHIFT_NO)
+ || (type == TYPE_MUL
+ && get_attr_dot (insn) == DOT_YES)
+ || type == TYPE_DIV
+ || (type == TYPE_INSERT
+ && get_attr_size (insn) == SIZE_32))
return true;
}
@@ -26604,8 +26638,8 @@ rs6000_adjust_priority (rtx insn ATTRIBUTE_UNUSED, int priority)
default:
break;
- case TYPE_IMUL:
- case TYPE_IDIV:
+ case TYPE_MUL:
+ case TYPE_DIV:
fprintf (stderr, "priority was %#x (%d) before adjustment\n",
priority, priority);
if (priority >= 0 && priority < 0x01000000)
@@ -26658,12 +26692,8 @@ is_nonpipeline_insn (rtx insn)
return false;
type = get_attr_type (insn);
- if (type == TYPE_IMUL
- || type == TYPE_IMUL2
- || type == TYPE_IMUL3
- || type == TYPE_LMUL
- || type == TYPE_IDIV
- || type == TYPE_LDIV
+ if (type == TYPE_MUL
+ || type == TYPE_DIV
|| type == TYPE_SDIV
|| type == TYPE_DDIV
|| type == TYPE_SSQRT
@@ -26746,22 +26776,25 @@ rs6000_use_sched_lookahead (void)
}
}
-/* We are choosing insn from the ready queue. Return nonzero if INSN can be chosen. */
+/* We are choosing insn from the ready queue. Return zero if INSN can be
+ chosen. */
static int
-rs6000_use_sched_lookahead_guard (rtx insn)
+rs6000_use_sched_lookahead_guard (rtx insn, int ready_index)
{
+ if (ready_index == 0)
+ return 0;
+
if (rs6000_cpu_attr != CPU_CELL)
- return 1;
+ return 0;
- if (insn == NULL_RTX || !INSN_P (insn))
- abort ();
+ gcc_assert (insn != NULL_RTX && INSN_P (insn));
if (!reload_completed
|| is_nonpipeline_insn (insn)
|| is_microcoded_insn (insn))
- return 0;
+ return 1;
- return 1;
+ return 0;
}
/* Determine if PAT refers to memory. If so, set MEM_REF to the MEM rtx
@@ -27259,8 +27292,7 @@ insn_must_be_first_in_group (rtx insn)
case TYPE_CR_LOGICAL:
case TYPE_MTJMPR:
case TYPE_MFJMPR:
- case TYPE_IDIV:
- case TYPE_LDIV:
+ case TYPE_DIV:
case TYPE_LOAD_L:
case TYPE_STORE_C:
case TYPE_ISYNC:
@@ -27275,21 +27307,11 @@ insn_must_be_first_in_group (rtx insn)
switch (type)
{
- case TYPE_INSERT_DWORD:
case TYPE_EXTS:
case TYPE_CNTLZ:
- case TYPE_SHIFT:
- case TYPE_VAR_SHIFT_ROTATE:
case TYPE_TRAP:
- case TYPE_IMUL:
- case TYPE_IMUL2:
- case TYPE_IMUL3:
- case TYPE_LMUL:
- case TYPE_IDIV:
- case TYPE_INSERT_WORD:
- case TYPE_DELAYED_COMPARE:
- case TYPE_IMUL_COMPARE:
- case TYPE_LMUL_COMPARE:
+ case TYPE_MUL:
+ case TYPE_INSERT:
case TYPE_FPCOMPARE:
case TYPE_MFCR:
case TYPE_MTCR:
@@ -27299,16 +27321,26 @@ insn_must_be_first_in_group (rtx insn)
case TYPE_SYNC:
case TYPE_LOAD_L:
case TYPE_STORE_C:
- case TYPE_LOAD_U:
- case TYPE_LOAD_UX:
- case TYPE_LOAD_EXT_UX:
- case TYPE_STORE_U:
- case TYPE_STORE_UX:
- case TYPE_FPLOAD_U:
- case TYPE_FPLOAD_UX:
- case TYPE_FPSTORE_U:
- case TYPE_FPSTORE_UX:
return true;
+ case TYPE_SHIFT:
+ if (get_attr_dot (insn) == DOT_NO
+ || get_attr_var_shift (insn) == VAR_SHIFT_NO)
+ return true;
+ else
+ break;
+ case TYPE_DIV:
+ if (get_attr_size (insn) == SIZE_32)
+ return true;
+ else
+ break;
+ case TYPE_LOAD:
+ case TYPE_STORE:
+ case TYPE_FPLOAD:
+ case TYPE_FPSTORE:
+ if (get_attr_update (insn) == UPDATE_YES)
+ return true;
+ else
+ break;
default:
break;
}
@@ -27322,28 +27354,33 @@ insn_must_be_first_in_group (rtx insn)
case TYPE_MFCR:
case TYPE_MFCRF:
case TYPE_MTCR:
- case TYPE_IDIV:
- case TYPE_LDIV:
+ case TYPE_DIV:
case TYPE_COMPARE:
- case TYPE_DELAYED_COMPARE:
- case TYPE_VAR_DELAYED_COMPARE:
case TYPE_ISYNC:
case TYPE_LOAD_L:
case TYPE_STORE_C:
- case TYPE_LOAD_U:
- case TYPE_LOAD_UX:
- case TYPE_LOAD_EXT:
- case TYPE_LOAD_EXT_U:
- case TYPE_LOAD_EXT_UX:
- case TYPE_STORE_U:
- case TYPE_STORE_UX:
- case TYPE_FPLOAD_U:
- case TYPE_FPLOAD_UX:
- case TYPE_FPSTORE_U:
- case TYPE_FPSTORE_UX:
case TYPE_MFJMPR:
case TYPE_MTJMPR:
return true;
+ case TYPE_MUL:
+ case TYPE_SHIFT:
+ if (get_attr_dot (insn) == DOT_YES)
+ return true;
+ else
+ break;
+ case TYPE_LOAD:
+ if (get_attr_sign_extend (insn) == SIGN_EXTEND_YES
+ || get_attr_update (insn) == UPDATE_YES)
+ return true;
+ else
+ break;
+ case TYPE_STORE:
+ case TYPE_FPLOAD:
+ case TYPE_FPSTORE:
+ if (get_attr_update (insn) == UPDATE_YES)
+ return true;
+ else
+ break;
default:
break;
}
@@ -27359,24 +27396,32 @@ insn_must_be_first_in_group (rtx insn)
case TYPE_MFCRF:
case TYPE_MTCR:
case TYPE_COMPARE:
- case TYPE_DELAYED_COMPARE:
- case TYPE_VAR_DELAYED_COMPARE:
- case TYPE_IMUL_COMPARE:
- case TYPE_LMUL_COMPARE:
case TYPE_SYNC:
case TYPE_ISYNC:
case TYPE_LOAD_L:
case TYPE_STORE_C:
- case TYPE_LOAD_U:
- case TYPE_LOAD_UX:
- case TYPE_LOAD_EXT:
- case TYPE_LOAD_EXT_U:
- case TYPE_LOAD_EXT_UX:
- case TYPE_STORE_UX:
case TYPE_VECSTORE:
case TYPE_MFJMPR:
case TYPE_MTJMPR:
return true;
+ case TYPE_SHIFT:
+ case TYPE_MUL:
+ if (get_attr_dot (insn) == DOT_YES)
+ return true;
+ else
+ break;
+ case TYPE_LOAD:
+ if (get_attr_sign_extend (insn) == SIGN_EXTEND_YES
+ || get_attr_update (insn) == UPDATE_YES)
+ return true;
+ else
+ break;
+ case TYPE_STORE:
+ if (get_attr_update (insn) == UPDATE_YES
+ && get_attr_indexed (insn) == INDEXED_YES)
+ return true;
+ else
+ break;
default:
break;
}
@@ -27417,17 +27462,8 @@ insn_must_be_last_in_group (rtx insn)
{
case TYPE_EXTS:
case TYPE_CNTLZ:
- case TYPE_SHIFT:
- case TYPE_VAR_SHIFT_ROTATE:
case TYPE_TRAP:
- case TYPE_IMUL:
- case TYPE_IMUL2:
- case TYPE_IMUL3:
- case TYPE_LMUL:
- case TYPE_IDIV:
- case TYPE_DELAYED_COMPARE:
- case TYPE_IMUL_COMPARE:
- case TYPE_LMUL_COMPARE:
+ case TYPE_MUL:
case TYPE_FPCOMPARE:
case TYPE_MFCR:
case TYPE_MTCR:
@@ -27438,6 +27474,17 @@ insn_must_be_last_in_group (rtx insn)
case TYPE_LOAD_L:
case TYPE_STORE_C:
return true;
+ case TYPE_SHIFT:
+ if (get_attr_dot (insn) == DOT_NO
+ || get_attr_var_shift (insn) == VAR_SHIFT_NO)
+ return true;
+ else
+ break;
+ case TYPE_DIV:
+ if (get_attr_size (insn) == SIZE_32)
+ return true;
+ else
+ break;
default:
break;
}
@@ -27451,10 +27498,19 @@ insn_must_be_last_in_group (rtx insn)
case TYPE_SYNC:
case TYPE_LOAD_L:
case TYPE_STORE_C:
- case TYPE_LOAD_EXT_U:
- case TYPE_LOAD_EXT_UX:
- case TYPE_STORE_UX:
return true;
+ case TYPE_LOAD:
+ if (get_attr_sign_extend (insn) == SIGN_EXTEND_YES
+ && get_attr_update (insn) == UPDATE_YES)
+ return true;
+ else
+ break;
+ case TYPE_STORE:
+ if (get_attr_update (insn) == UPDATE_YES
+ && get_attr_indexed (insn) == INDEXED_YES)
+ return true;
+ else
+ break;
default:
break;
}
@@ -27470,10 +27526,19 @@ insn_must_be_last_in_group (rtx insn)
case TYPE_SYNC:
case TYPE_LOAD_L:
case TYPE_STORE_C:
- case TYPE_LOAD_EXT_U:
- case TYPE_LOAD_EXT_UX:
- case TYPE_STORE_UX:
return true;
+ case TYPE_LOAD:
+ if (get_attr_sign_extend (insn) == SIGN_EXTEND_YES
+ && get_attr_update (insn) == UPDATE_YES)
+ return true;
+ else
+ break;
+ case TYPE_STORE:
+ if (get_attr_update (insn) == UPDATE_YES
+ && get_attr_indexed (insn) == INDEXED_YES)
+ return true;
+ else
+ break;
default:
break;
}
@@ -32260,7 +32325,7 @@ rs6000_code_end (void)
#if RS6000_WEAK
if (USE_HIDDEN_LINKONCE)
{
- DECL_COMDAT_GROUP (decl) = DECL_ASSEMBLER_NAME (decl);
+ cgraph_create_node (decl)->set_comdat_group (DECL_ASSEMBLER_NAME (decl));
targetm.asm_out.unique_section (decl, 0);
switch_to_section (get_named_section (decl, NULL, 0));
DECL_WEAK (decl) = 1;
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index f6da9b3a382..f74d313610c 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -157,9 +157,58 @@
;; Define an insn type attribute. This is used in function unit delay
;; computations.
-(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt,crypto,htm"
+(define_attr "type"
+ "integer,two,three,
+ add,logical,shift,insert,
+ mul,halfmul,div,
+ exts,cntlz,popcnt,isel,
+ load,store,fpload,fpstore,vecload,vecstore,
+ cmp,
+ branch,jmpreg,mfjmpr,mtjmpr,trap,isync,sync,load_l,store_c,
+ compare,
+ cr_logical,delayed_cr,mfcr,mfcrf,mtcr,
+ fpcompare,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,
+ brinc,
+ vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,
+ vecfloat,vecfdiv,vecdouble,mffgpr,mftgpr,crypto,
+ htm"
(const_string "integer"))
+;; What data size does this instruction work on?
+;; This is used for insert, mul.
+(define_attr "size" "8,16,32,64" (const_string "32"))
+
+;; Is this instruction record form ("dot", signed compare to 0, writing CR0)?
+;; This is used for add, logical, shift, mul.
+(define_attr "dot" "no,yes" (const_string "no"))
+
+;; Does this instruction sign-extend its result?
+;; This is used for load insns.
+(define_attr "sign_extend" "no,yes" (const_string "no"))
+
+;; Does this instruction use indexed (that is, reg+reg) addressing?
+;; This is used for load and store insns. If operand 0 or 1 is a MEM
+;; it is automatically set based on that. If a load or store instruction
+;; has fewer than two operands it needs to set this attribute manually
+;; or the compiler will crash.
+(define_attr "indexed" "no,yes"
+ (if_then_else (ior (match_operand 0 "indexed_address_mem")
+ (match_operand 1 "indexed_address_mem"))
+ (const_string "yes")
+ (const_string "no")))
+
+;; Does this instruction use update addressing?
+;; This is used for load and store insns. See the comments for "indexed".
+(define_attr "update" "no,yes"
+ (if_then_else (ior (match_operand 0 "update_address_mem")
+ (match_operand 1 "update_address_mem"))
+ (const_string "yes")
+ (const_string "no")))
+
+;; Is this instruction using a shift amount from a register?
+;; This is used for shift insns.
+(define_attr "var_shift" "no,yes" (const_string "no"))
+
;; Define floating point instruction sub-types for use with Xfpu.md
(define_attr "fp_type" "fp_default,fp_addsub_s,fp_addsub_d,fp_mul_s,fp_mul_d,fp_div_s,fp_div_d,fp_maddsub_s,fp_maddsub_d,fp_sqrt_s,fp_sqrt_d" (const_string "fp_default"))
@@ -191,7 +240,13 @@
;; If this instruction is microcoded on the CELL processor
; The default for load extended, the recorded instructions and rotate/shifts by a variable is always microcoded
(define_attr "cell_micro" "not,conditional,always"
- (if_then_else (eq_attr "type" "compare,delayed_compare,imul_compare,lmul_compare,load_ext,load_ext_ux,var_shift_rotate,var_delayed_compare")
+ (if_then_else (ior (eq_attr "type" "compare")
+ (and (eq_attr "type" "shift,mul")
+ (eq_attr "dot" "yes"))
+ (and (eq_attr "type" "load")
+ (eq_attr "sign_extend" "yes"))
+ (and (eq_attr "type" "shift")
+ (eq_attr "var_shift" "yes")))
(const_string "always")
(const_string "not")))
@@ -374,6 +429,9 @@
(V4SI "w")
(V2DI "d")])
+;; How many bits in this mode?
+(define_mode_attr bits [(QI "8") (HI "16") (SI "32") (DI "64")])
+
; DImode bits
(define_mode_attr dbits [(QI "56") (HI "48") (SI "32")])
@@ -490,11 +548,6 @@
(V2DI "X,X,X,X,X")
(V2DF "X,X,X,X,X")
(V1TI "X,X,X,X,X")])
-
-;; Mode attribute to give the correct type for integer divides
-(define_mode_attr idiv_ldiv [(SI "idiv")
- (DI "ldiv")])
-
;; Start with fixed-point load and store insns. Here we put only the more
;; complex forms. Basic data transfer is done later.
@@ -512,15 +565,7 @@
"@
l<wd>z%U1%X1 %0,%1
rldicl %0,%1,0,<dbits>"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
- (const_string "*")])])
+ [(set_attr "type" "load,shift")])
(define_insn "*zero_extend<mode>di2_internal2"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -531,7 +576,8 @@
"@
rldicl. %2,%1,0,<dbits>
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -557,7 +603,8 @@
"@
rldicl. %0,%1,0,<dbits>
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -584,18 +631,7 @@
mtvsrwz %x0,%1
lfiwzx %0,%y1
lxsiwzx %x0,%y1"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
- (const_string "*")
- (const_string "mffgpr")
- (const_string "fpload")
- (const_string "fpload")])])
+ [(set_attr "type" "load,shift,mffgpr,fpload,fpload")])
(define_insn "extendqidi2"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
@@ -669,15 +705,8 @@
"@
lha%U1%X1 %0,%1
extsh %0,%1"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ext_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_ext_u")
- (const_string "load_ext")))
- (const_string "exts")])])
+ [(set_attr "type" "load,exts")
+ (set_attr "sign_extend" "yes")])
(define_insn ""
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
@@ -746,7 +775,7 @@
(define_insn "*extendsidi2_lfiwax"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wl,!wu")
- (sign_extend:DI (match_operand:SI 1 "lwa_operand" "m,r,r,Z,Z")))]
+ (sign_extend:DI (match_operand:SI 1 "lwa_operand" "Y,r,r,Z,Z")))]
"TARGET_POWERPC64 && TARGET_LFIWAX"
"@
lwa%U1%X1 %0,%1
@@ -754,35 +783,18 @@
mtvsrwa %x0,%1
lfiwax %0,%y1
lxsiwax %x0,%y1"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ext_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_ext_u")
- (const_string "load_ext")))
- (const_string "exts")
- (const_string "mffgpr")
- (const_string "fpload")
- (const_string "fpload")])])
+ [(set_attr "type" "load,exts,mffgpr,fpload,fpload")
+ (set_attr "sign_extend" "yes")])
(define_insn "*extendsidi2_nocell"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (sign_extend:DI (match_operand:SI 1 "lwa_operand" "m,r")))]
+ (sign_extend:DI (match_operand:SI 1 "lwa_operand" "Y,r")))]
"TARGET_POWERPC64 && rs6000_gen_cell_microcode && !TARGET_LFIWAX"
"@
lwa%U1%X1 %0,%1
extsw %0,%1"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ext_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_ext_u")
- (const_string "load_ext")))
- (const_string "exts")])])
+ [(set_attr "type" "load,exts")
+ (set_attr "sign_extend" "yes")])
(define_insn "*extendsidi2_nocell"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
@@ -856,15 +868,7 @@
"@
lbz%U1%X1 %0,%1
rlwinm %0,%1,0,0xff"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
- (const_string "*")])])
+ [(set_attr "type" "load,shift")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -875,7 +879,8 @@
"@
andi. %2,%1,0xff
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -901,7 +906,8 @@
"@
andi. %0,%1,0xff
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -984,15 +990,7 @@
"@
lbz%U1%X1 %0,%1
rlwinm %0,%1,0,0xff"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
- (const_string "*")])])
+ [(set_attr "type" "load,shift")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -1003,7 +1001,8 @@
"@
andi. %2,%1,0xff
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -1029,7 +1028,8 @@
"@
andi. %0,%1,0xff
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -1118,15 +1118,7 @@
"@
lhz%U1%X1 %0,%1
rlwinm %0,%1,0,0xffff"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
- (const_string "*")])])
+ [(set_attr "type" "load,shift")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -1137,7 +1129,8 @@
"@
andi. %2,%1,0xffff
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -1163,7 +1156,8 @@
"@
andi. %0,%1,0xffff
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -1193,15 +1187,8 @@
"@
lha%U1%X1 %0,%1
extsh %0,%1"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ext_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_ext_u")
- (const_string "load_ext")))
- (const_string "exts")])])
+ [(set_attr "type" "load,exts")
+ (set_attr "sign_extend" "yes")])
(define_insn ""
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1282,7 +1269,7 @@
(match_dup 4)))]
"TARGET_MULHW"
"macchw. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*macchw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1294,7 +1281,7 @@
(match_operand:SI 3 "gpc_reg_operand" "0")))]
"TARGET_MULHW"
"macchw %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*macchwuc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
@@ -1314,7 +1301,7 @@
(match_dup 4)))]
"TARGET_MULHW"
"macchwu. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*macchwu"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1326,7 +1313,7 @@
(match_operand:SI 3 "gpc_reg_operand" "0")))]
"TARGET_MULHW"
"macchwu %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*machhwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
@@ -1348,7 +1335,7 @@
(match_dup 4)))]
"TARGET_MULHW"
"machhw. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*machhw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1361,7 +1348,7 @@
(match_operand:SI 3 "gpc_reg_operand" "0")))]
"TARGET_MULHW"
"machhw %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*machhwuc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
@@ -1383,7 +1370,7 @@
(match_dup 4)))]
"TARGET_MULHW"
"machhwu. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*machhwu"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1396,7 +1383,7 @@
(match_operand:SI 3 "gpc_reg_operand" "0")))]
"TARGET_MULHW"
"machhwu %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*maclhwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
@@ -1414,7 +1401,7 @@
(match_dup 4)))]
"TARGET_MULHW"
"maclhw. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*maclhw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1425,7 +1412,7 @@
(match_operand:SI 3 "gpc_reg_operand" "0")))]
"TARGET_MULHW"
"maclhw %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*maclhwuc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
@@ -1443,7 +1430,7 @@
(match_dup 4)))]
"TARGET_MULHW"
"maclhwu. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*maclhwu"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1454,7 +1441,7 @@
(match_operand:SI 3 "gpc_reg_operand" "0")))]
"TARGET_MULHW"
"maclhwu %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*nmacchwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
@@ -1474,7 +1461,7 @@
(match_dup 1)))))]
"TARGET_MULHW"
"nmacchw. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*nmacchw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1486,7 +1473,7 @@
(match_operand:HI 1 "gpc_reg_operand" "r")))))]
"TARGET_MULHW"
"nmacchw %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*nmachhwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
@@ -1508,7 +1495,7 @@
(const_int 16)))))]
"TARGET_MULHW"
"nmachhw. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*nmachhw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1521,7 +1508,7 @@
(const_int 16)))))]
"TARGET_MULHW"
"nmachhw %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*nmaclhwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
@@ -1539,7 +1526,7 @@
(match_dup 2)))))]
"TARGET_MULHW"
"nmaclhw. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*nmaclhw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1550,7 +1537,7 @@
(match_operand:HI 2 "gpc_reg_operand" "r")))))]
"TARGET_MULHW"
"nmaclhw %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*mulchwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
@@ -1568,7 +1555,7 @@
(match_dup 1))))]
"TARGET_MULHW"
"mulchw. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*mulchw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1579,7 +1566,7 @@
(match_operand:HI 1 "gpc_reg_operand" "r"))))]
"TARGET_MULHW"
"mulchw %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*mulchwuc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
@@ -1597,7 +1584,7 @@
(match_dup 1))))]
"TARGET_MULHW"
"mulchwu. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*mulchwu"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1608,7 +1595,7 @@
(match_operand:HI 1 "gpc_reg_operand" "r"))))]
"TARGET_MULHW"
"mulchwu %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*mulhhwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
@@ -1628,7 +1615,7 @@
(const_int 16))))]
"TARGET_MULHW"
"mulhhw. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*mulhhw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1640,7 +1627,7 @@
(const_int 16))))]
"TARGET_MULHW"
"mulhhw %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*mulhhwuc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
@@ -1660,7 +1647,7 @@
(const_int 16))))]
"TARGET_MULHW"
"mulhhwu. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*mulhhwu"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1672,7 +1659,7 @@
(const_int 16))))]
"TARGET_MULHW"
"mulhhwu %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*mullhwc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
@@ -1688,7 +1675,7 @@
(match_dup 2))))]
"TARGET_MULHW"
"mullhw. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*mullhw"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1698,7 +1685,7 @@
(match_operand:HI 2 "gpc_reg_operand" "r"))))]
"TARGET_MULHW"
"mullhw %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*mullhwuc"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
@@ -1714,7 +1701,7 @@
(match_dup 2))))]
"TARGET_MULHW"
"mullhwu. %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
(define_insn "*mullhwu"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -1724,7 +1711,7 @@
(match_operand:HI 2 "gpc_reg_operand" "r"))))]
"TARGET_MULHW"
"mullhwu %0,%1,%2"
- [(set_attr "type" "imul3")])
+ [(set_attr "type" "halfmul")])
;; IBM 405, 440, 464 and 476 string-search dlmzb instruction support.
(define_insn "dlmzb"
@@ -1841,7 +1828,7 @@
addi %0,%1,%2
addic %0,%1,%2
addis %0,%1,%v2"
- [(set_attr "length" "4,4,4,4")])
+ [(set_attr "type" "add")])
(define_insn "addsi3_high"
[(set (match_operand:SI 0 "gpc_reg_operand" "=b")
@@ -1849,7 +1836,7 @@
(high:SI (match_operand 2 "" ""))))]
"TARGET_MACHO && !TARGET_64BIT"
"addis %0,%1,ha16(%2)"
- [(set_attr "length" "4")])
+ [(set_attr "type" "add")])
(define_insn "*add<mode>3_internal2"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -1863,7 +1850,8 @@
addic. %3,%1,%2
#
#"
- [(set_attr "type" "fast_compare,compare,compare,compare")
+ [(set_attr "type" "add,compare,compare,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -1895,7 +1883,8 @@
addic. %0,%1,%2
#
#"
- [(set_attr "type" "fast_compare,compare,compare,compare")
+ [(set_attr "type" "add,compare,compare,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -1971,7 +1960,8 @@
"@
nor. %2,%1,%1
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -1997,7 +1987,8 @@
"@
nor. %0,%1,%1
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -2021,7 +2012,8 @@
""
"@
subf %0,%2,%1
- subfic %0,%2,%1")
+ subfic %0,%2,%1"
+ [(set_attr "type" "add")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -2033,7 +2025,8 @@
"@
subf. %3,%2,%1
#"
- [(set_attr "type" "fast_compare")
+ [(set_attr "type" "add")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -2063,7 +2056,8 @@
"@
subf. %0,%2,%1
#"
- [(set_attr "type" "fast_compare")
+ [(set_attr "type" "add")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -2108,7 +2102,8 @@
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
""
- "neg %0,%1")
+ "neg %0,%1"
+ [(set_attr "type" "add")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -2119,7 +2114,8 @@
"@
neg. %2,%1
#"
- [(set_attr "type" "fast_compare")
+ [(set_attr "type" "add")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -2145,7 +2141,8 @@
"@
neg. %0,%1
#"
- [(set_attr "type" "fast_compare")
+ [(set_attr "type" "add")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -2699,12 +2696,13 @@
"@
mullw %0,%1,%2
mulli %0,%1,%2"
- [(set (attr "type")
+ [(set_attr "type" "mul")
+ (set (attr "size")
(cond [(match_operand:SI 2 "s8bit_cint_operand" "")
- (const_string "imul3")
+ (const_string "8")
(match_operand:SI 2 "short_cint_operand" "")
- (const_string "imul2")]
- (const_string "imul")))])
+ (const_string "16")]
+ (const_string "32")))])
(define_insn "*mulsi3_internal1"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -2716,7 +2714,8 @@
"@
mullw. %3,%1,%2
#"
- [(set_attr "type" "imul_compare")
+ [(set_attr "type" "mul")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -2744,7 +2743,8 @@
"@
mullw. %0,%1,%2
#"
- [(set_attr "type" "imul_compare")
+ [(set_attr "type" "mul")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -2769,7 +2769,8 @@
(match_operand:GPR 2 "gpc_reg_operand" "r")))]
""
"div<wd>u %0,%1,%2"
- [(set_attr "type" "<idiv_ldiv>")])
+ [(set_attr "type" "div")
+ (set_attr "size" "<bits>")])
;; For powers of two we can do srai/aze for divide and then adjust for
@@ -2793,7 +2794,8 @@
(match_operand:GPR 2 "gpc_reg_operand" "r")))]
""
"div<wd> %0,%1,%2"
- [(set_attr "type" "<idiv_ldiv>")])
+ [(set_attr "type" "div")
+ (set_attr "size" "<bits>")])
(define_expand "mod<mode>3"
[(use (match_operand:GPR 0 "gpc_reg_operand" ""))
@@ -2915,7 +2917,8 @@
rlwinm %0,%1,0,%m2,%M2
andi. %0,%1,%b2
andis. %0,%1,%u2"
- [(set_attr "type" "*,*,fast_compare,fast_compare")])
+ [(set_attr "type" "*,shift,logical,logical")
+ (set_attr "dot" "no,no,yes,yes")])
(define_insn "andsi3_nomc"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
@@ -2925,7 +2928,8 @@
"!rs6000_gen_cell_microcode"
"@
and %0,%1,%2
- rlwinm %0,%1,0,%m2,%M2")
+ rlwinm %0,%1,0,%m2,%M2"
+ [(set_attr "type" "logical,shift")])
(define_insn "andsi3_internal0_nomc"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
@@ -2934,7 +2938,8 @@
"!rs6000_gen_cell_microcode"
"@
and %0,%1,%2
- rlwinm %0,%1,0,%m2,%M2")
+ rlwinm %0,%1,0,%m2,%M2"
+ [(set_attr "type" "logical,shift")])
;; Note to set cr's other than cr0 we do the and immediate and then
@@ -2958,8 +2963,9 @@
#
#
#"
- [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\
+ [(set_attr "type" "logical,logical,logical,shift,\
compare,compare,compare,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,4,4,8,8,8,8")])
(define_insn "*andsi3_internal3_mc"
@@ -2979,8 +2985,9 @@
#
#
#"
- [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
+ [(set_attr "type" "compare,logical,logical,shift,compare,\
compare,compare,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "8,4,4,4,8,8,8,8")])
(define_split
@@ -3039,8 +3046,9 @@
#
#
#"
- [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\
+ [(set_attr "type" "logical,logical,logical,shift,\
compare,compare,compare,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,4,4,8,8,8,8")])
(define_insn "*andsi3_internal5_mc"
@@ -3062,8 +3070,9 @@
#
#
#"
- [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
+ [(set_attr "type" "compare,logical,logical,shift,compare,\
compare,compare,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "8,4,4,4,8,8,8,8")])
(define_split
@@ -3194,7 +3203,8 @@
"@
%q4. %3,%1,%2
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -3223,7 +3233,8 @@
"@
%q4. %0,%1,%2
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -3348,7 +3359,8 @@
"@
%q4. %3,%1,%2
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -3377,7 +3389,8 @@
"@
%q4. %0,%1,%2
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -3439,7 +3452,7 @@
operands[1] = GEN_INT (start + size - 1);
return \"rlwimi %0,%3,%h4,%h2,%h1\";
}"
- [(set_attr "type" "insert_word")])
+ [(set_attr "type" "insert")])
(define_insn "*insvsi_internal1"
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
@@ -3458,7 +3471,7 @@
operands[1] = GEN_INT (start + size - 1);
return \"rlwimi %0,%3,%h4,%h2,%h1\";
}"
- [(set_attr "type" "insert_word")])
+ [(set_attr "type" "insert")])
(define_insn "*insvsi_internal2"
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
@@ -3477,7 +3490,7 @@
operands[1] = GEN_INT (start + size - 1);
return \"rlwimi %0,%3,%h4,%h2,%h1\";
}"
- [(set_attr "type" "insert_word")])
+ [(set_attr "type" "insert")])
(define_insn "*insvsi_internal3"
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
@@ -3496,7 +3509,7 @@
operands[1] = GEN_INT (start + size - 1);
return \"rlwimi %0,%3,%h4,%h2,%h1\";
}"
- [(set_attr "type" "insert_word")])
+ [(set_attr "type" "insert")])
(define_insn "*insvsi_internal4"
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
@@ -3518,7 +3531,7 @@
operands[1] = GEN_INT (insert_start + insert_size - 1);
return \"rlwimi %0,%3,%h5,%h2,%h1\";
}"
- [(set_attr "type" "insert_word")])
+ [(set_attr "type" "insert")])
;; combine patterns for rlwimi
(define_insn "*insvsi_internal5"
@@ -3538,7 +3551,7 @@
operands[1] = GEN_INT(me);
return \"rlwimi %0,%3,%h4,%h2,%h1\";
}"
- [(set_attr "type" "insert_word")])
+ [(set_attr "type" "insert")])
(define_insn "*insvsi_internal6"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -3557,7 +3570,7 @@
operands[1] = GEN_INT(me);
return \"rlwimi %0,%3,%h4,%h2,%h1\";
}"
- [(set_attr "type" "insert_word")])
+ [(set_attr "type" "insert")])
(define_insn "insvdi_internal"
[(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
@@ -3573,7 +3586,8 @@
operands[1] = GEN_INT (64 - start - size);
return \"rldimi %0,%3,%H1,%H2\";
}"
- [(set_attr "type" "insert_dword")])
+ [(set_attr "type" "insert")
+ (set_attr "size" "64")])
(define_insn "*insvdi_internal2"
[(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
@@ -3655,7 +3669,8 @@
else
operands[3] = GEN_INT (start + size);
return \"rlwinm %0,%1,%3,%s2,31\";
-}")
+}"
+ [(set_attr "type" "shift")])
(define_insn "*extzvsi_internal1"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -3696,7 +3711,8 @@
operands[3] = GEN_INT (start + size);
return \"rlwinm. %4,%1,%3,%s2,31\";
}"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -3747,7 +3763,8 @@
operands[3] = GEN_INT (start + size);
return \"rlwinm. %0,%1,%3,%s2,31\";
}"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -3783,7 +3800,8 @@
operands[3] = GEN_INT (start + size);
operands[2] = GEN_INT (64 - size);
return \"rldicl %0,%1,%3,%2\";
-}")
+}"
+ [(set_attr "type" "shift")])
(define_insn "*extzvdi_internal1"
[(set (match_operand:CC 0 "gpc_reg_operand" "=x")
@@ -3805,7 +3823,8 @@
operands[2] = GEN_INT (64 - size);
return \"rldicl. %4,%1,%3,%2\";
}"
- [(set_attr "type" "compare")])
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")])
(define_insn "*extzvdi_internal2"
[(set (match_operand:CC 4 "gpc_reg_operand" "=x")
@@ -3828,7 +3847,8 @@
operands[2] = GEN_INT (64 - size);
return \"rldicl. %0,%1,%3,%2\";
}"
- [(set_attr "type" "compare")])
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")])
(define_insn "rotlsi3"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
@@ -3838,7 +3858,8 @@
"@
rlwnm %0,%1,%2,0xffffffff
rlwinm %0,%1,%h2,0xffffffff"
- [(set_attr "type" "var_shift_rotate,integer")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*rotlsi3_64"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
@@ -3849,7 +3870,8 @@
"@
rlwnm %0,%1,%2,0xffffffff
rlwinm %0,%1,%h2,0xffffffff"
- [(set_attr "type" "var_shift_rotate,integer")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*rotlsi3_internal2"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -3863,7 +3885,9 @@
rlwinm. %3,%1,%h2,0xffffffff
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -3893,7 +3917,9 @@
rlwinm. %0,%1,%h2,0xffffffff
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -3920,7 +3946,8 @@
"@
rlwnm %0,%1,%2,%m3,%M3
rlwinm %0,%1,%h2,%m3,%M3"
- [(set_attr "type" "var_shift_rotate,integer")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*rotlsi3_internal5"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -3936,7 +3963,9 @@
rlwinm. %4,%1,%h2,%m3,%M3
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -3972,7 +4001,9 @@
rlwinm. %0,%1,%h2,%m3,%M3
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -4003,7 +4034,8 @@
[(set (attr "cell_micro")
(if_then_else (match_operand:SI 2 "const_int_operand" "")
(const_string "not")
- (const_string "always")))])
+ (const_string "always")))
+ (set_attr "type" "shift")])
(define_insn "*rotlsi3_internal7be"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -4016,7 +4048,8 @@
[(set (attr "cell_micro")
(if_then_else (match_operand:SI 2 "const_int_operand" "")
(const_string "not")
- (const_string "always")))])
+ (const_string "always")))
+ (set_attr "type" "shift")])
(define_insn "*rotlsi3_internal8le"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -4032,7 +4065,9 @@
rlwinm. %3,%1,%h2,0xff
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_insn "*rotlsi3_internal8be"
@@ -4049,7 +4084,9 @@
rlwinm. %3,%1,%h2,0xff
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -4103,7 +4140,9 @@
rlwinm. %0,%1,%h2,0xff
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_insn "*rotlsi3_internal9be"
@@ -4121,7 +4160,9 @@
rlwinm. %0,%1,%h2,0xff
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -4168,7 +4209,8 @@
"@
rlwnm %0,%1,%2,0xffff
rlwinm %0,%1,%h2,0xffff"
- [(set_attr "type" "var_shift_rotate,integer")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*rotlsi3_internal10be"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
@@ -4180,7 +4222,8 @@
"@
rlwnm %0,%1,%2,0xffff
rlwinm %0,%1,%h2,0xffff"
- [(set_attr "type" "var_shift_rotate,integer")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*rotlsi3_internal11le"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -4196,7 +4239,9 @@
rlwinm. %3,%1,%h2,0xffff
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_insn "*rotlsi3_internal11be"
@@ -4213,7 +4258,9 @@
rlwinm. %3,%1,%h2,0xffff
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -4267,7 +4314,9 @@
rlwinm. %0,%1,%h2,0xffff
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_insn "*rotlsi3_internal12be"
@@ -4285,7 +4334,9 @@
rlwinm. %0,%1,%h2,0xffff
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -4330,7 +4381,8 @@
"@
slw %0,%1,%2
slwi %0,%1,%h2"
- [(set_attr "type" "var_shift_rotate,shift")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*ashlsi3_64"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
@@ -4341,7 +4393,8 @@
"@
slw %0,%1,%2
slwi %0,%1,%h2"
- [(set_attr "type" "var_shift_rotate,shift")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -4355,7 +4408,9 @@
slwi. %3,%1,%h2
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -4385,7 +4440,9 @@
slwi. %0,%1,%h2
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -4409,7 +4466,8 @@
(match_operand:SI 2 "const_int_operand" "i"))
(match_operand:SI 3 "mask_operand" "n")))]
"includes_lshift_p (operands[2], operands[3])"
- "rlwinm %0,%1,%h2,%m3,%M3")
+ "rlwinm %0,%1,%h2,%m3,%M3"
+ [(set_attr "type" "shift")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -4423,7 +4481,8 @@
"@
rlwinm. %4,%1,%h2,%m3,%M3
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -4456,7 +4515,8 @@
"@
rlwinm. %0,%1,%h2,%m3,%M3
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -4485,7 +4545,8 @@
mr %0,%1
srw %0,%1,%2
srwi %0,%1,%h2"
- [(set_attr "type" "integer,var_shift_rotate,shift")])
+ [(set_attr "type" "integer,shift,shift")
+ (set_attr "var_shift" "no,yes,no")])
(define_insn "*lshrsi3_64"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
@@ -4496,7 +4557,8 @@
"@
srw %0,%1,%2
srwi %0,%1,%h2"
- [(set_attr "type" "var_shift_rotate,shift")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,?y,?y,?y")
@@ -4512,7 +4574,9 @@
#
#
#"
- [(set_attr "type" "fast_compare,var_delayed_compare,delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "logical,shift,shift,shift,shift,shift")
+ (set_attr "var_shift" "no,yes,no,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,4,8,8,8")])
(define_split
@@ -4544,7 +4608,9 @@
#
#
#"
- [(set_attr "type" "fast_compare,var_delayed_compare,delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "logical,shift,shift,shift,shift,shift")
+ (set_attr "var_shift" "no,yes,no,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,4,8,8,8")])
(define_split
@@ -4568,7 +4634,8 @@
(match_operand:SI 2 "const_int_operand" "i"))
(match_operand:SI 3 "mask_operand" "n")))]
"includes_rshift_p (operands[2], operands[3])"
- "rlwinm %0,%1,%s2,%m3,%M3")
+ "rlwinm %0,%1,%s2,%m3,%M3"
+ [(set_attr "type" "shift")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -4582,7 +4649,8 @@
"@
rlwinm. %4,%1,%s2,%m3,%M3
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -4615,7 +4683,8 @@
"@
rlwinm. %0,%1,%s2,%m3,%M3
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -4642,7 +4711,8 @@
(lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i")) 0)))]
"!BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (255))"
- "rlwinm %0,%1,%s2,0xff")
+ "rlwinm %0,%1,%s2,0xff"
+ [(set_attr "type" "shift")])
(define_insn "*lshiftrt_internal1be"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -4651,7 +4721,8 @@
(lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i")) 3)))]
"BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (255))"
- "rlwinm %0,%1,%s2,0xff")
+ "rlwinm %0,%1,%s2,0xff"
+ [(set_attr "type" "shift")])
(define_insn "*lshiftrt_internal2le"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -4666,7 +4737,8 @@
"@
rlwinm. %3,%1,%s2,0xff
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "*lshiftrt_internal2be"
@@ -4682,7 +4754,8 @@
"@
rlwinm. %3,%1,%s2,0xff
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -4737,7 +4810,8 @@
"@
rlwinm. %0,%1,%s2,0xff
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "*lshiftrt_internal3be"
@@ -4754,7 +4828,8 @@
"@
rlwinm. %0,%1,%s2,0xff
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -4800,7 +4875,8 @@
(lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i")) 0)))]
"!BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (65535))"
- "rlwinm %0,%1,%s2,0xffff")
+ "rlwinm %0,%1,%s2,0xffff"
+ [(set_attr "type" "shift")])
(define_insn "*lshiftrt_internal4be"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -4809,7 +4885,8 @@
(lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i")) 2)))]
"BYTES_BIG_ENDIAN && includes_rshift_p (operands[2], GEN_INT (65535))"
- "rlwinm %0,%1,%s2,0xffff")
+ "rlwinm %0,%1,%s2,0xffff"
+ [(set_attr "type" "shift")])
(define_insn "*lshiftrt_internal5le"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -4824,7 +4901,8 @@
"@
rlwinm. %3,%1,%s2,0xffff
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "*lshiftrt_internal5be"
@@ -4840,7 +4918,8 @@
"@
rlwinm. %3,%1,%s2,0xffff
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -4895,7 +4974,8 @@
"@
rlwinm. %0,%1,%s2,0xffff
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_insn "*lshiftrt_internal5be"
@@ -4912,7 +4992,8 @@
"@
rlwinm. %0,%1,%s2,0xffff
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -4959,7 +5040,8 @@
"@
sraw %0,%1,%2
srawi %0,%1,%h2"
- [(set_attr "type" "var_shift_rotate,shift")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*ashrsi3_64"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
@@ -4970,7 +5052,8 @@
"@
sraw %0,%1,%2
srawi %0,%1,%h2"
- [(set_attr "type" "var_shift_rotate,shift")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -4984,7 +5067,9 @@
srawi. %3,%1,%h2
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -5014,7 +5099,9 @@
srawi. %0,%1,%h2
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
;; Builtins to replace a division to generate FRE reciprocal estimate
@@ -5260,25 +5347,7 @@
emit_note (NOTE_INSN_DELETED);
DONE;
}
- [(set_attr_alternative "type"
- [(const_string "fp")
- (const_string "fp")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_u")
- (const_string "fpload")))
- (const_string "fp")
- (const_string "vecsimple")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_u")
- (const_string "fpload")))])])
+ [(set_attr "type" "fp,fp,fpload,fp,vecsimple,fpload")])
(define_expand "truncdfsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
@@ -6652,7 +6721,7 @@
? \"mulhw %0,%1,%2\;mullw %L0,%1,%2\"
: \"mulhw %L0,%1,%2\;mullw %0,%1,%2\";
}
- [(set_attr "type" "imul")
+ [(set_attr "type" "mul")
(set_attr "length" "8")])
(define_split
@@ -6686,7 +6755,7 @@
? \"mulhwu %0,%1,%2\;mullw %L0,%1,%2\"
: \"mulhwu %L0,%1,%2\;mullw %0,%1,%2\";
}"
- [(set_attr "type" "imul")
+ [(set_attr "type" "mul")
(set_attr "length" "8")])
(define_split
@@ -6719,7 +6788,7 @@
(const_int 32))))]
""
"mulhw %0,%1,%2"
- [(set_attr "type" "imul")])
+ [(set_attr "type" "mul")])
(define_insn "umulsi3_highpart"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -6731,7 +6800,7 @@
(const_int 32))))]
""
"mulhwu %0,%1,%2"
- [(set_attr "type" "imul")])
+ [(set_attr "type" "mul")])
;; Shift by a variable amount is too complex to be worth open-coding. We
;; just handle shifts by constants.
@@ -6786,12 +6855,13 @@
"@
mulld %0,%1,%2
mulli %0,%1,%2"
- [(set (attr "type")
+ [(set_attr "type" "mul")
+ (set (attr "size")
(cond [(match_operand:SI 2 "s8bit_cint_operand" "")
- (const_string "imul3")
+ (const_string "8")
(match_operand:SI 2 "short_cint_operand" "")
- (const_string "imul2")]
- (const_string "lmul")))])
+ (const_string "16")]
+ (const_string "64")))])
(define_insn "*muldi3_internal1"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -6803,7 +6873,9 @@
"@
mulld. %3,%1,%2
#"
- [(set_attr "type" "lmul_compare")
+ [(set_attr "type" "mul")
+ (set_attr "size" "64")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -6831,7 +6903,9 @@
"@
mulld. %0,%1,%2
#"
- [(set_attr "type" "lmul_compare")
+ [(set_attr "type" "mul")
+ (set_attr "size" "64")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -6859,7 +6933,8 @@
(const_int 64))))]
"TARGET_POWERPC64"
"mulhd %0,%1,%2"
- [(set_attr "type" "lmul")])
+ [(set_attr "type" "mul")
+ (set_attr "size" "64")])
(define_insn "umuldi3_highpart"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
@@ -6871,7 +6946,8 @@
(const_int 64))))]
"TARGET_POWERPC64"
"mulhdu %0,%1,%2"
- [(set_attr "type" "lmul")])
+ [(set_attr "type" "mul")
+ (set_attr "size" "64")])
(define_expand "mulditi3"
[(set (match_operand:TI 0 "gpc_reg_operand")
@@ -6909,7 +6985,8 @@
"@
rldcl %0,%1,%2,0
rldicl %0,%1,%H2,0"
- [(set_attr "type" "var_shift_rotate,integer")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*rotldi3_internal2"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -6923,7 +7000,9 @@
rldicl. %3,%1,%H2,0
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -6953,7 +7032,9 @@
rldicl. %0,%1,%H2,0
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -6980,7 +7061,8 @@
"@
rldc%B3 %0,%1,%2,%S3
rldic%B3 %0,%1,%H2,%S3"
- [(set_attr "type" "var_shift_rotate,integer")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*rotldi3_internal5"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -6996,7 +7078,9 @@
rldic%B3. %4,%1,%H2,%S3
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -7032,7 +7116,9 @@
rldic%B3. %0,%1,%H2,%S3
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -7062,7 +7148,8 @@
"@
rldcl %0,%1,%2,56
rldicl %0,%1,%H2,56"
- [(set_attr "type" "var_shift_rotate,integer")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*rotldi3_internal7be"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
@@ -7074,7 +7161,8 @@
"@
rldcl %0,%1,%2,56
rldicl %0,%1,%H2,56"
- [(set_attr "type" "var_shift_rotate,integer")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*rotldi3_internal8le"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -7090,7 +7178,9 @@
rldicl. %3,%1,%H2,56
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_insn "*rotldi3_internal8be"
@@ -7107,7 +7197,9 @@
rldicl. %3,%1,%H2,56
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -7161,7 +7253,9 @@
rldicl. %0,%1,%H2,56
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_insn "*rotldi3_internal9be"
@@ -7179,7 +7273,9 @@
rldicl. %0,%1,%H2,56
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -7226,7 +7322,8 @@
"@
rldcl %0,%1,%2,48
rldicl %0,%1,%H2,48"
- [(set_attr "type" "var_shift_rotate,integer")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*rotldi3_internal10be"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
@@ -7238,7 +7335,8 @@
"@
rldcl %0,%1,%2,48
rldicl %0,%1,%H2,48"
- [(set_attr "type" "var_shift_rotate,integer")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*rotldi3_internal11le"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -7254,7 +7352,9 @@
rldicl. %3,%1,%H2,48
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_insn "*rotldi3_internal11be"
@@ -7271,7 +7371,9 @@
rldicl. %3,%1,%H2,48
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -7325,7 +7427,9 @@
rldicl. %0,%1,%H2,48
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_insn "*rotldi3_internal12be"
@@ -7343,7 +7447,9 @@
rldicl. %0,%1,%H2,48
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -7390,7 +7496,8 @@
"@
rldcl %0,%1,%2,32
rldicl %0,%1,%H2,32"
- [(set_attr "type" "var_shift_rotate,integer")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*rotldi3_internal13be"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
@@ -7402,7 +7509,8 @@
"@
rldcl %0,%1,%2,32
rldicl %0,%1,%H2,32"
- [(set_attr "type" "var_shift_rotate,integer")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*rotldi3_internal14le"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -7418,7 +7526,9 @@
rldicl. %3,%1,%H2,32
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_insn "*rotldi3_internal14be"
@@ -7435,7 +7545,9 @@
rldicl. %3,%1,%H2,32
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -7489,7 +7601,9 @@
rldicl. %0,%1,%H2,32
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_insn "*rotldi3_internal15be"
@@ -7507,7 +7621,9 @@
rldicl. %0,%1,%H2,32
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -7559,7 +7675,8 @@
"@
sld %0,%1,%2
sldi %0,%1,%H2"
- [(set_attr "type" "var_shift_rotate,shift")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*ashldi3_internal2"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -7573,7 +7690,9 @@
sldi. %3,%1,%H2
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -7603,7 +7722,9 @@
sldi. %0,%1,%H2
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -7627,7 +7748,8 @@
(match_operand:SI 2 "const_int_operand" "i"))
(match_operand:DI 3 "const_int_operand" "n")))]
"TARGET_POWERPC64 && includes_rldic_lshift_p (operands[2], operands[3])"
- "rldic %0,%1,%H2,%W3")
+ "rldic %0,%1,%H2,%W3"
+ [(set_attr "type" "shift")])
(define_insn "ashldi3_internal5"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -7641,7 +7763,8 @@
"@
rldic. %4,%1,%H2,%W3
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -7675,7 +7798,8 @@
"@
rldic. %0,%1,%H2,%W3
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -7703,7 +7827,8 @@
(match_operand:SI 2 "const_int_operand" "i"))
(match_operand:DI 3 "mask64_operand" "n")))]
"TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
- "rldicr %0,%1,%H2,%S3")
+ "rldicr %0,%1,%H2,%S3"
+ [(set_attr "type" "shift")])
(define_insn "ashldi3_internal8"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -7717,7 +7842,8 @@
"@
rldicr. %4,%1,%H2,%S3
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -7751,7 +7877,8 @@
"@
rldicr. %0,%1,%H2,%S3
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -7788,7 +7915,8 @@
"@
srd %0,%1,%2
srdi %0,%1,%H2"
- [(set_attr "type" "var_shift_rotate,shift")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*lshrdi3_internal2"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -7802,7 +7930,9 @@
srdi. %3,%1,%H2
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -7832,7 +7962,9 @@
srdi. %0,%1,%H2
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -7876,7 +8008,8 @@
"@
srad %0,%1,%2
sradi %0,%1,%H2"
- [(set_attr "type" "var_shift_rotate,shift")])
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no")])
(define_insn "*ashrdi3_internal2"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -7890,7 +8023,9 @@
sradi. %3,%1,%H2
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -7920,7 +8055,9 @@
sradi. %0,%1,%H2
#
#"
- [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "var_shift" "yes,no,yes,no")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8,8")])
(define_split
@@ -7969,7 +8106,8 @@
andi. %0,%1,%b2
andis. %0,%1,%u2
#"
- [(set_attr "type" "*,*,*,fast_compare,fast_compare,*")
+ [(set_attr "type" "*,shift,shift,logical,logical,*")
+ (set_attr "dot" "no,no,no,yes,yes,no")
(set_attr "length" "4,4,4,4,4,8")])
(define_insn "anddi3_nomc"
@@ -7983,7 +8121,8 @@
rldic%B2 %0,%1,0,%S2
rlwinm %0,%1,0,%m2,%M2
#"
- [(set_attr "length" "4,4,4,8")])
+ [(set_attr "type" "*,shift,shift,*")
+ (set_attr "length" "4,4,4,8")])
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
@@ -8027,9 +8166,10 @@
#
#
#"
- [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\
- fast_compare,compare,compare,compare,compare,compare,\
+ [(set_attr "type" "logical,shift,shift,logical,\
+ logical,compare,compare,compare,compare,compare,\
compare,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
(define_split
@@ -8080,9 +8220,10 @@
#
#
#"
- [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\
- fast_compare,compare,compare,compare,compare,compare,\
+ [(set_attr "type" "logical,shift,shift,logical,\
+ logical,compare,compare,compare,compare,compare,\
compare,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
(define_split
@@ -8212,7 +8353,8 @@
"@
%q4. %3,%1,%2
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -8241,7 +8383,8 @@
"@
%q4. %0,%1,%2
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -8301,7 +8444,8 @@
"@
%q4. %3,%2,%1
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -8330,7 +8474,8 @@
"@
%q4. %0,%2,%1
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -8367,7 +8512,8 @@
"@
%q4. %3,%1,%2
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -8396,7 +8542,8 @@
"@
%q4. %0,%1,%2
#"
- [(set_attr "type" "fast_compare,compare")
+ [(set_attr "type" "logical,compare")
+ (set_attr "dot" "yes")
(set_attr "length" "4,8")])
(define_split
@@ -8878,31 +9025,7 @@
mt%0 %1
mt%0 %1
nop"
- [(set_attr_alternative "type"
- [(const_string "*")
- (const_string "*")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "store_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "store_u")
- (const_string "store")))
- (const_string "*")
- (const_string "*")
- (const_string "*")
- (const_string "mfjmpr")
- (const_string "mtjmpr")
- (const_string "*")
- (const_string "*")])
-
+ [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,mtjmpr,*,*")
(set_attr "length" "4,4,4,4,4,4,8,4,4,4,4")])
(define_insn "*movsi_internal1_single"
@@ -8924,44 +9047,7 @@
nop
stfs%U0%X0 %1,%0
lfs%U1%X1 %0,%1"
- [(set_attr_alternative "type"
- [(const_string "*")
- (const_string "*")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "store_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "store_u")
- (const_string "store")))
- (const_string "*")
- (const_string "*")
- (const_string "*")
- (const_string "mfjmpr")
- (const_string "mtjmpr")
- (const_string "*")
- (const_string "*")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_u")
- (const_string "fpstore")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_u")
- (const_string "fpload")))])
+ [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,mtjmpr,*,*,fpstore,fpload")
(set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4")])
;; Split a load of a large constant into the appropriate two-insn
@@ -8978,9 +9064,8 @@
(ior:SI (match_dup 0)
(match_dup 3)))]
"
-{ rtx tem = rs6000_emit_set_const (operands[0], SImode, operands[1], 2);
-
- if (tem == operands[0])
+{
+ if (rs6000_emit_set_const (operands[0], operands[1]))
DONE;
else
FAIL;
@@ -8996,7 +9081,8 @@
cmp<wd>i %2,%0,0
mr. %0,%1
#"
- [(set_attr "type" "cmp,fast_compare,cmp")
+ [(set_attr "type" "cmp,logical,cmp")
+ (set_attr "dot" "yes")
(set_attr "length" "4,4,8")])
(define_split
@@ -9024,26 +9110,7 @@
mf%1 %0
mt%0 %1
nop"
- [(set_attr_alternative "type"
- [(const_string "*")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "store_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "store_u")
- (const_string "store")))
- (const_string "*")
- (const_string "mfjmpr")
- (const_string "mtjmpr")
- (const_string "*")])])
+ [(set_attr "type" "*,load,store,*,mfjmpr,mtjmpr,*")])
(define_expand "mov<mode>"
[(set (match_operand:INT 0 "general_operand" "")
@@ -9064,26 +9131,7 @@
mf%1 %0
mt%0 %1
nop"
- [(set_attr_alternative "type"
- [(const_string "*")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "store_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "store_u")
- (const_string "store")))
- (const_string "*")
- (const_string "mfjmpr")
- (const_string "mtjmpr")
- (const_string "*")])])
+ [(set_attr "type" "*,load,store,*,mfjmpr,mtjmpr,*")])
;; Here is how to move condition codes around. When we store CC data in
;; an integer register or memory, we store just the high-order 4 bits.
@@ -9124,23 +9172,9 @@
(eq_attr "alternative" "9")
(const_string "mtjmpr")
(eq_attr "alternative" "10")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1],
- VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
+ (const_string "load")
(eq_attr "alternative" "11")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0],
- VOIDmode)")
- (const_string "store_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "store_u")
- (const_string "store")))
+ (const_string "store")
(match_test "TARGET_MFCRF")
(const_string "mfcrf")
]
@@ -9209,48 +9243,7 @@
nop
#
#"
- [(set_attr_alternative "type"
- [(const_string "*")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "store_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "store_u")
- (const_string "store")))
- (const_string "fp")
- (const_string "vecsimple")
- (const_string "vecsimple")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_u")
- (const_string "fpload")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_u")
- (const_string "fpstore")))
- (const_string "fpload")
- (const_string "fpstore")
- (const_string "mftgpr")
- (const_string "mffgpr")
- (const_string "mtjmpr")
- (const_string "mfjmpr")
- (const_string "*")
- (const_string "*")
- (const_string "*")])
+ [(set_attr "type" "*,load,store,fp,vecsimple,vecsimple,fpload,fpstore,fpload,fpstore,mftgpr,mffgpr,mtjmpr,mfjmpr,*,*,*")
(set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8")])
(define_insn "*mov<mode>_softfloat"
@@ -9270,29 +9263,7 @@
#
#
nop"
- [(set_attr_alternative "type"
- [(const_string "*")
- (const_string "mtjmpr")
- (const_string "mfjmpr")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "store_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "store_u")
- (const_string "store")))
- (const_string "*")
- (const_string "*")
- (const_string "*")
- (const_string "*")
- (const_string "*")])
+ [(set_attr "type" "*,mtjmpr,mfjmpr,load,store,*,*,*,*,*")
(set_attr "length" "4,4,4,4,4,4,4,4,8,4")])
@@ -9407,38 +9378,7 @@
#
#
#"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_u")
- (const_string "fpstore")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_u")
- (const_string "fpload")))
- (const_string "fp")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (const_string "fpload"))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (const_string "fpstore"))
- (const_string "vecsimple")
- (const_string "vecsimple")
- (const_string "store")
- (const_string "load")
- (const_string "two")
- (const_string "fp")
- (const_string "fp")
- (const_string "*")])
+ [(set_attr "type" "fpstore,fpload,fp,fpload,fpstore,vecsimple,vecsimple,store,load,two,fp,fp,*")
(set_attr "length" "4,4,4,4,4,4,4,8,8,8,8,12,16")])
(define_insn "*mov<mode>_softfloat32"
@@ -9483,57 +9423,7 @@
mffgpr %0,%1
mfvsrd %0,%x1
mtvsrd %x0,%1"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_u")
- (const_string "fpstore")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_u")
- (const_string "fpload")))
- (const_string "fp")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (const_string "fpload"))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (const_string "fpstore"))
- (const_string "vecsimple")
- (const_string "vecsimple")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "store_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "store_u")
- (const_string "store")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
- (const_string "*")
- (const_string "mtjmpr")
- (const_string "mfjmpr")
- (const_string "*")
- (const_string "*")
- (const_string "*")
- (const_string "*")
- (const_string "mftgpr")
- (const_string "mffgpr")
- (const_string "mftgpr")
- (const_string "mffgpr")])
+ [(set_attr "type" "fpstore,fpload,fp,fpload,fpstore,vecsimple,vecsimple,store,load,*,mtjmpr,mfjmpr,*,*,*,*,mftgpr,mffgpr,mftgpr,mffgpr")
(set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16,4,4,4,4")])
(define_insn "*mov<mode>_softfloat64"
@@ -9552,28 +9442,7 @@
#
#
nop"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "store_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "store_u")
- (const_string "store")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
- (const_string "*")
- (const_string "mtjmpr")
- (const_string "mfjmpr")
- (const_string "*")
- (const_string "*")
- (const_string "*")
- (const_string "*")])
+ [(set_attr "type" "store,load,*,mtjmpr,mfjmpr,*,*,*,*")
(set_attr "length" "4,4,4,4,4,8,12,16,4")])
(define_expand "mov<mode>"
@@ -10187,26 +10056,7 @@
lfd%U1%X1 %0,%1
fmr %0,%1
#"
- [(set_attr_alternative "type"
- [(const_string "store")
- (const_string "load")
- (const_string "*")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_u")
- (const_string "fpstore")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_u")
- (const_string "fpload")))
- (const_string "fp")
- (const_string "*")])])
+ [(set_attr "type" "store,load,*,fpstore,fpload,fp,*")])
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
@@ -10259,47 +10109,7 @@
mffgpr %0,%1
mfvsrd %0,%x1
mtvsrd %x0,%1"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "store_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "store_u")
- (const_string "store")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))
- (const_string "*")
- (const_string "*")
- (const_string "*")
- (const_string "*")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_u")
- (const_string "fpstore")))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_u")
- (const_string "fpload")))
- (const_string "fp")
- (const_string "mfjmpr")
- (const_string "mtjmpr")
- (const_string "*")
- (const_string "mftgpr")
- (const_string "mffgpr")
- (const_string "mftgpr")
- (const_string "mffgpr")])
+ [(set_attr "type" "store,load,*,*,*,*,fpstore,fpload,fp,mfjmpr,mtjmpr,*,mftgpr,mffgpr,mftgpr,mffgpr")
(set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4,4,4")])
;; Generate all one-bits and clear left or right.
@@ -10326,9 +10136,8 @@
[(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
"
-{ rtx tem = rs6000_emit_set_const (operands[0], DImode, operands[1], 5);
-
- if (tem == operands[0])
+{
+ if (rs6000_emit_set_const (operands[0], operands[1]))
DONE;
else
FAIL;
@@ -10341,9 +10150,8 @@
[(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
"
-{ rtx tem = rs6000_emit_set_const (operands[0], DImode, operands[1], 5);
-
- if (tem == operands[0])
+{
+ if (rs6000_emit_set_const (operands[0], operands[1]))
DONE;
else
FAIL;
@@ -10383,7 +10191,9 @@
return \"#\";
}
}"
- [(set_attr "type" "store_ux,store_ux,load_ux,load_ux,*,*")
+ [(set_attr "type" "store,store,load,load,*,*")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set (attr "cell_micro") (if_then_else (match_test "TARGET_STRING")
(const_string "always")
(const_string "conditional")))])
@@ -10495,7 +10305,9 @@
"TARGET_STRING && XVECLEN (operands[0], 0) == 8"
"*
{ return rs6000_output_load_multiple (operands); }"
- [(set_attr "type" "load_ux")
+ [(set_attr "type" "load")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "length" "32")])
(define_insn "*ldmsi7"
@@ -10517,7 +10329,9 @@
"TARGET_STRING && XVECLEN (operands[0], 0) == 7"
"*
{ return rs6000_output_load_multiple (operands); }"
- [(set_attr "type" "load_ux")
+ [(set_attr "type" "load")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "length" "32")])
(define_insn "*ldmsi6"
@@ -10537,7 +10351,9 @@
"TARGET_STRING && XVECLEN (operands[0], 0) == 6"
"*
{ return rs6000_output_load_multiple (operands); }"
- [(set_attr "type" "load_ux")
+ [(set_attr "type" "load")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "length" "32")])
(define_insn "*ldmsi5"
@@ -10555,7 +10371,9 @@
"TARGET_STRING && XVECLEN (operands[0], 0) == 5"
"*
{ return rs6000_output_load_multiple (operands); }"
- [(set_attr "type" "load_ux")
+ [(set_attr "type" "load")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "length" "32")])
(define_insn "*ldmsi4"
@@ -10571,7 +10389,9 @@
"TARGET_STRING && XVECLEN (operands[0], 0) == 4"
"*
{ return rs6000_output_load_multiple (operands); }"
- [(set_attr "type" "load_ux")
+ [(set_attr "type" "load")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "length" "32")])
(define_insn "*ldmsi3"
@@ -10585,7 +10405,9 @@
"TARGET_STRING && XVECLEN (operands[0], 0) == 3"
"*
{ return rs6000_output_load_multiple (operands); }"
- [(set_attr "type" "load_ux")
+ [(set_attr "type" "load")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "length" "32")])
(define_expand "store_multiple"
@@ -10653,7 +10475,9 @@
(match_operand:SI 10 "gpc_reg_operand" "r"))])]
"TARGET_STRING && XVECLEN (operands[0], 0) == 9"
"stswi %2,%1,%O0"
- [(set_attr "type" "store_ux")
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "cell_micro" "always")])
(define_insn "*stmsi7"
@@ -10675,7 +10499,9 @@
(match_operand:SI 9 "gpc_reg_operand" "r"))])]
"TARGET_STRING && XVECLEN (operands[0], 0) == 8"
"stswi %2,%1,%O0"
- [(set_attr "type" "store_ux")
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "cell_micro" "always")])
(define_insn "*stmsi6"
@@ -10695,7 +10521,9 @@
(match_operand:SI 8 "gpc_reg_operand" "r"))])]
"TARGET_STRING && XVECLEN (operands[0], 0) == 7"
"stswi %2,%1,%O0"
- [(set_attr "type" "store_ux")
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "cell_micro" "always")])
(define_insn "*stmsi5"
@@ -10713,7 +10541,9 @@
(match_operand:SI 7 "gpc_reg_operand" "r"))])]
"TARGET_STRING && XVECLEN (operands[0], 0) == 6"
"stswi %2,%1,%O0"
- [(set_attr "type" "store_ux")
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "cell_micro" "always")])
(define_insn "*stmsi4"
@@ -10729,7 +10559,9 @@
(match_operand:SI 6 "gpc_reg_operand" "r"))])]
"TARGET_STRING && XVECLEN (operands[0], 0) == 5"
"stswi %2,%1,%O0"
- [(set_attr "type" "store_ux")
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "cell_micro" "always")])
(define_insn "*stmsi3"
@@ -10743,7 +10575,9 @@
(match_operand:SI 5 "gpc_reg_operand" "r"))])]
"TARGET_STRING && XVECLEN (operands[0], 0) == 4"
"stswi %2,%1,%O0"
- [(set_attr "type" "store_ux")
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "cell_micro" "always")])
(define_expand "setmemsi"
@@ -10825,7 +10659,9 @@
&& (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 12)
&& REGNO (operands[4]) == 5"
"lswi %4,%1,%2\;stswi %4,%0,%2"
- [(set_attr "type" "store_ux")
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "cell_micro" "always")
(set_attr "length" "8")])
@@ -10865,7 +10701,9 @@
&& (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 10)
&& REGNO (operands[4]) == 5"
"lswi %4,%1,%2\;stswi %4,%0,%2"
- [(set_attr "type" "store_ux")
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "cell_micro" "always")
(set_attr "length" "8")])
@@ -10901,7 +10739,9 @@
&& (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 8)
&& REGNO (operands[4]) == 5"
"lswi %4,%1,%2\;stswi %4,%0,%2"
- [(set_attr "type" "store_ux")
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "cell_micro" "always")
(set_attr "length" "8")])
@@ -10926,7 +10766,9 @@
"TARGET_STRING && ! TARGET_POWERPC64
&& INTVAL (operands[2]) > 4 && INTVAL (operands[2]) <= 8"
"lswi %4,%1,%2\;stswi %4,%0,%2"
- [(set_attr "type" "store_ux")
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "cell_micro" "always")
(set_attr "length" "8")])
@@ -10950,7 +10792,9 @@
(clobber (match_scratch:SI 5 "=X"))]
"TARGET_STRING && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 4"
"lswi %4,%1,%2\;stswi %4,%0,%2"
- [(set_attr "type" "store_ux")
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "cell_micro" "always")
(set_attr "length" "8")])
@@ -10975,7 +10819,9 @@
"@
ldux %3,%0,%2
ldu %3,%2(%0)"
- [(set_attr "type" "load_ux,load_u")])
+ [(set_attr "type" "load")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "movdi_<mode>_update"
[(set (mem:DI (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
@@ -10991,7 +10837,9 @@
"@
stdux %3,%0,%2
stdu %3,%2(%0)"
- [(set_attr "type" "store_ux,store_u")])
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
;; This pattern is only conditional on TARGET_POWERPC64, as it is
;; needed for stack allocation, even if the user passes -mno-update.
@@ -11005,7 +10853,9 @@
"@
stdux %3,%0,%2
stdu %3,%2(%0)"
- [(set_attr "type" "store_ux,store_u")])
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movsi_update1"
[(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
@@ -11019,7 +10869,9 @@
"@
lwzux %3,%0,%2
lwzu %3,%2(%0)"
- [(set_attr "type" "load_ux,load_u")])
+ [(set_attr "type" "load")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movsi_update2"
[(set (match_operand:DI 3 "gpc_reg_operand" "=r")
@@ -11031,7 +10883,10 @@
"TARGET_POWERPC64 && rs6000_gen_cell_microcode
&& !avoiding_indexed_address_p (DImode)"
"lwaux %3,%0,%2"
- [(set_attr "type" "load_ext_ux")])
+ [(set_attr "type" "load")
+ (set_attr "sign_extend" "yes")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")])
(define_insn "movsi_update"
[(set (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
@@ -11047,7 +10902,9 @@
"@
stwux %3,%0,%2
stwu %3,%2(%0)"
- [(set_attr "type" "store_ux,store_u")])
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
;; This is an unconditional pattern; needed for stack allocation, even
;; if the user passes -mno-update.
@@ -11061,7 +10918,9 @@
"@
stwux %3,%0,%2
stwu %3,%2(%0)"
- [(set_attr "type" "store_ux,store_u")])
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movhi_update1"
[(set (match_operand:HI 3 "gpc_reg_operand" "=r,r")
@@ -11075,7 +10934,9 @@
"@
lhzux %3,%0,%2
lhzu %3,%2(%0)"
- [(set_attr "type" "load_ux,load_u")])
+ [(set_attr "type" "load")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movhi_update2"
[(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
@@ -11090,7 +10951,9 @@
"@
lhzux %3,%0,%2
lhzu %3,%2(%0)"
- [(set_attr "type" "load_ux,load_u")])
+ [(set_attr "type" "load")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movhi_update3"
[(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
@@ -11105,7 +10968,10 @@
"@
lhaux %3,%0,%2
lhau %3,%2(%0)"
- [(set_attr "type" "load_ext_ux,load_ext_u")])
+ [(set_attr "type" "load")
+ (set_attr "sign_extend" "yes")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movhi_update4"
[(set (mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
@@ -11119,7 +10985,9 @@
"@
sthux %3,%0,%2
sthu %3,%2(%0)"
- [(set_attr "type" "store_ux,store_u")])
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movqi_update1"
[(set (match_operand:QI 3 "gpc_reg_operand" "=r,r")
@@ -11133,7 +11001,9 @@
"@
lbzux %3,%0,%2
lbzu %3,%2(%0)"
- [(set_attr "type" "load_ux,load_u")])
+ [(set_attr "type" "load")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movqi_update2"
[(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
@@ -11148,7 +11018,9 @@
"@
lbzux %3,%0,%2
lbzu %3,%2(%0)"
- [(set_attr "type" "load_ux,load_u")])
+ [(set_attr "type" "load")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movqi_update3"
[(set (mem:QI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
@@ -11162,7 +11034,9 @@
"@
stbux %3,%0,%2
stbu %3,%2(%0)"
- [(set_attr "type" "store_ux,store_u")])
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movsf_update1"
[(set (match_operand:SF 3 "gpc_reg_operand" "=f,f")
@@ -11176,7 +11050,9 @@
"@
lfsux %3,%0,%2
lfsu %3,%2(%0)"
- [(set_attr "type" "fpload_ux,fpload_u")])
+ [(set_attr "type" "fpload")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movsf_update2"
[(set (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
@@ -11190,7 +11066,9 @@
"@
stfsux %3,%0,%2
stfsu %3,%2(%0)"
- [(set_attr "type" "fpstore_ux,fpstore_u")])
+ [(set_attr "type" "fpstore")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movsf_update3"
[(set (match_operand:SF 3 "gpc_reg_operand" "=r,r")
@@ -11204,7 +11082,9 @@
"@
lwzux %3,%0,%2
lwzu %3,%2(%0)"
- [(set_attr "type" "load_ux,load_u")])
+ [(set_attr "type" "load")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movsf_update4"
[(set (mem:SF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
@@ -11218,7 +11098,9 @@
"@
stwux %3,%0,%2
stwu %3,%2(%0)"
- [(set_attr "type" "store_ux,store_u")])
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movdf_update1"
[(set (match_operand:DF 3 "gpc_reg_operand" "=d,d")
@@ -11232,7 +11114,9 @@
"@
lfdux %3,%0,%2
lfdu %3,%2(%0)"
- [(set_attr "type" "fpload_ux,fpload_u")])
+ [(set_attr "type" "fpload")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
(define_insn "*movdf_update2"
[(set (mem:DF (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
@@ -11246,7 +11130,9 @@
"@
stfdux %3,%0,%2
stfdu %3,%2(%0)"
- [(set_attr "type" "fpstore_ux,fpstore_u")])
+ [(set_attr "type" "fpstore")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes,no")])
;; After inserting conditional returns we can sometimes have
@@ -11916,7 +11802,9 @@
operands[2] = gen_rtx_REG (Pmode, 2);
return \"lwz %0,%1(%2)\";
}"
- [(set_attr "type" "load")])
+ [(set_attr "type" "load")
+ (set_attr "update" "no")
+ (set_attr "indexed" "no")])
(define_insn "load_toc_aix_di"
[(parallel [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
@@ -11938,7 +11826,9 @@
operands[2] = gen_rtx_REG (Pmode, 2);
return \"ld %0,%1(%2)\";
}"
- [(set_attr "type" "load")])
+ [(set_attr "type" "load")
+ (set_attr "update" "no")
+ (set_attr "indexed" "no")])
(define_insn "load_toc_v4_pic_si"
[(set (reg:SI LR_REGNO)
@@ -12914,14 +12804,15 @@
operands[1] = gen_rtx_REG (Pmode, 0);
return "st<wd>%U0%X0 %1,%0";
}
- [(set (attr "type")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "store_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "store_u")
- (const_string "store"))))
+ [(set_attr "type" "store")
+ (set (attr "update")
+ (if_then_else (match_operand 0 "update_address_mem")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "indexed")
+ (if_then_else (match_operand 0 "indexed_address_mem")
+ (const_string "yes")
+ (const_string "no")))
(set_attr "length" "4")])
(define_insn "probe_stack_range<P:mode>"
@@ -13354,7 +13245,8 @@
"@
mfcr %3%Q2\;rlwinm. %3,%3,%J1,1
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "8,16")])
(define_split
@@ -13435,7 +13327,8 @@
return \"mfcr %4%Q2\;rlwinm. %4,%4,%5,%6,%6\";
}"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "shift")
+ (set_attr "dot" "yes")
(set_attr "length" "8,16")])
(define_split
@@ -15118,7 +15011,9 @@
(match_operand:SI 2 "gpc_reg_operand" "r"))])]
"TARGET_MULTIPLE"
"stmw %2,%1"
- [(set_attr "type" "store_ux")])
+ [(set_attr "type" "store")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")])
; The following comment applies to:
; save_gpregs_*
@@ -15277,7 +15172,9 @@
(match_operand:SI 2 "memory_operand" "m"))])]
"TARGET_MULTIPLE"
"lmw %1,%2"
- [(set_attr "type" "load_ux")
+ [(set_attr "type" "load")
+ (set_attr "update" "yes")
+ (set_attr "indexed" "yes")
(set_attr "cell_micro" "always")])
(define_insn "*return_internal_<mode>"
@@ -15789,7 +15686,8 @@
UNSPEC_DIV_EXTEND))]
"TARGET_POPCNTD"
"div<wd><div_extend> %0,%1,%2"
- [(set_attr "type" "<idiv_ldiv>")])
+ [(set_attr "type" "div")
+ (set_attr "size" "<bits>")])
;; Pack/unpack 128-bit floating point types that take 2 scalar registers
diff --git a/gcc/config/rs6000/rs64.md b/gcc/config/rs6000/rs64.md
index 597f3aeecaf..c891ac4b27f 100644
--- a/gcc/config/rs6000/rs64.md
+++ b/gcc/config/rs6000/rs64.md
@@ -26,17 +26,17 @@
;; RS64a 64-bit IU, LSU, FPU, BPU
(define_insn_reservation "rs64a-load" 2
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u")
+ (and (eq_attr "type" "load")
(eq_attr "cpu" "rs64a"))
"lsu_rs64")
(define_insn_reservation "rs64a-store" 2
- (and (eq_attr "type" "store,store_ux,store_u,fpstore,fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "store,fpstore")
(eq_attr "cpu" "rs64a"))
"lsu_rs64")
(define_insn_reservation "rs64a-fpload" 3
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "rs64a"))
"lsu_rs64")
@@ -46,8 +46,9 @@
"lsu_rs64")
(define_insn_reservation "rs64a-integer" 1
- (and (eq_attr "type" "integer,insert_word,insert_dword,shift,trap,\
- var_shift_rotate,cntlz,exts,isel")
+ (and (ior (eq_attr "type" "integer,insert,trap,cntlz,exts,isel")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "no")))
(eq_attr "cpu" "rs64a"))
"iu_rs64")
@@ -62,38 +63,45 @@
"iu_rs64,iu_rs64,iu_rs64")
(define_insn_reservation "rs64a-imul" 20
- (and (eq_attr "type" "imul,imul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "32")
(eq_attr "cpu" "rs64a"))
"mciu_rs64*13")
(define_insn_reservation "rs64a-imul2" 12
- (and (eq_attr "type" "imul2")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "16")
(eq_attr "cpu" "rs64a"))
"mciu_rs64*5")
(define_insn_reservation "rs64a-imul3" 8
- (and (eq_attr "type" "imul3")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "8")
(eq_attr "cpu" "rs64a"))
"mciu_rs64*2")
(define_insn_reservation "rs64a-lmul" 34
- (and (eq_attr "type" "lmul,lmul_compare")
+ (and (eq_attr "type" "mul")
+ (eq_attr "size" "64")
(eq_attr "cpu" "rs64a"))
"mciu_rs64*34")
(define_insn_reservation "rs64a-idiv" 66
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "32")
(eq_attr "cpu" "rs64a"))
"mciu_rs64*66")
(define_insn_reservation "rs64a-ldiv" 66
- (and (eq_attr "type" "ldiv")
+ (and (eq_attr "type" "div")
+ (eq_attr "size" "64")
(eq_attr "cpu" "rs64a"))
"mciu_rs64*66")
(define_insn_reservation "rs64a-compare" 3
- (and (eq_attr "type" "cmp,fast_compare,compare,\
- delayed_compare,var_delayed_compare")
+ (and (ior (eq_attr "type" "cmp,compare")
+ (and (eq_attr "type" "add,logical,shift")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "rs64a"))
"iu_rs64,nothing,bpu_rs64")
diff --git a/gcc/config/rs6000/titan.md b/gcc/config/rs6000/titan.md
index c0c3155e4a9..4326cb90fdc 100644
--- a/gcc/config/rs6000/titan.md
+++ b/gcc/config/rs6000/titan.md
@@ -34,28 +34,26 @@
;; instructions. It provides its own, dedicated result-bus, so we
;; don't need the titan_fxu_wb reservation to complete.
(define_insn_reservation "titan_fxu_adder" 1
- (and (eq_attr "type" "cmp,fast_compare,trap")
+ (and (ior (eq_attr "type" "cmp,trap")
+ (and (eq_attr "type" "add,logical")
+ (eq_attr "dot" "yes")))
(eq_attr "cpu" "titan"))
"titan_issue,titan_fxu_sh")
-;; Keep the titan_imul and titan_mulhw (half-word) rules in order, to
-;; ensure the proper match: the half-word instructions are tagged as
-;; imul3 only, whereas regular multiplys will always carry a imul tag.
-
(define_insn_reservation "titan_imul" 5
- (and (eq_attr "type" "imul,imul2,imul_compare")
+ (and (eq_attr "type" "mul")
(eq_attr "cpu" "titan"))
"titan_issue,titan_fxu_sh,nothing*5,titan_fxu_wb")
(define_insn_reservation "titan_mulhw" 4
- (and (eq_attr "type" "imul3")
+ (and (eq_attr "type" "halfmul")
(eq_attr "cpu" "titan"))
"titan_issue,titan_fxu_sh,nothing*4,titan_fxu_wb")
(define_bypass 2 "titan_mulhw" "titan_mulhw")
(define_insn_reservation "titan_fxu_shift_and_rotate" 2
- (and (eq_attr "type" "insert_word,shift,var_shift_rotate,cntlz")
+ (and (eq_attr "type" "insert,shift,cntlz")
(eq_attr "cpu" "titan"))
"titan_issue,titan_fxu_sh,nothing*2,titan_fxu_wb")
@@ -71,12 +69,14 @@
;; through its latency and initial disptach bottlenecks (i.e. issue
;; slots and fxu scheduler availability)
(define_insn_reservation "titan_fxu_div" 34
- (and (eq_attr "type" "idiv")
+ (and (eq_attr "type" "div")
(eq_attr "cpu" "titan"))
"titan_issue,titan_fxu_sh")
(define_insn_reservation "titan_fxu_alu" 1
- (and (eq_attr "type" "integer,exts")
+ (and (ior (eq_attr "type" "integer,exts")
+ (and (eq_attr "type" "add,logical")
+ (eq_attr "dot" "no")))
(eq_attr "cpu" "titan"))
"titan_issue,titan_fxu_sh,nothing,titan_fxu_wb")
@@ -95,13 +95,12 @@
;; Loads.
(define_insn_reservation "titan_lsu_load" 3
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
- load_l,sync")
+ (and (eq_attr "type" "load,load_l,sync")
(eq_attr "cpu" "titan"))
"titan_issue,titan_lsu_sh")
(define_insn_reservation "titan_lsu_fpload" 12
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "titan"))
"titan_issue,titan_lsu_sh")
@@ -115,12 +114,12 @@
;; Stores.
(define_insn_reservation "titan_lsu_store" 12
- (and (eq_attr "type" "store,store_ux,store_u,store_c")
+ (and (eq_attr "type" "store,store_c")
(eq_attr "cpu" "titan"))
"titan_issue,titan_lsu_sh")
(define_insn_reservation "titan_lsu_fpstore" 12
- (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
+ (and (eq_attr "type" "fpstore")
(eq_attr "cpu" "titan"))
"titan_issue,titan_lsu_sh")
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index 23d85ab0628..cf430bb5387 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -657,8 +657,9 @@
gcc_unreachable ();
}
}
- [(set_attr "type" "vecstore,vecload,vecsimple,vecsimple,vecsimple,vecstore,vecload,store_ux,store_ux,load_ux,load_ux, *, *")
- (set_attr "length" " 4, 4, 4, 4, 8, 4, 4, 16, 16, 16, 16,16,16")
+ [(set_attr "type" "vecstore,vecload,vecsimple,vecsimple,vecsimple,vecstore,vecload,store,store,load,load, *, *")
+ (set_attr "update" " *, *, *, *, *, *, *, yes, yes, yes, yes, *, *")
+ (set_attr "length" " 4, 4, 4, 4, 8, 4, 4, 16, 16, 16, 16,16,16")
(set (attr "cell_micro") (if_then_else (match_test "TARGET_STRING")
(const_string "always")
(const_string "conditional")))])
@@ -1613,22 +1614,7 @@
lfd%U1%X1 %0,%1
lxsd%U1x %x0,%y1
ld%U1%X1 %0,%1"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_u")
- (const_string "fpload")))
- (const_string "fpload")
- (if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "load_ux")
- (if_then_else
- (match_test "update_address_mem (operands[1], VOIDmode)")
- (const_string "load_u")
- (const_string "load")))])
+ [(set_attr "type" "fpload,fpload,load")
(set_attr "length" "4")])
;; Optimize storing a single scalar element that is the right location to
@@ -1643,16 +1629,7 @@
stfd%U0%X0 %1,%0
stxsd%U0x %x1,%y0
stxsd%U0x %x1,%y0"
- [(set_attr_alternative "type"
- [(if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (if_then_else
- (match_test "update_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_u")
- (const_string "fpstore")))
- (const_string "fpstore")
- (const_string "fpstore")])
+ [(set_attr "type" "fpstore")
(set_attr "length" "4")])
;; Extract a SF element from V4SF
diff --git a/gcc/config/rs6000/vxworks.h b/gcc/config/rs6000/vxworks.h
index 7b4e9b9eba6..a9ddea22dba 100644
--- a/gcc/config/rs6000/vxworks.h
+++ b/gcc/config/rs6000/vxworks.h
@@ -60,6 +60,12 @@ along with GCC; see the file COPYING3. If not see
#define SUBTARGET_EXTRA_SPECS /* none needed */
+/* VxWorks and VxWorksAE (aka 653) expect different CPU values to designate
+ SPE on 8548. We define a dedicated macro for the base VxWorks here, which
+ the AE configuration will override. */
+
+#define VXCPU_FOR_8548 "PPC85XX"
+
/* FIXME: The only reason we allow no -mcpu switch at all is because
config-ml.in insists on a "." multilib. */
#define CPP_SPEC \
@@ -73,6 +79,7 @@ along with GCC; see the file COPYING3. If not see
mcpu=604 : -DCPU=PPC604 ; \
mcpu=860 : -DCPU=PPC860 ; \
mcpu=8540: -DCPU=PPC85XX ; \
+ mcpu=8548: -DCPU=" VXCPU_FOR_8548 "; \
: -DCPU=PPC604 }}" \
VXWORKS_ADDITIONAL_CPP_SPEC
diff --git a/gcc/config/rs6000/vxworksae.h b/gcc/config/rs6000/vxworksae.h
new file mode 100644
index 00000000000..95a2a7c4632
--- /dev/null
+++ b/gcc/config/rs6000/vxworksae.h
@@ -0,0 +1,23 @@
+/* Definitions of target machine for GNU compiler. PowerPC VxworksAE version.
+ Copyright (C) 2005-2014 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* VxWorksAE for E500V2 expects a specific CPU value to designate 8548. */
+#undef VXCPU_FOR_8548
+#define VXCPU_FOR_8548 "PPCE500V2"
diff --git a/gcc/config/rs6000/xfpu.md b/gcc/config/rs6000/xfpu.md
index b1e28b9fefd..c875df3a248 100644
--- a/gcc/config/rs6000/xfpu.md
+++ b/gcc/config/rs6000/xfpu.md
@@ -118,12 +118,12 @@
"Xfpu_issue*2,Xfpu_mul,nothing*7,Xfpu_addsub")
(define_insn_reservation "fp-load" 10 ;; FIXME. Is double/single precision the same ?
- (and (eq_attr "type" "fpload, fpload_ux, fpload_u")
+ (and (eq_attr "type" "fpload")
(eq_attr "cpu" "ppc405"))
"Xfpu_issue*10")
-(define_insn_reservation "fp-store" 4
- (and (eq_attr "type" "fpstore, fpstore_ux, fpstore_u")
+(define_insn_reservation "fp-store" 4
+ (and (eq_attr "type" "fpstore")
(eq_attr "cpu" "ppc405"))
"Xfpu_issue*4")
diff --git a/gcc/config/rtems.h b/gcc/config/rtems.h
index 3da27c57ef4..f14aed36aa6 100644
--- a/gcc/config/rtems.h
+++ b/gcc/config/rtems.h
@@ -13,8 +13,13 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* The system headers under RTEMS are C++-aware. */
diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c
index 4242c1a9717..9f834481b4f 100644
--- a/gcc/config/rx/rx.c
+++ b/gcc/config/rx/rx.c
@@ -55,6 +55,7 @@
#include "langhooks.h"
#include "opts.h"
#include "cgraph.h"
+#include "builtins.h"
static unsigned int rx_gp_base_regnum_val = INVALID_REGNUM;
static unsigned int rx_pid_base_regnum_val = INVALID_REGNUM;
@@ -1810,9 +1811,68 @@ rx_expand_prologue (void)
}
static void
+add_vector_labels (FILE *file, const char *aname)
+{
+ tree vec_attr;
+ tree val_attr;
+ const char *vname = "vect";
+ const char *s;
+ int vnum;
+
+ /* This node is for the vector/interrupt tag itself */
+ vec_attr = lookup_attribute (aname, DECL_ATTRIBUTES (current_function_decl));
+ if (!vec_attr)
+ return;
+
+ /* Now point it at the first argument */
+ vec_attr = TREE_VALUE (vec_attr);
+
+ /* Iterate through the arguments. */
+ while (vec_attr)
+ {
+ val_attr = TREE_VALUE (vec_attr);
+ switch (TREE_CODE (val_attr))
+ {
+ case STRING_CST:
+ s = TREE_STRING_POINTER (val_attr);
+ goto string_id_common;
+
+ case IDENTIFIER_NODE:
+ s = IDENTIFIER_POINTER (val_attr);
+
+ string_id_common:
+ if (strcmp (s, "$default") == 0)
+ {
+ fprintf (file, "\t.global\t$tableentry$default$%s\n", vname);
+ fprintf (file, "$tableentry$default$%s:\n", vname);
+ }
+ else
+ vname = s;
+ break;
+
+ case INTEGER_CST:
+ vnum = TREE_INT_CST_LOW (val_attr);
+
+ fprintf (file, "\t.global\t$tableentry$%d$%s\n", vnum, vname);
+ fprintf (file, "$tableentry$%d$%s:\n", vnum, vname);
+ break;
+
+ default:
+ ;
+ }
+
+ vec_attr = TREE_CHAIN (vec_attr);
+ }
+
+}
+
+static void
rx_output_function_prologue (FILE * file,
HOST_WIDE_INT frame_size ATTRIBUTE_UNUSED)
{
+ add_vector_labels (file, "interrupt");
+ add_vector_labels (file, "vector");
+
if (is_fast_interrupt_func (NULL_TREE))
asm_fprintf (file, "\t; Note: Fast Interrupt Handler\n");
@@ -2602,7 +2662,6 @@ rx_handle_func_attribute (tree * node,
bool * no_add_attrs)
{
gcc_assert (DECL_P (* node));
- gcc_assert (args == NULL_TREE);
if (TREE_CODE (* node) != FUNCTION_DECL)
{
@@ -2618,6 +2677,28 @@ rx_handle_func_attribute (tree * node,
return NULL_TREE;
}
+/* Check "vector" attribute. */
+
+static tree
+rx_handle_vector_attribute (tree * node,
+ tree name,
+ tree args,
+ int flags ATTRIBUTE_UNUSED,
+ bool * no_add_attrs)
+{
+ gcc_assert (DECL_P (* node));
+ gcc_assert (args != NULL_TREE);
+
+ if (TREE_CODE (* node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute only applies to functions",
+ name);
+ * no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Table of RX specific attributes. */
const struct attribute_spec rx_attribute_table[] =
{
@@ -2625,10 +2706,12 @@ const struct attribute_spec rx_attribute_table[] =
affects_type_identity. */
{ "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute,
false },
- { "interrupt", 0, 0, true, false, false, rx_handle_func_attribute,
+ { "interrupt", 0, -1, true, false, false, rx_handle_func_attribute,
false },
{ "naked", 0, 0, true, false, false, rx_handle_func_attribute,
false },
+ { "vector", 1, -1, true, false, false, rx_handle_vector_attribute,
+ false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
@@ -3155,6 +3238,9 @@ rx_adjust_insn_length (rtx insn, int current_length)
bool zero;
int factor;
+ if (!INSN_P (insn))
+ return current_length;
+
switch (INSN_CODE (insn))
{
default:
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index ef080ad6c79..85a6ca9f67f 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see
#include "opts.h"
#include "tree-pass.h"
#include "context.h"
+#include "builtins.h"
/* Define the specific costs for a given cpu. */
@@ -1675,7 +1676,7 @@ s390_narrow_logical_operator (enum rtx_code code, rtx *memop, rtx *immop)
static struct machine_function *
s390_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* Map for smallest class containing reg regno. */
diff --git a/gcc/config/score/score.c b/gcc/config/score/score.c
index e238d6d092c..576a2a0cde9 100644
--- a/gcc/config/score/score.c
+++ b/gcc/config/score/score.c
@@ -51,6 +51,7 @@
#include "langhooks.h"
#include "df.h"
#include "opts.h"
+#include "builtins.h"
#define SCORE_SDATA_MAX score_sdata_max
#define SCORE_STACK_ALIGN(LOC) (((LOC) + 3) & ~3)
@@ -1199,7 +1200,7 @@ score_output_external (FILE *file ATTRIBUTE_UNUSED,
if (score_in_small_data_p (decl))
{
- p = ggc_alloc_extern_list ();
+ p = ggc_alloc<extern_list> ();
p->next = extern_head;
p->name = name;
p->size = int_size_in_bytes (TREE_TYPE (decl));
diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md
index 31f2e1f5a0b..d7251f36e35 100644
--- a/gcc/config/sh/predicates.md
+++ b/gcc/config/sh/predicates.md
@@ -1119,10 +1119,8 @@
;; A predicate that returns true if OP is a valid construct around the T bit
;; that can be used as an operand for conditional branches.
(define_predicate "cbranch_treg_value"
- (match_code "eq,ne,reg,subreg,xor,sign_extend,zero_extend")
-{
- return sh_eval_treg_value (op) >= 0;
-})
+ (and (match_code "eq,ne,reg,subreg,xor,sign_extend,zero_extend")
+ (match_test "sh_eval_treg_value (op) >= 0")))
;; Returns true if OP is arith_reg_operand or t_reg_operand.
(define_predicate "arith_reg_or_t_reg_operand"
@@ -1134,6 +1132,28 @@
(define_predicate "negt_reg_shl31_operand"
(match_code "plus,minus,if_then_else")
{
+ /* (minus:SI (const_int -2147483648) ;; 0xffffffff80000000
+ (ashift:SI (match_operand:SI 1 "t_reg_operand")
+ (const_int 31)))
+ */
+ if (GET_CODE (op) == MINUS && satisfies_constraint_Jhb (XEXP (op, 0))
+ && GET_CODE (XEXP (op, 1)) == ASHIFT
+ && t_reg_operand (XEXP (XEXP (op, 1), 0), SImode)
+ && CONST_INT_P (XEXP (XEXP (op, 1), 1))
+ && INTVAL (XEXP (XEXP (op, 1), 1)) == 31)
+ return true;
+
+ /* (plus:SI (ashift:SI (match_operand:SI 1 "t_reg_operand")
+ (const_int 31))
+ (const_int -2147483648)) ;; 0xffffffff80000000
+ */
+ if (GET_CODE (op) == PLUS && satisfies_constraint_Jhb (XEXP (op, 1))
+ && GET_CODE (XEXP (op, 0)) == ASHIFT
+ && t_reg_operand (XEXP (XEXP (op, 0), 0), SImode)
+ && CONST_INT_P (XEXP (XEXP (op, 0), 1))
+ && INTVAL (XEXP (XEXP (op, 0), 1)) == 31)
+ return true;
+
/* (plus:SI (mult:SI (match_operand:SI 1 "t_reg_operand")
(const_int -2147483648)) ;; 0xffffffff80000000
(const_int -2147483648))
diff --git a/gcc/config/sh/sh-mem.cc b/gcc/config/sh/sh-mem.cc
index 0e38913b929..d3110f2351f 100644
--- a/gcc/config/sh/sh-mem.cc
+++ b/gcc/config/sh/sh-mem.cc
@@ -568,7 +568,7 @@ sh_expand_strlen (rtx *operands)
addr1 = adjust_automodify_address (addr1, SImode, current_addr, 0);
- /*start long loop. */
+ /* start long loop. */
emit_label (L_loop_long);
/* tmp1 is aligned, OK to load. */
@@ -589,29 +589,15 @@ sh_expand_strlen (rtx *operands)
addr1 = adjust_address (addr1, QImode, 0);
/* unroll remaining bytes. */
- emit_insn (gen_extendqisi2 (tmp1, addr1));
- emit_insn (gen_cmpeqsi_t (tmp1, const0_rtx));
- jump = emit_jump_insn (gen_branch_true (L_return));
- add_int_reg_note (jump, REG_BR_PROB, prob_likely);
-
- emit_move_insn (current_addr, plus_constant (Pmode, current_addr, 1));
-
- emit_insn (gen_extendqisi2 (tmp1, addr1));
- emit_insn (gen_cmpeqsi_t (tmp1, const0_rtx));
- jump = emit_jump_insn (gen_branch_true (L_return));
- add_int_reg_note (jump, REG_BR_PROB, prob_likely);
-
- emit_move_insn (current_addr, plus_constant (Pmode, current_addr, 1));
-
- emit_insn (gen_extendqisi2 (tmp1, addr1));
- emit_insn (gen_cmpeqsi_t (tmp1, const0_rtx));
- jump = emit_jump_insn (gen_branch_true (L_return));
- add_int_reg_note (jump, REG_BR_PROB, prob_likely);
-
- emit_move_insn (current_addr, plus_constant (Pmode, current_addr, 1));
+ for (int i = 0; i < 4; ++i)
+ {
+ emit_insn (gen_extendqisi2 (tmp1, addr1));
+ emit_move_insn (current_addr, plus_constant (Pmode, current_addr, 1));
+ emit_insn (gen_cmpeqsi_t (tmp1, const0_rtx));
+ jump = emit_jump_insn (gen_branch_true (L_return));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+ }
- emit_insn (gen_extendqisi2 (tmp1, addr1));
- jump = emit_jump_insn (gen_jump_compact (L_return));
emit_barrier_after (jump);
/* start byte loop. */
@@ -626,10 +612,9 @@ sh_expand_strlen (rtx *operands)
/* end loop. */
- emit_insn (gen_addsi3 (start_addr, start_addr, GEN_INT (1)));
-
emit_label (L_return);
+ emit_insn (gen_addsi3 (start_addr, start_addr, GEN_INT (1)));
emit_insn (gen_subsi3 (operands[0], current_addr, start_addr));
return true;
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 26a5d79f137..caa558ecea5 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -73,6 +73,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "pass_manager.h"
#include "context.h"
+#include "builtins.h"
int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;
@@ -202,6 +203,13 @@ static void push_regs (HARD_REG_SET *, int);
static int calc_live_regs (HARD_REG_SET *);
static HOST_WIDE_INT rounded_frame_size (int);
static bool sh_frame_pointer_required (void);
+static void sh_emit_mode_set (int, int, HARD_REG_SET);
+static int sh_mode_needed (int, rtx);
+static int sh_mode_after (int, int, rtx);
+static int sh_mode_entry (int);
+static int sh_mode_exit (int);
+static int sh_mode_priority (int entity, int n);
+
static rtx mark_constant_pool_use (rtx);
static tree sh_handle_interrupt_handler_attribute (tree *, tree, tree,
int, bool *);
@@ -564,6 +572,24 @@ static const struct attribute_spec sh_attribute_table[] =
#undef TARGET_FRAME_POINTER_REQUIRED
#define TARGET_FRAME_POINTER_REQUIRED sh_frame_pointer_required
+#undef TARGET_MODE_EMIT
+#define TARGET_MODE_EMIT sh_emit_mode_set
+
+#undef TARGET_MODE_NEEDED
+#define TARGET_MODE_NEEDED sh_mode_needed
+
+#undef TARGET_MODE_AFTER
+#define TARGET_MODE_AFTER sh_mode_after
+
+#undef TARGET_MODE_ENTRY
+#define TARGET_MODE_ENTRY sh_mode_entry
+
+#undef TARGET_MODE_EXIT
+#define TARGET_MODE_EXIT sh_mode_exit
+
+#undef TARGET_MODE_PRIORITY
+#define TARGET_MODE_PRIORITY sh_mode_priority
+
/* Return regmode weight for insn. */
#define INSN_REGMODE_WEIGHT(INSN, MODE)\
regmode_weight[((MODE) == SImode) ? 0 : 1][INSN_UID (INSN)]
@@ -904,15 +930,16 @@ sh_option_override (void)
sh_divsi3_libfunc = "__sdivsi3_1";
else
sh_divsi3_libfunc = "__sdivsi3";
+
if (sh_branch_cost == -1)
{
- sh_branch_cost = 1;
-
/* The SH1 does not have delay slots, hence we get a pipeline stall
at every branch. The SH4 is superscalar, so the single delay slot
- is not sufficient to keep both pipelines filled. */
- if (! TARGET_SH2 || TARGET_HARD_SH4)
- sh_branch_cost = 2;
+ is not sufficient to keep both pipelines filled.
+ In any case, set the default branch cost to '2', as it results in
+ slightly overall smaller code and also enables some if conversions
+ that are required for matching special T bit related insns. */
+ sh_branch_cost = 2;
}
/* Set -mzdcbranch for SH4 / SH4A if not otherwise specified by the user. */
@@ -2062,12 +2089,11 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison)
lsw_taken_prob = prob ? REG_BR_PROB_BASE : 0;
else
{
- gcc_assert (HOST_BITS_PER_WIDEST_INT >= 64);
lsw_taken_prob
= (prob
? (REG_BR_PROB_BASE
- - ((HOST_WIDEST_INT) REG_BR_PROB_BASE * rev_prob
- / ((HOST_WIDEST_INT) prob << 32)))
+ - ((gcov_type) REG_BR_PROB_BASE * rev_prob
+ / ((gcov_type) prob << 32)))
: 0);
}
}
@@ -2224,7 +2250,12 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison)
int
sh_eval_treg_value (rtx op)
{
- enum rtx_code code = GET_CODE (op);
+ if (t_reg_operand (op, GET_MODE (op)))
+ return 1;
+ if (negt_reg_operand (op, GET_MODE (op)))
+ return 0;
+
+ rtx_code code = GET_CODE (op);
if ((code != EQ && code != NE) || !CONST_INT_P (XEXP (op, 1)))
return -1;
@@ -13549,4 +13580,45 @@ sh_try_omit_signzero_extend (rtx extended_op, rtx insn)
return NULL_RTX;
}
+static void
+sh_emit_mode_set (int entity ATTRIBUTE_UNUSED, int mode,
+ HARD_REG_SET regs_live)
+{
+ fpscr_set_from_mem (mode, regs_live);
+}
+
+static int
+sh_mode_needed (int entity ATTRIBUTE_UNUSED, rtx insn)
+{
+ return recog_memoized (insn) >= 0 ? get_attr_fp_mode (insn) : FP_MODE_NONE;
+}
+
+static int
+sh_mode_after (int entity ATTRIBUTE_UNUSED, int mode, rtx insn)
+{
+ if (TARGET_HITACHI && recog_memoized (insn) >= 0 &&
+ get_attr_fp_set (insn) != FP_SET_NONE)
+ return (int) get_attr_fp_set (insn);
+ else
+ return mode;
+}
+
+static int
+sh_mode_entry (int entity ATTRIBUTE_UNUSED)
+{
+ return NORMAL_MODE (entity);
+}
+
+static int
+sh_mode_exit (int entity ATTRIBUTE_UNUSED)
+{
+ return sh_cfun_attr_renesas_p () ? FP_MODE_NONE : NORMAL_MODE (entity);
+}
+
+static int
+sh_mode_priority (int entity ATTRIBUTE_UNUSED, int n)
+{
+ return ((TARGET_FPU_SINGLE != 0) ^ (n) ? FP_MODE_SINGLE : FP_MODE_DOUBLE);
+}
+
#include "gt-sh.h"
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 00ee0edffda..e42b8d31b68 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -2218,32 +2218,9 @@ extern int current_function_interrupt;
? (TARGET_FMOVD ? FP_MODE_DOUBLE : FP_MODE_NONE) \
: ACTUAL_NORMAL_MODE (ENTITY))
-#define MODE_ENTRY(ENTITY) NORMAL_MODE (ENTITY)
-
-#define MODE_EXIT(ENTITY) \
- (sh_cfun_attr_renesas_p () ? FP_MODE_NONE : NORMAL_MODE (ENTITY))
-
#define EPILOGUE_USES(REGNO) ((TARGET_SH2E || TARGET_SH4) \
&& (REGNO) == FPSCR_REG)
-#define MODE_NEEDED(ENTITY, INSN) \
- (recog_memoized (INSN) >= 0 \
- ? get_attr_fp_mode (INSN) \
- : FP_MODE_NONE)
-
-#define MODE_AFTER(ENTITY, MODE, INSN) \
- (TARGET_HITACHI \
- && recog_memoized (INSN) >= 0 \
- && get_attr_fp_set (INSN) != FP_SET_NONE \
- ? (int) get_attr_fp_set (INSN) \
- : (MODE))
-
-#define MODE_PRIORITY_TO_MODE(ENTITY, N) \
- ((TARGET_FPU_SINGLE != 0) ^ (N) ? FP_MODE_SINGLE : FP_MODE_DOUBLE)
-
-#define EMIT_MODE_SET(ENTITY, MODE, HARD_REGS_LIVE) \
- fpscr_set_from_mem ((MODE), (HARD_REGS_LIVE))
-
#define MD_CAN_REDIRECT_BRANCH(INSN, SEQ) \
sh_can_redirect_branch ((INSN), (SEQ))
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 367f4ef2bbf..d998af96ec8 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -1830,6 +1830,8 @@
;; We allow a reg or 0 for one of the operands in order to be able to
;; do 'reg + T' sequences. Reload will load the constant 0 into the reg
;; as needed.
+;; FIXME: The load of constant 0 should be split out before reload, or else
+;; it will be difficult to hoist or combine the constant load.
(define_insn "*addc"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
(plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0")
@@ -1898,10 +1900,10 @@
;; can be scheduled much better since the load of the constant can be
;; done earlier, before any comparison insns that store the result in
;; the T bit.
-(define_insn_and_split "*addc_r_1"
- [(set (match_operand:SI 0 "arith_reg_dest" "")
- (plus:SI (match_operand:SI 1 "t_reg_operand" "")
- (match_operand:SI 2 "arith_reg_operand" "")))
+(define_insn_and_split "*addc_t_r"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (plus:SI (match_operand:SI 1 "t_reg_operand")
+ (match_operand:SI 2 "arith_reg_operand")))
(clobber (reg:SI T_REG))]
"TARGET_SH1"
"#"
@@ -1911,6 +1913,19 @@
(match_dup 1)))
(clobber (reg:SI T_REG))])])
+(define_insn_and_split "*addc_r_t"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (plus:SI (match_operand:SI 1 "arith_reg_operand")
+ (match_operand:SI 2 "t_reg_operand")))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ "#"
+ "&& 1"
+ [(parallel [(set (match_dup 0)
+ (plus:SI (plus:SI (match_dup 1) (const_int 0))
+ (match_dup 2)))
+ (clobber (reg:SI T_REG))])])
+
;; Use shlr-addc to do 'reg + (reg & 1)'.
(define_insn_and_split "*addc_r_lsb"
[(set (match_operand:SI 0 "arith_reg_dest")
@@ -8357,9 +8372,29 @@ label:
(const_int 2)
(const_int 2)
(const_int 0)])
- (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
- (const_string "single")
- (const_string "single")))])
+ (set_attr_alternative "fp_mode"
+ [(if_then_else (eq_attr "fmovd" "yes")
+ (const_string "single") (const_string "none"))
+ (const_string "none")
+ (const_string "single")
+ (const_string "single")
+ (const_string "none")
+ (if_then_else (eq_attr "fmovd" "yes")
+ (const_string "single") (const_string "none"))
+ (if_then_else (eq_attr "fmovd" "yes")
+ (const_string "single") (const_string "none"))
+ (const_string "none")
+ (const_string "none")
+ (const_string "none")
+ (const_string "none")
+ (const_string "none")
+ (const_string "none")
+ (const_string "none")
+ (const_string "none")
+ (const_string "none")
+ (const_string "none")
+ (const_string "none")
+ (const_string "none")])])
(define_split
[(set (match_operand:SF 0 "register_operand" "")
@@ -8804,7 +8839,7 @@ label:
(define_insn "jump_compact"
[(set (pc)
(label_ref (match_operand 0 "" "")))]
- "TARGET_SH1 && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
+ "TARGET_SH1 && !CROSSING_JUMP_P (insn)"
{
/* The length is 16 if the delay slot is unfilled. */
if (get_attr_length(insn) > 4)
@@ -11568,34 +11603,34 @@ label:
;; Store inverted T bit as MSB in a reg.
;; T = 0: 0x80000000 -> reg
;; T = 1: 0x00000000 -> reg
-;; On SH2A we can get away without clobbering the T_REG.
+;; On SH2A we can get away without clobbering the T_REG using the movrt insn.
+;; On non SH2A we resort to the following sequence:
+;; movt Rn
+;; tst Rn,Rn
+;; rotcr Rn
+;; The T bit value will be modified during the sequence, but the rotcr insn
+;; will restore its original value.
(define_insn_and_split "*negt_msb"
[(set (match_operand:SI 0 "arith_reg_dest")
(match_operand:SI 1 "negt_reg_shl31_operand"))]
- "TARGET_SH2A"
+ "TARGET_SH1"
"#"
"&& can_create_pseudo_p ()"
[(const_int 0)]
{
rtx tmp = gen_reg_rtx (SImode);
- emit_insn (gen_movrt (tmp, get_t_reg_rtx ()));
- emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx));
- DONE;
-})
-(define_insn_and_split "*negt_msb"
- [(set (match_operand:SI 0 "arith_reg_dest")
- (match_operand:SI 1 "negt_reg_shl31_operand"))
- (clobber (reg:SI T_REG))]
- "TARGET_SH1 && !TARGET_SH2A"
- "#"
- "&& can_create_pseudo_p ()"
- [(const_int 0)]
-{
- rtx tmp = gen_reg_rtx (SImode);
- emit_move_insn (tmp, get_t_reg_rtx ());
- emit_insn (gen_cmpeqsi_t (tmp, const0_rtx));
- emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ()));
+ if (TARGET_SH2A)
+ {
+ emit_insn (gen_movrt (tmp, get_t_reg_rtx ()));
+ emit_insn (gen_rotrsi3 (operands[0], tmp, const1_rtx));
+ }
+ else
+ {
+ emit_move_insn (tmp, get_t_reg_rtx ());
+ emit_insn (gen_cmpeqsi_t (tmp, const0_rtx));
+ emit_insn (gen_rotcr (operands[0], tmp, get_t_reg_rtx ()));
+ }
DONE;
})
@@ -11624,14 +11659,22 @@ label:
(define_insn "*cset_zero"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (if_then_else:SI (match_operand:SI 1 "t_reg_operand")
+ (if_then_else:SI (match_operand:SI 1 "cbranch_treg_value")
(match_operand:SI 2 "arith_reg_operand" "0")
(const_int 0)))]
"TARGET_SH1 && TARGET_ZDCBRANCH"
{
- return "bt 0f" "\n"
- " mov #0,%0" "\n"
- "0:";
+ int tval = sh_eval_treg_value (operands[1]);
+ if (tval == true)
+ return "bt 0f" "\n"
+ " mov #0,%0" "\n"
+ "0:";
+ else if (tval == false)
+ return "bf 0f" "\n"
+ " mov #0,%0" "\n"
+ "0:";
+ else
+ gcc_unreachable ();
}
[(set_attr "type" "arith") ;; poor approximation
(set_attr "length" "4")])
diff --git a/gcc/config/sol2-clearcap.map b/gcc/config/sol2-clearcap.map
new file mode 100644
index 00000000000..2d880c983e4
--- /dev/null
+++ b/gcc/config/sol2-clearcap.map
@@ -0,0 +1,2 @@
+# Clear all hardware capabilities emitted by Sun as.
+hwcap_1 = V0x0 OVERRIDE;
diff --git a/gcc/config/sol2-clearcapv2.map b/gcc/config/sol2-clearcapv2.map
new file mode 100644
index 00000000000..3c0cacedbf0
--- /dev/null
+++ b/gcc/config/sol2-clearcapv2.map
@@ -0,0 +1,7 @@
+# Clear all hardware capabilities emitted by Sun as.
+#
+# Uses mapfile v2 syntax which is the only way to clear AT_SUN_CAP_HW2 flags.
+$mapfile_version 2
+CAPABILITY {
+ HW = ;
+};
diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h
index d88de37bd2e..d41e3c4428a 100644
--- a/gcc/config/sol2.h
+++ b/gcc/config/sol2.h
@@ -268,12 +268,21 @@ along with GCC; see the file COPYING3. If not see
#define LINK_LIBGCC_MAPFILE_SPEC ""
#endif
+/* Clear hardware capabilities, either explicitly or with OpenMP:
+ #pragma openmp declare simd creates clones for SSE2, AVX, and AVX2. */
+#ifdef HAVE_LD_CLEARCAP
+#define LINK_CLEARCAP_SPEC " %{mclear-hwcap|fopenmp*:-M %sclearcap.map}"
+#else
+#define LINK_CLEARCAP_SPEC ""
+#endif
+
#undef LINK_SPEC
#define LINK_SPEC \
"%{h*} %{v:-V} \
%{!shared:%{!static:%{rdynamic: " RDYNAMIC_SPEC "}}} \
%{static:-dn -Bstatic} \
- %{shared:-G -dy %{!mimpure-text:-z text}} " LINK_LIBGCC_MAPFILE_SPEC " \
+ %{shared:-G -dy %{!mimpure-text:-z text}} " \
+ LINK_LIBGCC_MAPFILE_SPEC LINK_CLEARCAP_SPEC " \
%{symbolic:-Bsymbolic -G -dy -z text} \
%(link_arch) \
%{Qy:} %{!Qn:-Qy}"
diff --git a/gcc/config/sol2.opt b/gcc/config/sol2.opt
index a5ae7c510ad..16a3e5f581b 100644
--- a/gcc/config/sol2.opt
+++ b/gcc/config/sol2.opt
@@ -27,6 +27,10 @@ Driver Joined
Ym,
Driver Joined
+mclear-hwcap
+Target Report
+Clear hardware capabilities when linking
+
mimpure-text
Target Report
Pass -z text to linker
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index 1d63e46406d..ee2091bb8e0 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -69,7 +69,6 @@ extern bool sparc_expand_move (enum machine_mode, rtx *);
extern void sparc_emit_set_symbolic_const64 (rtx, rtx, rtx);
extern int sparc_splitdi_legitimate (rtx, rtx);
extern int sparc_split_regreg_legitimate (rtx, rtx);
-extern int sparc_absnegfloat_split_legitimate (rtx, rtx);
extern const char *output_ubranch (rtx, rtx);
extern const char *output_cbranch (rtx, rtx, int, int, int, rtx);
extern const char *output_return (rtx);
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index ff1e9d154b2..8b1dfa6d3b0 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "context.h"
#include "wide-int.h"
+#include "builtins.h"
/* Processor costs */
@@ -8543,22 +8544,6 @@ sparc_split_regreg_legitimate (rtx reg1, rtx reg2)
return 0;
}
-/* Return 1 if x and y are some kind of REG and they refer to
- different hard registers. This test is guaranteed to be
- run after reload. */
-
-int
-sparc_absnegfloat_split_legitimate (rtx x, rtx y)
-{
- if (GET_CODE (x) != REG)
- return 0;
- if (GET_CODE (y) != REG)
- return 0;
- if (REGNO (x) == REGNO (y))
- return 0;
- return 1;
-}
-
/* Return 1 if REGNO (reg1) is even and REGNO (reg1) == REGNO (reg2) - 1.
This makes them candidates for using ldd and std insns.
@@ -10931,8 +10916,8 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
&& TREE_CODE (arg2) == INTEGER_CST)
{
bool overflow = false;
- wide_int result = arg2;
- wide_int tmp;
+ widest_int result = wi::to_widest (arg2);
+ widest_int tmp;
unsigned i;
for (i = 0; i < VECTOR_CST_NELTS (arg0); ++i)
@@ -10942,8 +10927,8 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
bool neg1_ovf, neg2_ovf, add1_ovf, add2_ovf;
- tmp = wi::neg (e1, &neg1_ovf);
- tmp = wi::add (e0, tmp, SIGNED, &add1_ovf);
+ tmp = wi::neg (wi::to_widest (e1), &neg1_ovf);
+ tmp = wi::add (wi::to_widest (e0), tmp, SIGNED, &add1_ovf);
if (wi::neg_p (tmp))
tmp = wi::neg (tmp, &neg2_ovf);
else
@@ -11494,7 +11479,7 @@ sparc_can_output_mi_thunk (const_tree thunk_fndecl ATTRIBUTE_UNUSED,
static struct machine_function *
sparc_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* Locate some local-dynamic symbol still in use by this function
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index e2a4669e05d..b6cd7f02685 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -424,6 +424,10 @@
(define_attr "fptype" "single,double"
(const_string "single"))
+;; FP precision specific to the UT699.
+(define_attr "fptype_ut699" "none,single"
+ (const_string "none"))
+
;; UltraSPARC-III integer load type.
(define_attr "us3load_type" "2cycle,3cycle"
(const_string "2cycle"))
@@ -464,7 +468,8 @@
(const_string "false")
(and (eq_attr "fix_ut699" "true")
(and (eq_attr "type" "fpload,fp,fpmove,fpmul,fpdivs,fpsqrts")
- (eq_attr "fptype" "single")))
+ (ior (eq_attr "fptype" "single")
+ (eq_attr "fptype_ut699" "single"))))
(const_string "false")
(eq_attr "length" "1")
(const_string "true")
@@ -1886,7 +1891,7 @@
emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
operands[1]));
#else
- unsigned int low, high;
+ HOST_WIDE_INT low, high;
low = trunc_int_for_mode (INTVAL (operands[1]), SImode);
high = trunc_int_for_mode (INTVAL (operands[1]) >> 32, SImode);
@@ -3455,7 +3460,8 @@
"TARGET_FPU"
"fdtos\t%1, %0"
[(set_attr "type" "fp")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "double")
+ (set_attr "fptype_ut699" "single")])
(define_expand "trunctfsf2"
[(set (match_operand:SF 0 "register_operand" "")
@@ -3496,7 +3502,7 @@
"TARGET_FPU"
"fitos\t%1, %0"
[(set_attr "type" "fp")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "single")])
(define_insn "floatsidf2"
[(set (match_operand:DF 0 "register_operand" "=e")
@@ -3583,7 +3589,7 @@
"TARGET_FPU"
"fstoi\t%1, %0"
[(set_attr "type" "fp")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "single")])
(define_insn "fix_truncdfsi2"
[(set (match_operand:SI 0 "register_operand" "=f")
@@ -3591,7 +3597,8 @@
"TARGET_FPU"
"fdtoi\t%1, %0"
[(set_attr "type" "fp")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "double")
+ (set_attr "fptype_ut699" "single")])
(define_expand "fix_trunctfsi2"
[(set (match_operand:SI 0 "register_operand" "")
@@ -4822,7 +4829,7 @@
[(set (match_dup 3) (match_dup 4))
(set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
{
- operands[4] = GEN_INT (~INTVAL (operands[2]));
+ operands[4] = gen_int_mode (~INTVAL (operands[2]), SImode);
})
(define_insn_and_split "*or_not_di_sp32"
@@ -4899,7 +4906,7 @@
[(set (match_dup 3) (match_dup 4))
(set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
{
- operands[4] = GEN_INT (~INTVAL (operands[2]));
+ operands[4] = gen_int_mode (~INTVAL (operands[2]), SImode);
})
(define_split
@@ -4911,7 +4918,7 @@
[(set (match_dup 3) (match_dup 4))
(set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
{
- operands[4] = GEN_INT (~INTVAL (operands[2]));
+ operands[4] = gen_int_mode (~INTVAL (operands[2]), SImode);
})
;; Split DImode logical operations requiring two instructions.
@@ -5554,53 +5561,52 @@
[(set_attr "type" "fpdivs")])
(define_expand "negtf2"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
- (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
+ [(set (match_operand:TF 0 "register_operand" "")
+ (neg:TF (match_operand:TF 1 "register_operand" "")))]
"TARGET_FPU"
"")
-(define_insn_and_split "*negtf2_notv9"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
- (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
- ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
- "TARGET_FPU
- && ! TARGET_V9"
- "@
- fnegs\t%0, %0
- #"
- "&& reload_completed
- && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
- [(set (match_dup 2) (neg:SF (match_dup 3)))
- (set (match_dup 4) (match_dup 5))
- (set (match_dup 6) (match_dup 7))]
- "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
- operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
- operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
- operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
- operands[6] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
- operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
- [(set_attr "type" "fpmove,*")
- (set_attr "length" "*,2")])
-
-(define_insn_and_split "*negtf2_v9"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
- (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
- ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
- "TARGET_FPU && TARGET_V9"
- "@
- fnegd\t%0, %0
- #"
- "&& reload_completed
- && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
- [(set (match_dup 2) (neg:DF (match_dup 3)))
- (set (match_dup 4) (match_dup 5))]
- "operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
- operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
- operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
- operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
- [(set_attr "type" "fpmove,*")
- (set_attr "length" "*,2")
- (set_attr "fptype" "double")])
+(define_insn "*negtf2_hq"
+ [(set (match_operand:TF 0 "register_operand" "=e")
+ (neg:TF (match_operand:TF 1 "register_operand" "e")))]
+ "TARGET_FPU && TARGET_HARD_QUAD"
+ "fnegq\t%1, %0"
+ [(set_attr "type" "fpmove")])
+
+(define_insn_and_split "*negtf2"
+ [(set (match_operand:TF 0 "register_operand" "=e")
+ (neg:TF (match_operand:TF 1 "register_operand" "e")))]
+ "TARGET_FPU && !TARGET_HARD_QUAD"
+ "#"
+ "&& reload_completed"
+ [(clobber (const_int 0))]
+{
+ rtx set_dest = operands[0];
+ rtx set_src = operands[1];
+ rtx dest1, dest2;
+ rtx src1, src2;
+
+ dest1 = gen_df_reg (set_dest, 0);
+ dest2 = gen_df_reg (set_dest, 1);
+ src1 = gen_df_reg (set_src, 0);
+ src2 = gen_df_reg (set_src, 1);
+
+ /* Now emit using the real source and destination we found, swapping
+ the order if we detect overlap. */
+ if (reg_overlap_mentioned_p (dest1, src2))
+ {
+ emit_insn (gen_movdf (dest2, src2));
+ emit_insn (gen_negdf2 (dest1, src1));
+ }
+ else
+ {
+ emit_insn (gen_negdf2 (dest1, src1));
+ if (REGNO (dest2) != REGNO (src2))
+ emit_insn (gen_movdf (dest2, src2));
+ }
+ DONE;
+}
+ [(set_attr "length" "2")])
(define_expand "negdf2"
[(set (match_operand:DF 0 "register_operand" "")
@@ -5609,22 +5615,39 @@
"")
(define_insn_and_split "*negdf2_notv9"
- [(set (match_operand:DF 0 "register_operand" "=e,e")
- (neg:DF (match_operand:DF 1 "register_operand" "0,e")))]
- "TARGET_FPU && ! TARGET_V9"
- "@
- fnegs\t%0, %0
- #"
- "&& reload_completed
- && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
- [(set (match_dup 2) (neg:SF (match_dup 3)))
- (set (match_dup 4) (match_dup 5))]
- "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
- operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
- operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
- operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);"
- [(set_attr "type" "fpmove,*")
- (set_attr "length" "*,2")])
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (neg:DF (match_operand:DF 1 "register_operand" "e")))]
+ "TARGET_FPU && !TARGET_V9"
+ "#"
+ "&& reload_completed"
+ [(clobber (const_int 0))]
+{
+ rtx set_dest = operands[0];
+ rtx set_src = operands[1];
+ rtx dest1, dest2;
+ rtx src1, src2;
+
+ dest1 = gen_highpart (SFmode, set_dest);
+ dest2 = gen_lowpart (SFmode, set_dest);
+ src1 = gen_highpart (SFmode, set_src);
+ src2 = gen_lowpart (SFmode, set_src);
+
+ /* Now emit using the real source and destination we found, swapping
+ the order if we detect overlap. */
+ if (reg_overlap_mentioned_p (dest1, src2))
+ {
+ emit_insn (gen_movsf (dest2, src2));
+ emit_insn (gen_negsf2 (dest1, src1));
+ }
+ else
+ {
+ emit_insn (gen_negsf2 (dest1, src1));
+ if (REGNO (dest2) != REGNO (src2))
+ emit_insn (gen_movsf (dest2, src2));
+ }
+ DONE;
+}
+ [(set_attr "length" "2")])
(define_insn "*negdf2_v9"
[(set (match_operand:DF 0 "register_operand" "=e")
@@ -5647,56 +5670,47 @@
"TARGET_FPU"
"")
-(define_insn_and_split "*abstf2_notv9"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
- (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
- ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
- "TARGET_FPU && ! TARGET_V9"
- "@
- fabss\t%0, %0
- #"
- "&& reload_completed
- && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
- [(set (match_dup 2) (abs:SF (match_dup 3)))
- (set (match_dup 4) (match_dup 5))
- (set (match_dup 6) (match_dup 7))]
- "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
- operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
- operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
- operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
- operands[6] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
- operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
- [(set_attr "type" "fpmove,*")
- (set_attr "length" "*,2")])
-
-(define_insn "*abstf2_hq_v9"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
- (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
- "TARGET_FPU && TARGET_V9 && TARGET_HARD_QUAD"
- "@
- fabsd\t%0, %0
- fabsq\t%1, %0"
- [(set_attr "type" "fpmove")
- (set_attr "fptype" "double,*")])
+(define_insn "*abstf2_hq"
+ [(set (match_operand:TF 0 "register_operand" "=e")
+ (abs:TF (match_operand:TF 1 "register_operand" "e")))]
+ "TARGET_FPU && TARGET_HARD_QUAD"
+ "fabsq\t%1, %0"
+ [(set_attr "type" "fpmove")])
-(define_insn_and_split "*abstf2_v9"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
- (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
- "TARGET_FPU && TARGET_V9 && !TARGET_HARD_QUAD"
- "@
- fabsd\t%0, %0
- #"
- "&& reload_completed
- && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
- [(set (match_dup 2) (abs:DF (match_dup 3)))
- (set (match_dup 4) (match_dup 5))]
- "operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
- operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
- operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
- operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
- [(set_attr "type" "fpmove,*")
- (set_attr "length" "*,2")
- (set_attr "fptype" "double,*")])
+(define_insn_and_split "*abstf2"
+ [(set (match_operand:TF 0 "register_operand" "=e")
+ (abs:TF (match_operand:TF 1 "register_operand" "e")))]
+ "TARGET_FPU && !TARGET_HARD_QUAD"
+ "#"
+ "&& reload_completed"
+ [(clobber (const_int 0))]
+{
+ rtx set_dest = operands[0];
+ rtx set_src = operands[1];
+ rtx dest1, dest2;
+ rtx src1, src2;
+
+ dest1 = gen_df_reg (set_dest, 0);
+ dest2 = gen_df_reg (set_dest, 1);
+ src1 = gen_df_reg (set_src, 0);
+ src2 = gen_df_reg (set_src, 1);
+
+ /* Now emit using the real source and destination we found, swapping
+ the order if we detect overlap. */
+ if (reg_overlap_mentioned_p (dest1, src2))
+ {
+ emit_insn (gen_movdf (dest2, src2));
+ emit_insn (gen_absdf2 (dest1, src1));
+ }
+ else
+ {
+ emit_insn (gen_absdf2 (dest1, src1));
+ if (REGNO (dest2) != REGNO (src2))
+ emit_insn (gen_movdf (dest2, src2));
+ }
+ DONE;
+}
+ [(set_attr "length" "2")])
(define_expand "absdf2"
[(set (match_operand:DF 0 "register_operand" "")
@@ -5705,22 +5719,39 @@
"")
(define_insn_and_split "*absdf2_notv9"
- [(set (match_operand:DF 0 "register_operand" "=e,e")
- (abs:DF (match_operand:DF 1 "register_operand" "0,e")))]
- "TARGET_FPU && ! TARGET_V9"
- "@
- fabss\t%0, %0
- #"
- "&& reload_completed
- && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
- [(set (match_dup 2) (abs:SF (match_dup 3)))
- (set (match_dup 4) (match_dup 5))]
- "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
- operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
- operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
- operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);"
- [(set_attr "type" "fpmove,*")
- (set_attr "length" "*,2")])
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (abs:DF (match_operand:DF 1 "register_operand" "e")))]
+ "TARGET_FPU && !TARGET_V9"
+ "#"
+ "&& reload_completed"
+ [(clobber (const_int 0))]
+{
+ rtx set_dest = operands[0];
+ rtx set_src = operands[1];
+ rtx dest1, dest2;
+ rtx src1, src2;
+
+ dest1 = gen_highpart (SFmode, set_dest);
+ dest2 = gen_lowpart (SFmode, set_dest);
+ src1 = gen_highpart (SFmode, set_src);
+ src2 = gen_lowpart (SFmode, set_src);
+
+ /* Now emit using the real source and destination we found, swapping
+ the order if we detect overlap. */
+ if (reg_overlap_mentioned_p (dest1, src2))
+ {
+ emit_insn (gen_movsf (dest2, src2));
+ emit_insn (gen_abssf2 (dest1, src1));
+ }
+ else
+ {
+ emit_insn (gen_abssf2 (dest1, src1));
+ if (REGNO (dest2) != REGNO (src2))
+ emit_insn (gen_movsf (dest2, src2));
+ }
+ DONE;
+}
+ [(set_attr "length" "2")])
(define_insn "*absdf2_v9"
[(set (match_operand:DF 0 "register_operand" "=e")
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index 88e3f5e5909..a32a3a33bdf 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -66,6 +66,7 @@
#include "df.h"
#include "dumpfile.h"
#include "cfgloop.h"
+#include "builtins.h"
/* Builtin types, data and prototypes. */
@@ -223,7 +224,7 @@ struct GTY(()) machine_function
static struct machine_function *
spu_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
/* Implement TARGET_OPTION_OVERRIDE. */
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index 6a64fccbe11..1463d52ef01 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -62,6 +62,7 @@
#include "gimplify.h"
#include "df.h"
#include "reload.h"
+#include "builtins.h"
static rtx emit_addhi3_postreload (rtx, rtx, rtx);
static void xstormy16_asm_out_constructor (rtx, int);
diff --git a/gcc/config/t-sol2 b/gcc/config/t-sol2
index a4c4af4ad03..25feb0486fd 100644
--- a/gcc/config/t-sol2
+++ b/gcc/config/t-sol2
@@ -35,3 +35,10 @@ sol2-stubs.o: $(srcdir)/config/sol2-stubs.c
sol2.o: $(srcdir)/config/sol2.c
$(COMPILE) $<
$(POSTCOMPILE)
+
+# Install clearcap.map if present.
+install: install-clearcap-map
+
+# Ignore failures: file only exists if linker supports it.
+install-clearcap-map:
+ -$(INSTALL_DATA) clearcap.map $(DESTDIR)$(libdir)
diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c
index c3b71261501..ab53fab26b8 100644
--- a/gcc/config/tilegx/tilegx.c
+++ b/gcc/config/tilegx/tilegx.c
@@ -61,6 +61,7 @@
#include "tilegx-builtins.h"
#include "tilegx-multiply.h"
#include "diagnostic.h"
+#include "builtins.h"
/* SYMBOL_REF for GOT */
static GTY(()) rtx g_got_symbol = NULL;
@@ -735,7 +736,7 @@ create_temp_reg_if_possible (enum machine_mode mode, rtx default_reg)
static struct machine_function *
tilegx_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c
index 74f88008fc7..1749556a557 100644
--- a/gcc/config/tilepro/tilepro.c
+++ b/gcc/config/tilepro/tilepro.c
@@ -62,6 +62,7 @@
#include "tilepro-builtins.h"
#include "tilepro-multiply.h"
#include "diagnostic.h"
+#include "builtins.h"
/* SYMBOL_REF for GOT */
static GTY(()) rtx g_got_symbol = NULL;
@@ -674,7 +675,7 @@ create_temp_reg_if_possible (enum machine_mode mode, rtx default_reg)
static struct machine_function *
tilepro_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
diff --git a/gcc/config/v850/rtems.h b/gcc/config/v850/rtems.h
index 01dff3e52ac..42ebb9fc0f1 100644
--- a/gcc/config/v850/rtems.h
+++ b/gcc/config/v850/rtems.h
@@ -13,8 +13,13 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* Specify predefined symbols in preprocessor. */
diff --git a/gcc/config/v850/v850-opts.h b/gcc/config/v850/v850-opts.h
index a91b1b05906..c3d9b7aac26 100644
--- a/gcc/config/v850/v850-opts.h
+++ b/gcc/config/v850/v850-opts.h
@@ -13,8 +13,13 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef V850_OPTS_H
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index eb193265700..e164586bfdc 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -45,6 +45,7 @@
#include "target-def.h"
#include "df.h"
#include "opts.h"
+#include "builtins.h"
#ifndef streq
#define streq(a,b) (strcmp (a, b) == 0)
diff --git a/gcc/config/v850/v850.h b/gcc/config/v850/v850.h
index 92db20a4405..6ccdc5d6514 100644
--- a/gcc/config/v850/v850.h
+++ b/gcc/config/v850/v850.h
@@ -14,8 +14,13 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_V850_H
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index 818137baceb..4897ac2d62c 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "target-def.h"
#include "wide-int.h"
+#include "builtins.h"
static void vax_option_override (void);
static bool vax_legitimate_address_p (enum machine_mode, rtx, bool);
diff --git a/gcc/config/vax/vax.md b/gcc/config/vax/vax.md
index d3929731b64..fc73367dfea 100644
--- a/gcc/config/vax/vax.md
+++ b/gcc/config/vax/vax.md
@@ -423,7 +423,7 @@
"vax_expand_addsub_di_operands (operands, MINUS); DONE;")
(define_insn "sbcdi3"
- [(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr,=Rr")
+ [(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr,Rr")
(minus:DI (match_operand:DI 1 "general_addsub_di_operand" "0,I")
(match_operand:DI 2 "general_addsub_di_operand" "nRr,Rr")))]
"TARGET_QMATH"
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index 06e1eb78ada..540ffecd391 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h"
#include "gimplify.h"
#include "df.h"
+#include "builtins.h"
/* Enumeration for all of the relational tests, so that we can build
@@ -1355,7 +1356,7 @@ xtensa_expand_nonlocal_goto (rtx *operands)
static struct machine_function *
xtensa_init_machine_status (void)
{
- return ggc_alloc_cleared_machine_function ();
+ return ggc_cleared_alloc<machine_function> ();
}
diff --git a/gcc/configure b/gcc/configure
index d912261c1cf..f60d3476a65 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -5862,49 +5862,6 @@ _ACEOF
fi
-ac_fn_c_check_type "$LINENO" "__int64" "ac_cv_type___int64" "$ac_includes_default"
-if test "x$ac_cv_type___int64" = x""yes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE___INT64 1
-_ACEOF
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of __int64" >&5
-$as_echo_n "checking size of __int64... " >&6; }
-if test "${ac_cv_sizeof___int64+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int64))" "ac_cv_sizeof___int64" "$ac_includes_default"; then :
-
-else
- if test "$ac_cv_type___int64" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ as_fn_set_status 77
-as_fn_error "cannot compute sizeof (__int64)
-See \`config.log' for more details." "$LINENO" 5; }; }
- else
- ac_cv_sizeof___int64=0
- fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof___int64" >&5
-$as_echo "$ac_cv_sizeof___int64" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF___INT64 $ac_cv_sizeof___int64
-_ACEOF
-
-
-fi
-
ac_fn_c_find_intX_t "$LINENO" "8" "ac_cv_c_int8_t"
case $ac_cv_c_int8_t in #(
no|yes) ;; #(
@@ -6269,6 +6226,9 @@ fi
+if test x"$ac_cv_c_uint64_t" = x"no" -o x"$ac_cv_c_int64_t" = x"no"; then
+ as_fn_error "uint64_t or int64_t not found" "$LINENO" 5
+fi
# ---------------------
# Warnings and checking
@@ -11150,12 +11110,6 @@ else
done
fi
-if test x$need_64bit_hwint = xyes; then
-
-$as_echo "#define NEED_64BIT_HOST_WIDE_INT 1" >>confdefs.h
-
-fi
-
if test x$use_long_long_for_widest_fast_int = xyes; then
$as_echo "#define USE_LONG_LONG_FOR_WIDEST_FAST_INT 1" >>confdefs.h
@@ -17994,7 +17948,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 17997 "configure"
+#line 17951 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -18100,7 +18054,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18103 "configure"
+#line 18057 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -26153,8 +26107,8 @@ $as_echo_n "checking assembler and linker for explicit JALR relocation... " >&6;
fi
elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x; then
echo ' .ent x' > conftest.s
- echo 'x: ld $2,%got_disp(y)($3)' >> conftest.s
- echo ' ld $25,%call16(y)($28)' >> conftest.s
+ echo 'x: lw $2,%got_disp(y)($3)' >> conftest.s
+ echo ' lw $25,%call16(y)($28)' >> conftest.s
echo ' .reloc 1f,R_MIPS_JALR,y' >> conftest.s
echo '1: jalr $25' >> conftest.s
echo ' .reloc 1f,R_MIPS_JALR,x' >> conftest.s
@@ -26966,6 +26920,34 @@ _ACEOF
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker mapfile support for clearing hardware capabilities" >&5
+$as_echo_n "checking linker mapfile support for clearing hardware capabilities... " >&6; }
+saved_LDFLAGS="$LDFLAGS"
+for clearcap_map in sol2-clearcapv2.map sol2-clearcap.map; do
+ LDFLAGS="$saved_LDFLAGS -Wl,-M,${srcdir}/config/$clearcap_map"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int main(void) {return 0;}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ gcc_cv_ld_clearcap=yes; break
+else
+ gcc_cv_ld_clearcap=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+done
+LDFLAGS="$saved_LDFLAGS"
+if test "x$gcc_cv_ld_clearcap" = xyes; then
+
+$as_echo "#define HAVE_LD_CLEARCAP 1" >>confdefs.h
+
+ ac_config_links="$ac_config_links clearcap.map:${srcdir}/config/$clearcap_map"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_clearcap" >&5
+$as_echo "$gcc_cv_ld_clearcap" >&6; }
+
case "$target:$tm_file" in
powerpc64-*-freebsd* | powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*)
case "$target" in
@@ -27331,6 +27313,13 @@ case "$target" in
gcc_cv_target_dl_iterate_phdr=no
fi
;;
+ *-*-dragonfly* | *-*-freebsd*)
+ if grep dl_iterate_phdr $target_header_dir/sys/link_elf.h > /dev/null 2>&1; then
+ gcc_cv_target_dl_iterate_phdr=yes
+ else
+ gcc_cv_target_dl_iterate_phdr=no
+ fi
+ ;;
esac
if test x$gcc_cv_target_dl_iterate_phdr = xyes; then
@@ -28495,6 +28484,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# Files that config.status was made for.
config_files="$ac_config_files"
config_headers="$ac_config_headers"
+config_links="$ac_config_links"
config_commands="$ac_config_commands"
_ACEOF
@@ -28524,6 +28514,9 @@ $config_files
Configuration headers:
$config_headers
+Configuration links:
+$config_links
+
Configuration commands:
$config_commands
@@ -28659,6 +28652,7 @@ do
"as") CONFIG_FILES="$CONFIG_FILES as:exec-tool.in" ;;
"collect-ld") CONFIG_FILES="$CONFIG_FILES collect-ld:exec-tool.in" ;;
"nm") CONFIG_FILES="$CONFIG_FILES nm:exec-tool.in" ;;
+ "clearcap.map") CONFIG_LINKS="$CONFIG_LINKS clearcap.map:${srcdir}/config/$clearcap_map" ;;
"$all_outputs") CONFIG_FILES="$CONFIG_FILES $all_outputs" ;;
"default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;
@@ -28674,6 +28668,7 @@ done
if $ac_need_defaults; then
test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links
test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
fi
@@ -28995,7 +28990,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
fi # test -n "$CONFIG_HEADERS"
-eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :L $CONFIG_LINKS :C $CONFIG_COMMANDS"
shift
for ac_tag
do
@@ -29231,7 +29226,38 @@ $as_echo "$as_me: $ac_file is unchanged" >&6;}
|| as_fn_error "could not create -" "$LINENO" 5
fi
;;
+ :L)
+ #
+ # CONFIG_LINK
+ #
+
+ if test "$ac_source" = "$ac_file" && test "$srcdir" = '.'; then
+ :
+ else
+ # Prefer the file from the source tree if names are identical.
+ if test "$ac_source" = "$ac_file" || test ! -r "$ac_source"; then
+ ac_source=$srcdir/$ac_source
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: linking $ac_source to $ac_file" >&5
+$as_echo "$as_me: linking $ac_source to $ac_file" >&6;}
+
+ if test ! -r "$ac_source"; then
+ as_fn_error "$ac_source: file not found" "$LINENO" 5
+ fi
+ rm -f "$ac_file"
+ # Try a relative symlink, then a hard link, then a copy.
+ case $srcdir in
+ [\\/$]* | ?:[\\/]* ) ac_rel_source=$ac_source ;;
+ *) ac_rel_source=$ac_top_build_prefix$ac_source ;;
+ esac
+ ln -s "$ac_rel_source" "$ac_file" 2>/dev/null ||
+ ln "$ac_source" "$ac_file" 2>/dev/null ||
+ cp -p "$ac_source" "$ac_file" ||
+ as_fn_error "cannot link or copy $ac_source to $ac_file" "$LINENO" 5
+ fi
+ ;;
:C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
$as_echo "$as_me: executing $ac_file commands" >&6;}
;;
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 5565524c89a..aa697cebce9 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -311,8 +311,10 @@ AC_CHECK_SIZEOF(short)
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
AC_CHECK_TYPES([long long], [AC_CHECK_SIZEOF(long long)])
-AC_CHECK_TYPES([__int64], [AC_CHECK_SIZEOF(__int64)])
GCC_STDINT_TYPES
+if test x"$ac_cv_c_uint64_t" = x"no" -o x"$ac_cv_c_int64_t" = x"no"; then
+ AC_MSG_ERROR([uint64_t or int64_t not found])
+fi
# ---------------------
# Warnings and checking
@@ -1372,14 +1374,9 @@ else
done
fi
-if test x$need_64bit_hwint = xyes; then
- AC_DEFINE(NEED_64BIT_HOST_WIDE_INT, 1,
-[Define to 1 if HOST_WIDE_INT must be 64 bits wide (see hwint.h).])
-fi
-
if test x$use_long_long_for_widest_fast_int = xyes; then
AC_DEFINE(USE_LONG_LONG_FOR_WIDEST_FAST_INT, 1,
-[Define to 1 if the 'long long' (or '__int64') is wider than 'long' but still
+[Define to 1 if the 'long long' type is wider than 'long' but still
efficiently supported by the host hardware.])
fi
@@ -4206,8 +4203,8 @@ x:
fi
elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x; then
echo ' .ent x' > conftest.s
- echo 'x: ld $2,%got_disp(y)($3)' >> conftest.s
- echo ' ld $25,%call16(y)($28)' >> conftest.s
+ echo 'x: lw $2,%got_disp(y)($3)' >> conftest.s
+ echo ' lw $25,%call16(y)($28)' >> conftest.s
echo ' .reloc 1f,R_MIPS_JALR,y' >> conftest.s
echo '1: jalr $25' >> conftest.s
echo ' .reloc 1f,R_MIPS_JALR,x' >> conftest.s
@@ -4737,6 +4734,21 @@ if test x"$gcc_cv_ld_as_needed" = xyes; then
[Define to the linker option to keep unused dependencies.])
fi
+AC_MSG_CHECKING(linker mapfile support for clearing hardware capabilities)
+saved_LDFLAGS="$LDFLAGS"
+for clearcap_map in sol2-clearcapv2.map sol2-clearcap.map; do
+ LDFLAGS="$saved_LDFLAGS -Wl,-M,${srcdir}/config/$clearcap_map"
+ AC_LINK_IFELSE([int main(void) {return 0;}],
+ [gcc_cv_ld_clearcap=yes; break], [gcc_cv_ld_clearcap=no])
+done
+LDFLAGS="$saved_LDFLAGS"
+if test "x$gcc_cv_ld_clearcap" = xyes; then
+ AC_DEFINE([HAVE_LD_CLEARCAP], 1,
+[Define if the linker supports clearing hardware capabilities via mapfile.])
+ AC_CONFIG_LINKS([clearcap.map:${srcdir}/config/$clearcap_map])
+fi
+AC_MSG_RESULT($gcc_cv_ld_clearcap)
+
case "$target:$tm_file" in
powerpc64-*-freebsd* | powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*)
case "$target" in
@@ -5024,6 +5036,13 @@ case "$target" in
gcc_cv_target_dl_iterate_phdr=no
fi
;;
+ *-*-dragonfly* | *-*-freebsd*)
+ if grep dl_iterate_phdr $target_header_dir/sys/link_elf.h > /dev/null 2>&1; then
+ gcc_cv_target_dl_iterate_phdr=yes
+ else
+ gcc_cv_target_dl_iterate_phdr=no
+ fi
+ ;;
esac
GCC_TARGET_TEMPLATE([TARGET_DL_ITERATE_PHDR])
if test x$gcc_cv_target_dl_iterate_phdr = xyes; then
diff --git a/gcc/convert.c b/gcc/convert.c
index 91c1da265a8..2d9600dd853 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -32,6 +32,8 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "target.h"
#include "langhooks.h"
+#include "builtins.h"
+#include "ubsan.h"
/* Convert EXPR to some pointer or reference type TYPE.
EXPR must be pointer, reference, integer, enumeral, or literal zero;
@@ -394,6 +396,7 @@ convert_to_integer (tree type, tree expr)
tree intype = TREE_TYPE (expr);
unsigned int inprec = element_precision (intype);
unsigned int outprec = element_precision (type);
+ location_t loc = EXPR_LOCATION (expr);
/* An INTEGER_TYPE cannot be incomplete, but an ENUMERAL_TYPE can
be. Consider `enum E = { a, b = (enum E) 3 };'. */
@@ -844,7 +847,17 @@ convert_to_integer (tree type, tree expr)
return build1 (CONVERT_EXPR, type, expr);
case REAL_TYPE:
- return build1 (FIX_TRUNC_EXPR, type, expr);
+ if (flag_sanitize & SANITIZE_FLOAT_CAST)
+ {
+ expr = save_expr (expr);
+ tree check = ubsan_instrument_float_cast (loc, type, expr);
+ expr = build1 (FIX_TRUNC_EXPR, type, expr);
+ if (check == NULL)
+ return expr;
+ return fold_build2 (COMPOUND_EXPR, TREE_TYPE (expr), check, expr);
+ }
+ else
+ return build1 (FIX_TRUNC_EXPR, type, expr);
case FIXED_POINT_TYPE:
return build1 (FIXED_CONVERT_EXPR, type, expr);
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 41ad1a3b22d..bbb515092bb 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -43,8 +43,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#ifndef USED_FOR_TARGET
-typedef HOST_WIDEST_INT gcov_type;
-typedef unsigned HOST_WIDEST_INT gcov_type_unsigned;
+typedef int64_t gcov_type;
+typedef uint64_t gcov_type_unsigned;
struct bitmap_head;
typedef struct bitmap_head *bitmap;
diff --git a/gcc/coverage.c b/gcc/coverage.c
index ff1e67d0a03..5e9005eb1b8 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -667,7 +667,7 @@ coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
list. */
if (!DECL_EXTERNAL (current_function_decl))
{
- item = ggc_alloc_coverage_data ();
+ item = ggc_alloc<coverage_data> ();
item->ident = current_function_funcdef_no + 1;
item->lineno_checksum = lineno_checksum;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 938fbf59f3f..9b439a964b5 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,359 @@
+2014-06-02 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ PR c++/59483
+ PR c++/61148
+ * search.c (accessible_p): Use current_nonlambda_class_type.
+ * semantics.c (check_accessibility_of_qualified_id): Likewise.
+
+2014-06-02 Andrew MacLeod <amacleod@redhat.com>
+
+ * decl.c: Include builtins.h.
+ * semantics.c: Likewise.
+
+2014-05-31 Paolo Carlini <paolo.carlini@oracle.com>
+
+ DR 1227
+ PR c++/57543
+ * cp-tree.h (TYPE_HAS_LATE_RETURN_TYPE): Add.
+ * pt.c (tsubst_function_type): Inject the this parameter; do the
+ substitutions in the order mandated by the DR.
+ (copy_default_args_to_explicit_spec): Copy TYPE_HAS_LATE_RETURN_TYPE.
+ * decl.c (grokdeclarator): Maybe set TYPE_HAS_LATE_RETURN_TYPE.
+ (static_fn_type): Copy it.
+ * decl2.c (build_memfn_type, change_return_type,
+ cp_reconstruct_complex_type): Likewise.
+ * parser.c (cp_parser_lambda_declarator_opt): Likewise.
+ * tree.c (strip_typedefs): Likewise.
+ * typeck.c (merge_types): Likewise.
+
+2014-05-30 Jason Merrill <jason@redhat.com>
+
+ PR c++/56947
+ * pt.c (instantiate_decl): Check that defer_ok is not set for
+ local class members.
+
+ PR c++/60992
+ * pt.c (tsubst_init): Split out from...
+ (tsubst_expr) [DECL_EXPR]: Here.
+ (tsubst_copy) [VAR_DECL]: Use it.
+ * semantics.c (finish_id_expression): Return the decl for static/const.
+
+2014-05-28 Jason Merrill <jason@redhat.com>
+
+ PR c++/47202
+ * decl.c (cxx_comdat_group): Return a decl.
+ * optimize.c (cdtor_comdat_group): Get its DECL_ASSEMBLER_NAME.
+
+ * pt.c (tsubst) [ARRAY_TYPE]: Check for array of array of unknown
+ bound.
+
+ PR c++/61242
+ * call.c (build_aggr_conv): Ignore passed in flags.
+ (build_array_conv, build_complex_conv): Likewise.
+
+2014-05-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * optimize.c (maybe_thunk_body): Use set_comdat_group.
+ (maybe_clone_body): Likewise.
+ * decl.c (duplicate_decls): Update code duplicating comdat group;
+ do not copy symtab pointer; before freeing newdecl remove it
+ from symtab.
+ * decl2.c (constrain_visibility): Use set_comdat_group.
+
+2014-05-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * rtti.c: Include tm_p.h
+ (emit_tinfo_decl): Force RTTI data to be aligned to required
+ ABI alignment only.
+
+2014-05-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * class.c (build_vtable): Align vtables to TARGET_VTABLE_ENTRY_ALIGN
+ ignoring other target adjustments.
+
+2014-05-23 Thomas Schwinge <thomas@codesourcery.com>
+
+ * semantics.c (finish_omp_clauses): Remove duplicated variable
+ initialization.
+
+ * parser.c (cp_parser_omp_target): Return bool values.
+
+2014-05-22 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/61088
+ * lambda.c (add_capture): Enforce that capture by value requires
+ complete type.
+ * typeck2.c (cxx_incomplete_type_inform): Early return if
+ TYPE_MAIN_DECL is null.
+
+2014-05-21 Jonathan Wakely <jwakely@redhat.com>
+
+ PR c/61271
+ * cp-array-notation.c (cilkplus_an_triplet_types_ok_p): Fix condition.
+
+2014-05-21 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ PR c++/61133
+ * lambda.c (build_capture_proxy, add_capture): Treat normal
+ captures and init-captures identically.
+
+2014-05-21 Mark Wielaard <mjw@redhat.com>
+
+ PR debug/16063
+ * cp-lang.c (cxx_enum_underlying_base_type): New function.
+ (LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE): Define.
+
+2014-05-21 Richard Sandiford <rsandifo@linux.vnet.ibm.com>
+
+ * cvt.c (convert_to_void): Use void_node instead of void_zero_node.
+ * cp-array-notation.c (replace_invariant_exprs): Likewise.
+ (expand_array_notation): Handle VOID_CST.
+ * error.c (dump_expr): Likewise.
+ * cxx-pretty-print.c (cxx_pretty_printer::primary_expression)
+ (cxx_pretty_printer::expression): Likewise.
+ (pp_cxx_new_expression): Use void_node instead of void_zero_node.
+ * decl.c (register_dtor_fn): Likewise.
+ * init.c (build_raw_new_expr, build_new_1, build_vec_init)
+ (build_delete, push_base_cleanups): Likewise.
+ * mangle.c (write_expression): Likewise.
+ * semantics.c (finish_break_stmt, empty_expr_stmt_p): Likewise.
+ * pt.c (tsubst_decl, tsubst_copy_and_build): Likewise.
+ (tsubst, tsubst_copy, build_non_dependent_expr): Handle VOID_CST.
+ * tree.c (cp_tree_equal): Likewise.
+ (build_dummy_object, is_dummy_object, stabilize_expr): Use void_node
+ instead of void_zero_node.
+ * typeck.c (check_return_expr): Likewise.
+ * typeck2.c (build_functional_cast): Likewise.
+
+2014-05-21 Igor Zamyatin <igor.zamyatin@intel.com>
+
+ PR c/60189
+ * parser.c (cp_parser_postfix_expression): Move handling of cilk_sync
+ from here to...
+ (cp_parser_statement): ...here. Make sure only semicolon can go after
+ Cilk_sync.
+
+2014-05-20 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58753
+ PR c++/58930
+ PR c++/58704
+ * typeck2.c (digest_nsdmi_init): New.
+ * parser.c (cp_parser_late_parse_one_default_arg): Use it.
+ * init.c (get_nsdmi): Likewise.
+ * cp-tree.h (digest_nsdmi_init): Declare.
+
+2014-05-20 Jason Merrill <jason@redhat.com>
+
+ * typeck.c (get_member_function_from_ptrfunc): Don't try to look
+ up a virtual function in a dummy object.
+
+2014-05-20 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/60373
+ * decl.c (duplicate_decls): Replace pair of warning_at with
+ warning_at + inform.
+ (maybe_commonize_var): Likewise.
+
+2014-05-20 Richard Sandiford <rsandifo@linux.vnet.ibm.com>
+
+ PR bootstrap/61210
+ * pt.c (tsubst_copy, tsubst_omp_for_iterator, tsubst_expr)
+ (tsubst_copy_and_build): Perform recursive substitutions in a
+ deterministic order.
+
+2014-05-20 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58664
+ * typeck2.c (cxx_incomplete_type_inform): New.
+ (cxx_incomplete_type_diagnostic): Use it.
+ * decl.c (grokdeclarator): Check the element type of an
+ incomplete array type; call the above.
+ * cp-tree.h (cxx_incomplete_type_inform): Declare.
+
+2014-05-19 Jason Merrill <jason@redhat.com>
+
+ PR c++/58761
+ * pt.c (tsubst_copy): Don't check at_function_scope_p.
+ (instantiate_class_template_1): Don't push_to_top_level in an nsdmi.
+
+2014-05-19 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * typeck2.c (cxx_incomplete_type_diagnostic): Use inform.
+ * parser.c (cp_parser_enum_specifier): Likewise.
+
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * class.c (sorted_fields_type_new): Adjust.
+ * cp-cilkplus.c (cilk_install_body_with_frame_cleanup): Likewise.
+ * cp-objcp-common.c (decl_shadowed_for_var_insert): Likewise.
+ * cp-tree.h: Remove usage of variable_size gty attribute.
+ * decl.c (make_label_decl): Adjust.
+ (check_goto): Likewise.
+ (start_preparsed_function): Likewise.
+ (save_function_data): Likewise.
+ * lex.c (init_reswords): Likewise.
+ (retrofit_lang_decl): Likewise.
+ (cxx_dup_lang_specific_decl): Likewise.
+ (copy_lang_type): Likewise.
+ (cxx_make_type): Likewise.
+ * name-lookup.c (binding_entry_make): Likewise.
+ (binding_table_construct): Likewise.
+ (binding_table_new): Likewise.
+ (cxx_binding_make): Likewise.
+ (pushdecl_maybe_friend_1): Likewise.
+ (begin_scope): Likewise.
+ (push_to_top_level): Likewise.
+ * parser.c (cp_lexer_alloc): Likewise.
+ (cp_lexer_new_from_tokens): Likewise.
+ (cp_token_cache_new): Likewise.
+ (cp_parser_context_new): Likewise.
+ (cp_parser_new): Likewise.
+ (cp_parser_nested_name_specifier_opt): Likewise.
+ (cp_parser_template_id): Likewise.
+ * pt.c (maybe_process_partial_specialization): Likewise.
+ (register_specialization): Likewise.
+ (add_pending_template): Likewise.
+ (lookup_template_class_1): Likewise.
+ (push_tinst_level): Likewise.
+ * semantics.c (register_constexpr_fundef): Likewise.
+ (cxx_eval_call_expression): Likewise.
+ * typeck2.c (abstract_virtuals_error_sfinae): Likewise.
+
+2014-05-16 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51640
+ * parser.c (cp_parser_diagnose_invalid_type_name): Early return
+ when cp_parser_lookup_name sets ambiguous_decls.
+
+2014-05-15 Jason Merrill <jason@redhat.com>
+
+ * call.c (print_conversion_rejection): Use loc consistently.
+
+2014-05-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * cp-tree.h (DIRECT_LIST_INIT_P): Add.
+ * call.c (convert_like_real, build_new_method_call_1): Use it.
+ * decl2.c (grokfield): Likewise.
+ * init.c (perform_member_init, build_aggr_init, expand_default_init,
+ build_new_1): Likewise.
+ * mangle.c (write_expression): Likewise.
+ * parser.c (cp_parser_late_parse_one_default_arg): Likewise.
+
+2014-05-14 Jason Merrill <jason@redhat.com>
+
+ PR c++/20332
+ PR c++/21631
+ * call.c (reference_binding): Treat lvalue/rvalue mismatch and
+ dropped cv-quals as a bad conversion.
+ (convert_like_real) [ck_ref_bind]: Explain them.
+ (compare_ics): Check badness before stripping reference
+ bindings. Handle comparing bad reference bindings.
+ * typeck.c (comp_cv_qualification): Add overload that just takes
+ integers.
+ * cp-tree.h: Declare it.
+
+ * call.c (struct conversion_info): Rename 'from_type' to 'from'.
+ (arg_conversion_rejection, bad_arg_conversion_rejection)
+ (explicit_conversion_rejection, template_conversion_rejection): Adjust.
+ (add_function_candidate): Pass actual argument, rather than type, to
+ bad_arg_conversion_rejection.
+ (print_conversion_rejection): Explain what's wrong with the conversion.
+ (print_z_candidates): Say "candidate:" before each candidate.
+ (splice_viable): Be strict if we see a viable or template candidate.
+ (build_user_type_conversion_1): Pass false to strict parameter.
+ (perform_overload_resolution, build_conditional_expr_1): Likewise.
+ (build_new_op_1, build_new_method_call_1): Likewise.
+ (build_op_call_1): Pass true to strict parameter.
+
+2014-05-13 Jason Merrill <jason@redhat.com>
+
+ * call.c (print_error_for_call_failure): Say "no match" rather
+ than "ambiguous" if there were no strict matches.
+ (build_new_method_call_1): Likewise.
+
+ PR c++/61151
+ * semantics.c (is_this_parameter): Allow capture proxies too.
+
+2014-05-12 Jason Merrill <jason@redhat.com>
+
+ * call.c (maybe_print_user_conv_context): New.
+ (convert_like_real): Use it. Print call context for bad
+ user-defined conversion.
+ (build_over_call): Print call context for bad 'this' conversion.
+
+ * call.c (convert_like_real): Use inform for identifying the
+ declaration point.
+
+2014-05-12 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * cvt.c (cp_convert_to_pointer): Don't call error_at if
+ complain & tf_error is false.
+
+ * decl.c (make_unbound_class_template): Prefer inform for
+ "declared here"-type message.
+
+2014-05-09 Momchil Velikov <momchil.velikov@gmail.com>
+
+ PR c++/60463
+ PR c++/60755
+ * lambda.c (lambda_expr_this_capture): Add new parameter
+ add_capture_p controlling whether the functions will try to
+ capture 'this' via the default capture.
+ (maybe_resolve_dummy): Likewise.
+ * cp-tree.h: Adjust prototypes.
+ * call.c, semantics.c: Change callers of these functions.
+ * call.c (build_new_method_call_1): Use the actual 'this' that
+ would be potentially captured for the overload resolution, instead
+ of the dummy object.
+
+2014-05-09 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * pt.c (convert_nontype_argument_function): Add tsubst_flags_t
+ parameter.
+ (convert_nontype_argument): Adjust calls.
+ (coerce_template_parameter_pack): Add missing complain & tf_error
+ check.
+
+2014-05-09 Jason Merrill <jason@redhat.com>
+
+ DR 587
+ PR c++/51317
+ * call.c (build_conditional_expr_1, conditional_conversion): Handle
+ non-class lvalues and xvalues that differ only in cv-qualifiers.
+
+ DR 5
+ PR c++/60019
+ * call.c (build_user_type_conversion_1): The copy-init temporary
+ is cv-unqualified.
+
+ PR c++/58714
+ * tree.c (stabilize_expr): A stabilized prvalue is an xvalue.
+
+ PR c++/54348
+ * call.c (build_conditional_expr_1): If overload resolution finds
+ no match, just say "different types".
+
+ PR c++/32019
+ * call.c (build_conditional_expr_1): Improve ambiguity diagnostic.
+
+ PR c++/22434
+ * call.c (build_conditional_expr_1): Don't try to pool cv-quals
+ if we didn't find a conversion.
+ Don't accept a bad conversion too early.
+
+2014-05-08 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/13981
+ * typeck.c (convert_for_assignment): Provide an inform for pointers
+ to incomplete class types.
+
+2014-05-07 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/61083
+ * pt.c (convert_nontype_argument): Protect all the error calls
+ with complain & tf_error.
+
2014-05-07 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/61080
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 857df57c60c..77aa8caf678 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -458,9 +458,9 @@ enum rejection_reason_code {
struct conversion_info {
/* The index of the argument, 0-based. */
int n_arg;
- /* The type of the actual argument. */
- tree from_type;
- /* The type of the formal argument. */
+ /* The actual argument or its type. */
+ tree from;
+ /* The type of the parameter. */
tree to_type;
};
@@ -644,7 +644,7 @@ arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to)
struct rejection_reason *r = alloc_rejection (rr_arg_conversion);
int adjust = first_arg != NULL_TREE;
r->u.conversion.n_arg = n_arg - adjust;
- r->u.conversion.from_type = from;
+ r->u.conversion.from = from;
r->u.conversion.to_type = to;
return r;
}
@@ -655,7 +655,7 @@ bad_arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to)
struct rejection_reason *r = alloc_rejection (rr_bad_arg_conversion);
int adjust = first_arg != NULL_TREE;
r->u.bad_conversion.n_arg = n_arg - adjust;
- r->u.bad_conversion.from_type = from;
+ r->u.bad_conversion.from = from;
r->u.bad_conversion.to_type = to;
return r;
}
@@ -665,7 +665,7 @@ explicit_conversion_rejection (tree from, tree to)
{
struct rejection_reason *r = alloc_rejection (rr_explicit_conversion);
r->u.conversion.n_arg = 0;
- r->u.conversion.from_type = from;
+ r->u.conversion.from = from;
r->u.conversion.to_type = to;
return r;
}
@@ -675,7 +675,7 @@ template_conversion_rejection (tree from, tree to)
{
struct rejection_reason *r = alloc_rejection (rr_template_conversion);
r->u.conversion.n_arg = 0;
- r->u.conversion.from_type = from;
+ r->u.conversion.from = from;
r->u.conversion.to_type = to;
return r;
}
@@ -890,7 +890,9 @@ build_aggr_conv (tree type, tree ctor, int flags, tsubst_flags_t complain)
if (ctor == error_mark_node)
return NULL;
- flags |= LOOKUP_NO_NARROWING;
+ /* The conversions within the init-list aren't affected by the enclosing
+ context; they're always simple copy-initialization. */
+ flags = LOOKUP_IMPLICIT|LOOKUP_NO_NARROWING;
for (; field; field = next_initializable_field (DECL_CHAIN (field)))
{
@@ -963,6 +965,8 @@ build_array_conv (tree type, tree ctor, int flags, tsubst_flags_t complain)
return NULL;
}
+ flags = LOOKUP_IMPLICIT|LOOKUP_NO_NARROWING;
+
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), i, val)
{
conversion *sub
@@ -1007,6 +1011,8 @@ build_complex_conv (tree type, tree ctor, int flags,
if (len != 2)
return NULL;
+ flags = LOOKUP_IMPLICIT|LOOKUP_NO_NARROWING;
+
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), i, val)
{
conversion *sub
@@ -1540,15 +1546,11 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
[8.5.3/5 dcl.init.ref] is changed to also require direct bindings for
const and rvalue references to rvalues of compatible class type.
We should also do direct bindings for non-class xvalues. */
- if (compatible_p
- && (is_lvalue
- || (((CP_TYPE_CONST_NON_VOLATILE_P (to)
- && !(flags & LOOKUP_NO_RVAL_BIND))
- || TYPE_REF_IS_RVALUE (rto))
- && (gl_kind
- || (!(flags & LOOKUP_NO_TEMP_BIND)
- && (CLASS_TYPE_P (from)
- || TREE_CODE (from) == ARRAY_TYPE))))))
+ if (related_p
+ && (gl_kind
+ || (!(flags & LOOKUP_NO_TEMP_BIND)
+ && (CLASS_TYPE_P (from)
+ || TREE_CODE (from) == ARRAY_TYPE))))
{
/* [dcl.init.ref]
@@ -1603,6 +1605,16 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
&& !(flags & LOOKUP_PREFER_RVALUE))
conv->bad_p = true;
+ /* Nor the reverse. */
+ if (!is_lvalue && !TYPE_REF_IS_RVALUE (rto)
+ && (!CP_TYPE_CONST_NON_VOLATILE_P (to)
+ || (flags & LOOKUP_NO_RVAL_BIND))
+ && TREE_CODE (to) != FUNCTION_TYPE)
+ conv->bad_p = true;
+
+ if (!compatible_p)
+ conv->bad_p = true;
+
return conv;
}
/* [class.conv.fct] A conversion function is never used to convert a
@@ -1647,24 +1659,6 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
difference in top-level cv-qualification is subsumed by the
initialization itself and does not constitute a conversion. */
- /* [dcl.init.ref]
-
- Otherwise, the reference shall be an lvalue reference to a
- non-volatile const type, or the reference shall be an rvalue
- reference. */
- if (!CP_TYPE_CONST_NON_VOLATILE_P (to) && !TYPE_REF_IS_RVALUE (rto))
- return NULL;
-
- /* [dcl.init.ref]
-
- Otherwise, a temporary of type "cv1 T1" is created and
- initialized from the initializer expression using the rules for a
- non-reference copy initialization. If T1 is reference-related to
- T2, cv1 must be the same cv-qualification as, or greater
- cv-qualification than, cv2; otherwise, the program is ill-formed. */
- if (related_p && !at_least_as_qualified_p (to, from))
- return NULL;
-
/* We're generating a temporary now, but don't bind any more in the
conversion (specifically, don't slice the temporary returned by a
conversion operator). */
@@ -1710,6 +1704,24 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
conv->need_temporary_p = true;
conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
+ /* [dcl.init.ref]
+
+ Otherwise, the reference shall be an lvalue reference to a
+ non-volatile const type, or the reference shall be an rvalue
+ reference. */
+ if (!CP_TYPE_CONST_NON_VOLATILE_P (to) && !TYPE_REF_IS_RVALUE (rto))
+ conv->bad_p = true;
+
+ /* [dcl.init.ref]
+
+ Otherwise, a temporary of type "cv1 T1" is created and
+ initialized from the initializer expression using the rules for a
+ non-reference copy initialization. If T1 is reference-related to
+ T2, cv1 must be the same cv-qualification as, or greater
+ cv-qualification than, cv2; otherwise, the program is ill-formed. */
+ if (related_p && !at_least_as_qualified_p (to, from))
+ conv->bad_p = true;
+
return conv;
}
@@ -2072,7 +2084,7 @@ add_function_candidate (struct z_candidate **candidates,
if (t->bad_p)
{
viable = -1;
- reason = bad_arg_conversion_rejection (first_arg, i, argtype, to_type);
+ reason = bad_arg_conversion_rejection (first_arg, i, arg, to_type);
}
}
@@ -2161,7 +2173,7 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
if (t->bad_p)
{
viable = -1;
- reason = bad_arg_conversion_rejection (NULL_TREE, i, argtype, convert_type);
+ reason = bad_arg_conversion_rejection (NULL_TREE, i, arg, convert_type);
}
if (i == 0)
@@ -2227,7 +2239,7 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
else if (t->bad_p)
{
viable = 0;
- reason = bad_arg_conversion_rejection (NULL_TREE, i, argtypes[i],
+ reason = bad_arg_conversion_rejection (NULL_TREE, i, args[i],
types[i]);
}
convs[i] = t;
@@ -3120,6 +3132,7 @@ splice_viable (struct z_candidate *cands,
struct z_candidate *viable;
struct z_candidate **last_viable;
struct z_candidate **cand;
+ bool found_strictly_viable = false;
/* Be strict inside templates, since build_over_call won't actually
do the conversions to get pedwarns. */
@@ -3134,6 +3147,25 @@ splice_viable (struct z_candidate *cands,
while (*cand)
{
struct z_candidate *c = *cand;
+ if (!strict_p
+ && (c->viable == 1 || TREE_CODE (c->fn) == TEMPLATE_DECL))
+ {
+ /* Be strict in the presence of a viable candidate. Also if
+ there are template candidates, so that we get deduction errors
+ for them instead of silently preferring a bad conversion. */
+ strict_p = true;
+ if (viable && !found_strictly_viable)
+ {
+ /* Put any spliced near matches back onto the main list so
+ that we see them if there is no strict match. */
+ *any_viable_p = false;
+ *last_viable = cands;
+ cands = viable;
+ viable = NULL;
+ last_viable = &viable;
+ }
+ }
+
if (strict_p ? c->viable == 1 : c->viable)
{
*last_viable = c;
@@ -3141,6 +3173,8 @@ splice_viable (struct z_candidate *cands,
c->next = NULL;
last_viable = &c->next;
*any_viable_p = true;
+ if (c->viable == 1)
+ found_strictly_viable = true;
}
else
cand = &c->next;
@@ -3195,18 +3229,37 @@ equal_functions (tree fn1, tree fn2)
static void
print_conversion_rejection (location_t loc, struct conversion_info *info)
{
+ tree from = info->from;
+ if (!TYPE_P (from))
+ from = lvalue_type (from);
if (info->n_arg == -1)
- /* Conversion of implicit `this' argument failed. */
- inform (loc, " no known conversion for implicit "
- "%<this%> parameter from %qT to %qT",
- info->from_type, info->to_type);
+ {
+ /* Conversion of implicit `this' argument failed. */
+ if (!TYPE_P (info->from))
+ /* A bad conversion for 'this' must be discarding cv-quals. */
+ inform (loc, " passing %qT as %<this%> "
+ "argument discards qualifiers",
+ from);
+ else
+ inform (loc, " no known conversion for implicit "
+ "%<this%> parameter from %qT to %qT",
+ from, info->to_type);
+ }
+ else if (!TYPE_P (info->from))
+ {
+ if (info->n_arg >= 0)
+ inform (loc, " conversion of argument %d would be ill-formed:",
+ info->n_arg + 1);
+ perform_implicit_conversion (info->to_type, info->from,
+ tf_warning_or_error);
+ }
else if (info->n_arg == -2)
/* Conversion of conversion function return value failed. */
inform (loc, " no known conversion from %qT to %qT",
- info->from_type, info->to_type);
+ from, info->to_type);
else
inform (loc, " no known conversion for argument %d from %qT to %qT",
- info->n_arg+1, info->from_type, info->to_type);
+ info->n_arg + 1, from, info->to_type);
}
/* Print information about a candidate with WANT parameters and we found
@@ -3281,13 +3334,13 @@ print_z_candidate (location_t loc, const char *msgstr,
case rr_explicit_conversion:
inform (cloc, " return type %qT of explicit conversion function "
"cannot be converted to %qT with a qualification "
- "conversion", r->u.conversion.from_type,
+ "conversion", r->u.conversion.from,
r->u.conversion.to_type);
break;
case rr_template_conversion:
inform (cloc, " conversion from return type %qT of template "
"conversion function specialization to %qT is not an "
- "exact match", r->u.conversion.from_type,
+ "exact match", r->u.conversion.from,
r->u.conversion.to_type);
break;
case rr_template_unification:
@@ -3377,9 +3430,8 @@ print_z_candidates (location_t loc, struct z_candidate *candidates)
for (n_candidates = 0, cand1 = candidates; cand1; cand1 = cand1->next)
n_candidates++;
- inform_n (loc, n_candidates, "candidate is:", "candidates are:");
for (; candidates; candidates = candidates->next)
- print_z_candidate (loc, NULL, candidates);
+ print_z_candidate (loc, "candidate:", candidates);
}
/* USER_SEQ is a user-defined conversion sequence, beginning with a
@@ -3663,7 +3715,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
}
}
- candidates = splice_viable (candidates, pedantic, &any_viable_p);
+ candidates = splice_viable (candidates, false, &any_viable_p);
if (!any_viable_p)
{
if (args)
@@ -3693,11 +3745,20 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
return cand;
}
+ tree convtype;
+ if (!DECL_CONSTRUCTOR_P (cand->fn))
+ convtype = non_reference (TREE_TYPE (TREE_TYPE (cand->fn)));
+ else if (cand->second_conv->kind == ck_rvalue)
+ /* DR 5: [in the first step of copy-initialization]...if the function
+ is a constructor, the call initializes a temporary of the
+ cv-unqualified version of the destination type. */
+ convtype = cv_unqualified (totype);
+ else
+ convtype = totype;
/* Build the user conversion sequence. */
conv = build_conv
(ck_user,
- (DECL_CONSTRUCTOR_P (cand->fn)
- ? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))),
+ convtype,
build_identity_conv (TREE_TYPE (expr), expr));
conv->cand = cand;
if (cand->viable == -1)
@@ -3889,7 +3950,7 @@ perform_overload_resolution (tree fn,
LOOKUP_NORMAL,
candidates, complain);
- *candidates = splice_viable (*candidates, pedantic, any_viable_p);
+ *candidates = splice_viable (*candidates, false, any_viable_p);
if (*any_viable_p)
cand = tourney (*candidates, complain);
else
@@ -3905,13 +3966,13 @@ perform_overload_resolution (tree fn,
functions. */
static void
-print_error_for_call_failure (tree fn, vec<tree, va_gc> *args, bool any_viable_p,
+print_error_for_call_failure (tree fn, vec<tree, va_gc> *args,
struct z_candidate *candidates)
{
tree name = DECL_NAME (OVL_CURRENT (fn));
location_t loc = location_of (name);
- if (!any_viable_p)
+ if (!any_strictly_viable (candidates))
error_at (loc, "no matching function for call to %<%D(%A)%>",
name, build_tree_list_vec (args));
else
@@ -3955,7 +4016,7 @@ build_new_function_call (tree fn, vec<tree, va_gc> **args, bool koenig_p,
if (!fn)
{
if (complain & tf_error)
- print_error_for_call_failure (orig_fn, *args, false, NULL);
+ print_error_for_call_failure (orig_fn, *args, NULL);
return error_mark_node;
}
}
@@ -3975,7 +4036,7 @@ build_new_function_call (tree fn, vec<tree, va_gc> **args, bool koenig_p,
return cp_build_function_call_vec (candidates->fn, args, complain);
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
fn = TREE_OPERAND (fn, 0);
- print_error_for_call_failure (fn, *args, any_viable_p, candidates);
+ print_error_for_call_failure (fn, *args, candidates);
}
result = error_mark_node;
}
@@ -4057,7 +4118,7 @@ build_operator_new_call (tree fnname, vec<tree, va_gc> **args,
if (!cand)
{
if (complain & tf_error)
- print_error_for_call_failure (fns, *args, any_viable_p, candidates);
+ print_error_for_call_failure (fns, *args, candidates);
return error_mark_node;
}
@@ -4200,7 +4261,9 @@ build_op_call_1 (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain)
}
}
- candidates = splice_viable (candidates, pedantic, &any_viable_p);
+ /* Be strict here because if we choose a bad conversion candidate, the
+ errors we get won't mention the call context. */
+ candidates = splice_viable (candidates, true, &any_viable_p);
if (!any_viable_p)
{
if (complain & tf_error)
@@ -4373,20 +4436,31 @@ conditional_conversion (tree e1, tree e2, tsubst_flags_t complain)
If E2 is an lvalue: E1 can be converted to match E2 if E1 can be
implicitly converted (clause _conv_) to the type "lvalue reference to
T2", subject to the constraint that in the conversion the
- reference must bind directly (_dcl.init.ref_) to an lvalue. */
- if (real_lvalue_p (e2))
+ reference must bind directly (_dcl.init.ref_) to an lvalue.
+
+ If E2 is an xvalue: E1 can be converted to match E2 if E1 can be
+ implicitly converted to the type "rvalue reference to T2", subject to
+ the constraint that the reference must bind directly. */
+ if (lvalue_or_rvalue_with_address_p (e2))
{
- conv = implicit_conversion (build_reference_type (t2),
+ tree rtype = cp_build_reference_type (t2, !real_lvalue_p (e2));
+ conv = implicit_conversion (rtype,
t1,
e1,
/*c_cast_p=*/false,
LOOKUP_NO_TEMP_BIND|LOOKUP_NO_RVAL_BIND
|LOOKUP_ONLYCONVERTING,
complain);
- if (conv)
+ if (conv && !conv->bad_p)
return conv;
}
+ /* If E2 is a prvalue or if neither of the conversions above can be done
+ and at least one of the operands has (possibly cv-qualified) class
+ type: */
+ if (!CLASS_TYPE_P (t1) && !CLASS_TYPE_P (t2))
+ return NULL;
+
/* [expr.cond]
If E1 and E2 have class type, and the underlying class types are
@@ -4681,10 +4755,17 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
/* [expr.cond]
Otherwise, if the second and third operand have different types,
- and either has (possibly cv-qualified) class type, an attempt is
- made to convert each of those operands to the type of the other. */
+ and either has (possibly cv-qualified) class type, or if both are
+ glvalues of the same value category and the same type except for
+ cv-qualification, an attempt is made to convert each of those operands
+ to the type of the other. */
else if (!same_type_p (arg2_type, arg3_type)
- && (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type)))
+ && (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type)
+ || (same_type_ignoring_top_level_qualifiers_p (arg2_type,
+ arg3_type)
+ && lvalue_or_rvalue_with_address_p (arg2)
+ && lvalue_or_rvalue_with_address_p (arg3)
+ && real_lvalue_p (arg2) == real_lvalue_p (arg3))))
{
conversion *conv2;
conversion *conv3;
@@ -4710,11 +4791,19 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
|| (conv3 && conv3->kind == ck_ambig))
{
if (complain & tf_error)
- error_at (loc, "operands to ?: have different types %qT and %qT",
- arg2_type, arg3_type);
+ {
+ error_at (loc, "operands to ?: have different types %qT and %qT",
+ arg2_type, arg3_type);
+ if (conv2 && !conv2->bad_p && conv3 && !conv3->bad_p)
+ inform (loc, " and each type can be converted to the other");
+ else if (conv2 && conv2->kind == ck_ambig)
+ convert_like (conv2, arg2, complain);
+ else
+ convert_like (conv3, arg3, complain);
+ }
result = error_mark_node;
}
- else if (conv2 && (!conv2->bad_p || !conv3))
+ else if (conv2 && !conv2->bad_p)
{
arg2 = convert_like (conv2, arg2, complain);
arg2 = convert_from_reference (arg2);
@@ -4727,7 +4816,7 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
if (error_operand_p (arg2))
result = error_mark_node;
}
- else if (conv3 && (!conv3->bad_p || !conv2))
+ else if (conv3 && !conv3->bad_p)
{
arg3 = convert_like (conv3, arg3, complain);
arg3 = convert_from_reference (arg3);
@@ -4757,7 +4846,8 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
conditional expression failing altogether, even though,
according to this step, the one operand could be converted to
the type of the other. */
- if ((conv2 || conv3)
+ if (((conv2 && !conv2->bad_p)
+ || (conv3 && !conv3->bad_p))
&& CLASS_TYPE_P (arg2_type)
&& cp_type_quals (arg2_type) != cp_type_quals (arg3_type))
arg2_type = arg3_type =
@@ -4813,14 +4903,12 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
If the overload resolution fails, the program is
ill-formed. */
- candidates = splice_viable (candidates, pedantic, &any_viable_p);
+ candidates = splice_viable (candidates, false, &any_viable_p);
if (!any_viable_p)
{
if (complain & tf_error)
- {
- op_error (loc, COND_EXPR, NOP_EXPR, arg1, arg2, arg3, FALSE);
- print_z_candidates (loc, candidates);
- }
+ error_at (loc, "operands to ?: have different types %qT and %qT",
+ arg2_type, arg3_type);
return error_mark_node;
}
cand = tourney (candidates, complain);
@@ -5339,7 +5427,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
break;
default:
- strict_p = pedantic;
+ strict_p = false;
break;
}
@@ -5908,6 +5996,23 @@ conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
}
}
+/* We gave a diagnostic during a conversion. If this was in the second
+ standard conversion sequence of a user-defined conversion sequence, say
+ which user-defined conversion. */
+
+static void
+maybe_print_user_conv_context (conversion *convs)
+{
+ if (convs->user_conv_p)
+ for (conversion *t = convs; t; t = next_conversion (t))
+ if (t->kind == ck_user)
+ {
+ print_z_candidate (0, " after user-defined conversion:",
+ t->cand);
+ break;
+ }
+}
+
/* Perform the conversions in CONVS on the expression EXPR. FN and
ARGNUM are used for diagnostics. ARGNUM is zero based, -1
indicates the `this' argument of a method. INNER is nonzero when
@@ -5969,11 +6074,15 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
/*c_cast_p=*/false,
complain);
if (convs->kind == ck_ref_bind)
- return convert_to_reference (totype, expr, CONV_IMPLICIT,
+ expr = convert_to_reference (totype, expr, CONV_IMPLICIT,
LOOKUP_NORMAL, NULL_TREE,
complain);
else
- return cp_convert (totype, expr, complain);
+ expr = cp_convert (totype, expr, complain);
+ if (fn)
+ inform (DECL_SOURCE_LOCATION (fn),
+ " initializing argument %P of %qD", argnum, fn);
+ return expr;
}
else if (t->kind == ck_user || !t->bad_p)
{
@@ -5996,7 +6105,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
TREE_TYPE (expr), totype);
if (complained && fn)
inform (DECL_SOURCE_LOCATION (fn),
- "initializing argument %P of %qD", argnum, fn);
+ " initializing argument %P of %qD", argnum, fn);
return cp_convert (totype, expr, complain);
}
@@ -6016,8 +6125,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
constructors, but actually trying to call one is an error. */
if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn)
/* Unless this is for direct-list-initialization. */
- && !(BRACE_ENCLOSED_INITIALIZER_P (expr)
- && CONSTRUCTOR_IS_DIRECT_INIT (expr)))
+ && !DIRECT_LIST_INIT_P (expr))
{
if (!(complain & tf_error))
return error_mark_node;
@@ -6101,7 +6209,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
build_user_type_conversion (totype, convs->u.expr, LOOKUP_NORMAL,
complain);
if (fn)
- inform (input_location, "initializing argument %P of %q+D",
+ inform (input_location, " initializing argument %P of %q+D",
argnum, fn);
}
return error_mark_node;
@@ -6221,9 +6329,14 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
/* Copy-list-initialization doesn't actually involve a copy. */
return expr;
expr = build_temp (expr, totype, flags, &diag_kind, complain);
- if (diag_kind && fn && complain)
- emit_diagnostic (diag_kind, DECL_SOURCE_LOCATION (fn), 0,
- " initializing argument %P of %qD", argnum, fn);
+ if (diag_kind && complain)
+ {
+ maybe_print_user_conv_context (convs);
+ if (fn)
+ inform (DECL_SOURCE_LOCATION (fn),
+ " initializing argument %P of %qD", argnum, fn);
+ }
+
return build_cplus_new (totype, expr, complain);
case ck_ref_bind:
@@ -6232,15 +6345,24 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (convs->bad_p && !next_conversion (convs)->bad_p)
{
- gcc_assert (TYPE_REF_IS_RVALUE (ref_type)
- && (real_lvalue_p (expr)
- || next_conversion(convs)->kind == ck_rvalue));
-
- error_at (loc, "cannot bind %qT lvalue to %qT",
- TREE_TYPE (expr), totype);
+ tree extype = TREE_TYPE (expr);
+ if (TYPE_REF_IS_RVALUE (ref_type)
+ && real_lvalue_p (expr))
+ error_at (loc, "cannot bind %qT lvalue to %qT",
+ extype, totype);
+ else if (!TYPE_REF_IS_RVALUE (ref_type) && !real_lvalue_p (expr)
+ && !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type)))
+ error_at (loc, "invalid initialization of non-const reference of "
+ "type %qT from an rvalue of type %qT", totype, extype);
+ else if (!reference_compatible_p (TREE_TYPE (totype), extype))
+ error_at (loc, "binding %qT to reference of type %qT "
+ "discards qualifiers", extype, totype);
+ else
+ gcc_unreachable ();
+ maybe_print_user_conv_context (convs);
if (fn)
inform (input_location,
- "initializing argument %P of %q+D", argnum, fn);
+ " initializing argument %P of %q+D", argnum, fn);
return error_mark_node;
}
@@ -6901,8 +7023,12 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
if (convs[i]->bad_p)
{
if (complain & tf_error)
- permerror (input_location, "passing %qT as %<this%> argument of %q#D discards qualifiers",
- TREE_TYPE (argtype), fn);
+ {
+ if (permerror (input_location, "passing %qT as %<this%> "
+ "argument discards qualifiers",
+ TREE_TYPE (argtype)))
+ inform (DECL_SOURCE_LOCATION (fn), " in call to %qD", fn);
+ }
else
return error_mark_node;
}
@@ -7726,7 +7852,11 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
if (DECL_DESTRUCTOR_P (fn))
name = complete_dtor_identifier;
- first_mem_arg = instance;
+ /* For the overload resolution we need to find the actual `this`
+ that would be captured if the call turns out to be to a
+ non-static member function. Do not actually capture it at this
+ point. */
+ first_mem_arg = maybe_resolve_dummy (instance, false);
/* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0);
@@ -7734,8 +7864,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
/* If CONSTRUCTOR_IS_DIRECT_INIT is set, this was a T{ } form
initializer, not T({ }). */
if (DECL_CONSTRUCTOR_P (fn) && args != NULL && !vec_safe_is_empty (*args)
- && BRACE_ENCLOSED_INITIALIZER_P ((**args)[0])
- && CONSTRUCTOR_IS_DIRECT_INIT ((**args)[0]))
+ && DIRECT_LIST_INIT_P ((**args)[0]))
{
tree init_list = (**args)[0];
tree init = NULL_TREE;
@@ -7782,7 +7911,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
access_binfo, flags, &candidates, complain);
}
any_viable_p = false;
- candidates = splice_viable (candidates, pedantic, &any_viable_p);
+ candidates = splice_viable (candidates, false, &any_viable_p);
if (!any_viable_p)
{
@@ -7829,8 +7958,12 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
arglist = build_tree_list_vec (user_args);
if (skip_first_for_error)
arglist = TREE_CHAIN (arglist);
- error ("call of overloaded %<%s(%A)%> is ambiguous", pretty_name,
- arglist);
+ if (!any_strictly_viable (candidates))
+ error ("no matching function for call to %<%s(%A)%>",
+ pretty_name, arglist);
+ else
+ error ("call of overloaded %<%s(%A)%> is ambiguous",
+ pretty_name, arglist);
print_z_candidates (location_of (name), candidates);
if (free_p)
free (pretty_name);
@@ -7864,7 +7997,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
&& !DECL_CONSTRUCTOR_P (fn)
&& is_dummy_object (instance))
{
- instance = maybe_resolve_dummy (instance);
+ instance = maybe_resolve_dummy (instance, true);
if (instance == error_mark_node)
call = error_mark_node;
else if (!is_dummy_object (instance))
@@ -8115,6 +8248,12 @@ compare_ics (conversion *ics1, conversion *ics2)
conversion *ref_conv1;
conversion *ref_conv2;
+ /* Compare badness before stripping the reference conversion. */
+ if (ics1->bad_p > ics2->bad_p)
+ return -1;
+ else if (ics1->bad_p < ics2->bad_p)
+ return 1;
+
/* Handle implicit object parameters. */
maybe_handle_implicit_object (&ics1);
maybe_handle_implicit_object (&ics2);
@@ -8143,31 +8282,19 @@ compare_ics (conversion *ics1, conversion *ics2)
--a user-defined conversion sequence (_over.ics.user_) is a
better conversion sequence than an ellipsis conversion sequence
(_over.ics.ellipsis_). */
- rank1 = CONVERSION_RANK (ics1);
- rank2 = CONVERSION_RANK (ics2);
+ /* Use BAD_CONVERSION_RANK because we already checked for a badness
+ mismatch. If both ICS are bad, we try to make a decision based on
+ what would have happened if they'd been good. This is not an
+ extension, we'll still give an error when we build up the call; this
+ just helps us give a more helpful error message. */
+ rank1 = BAD_CONVERSION_RANK (ics1);
+ rank2 = BAD_CONVERSION_RANK (ics2);
if (rank1 > rank2)
return -1;
else if (rank1 < rank2)
return 1;
- if (rank1 == cr_bad)
- {
- /* Both ICS are bad. We try to make a decision based on what would
- have happened if they'd been good. This is not an extension,
- we'll still give an error when we build up the call; this just
- helps us give a more helpful error message. */
- rank1 = BAD_CONVERSION_RANK (ics1);
- rank2 = BAD_CONVERSION_RANK (ics2);
-
- if (rank1 > rank2)
- return -1;
- else if (rank1 < rank2)
- return 1;
-
- /* We couldn't make up our minds; try to figure it out below. */
- }
-
if (ics1->ellipsis_p)
/* Both conversions are ellipsis conversions. */
return 0;
@@ -8487,13 +8614,30 @@ compare_ics (conversion *ics1, conversion *ics2)
|| (TYPE_REF_IS_RVALUE (ref_conv1->type)
!= TYPE_REF_IS_RVALUE (ref_conv2->type))))
{
+ if (ref_conv1->bad_p
+ && !same_type_p (TREE_TYPE (ref_conv1->type),
+ TREE_TYPE (ref_conv2->type)))
+ /* Don't prefer a bad conversion that drops cv-quals to a bad
+ conversion with the wrong rvalueness. */
+ return 0;
return (ref_conv1->rvaluedness_matches_p
- ref_conv2->rvaluedness_matches_p);
}
if (same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2))
- return comp_cv_qualification (TREE_TYPE (ref_conv2->type),
- TREE_TYPE (ref_conv1->type));
+ {
+ int q1 = cp_type_quals (TREE_TYPE (ref_conv1->type));
+ int q2 = cp_type_quals (TREE_TYPE (ref_conv2->type));
+ if (ref_conv1->bad_p)
+ {
+ /* Prefer the one that drops fewer cv-quals. */
+ tree ftype = next_conversion (ref_conv1)->type;
+ int fquals = cp_type_quals (ftype);
+ q1 ^= fquals;
+ q2 ^= fquals;
+ }
+ return comp_cv_qualification (q2, q1);
+ }
}
/* Neither conversion sequence is better than the other. */
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index c96d79dbc82..14780e787da 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -768,11 +768,8 @@ build_vtable (tree class_type, tree name, tree vtable_type)
TREE_READONLY (decl) = 1;
DECL_VIRTUAL_P (decl) = 1;
DECL_ALIGN (decl) = TARGET_VTABLE_ENTRY_ALIGN;
+ DECL_USER_ALIGN (decl) = true;
DECL_VTABLE_OR_VTT_P (decl) = 1;
- /* At one time the vtable info was grabbed 2 words at a time. This
- fails on sparc unless you have 8-byte alignment. (tiemann) */
- DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
- DECL_ALIGN (decl));
set_linkage_according_to_type (class_type, decl);
/* The vtable has not been defined -- yet. */
DECL_EXTERNAL (decl) = 1;
@@ -6487,7 +6484,7 @@ static struct sorted_fields_type *
sorted_fields_type_new (int n)
{
struct sorted_fields_type *sft;
- sft = ggc_alloc_sorted_fields_type (sizeof (struct sorted_fields_type)
+ sft = (sorted_fields_type *) ggc_internal_alloc (sizeof (sorted_fields_type)
+ n * sizeof (tree));
sft->len = n;
diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c
index 65b8bcb8169..ff82deee7be 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -26,7 +26,7 @@
An array notation expression has 4 major components:
1. The array name
2. Start Index
- 3. Number of elements we need to acess (we call it length)
+ 3. Number of elements we need to access (we call it length)
4. Stride
So, if we have something like A[0:5:2], we are accessing A[0], A[2], A[4],
@@ -181,7 +181,7 @@ replace_invariant_exprs (tree *node)
if (VOID_TYPE_P (TREE_TYPE (t)))
{
finish_expr_stmt (t);
- new_var = void_zero_node;
+ new_var = void_node;
}
else
new_var = get_temp_regvar (TREE_TYPE (t), t);
@@ -1126,6 +1126,7 @@ expand_array_notation_exprs (tree t)
{
case ERROR_MARK:
case IDENTIFIER_NODE:
+ case VOID_CST:
case INTEGER_CST:
case REAL_CST:
case FIXED_CST:
@@ -1417,7 +1418,7 @@ cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length,
error_at (loc, "stride of array notation triplet is not an integer");
return false;
}
- if (!TREE_CODE (type) == FUNCTION_TYPE)
+ if (TREE_CODE (type) == FUNCTION_TYPE)
{
error_at (loc, "array notation cannot be used with function type");
return false;
diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c
index f3a2aff048d..daa9b8ebb38 100644
--- a/gcc/cp/cp-cilkplus.c
+++ b/gcc/cp/cp-cilkplus.c
@@ -118,7 +118,7 @@ cilk_install_body_with_frame_cleanup (tree fndecl, tree orig_body, void *wd)
tree dtor = create_cilk_function_exit (frame, false, false);
add_local_decl (cfun, frame);
- cfun->language = ggc_alloc_cleared_language_function ();
+ cfun->language = ggc_cleared_alloc<language_function> ();
location_t loc = EXPR_LOCATION (orig_body);
tree list = alloc_stmt_list ();
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index c28c07a9d1f..014f393ecfa 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "stor-layout.h"
#include "cp-tree.h"
#include "c-family/c-common.h"
#include "langhooks.h"
@@ -40,6 +41,7 @@ static enum classify_record cp_classify_record (tree type);
static tree cp_eh_personality (void);
static tree get_template_innermost_arguments_folded (const_tree);
static tree get_template_argument_pack_elems_folded (const_tree);
+static tree cxx_enum_underlying_base_type (const_tree);
/* Lang hooks common to C++ and ObjC++ are declared in cp/cp-objcp-common.h;
consequently, there should be very few hooks below. */
@@ -81,6 +83,8 @@ static tree get_template_argument_pack_elems_folded (const_tree);
#define LANG_HOOKS_EH_PERSONALITY cp_eh_personality
#undef LANG_HOOKS_EH_RUNTIME_TYPE
#define LANG_HOOKS_EH_RUNTIME_TYPE build_eh_type_type
+#undef LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE
+#define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE cxx_enum_underlying_base_type
/* Each front end provides its own lang hook initializer. */
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
@@ -219,5 +223,21 @@ get_template_argument_pack_elems_folded (const_tree t)
return fold_cplus_constants (get_template_argument_pack_elems (t));
}
+/* The C++ version of the enum_underlying_base_type langhook.
+ See also cp/semantics.c (finish_underlying_type). */
+
+static
+tree cxx_enum_underlying_base_type (const_tree type)
+{
+ tree underlying_type = ENUM_UNDERLYING_TYPE (type);
+
+ if (! ENUM_FIXED_UNDERLYING_TYPE_P (type))
+ underlying_type
+ = c_common_type_for_mode (TYPE_MODE (underlying_type),
+ TYPE_UNSIGNED (underlying_type));
+
+ return underlying_type;
+}
+
#include "gt-cp-cp-lang.h"
#include "gtype-cp.h"
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index aa0ff839cee..78dddef70d1 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -208,7 +208,7 @@ decl_shadowed_for_var_insert (tree from, tree to)
struct tree_decl_map *h;
void **loc;
- h = ggc_alloc_tree_decl_map ();
+ h = ggc_alloc<tree_decl_map> ();
h->base.from = from;
h->to = to;
loc = htab_find_slot_with_hash (shadowed_var_for_decl, h, DECL_UID (from),
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 34d3d203336..3e4ec3d72d9 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -125,7 +125,7 @@ c-common.h, not after.
Usage of TYPE_LANG_FLAG_?:
0: TYPE_DEPENDENT_P
1: TYPE_HAS_USER_CONSTRUCTOR.
- 2: unused
+ 2: TYPE_HAS_LATE_RETURN_TYPE (in FUNCTION_TYPE, METHOD_TYPE)
3: TYPE_FOR_JAVA.
4: TYPE_HAS_NONTRIVIAL_DESTRUCTOR
5: CLASS_TYPE_P (in RECORD_TYPE and UNION_TYPE)
@@ -1484,7 +1484,7 @@ struct GTY(()) lang_type_ptrmem {
tree record;
};
-struct GTY((variable_size)) lang_type {
+struct GTY(()) lang_type {
union lang_type_u
{
struct lang_type_header GTY((skip (""))) h;
@@ -2062,7 +2062,7 @@ struct GTY(()) lang_decl_parm {
union rather than a struct containing a union as its only field, but
tree.h declares it as a struct. */
-struct GTY((variable_size)) lang_decl {
+struct GTY(()) lang_decl {
union GTY((desc ("%h.base.selector"))) lang_decl_u {
struct lang_decl_base GTY ((default)) base;
struct lang_decl_min GTY((tag ("0"))) min;
@@ -3404,6 +3404,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
user-declared constructor. */
#define TYPE_HAS_USER_CONSTRUCTOR(NODE) (TYPE_LANG_FLAG_1 (NODE))
+/* Nonzero means that the FUNCTION_TYPE or METHOD_TYPE has a
+ late-specified return type. */
+#define TYPE_HAS_LATE_RETURN_TYPE(NODE) \
+ (TYPE_LANG_FLAG_2 (FUNC_OR_METHOD_CHECK (NODE)))
+
/* When appearing in an INDIRECT_REF, it means that the tree structure
underneath is actually a call to a constructor. This is needed
when the constructor must initialize local storage (which can
@@ -3437,6 +3442,9 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
B b{1,2}, not B b({1,2}) or B b = {1,2}. */
#define CONSTRUCTOR_IS_DIRECT_INIT(NODE) (TREE_LANG_FLAG_0 (CONSTRUCTOR_CHECK (NODE)))
+#define DIRECT_LIST_INIT_P(NODE) \
+ (BRACE_ENCLOSED_INITIALIZER_P (NODE) && CONSTRUCTOR_IS_DIRECT_INIT (NODE))
+
/* True if NODE represents a conversion for direct-initialization in a
template. Set by perform_implicit_conversion_flags. */
#define IMPLICIT_CONV_EXPR_DIRECT_INIT(NODE) \
@@ -3588,7 +3596,8 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
do { \
if (TYPE_LANG_SPECIFIC (NODE) == NULL) \
{ \
- TYPE_LANG_SPECIFIC (NODE) = ggc_alloc_cleared_lang_type \
+ TYPE_LANG_SPECIFIC (NODE) \
+ = (struct lang_type *) ggc_internal_cleared_alloc \
(sizeof (struct lang_type_ptrmem)); \
TYPE_LANG_SPECIFIC (NODE)->u.ptrmem.h.is_lang_type_class = 0; \
} \
@@ -5890,8 +5899,8 @@ extern void insert_pending_capture_proxies (void);
extern bool is_capture_proxy (tree);
extern bool is_normal_capture_proxy (tree);
extern void register_capture_members (tree);
-extern tree lambda_expr_this_capture (tree);
-extern tree maybe_resolve_dummy (tree);
+extern tree lambda_expr_this_capture (tree, bool);
+extern tree maybe_resolve_dummy (tree, bool);
extern tree nonlambda_method_basetype (void);
extern void maybe_add_lambda_conv_op (tree);
extern bool is_lambda_ignored_entity (tree);
@@ -6034,6 +6043,7 @@ extern bool comptypes (tree, tree, int);
extern bool same_type_ignoring_top_level_qualifiers_p (tree, tree);
extern bool compparms (const_tree, const_tree);
extern int comp_cv_qualification (const_tree, const_tree);
+extern int comp_cv_qualification (int, int);
extern int comp_cv_qual_signature (tree, tree);
extern tree cxx_sizeof_or_alignof_expr (tree, enum tree_code, bool);
extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, bool);
@@ -6153,6 +6163,7 @@ extern void cxx_incomplete_type_diagnostic (const_tree, const_tree, diagnostic_t
extern void cxx_incomplete_type_error (const_tree, const_tree);
#define cxx_incomplete_type_error(V,T) \
(cxx_incomplete_type_diagnostic ((V), (T), DK_ERROR))
+extern void cxx_incomplete_type_inform (const_tree);
extern tree error_not_base_type (tree, tree);
extern tree binfo_or_else (tree, tree);
extern void cxx_readonly_error (tree, enum lvalue_use);
@@ -6166,6 +6177,7 @@ extern tree store_init_value (tree, tree, vec<tree, va_gc>**, int);
extern void check_narrowing (tree, tree);
extern tree digest_init (tree, tree, tsubst_flags_t);
extern tree digest_init_flags (tree, tree, int);
+extern tree digest_nsdmi_init (tree, tree);
extern tree build_scoped_ref (tree, tree, tree *);
extern tree build_x_arrow (location_t, tree,
tsubst_flags_t);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index c833722538e..2a827237f28 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -198,8 +198,9 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
complain);
}
}
- error_at (loc, "cannot convert %qE from type %qT to type %qT",
- expr, intype, type);
+ if (complain & tf_error)
+ error_at (loc, "cannot convert %qE from type %qT to type %qT",
+ expr, intype, type);
return error_mark_node;
}
@@ -1284,7 +1285,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
}
else
return error_mark_node;
- expr = void_zero_node;
+ expr = void_node;
}
else if (implicit != ICV_CAST && probe == expr && is_overloaded_fn (probe))
{
@@ -1414,7 +1415,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
expr = build1 (CONVERT_EXPR, void_type_node, expr);
}
if (! TREE_SIDE_EFFECTS (expr))
- expr = void_zero_node;
+ expr = void_node;
return expr;
}
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index c39fb7d7165..f5f91c804c1 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -403,6 +403,7 @@ cxx_pretty_printer::primary_expression (tree t)
{
switch (TREE_CODE (t))
{
+ case VOID_CST:
case INTEGER_CST:
case REAL_CST:
case COMPLEX_CST:
@@ -690,7 +691,7 @@ pp_cxx_new_expression (cxx_pretty_printer *pp, tree t)
pp_left_paren (pp);
if (TREE_CODE (init) == TREE_LIST)
pp_c_expression_list (pp, init);
- else if (init == void_zero_node)
+ else if (init == void_node)
; /* OK, empty initializer list. */
else
pp->expression (init);
@@ -1028,6 +1029,7 @@ cxx_pretty_printer::expression (tree t)
switch (TREE_CODE (t))
{
case STRING_CST:
+ case VOID_CST:
case INTEGER_CST:
case REAL_CST:
case COMPLEX_CST:
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 01a36252b2e..c61ad68f92b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "cilk.h"
#include "wide-int.h"
+#include "builtins.h"
/* Possible cases of bad specifiers type used by bad_specifiers. */
enum bad_spec_place {
@@ -2065,8 +2066,17 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
/* Merge the storage class information. */
merge_weak (newdecl, olddecl);
- if (DECL_ONE_ONLY (olddecl))
- DECL_COMDAT_GROUP (newdecl) = DECL_COMDAT_GROUP (olddecl);
+ if ((TREE_CODE (olddecl) == FUNCTION_DECL || TREE_CODE (olddecl) == VAR_DECL)
+ && (DECL_EXTERNAL (olddecl) || TREE_PUBLIC (olddecl) || TREE_STATIC (olddecl))
+ && DECL_ONE_ONLY (olddecl))
+ {
+ struct symtab_node *symbol;
+ if (TREE_CODE (olddecl) == FUNCTION_DECL)
+ symbol = cgraph_get_create_node (newdecl);
+ else
+ symbol = varpool_node_for_decl (newdecl);
+ symbol->set_comdat_group (symtab_get_node (olddecl)->get_comdat_group ());
+ }
DECL_DEFER_OUTPUT (newdecl) |= DECL_DEFER_OUTPUT (olddecl);
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
@@ -2306,10 +2316,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
&& DECL_VISIBILITY_SPECIFIED (newdecl)
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
- warning_at (input_location, OPT_Wattributes,
- "%q+D: visibility attribute ignored because it", newdecl);
- warning_at (DECL_SOURCE_LOCATION (olddecl), OPT_Wattributes,
- "conflicts with previous declaration here");
+ if (warning_at (DECL_SOURCE_LOCATION (newdecl), OPT_Wattributes,
+ "%qD: visibility attribute ignored because it "
+ "conflicts with previous declaration", newdecl))
+ inform (DECL_SOURCE_LOCATION (olddecl),
+ "previous declaration of %qD", olddecl);
}
/* Choose the declaration which specified visibility. */
if (DECL_VISIBILITY_SPECIFIED (olddecl))
@@ -2375,6 +2386,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
int function_size;
+ struct symtab_node *snode = symtab_get_node (olddecl);
function_size = sizeof (struct tree_decl_common);
@@ -2385,6 +2397,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
(char *) newdecl + sizeof (struct tree_decl_common),
sizeof (struct tree_function_decl) - sizeof (struct tree_decl_common));
+
+ /* Preserve symtab node mapping. */
+ olddecl->decl_with_vis.symtab_node = snode;
+
if (new_template_info)
/* If newdecl is a template instantiation, it is possible that
the following sequence of events has occurred:
@@ -2414,6 +2430,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
else
{
size_t size = tree_code_size (TREE_CODE (olddecl));
+
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl_common) - sizeof (struct tree_common));
@@ -2427,10 +2444,17 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
case TYPE_DECL:
case CONST_DECL:
{
+ struct symtab_node *snode = NULL;
+
+ if (TREE_CODE (olddecl) == VAR_DECL
+ && (TREE_STATIC (olddecl) || TREE_PUBLIC (olddecl) || DECL_EXTERNAL (olddecl)))
+ snode = symtab_get_node (olddecl);
memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
(char *) newdecl + sizeof (struct tree_decl_common),
size - sizeof (struct tree_decl_common)
+ TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
+ if (TREE_CODE (olddecl) == VAR_DECL)
+ olddecl->decl_with_vis.symtab_node = snode;
}
break;
default:
@@ -2465,7 +2489,21 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
/* The NEWDECL will no longer be needed. Because every out-of-class
declaration of a member results in a call to duplicate_decls,
- freeing these nodes represents in a significant savings. */
+ freeing these nodes represents in a significant savings.
+
+ Before releasing the node, be sore to remove function from symbol
+ table that might have been inserted there to record comdat group.
+ Be sure to however do not free DECL_STRUCT_FUNCTION becuase this
+ structure is shared in between newdecl and oldecl. */
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
+ DECL_STRUCT_FUNCTION (newdecl) = NULL;
+ if (TREE_CODE (newdecl) == FUNCTION_DECL
+ || TREE_CODE (newdecl) == VAR_DECL)
+ {
+ struct symtab_node *snode = symtab_get_node (newdecl);
+ if (snode)
+ symtab_remove_node (snode);
+ }
ggc_free (newdecl);
return olddecl;
@@ -2700,7 +2738,7 @@ make_label_decl (tree id, int local_p)
/* Record this label on the list of labels used in this function.
We do this before calling make_label_decl so that we get the
IDENTIFIER_LABEL_VALUE before the new label is declared. */
- ent = ggc_alloc_cleared_named_label_entry ();
+ ent = ggc_cleared_alloc<named_label_entry> ();
ent->label_decl = decl;
slot = htab_find_slot (named_labels, ent, INSERT);
@@ -2931,7 +2969,7 @@ check_goto (tree decl)
&& ent->uses->names_in_scope == current_binding_level->names)
return;
- new_use = ggc_alloc_named_label_use_entry ();
+ new_use = ggc_alloc<named_label_use_entry> ();
new_use->binding_level = current_binding_level;
new_use->names_in_scope = current_binding_level->names;
new_use->o_goto_locus = input_location;
@@ -3490,8 +3528,9 @@ make_unbound_class_template (tree context, tree name, tree parm_list,
{
if (complain & tf_error)
{
- error ("template parameters do not match template");
- error ("%q+D declared here", tmpl);
+ error ("template parameters do not match template %qD", tmpl);
+ inform (DECL_SOURCE_LOCATION (tmpl),
+ "%qD declared here", tmpl);
}
return error_mark_node;
}
@@ -5025,13 +5064,12 @@ maybe_commonize_var (tree decl)
be merged. */
TREE_PUBLIC (decl) = 0;
DECL_COMMON (decl) = 0;
- warning_at (input_location, 0,
- "sorry: semantics of inline function static "
- "data %q+#D are wrong (you%'ll wind up "
- "with multiple copies)", decl);
- warning_at (DECL_SOURCE_LOCATION (decl), 0,
- " you can work around this by removing "
- "the initializer");
+ if (warning_at (DECL_SOURCE_LOCATION (decl), 0,
+ "sorry: semantics of inline function static "
+ "data %q#D are wrong (you%'ll wind up "
+ "with multiple copies)", decl))
+ inform (DECL_SOURCE_LOCATION (decl),
+ "you can work around this by removing the initializer");
}
}
}
@@ -6829,7 +6867,7 @@ register_dtor_fn (tree decl)
type = TREE_TYPE (decl);
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
- return void_zero_node;
+ return void_node;
/* If we're using "__cxa_atexit" (or "__cxa_thread_atexit" or
"__aeabi_atexit"), and DECL is a class object, we can just pass the
@@ -7076,7 +7114,7 @@ expand_static_init (tree decl, tree init)
TARGET_EXPR_CLEANUP (begin)
= build3 (COND_EXPR, void_type_node, flag,
- void_zero_node,
+ void_node,
build_call_n (abort_fn, 1, guard_addr));
CLEANUP_EH_ONLY (begin) = 1;
@@ -8424,7 +8462,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
tree comp = build2 (LT_EXPR, boolean_type_node, itype,
ssize_int (-1));
comp = build3 (COND_EXPR, void_type_node, comp,
- throw_bad_array_length (), void_zero_node);
+ throw_bad_array_length (), void_node);
finish_expr_stmt (comp);
}
else if (flag_sanitize & SANITIZE_VLA)
@@ -8780,6 +8818,7 @@ grokdeclarator (const cp_declarator *declarator,
bool template_parm_flag = false;
bool typedef_p = decl_spec_seq_has_spec_p (declspecs, ds_typedef);
bool constexpr_p = decl_spec_seq_has_spec_p (declspecs, ds_constexpr);
+ bool late_return_type_p = false;
source_location saved_loc = input_location;
const char *errmsg;
@@ -9623,6 +9662,9 @@ grokdeclarator (const cp_declarator *declarator,
if (type == error_mark_node)
return error_mark_node;
+ if (declarator->u.function.late_return_type)
+ late_return_type_p = true;
+
if (ctype == NULL_TREE
&& decl_context == FIELD
&& funcdecl_p
@@ -10553,6 +10595,10 @@ grokdeclarator (const cp_declarator *declarator,
decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
publicp = (! friendp || ! staticp)
&& function_context == NULL_TREE;
+
+ if (late_return_type_p)
+ TYPE_HAS_LATE_RETURN_TYPE (type) = 1;
+
decl = grokfndecl (ctype, type,
TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
? unqualified_id : dname,
@@ -10585,11 +10631,16 @@ grokdeclarator (const cp_declarator *declarator,
}
else if (!staticp && !dependent_type_p (type)
&& !COMPLETE_TYPE_P (complete_type (type))
- && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
+ && (TREE_CODE (type) != ARRAY_TYPE
+ || !COMPLETE_TYPE_P (TREE_TYPE (type))
+ || initialized == 0))
{
if (unqualified_id)
- error ("field %qD has incomplete type %qT",
- unqualified_id, type);
+ {
+ error ("field %qD has incomplete type %qT",
+ unqualified_id, type);
+ cxx_incomplete_type_inform (strip_array_types (type));
+ }
else
error ("name %qT has incomplete type", type);
@@ -10772,6 +10823,9 @@ grokdeclarator (const cp_declarator *declarator,
publicp = (ctype != NULL_TREE
|| storage_class != sc_static);
+ if (late_return_type_p)
+ TYPE_HAS_LATE_RETURN_TYPE (type) = 1;
+
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, memfn_quals, rqual, raises,
1, friendp,
@@ -13302,7 +13356,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
/* Initialize the language data structures. Whenever we start
a new function, we destroy temporaries in the usual way. */
- cfun->language = ggc_alloc_cleared_language_function ();
+ cfun->language = ggc_cleared_alloc<language_function> ();
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
current_binding_level = bl;
@@ -13607,7 +13661,7 @@ save_function_data (tree decl)
gcc_assert (!DECL_PENDING_INLINE_P (decl));
/* Make a copy. */
- f = ggc_alloc_language_function ();
+ f = ggc_alloc<language_function> ();
memcpy (f, cp_function_chain, sizeof (struct language_function));
DECL_SAVED_FUNCTION_DATA (decl) = f;
@@ -14379,6 +14433,8 @@ static_fn_type (tree memfntype)
(fntype, TYPE_ATTRIBUTES (memfntype)));
fntype = (build_exception_variant
(fntype, TYPE_RAISES_EXCEPTIONS (memfntype)));
+ if (TYPE_HAS_LATE_RETURN_TYPE (memfntype))
+ TYPE_HAS_LATE_RETURN_TYPE (fntype) = 1;
return fntype;
}
@@ -14442,18 +14498,17 @@ cp_missing_noreturn_ok_p (tree decl)
return DECL_MAIN_P (decl);
}
-/* Return the COMDAT group into which DECL should be placed. */
+/* Return the decl used to identify the COMDAT group into which DECL should
+ be placed. */
tree
cxx_comdat_group (tree decl)
{
- tree name;
-
/* Virtual tables, construction virtual tables, and virtual table
tables all go in a single COMDAT group, named after the primary
virtual table. */
if (VAR_P (decl) && DECL_VTABLE_OR_VTT_P (decl))
- name = DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (DECL_CONTEXT (decl)));
+ decl = CLASSTYPE_VTABLES (DECL_CONTEXT (decl));
/* For all other DECLs, the COMDAT group is the mangled name of the
declaration itself. */
else
@@ -14471,10 +14526,9 @@ cxx_comdat_group (tree decl)
else
break;
}
- name = DECL_ASSEMBLER_NAME (decl);
}
- return name;
+ return decl;
}
/* Returns the return type for FN as written by the user, which may include
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 71402181af6..602a0c55759 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -119,6 +119,7 @@ build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals,
tree raises;
tree attrs;
int type_quals;
+ bool late_return_type_p;
if (fntype == error_mark_node || ctype == error_mark_node)
return error_mark_node;
@@ -130,6 +131,7 @@ build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals,
ctype = cp_build_qualified_type (ctype, type_quals);
raises = TYPE_RAISES_EXCEPTIONS (fntype);
attrs = TYPE_ATTRIBUTES (fntype);
+ late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (fntype);
fntype = build_method_type_directly (ctype, TREE_TYPE (fntype),
(TREE_CODE (fntype) == METHOD_TYPE
? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
@@ -140,6 +142,8 @@ build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals,
fntype = build_ref_qualified_type (fntype, rqual);
if (raises)
fntype = build_exception_variant (fntype, raises);
+ if (late_return_type_p)
+ TYPE_HAS_LATE_RETURN_TYPE (fntype) = 1;
return fntype;
}
@@ -154,6 +158,7 @@ change_return_type (tree new_ret, tree fntype)
tree args = TYPE_ARG_TYPES (fntype);
tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
tree attrs = TYPE_ATTRIBUTES (fntype);
+ bool late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (fntype);
if (new_ret == error_mark_node)
return fntype;
@@ -175,6 +180,8 @@ change_return_type (tree new_ret, tree fntype)
newtype = build_exception_variant (newtype, raises);
if (attrs)
newtype = cp_build_type_attribute_variant (newtype, attrs);
+ if (late_return_type_p)
+ TYPE_HAS_LATE_RETURN_TYPE (newtype) = 1;
return newtype;
}
@@ -983,8 +990,7 @@ grokfield (const cp_declarator *declarator,
if (attrlist)
cplus_decl_attributes (&value, attrlist, 0);
- if (init && BRACE_ENCLOSED_INITIALIZER_P (init)
- && CONSTRUCTOR_IS_DIRECT_INIT (init))
+ if (init && DIRECT_LIST_INIT_P (init))
flags = LOOKUP_NORMAL;
else
flags = LOOKUP_IMPLICIT;
@@ -1277,6 +1283,7 @@ tree
cp_reconstruct_complex_type (tree type, tree bottom)
{
tree inner, outer;
+ bool late_return_type_p = false;
if (TYPE_PTR_P (type))
{
@@ -1302,6 +1309,7 @@ cp_reconstruct_complex_type (tree type, tree bottom)
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
+ late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (type);
inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
outer = build_function_type (inner, TYPE_ARG_TYPES (type));
outer = apply_memfn_quals (outer,
@@ -1310,6 +1318,7 @@ cp_reconstruct_complex_type (tree type, tree bottom)
}
else if (TREE_CODE (type) == METHOD_TYPE)
{
+ late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (type);
inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
/* The build_method_type_directly() routine prepends 'this' to argument list,
so we must compensate by getting rid of it. */
@@ -1328,7 +1337,12 @@ cp_reconstruct_complex_type (tree type, tree bottom)
if (TYPE_ATTRIBUTES (type))
outer = cp_build_type_attribute_variant (outer, TYPE_ATTRIBUTES (type));
- return cp_build_qualified_type (outer, cp_type_quals (type));
+ outer = cp_build_qualified_type (outer, cp_type_quals (type));
+
+ if (late_return_type_p)
+ TYPE_HAS_LATE_RETURN_TYPE (outer) = 1;
+
+ return outer;
}
/* Replaces any constexpr expression that may be into the attributes
@@ -2094,7 +2108,14 @@ constrain_visibility (tree decl, int visibility, bool tmpl)
TREE_PUBLIC (decl) = 0;
DECL_WEAK (decl) = 0;
DECL_COMMON (decl) = 0;
- DECL_COMDAT_GROUP (decl) = NULL_TREE;
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == VAR_DECL)
+ {
+ struct symtab_node *snode = symtab_get_node (decl);
+
+ if (snode)
+ snode->set_comdat_group (NULL);
+ }
DECL_INTERFACE_KNOWN (decl) = 1;
if (DECL_LANG_SPECIFIC (decl))
DECL_NOT_REALLY_EXTERN (decl) = 1;
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 699d5458a40..b3b5bbb0971 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1913,6 +1913,7 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
pp_cxx_ws_string (pp, M_("<unknown>"));
break;
+ case VOID_CST:
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 6838d2aadd0..8edf5193750 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -534,12 +534,16 @@ get_nsdmi (tree member, bool in_ctor)
if (!in_ctor)
inject_this_parameter (DECL_CONTEXT (member), TYPE_UNQUALIFIED);
if (DECL_LANG_SPECIFIC (member) && DECL_TEMPLATE_INFO (member))
- /* Do deferred instantiation of the NSDMI. */
- init = (tsubst_copy_and_build
- (DECL_INITIAL (DECL_TI_TEMPLATE (member)),
- DECL_TI_ARGS (member),
- tf_warning_or_error, member, /*function_p=*/false,
- /*integral_constant_expression_p=*/false));
+ {
+ /* Do deferred instantiation of the NSDMI. */
+ init = (tsubst_copy_and_build
+ (DECL_INITIAL (DECL_TI_TEMPLATE (member)),
+ DECL_TI_ARGS (member),
+ tf_warning_or_error, member, /*function_p=*/false,
+ /*integral_constant_expression_p=*/false));
+
+ init = digest_nsdmi_init (member, init);
+ }
else
{
init = DECL_INITIAL (member);
@@ -642,8 +646,7 @@ perform_member_init (tree member, tree init)
&& TREE_TYPE (init) == type)
/* { } mem-initializer. */
|| (TREE_CODE (init) == TREE_LIST
- && TREE_CODE (TREE_VALUE (init)) == CONSTRUCTOR
- && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (init))))
+ && DIRECT_LIST_INIT_P (TREE_VALUE (init))))
&& (CP_AGGREGATE_TYPE_P (type)
|| is_std_init_list (type)))))
{
@@ -1515,8 +1518,7 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
&& TREE_CODE (init) != TREE_LIST
&& !(TREE_CODE (init) == TARGET_EXPR
&& TARGET_EXPR_DIRECT_INIT_P (init))
- && !(BRACE_ENCLOSED_INITIALIZER_P (init)
- && CONSTRUCTOR_IS_DIRECT_INIT (init)))
+ && !DIRECT_LIST_INIT_P (init))
flags |= LOOKUP_ONLYCONVERTING;
if (TREE_CODE (type) == ARRAY_TYPE)
@@ -1589,8 +1591,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
/* If we have direct-initialization from an initializer list, pull
it out of the TREE_LIST so the code below can see it. */
if (init && TREE_CODE (init) == TREE_LIST
- && BRACE_ENCLOSED_INITIALIZER_P (TREE_VALUE (init))
- && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (init)))
+ && DIRECT_LIST_INIT_P (TREE_VALUE (init)))
{
gcc_checking_assert ((flags & LOOKUP_ONLYCONVERTING) == 0
&& TREE_CHAIN (init) == NULL_TREE);
@@ -2119,7 +2120,7 @@ build_raw_new_expr (vec<tree, va_gc> *placement, tree type, tree nelts,
if (init == NULL)
init_list = NULL_TREE;
else if (init->is_empty ())
- init_list = void_zero_node;
+ init_list = void_node;
else
init_list = build_tree_list_vec (init);
@@ -2791,8 +2792,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
{
tree vecinit = NULL_TREE;
if (vec_safe_length (*init) == 1
- && BRACE_ENCLOSED_INITIALIZER_P ((**init)[0])
- && CONSTRUCTOR_IS_DIRECT_INIT ((**init)[0]))
+ && DIRECT_LIST_INIT_P ((**init)[0]))
{
vecinit = (**init)[0];
if (CONSTRUCTOR_NELTS (vecinit) == 0)
@@ -2935,7 +2935,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
TARGET_EXPR_CLEANUP (begin)
= build3 (COND_EXPR, void_type_node, sentry,
- cleanup, void_zero_node);
+ cleanup, void_node);
end = build2 (MODIFY_EXPR, TREE_TYPE (sentry),
sentry, boolean_false_node);
@@ -3598,7 +3598,7 @@ build_vec_init (tree base, tree maxindex, tree init,
else
throw_call = throw_bad_array_new_length ();
length_check = build3 (COND_EXPR, void_type_node, length_check,
- throw_call, void_zero_node);
+ throw_call, void_node);
finish_expr_stmt (length_check);
}
@@ -4020,7 +4020,7 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete,
}
if (auto_delete != sfk_deleting_destructor)
- return void_zero_node;
+ return void_node;
return build_op_delete_call (DELETE_EXPR, addr,
cxx_sizeof_nowarn (type),
@@ -4108,8 +4108,7 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete,
}
if (ifexp != integer_one_node)
- expr = build3 (COND_EXPR, void_type_node,
- ifexp, expr, void_zero_node);
+ expr = build3 (COND_EXPR, void_type_node, ifexp, expr, void_node);
return expr;
}
@@ -4154,7 +4153,7 @@ push_base_cleanups (void)
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
{
expr = build3 (COND_EXPR, void_type_node, cond,
- expr, void_zero_node);
+ expr, void_node);
finish_decl_cleanup (NULL_TREE, expr);
}
}
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 5ba6f141b72..e72682c9487 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -367,10 +367,7 @@ build_capture_proxy (tree member)
object = TREE_OPERAND (object, 0);
/* Remove the __ inserted by add_capture. */
- if (DECL_NORMAL_CAPTURE_P (member))
- name = get_identifier (IDENTIFIER_POINTER (DECL_NAME (member)) + 2);
- else
- name = DECL_NAME (member);
+ name = get_identifier (IDENTIFIER_POINTER (DECL_NAME (member)) + 2);
type = lambda_proxy_type (object);
@@ -456,6 +453,9 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
initializer = build_x_compound_expr_from_list (initializer, ELK_INIT,
tf_warning_or_error);
type = TREE_TYPE (initializer);
+ if (type == error_mark_node)
+ return error_mark_node;
+
if (array_of_runtime_bound_p (type))
{
vla = true;
@@ -492,25 +492,27 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
error ("cannot capture %qE by reference", initializer);
}
else
- /* Capture by copy requires a complete type. */
- type = complete_type (type);
+ {
+ /* Capture by copy requires a complete type. */
+ type = complete_type (type);
+ if (!dependent_type_p (type) && !COMPLETE_TYPE_P (type))
+ {
+ error ("capture by copy of incomplete type %qT", type);
+ cxx_incomplete_type_inform (type);
+ return error_mark_node;
+ }
+ }
}
/* Add __ to the beginning of the field name so that user code
won't find the field with name lookup. We can't just leave the name
unset because template instantiation uses the name to find
instantiated fields. */
- if (!explicit_init_p)
- {
- buf = (char *) alloca (IDENTIFIER_LENGTH (id) + 3);
- buf[1] = buf[0] = '_';
- memcpy (buf + 2, IDENTIFIER_POINTER (id),
- IDENTIFIER_LENGTH (id) + 1);
- name = get_identifier (buf);
- }
- else
- /* But captures with explicit initializers are named. */
- name = id;
+ buf = (char *) alloca (IDENTIFIER_LENGTH (id) + 3);
+ buf[1] = buf[0] = '_';
+ memcpy (buf + 2, IDENTIFIER_POINTER (id),
+ IDENTIFIER_LENGTH (id) + 1);
+ name = get_identifier (buf);
/* If TREE_TYPE isn't set, we're still in the introducer, so check
for duplicates. */
@@ -624,11 +626,12 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
return var;
}
-/* Return the capture pertaining to a use of 'this' in LAMBDA, in the form of an
- INDIRECT_REF, possibly adding it through default capturing. */
+/* Return the capture pertaining to a use of 'this' in LAMBDA, in the
+ form of an INDIRECT_REF, possibly adding it through default
+ capturing, if ADD_CAPTURE_P is false. */
tree
-lambda_expr_this_capture (tree lambda)
+lambda_expr_this_capture (tree lambda, bool add_capture_p)
{
tree result;
@@ -648,7 +651,8 @@ lambda_expr_this_capture (tree lambda)
/* Try to default capture 'this' if we can. */
if (!this_capture
- && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE)
+ && (!add_capture_p
+ || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE))
{
tree lambda_stack = NULL_TREE;
tree init = NULL_TREE;
@@ -708,9 +712,14 @@ lambda_expr_this_capture (tree lambda)
}
if (init)
- this_capture = add_default_capture (lambda_stack,
- /*id=*/this_identifier,
- init);
+ {
+ if (add_capture_p)
+ this_capture = add_default_capture (lambda_stack,
+ /*id=*/this_identifier,
+ init);
+ else
+ this_capture = init;
+ }
}
if (!this_capture)
@@ -742,7 +751,7 @@ lambda_expr_this_capture (tree lambda)
'this' capture. */
tree
-maybe_resolve_dummy (tree object)
+maybe_resolve_dummy (tree object, bool add_capture_p)
{
if (!is_dummy_object (object))
return object;
@@ -758,7 +767,7 @@ maybe_resolve_dummy (tree object)
{
/* In a lambda, need to go through 'this' capture. */
tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type);
- tree cap = lambda_expr_this_capture (lam);
+ tree cap = lambda_expr_this_capture (lam, add_capture_p);
object = build_x_indirect_ref (EXPR_LOCATION (object), cap,
RO_NULL, tf_warning_or_error);
}
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 3fe275e4933..57b779d77e1 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -182,7 +182,7 @@ init_reswords (void)
/* The Objective-C keywords are all context-dependent. */
mask |= D_OBJC;
- ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
+ ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
for (i = 0; i < num_c_common_reswords; i++)
{
if (c_common_reswords[i].disable & D_CONLY)
@@ -555,7 +555,7 @@ retrofit_lang_decl (tree t)
else
gcc_unreachable ();
- ld = ggc_alloc_cleared_lang_decl (size);
+ ld = (struct lang_decl *) ggc_internal_cleared_alloc (size);
ld->u.base.selector = sel;
@@ -597,7 +597,7 @@ cxx_dup_lang_specific_decl (tree node)
else
gcc_unreachable ();
- ld = ggc_alloc_lang_decl (size);
+ ld = (struct lang_decl *) ggc_internal_alloc (size);
memcpy (ld, DECL_LANG_SPECIFIC (node), size);
DECL_LANG_SPECIFIC (node) = ld;
@@ -635,7 +635,7 @@ copy_lang_type (tree node)
size = sizeof (struct lang_type);
else
size = sizeof (struct lang_type_ptrmem);
- lt = ggc_alloc_lang_type (size);
+ lt = (struct lang_type *) ggc_internal_alloc (size);
memcpy (lt, TYPE_LANG_SPECIFIC (node), size);
TYPE_LANG_SPECIFIC (node) = lt;
@@ -668,7 +668,8 @@ cxx_make_type (enum tree_code code)
|| code == BOUND_TEMPLATE_TEMPLATE_PARM)
{
struct lang_type *pi
- = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+ = (struct lang_type *) ggc_internal_cleared_alloc
+ (sizeof (struct lang_type));
TYPE_LANG_SPECIFIC (t) = pi;
pi->u.c.h.is_lang_type_class = 1;
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 97fb4c6ec3c..1b2c2cd7944 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -2806,14 +2806,13 @@ write_expression (tree expr)
write_type (type);
if (init && TREE_CODE (init) == TREE_LIST
- && TREE_CODE (TREE_VALUE (init)) == CONSTRUCTOR
- && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (init)))
+ && DIRECT_LIST_INIT_P (TREE_VALUE (init)))
write_expression (TREE_VALUE (init));
else
{
if (init)
write_string ("pi");
- if (init && init != void_zero_node)
+ if (init && init != void_node)
for (t = init; t; t = TREE_CHAIN (t))
write_expression (TREE_VALUE (t));
write_char ('E');
@@ -3521,7 +3520,11 @@ mangle_decl (const tree decl)
if (vague_linkage_p (decl))
DECL_WEAK (alias) = 1;
if (TREE_CODE (decl) == FUNCTION_DECL)
- cgraph_same_body_alias (cgraph_get_create_node (decl), alias, decl);
+ {
+ /* Don't create an alias to an unreferenced function. */
+ if (struct cgraph_node *n = cgraph_get_node (decl))
+ cgraph_same_body_alias (n, alias, decl);
+ }
else
varpool_extra_name_alias (alias, decl);
#endif
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index d900560490e..2baeeb76d18 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -105,7 +105,7 @@ binding_entry_make (tree name, tree type)
free_binding_entry = entry->chain;
}
else
- entry = ggc_alloc_binding_entry_s ();
+ entry = ggc_alloc<binding_entry_s> ();
entry->name = name;
entry->type = type;
@@ -147,7 +147,7 @@ binding_table_construct (binding_table table, size_t chain_count)
{
table->chain_count = chain_count;
table->entry_count = 0;
- table->chain = ggc_alloc_cleared_vec_binding_entry (table->chain_count);
+ table->chain = ggc_cleared_vec_alloc<binding_entry> (table->chain_count);
}
/* Make TABLE's entries ready for reuse. */
@@ -181,7 +181,7 @@ binding_table_free (binding_table table)
static inline binding_table
binding_table_new (size_t chain_count)
{
- binding_table table = ggc_alloc_binding_table_s ();
+ binding_table table = ggc_alloc<binding_table_s> ();
table->chain = NULL;
binding_table_construct (table, chain_count);
return table;
@@ -299,7 +299,7 @@ cxx_binding_make (tree value, tree type)
free_bindings = binding->previous;
}
else
- binding = ggc_alloc_cxx_binding ();
+ binding = ggc_alloc<cxx_binding> ();
cxx_binding_init (binding, value, type);
@@ -775,7 +775,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
= htab_create_ggc (20, cxx_int_tree_map_hash,
cxx_int_tree_map_eq, NULL);
- h = ggc_alloc_cxx_int_tree_map ();
+ h = ggc_alloc<cxx_int_tree_map> ();
h->uid = DECL_UID (x);
h->to = t;
loc = htab_find_slot_with_hash
@@ -1544,7 +1544,7 @@ begin_scope (scope_kind kind, tree entity)
free_binding_level = scope->level_chain;
}
else
- scope = ggc_alloc_cleared_cp_binding_level ();
+ scope = ggc_cleared_alloc<cp_binding_level> ();
scope->this_entity = entity;
scope->more_cleanups_ok = true;
@@ -6074,7 +6074,7 @@ push_to_top_level (void)
bool need_pop;
bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
- s = ggc_alloc_cleared_saved_scope ();
+ s = ggc_cleared_alloc<saved_scope> ();
b = scope_chain ? current_binding_level : 0;
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index b089432a305..3f89b8197a2 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -170,6 +170,8 @@ cdtor_comdat_group (tree complete, tree base)
complete_name = cxx_comdat_group (complete);
if (base_name == NULL)
base_name = cxx_comdat_group (base);
+ complete_name = DECL_ASSEMBLER_NAME (complete_name);
+ base_name = DECL_ASSEMBLER_NAME (base_name);
gcc_assert (IDENTIFIER_LENGTH (complete_name)
== IDENTIFIER_LENGTH (base_name));
grp_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name) + 1);
@@ -285,7 +287,7 @@ maybe_thunk_body (tree fn, bool force)
else if (HAVE_COMDAT_GROUP)
{
tree comdat_group = cdtor_comdat_group (fns[1], fns[0]);
- DECL_COMDAT_GROUP (fns[0]) = comdat_group;
+ cgraph_get_create_node (fns[0])->set_comdat_group (comdat_group);
symtab_add_to_same_comdat_group (cgraph_get_create_node (fns[1]),
cgraph_get_create_node (fns[0]));
symtab_add_to_same_comdat_group (symtab_get_node (fn),
@@ -473,7 +475,7 @@ maybe_clone_body (tree fn)
name of fn was corrupted by write_mangled_name by adding *INTERNAL*
to it. By doing so, it also corrupted the comdat group. */
if (DECL_ONE_ONLY (fn))
- DECL_COMDAT_GROUP (clone) = cxx_comdat_group (clone);
+ cgraph_get_create_node (clone)->set_comdat_group (cxx_comdat_group (clone));
DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn);
DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
@@ -550,7 +552,7 @@ maybe_clone_body (tree fn)
into the same, *[CD]5* comdat group instead of
*[CD][12]*. */
comdat_group = cdtor_comdat_group (fns[1], fns[0]);
- DECL_COMDAT_GROUP (fns[0]) = comdat_group;
+ cgraph_get_create_node (fns[0])->set_comdat_group (comdat_group);
symtab_add_to_same_comdat_group (symtab_get_node (clone),
symtab_get_node (fns[0]));
}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 5542dcd9ba3..2591ae545a8 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -602,7 +602,7 @@ cp_lexer_alloc (void)
c_common_no_more_pch ();
/* Allocate the memory. */
- lexer = ggc_alloc_cleared_cp_lexer ();
+ lexer = ggc_cleared_alloc<cp_lexer> ();
/* Initially we are not debugging. */
lexer->debugging_p = false;
@@ -665,7 +665,7 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
{
cp_token *first = cache->first;
cp_token *last = cache->last;
- cp_lexer *lexer = ggc_alloc_cleared_cp_lexer ();
+ cp_lexer *lexer = ggc_cleared_alloc<cp_lexer> ();
/* We do not own the buffer. */
lexer->buffer = NULL;
@@ -1240,7 +1240,7 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
static cp_token_cache *
cp_token_cache_new (cp_token *first, cp_token *last)
{
- cp_token_cache *cache = ggc_alloc_cp_token_cache ();
+ cp_token_cache *cache = ggc_alloc<cp_token_cache> ();
cache->first = first;
cache->last = last;
return cache;
@@ -1822,7 +1822,7 @@ cp_parser_context_new (cp_parser_context* next)
memset (context, 0, sizeof (*context));
}
else
- context = ggc_alloc_cleared_cp_parser_context ();
+ context = ggc_cleared_alloc<cp_parser_context> ();
/* No errors have occurred yet in this context. */
context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
@@ -2880,13 +2880,21 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
tree scope, tree id,
location_t location)
{
- tree decl, old_scope;
+ tree decl, old_scope, ambiguous_decls;
cp_parser_commit_to_tentative_parse (parser);
/* Try to lookup the identifier. */
old_scope = parser->scope;
parser->scope = scope;
- decl = cp_parser_lookup_name_simple (parser, id, location);
+ decl = cp_parser_lookup_name (parser, id, none_type,
+ /*is_template=*/false,
+ /*is_namespace=*/false,
+ /*check_dependency=*/true,
+ &ambiguous_decls, location);
parser->scope = old_scope;
+ if (ambiguous_decls)
+ /* If the lookup was ambiguous, an error will already have
+ been issued. */
+ return;
/* If the lookup found a template-name, it means that the user forgot
to specify an argument list. Emit a useful error message. */
if (TREE_CODE (decl) == TEMPLATE_DECL)
@@ -3413,7 +3421,7 @@ cp_parser_new (void)
for (i = 0; i < sizeof (binops) / sizeof (binops[0]); i++)
binops_by_token[binops[i].token_type] = binops[i];
- parser = ggc_alloc_cleared_cp_parser ();
+ parser = ggc_cleared_alloc<cp_parser> ();
parser->lexer = lexer;
parser->context = cp_parser_context_new (NULL);
@@ -5427,7 +5435,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
token->type = CPP_NESTED_NAME_SPECIFIER;
/* Retrieve any deferred checks. Do not pop this access checks yet
so the memory will not be reclaimed during token replacing below. */
- token->u.tree_check_value = ggc_alloc_cleared_tree_check ();
+ token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> ();
token->u.tree_check_value->value = parser->scope;
token->u.tree_check_value->checks = get_deferred_access_checks ();
token->u.tree_check_value->qualifying_scope =
@@ -5837,20 +5845,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
}
break;
}
-
- case RID_CILK_SYNC:
- if (flag_cilkplus)
- {
- tree sync_expr = build_cilk_sync ();
- SET_EXPR_LOCATION (sync_expr,
- cp_lexer_peek_token (parser->lexer)->location);
- finish_expr_stmt (sync_expr);
- }
- else
- error_at (token->location, "-fcilkplus must be enabled to use"
- " %<_Cilk_sync%>");
- cp_lexer_consume_token (parser->lexer);
- break;
case RID_BUILTIN_SHUFFLE:
{
@@ -9158,6 +9152,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
DECL_ARTIFICIAL (fco) = 1;
/* Give the object parameter a different name. */
DECL_NAME (DECL_ARGUMENTS (fco)) = get_identifier ("__closure");
+ if (LAMBDA_EXPR_RETURN_TYPE (lambda_expr))
+ TYPE_HAS_LATE_RETURN_TYPE (TREE_TYPE (fco)) = 1;
}
if (template_param_list)
{
@@ -9406,6 +9402,24 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
statement = cp_parser_jump_statement (parser);
break;
+ case RID_CILK_SYNC:
+ cp_lexer_consume_token (parser->lexer);
+ if (flag_cilkplus)
+ {
+ tree sync_expr = build_cilk_sync ();
+ SET_EXPR_LOCATION (sync_expr,
+ token->location);
+ statement = finish_expr_stmt (sync_expr);
+ }
+ else
+ {
+ error_at (token->location, "-fcilkplus must be enabled to use"
+ " %<_Cilk_sync%>");
+ statement = error_mark_node;
+ }
+ cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+ break;
+
/* Objective-C++ exception-handling constructs. */
case RID_AT_TRY:
case RID_AT_CATCH:
@@ -13502,7 +13516,7 @@ cp_parser_template_id (cp_parser *parser,
token->type = CPP_TEMPLATE_ID;
/* Retrieve any deferred checks. Do not pop this access checks yet
so the memory will not be reclaimed during token replacing below. */
- token->u.tree_check_value = ggc_alloc_cleared_tree_check ();
+ token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> ();
token->u.tree_check_value->value = template_id;
token->u.tree_check_value->checks = get_deferred_access_checks ();
token->keyword = RID_MAX;
@@ -15532,9 +15546,10 @@ cp_parser_enum_specifier (cp_parser* parser)
}
else
{
- error_at (type_start_token->location, "multiple definition of %q#T", type);
- error_at (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
- "previous definition here");
+ error_at (type_start_token->location,
+ "multiple definition of %q#T", type);
+ inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
+ "previous definition here");
type = error_mark_node;
}
@@ -23672,16 +23687,7 @@ cp_parser_late_parse_one_default_arg (cp_parser *parser, tree decl,
parsed_arg = check_default_argument (parmtype, parsed_arg,
tf_warning_or_error);
else
- {
- int flags = LOOKUP_IMPLICIT;
- if (BRACE_ENCLOSED_INITIALIZER_P (parsed_arg)
- && CONSTRUCTOR_IS_DIRECT_INIT (parsed_arg))
- flags = LOOKUP_NORMAL;
- parsed_arg = digest_init_flags (TREE_TYPE (decl), parsed_arg, flags);
- if (TREE_CODE (parsed_arg) == TARGET_EXPR)
- /* This represents the whole initialization. */
- TARGET_EXPR_DIRECT_INIT_P (parsed_arg) = true;
- }
+ parsed_arg = digest_nsdmi_init (decl, parsed_arg);
}
/* If the token stream has not been completely used up, then
@@ -30333,8 +30339,12 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
cp_lexer_consume_token (parser->lexer);
strcpy (p_name, "#pragma omp target");
if (!flag_openmp) /* flag_openmp_simd */
- return cp_parser_omp_teams (parser, pragma_tok, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses);
+ {
+ tree stmt = cp_parser_omp_teams (parser, pragma_tok, p_name,
+ OMP_TARGET_CLAUSE_MASK,
+ cclauses);
+ return stmt != NULL_TREE;
+ }
keep_next_level (true);
tree sb = begin_omp_structured_block ();
unsigned save = cp_parser_begin_omp_structured_block (parser);
@@ -30342,8 +30352,8 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
OMP_TARGET_CLAUSE_MASK, cclauses);
cp_parser_end_omp_structured_block (parser, save);
tree body = finish_omp_structured_block (sb);
- if (ret == NULL)
- return ret;
+ if (ret == NULL_TREE)
+ return false;
tree stmt = make_node (OMP_TARGET);
TREE_TYPE (stmt) = void_type_node;
OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
@@ -30354,7 +30364,7 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
else if (!flag_openmp) /* flag_openmp_simd */
{
cp_parser_require_pragma_eol (parser, pragma_tok);
- return NULL_TREE;
+ return false;
}
else if (strcmp (p, "data") == 0)
{
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f23eec3504c..c0e0646704d 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -142,7 +142,7 @@ static int type_unification_real (tree, tree, tree, const tree *,
vec<deferred_access_check, va_gc> **,
bool);
static void note_template_header (int);
-static tree convert_nontype_argument_function (tree, tree);
+static tree convert_nontype_argument_function (tree, tree, tsubst_flags_t);
static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
static tree convert_template_argument (tree, tree, tree,
tsubst_flags_t, int, tree);
@@ -944,7 +944,7 @@ maybe_process_partial_specialization (tree type)
elt.args = INNERMOST_TEMPLATE_ARGS (elt.args);
slot = htab_find_slot (type_specializations, &elt, INSERT);
- entry = ggc_alloc_spec_entry ();
+ entry = ggc_alloc<spec_entry> ();
*entry = elt;
*slot = entry;
}
@@ -1481,7 +1481,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
if (slot != NULL /* !optimize_specialization_lookup_p (tmpl) */)
{
- spec_entry *entry = ggc_alloc_spec_entry ();
+ spec_entry *entry = ggc_alloc<spec_entry> ();
gcc_assert (tmpl && args && spec);
*entry = elt;
*slot = entry;
@@ -2256,6 +2256,10 @@ copy_default_args_to_explicit_spec (tree decl)
TYPE_ATTRIBUTES (old_type));
new_type = build_exception_variant (new_type,
TYPE_RAISES_EXCEPTIONS (old_type));
+
+ if (TYPE_HAS_LATE_RETURN_TYPE (old_type))
+ TYPE_HAS_LATE_RETURN_TYPE (new_type) = 1;
+
TREE_TYPE (decl) = new_type;
}
@@ -5272,7 +5276,8 @@ get_underlying_template (tree tmpl)
and check that the resulting function has external linkage. */
static tree
-convert_nontype_argument_function (tree type, tree expr)
+convert_nontype_argument_function (tree type, tree expr,
+ tsubst_flags_t complain)
{
tree fns = expr;
tree fn, fn_no_ptr;
@@ -5298,25 +5303,34 @@ convert_nontype_argument_function (tree type, tree expr)
if (TREE_CODE (fn_no_ptr) != FUNCTION_DECL)
{
- error ("%qE is not a valid template argument for type %qT", expr, type);
- if (TYPE_PTR_P (type))
- error ("it must be the address of a function with external linkage");
- else
- error ("it must be the name of a function with external linkage");
+ if (complain & tf_error)
+ {
+ error ("%qE is not a valid template argument for type %qT",
+ expr, type);
+ if (TYPE_PTR_P (type))
+ error ("it must be the address of a function with "
+ "external linkage");
+ else
+ error ("it must be the name of a function with "
+ "external linkage");
+ }
return NULL_TREE;
}
linkage = decl_linkage (fn_no_ptr);
if (cxx_dialect >= cxx11 ? linkage == lk_none : linkage != lk_external)
{
- if (cxx_dialect >= cxx11)
- error ("%qE is not a valid template argument for type %qT "
- "because %qD has no linkage",
- expr, type, fn_no_ptr);
- else
- error ("%qE is not a valid template argument for type %qT "
- "because %qD does not have external linkage",
- expr, type, fn_no_ptr);
+ if (complain & tf_error)
+ {
+ if (cxx_dialect >= cxx11)
+ error ("%qE is not a valid template argument for type %qT "
+ "because %qD has no linkage",
+ expr, type, fn_no_ptr);
+ else
+ error ("%qE is not a valid template argument for type %qT "
+ "because %qD does not have external linkage",
+ expr, type, fn_no_ptr);
+ }
return NULL_TREE;
}
@@ -5812,17 +5826,18 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
{
if (VAR_P (expr))
{
- error ("%qD is not a valid template argument "
- "because %qD is a variable, not the address of "
- "a variable",
- expr, expr);
+ if (complain & tf_error)
+ error ("%qD is not a valid template argument "
+ "because %qD is a variable, not the address of "
+ "a variable", expr, expr);
return NULL_TREE;
}
if (POINTER_TYPE_P (expr_type))
{
- error ("%qE is not a valid template argument for %qT "
- "because it is not the address of a variable",
- expr, type);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument for %qT "
+ "because it is not the address of a variable",
+ expr, type);
return NULL_TREE;
}
/* Other values, like integer constants, might be valid
@@ -5837,23 +5852,24 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
? TREE_OPERAND (expr, 0) : expr);
if (!VAR_P (decl))
{
- error ("%qE is not a valid template argument of type %qT "
- "because %qE is not a variable",
- expr, type, decl);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument of type %qT "
+ "because %qE is not a variable", expr, type, decl);
return NULL_TREE;
}
else if (cxx_dialect < cxx11 && !DECL_EXTERNAL_LINKAGE_P (decl))
{
- error ("%qE is not a valid template argument of type %qT "
- "because %qD does not have external linkage",
- expr, type, decl);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument of type %qT "
+ "because %qD does not have external linkage",
+ expr, type, decl);
return NULL_TREE;
}
else if (cxx_dialect >= cxx11 && decl_linkage (decl) == lk_none)
{
- error ("%qE is not a valid template argument of type %qT "
- "because %qD has no linkage",
- expr, type, decl);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument of type %qT "
+ "because %qD has no linkage", expr, type, decl);
return NULL_TREE;
}
}
@@ -5881,15 +5897,17 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
if (!at_least_as_qualified_p (TREE_TYPE (type), expr_type))
{
- error ("%qE is not a valid template argument for type %qT "
- "because of conflicts in cv-qualification", expr, type);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument for type %qT "
+ "because of conflicts in cv-qualification", expr, type);
return NULL_TREE;
}
if (!real_lvalue_p (expr))
{
- error ("%qE is not a valid template argument for type %qT "
- "because it is not an lvalue", expr, type);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is not an lvalue", expr, type);
return NULL_TREE;
}
@@ -5905,26 +5923,29 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
expr = TREE_OPERAND (expr, 0);
if (DECL_P (expr))
{
- error ("%q#D is not a valid template argument for type %qT "
- "because a reference variable does not have a constant "
- "address", expr, type);
+ if (complain & tf_error)
+ error ("%q#D is not a valid template argument for type %qT "
+ "because a reference variable does not have a constant "
+ "address", expr, type);
return NULL_TREE;
}
}
if (!DECL_P (expr))
{
- error ("%qE is not a valid template argument for type %qT "
- "because it is not an object with external linkage",
- expr, type);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is not an object with external linkage",
+ expr, type);
return NULL_TREE;
}
if (!DECL_EXTERNAL_LINKAGE_P (expr))
{
- error ("%qE is not a valid template argument for type %qT "
- "because object %qD has not external linkage",
- expr, type, expr);
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument for type %qT "
+ "because object %qD has not external linkage",
+ expr, type, expr);
return NULL_TREE;
}
@@ -5952,7 +5973,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
/* Null pointer values are OK in C++11. */
return perform_qualification_conversions (type, expr);
- expr = convert_nontype_argument_function (type, expr);
+ expr = convert_nontype_argument_function (type, expr, complain);
if (!expr || expr == error_mark_node)
return expr;
}
@@ -5966,13 +5987,17 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
{
if (TREE_CODE (expr) == ADDR_EXPR)
{
- error ("%qE is not a valid template argument for type %qT "
- "because it is a pointer", expr, type);
- inform (input_location, "try using %qE instead", TREE_OPERAND (expr, 0));
+ if (complain & tf_error)
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is a pointer", expr, type);
+ inform (input_location, "try using %qE instead",
+ TREE_OPERAND (expr, 0));
+ }
return NULL_TREE;
}
- expr = convert_nontype_argument_function (type, expr);
+ expr = convert_nontype_argument_function (type, expr, complain);
if (!expr || expr == error_mark_node)
return expr;
@@ -6006,13 +6031,16 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
provide a superior diagnostic. */
if (!same_type_p (TREE_TYPE (expr), type))
{
- error ("%qE is not a valid template argument for type %qT "
- "because it is of type %qT", expr, type,
- TREE_TYPE (expr));
- /* If we are just one standard conversion off, explain. */
- if (can_convert_standard (type, TREE_TYPE (expr), complain))
- inform (input_location,
- "standard conversions are not allowed in this context");
+ if (complain & tf_error)
+ {
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is of type %qT", expr, type,
+ TREE_TYPE (expr));
+ /* If we are just one standard conversion off, explain. */
+ if (can_convert_standard (type, TREE_TYPE (expr), complain))
+ inform (input_location,
+ "standard conversions are not allowed in this context");
+ }
return NULL_TREE;
}
}
@@ -6035,8 +6063,9 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
{
if (expr != nullptr_node)
{
- error ("%qE is not a valid template argument for type %qT "
- "because it is of type %qT", expr, type, TREE_TYPE (expr));
+ if (complain & tf_error)
+ error ("%qE is not a valid template argument for type %qT "
+ "because it is of type %qT", expr, type, TREE_TYPE (expr));
return NULL_TREE;
}
return expr;
@@ -6681,8 +6710,9 @@ coerce_template_parameter_pack (tree parms,
if (arg_idx - parm_idx < TREE_VEC_LENGTH (packed_args)
&& TREE_VEC_LENGTH (packed_args) > 0)
{
- error ("wrong number of template arguments (%d, should be %d)",
- arg_idx - parm_idx, TREE_VEC_LENGTH (packed_args));
+ if (complain & tf_error)
+ error ("wrong number of template arguments (%d, should be %d)",
+ arg_idx - parm_idx, TREE_VEC_LENGTH (packed_args));
return error_mark_node;
}
@@ -7181,7 +7211,7 @@ add_pending_template (tree d)
if (level)
push_tinst_level (d);
- pt = ggc_alloc_pending_template ();
+ pt = ggc_alloc<pending_template> ();
pt->next = NULL;
pt->tinst = current_tinst_level;
if (last_pending_template)
@@ -7811,7 +7841,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
elt.spec = t;
slot = htab_find_slot_with_hash (type_specializations,
&elt, hash, INSERT);
- entry = ggc_alloc_spec_entry ();
+ entry = ggc_alloc<spec_entry> ();
*entry = elt;
*slot = entry;
@@ -8236,7 +8266,7 @@ push_tinst_level (tree d)
if (limit_bad_template_recursion (d))
return 0;
- new_level = ggc_alloc_tinst_level ();
+ new_level = ggc_alloc<tinst_level> ();
new_level->decl = d;
new_level->locus = input_location;
new_level->errors = errorcount+sorrycount;
@@ -8916,6 +8946,9 @@ instantiate_class_template_1 (tree type)
push_deferring_access_checks (dk_no_deferred);
fn_context = decl_function_context (TYPE_MAIN_DECL (type));
+ /* Also avoid push_to_top_level for a lambda in an NSDMI. */
+ if (!fn_context && LAMBDA_TYPE_P (type) && TYPE_CLASS_SCOPE_P (type))
+ fn_context = error_mark_node;
if (!fn_context)
push_to_top_level ();
/* Use #pragma pack from the template context. */
@@ -10882,7 +10915,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* Set up DECL_TEMPLATE_INFO so that we can get at the
NSDMI in perform_member_init. Still set DECL_INITIAL
so that we know there is one. */
- DECL_INITIAL (r) = void_zero_node;
+ DECL_INITIAL (r) = void_node;
gcc_assert (DECL_LANG_SPECIFIC (r) == NULL);
retrofit_lang_decl (r);
DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
@@ -11293,8 +11326,42 @@ tsubst_function_type (tree t,
/* The TYPE_CONTEXT is not used for function/method types. */
gcc_assert (TYPE_CONTEXT (t) == NULL_TREE);
- /* Substitute the return type. */
- return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ /* DR 1227: Mixing immediate and non-immediate contexts in deduction
+ failure. */
+ bool late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (t);
+
+ if (late_return_type_p)
+ {
+ /* Substitute the argument types. */
+ arg_types = tsubst_arg_types (TYPE_ARG_TYPES (t), args, NULL_TREE,
+ complain, in_decl);
+ if (arg_types == error_mark_node)
+ return error_mark_node;
+
+ tree save_ccp = current_class_ptr;
+ tree save_ccr = current_class_ref;
+ tree this_type = (TREE_CODE (t) == METHOD_TYPE
+ ? TREE_TYPE (TREE_VALUE (arg_types)) : NULL_TREE);
+ bool do_inject = this_type && CLASS_TYPE_P (this_type);
+ if (do_inject)
+ {
+ /* DR 1207: 'this' is in scope in the trailing return type. */
+ inject_this_parameter (this_type, cp_type_quals (this_type));
+ }
+
+ /* Substitute the return type. */
+ return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+
+ if (do_inject)
+ {
+ current_class_ptr = save_ccp;
+ current_class_ref = save_ccr;
+ }
+ }
+ else
+ /* Substitute the return type. */
+ return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+
if (return_type == error_mark_node)
return error_mark_node;
/* DR 486 clarifies that creation of a function type with an
@@ -11315,11 +11382,14 @@ tsubst_function_type (tree t,
if (abstract_virtuals_error_sfinae (ACU_RETURN, return_type, complain))
return error_mark_node;
- /* Substitute the argument types. */
- arg_types = tsubst_arg_types (TYPE_ARG_TYPES (t), args, NULL_TREE,
- complain, in_decl);
- if (arg_types == error_mark_node)
- return error_mark_node;
+ if (!late_return_type_p)
+ {
+ /* Substitute the argument types. */
+ arg_types = tsubst_arg_types (TYPE_ARG_TYPES (t), args, NULL_TREE,
+ complain, in_decl);
+ if (arg_types == error_mark_node)
+ return error_mark_node;
+ }
/* Construct a new type node and return it. */
if (TREE_CODE (t) == FUNCTION_TYPE)
@@ -11355,6 +11425,9 @@ tsubst_function_type (tree t,
}
fntype = cp_build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
+ if (late_return_type_p)
+ TYPE_HAS_LATE_RETURN_TYPE (fntype) = 1;
+
return fntype;
}
@@ -12055,7 +12128,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (type == TREE_TYPE (t) && domain == TYPE_DOMAIN (t))
return t;
- /* These checks should match the ones in grokdeclarator.
+ /* These checks should match the ones in create_array_type_for_decl.
[temp.deduct]
@@ -12066,6 +12139,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
an abstract class type. */
if (VOID_TYPE_P (type)
|| TREE_CODE (type) == FUNCTION_TYPE
+ || (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_DOMAIN (type) == NULL_TREE)
|| TREE_CODE (type) == REFERENCE_TYPE)
{
if (complain & tf_error)
@@ -12257,6 +12332,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
break;
+ case VOID_CST:
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
@@ -12481,6 +12557,37 @@ tsubst_qualified_id (tree qualified_id, tree args,
return expr;
}
+/* tsubst the initializer for a VAR_DECL. INIT is the unsubstituted
+ initializer, DECL is the substituted VAR_DECL. Other arguments are as
+ for tsubst. */
+
+static tree
+tsubst_init (tree init, tree decl, tree args,
+ tsubst_flags_t complain, tree in_decl)
+{
+ if (!init)
+ return NULL_TREE;
+
+ init = tsubst_expr (init, args, complain, in_decl, false);
+
+ if (!init)
+ {
+ /* If we had an initializer but it
+ instantiated to nothing,
+ value-initialize the object. This will
+ only occur when the initializer was a
+ pack expansion where the parameter packs
+ used in that expansion were of length
+ zero. */
+ init = build_value_init (TREE_TYPE (decl),
+ complain);
+ if (TREE_CODE (init) == AGGR_INIT_EXPR)
+ init = get_target_expr_sfinae (init, complain);
+ }
+
+ return init;
+}
+
/* Like tsubst, but deals with expressions. This function just replaces
template parms; to finish processing the resultant expression, use
tsubst_copy_and_build or tsubst_expr. */
@@ -12505,7 +12612,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
/* We get here for a use of 'this' in an NSDMI. */
if (DECL_NAME (t) == this_identifier
- && at_function_scope_p ()
+ && current_function_decl
&& DECL_CONSTRUCTOR_P (current_function_decl))
return current_class_ptr;
@@ -12638,11 +12745,34 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
local static or constant. Building a new VAR_DECL
should be OK in all those cases. */
r = tsubst_decl (t, args, complain);
- if (decl_constant_var_p (r))
- /* A use of a local constant must decay to its value. */
- return integral_constant_value (r);
+ if (decl_maybe_constant_var_p (r))
+ {
+ /* We can't call cp_finish_decl, so handle the
+ initializer by hand. */
+ tree init = tsubst_init (DECL_INITIAL (t), r, args,
+ complain, in_decl);
+ if (!processing_template_decl)
+ init = maybe_constant_init (init);
+ if (processing_template_decl
+ ? potential_constant_expression (init)
+ : reduced_constant_expression_p (init))
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
+ = TREE_CONSTANT (r) = true;
+ DECL_INITIAL (r) = init;
+ }
gcc_assert (cp_unevaluated_operand || TREE_STATIC (r)
+ || decl_constant_var_p (r)
|| errorcount || sorrycount);
+ if (!processing_template_decl)
+ {
+ if (TREE_STATIC (r))
+ rest_of_decl_compilation (r, toplevel_bindings_p (),
+ at_eof);
+ else if (decl_constant_var_p (r))
+ /* A use of a local constant decays to its value.
+ FIXME update for core DR 696. */
+ return integral_constant_value (r);
+ }
return r;
}
}
@@ -12705,9 +12835,11 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case IMPLICIT_CONV_EXPR:
case CONVERT_EXPR:
case NOP_EXPR:
- return build1
- (code, tsubst (TREE_TYPE (t), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ return build1 (code, type, op0);
+ }
case SIZEOF_EXPR:
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
@@ -12775,9 +12907,11 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case REALPART_EXPR:
case IMAGPART_EXPR:
case PAREN_EXPR:
- return build1
- (code, tsubst (TREE_TYPE (t), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ return build1 (code, type, op0);
+ }
case COMPONENT_REF:
{
@@ -12851,24 +12985,26 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
- return build_nt
- (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
+ {
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ return build_nt (code, op0, op1);
+ }
case SCOPE_REF:
- return build_qualified_name (/*type=*/NULL_TREE,
- tsubst_copy (TREE_OPERAND (t, 0),
- args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1),
- args, complain, in_decl),
- QUALIFIED_NAME_IS_TEMPLATE (t));
+ {
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ return build_qualified_name (/*type=*/NULL_TREE, op0, op1,
+ QUALIFIED_NAME_IS_TEMPLATE (t));
+ }
case ARRAY_REF:
- return build_nt
- (ARRAY_REF,
- tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
- NULL_TREE, NULL_TREE);
+ {
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ return build_nt (ARRAY_REF, op0, op1, NULL_TREE, NULL_TREE);
+ }
case CALL_EXPR:
{
@@ -12886,29 +13022,29 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case PSEUDO_DTOR_EXPR:
case VEC_PERM_EXPR:
{
- r = build_nt
- (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ tree op2 = tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl);
+ r = build_nt (code, op0, op1, op2);
TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
return r;
}
case NEW_EXPR:
{
- r = build_nt
- (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ tree op2 = tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl);
+ r = build_nt (code, op0, op1, op2);
NEW_EXPR_USE_GLOBAL (r) = NEW_EXPR_USE_GLOBAL (t);
return r;
}
case DELETE_EXPR:
{
- r = build_nt
- (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ r = build_nt (code, op0, op1);
DELETE_EXPR_USE_GLOBAL (r) = DELETE_EXPR_USE_GLOBAL (t);
DELETE_EXPR_USE_VEC (r) = DELETE_EXPR_USE_VEC (t);
return r;
@@ -12988,10 +13124,11 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_unreachable ();
case VA_ARG_EXPR:
- return build_x_va_arg (EXPR_LOCATION (t),
- tsubst_copy (TREE_OPERAND (t, 0), args, complain,
- in_decl),
- tsubst (TREE_TYPE (t), args, complain, in_decl));
+ {
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ return build_x_va_arg (EXPR_LOCATION (t), op0, type);
+ }
case CLEANUP_POINT_EXPR:
/* We shouldn't have built any of these during initial template
@@ -13000,13 +13137,15 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_unreachable ();
case OFFSET_REF:
- r = build2
- (code, tsubst (TREE_TYPE (t), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
- PTRMEM_OK_P (r) = PTRMEM_OK_P (t);
- mark_used (TREE_OPERAND (r, 1));
- return r;
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+ tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
+ r = build2 (code, type, op0, op1);
+ PTRMEM_OK_P (r) = PTRMEM_OK_P (t);
+ mark_used (TREE_OPERAND (r, 1));
+ return r;
+ }
case EXPR_PACK_EXPANSION:
error ("invalid use of pack expansion expression");
@@ -13016,6 +13155,10 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
error ("use %<...%> to expand argument pack");
return error_mark_node;
+ case VOID_CST:
+ gcc_checking_assert (t == void_node && VOID_TYPE_P (TREE_TYPE (t)));
+ return t;
+
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
@@ -13241,10 +13384,12 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree initv,
cond = RECUR (TREE_VEC_ELT (OMP_FOR_COND (t), i));
incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
if (TREE_CODE (incr) == MODIFY_EXPR)
- incr = build_x_modify_expr (EXPR_LOCATION (incr),
- RECUR (TREE_OPERAND (incr, 0)), NOP_EXPR,
- RECUR (TREE_OPERAND (incr, 1)),
- complain);
+ {
+ tree lhs = RECUR (TREE_OPERAND (incr, 0));
+ tree rhs = RECUR (TREE_OPERAND (incr, 1));
+ incr = build_x_modify_expr (EXPR_LOCATION (incr), lhs,
+ NOP_EXPR, rhs, complain);
+ }
else
incr = RECUR (incr);
TREE_VEC_ELT (declv, i) = decl;
@@ -13290,9 +13435,11 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree initv,
}
cond = TREE_VEC_ELT (OMP_FOR_COND (t), i);
if (COMPARISON_CLASS_P (cond))
- cond = build2 (TREE_CODE (cond), boolean_type_node,
- RECUR (TREE_OPERAND (cond, 0)),
- RECUR (TREE_OPERAND (cond, 1)));
+ {
+ tree op0 = RECUR (TREE_OPERAND (cond, 0));
+ tree op1 = RECUR (TREE_OPERAND (cond, 1));
+ cond = build2 (TREE_CODE (cond), boolean_type_node, op0, op1);
+ }
else
cond = RECUR (cond);
incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
@@ -13310,11 +13457,12 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree initv,
|| TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR)
{
tree rhs = TREE_OPERAND (incr, 1);
- incr = build2 (MODIFY_EXPR, TREE_TYPE (decl),
- RECUR (TREE_OPERAND (incr, 0)),
+ tree lhs = RECUR (TREE_OPERAND (incr, 0));
+ tree rhs0 = RECUR (TREE_OPERAND (rhs, 0));
+ tree rhs1 = RECUR (TREE_OPERAND (rhs, 1));
+ incr = build2 (MODIFY_EXPR, TREE_TYPE (decl), lhs,
build2 (TREE_CODE (rhs), TREE_TYPE (decl),
- RECUR (TREE_OPERAND (rhs, 0)),
- RECUR (TREE_OPERAND (rhs, 1))));
+ rhs0, rhs1));
}
else
incr = RECUR (incr);
@@ -13334,11 +13482,12 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree initv,
|| (TREE_CODE (TREE_OPERAND (incr, 2)) == MINUS_EXPR)))
{
tree rhs = TREE_OPERAND (incr, 2);
- incr = build2 (MODIFY_EXPR, TREE_TYPE (decl),
- RECUR (TREE_OPERAND (incr, 0)),
+ tree lhs = RECUR (TREE_OPERAND (incr, 0));
+ tree rhs0 = RECUR (TREE_OPERAND (rhs, 0));
+ tree rhs1 = RECUR (TREE_OPERAND (rhs, 1));
+ incr = build2 (MODIFY_EXPR, TREE_TYPE (decl), lhs,
build2 (TREE_CODE (rhs), TREE_TYPE (decl),
- RECUR (TREE_OPERAND (rhs, 0)),
- RECUR (TREE_OPERAND (rhs, 1))));
+ rhs0, rhs1));
}
else
incr = RECUR (incr);
@@ -13493,26 +13642,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
init = cp_fname_init (name, &TREE_TYPE (decl));
}
else
- {
- tree t = RECUR (init);
-
- if (init && !t)
- {
- /* If we had an initializer but it
- instantiated to nothing,
- value-initialize the object. This will
- only occur when the initializer was a
- pack expansion where the parameter packs
- used in that expansion were of length
- zero. */
- init = build_value_init (TREE_TYPE (decl),
- complain);
- if (TREE_CODE (init) == AGGR_INIT_EXPR)
- init = get_target_expr_sfinae (init, complain);
- }
- else
- init = t;
- }
+ init = tsubst_init (init, decl, args, complain, in_decl);
if (VAR_P (decl))
const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P
@@ -13616,9 +13746,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
break;
case CASE_LABEL_EXPR:
- finish_case_label (EXPR_LOCATION (t),
- RECUR (CASE_LOW (t)),
- RECUR (CASE_HIGH (t)));
+ {
+ tree low = RECUR (CASE_LOW (t));
+ tree high = RECUR (CASE_HIGH (t));
+ finish_case_label (EXPR_LOCATION (t), low, high);
+ }
break;
case LABEL_EXPR:
@@ -13645,14 +13777,18 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
break;
case ASM_EXPR:
- tmp = finish_asm_stmt
- (ASM_VOLATILE_P (t),
- RECUR (ASM_STRING (t)),
- tsubst_copy_asm_operands (ASM_OUTPUTS (t), args, complain, in_decl),
- tsubst_copy_asm_operands (ASM_INPUTS (t), args, complain, in_decl),
- tsubst_copy_asm_operands (ASM_CLOBBERS (t), args, complain, in_decl),
- tsubst_copy_asm_operands (ASM_LABELS (t), args, complain, in_decl));
{
+ tree string = RECUR (ASM_STRING (t));
+ tree outputs = tsubst_copy_asm_operands (ASM_OUTPUTS (t), args,
+ complain, in_decl);
+ tree inputs = tsubst_copy_asm_operands (ASM_INPUTS (t), args,
+ complain, in_decl);
+ tree clobbers = tsubst_copy_asm_operands (ASM_CLOBBERS (t), args,
+ complain, in_decl);
+ tree labels = tsubst_copy_asm_operands (ASM_LABELS (t), args,
+ complain, in_decl);
+ tmp = finish_asm_stmt (ASM_VOLATILE_P (t), string, outputs, inputs,
+ clobbers, labels);
tree asm_expr = tmp;
if (TREE_CODE (asm_expr) == CLEANUP_POINT_EXPR)
asm_expr = TREE_OPERAND (asm_expr, 0);
@@ -13949,8 +14085,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
break;
case MUST_NOT_THROW_EXPR:
- RETURN (build_must_not_throw_expr (RECUR (TREE_OPERAND (t, 0)),
- RECUR (MUST_NOT_THROW_COND (t))));
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree cond = RECUR (MUST_NOT_THROW_COND (t));
+ RETURN (build_must_not_throw_expr (op0, cond));
+ }
case EXPR_PACK_EXPANSION:
error ("invalid use of pack expansion expression");
@@ -14217,9 +14356,11 @@ tsubst_copy_and_build (tree t,
}
case NOP_EXPR:
- RETURN (build_nop
- (tsubst (TREE_TYPE (t), args, complain, in_decl),
- RECUR (TREE_OPERAND (t, 0))));
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ RETURN (build_nop (type, op0));
+ }
case IMPLICIT_CONV_EXPR:
{
@@ -14233,10 +14374,11 @@ tsubst_copy_and_build (tree t,
}
case CONVERT_EXPR:
- RETURN (build1
- (CONVERT_EXPR,
- tsubst (TREE_TYPE (t), args, complain, in_decl),
- RECUR (TREE_OPERAND (t, 0))));
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ RETURN (build1 (CONVERT_EXPR, type, op0));
+ }
case CAST_EXPR:
case REINTERPRET_CAST_EXPR:
@@ -14301,12 +14443,12 @@ tsubst_copy_and_build (tree t,
case REALPART_EXPR:
case IMAGPART_EXPR:
RETURN (build_x_unary_op (input_location, TREE_CODE (t),
- RECUR (TREE_OPERAND (t, 0)),
+ RECUR (TREE_OPERAND (t, 0)),
complain|decltype_flag));
case FIX_TRUNC_EXPR:
RETURN (cp_build_unary_op (FIX_TRUNC_EXPR, RECUR (TREE_OPERAND (t, 0)),
- 0, complain));
+ 0, complain));
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
@@ -14356,13 +14498,15 @@ tsubst_copy_and_build (tree t,
{
warning_sentinel s1(warn_type_limits);
warning_sentinel s2(warn_div_by_zero);
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree op1 = RECUR (TREE_OPERAND (t, 1));
tree r = build_x_binary_op
(input_location, TREE_CODE (t),
- RECUR (TREE_OPERAND (t, 0)),
+ op0,
(TREE_NO_WARNING (TREE_OPERAND (t, 0))
? ERROR_MARK
: TREE_CODE (TREE_OPERAND (t, 0))),
- RECUR (TREE_OPERAND (t, 1)),
+ op1,
(TREE_NO_WARNING (TREE_OPERAND (t, 1))
? ERROR_MARK
: TREE_CODE (TREE_OPERAND (t, 1))),
@@ -14375,8 +14519,11 @@ tsubst_copy_and_build (tree t,
}
case POINTER_PLUS_EXPR:
- return fold_build_pointer_plus (RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)));
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree op1 = RECUR (TREE_OPERAND (t, 1));
+ return fold_build_pointer_plus (op0, op1);
+ }
case SCOPE_REF:
RETURN (tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
@@ -14486,11 +14633,10 @@ tsubst_copy_and_build (tree t,
case MODOP_EXPR:
{
warning_sentinel s(warn_div_by_zero);
+ tree lhs = RECUR (TREE_OPERAND (t, 0));
+ tree rhs = RECUR (TREE_OPERAND (t, 2));
tree r = build_x_modify_expr
- (EXPR_LOCATION (t),
- RECUR (TREE_OPERAND (t, 0)),
- TREE_CODE (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2)),
+ (EXPR_LOCATION (t), lhs, TREE_CODE (TREE_OPERAND (t, 1)), rhs,
complain|decltype_flag);
/* TREE_NO_WARNING must be set if either the expression was
parenthesized or it uses an operator such as >>= rather
@@ -14540,7 +14686,7 @@ tsubst_copy_and_build (tree t,
else
{
init_vec = make_tree_vector ();
- if (init == void_zero_node)
+ if (init == void_node)
gcc_assert (init_vec != NULL);
else
{
@@ -14549,10 +14695,9 @@ tsubst_copy_and_build (tree t,
}
}
- ret = build_new (&placement_vec,
- tsubst (TREE_OPERAND (t, 1), args, complain, in_decl),
- RECUR (TREE_OPERAND (t, 2)),
- &init_vec,
+ tree op1 = tsubst (TREE_OPERAND (t, 1), args, complain, in_decl);
+ tree op2 = RECUR (TREE_OPERAND (t, 2));
+ ret = build_new (&placement_vec, op1, op2, &init_vec,
NEW_EXPR_USE_GLOBAL (t),
complain);
@@ -14565,12 +14710,14 @@ tsubst_copy_and_build (tree t,
}
case DELETE_EXPR:
- RETURN (delete_sanity
- (RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)),
- DELETE_EXPR_USE_VEC (t),
- DELETE_EXPR_USE_GLOBAL (t),
- complain));
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree op1 = RECUR (TREE_OPERAND (t, 1));
+ RETURN (delete_sanity (op0, op1,
+ DELETE_EXPR_USE_VEC (t),
+ DELETE_EXPR_USE_GLOBAL (t),
+ complain));
+ }
case COMPOUND_EXPR:
{
@@ -14837,11 +14984,13 @@ tsubst_copy_and_build (tree t,
}
case PSEUDO_DTOR_EXPR:
- RETURN (finish_pseudo_destructor_expr
- (RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)),
- tsubst (TREE_OPERAND (t, 2), args, complain, in_decl),
- input_location));
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree op1 = RECUR (TREE_OPERAND (t, 1));
+ tree op2 = tsubst (TREE_OPERAND (t, 2), args, complain, in_decl);
+ RETURN (finish_pseudo_destructor_expr (op0, op1, op2,
+ input_location));
+ }
case TREE_LIST:
{
@@ -15165,9 +15314,11 @@ tsubst_copy_and_build (tree t,
}
case VA_ARG_EXPR:
- RETURN (build_x_va_arg (EXPR_LOCATION (t),
- RECUR (TREE_OPERAND (t, 0)),
- tsubst (TREE_TYPE (t), args, complain, in_decl)));
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ RETURN (build_x_va_arg (EXPR_LOCATION (t), op0, type));
+ }
case OFFSETOF_EXPR:
RETURN (finish_offsetof (RECUR (TREE_OPERAND (t, 0))));
@@ -15196,9 +15347,9 @@ tsubst_copy_and_build (tree t,
cur_stmt_expr = old_stmt_expr;
/* If the resulting list of expression statement is empty,
- fold it further into void_zero_node. */
+ fold it further into void_node. */
if (empty_expr_stmt_p (stmt_expr))
- stmt_expr = void_zero_node;
+ stmt_expr = void_node;
RETURN (stmt_expr);
}
@@ -15276,11 +15427,13 @@ tsubst_copy_and_build (tree t,
RETURN (finish_parenthesized_expr (RECUR (TREE_OPERAND (t, 0))));
case VEC_PERM_EXPR:
- RETURN (build_x_vec_perm_expr (input_location,
- RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2)),
- complain));
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree op1 = RECUR (TREE_OPERAND (t, 1));
+ tree op2 = RECUR (TREE_OPERAND (t, 2));
+ RETURN (build_x_vec_perm_expr (input_location, op0, op1, op2,
+ complain));
+ }
default:
/* Handle Objective-C++ constructs, if appropriate. */
@@ -19587,6 +19740,11 @@ instantiate_decl (tree d, int defer_ok,
if (external_p && !always_instantiate_p (d))
return d;
+ /* Any local class members should be instantiated from the TAG_DEFN
+ with defer_ok == 0. */
+ gcc_checking_assert (!defer_ok || !decl_function_context (d)
+ || LAMBDA_TYPE_P (DECL_CONTEXT (d)));
+
gen_tmpl = most_general_template (tmpl);
gen_args = DECL_TI_ARGS (d);
@@ -21483,9 +21641,11 @@ build_non_dependent_expr (tree expr)
cannot be used to initialize a "char *". */
if (TREE_CODE (expr) == STRING_CST)
return expr;
- /* Preserve arithmetic constants, as an optimization -- there is no
+ /* Preserve void and arithmetic constants, as an optimization -- there is no
reason to create a new node. */
- if (TREE_CODE (expr) == INTEGER_CST || TREE_CODE (expr) == REAL_CST)
+ if (TREE_CODE (expr) == VOID_CST
+ || TREE_CODE (expr) == INTEGER_CST
+ || TREE_CODE (expr) == REAL_CST)
return expr;
/* Preserve THROW_EXPRs -- all throw-expressions have type "void".
There is at least one place where we want to know that a
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index e9e2c44faf7..b665a8d245f 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "tm_p.h"
#include "stringpool.h"
#include "stor-layout.h"
#include "cp-tree.h"
@@ -1596,6 +1597,12 @@ emit_tinfo_decl (tree decl)
DECL_INITIAL (decl) = init;
mark_used (decl);
cp_finish_decl (decl, init, false, NULL_TREE, 0);
+ /* Avoid targets optionally bumping up the alignment to improve
+ vector instruction accesses, tinfo are never accessed this way. */
+#ifdef DATA_ABI_ALIGNMENT
+ DECL_ALIGN (decl) = DATA_ABI_ALIGNMENT (decl, TYPE_ALIGN (TREE_TYPE (decl)));
+ DECL_USER_ALIGN (decl) = true;
+#endif
return true;
}
else
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index c3eed90f6c3..424b26cd3e1 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -917,9 +917,11 @@ accessible_p (tree type, tree decl, bool consider_local_p)
/* Figure out where the reference is occurring. Check to see if
DECL is private or protected in this scope, since that will
determine whether protected access is allowed. */
- if (current_class_type)
+ tree ct = current_nonlambda_class_type ();
+ if (ct)
protected_ok = protected_accessible_p (decl,
- current_class_type, binfo);
+ ct,
+ binfo);
/* Now, loop through the classes of which we are a friend. */
if (!protected_ok)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 4afb821de06..21920b41ca5 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify.h"
#include "bitmap.h"
#include "omp-low.h"
+#include "builtins.h"
static bool verify_constant (tree, bool, bool *, bool *);
#define VERIFY_CONSTANT(X) \
@@ -1083,7 +1084,7 @@ finish_break_stmt (void)
block_may_fallthru returns true when given something it does not
understand. */
if (!block_may_fallthru (cur_stmt_list))
- return void_zero_node;
+ return void_node;
return add_stmt (build_stmt (input_location, BREAK_STMT));
}
@@ -1675,7 +1676,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
object = maybe_dummy_object (scope, NULL);
}
- object = maybe_resolve_dummy (object);
+ object = maybe_resolve_dummy (object, true);
if (object == error_mark_node)
return error_mark_node;
@@ -1835,10 +1836,11 @@ check_accessibility_of_qualified_id (tree decl,
/* If the reference is to a non-static member of the
current class, treat it as if it were referenced through
`this'. */
+ tree ct;
if (DECL_NONSTATIC_MEMBER_P (decl)
&& current_class_ptr
- && DERIVED_FROM_P (scope, current_class_type))
- qualifying_type = current_class_type;
+ && DERIVED_FROM_P (scope, ct = current_nonlambda_class_type ()))
+ qualifying_type = ct;
/* Otherwise, use the type indicated by the
nested-name-specifier. */
else
@@ -2095,7 +2097,7 @@ empty_expr_stmt_p (tree expr_stmt)
{
tree body = NULL_TREE;
- if (expr_stmt == void_zero_node)
+ if (expr_stmt == void_node)
return true;
if (expr_stmt)
@@ -2434,7 +2436,7 @@ finish_this_expr (void)
/* In a lambda expression, 'this' refers to the captured 'this'. */
if (LAMBDA_TYPE_P (type))
- result = lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (type));
+ result = lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (type), true);
else
result = current_class_ptr;
}
@@ -3166,12 +3168,7 @@ finish_id_expression (tree id_expression,
else if (TREE_STATIC (decl)
/* It's not a use (3.2) if we're in an unevaluated context. */
|| cp_unevaluated_operand)
- {
- if (processing_template_decl)
- /* For a use of an outer static/unevaluated var, return the id
- so that we'll look it up again in the instantiation. */
- return id_expression;
- }
+ /* OK */;
else
{
tree context = DECL_CONTEXT (decl);
@@ -3190,13 +3187,13 @@ finish_id_expression (tree id_expression,
the complexity of the problem"
FIXME update for final resolution of core issue 696. */
- if (decl_constant_var_p (decl))
+ if (decl_maybe_constant_var_p (decl))
{
if (processing_template_decl)
/* In a template, the constant value may not be in a usable
- form, so look it up again at instantiation time. */
- return id_expression;
- else
+ form, so wait until instantiation time. */
+ return decl;
+ else if (decl_constant_var_p (decl))
return integral_constant_value (decl);
}
@@ -5222,7 +5219,7 @@ finish_omp_clauses (tree clauses)
{
bitmap_head generic_head, firstprivate_head, lastprivate_head;
bitmap_head aligned_head;
- tree c, t, *pc = &clauses;
+ tree c, t, *pc;
bool branch_seen = false;
bool copyprivate_seen = false;
@@ -8024,7 +8021,7 @@ register_constexpr_fundef (tree fun, tree body)
htab_find_slot (constexpr_fundef_table, &entry, INSERT);
gcc_assert (*slot == NULL);
- *slot = ggc_alloc_constexpr_fundef ();
+ *slot = ggc_alloc<constexpr_fundef> ();
**slot = entry;
return fun;
@@ -8158,8 +8155,10 @@ maybe_initialize_constexpr_call_table (void)
bool
is_this_parameter (tree t)
{
- return (TREE_CODE (t) == PARM_DECL
- && DECL_NAME (t) == this_identifier);
+ if (!DECL_P (t) || DECL_NAME (t) != this_identifier)
+ return false;
+ gcc_assert (TREE_CODE (t) == PARM_DECL || is_capture_proxy (t));
+ return true;
}
/* We have an expression tree T that represents a call, either CALL_EXPR
@@ -8466,7 +8465,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
{
/* We need to keep a pointer to the entry, not just the slot, as the
slot can move in the call to cxx_eval_builtin_function_call. */
- *slot = entry = ggc_alloc_constexpr_call ();
+ *slot = entry = ggc_alloc<constexpr_call> ();
*entry = new_call;
}
/* Calls which are in progress have their result set to NULL
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index e14002482be..587ae80bcc1 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1257,6 +1257,8 @@ strip_typedefs (tree t)
if (TYPE_RAISES_EXCEPTIONS (t))
result = build_exception_variant (result,
TYPE_RAISES_EXCEPTIONS (t));
+ if (TYPE_HAS_LATE_RETURN_TYPE (t))
+ TYPE_HAS_LATE_RETURN_TYPE (result) = 1;
}
break;
case TYPENAME_TYPE:
@@ -2620,6 +2622,11 @@ cp_tree_equal (tree t1, tree t2)
switch (code1)
{
+ case VOID_CST:
+ /* There's only a single VOID_CST node, so we should never reach
+ here. */
+ gcc_unreachable ();
+
case INTEGER_CST:
return tree_int_cst_equal (t1, t2);
@@ -2947,7 +2954,7 @@ member_p (const_tree decl)
tree
build_dummy_object (tree type)
{
- tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_zero_node);
+ tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_node);
return cp_build_indirect_ref (decl, RO_NULL, tf_warning_or_error);
}
@@ -2997,7 +3004,7 @@ is_dummy_object (const_tree ob)
if (INDIRECT_REF_P (ob))
ob = TREE_OPERAND (ob, 0);
return (TREE_CODE (ob) == NOP_EXPR
- && TREE_OPERAND (ob, 0) == void_zero_node);
+ && TREE_OPERAND (ob, 0) == void_node);
}
/* Returns 1 iff type T is something we want to treat as a scalar type for
@@ -3775,7 +3782,7 @@ stabilize_expr (tree exp, tree* initp)
else if (VOID_TYPE_P (TREE_TYPE (exp)))
{
init_expr = exp;
- exp = void_zero_node;
+ exp = void_node;
}
/* There are no expressions with REFERENCE_TYPE, but there can be call
arguments with such a type; just treat it as a pointer. */
@@ -3785,6 +3792,10 @@ stabilize_expr (tree exp, tree* initp)
{
init_expr = get_target_expr (exp);
exp = TARGET_EXPR_SLOT (init_expr);
+ if (CLASS_TYPE_P (TREE_TYPE (exp)))
+ exp = move (exp);
+ else
+ exp = rvalue (exp);
}
else
{
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 7b28a9a5869..aa96fb49318 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -818,6 +818,7 @@ merge_types (tree t1, tree t2)
tree p2 = TYPE_ARG_TYPES (t2);
tree parms;
tree rval, raises;
+ bool late_return_type_p = TYPE_HAS_LATE_RETURN_TYPE (t1);
/* Save space: see if the result is identical to one of the args. */
if (valtype == TREE_TYPE (t1) && ! p2)
@@ -842,6 +843,8 @@ merge_types (tree t1, tree t2)
raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1),
TYPE_RAISES_EXCEPTIONS (t2));
t1 = build_exception_variant (rval, raises);
+ if (late_return_type_p)
+ TYPE_HAS_LATE_RETURN_TYPE (t1) = 1;
break;
}
@@ -854,6 +857,8 @@ merge_types (tree t1, tree t2)
TYPE_RAISES_EXCEPTIONS (t2));
cp_ref_qualifier rqual = type_memfn_rqual (t1);
tree t3;
+ bool late_return_type_1_p = TYPE_HAS_LATE_RETURN_TYPE (t1);
+ bool late_return_type_2_p = TYPE_HAS_LATE_RETURN_TYPE (t2);
/* If this was a member function type, get back to the
original type of type member function (i.e., without
@@ -867,6 +872,10 @@ merge_types (tree t1, tree t2)
TYPE_ARG_TYPES (t3));
t1 = build_exception_variant (t3, raises);
t1 = build_ref_qualified_type (t1, rqual);
+ if (late_return_type_1_p)
+ TYPE_HAS_LATE_RETURN_TYPE (t1) = 1;
+ if (late_return_type_2_p)
+ TYPE_HAS_LATE_RETURN_TYPE (t2) = 1;
break;
}
@@ -1452,11 +1461,8 @@ at_least_as_qualified_p (const_tree type1, const_tree type2)
more cv-qualified that TYPE1, and 0 otherwise. */
int
-comp_cv_qualification (const_tree type1, const_tree type2)
+comp_cv_qualification (int q1, int q2)
{
- int q1 = cp_type_quals (type1);
- int q2 = cp_type_quals (type2);
-
if (q1 == q2)
return 0;
@@ -1468,6 +1474,14 @@ comp_cv_qualification (const_tree type1, const_tree type2)
return 0;
}
+int
+comp_cv_qualification (const_tree type1, const_tree type2)
+{
+ int q1 = cp_type_quals (type1);
+ int q2 = cp_type_quals (type2);
+ return comp_cv_qualification (q1, q2);
+}
+
/* Returns 1 if the cv-qualification signature of TYPE1 is a proper
subset of the cv-qualification signature of TYPE2, and the types
are similar. Returns -1 if the other way 'round, and 0 otherwise. */
@@ -3248,6 +3262,12 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
&& !TYPE_POLYMORPHIC_P (basetype)
&& resolves_to_fixed_type_p (instance_ptr, 0));
+ /* If we don't really have an object (i.e. in an ill-formed
+ conversion from PMF to pointer), we can't resolve virtual
+ functions anyway. */
+ if (!nonvirtual && is_dummy_object (instance_ptr))
+ nonvirtual = true;
+
if (TREE_SIDE_EFFECTS (instance_ptr))
instance_ptr = instance_save_expr = save_expr (instance_ptr);
@@ -8094,6 +8114,14 @@ convert_for_assignment (tree type, tree rhs,
default:
gcc_unreachable();
}
+ if (TYPE_PTR_P (rhstype)
+ && TYPE_PTR_P (type)
+ && CLASS_TYPE_P (TREE_TYPE (rhstype))
+ && CLASS_TYPE_P (TREE_TYPE (type))
+ && !COMPLETE_TYPE_P (TREE_TYPE (rhstype)))
+ inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL
+ (TREE_TYPE (rhstype))),
+ "class type %qT is incomplete", TREE_TYPE (rhstype));
}
return error_mark_node;
}
@@ -8405,7 +8433,7 @@ check_return_expr (tree retval, bool *no_warning)
else
{
if (!retval)
- retval = void_zero_node;
+ retval = void_node;
auto_node = type_uses_auto (current_function_auto_return_pattern);
type = do_auto_deduction (current_function_auto_return_pattern,
retval, auto_node);
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 1d8b78278bf..18bc25f766d 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -294,7 +294,7 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use,
slot = htab_find_slot_with_hash (abstract_pending_vars, type,
(hashval_t)TYPE_UID (type), INSERT);
- pat = ggc_alloc_pending_abstract_type ();
+ pat = ggc_alloc<pending_abstract_type> ();
pat->type = type;
pat->decl = decl;
pat->use = use;
@@ -429,6 +429,28 @@ abstract_virtuals_error (abstract_class_use use, tree type)
return abstract_virtuals_error_sfinae (use, type, tf_warning_or_error);
}
+/* Print an inform about the declaration of the incomplete type TYPE. */
+
+void
+cxx_incomplete_type_inform (const_tree type)
+{
+ if (!TYPE_MAIN_DECL (type))
+ return;
+
+ location_t loc = DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type));
+ tree ptype = strip_top_quals (CONST_CAST_TREE (type));
+
+ if (current_class_type
+ && TYPE_BEING_DEFINED (current_class_type)
+ && same_type_p (ptype, current_class_type))
+ inform (loc, "definition of %q#T is not complete until "
+ "the closing brace", ptype);
+ else if (!TYPE_TEMPLATE_INFO (ptype))
+ inform (loc, "forward declaration of %q#T", ptype);
+ else
+ inform (loc, "declaration of %q#T", ptype);
+}
+
/* Print an error message for invalid use of an incomplete type.
VALUE is the expression that was used (or 0 if that isn't known)
and TYPE is the type that was invalid. DIAG_KIND indicates the
@@ -438,7 +460,7 @@ void
cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
diagnostic_t diag_kind)
{
- int decl = 0;
+ bool is_decl = false, complained = false;
gcc_assert (diag_kind == DK_WARNING
|| diag_kind == DK_PEDWARN
@@ -452,10 +474,10 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
|| TREE_CODE (value) == PARM_DECL
|| TREE_CODE (value) == FIELD_DECL))
{
- emit_diagnostic (diag_kind, input_location, 0,
- "%q+D has incomplete type", value);
- decl = 1;
- }
+ complained = emit_diagnostic (diag_kind, input_location, 0,
+ "%q+D has incomplete type", value);
+ is_decl = true;
+ }
retry:
/* We must print an error message. Be clever about what it says. */
@@ -464,15 +486,12 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
- if (!decl)
- emit_diagnostic (diag_kind, input_location, 0,
- "invalid use of incomplete type %q#T", type);
- if (!TYPE_TEMPLATE_INFO (type))
- emit_diagnostic (diag_kind, input_location, 0,
- "forward declaration of %q+#T", type);
- else
- emit_diagnostic (diag_kind, input_location, 0,
- "declaration of %q+#T", type);
+ if (!is_decl)
+ complained = emit_diagnostic (diag_kind, input_location, 0,
+ "invalid use of incomplete type %q#T",
+ type);
+ if (complained)
+ cxx_incomplete_type_inform (type);
break;
case VOID_TYPE:
@@ -1098,6 +1117,22 @@ digest_init_flags (tree type, tree init, int flags)
{
return digest_init_r (type, init, false, flags, tf_warning_or_error);
}
+
+/* Process the initializer INIT for an NSDMI DECL (a FIELD_DECL). */
+tree
+digest_nsdmi_init (tree decl, tree init)
+{
+ gcc_assert (TREE_CODE (decl) == FIELD_DECL);
+
+ int flags = LOOKUP_IMPLICIT;
+ if (DIRECT_LIST_INIT_P (init))
+ flags = LOOKUP_NORMAL;
+ init = digest_init_flags (TREE_TYPE (decl), init, flags);
+ if (TREE_CODE (init) == TARGET_EXPR)
+ /* This represents the whole initialization. */
+ TARGET_EXPR_DIRECT_INIT_P (init) = true;
+ return init;
+}
/* Set of flags used within process_init_constructor to describe the
initializers. */
@@ -1856,7 +1891,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
if (parms == NULL_TREE)
{
if (VOID_TYPE_P (type))
- return void_zero_node;
+ return void_node;
return build_value_init (cv_unqualified (type), complain);
}
diff --git a/gcc/dbgcnt.def b/gcc/dbgcnt.def
index 6f8f675e540..0edc72a8941 100644
--- a/gcc/dbgcnt.def
+++ b/gcc/dbgcnt.def
@@ -150,6 +150,7 @@ DEBUG_COUNTER (dce)
DEBUG_COUNTER (dce_fast)
DEBUG_COUNTER (dce_ud)
DEBUG_COUNTER (delete_trivial_dead)
+DEBUG_COUNTER (devirt)
DEBUG_COUNTER (df_byte_scan)
DEBUG_COUNTER (dse)
DEBUG_COUNTER (dse1)
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index e6c98850063..6cb43411917 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -976,7 +976,7 @@ dbxout_init (const char *input_file_name)
const char *mapped_name;
typevec_len = 100;
- typevec = ggc_alloc_cleared_vec_typeinfo (typevec_len);
+ typevec = ggc_cleared_vec_alloc<typeinfo> (typevec_len);
/* stabstr_ob contains one string, which will be just fine with
1-byte alignment. */
diff --git a/gcc/df-scan.c b/gcc/df-scan.c
index 0b5b4374b7f..992d0aff414 100644
--- a/gcc/df-scan.c
+++ b/gcc/df-scan.c
@@ -3385,10 +3385,13 @@ df_get_call_refs (struct df_collection_rec *collection_rec,
bool is_sibling_call;
unsigned int i;
HARD_REG_SET defs_generated;
+ HARD_REG_SET fn_reg_set_usage;
CLEAR_HARD_REG_SET (defs_generated);
df_find_hard_reg_defs (PATTERN (insn_info->insn), &defs_generated);
is_sibling_call = SIBLING_CALL_P (insn_info->insn);
+ get_call_reg_set_usage (insn_info->insn, &fn_reg_set_usage,
+ regs_invalidated_by_call);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
@@ -3412,7 +3415,7 @@ df_get_call_refs (struct df_collection_rec *collection_rec,
NULL, bb, insn_info, DF_REF_REG_DEF, flags);
}
}
- else if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i)
+ else if (TEST_HARD_REG_BIT (fn_reg_set_usage, i)
/* no clobbers for regs that are the result of the call */
&& !TEST_HARD_REG_BIT (defs_generated, i)
&& (!is_sibling_call
diff --git a/gcc/doc/arm-neon-intrinsics.texi b/gcc/doc/arm-neon-intrinsics.texi
index 67f84e096a7..56987e4a686 100644
--- a/gcc/doc/arm-neon-intrinsics.texi
+++ b/gcc/doc/arm-neon-intrinsics.texi
@@ -2,8 +2,6 @@
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
-@c This file is generated automatically using gcc/config/arm/neon-docgen.ml
-@c Please do not edit manually.
@subsubsection Addition
@itemize @bullet
diff --git a/gcc/doc/avr-mmcu.texi b/gcc/doc/avr-mmcu.texi
index 175407b095c..d634716dd32 100644
--- a/gcc/doc/avr-mmcu.texi
+++ b/gcc/doc/avr-mmcu.texi
@@ -18,7 +18,7 @@
@item avr25
``Classic'' devices with up to 8@tie{}KiB of program memory and with the @code{MOVW} instruction.
-@*@var{mcu}@tie{}= @code{ata5272}, @code{ata6289}, @code{attiny13}, @code{attiny13a}, @code{attiny2313}, @code{attiny2313a}, @code{attiny24}, @code{attiny24a}, @code{attiny25}, @code{attiny261}, @code{attiny261a}, @code{attiny43u}, @code{attiny4313}, @code{attiny44}, @code{attiny44a}, @code{attiny45}, @code{attiny461}, @code{attiny461a}, @code{attiny48}, @code{attiny84}, @code{attiny84a}, @code{attiny85}, @code{attiny861}, @code{attiny861a}, @code{attiny87}, @code{attiny88}, @code{at86rf401}.
+@*@var{mcu}@tie{}= @code{ata5272}, @code{attiny13}, @code{attiny13a}, @code{attiny2313}, @code{attiny2313a}, @code{attiny24}, @code{attiny24a}, @code{attiny25}, @code{attiny261}, @code{attiny261a}, @code{attiny43u}, @code{attiny4313}, @code{attiny44}, @code{attiny44a}, @code{attiny45}, @code{attiny461}, @code{attiny461a}, @code{attiny48}, @code{attiny84}, @code{attiny84a}, @code{attiny85}, @code{attiny861}, @code{attiny861a}, @code{attiny87}, @code{attiny88}, @code{at86rf401}.
@item avr3
``Classic'' devices with 16@tie{}KiB up to 64@tie{}KiB of program memory.
@@ -34,7 +34,7 @@
@item avr4
``Enhanced'' devices with up to 8@tie{}KiB of program memory.
-@*@var{mcu}@tie{}= @code{ata6285}, @code{ata6286}, @code{atmega48}, @code{atmega48a}, @code{atmega48p}, @code{atmega48pa}, @code{atmega8}, @code{atmega8a}, @code{atmega8hva}, @code{atmega8515}, @code{atmega8535}, @code{atmega88}, @code{atmega88a}, @code{atmega88p}, @code{atmega88pa}, @code{at90pwm1}, @code{at90pwm2}, @code{at90pwm2b}, @code{at90pwm3}, @code{at90pwm3b}, @code{at90pwm81}.
+@*@var{mcu}@tie{}= @code{ata6285}, @code{ata6286}, @code{ata6289}, @code{atmega48}, @code{atmega48a}, @code{atmega48p}, @code{atmega48pa}, @code{atmega8}, @code{atmega8a}, @code{atmega8hva}, @code{atmega8515}, @code{atmega8535}, @code{atmega88}, @code{atmega88a}, @code{atmega88p}, @code{atmega88pa}, @code{at90pwm1}, @code{at90pwm2}, @code{at90pwm2b}, @code{at90pwm3}, @code{at90pwm3b}, @code{at90pwm81}.
@item avr5
``Enhanced'' devices with 16@tie{}KiB up to 64@tie{}KiB of program memory.
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 9780d923804..23a7809063e 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -55,6 +55,7 @@ extensions, accepted by GCC in C90 mode and in C++.
* Mixed Declarations:: Mixing declarations and code.
* Function Attributes:: Declaring that functions have no side effects,
or that they can never return.
+* Label Attributes:: Specifying attributes on labels.
* Attribute Syntax:: Formal syntax for attributes.
* Function Prototypes:: Prototype declarations and old-style definitions.
* C++ Comments:: C++ comments are recognized.
@@ -65,11 +66,7 @@ extensions, accepted by GCC in C90 mode and in C++.
* Alignment:: Inquiring about the alignment of a type or variable.
* Inline:: Defining inline functions (as fast as macros).
* Volatiles:: What constitutes an access to a volatile object.
-* Extended Asm:: Assembler instructions with C expressions as operands.
- (With them you can define ``built-in'' functions.)
-* Constraints:: Constraints for asm operands
-* Asm Labels:: Specifying the assembler name to use for a C symbol.
-* Explicit Reg Vars:: Defining variables residing in specified registers.
+* Using Assembly Language with C:: Instructions and extensions for interfacing C with assembler.
* Alternate Keywords:: @code{__const__}, @code{__asm__}, etc., for header files.
* Incomplete Enums:: @code{enum foo;}, with details to follow.
* Function Names:: Printable strings which are the name of the current
@@ -376,6 +373,8 @@ goto *(&&foo + array[i]);
This is more friendly to code living in shared libraries, as it reduces
the number of dynamic relocations that are needed, and by consequence,
allows the data to be read-only.
+This alternative with label differences is not supported for the AVR target,
+please use the first approach for AVR programs.
The @code{&&foo} expressions for the same label might have different
values if the containing function is inlined or cloned. If a program
@@ -2185,7 +2184,8 @@ attributes are currently defined for functions on all targets:
@code{error} and @code{warning}.
Several other attributes are defined for functions on particular
target systems. Other attributes, including @code{section} are
-supported for variables declarations (@pxref{Variable Attributes})
+supported for variables declarations (@pxref{Variable Attributes}),
+labels (@pxref{Label Attributes})
and for types (@pxref{Type Attributes}).
GCC plugins may provide their own attributes.
@@ -3091,6 +3091,28 @@ On RL78, use @code{brk_interrupt} instead of @code{interrupt} for
handlers intended to be used with the @code{BRK} opcode (i.e.@: those
that must end with @code{RETB} instead of @code{RETI}).
+On RX targets, you may specify one or more vector numbers as arguments
+to the attribute, as well as naming an alternate table name.
+Parameters are handled sequentially, so one handler can be assigned to
+multiple entries in multiple tables. One may also pass the magic
+string @code{"$default"} which causes the function to be used for any
+unfilled slots in the current table.
+
+This example shows a simple assignment of a function to one vector in
+the default table (note that preprocessor macros may be used for
+chip-specific symbolic vector names):
+@smallexample
+void __attribute__ ((interrupt (5))) txd1_handler ();
+@end smallexample
+
+This example assigns a function to two slots in the default table
+(using preprocessor macros defined elsewhere) and makes it the default
+for the @code{dct} table:
+@smallexample
+void __attribute__ ((interrupt (RXD1_VECT,RXD2_VECT,"dct","$default")))
+ txd1_handler ();
+@end smallexample
+
@item interrupt_handler
@cindex interrupt handler functions on the Blackfin, m68k, H8/300 and SH processors
Use this attribute on the Blackfin, m68k, H8/300, H8/300H, H8S, and SH to
@@ -3209,14 +3231,16 @@ efficient @code{jal} instruction.
@item malloc
@cindex @code{malloc} attribute
-The @code{malloc} attribute is used to tell the compiler that a function
-may be treated as if any non-@code{NULL} pointer it returns cannot
-alias any other pointer valid when the function returns and that the memory
-has undefined content.
-This often improves optimization.
-Standard functions with this property include @code{malloc} and
-@code{calloc}. @code{realloc}-like functions do not have this
-property as the memory pointed to does not have undefined content.
+This tells the compiler that a function is @code{malloc}-like, i.e.,
+that the pointer @var{P} returned by the function cannot alias any
+other pointer valid when the function returns, and moreover no
+pointers to valid objects occur in any storage addressed by @var{P}.
+
+Using this attribute can improve optimization. Functions like
+@code{malloc} and @code{calloc} have this property because they return
+a pointer to uninitialized or zeroed-out storage. However, functions
+like @code{realloc} do not have this property, as they can return a
+pointer to storage containing pointers.
@item mips16/nomips16
@cindex @code{mips16} attribute
@@ -3621,8 +3645,8 @@ than 2.96.
@cindex @code{hot} function attribute
The @code{hot} attribute on a function is used to inform the compiler that
the function is a hot spot of the compiled program. The function is
-optimized more aggressively and on many target it is placed into special
-subsection of the text section so all hot functions appears close together
+optimized more aggressively and on many targets it is placed into a special
+subsection of the text section so all hot functions appear close together,
improving locality.
When profile feedback is available, via @option{-fprofile-use}, hot functions
@@ -3631,23 +3655,14 @@ are automatically detected and this attribute is ignored.
The @code{hot} attribute on functions is not implemented in GCC versions
earlier than 4.3.
-@cindex @code{hot} label attribute
-The @code{hot} attribute on a label is used to inform the compiler that
-path following the label are more likely than paths that are not so
-annotated. This attribute is used in cases where @code{__builtin_expect}
-cannot be used, for instance with computed goto or @code{asm goto}.
-
-The @code{hot} attribute on labels is not implemented in GCC versions
-earlier than 4.8.
-
@item cold
@cindex @code{cold} function attribute
The @code{cold} attribute on functions is used to inform the compiler that
the function is unlikely to be executed. The function is optimized for
-size rather than speed and on many targets it is placed into special
-subsection of the text section so all cold functions appears close together
+size rather than speed and on many targets it is placed into a special
+subsection of the text section so all cold functions appear close together,
improving code locality of non-cold parts of program. The paths leading
-to call of cold functions within code are marked as unlikely by the branch
+to calls of cold functions within code are marked as unlikely by the branch
prediction mechanism. It is thus useful to mark functions used to handle
unlikely conditions, such as @code{perror}, as cold to improve optimization
of hot functions that do call marked functions in rare occasions.
@@ -3658,15 +3673,6 @@ are automatically detected and this attribute is ignored.
The @code{cold} attribute on functions is not implemented in GCC versions
earlier than 4.3.
-@cindex @code{cold} label attribute
-The @code{cold} attribute on labels is used to inform the compiler that
-the path following the label is unlikely to be executed. This attribute
-is used in cases where @code{__builtin_expect} cannot be used, for instance
-with computed goto or @code{asm goto}.
-
-The @code{cold} attribute on labels is not implemented in GCC versions
-earlier than 4.8.
-
@item no_sanitize_address
@itemx no_address_safety_analysis
@cindex @code{no_sanitize_address} function attribute
@@ -3776,6 +3782,18 @@ registers) are saved in the function prologue. If the function is a leaf
function, only volatiles used by the function are saved. A normal function
return is generated instead of a return from interrupt.
+@item break_handler
+@cindex break handler functions
+Use this attribute on the MicroBlaze ports to indicate that
+the specified function is an break handler. The compiler generates function
+entry and exit sequences suitable for use in an break handler when this
+attribute is present. The return from @code{break_handler} is done through
+the @code{rtbd} instead of @code{rtsd}.
+
+@smallexample
+void f () __attribute__ ((break_handler));
+@end smallexample
+
@item section ("@var{section-name}")
@cindex @code{section} function attribute
Normally, the compiler places the code it generates in the @code{text} section.
@@ -4297,6 +4315,13 @@ When applied to a member function of a C++ class template, the
attribute also means that the function is instantiated if the
class itself is instantiated.
+@item vector
+@cindex @code{vector} attibute
+This RX attribute is similar to the @code{attribute}, including its
+parameters, but does not make the function an interrupt-handler type
+function (i.e. it retains the normal C function calling ABI). See the
+@code{interrupt} attribute for a description of its arguments.
+
@item version_id
@cindex @code{version_id} attribute
This IA-64 HP-UX attribute, attached to a global variable or function, renames a
@@ -4519,6 +4544,65 @@ attachment of attributes to their corresponding declarations, whereas
@code{#pragma GCC} is of use for constructs that do not naturally form
part of the grammar. @xref{Pragmas,,Pragmas Accepted by GCC}.
+@node Label Attributes
+@section Label Attributes
+@cindex Label Attributes
+
+GCC allows attributes to be set on C labels. @xref{Attribute Syntax}, for
+details of the exact syntax for using attributes. Other attributes are
+available for functions (@pxref{Function Attributes}), variables
+(@pxref{Variable Attributes}) and for types (@pxref{Type Attributes}).
+
+This example uses the @code{cold} label attribute to indicate the
+@code{ErrorHandling} branch is unlikely to be taken and that the
+@code{ErrorHandling} label is unused:
+
+@smallexample
+
+ asm goto ("some asm" : : : : NoError);
+
+/* This branch (the fallthru from the asm) is less commonly used */
+ErrorHandling:
+ __attribute__((cold, unused)); /* Semi-colon is required here */
+ printf("error\n");
+ return 0;
+
+NoError:
+ printf("no error\n");
+ return 1;
+@end smallexample
+
+@table @code
+@item unused
+@cindex @code{unused} label attribute
+This feature is intended for program-generated code that may contain
+unused labels, but which is compiled with @option{-Wall}. It is
+not normally appropriate to use in it human-written code, though it
+could be useful in cases where the code that jumps to the label is
+contained within an @code{#ifdef} conditional.
+
+@item hot
+@cindex @code{hot} label attribute
+The @code{hot} attribute on a label is used to inform the compiler that
+the path following the label is more likely than paths that are not so
+annotated. This attribute is used in cases where @code{__builtin_expect}
+cannot be used, for instance with computed goto or @code{asm goto}.
+
+The @code{hot} attribute on labels is not implemented in GCC versions
+earlier than 4.8.
+
+@item cold
+@cindex @code{cold} label attribute
+The @code{cold} attribute on labels is used to inform the compiler that
+the path following the label is unlikely to be executed. This attribute
+is used in cases where @code{__builtin_expect} cannot be used, for instance
+with computed goto or @code{asm goto}.
+
+The @code{cold} attribute on labels is not implemented in GCC versions
+earlier than 4.8.
+
+@end table
+
@node Attribute Syntax
@section Attribute Syntax
@cindex attribute syntax
@@ -4542,6 +4626,8 @@ applying to functions. @xref{Variable Attributes}, for details of the
semantics of attributes applying to variables. @xref{Type Attributes},
for details of the semantics of attributes applying to structure, union
and enumerated types.
+@xref{Label Attributes}, for details of the semantics of attributes
+applying to labels.
An @dfn{attribute specifier} is of the form
@code{__attribute__ ((@var{attribute-list}))}. An @dfn{attribute list}
@@ -4579,14 +4665,10 @@ with the list being a single string constant.
An @dfn{attribute specifier list} is a sequence of one or more attribute
specifiers, not separated by any other tokens.
+@subsubheading Label Attributes
+
In GNU C, an attribute specifier list may appear after the colon following a
-label, other than a @code{case} or @code{default} label. The only
-attribute it makes sense to use after a label is @code{unused}. This
-feature is intended for program-generated code that may contain unused labels,
-but which is compiled with @option{-Wall}. It is
-not normally appropriate to use in it human-written code, though it
-could be useful in cases where the code that jumps to the label is
-contained within an @code{#ifdef} conditional. GNU C++ only permits
+label, other than a @code{case} or @code{default} label. GNU C++ only permits
attributes on labels if the attribute specifier is immediately
followed by a semicolon (i.e., the label applies to an empty
statement). If the semicolon is missing, C++ label attributes are
@@ -4594,6 +4676,8 @@ ambiguous, as it is permissible for a declaration, which could begin
with an attribute list, to be labelled in C++. Declarations cannot be
labelled in C90 or C99, so the ambiguity does not arise there.
+@subsubheading Type Attributes
+
An attribute specifier list may appear as part of a @code{struct},
@code{union} or @code{enum} specifier. It may go either immediately
after the @code{struct}, @code{union} or @code{enum} keyword, or after
@@ -4608,6 +4692,9 @@ defined is not complete until after the attribute specifiers.
@c attributes could use sizeof for the structure, but the size could be
@c changed later by "packed" attributes.
+
+@subsubheading All other attributes
+
Otherwise, an attribute specifier appears as part of a declaration,
counting declarations of unnamed parameters and type names, and relates
to that declaration (which may be nested in another declaration, for
@@ -4848,7 +4935,8 @@ by an attribute specification inside double parentheses. Some
attributes are currently defined generically for variables.
Other attributes are defined for variables on particular target
systems. Other attributes are available for functions
-(@pxref{Function Attributes}) and for types (@pxref{Type Attributes}).
+(@pxref{Function Attributes}), labels (@pxref{Label Attributes}) and for
+types (@pxref{Type Attributes}).
Other front ends might define more attributes
(@pxref{C++ Extensions,,Extensions to the C++ Language}).
@@ -5504,8 +5592,8 @@ inside double parentheses. Seven attributes are currently defined for
types: @code{aligned}, @code{packed}, @code{transparent_union},
@code{unused}, @code{deprecated}, @code{visibility}, and
@code{may_alias}. Other attributes are defined for functions
-(@pxref{Function Attributes}) and for variables (@pxref{Variable
-Attributes}).
+(@pxref{Function Attributes}), labels (@pxref{Label
+Attributes}) and for variables (@pxref{Variable Attributes}).
You may also specify any one of these attributes with @samp{__}
preceding and following its keyword. This allows you to use these
@@ -6137,491 +6225,950 @@ bit-fields are only partially accessed, if they straddle a storage unit
boundary. For these reasons it is unwise to use volatile bit-fields to
access hardware.
+@node Using Assembly Language with C
+@section How to Use Inline Assembly Language in C Code
+
+GCC provides various extensions that allow you to embed assembler within
+C code.
+
+@menu
+* Basic Asm:: Inline assembler with no operands.
+* Extended Asm:: Inline assembler with operands.
+* Constraints:: Constraints for @code{asm} operands
+* Asm Labels:: Specifying the assembler name to use for a C symbol.
+* Explicit Reg Vars:: Defining variables residing in specified registers.
+* Size of an asm:: How GCC calculates the size of an @code{asm} block.
+@end menu
+
+@node Basic Asm
+@subsection Basic Asm --- Assembler Instructions with No Operands
+@cindex basic @code{asm}
+
+The @code{asm} keyword allows you to embed assembler instructions within
+C code.
+
+@example
+asm [ volatile ] ( AssemblerInstructions )
+@end example
+
+To create headers compatible with ISO C, write @code{__asm__} instead of
+@code{asm} (@pxref{Alternate Keywords}).
+
+By definition, a Basic @code{asm} statement is one with no operands.
+@code{asm} statements that contain one or more colons (used to delineate
+operands) are considered to be Extended (for example, @code{asm("int $3")}
+is Basic, and @code{asm("int $3" : )} is Extended). @xref{Extended Asm}.
+
+@subsubheading Qualifiers
+@emph{volatile}
+@*
+This optional qualifier has no effect. All Basic @code{asm} blocks are
+implicitly volatile.
+
+@subsubheading Parameters
+@emph{AssemblerInstructions}
+@*
+This is a literal string that specifies the assembler code. The string can
+contain any instructions recognized by the assembler, including directives.
+GCC does not parse the assembler instructions themselves and
+does not know what they mean or even whether they are valid assembler input.
+The compiler copies it verbatim to the assembly language output file, without
+processing dialects or any of the "%" operators that are available with
+Extended @code{asm}. This results in minor differences between Basic
+@code{asm} strings and Extended @code{asm} templates. For example, to refer to
+registers you might use %%eax in Extended @code{asm} and %eax in Basic
+@code{asm}.
+
+You may place multiple assembler instructions together in a single @code{asm}
+string, separated by the characters normally used in assembly code for the
+system. A combination that works in most places is a newline to break the
+line, plus a tab character (written as "\n\t").
+Some assemblers allow semicolons as a line separator. However,
+note that some assembler dialects use semicolons to start a comment.
+
+Do not expect a sequence of @code{asm} statements to remain perfectly
+consecutive after compilation. If certain instructions need to remain
+consecutive in the output, put them in a single multi-instruction asm
+statement. Note that GCC's optimizers can move @code{asm} statements
+relative to other code, including across jumps.
+
+@code{asm} statements may not perform jumps into other @code{asm} statements.
+GCC does not know about these jumps, and therefore cannot take
+account of them when deciding how to optimize. Jumps from @code{asm} to C
+labels are only supported in Extended @code{asm}.
+
+@subsubheading Remarks
+Using Extended @code{asm} will typically produce smaller, safer, and more
+efficient code, and in most cases it is a better solution. When writing
+inline assembly language outside of C functions, however, you must use Basic
+@code{asm}. Extended @code{asm} statements have to be inside a C function.
+
+Under certain circumstances, GCC may duplicate (or remove duplicates of) your
+assembly code when optimizing. This can lead to unexpected duplicate
+symbol errors during compilation if your assembly code defines symbols or
+labels.
+
+Safely accessing C data and calling functions from Basic @code{asm} is more
+complex than it may appear. To access C data, it is better to use Extended
+@code{asm}.
+
+Since GCC does not parse the AssemblerInstructions, it has no
+visibility of any symbols it references. This may result in GCC discarding
+those symbols as unreferenced.
+
+Unlike Extended @code{asm}, all Basic @code{asm} blocks are implicitly
+volatile. @xref{Volatile}. Similarly, Basic @code{asm} blocks are not treated
+as though they used a "memory" clobber (@pxref{Clobbers}).
+
+All Basic @code{asm} blocks use the assembler dialect specified by the
+@option{-masm} command-line option. Basic @code{asm} provides no
+mechanism to provide different assembler strings for different dialects.
+
+Here is an example of Basic @code{asm} for i386:
+
+@example
+/* Note that this code will not compile with -masm=intel */
+#define DebugBreak() asm("int $3")
+@end example
+
@node Extended Asm
-@section Assembler Instructions with C Expression Operands
+@subsection Extended Asm - Assembler Instructions with C Expression Operands
+@cindex @code{asm} keyword
@cindex extended @code{asm}
-@cindex @code{asm} expressions
@cindex assembler instructions
-@cindex registers
-In an assembler instruction using @code{asm}, you can specify the
-operands of the instruction using C expressions. This means you need not
-guess which registers or memory locations contain the data you want
-to use.
+The @code{asm} keyword allows you to embed assembler instructions within C
+code. With Extended @code{asm} you can read and write C variables from
+assembler and perform jumps from assembler code to C labels.
-You must specify an assembler instruction template much like what
-appears in a machine description, plus an operand constraint string for
-each operand.
+@example
+@ifhtml
+asm [volatile] ( AssemblerTemplate : [OutputOperands] [ : [InputOperands] [ : [Clobbers] ] ] )
+
+asm [volatile] goto ( AssemblerTemplate : : [InputOperands] : [Clobbers] : GotoLabels )
+@end ifhtml
+@ifnothtml
+asm [volatile] ( AssemblerTemplate
+ : [OutputOperands]
+ [ : [InputOperands]
+ [ : [Clobbers] ] ])
+
+asm [volatile] goto ( AssemblerTemplate
+ :
+ : [InputOperands]
+ : [Clobbers]
+ : GotoLabels)
+@end ifnothtml
+@end example
-For example, here is how to use the 68881's @code{fsinx} instruction:
+To create headers compatible with ISO C, write @code{__asm__} instead of
+@code{asm} and @code{__volatile__} instead of @code{volatile}
+(@pxref{Alternate Keywords}). There is no alternate for @code{goto}.
+
+By definition, Extended @code{asm} is an @code{asm} statement that contains
+operands. To separate the classes of operands, you use colons. Basic
+@code{asm} statements contain no colons. (So, for example,
+@code{asm("int $3")} is Basic @code{asm}, and @code{asm("int $3" : )} is
+Extended @code{asm}. @pxref{Basic Asm}.)
+
+@subsubheading Qualifiers
+@emph{volatile}
+@*
+The typical use of Extended @code{asm} statements is to manipulate input
+values to produce output values. However, your @code{asm} statements may
+also produce side effects. If so, you may need to use the @code{volatile}
+qualifier to disable certain optimizations. @xref{Volatile}.
+
+@emph{goto}
+@*
+This qualifier informs the compiler that the @code{asm} statement may
+perform a jump to one of the labels listed in the GotoLabels section.
+@xref{GotoLabels}.
+
+@subsubheading Parameters
+@emph{AssemblerTemplate}
+@*
+This is a literal string that contains the assembler code. It is a
+combination of fixed text and tokens that refer to the input, output,
+and goto parameters. @xref{AssemblerTemplate}.
+
+@emph{OutputOperands}
+@*
+A comma-separated list of the C variables modified by the instructions in the
+AssemblerTemplate. @xref{OutputOperands}.
+
+@emph{InputOperands}
+@*
+A comma-separated list of C expressions read by the instructions in the
+AssemblerTemplate. @xref{InputOperands}.
+
+@emph{Clobbers}
+@*
+A comma-separated list of registers or other values changed by the
+AssemblerTemplate, beyond those listed as outputs. @xref{Clobbers}.
+
+@emph{GotoLabels}
+@*
+When you are using the @code{goto} form of @code{asm}, this section contains
+the list of all C labels to which the AssemblerTemplate may jump.
+@xref{GotoLabels}.
+
+@subsubheading Remarks
+The @code{asm} statement allows you to include assembly instructions directly
+within C code. This may help you to maximize performance in time-sensitive
+code or to access assembly instructions that are not readily available to C
+programs.
+
+Note that Extended @code{asm} statements must be inside a function. Only
+Basic @code{asm} may be outside functions (@pxref{Basic Asm}).
+
+While the uses of @code{asm} are many and varied, it may help to think of an
+@code{asm} statement as a series of low-level instructions that convert input
+parameters to output parameters. So a simple (if not particularly useful)
+example for i386 using @code{asm} might look like this:
-@smallexample
-asm ("fsinx %1,%0" : "=f" (result) : "f" (angle));
-@end smallexample
+@example
+int src = 1;
+int dst;
-@noindent
-Here @code{angle} is the C expression for the input operand while
-@code{result} is that of the output operand. Each has @samp{"f"} as its
-operand constraint, saying that a floating-point register is required.
-The @samp{=} in @samp{=f} indicates that the operand is an output; all
-output operands' constraints must use @samp{=}. The constraints use the
-same language used in the machine description (@pxref{Constraints}).
-
-Each operand is described by an operand-constraint string followed by
-the C expression in parentheses. A colon separates the assembler
-template from the first output operand and another separates the last
-output operand from the first input, if any. Commas separate the
-operands within each group. The total number of operands is currently
-limited to 30; this limitation may be lifted in some future version of
-GCC@.
-
-If there are no output operands but there are input operands, you must
-place two consecutive colons surrounding the place where the output
-operands would go.
-
-As of GCC version 3.1, it is also possible to specify input and output
-operands using symbolic names which can be referenced within the
-assembler code. These names are specified inside square brackets
-preceding the constraint string, and can be referenced inside the
-assembler code using @code{%[@var{name}]} instead of a percentage sign
-followed by the operand number. Using named operands the above example
-could look like:
-
-@smallexample
-asm ("fsinx %[angle],%[output]"
- : [output] "=f" (result)
- : [angle] "f" (angle));
-@end smallexample
+asm ("mov %1, %0\n\t"
+ "add $1, %0"
+ : "=r" (dst)
+ : "r" (src));
-@noindent
-Note that the symbolic operand names have no relation whatsoever to
-other C identifiers. You may use any name you like, even those of
-existing C symbols, but you must ensure that no two operands within the same
-assembler construct use the same symbolic name.
-
-Output operand expressions must be lvalues; the compiler can check this.
-The input operands need not be lvalues. The compiler cannot check
-whether the operands have data types that are reasonable for the
-instruction being executed. It does not parse the assembler instruction
-template and does not know what it means or even whether it is valid
-assembler input. The extended @code{asm} feature is most often used for
-machine instructions the compiler itself does not know exist. If
-the output expression cannot be directly addressed (for example, it is a
-bit-field), your constraint must allow a register. In that case, GCC
-uses the register as the output of the @code{asm}, and then stores
-that register into the output.
-
-The ordinary output operands must be write-only; GCC assumes that
-the values in these operands before the instruction are dead and need
-not be generated. Extended asm supports input-output or read-write
-operands. Use the constraint character @samp{+} to indicate such an
-operand and list it with the output operands.
-
-You may, as an alternative, logically split its function into two
-separate operands, one input operand and one write-only output
-operand. The connection between them is expressed by constraints
-that say they need to be in the same location when the instruction
-executes. You can use the same C expression for both operands, or
-different expressions. For example, here we write the (fictitious)
-@samp{combine} instruction with @code{bar} as its read-only source
-operand and @code{foo} as its read-write destination:
-
-@smallexample
-asm ("combine %2,%0" : "=r" (foo) : "0" (foo), "g" (bar));
-@end smallexample
+printf("%d\n", dst);
+@end example
-@noindent
-The constraint @samp{"0"} for operand 1 says that it must occupy the
-same location as operand 0. A number in constraint is allowed only in
-an input operand and it must refer to an output operand.
+This code will copy @var{src} to @var{dst} and add 1 to @var{dst}.
-Only a number in the constraint can guarantee that one operand is in
-the same place as another. The mere fact that @code{foo} is the value
-of both operands is not enough to guarantee that they are in the
-same place in the generated assembler code. The following does not
-work reliably:
+@anchor{Volatile}
+@subsubsection Volatile
+@cindex volatile @code{asm}
+@cindex @code{asm} volatile
-@smallexample
-asm ("combine %2,%0" : "=r" (foo) : "r" (foo), "g" (bar));
-@end smallexample
+GCC's optimizers sometimes discard @code{asm} statements if they determine
+there is no need for the output variables. Also, the optimizers may move
+code out of loops if they believe that the code will always return the same
+result (i.e. none of its input values change between calls). Using the
+@code{volatile} qualifier disables these optimizations. @code{asm} statements
+that have no output operands are implicitly volatile.
-Various optimizations or reloading could cause operands 0 and 1 to be in
-different registers; GCC knows no reason not to do so. For example, the
-compiler might find a copy of the value of @code{foo} in one register and
-use it for operand 1, but generate the output operand 0 in a different
-register (copying it afterward to @code{foo}'s own address). Of course,
-since the register for operand 1 is not even mentioned in the assembler
-code, the result will not work, but GCC can't tell that.
+Examples:
-As of GCC version 3.1, one may write @code{[@var{name}]} instead of
-the operand number for a matching constraint. For example:
+This i386 code demonstrates a case that does not use (or require) the
+@code{volatile} qualifier. If it is performing assertion checking, this code
+uses @code{asm} to perform the validation. Otherwise, @var{dwRes} is
+unreferenced by any code. As a result, the optimizers can discard the
+@code{asm} statement, which in turn removes the need for the entire
+@code{DoCheck} routine. By omitting the @code{volatile} qualifier when it
+isn't needed you allow the optimizers to produce the most efficient code
+possible.
-@smallexample
-asm ("cmoveq %1,%2,%[result]"
- : [result] "=r"(result)
- : "r" (test), "r"(new), "[result]"(old));
-@end smallexample
+@example
+void DoCheck(uint32_t dwSomeValue)
+@{
+ uint32_t dwRes;
-Sometimes you need to make an @code{asm} operand be a specific register,
-but there's no matching constraint letter for that register @emph{by
-itself}. To force the operand into that register, use a local variable
-for the operand and specify the register in the variable declaration.
-@xref{Explicit Reg Vars}. Then for the @code{asm} operand, use any
-register constraint letter that matches the register:
+ // Assumes dwSomeValue is not zero.
+ asm ("bsfl %1,%0"
+ : "=r" (dwRes)
+ : "r" (dwSomeValue)
+ : "cc");
-@smallexample
-register int *p1 asm ("r0") = @dots{};
-register int *p2 asm ("r1") = @dots{};
-register int *result asm ("r0");
-asm ("sysint" : "=r" (result) : "0" (p1), "r" (p2));
-@end smallexample
+ assert(dwRes > 3);
+@}
+@end example
-@anchor{Example of asm with clobbered asm reg}
-In the above example, beware that a register that is call-clobbered by
-the target ABI will be overwritten by any function call in the
-assignment, including library calls for arithmetic operators.
-Also a register may be clobbered when generating some operations,
-like variable shift, memory copy or memory move on x86.
-Assuming it is a call-clobbered register, this may happen to @code{r0}
-above by the assignment to @code{p2}. If you have to use such a
-register, use temporary variables for expressions between the register
-assignment and use:
+The next example shows a case where the optimizers can recognize that the input
+(@var{dwSomeValue}) never changes during the execution of the function and can
+therefore move the @code{asm} outside the loop to produce more efficient code.
+Again, using @code{volatile} disables this type of optimization.
-@smallexample
-int t1 = @dots{};
-register int *p1 asm ("r0") = @dots{};
-register int *p2 asm ("r1") = t1;
-register int *result asm ("r0");
-asm ("sysint" : "=r" (result) : "0" (p1), "r" (p2));
-@end smallexample
+@example
+void do_print(uint32_t dwSomeValue)
+@{
+ uint32_t dwRes;
+
+ for (uint32_t x=0; x < 5; x++)
+ @{
+ // Assumes dwSomeValue is not zero.
+ asm ("bsfl %1,%0"
+ : "=r" (dwRes)
+ : "r" (dwSomeValue)
+ : "cc");
+
+ printf("%u: %u %u\n", x, dwSomeValue, dwRes);
+ @}
+@}
+@end example
-Some instructions clobber specific hard registers. To describe this,
-write a third colon after the input operands, followed by the names of
-the clobbered hard registers (given as strings). Here is a realistic
-example for the VAX:
+The following example demonstrates a case where you need to use the
+@code{volatile} qualifier. It uses the i386 RDTSC instruction, which reads
+the computer's time-stamp counter. Without the @code{volatile} qualifier,
+the optimizers might assume that the @code{asm} block will always return the
+same value and therefore optimize away the second call.
-@smallexample
-asm volatile ("movc3 %0,%1,%2"
- : /* @r{no outputs} */
- : "g" (from), "g" (to), "g" (count)
- : "r0", "r1", "r2", "r3", "r4", "r5");
-@end smallexample
+@example
+uint64_t msr;
-You may not write a clobber description in a way that overlaps with an
-input or output operand. For example, you may not have an operand
-describing a register class with one member if you mention that register
-in the clobber list. Variables declared to live in specific registers
-(@pxref{Explicit Reg Vars}), and used as asm input or output operands must
-have no part mentioned in the clobber description.
-There is no way for you to specify that an input
-operand is modified without also specifying it as an output
-operand. Note that if all the output operands you specify are for this
-purpose (and hence unused), you then also need to specify
-@code{volatile} for the @code{asm} construct, as described below, to
-prevent GCC from deleting the @code{asm} statement as unused.
+asm volatile ( "rdtsc\n\t" // Returns the time in EDX:EAX.
+ "shl $32, %%rdx\n\t" // Shift the upper bits left.
+ "or %%rdx, %0" // 'Or' in the lower bits.
+ : "=a" (msr)
+ :
+ : "rdx");
-If you refer to a particular hardware register from the assembler code,
-you probably have to list the register after the third colon to
-tell the compiler the register's value is modified. In some assemblers,
-the register names begin with @samp{%}; to produce one @samp{%} in the
-assembler code, you must write @samp{%%} in the input.
+printf("msr: %llx\n", msr);
-If your assembler instruction can alter the condition code register, add
-@samp{cc} to the list of clobbered registers. GCC on some machines
-represents the condition codes as a specific hardware register;
-@samp{cc} serves to name this register. On other machines, the
-condition code is handled differently, and specifying @samp{cc} has no
-effect. But it is valid no matter what the machine.
+// Do other work...
-If your assembler instructions access memory in an unpredictable
-fashion, add @samp{memory} to the list of clobbered registers. This
-causes GCC to not keep memory values cached in registers across the
-assembler instruction and not optimize stores or loads to that memory.
-You also should add the @code{volatile} keyword if the memory
-affected is not listed in the inputs or outputs of the @code{asm}, as
-the @samp{memory} clobber does not count as a side-effect of the
-@code{asm}. If you know how large the accessed memory is, you can add
-it as input or output but if this is not known, you should add
-@samp{memory}. As an example, if you access ten bytes of a string, you
-can use a memory input like:
+// Reprint the timestamp
+asm volatile ( "rdtsc\n\t" // Returns the time in EDX:EAX.
+ "shl $32, %%rdx\n\t" // Shift the upper bits left.
+ "or %%rdx, %0" // 'Or' in the lower bits.
+ : "=a" (msr)
+ :
+ : "rdx");
-@smallexample
-@{"m"( (@{ struct @{ char x[10]; @} *p = (void *)ptr ; *p; @}) )@}.
-@end smallexample
+printf("msr: %llx\n", msr);
+@end example
-Note that in the following example the memory input is necessary,
-otherwise GCC might optimize the store to @code{x} away:
-@smallexample
-int foo ()
-@{
- int x = 42;
- int *y = &x;
- int result;
- asm ("magic stuff accessing an 'int' pointed to by '%1'"
- : "=&d" (result) : "a" (y), "m" (*y));
- return result;
-@}
-@end smallexample
+GCC's optimizers will not treat this code like the non-volatile code in the
+earlier examples. They do not move it out of loops or omit it on the
+assumption that the result from a previous call is still valid.
-You can put multiple assembler instructions together in a single
-@code{asm} template, separated by the characters normally used in assembly
-code for the system. A combination that works in most places is a newline
-to break the line, plus a tab character to move to the instruction field
-(written as @samp{\n\t}). Sometimes semicolons can be used, if the
-assembler allows semicolons as a line-breaking character. Note that some
-assembler dialects use semicolons to start a comment.
-The input operands are guaranteed not to use any of the clobbered
-registers, and neither do the output operands' addresses, so you can
-read and write the clobbered registers as many times as you like. Here
-is an example of multiple instructions in a template; it assumes the
-subroutine @code{_foo} accepts arguments in registers 9 and 10:
+Note that the compiler can move even volatile @code{asm} instructions relative
+to other code, including across jump instructions. For example, on many
+targets there is a system register that controls the rounding mode of
+floating-point operations. Setting it with a volatile @code{asm}, as in the
+following PowerPC example, will not work reliably.
-@smallexample
-asm ("movl %0,r9\n\tmovl %1,r10\n\tcall _foo"
- : /* no outputs */
- : "g" (from), "g" (to)
- : "r9", "r10");
-@end smallexample
+@example
+asm volatile("mtfsf 255, %0" : : "f" (fpenv));
+sum = x + y;
+@end example
-Unless an output operand has the @samp{&} constraint modifier, GCC
-may allocate it in the same register as an unrelated input operand, on
-the assumption the inputs are consumed before the outputs are produced.
-This assumption may be false if the assembler code actually consists of
-more than one instruction. In such a case, use @samp{&} for each output
-operand that may not overlap an input. @xref{Modifiers}.
+The compiler may move the addition back before the volatile @code{asm}. To
+make it work as expected, add an artificial dependency to the @code{asm} by
+referencing a variable in the subsequent code, for example:
-If you want to test the condition code produced by an assembler
-instruction, you must include a branch and a label in the @code{asm}
-construct, as follows:
+@example
+asm volatile ("mtfsf 255,%1" : "=X" (sum) : "f" (fpenv));
+sum = x + y;
+@end example
-@smallexample
-asm ("clr %0\n\tfrob %1\n\tbeq 0f\n\tmov #1,%0\n0:"
- : "g" (result)
- : "g" (input));
-@end smallexample
+Under certain circumstances, GCC may duplicate (or remove duplicates of) your
+assembly code when optimizing. This can lead to unexpected duplicate symbol
+errors during compilation if your asm code defines symbols or labels. Using %=
+(@pxref{AssemblerTemplate}) may help resolve this problem.
+
+@anchor{AssemblerTemplate}
+@subsubsection Assembler Template
+@cindex @code{asm} assembler template
+
+An assembler template is a literal string containing assembler instructions.
+The compiler will replace any references to inputs, outputs, and goto labels
+in the template, and then output the resulting string to the assembler. The
+string can contain any instructions recognized by the assembler, including
+directives. GCC does not parse the assembler instructions
+themselves and does not know what they mean or even whether they are valid
+assembler input. However, it does count the statements
+(@pxref{Size of an asm}).
+
+You may place multiple assembler instructions together in a single @code{asm}
+string, separated by the characters normally used in assembly code for the
+system. A combination that works in most places is a newline to break the
+line, plus a tab character to move to the instruction field (written as
+"\n\t"). Some assemblers allow semicolons as a line separator. However, note
+that some assembler dialects use semicolons to start a comment.
+
+Do not expect a sequence of @code{asm} statements to remain perfectly
+consecutive after compilation, even when you are using the @code{volatile}
+qualifier. If certain instructions need to remain consecutive in the output,
+put them in a single multi-instruction asm statement.
+
+Accessing data from C programs without using input/output operands (such as
+by using global symbols directly from the assembler template) may not work as
+expected. Similarly, calling functions directly from an assembler template
+requires a detailed understanding of the target assembler and ABI.
+
+Since GCC does not parse the AssemblerTemplate, it has no visibility of any
+symbols it references. This may result in GCC discarding those symbols as
+unreferenced unless they are also listed as input, output, or goto operands.
+
+GCC can support multiple assembler dialects (for example, GCC for i386
+supports "att" and "intel" dialects) for inline assembler. In builds that
+support this capability, the @option{-masm} option controls which dialect
+GCC uses as its default. The hardware-specific documentation for the
+@option{-masm} option contains the list of supported dialects, as well as the
+default dialect if the option is not specified. This information may be
+important to understand, since assembler code that works correctly when
+compiled using one dialect will likely fail if compiled using another.
+
+@subsubheading Using braces in @code{asm} templates
+
+If your code needs to support multiple assembler dialects (for example, if
+you are writing public headers that need to support a variety of compilation
+options), use constructs of this form:
-@noindent
-This assumes your assembler supports local labels, as the GNU assembler
-and most Unix assemblers do.
+@example
+@{ dialect0 | dialect1 | dialect2... @}
+@end example
-Speaking of labels, jumps from one @code{asm} to another are not
-supported. The compiler's optimizers do not know about these jumps, and
-therefore they cannot take account of them when deciding how to
-optimize. @xref{Extended asm with goto}.
+This construct outputs 'dialect0' when using dialect #0 to compile the code,
+'dialect1' for dialect #1, etc. If there are fewer alternatives within the
+braces than the number of dialects the compiler supports, the construct
+outputs nothing.
-@cindex macros containing @code{asm}
-Usually the most convenient way to use these @code{asm} instructions is to
-encapsulate them in macros that look like functions. For example,
+For example, if an i386 compiler supports two dialects (att, intel), an
+assembler template such as this:
-@smallexample
-#define sin(x) \
-(@{ double __value, __arg = (x); \
- asm ("fsinx %1,%0": "=f" (__value): "f" (__arg)); \
- __value; @})
-@end smallexample
+@example
+"bt@{l %[Offset],%[Base] | %[Base],%[Offset]@}; jc %l2"
+@end example
-@noindent
-Here the variable @code{__arg} is used to make sure that the instruction
-operates on a proper @code{double} value, and to accept only those
-arguments @code{x} that can convert automatically to a @code{double}.
-
-Another way to make sure the instruction operates on the correct data
-type is to use a cast in the @code{asm}. This is different from using a
-variable @code{__arg} in that it converts more different types. For
-example, if the desired type is @code{int}, casting the argument to
-@code{int} accepts a pointer with no complaint, while assigning the
-argument to an @code{int} variable named @code{__arg} warns about
-using a pointer unless the caller explicitly casts it.
-
-If an @code{asm} has output operands, GCC assumes for optimization
-purposes the instruction has no side effects except to change the output
-operands. This does not mean instructions with a side effect cannot be
-used, but you must be careful, because the compiler may eliminate them
-if the output operands aren't used, or move them out of loops, or
-replace two with one if they constitute a common subexpression. Also,
-if your instruction does have a side effect on a variable that otherwise
-appears not to change, the old value of the variable may be reused later
-if it happens to be found in a register.
-
-You can prevent an @code{asm} instruction from being deleted
-by writing the keyword @code{volatile} after
-the @code{asm}. For example:
-
-@smallexample
-#define get_and_set_priority(new) \
-(@{ int __old; \
- asm volatile ("get_and_set_priority %0, %1" \
- : "=g" (__old) : "g" (new)); \
- __old; @})
-@end smallexample
+would produce the output:
-@noindent
-The @code{volatile} keyword indicates that the instruction has
-important side-effects. GCC does not delete a volatile @code{asm} if
-it is reachable. (The instruction can still be deleted if GCC can
-prove that control flow never reaches the location of the
-instruction.) Note that even a volatile @code{asm} instruction
-can be moved relative to other code, including across jump
-instructions. For example, on many targets there is a system
-register that can be set to control the rounding mode of
-floating-point operations. You might try
-setting it with a volatile @code{asm}, like this PowerPC example:
+@example
+For att: "btl %[Offset],%[Base] ; jc %l2"
+For intel: "bt %[Base],%[Offset]; jc %l2"
+@end example
-@smallexample
- asm volatile("mtfsf 255,%0" : : "f" (fpenv));
- sum = x + y;
-@end smallexample
+Using that same compiler, this code:
-@noindent
-This does not work reliably, as the compiler may move the addition back
-before the volatile @code{asm}. To make it work you need to add an
-artificial dependency to the @code{asm} referencing a variable in the code
-you don't want moved, for example:
+@example
+"xchg@{l@}\t@{%%@}ebx, %1"
+@end example
-@smallexample
- asm volatile ("mtfsf 255,%1" : "=X"(sum): "f"(fpenv));
- sum = x + y;
-@end smallexample
+would produce
-Similarly, you can't expect a
-sequence of volatile @code{asm} instructions to remain perfectly
-consecutive. If you want consecutive output, use a single @code{asm}.
-Also, GCC performs some optimizations across a volatile @code{asm}
-instruction; GCC does not ``forget everything'' when it encounters
-a volatile @code{asm} instruction the way some other compilers do.
+@example
+For att: "xchgl\t%%ebx, %1"
+For intel: "xchg\tebx, %1"
+@end example
-An @code{asm} instruction without any output operands is treated
-identically to a volatile @code{asm} instruction.
+There is no support for nesting dialect alternatives. Also, there is no
+``escape'' for an open brace (@{), so do not use open braces in an Extended
+@code{asm} template other than as a dialect indicator.
-It is a natural idea to look for a way to give access to the condition
-code left by the assembler instruction. However, when we attempted to
-implement this, we found no way to make it work reliably. The problem
-is that output operands might need reloading, which result in
-additional following ``store'' instructions. On most machines, these
-instructions alter the condition code before there is time to
-test it. This problem doesn't arise for ordinary ``test'' and
-``compare'' instructions because they don't have any output operands.
+@subsubheading Other format strings
-For reasons similar to those described above, it is not possible to give
-an assembler instruction access to the condition code left by previous
-instructions.
+In addition to the tokens described by the input, output, and goto operands,
+there are a few special cases:
-@anchor{Extended asm with goto}
-As of GCC version 4.5, @code{asm goto} may be used to have the assembly
-jump to one or more C labels. In this form, a fifth section after the
-clobber list contains a list of all C labels to which the assembly may jump.
-Each label operand is implicitly self-named. The @code{asm} is also assumed
-to fall through to the next statement.
+@itemize
+@item
+"%%" outputs a single "%" into the assembler code.
-This form of @code{asm} is restricted to not have outputs. This is due
-to a internal restriction in the compiler that control transfer instructions
-cannot have outputs. This restriction on @code{asm goto} may be lifted
-in some future version of the compiler. In the meantime, @code{asm goto}
-may include a memory clobber, and so leave outputs in memory.
+@item
+"%=" outputs a number that is unique to each instance of the @code{asm}
+statement in the entire compilation. This option is useful when creating local
+labels and referring to them multiple times in a single template that
+generates multiple assembler instructions.
-@smallexample
+@end itemize
+
+@anchor{OutputOperands}
+@subsubsection Output Operands
+@cindex @code{asm} output operands
+
+An @code{asm} statement has zero or more output operands indicating the names
+of C variables modified by the assembler code.
+
+In this i386 example, @var{old} (referred to in the template string as
+@code{%0}) and @var{*Base} (as @code{%1}) are outputs and @var{Offset}
+(@code{%2}) is an input:
+
+@example
+bool old;
+
+__asm__ ("btsl %2,%1\n\t" // Turn on zero-based bit #Offset in Base.
+ "sbb %0,%0" // Use the CF to calculate old.
+ : "=r" (old), "+rm" (*Base)
+ : "Ir" (Offset)
+ : "cc");
+
+return old;
+@end example
+
+Operands use this format:
+
+@example
+[ [asmSymbolicName] ] "constraint" (cvariablename)
+@end example
+
+@emph{asmSymbolicName}
+@*
+
+When not using asmSymbolicNames, use the (zero-based) position of the operand
+in the list of operands in the assembler template. For example if there are
+three output operands, use @code{%0} in the template to refer to the first,
+@code{%1} for the second, and @code{%2} for the third. When using an
+asmSymbolicName, reference it by enclosing the name in square brackets
+(i.e. @code{%[Value]}). The scope of the name is the @code{asm} statement
+that contains the definition. Any valid C variable name is acceptable,
+including names already defined in the surrounding code. No two operands
+within the same @code{asm} statement can use the same symbolic name.
+
+@emph{constraint}
+@*
+Output constraints must begin with either @code{"="} (a variable overwriting an
+existing value) or @code{"+"} (when reading and writing). When using
+@code{"="}, do not assume the location will contain the existing value (except
+when tying the variable to an input; @pxref{InputOperands,,Input Operands}).
+
+After the prefix, there must be one or more additional constraints
+(@pxref{Constraints}) that describe where the value resides. Common
+constraints include @code{"r"} for register and @code{"m"} for memory.
+When you list more than one possible location (for example @code{"=rm"}), the
+compiler chooses the most efficient one based on the current context. If you
+list as many alternates as the @code{asm} statement allows, you will permit
+the optimizers to produce the best possible code. If you must use a specific
+register, but your Machine Constraints do not provide sufficient
+control to select the specific register you want, Local Reg Vars may provide
+a solution (@pxref{Local Reg Vars}).
+
+@emph{cvariablename}
+@*
+Specifies the C variable name of the output (enclosed by parentheses). Accepts
+any (non-constant) variable within scope.
+
+Remarks:
+
+The total number of input + output + goto operands has a limit of 30. Commas
+separate the operands. When the compiler selects the registers to use to
+represent the output operands, it will not use any of the clobbered registers
+(@pxref{Clobbers}).
+
+Output operand expressions must be lvalues. The compiler cannot check whether
+the operands have data types that are reasonable for the instruction being
+executed. For output expressions that are not directly addressable (for
+example a bit-field), the constraint must allow a register. In that case, GCC
+uses the register as the output of the @code{asm}, and then stores that
+register into the output.
+
+Unless an output operand has the '@code{&}' constraint modifier
+(@pxref{Modifiers}), GCC may allocate it in the same register as an unrelated
+input operand, on the assumption that the assembler code will consume its
+inputs before producing outputs. This assumption may be false if the assembler
+code actually consists of more than one instruction. In this case, use
+'@code{&}' on each output operand that must not overlap an input.
+
+The same problem can occur if one output parameter (@var{a}) allows a register
+constraint and another output parameter (@var{b}) allows a memory constraint.
+The code generated by GCC to access the memory address in @var{b} can contain
+registers which @emph{might} be shared by @var{a}, and GCC considers those
+registers to be inputs to the asm. As above, GCC assumes that such input
+registers are consumed before any outputs are written. This assumption may
+result in incorrect behavior if the asm writes to @var{a} before using
+@var{b}. Combining the `@code{&}' constraint with the register constraint
+ensures that modifying @var{a} will not affect what address is referenced by
+@var{b}. Omitting the `@code{&}' constraint means that the location of @var{b}
+will be undefined if @var{a} is modified before using @var{b}.
+
+@code{asm} supports operand modifiers on operands (for example @code{%k2}
+instead of simply @code{%2}). Typically these qualifiers are hardware
+dependent. The list of supported modifiers for i386 is found at
+@ref{i386Operandmodifiers,i386 Operand modifiers}.
+
+If the C code that follows the @code{asm} makes no use of any of the output
+operands, use @code{volatile} for the @code{asm} statement to prevent the
+optimizers from discarding the @code{asm} statement as unneeded
+(see @ref{Volatile}).
+
+Examples:
+
+This code makes no use of the optional asmSymbolicName. Therefore it
+references the first output operand as @code{%0} (were there a second, it
+would be @code{%1}, etc). The number of the first input operand is one greater
+than that of the last output operand. In this i386 example, that makes
+@var{Mask} @code{%1}:
+
+@example
+uint32_t Mask = 1234;
+uint32_t Index;
+
+ asm ("bsfl %1, %0"
+ : "=r" (Index)
+ : "r" (Mask)
+ : "cc");
+@end example
+
+That code overwrites the variable Index ("="), placing the value in a register
+("r"). The generic "r" constraint instead of a constraint for a specific
+register allows the compiler to pick the register to use, which can result
+in more efficient code. This may not be possible if an assembler instruction
+requires a specific register.
+
+The following i386 example uses the asmSymbolicName operand. It produces the
+same result as the code above, but some may consider it more readable or more
+maintainable since reordering index numbers is not necessary when adding or
+removing operands. The names aIndex and aMask are only used to emphasize which
+names get used where. It is acceptable to reuse the names Index and Mask.
+
+@example
+uint32_t Mask = 1234;
+uint32_t Index;
+
+ asm ("bsfl %[aMask], %[aIndex]"
+ : [aIndex] "=r" (Index)
+ : [aMask] "r" (Mask)
+ : "cc");
+@end example
+
+Here are some more examples of output operands.
+
+@example
+uint32_t c = 1;
+uint32_t d;
+uint32_t *e = &c;
+
+asm ("mov %[e], %[d]"
+ : [d] "=rm" (d)
+ : [e] "rm" (*e));
+@end example
+
+Here, @var{d} may either be in a register or in memory. Since the compiler
+might already have the current value of the uint32_t pointed to by @var{e}
+in a register, you can enable it to choose the best location
+for @var{d} by specifying both constraints.
+
+@anchor{InputOperands}
+@subsubsection Input Operands
+@cindex @code{asm} input operands
+@cindex @code{asm} expressions
+
+Input operands make inputs from C variables and expressions available to the
+assembly code.
+
+Specify input operands by using the format:
+
+@example
+[ [asmSymbolicName] ] "constraint" (cexpression)
+@end example
+
+@emph{asmSymbolicName}
+@*
+When not using asmSymbolicNames, use the (zero-based) position of the operand
+in the list of operands, including outputs, in the assembler template. For
+example, if there are two output parameters and three inputs, @code{%2} refers
+to the first input, @code{%3} to the second, and @code{%4} to the third.
+When using an asmSymbolicName, reference it by enclosing the name in square
+brackets (e.g. @code{%[Value]}). The scope of the name is the @code{asm}
+statement that contains the definition. Any valid C variable name is
+acceptable, including names already defined in the surrounding code. No two
+operands within the same @code{asm} statement can use the same symbolic name.
+
+@emph{constraint}
+@*
+Input constraints must be a string containing one or more constraints
+(@pxref{Constraints}). When you give more than one possible constraint
+(for example, @code{"irm"}), the compiler will choose the most efficient
+method based on the current context. Input constraints may not begin with
+either "=" or "+". If you must use a specific register, but your Machine
+Constraints do not provide sufficient control to select the specific
+register you want, Local Reg Vars may provide a solution
+(@pxref{Local Reg Vars}).
+
+Input constraints can also be digits (for example, @code{"0"}). This indicates
+that the specified input will be in the same place as the output constraint
+at the (zero-based) index in the output constraint list. When using
+asmSymbolicNames for the output operands, you may use these names (enclosed
+in brackets []) instead of digits.
+
+@emph{cexpression}
+@*
+This is the C variable or expression being passed to the @code{asm} statement
+as input.
+
+When the compiler selects the registers to use to represent the input
+operands, it will not use any of the clobbered registers (@pxref{Clobbers}).
+
+If there are no output operands but there are input operands, place two
+consecutive colons where the output operands would go:
+
+@example
+__asm__ ("some instructions"
+ : /* No outputs. */
+ : "r" (Offset / 8);
+@end example
+
+@strong{Warning:} Do @emph{not} modify the contents of input-only operands
+(except for inputs tied to outputs). The compiler assumes that on exit from
+the @code{asm} statement these operands will contain the same values as they
+had before executing the assembler. It is @emph{not} possible to use Clobbers
+to inform the compiler that the values in these inputs are changing. One
+common work-around is to tie the changing input variable to an output variable
+that never gets used. Note, however, that if the code that follows the
+@code{asm} statement makes no use of any of the output operands, the GCC
+optimizers may discard the @code{asm} statement as unneeded
+(see @ref{Volatile}).
+
+Remarks:
+
+The total number of input + output + goto operands has a limit of 30.
+
+@code{asm} supports operand modifiers on operands (for example @code{%k2}
+instead of simply @code{%2}). Typically these qualifiers are hardware
+dependent. The list of supported modifiers for i386 is found at
+@ref{i386Operandmodifiers,i386 Operand modifiers}.
+
+Examples:
+
+In this example using the fictitious @code{combine} instruction, the
+constraint @code{"0"} for input operand 1 says that it must occupy the same
+location as output operand 0. Only input operands may use numbers in
+constraints, and they must each refer to an output operand. Only a number (or
+the symbolic assembler name) in the constraint can guarantee that one operand
+is in the same place as another. The mere fact that @var{foo} is the value of
+both operands is not enough to guarantee that they are in the same place in
+the generated assembler code.
+
+@example
+asm ("combine %2, %0"
+ : "=r" (foo)
+ : "0" (foo), "g" (bar));
+@end example
+
+Here is an example using symbolic names.
+
+@example
+asm ("cmoveq %1, %2, %[result]"
+ : [result] "=r"(result)
+ : "r" (test), "r" (new), "[result]" (old));
+@end example
+
+@anchor{Clobbers}
+@subsubsection Clobbers
+@cindex @code{asm} clobbers
+
+While the compiler is aware of changes to entries listed in the output
+operands, the assembler code may modify more than just the outputs. For
+example, calculations may require additional registers, or the processor may
+overwrite a register as a side effect of a particular assembler instruction.
+In order to inform the compiler of these changes, list them in the clobber
+list. Clobber list items are either register names or the special clobbers
+(listed below). Each clobber list item is enclosed in double quotes and
+separated by commas.
+
+Clobber descriptions may not in any way overlap with an input or output
+operand. For example, you may not have an operand describing a register class
+with one member when listing that register in the clobber list. Variables
+declared to live in specific registers (@pxref{Explicit Reg Vars}), and used
+as @code{asm} input or output operands, must have no part mentioned in the
+clobber description. In particular, there is no way to specify that input
+operands get modified without also specifying them as output operands.
+
+When the compiler selects which registers to use to represent input and output
+operands, it will not use any of the clobbered registers. As a result,
+clobbered registers are available for any use in the assembler code.
+
+Here is a realistic example for the VAX showing the use of clobbered
+registers:
+
+@example
+asm volatile ("movc3 %0, %1, %2"
+ : /* No outputs. */
+ : "g" (from), "g" (to), "g" (count)
+ : "r0", "r1", "r2", "r3", "r4", "r5");
+@end example
+
+Also, there are two special clobber arguments:
+
+@enumerate
+@item
+The @code{"cc"} clobber indicates that the assembler code modifies the flags
+register. On some machines, GCC represents the condition codes as a specific
+hardware register; "cc" serves to name this register. On other machines,
+condition code handling is different, and specifying "cc" has no effect. But
+it is valid no matter what the machine.
+
+@item
+The "memory" clobber tells the compiler that the assembly code performs memory
+reads or writes to items other than those listed in the input and output
+operands (for example accessing the memory pointed to by one of the input
+parameters). To ensure memory contains correct values, GCC may need to flush
+specific register values to memory before executing the @code{asm}. Further,
+the compiler will not assume that any values read from memory before an
+@code{asm} will remain unchanged after that @code{asm}; it will reload them as
+needed. This effectively forms a read/write memory barrier for the compiler.
+
+Note that this clobber does not prevent the @emph{processor} from doing
+speculative reads past the @code{asm} statement. To prevent that, you need
+processor-specific fence instructions.
+
+Flushing registers to memory has performance implications and may be an issue
+for time-sensitive code. One trick to avoid this is available if the size of
+the memory being accessed is known at compile time. For example, if accessing
+ten bytes of a string, use a memory input like:
+
+@code{@{"m"( (@{ struct @{ char x[10]; @} *p = (void *)ptr ; *p; @}) )@}}.
+
+@end enumerate
+
+@anchor{GotoLabels}
+@subsubsection Goto Labels
+@cindex @code{asm} goto labels
+
+@code{asm goto} allows assembly code to jump to one or more C labels. The
+GotoLabels section in an @code{asm goto} statement contains a comma-separated
+list of all C labels to which the assembler code may jump. GCC assumes that
+@code{asm} execution falls through to the next statement (if this is not the
+case, consider using the @code{__builtin_unreachable} intrinsic after the
+@code{asm} statement). Optimization of @code{asm goto} may be improved by
+using the @code{hot} and @code{cold} label attributes (@pxref{Label
+Attributes}). The total number of input + output + goto operands has
+a limit of 30.
+
+An @code{asm goto} statement can not have outputs (which means that the
+statement is implicitly volatile). This is due to an internal restriction of
+the compiler: control transfer instructions cannot have outputs. If the
+assembler code does modify anything, use the "memory" clobber to force the
+optimizers to flush all register values to memory, and reload them if
+necessary, after the @code{asm} statement.
+
+To reference a label, prefix it with @code{%l} (that's a lowercase L) followed
+by its (zero-based) position in GotoLabels plus the number of input
+arguments. For example, if the @code{asm} has three inputs and references two
+labels, refer to the first label as @code{%l3} and the second as @code{%l4}).
+
+@code{asm} statements may not perform jumps into other @code{asm} statements.
+GCC's optimizers do not know about these jumps; therefore they cannot take
+account of them when deciding how to optimize.
+
+Example code for i386 might look like:
+
+@example
+asm goto (
+ "btl %1, %0\n\t"
+ "jc %l2"
+ : /* No outputs. */
+ : "r" (p1), "r" (p2)
+ : "cc"
+ : carry);
+
+return 0;
+
+carry:
+return 1;
+@end example
+
+The following example shows an @code{asm goto} that uses the memory clobber.
+
+@example
int frob(int x)
@{
int y;
asm goto ("frob %%r5, %1; jc %l[error]; mov (%2), %%r5"
- : : "r"(x), "r"(&y) : "r5", "memory" : error);
+ : /* No outputs. */
+ : "r"(x), "r"(&y)
+ : "r5", "memory"
+ : error);
return y;
- error:
+error:
return -1;
@}
-@end smallexample
+@end example
-@noindent
-In this (inefficient) example, the @code{frob} instruction sets the
-carry bit to indicate an error. The @code{jc} instruction detects
-this and branches to the @code{error} label. Finally, the output
-of the @code{frob} instruction (@code{%r5}) is stored into the memory
-for variable @code{y}, which is later read by the @code{return} statement.
+@anchor{i386Operandmodifiers}
+@subsubsection i386 Operand modifiers
-@smallexample
-void doit(void)
+Input, output, and goto operands for extended @code{asm} statements can use
+modifiers to affect the code output to the assembler. For example, the
+following code uses the "h" and "b" modifiers for i386:
+
+@example
+uint16_t num;
+asm volatile ("xchg %h0, %b0" : "+a" (num) );
+@end example
+
+These modifiers generate this assembler code:
+
+@example
+xchg %ah, %al
+@end example
+
+The rest of this discussion uses the following code for illustrative purposes.
+
+@example
+int main()
@{
- int i = 0;
- asm goto ("mfsr %%r1, 123; jmp %%r1;"
- ".pushsection doit_table;"
- ".long %l0, %l1, %l2, %l3;"
- ".popsection"
- : : : "r1" : label1, label2, label3, label4);
- __builtin_unreachable ();
-
- label1:
- f1();
- return;
- label2:
- f2();
- return;
- label3:
- i = 1;
- label4:
- f3(i);
-@}
-@end smallexample
+ int iInt = 1;
-@noindent
-In this (also inefficient) example, the @code{mfsr} instruction reads
-an address from some out-of-band machine register, and the following
-@code{jmp} instruction branches to that address. The address read by
-the @code{mfsr} instruction is assumed to have been previously set via
-some application-specific mechanism to be one of the four values stored
-in the @code{doit_table} section. Finally, the @code{asm} is followed
-by a call to @code{__builtin_unreachable} to indicate that the @code{asm}
-does not in fact fall through.
-
-@smallexample
-#define TRACE1(NUM) \
- do @{ \
- asm goto ("0: nop;" \
- ".pushsection trace_table;" \
- ".long 0b, %l0;" \
- ".popsection" \
- : : : : trace#NUM); \
- if (0) @{ trace#NUM: trace(); @} \
- @} while (0)
-#define TRACE TRACE1(__COUNTER__)
-@end smallexample
+top:
-@noindent
-In this example (which in fact inspired the @code{asm goto} feature)
-we want on rare occasions to call the @code{trace} function; on other
-occasions we'd like to keep the overhead to the absolute minimum.
-The normal code path consists of a single @code{nop} instruction.
-However, we record the address of this @code{nop} together with the
-address of a label that calls the @code{trace} function. This allows
-the @code{nop} instruction to be patched at run time to be an
-unconditional branch to the stored label. It is assumed that an
-optimizing compiler moves the labeled block out of line, to
-optimize the fall through path from the @code{asm}.
-
-If you are writing a header file that should be includable in ISO C
-programs, write @code{__asm__} instead of @code{asm}. @xref{Alternate
-Keywords}.
+ asm volatile goto ("some assembler instructions here"
+ : /* No outputs. */
+ : "q" (iInt), "X" (sizeof(unsigned char) + 1)
+ : /* No clobbers. */
+ : top);
+@}
+@end example
-@subsection Size of an @code{asm}
+With no modifiers, this is what the output from the operands would be for the
+att and intel dialects of assembler:
+
+@multitable {Operand} {masm=att} {OFFSET FLAT:.L2}
+@headitem Operand @tab masm=att @tab masm=intel
+@item @code{%0}
+@tab @code{%eax}
+@tab @code{eax}
+@item @code{%1}
+@tab @code{$2}
+@tab @code{2}
+@item @code{%2}
+@tab @code{$.L2}
+@tab @code{OFFSET FLAT:.L2}
+@end multitable
-Some targets require that GCC track the size of each instruction used in
-order to generate correct code. Because the final length of an
-@code{asm} is only known by the assembler, GCC must make an estimate as
-to how big it will be. The estimate is formed by counting the number of
-statements in the pattern of the @code{asm} and multiplying that by the
-length of the longest instruction on that processor. Statements in the
-@code{asm} are identified by newline characters and whatever statement
-separator characters are supported by the assembler; on most processors
-this is the @samp{;} character.
-
-Normally, GCC's estimate is perfectly adequate to ensure that correct
-code is generated, but it is possible to confuse the compiler if you use
-pseudo instructions or assembler macros that expand into multiple real
-instructions or if you use assembler directives that expand to more
-space in the object file than is needed for a single instruction.
-If this happens then the assembler produces a diagnostic saying that
-a label is unreachable.
+The table below shows the list of supported modifiers and their effects.
+
+@multitable {Modifier} {Print the opcode suffix for the size of th} {Operand} {masm=att} {masm=intel}
+@headitem Modifier @tab Description @tab Operand @tab @option{masm=att} @tab @option{masm=intel}
+@item @code{z}
+@tab Print the opcode suffix for the size of the current integer operand (one of @code{b}/@code{w}/@code{l}/@code{q}).
+@tab @code{%z0}
+@tab @code{l}
+@tab
+@item @code{b}
+@tab Print the QImode name of the register.
+@tab @code{%b0}
+@tab @code{%al}
+@tab @code{al}
+@item @code{h}
+@tab Print the QImode name for a ``high'' register.
+@tab @code{%h0}
+@tab @code{%ah}
+@tab @code{ah}
+@item @code{w}
+@tab Print the HImode name of the register.
+@tab @code{%w0}
+@tab @code{%ax}
+@tab @code{ax}
+@item @code{k}
+@tab Print the SImode name of the register.
+@tab @code{%k0}
+@tab @code{%eax}
+@tab @code{eax}
+@item @code{q}
+@tab Print the DImode name of the register.
+@tab @code{%q0}
+@tab @code{%rax}
+@tab @code{rax}
+@item @code{l}
+@tab Print the label name with no punctuation.
+@tab @code{%l2}
+@tab @code{.L2}
+@tab @code{.L2}
+@item @code{c}
+@tab Require a constant operand and print the constant expression with no punctuation.
+@tab @code{%c1}
+@tab @code{2}
+@tab @code{2}
+@end multitable
-@subsection i386 floating-point asm operands
+@anchor{i386floatingpointasmoperands}
+@subsubsection i386 floating-point asm operands
On i386 targets, there are several rules on the usage of stack-like registers
in the operands of an @code{asm}. These rules apply only to the operands
@@ -6715,10 +7262,12 @@ for the compiler to know that @code{fyl2xp1} pops both inputs.
asm ("fyl2xp1" : "=t" (result) : "0" (x), "u" (y) : "st(1)");
@end smallexample
+@lowersections
@include md.texi
+@raisesections
@node Asm Labels
-@section Controlling Names Used in Assembler Code
+@subsection Controlling Names Used in Assembler Code
@cindex assembler names for identifiers
@cindex names used in assembler code
@cindex identifiers, names in assembler code
@@ -6766,7 +7315,7 @@ does not as yet have the ability to store static variables in registers.
Perhaps that will be added.
@node Explicit Reg Vars
-@section Variables in Specified Registers
+@subsection Variables in Specified Registers
@cindex explicit register variables
@cindex variables in specified registers
@cindex specified registers
@@ -6806,7 +7355,7 @@ specified for that operand in the @code{asm}.)
@end menu
@node Global Reg Vars
-@subsection Defining Global Register Variables
+@subsubsection Defining Global Register Variables
@cindex global register variables
@cindex registers, global variables in
@@ -6903,7 +7452,7 @@ On the 68000, a2 @dots{} a5 should be suitable, as should d2 @dots{} d7.
Of course, it does not do to use more than a few of those.
@node Local Reg Vars
-@subsection Specifying Registers for Local Variables
+@subsubsection Specifying Registers for Local Variables
@cindex local variables, specifying registers
@cindex specifying registers for local variables
@cindex registers for local variables
@@ -6946,21 +7495,59 @@ Stores into local register variables may be deleted when they appear to be dead
according to dataflow analysis. References to local register variables may
be deleted or moved or simplified.
-As for global register variables, it's recommended that you choose a
+As with global register variables, it is recommended that you choose a
register that is normally saved and restored by function calls on
-your machine, so that library routines will not clobber it. A common
-pitfall is to initialize multiple call-clobbered registers with
-arbitrary expressions, where a function call or library call for an
-arithmetic operator overwrites a register value from a previous
-assignment, for example @code{r0} below:
+your machine, so that library routines will not clobber it.
+
+Sometimes when writing inline @code{asm} code, you need to make an operand be a
+specific register, but there's no matching constraint letter for that
+register. To force the operand into that register, create a local variable
+and specify the register in the variable's declaration. Then use the local
+variable for the asm operand and specify any constraint letter that matches
+the register:
+
@smallexample
register int *p1 asm ("r0") = @dots{};
register int *p2 asm ("r1") = @dots{};
+register int *result asm ("r0");
+asm ("sysint" : "=r" (result) : "0" (p1), "r" (p2));
@end smallexample
-@noindent
-In those cases, a solution is to use a temporary variable for
-each arbitrary expression. @xref{Example of asm with clobbered asm reg}.
+@emph{Warning:} In the above example, be aware that a register (for example r0) can be
+call-clobbered by subsequent code, including function calls and library calls
+for arithmetic operators on other variables (for example the initialization
+of p2). In this case, use temporary variables for expressions between the
+register assignments:
+
+@smallexample
+int t1 = @dots{};
+register int *p1 asm ("r0") = @dots{};
+register int *p2 asm ("r1") = t1;
+register int *result asm ("r0");
+asm ("sysint" : "=r" (result) : "0" (p1), "r" (p2));
+@end smallexample
+
+@node Size of an asm
+@subsection Size of an @code{asm}
+
+Some targets require that GCC track the size of each instruction used
+in order to generate correct code. Because the final length of the
+code produced by an @code{asm} statement is only known by the
+assembler, GCC must make an estimate as to how big it will be. It
+does this by counting the number of instructions in the pattern of the
+@code{asm} and multiplying that by the length of the longest
+instruction supported by that processor. (When working out the number
+of instructions, it assumes that any occurrence of a newline or of
+whatever statement separator character is supported by the assembler --
+typically @samp{;} --- indicates the end of an instruction.)
+
+Normally, GCC's estimate is adequate to ensure that correct
+code is generated, but it is possible to confuse the compiler if you use
+pseudo instructions or assembler macros that expand into multiple real
+instructions, or if you use assembler directives that expand to more
+space in the object file than is needed for a single instruction.
+If this happens then the assembler may produce a diagnostic saying that
+a label is unreachable.
@node Alternate Keywords
@section Alternate Keywords
@@ -9107,6 +9694,7 @@ to those machines. Generally these generate calls to specific machine
instructions, but allow the compiler to schedule those calls.
@menu
+* AArch64 Built-in Functions::
* Alpha Built-in Functions::
* Altera Nios II Built-in Functions::
* ARC Built-in Functions::
@@ -9114,6 +9702,7 @@ instructions, but allow the compiler to schedule those calls.
* ARM iWMMXt Built-in Functions::
* ARM NEON Intrinsics::
* ARM ACLE Intrinsics::
+* ARM Floating Point Status and Control Intrinsics::
* AVR Built-in Functions::
* Blackfin Built-in Functions::
* FR-V Built-in Functions::
@@ -9139,6 +9728,18 @@ instructions, but allow the compiler to schedule those calls.
* TILEPro Built-in Functions::
@end menu
+@node AArch64 Built-in Functions
+@subsection AArch64 Built-in Functions
+
+These built-in functions are available for the AArch64 family of
+processors.
+@smallexample
+unsigned int __builtin_aarch64_get_fpcr ()
+void __builtin_aarch64_set_fpcr (unsigned int)
+unsigned int __builtin_aarch64_get_fpsr ()
+void __builtin_aarch64_set_fpsr (unsigned int)
+@end smallexample
+
@node Alpha Built-in Functions
@subsection Alpha Built-in Functions
@@ -9918,6 +10519,17 @@ the @option{-march=armv8-a+crc} switch is used:
@include arm-acle-intrinsics.texi
+@node ARM Floating Point Status and Control Intrinsics
+@subsection ARM Floating Point Status and Control Intrinsics
+
+These built-in functions are available for the ARM family of
+processors with floating-point unit.
+
+@smallexample
+unsigned int __builtin_arm_get_fpscr ()
+void __builtin_arm_set_fpscr (unsigned int)
+@end smallexample
+
@node AVR Built-in Functions
@subsection AVR Built-in Functions
@@ -11335,7 +11947,7 @@ used. All of them generate the machine instruction that is part of the
name.
@smallexample
-v32qi __builtin_ia32_mpsadbw256 (v32qi,v32qi,v32qi,int)
+v32qi __builtin_ia32_mpsadbw256 (v32qi,v32qi,int)
v32qi __builtin_ia32_pabsb256 (v32qi)
v16hi __builtin_ia32_pabsw256 (v16hi)
v8si __builtin_ia32_pabsd256 (v8si)
@@ -11570,8 +12182,8 @@ The following built-in functions are available when @option{-mxop} is used.
@smallexample
v2df __builtin_ia32_vfrczpd (v2df)
v4sf __builtin_ia32_vfrczps (v4sf)
-v2df __builtin_ia32_vfrczsd (v2df, v2df)
-v4sf __builtin_ia32_vfrczss (v4sf, v4sf)
+v2df __builtin_ia32_vfrczsd (v2df)
+v4sf __builtin_ia32_vfrczss (v4sf)
v4df __builtin_ia32_vfrczpd256 (v4df)
v8sf __builtin_ia32_vfrczps256 (v8sf)
v2di __builtin_ia32_vpcmov (v2di, v2di, v2di)
@@ -12701,6 +13313,15 @@ This sets the indicated bits in the saved copy of the status register
currently residing on the stack. This only works inside interrupt
handlers and the changes to the status register will only take affect
once the handler returns.
+
+@item __delay_cycles (long long @var{cycles})
+This inserts an instruction sequence that takes exactly @var{cycles}
+cycles (between 0 and about 17E9) to complete. The inserted sequence
+may use jumps, loops, or no-ops, and does not interfere with any other
+instructions. Note that @var{cycles} must be a compile-time constant
+integer - that is, you must pass a number, not a variable that may be
+optimized to a constant later. The number of cycles delayed by this
+builtin is exact.
@end table
@node NDS32 Built-in Functions
@@ -16392,11 +17013,9 @@ adding a call to the @code{.init} section.
@node Symbol-Renaming Pragmas
@subsection Symbol-Renaming Pragmas
-For compatibility with the Solaris system headers, GCC
-supports two @code{#pragma} directives that change the name used in
-assembly for a given declaration. To get this effect
-on all platforms supported by GCC, use the asm labels extension (@pxref{Asm
-Labels}).
+GCC supports a @code{#pragma} directive that changes the name used in
+assembly for a given declaration. This effect can also be achieved
+using the asm labels extension (@pxref{Asm Labels}).
@table @code
@item redefine_extname @var{oldname} @var{newname}
@@ -16408,17 +17027,17 @@ is defined if this pragma is available (currently on all platforms).
@end table
This pragma and the asm labels extension interact in a complicated
-manner. Here are some corner cases you may want to be aware of.
+manner. Here are some corner cases you may want to be aware of:
@enumerate
-@item Both pragmas silently apply only to declarations with external
+@item This pragma silently applies only to declarations with external
linkage. Asm labels do not have this restriction.
-@item In C++, both pragmas silently apply only to declarations with
+@item In C++, this pragma silently applies only to declarations with
``C'' linkage. Again, asm labels do not have this restriction.
-@item If any of the three ways of changing the assembly name of a
-declaration is applied to a declaration whose assembly name has
+@item If either of the ways of changing the assembly name of a
+declaration are applied to a declaration whose assembly name has
already been determined (either by a previous use of one of these
features, or because the compiler needed the assembly name in order to
generate code), and the new name is different, a warning issues and
@@ -16584,8 +17203,7 @@ TODO - Remember to fix this}.
This pragma allows the user to set the visibility for multiple
declarations without having to give each a visibility attribute
-@xref{Function Attributes}, for more information about visibility and
-the attribute syntax.
+(@pxref{Function Attributes}).
In C++, @samp{#pragma GCC visibility} affects only namespace-scope
declarations. Class members and template specializations are not
diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
index d32ac00e48e..e50eef66b3e 100644
--- a/gcc/doc/gty.texi
+++ b/gcc/doc/gty.texi
@@ -382,38 +382,6 @@ of pointers. @code{reorder} functions can be expensive. When
possible, it is better to depend on properties of the data, like an ID
number or the hash of a string instead.
-@findex variable_size
-@item variable_size
-
-The type machinery expects the types to be of constant size. When this
-is not true, for example, with structs that have array fields or unions,
-the type machinery cannot tell how many bytes need to be allocated at
-each allocation. The @code{variable_size} is used to mark such types.
-The type machinery then provides allocators that take a parameter
-indicating an exact size of object being allocated. Note that the size
-must be provided in bytes whereas the @code{length} option works with
-array lengths in number of elements.
-
-For example,
-@smallexample
-struct GTY((variable_size)) sorted_fields_type @{
- int len;
- tree GTY((length ("%h.len"))) elts[1];
-@};
-@end smallexample
-
-Then the objects of @code{struct sorted_fields_type} are allocated in GC
-memory as follows:
-@smallexample
- field_vec = ggc_alloc_sorted_fields_type (size);
-@end smallexample
-
-If @var{field_vec->elts} stores @var{n} elements, then @var{size}
-could be calculated as follows:
-@smallexample
- size_t size = sizeof (struct sorted_fields_type) + n * sizeof (tree);
-@end smallexample
-
@findex atomic
@item atomic
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 3fe9d5f302c..94755949d65 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -216,6 +216,8 @@ Objective-C and Objective-C++ Dialects}.
-fobjc-gc @gol
-fobjc-nilcheck @gol
-fobjc-std=objc1 @gol
+-fno-local-ivars @gol
+-fivar-visibility=@var{public|protected|private|package} @gol
-freplace-objc-classes @gol
-fzero-link @gol
-gen-decls @gol
@@ -262,7 +264,7 @@ Objective-C and Objective-C++ Dialects}.
-Wparentheses -Wpedantic-ms-format -Wno-pedantic-ms-format @gol
-Wpointer-arith -Wno-pointer-to-int-cast @gol
-Wredundant-decls -Wno-return-local-addr @gol
--Wreturn-type -Wsequence-point -Wshadow @gol
+-Wreturn-type -Wsequence-point -Wshadow -Wno-shadow-ivar @gol
-Wsign-compare -Wsign-conversion -Wfloat-conversion @gol
-Wsizeof-pointer-memaccess @gol
-Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol
@@ -427,8 +429,8 @@ Objective-C and Objective-C++ Dialects}.
-ftree-vectorize -ftree-vrp @gol
-funit-at-a-time -funroll-all-loops -funroll-loops @gol
-funsafe-loop-optimizations -funsafe-math-optimizations -funswitch-loops @gol
--fvariable-expansion-in-unroller -fvect-cost-model -fvpt -fweb @gol
--fwhole-program -fwpa -fuse-ld=@var{linker} -fuse-linker-plugin @gol
+-fuse-caller-save -fvariable-expansion-in-unroller -fvect-cost-model -fvpt @gol
+-fweb -fwhole-program -fwpa -fuse-ld=@var{linker} -fuse-linker-plugin @gol
--param @var{name}=@var{value}
-O -O0 -O1 -O2 -O3 -Os -Ofast -Og}
@@ -670,6 +672,7 @@ Objective-C and Objective-C++ Dialects}.
-mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -mavx @gol
-mavx2 -mavx512f -mavx512pf -mavx512er -mavx512cd -msha @gol
-maes -mpclmul -mfsgsbase -mrdrnd -mf16c -mfma -mprefetchwt1 @gol
+-mclflushopt -mxsavec -mxsaves @gol
-msse4a -m3dnow -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop -mlzcnt @gol
-mbmi2 -mfxsr -mxsave -mxsaveopt -mrtm -mlwp -mthreads @gol
-mno-align-stringops -minline-all-stringops @gol
@@ -870,7 +873,7 @@ Objective-C and Objective-C++ Dialects}.
See RS/6000 and PowerPC Options.
@emph{RL78 Options}
-@gccoptlist{-msim -mmul=none -mmul=g13 -mmul=rl78}
+@gccoptlist{-msim -mmul=none -mmul=g13 -mmul=rl78 -m64bit-doubles -m32bit-doubles}
@emph{RS/6000 and PowerPC Options}
@gccoptlist{-mcpu=@var{cpu-type} @gol
@@ -980,7 +983,7 @@ See RS/6000 and PowerPC Options.
-mpretend-cmove -mtas}
@emph{Solaris 2 Options}
-@gccoptlist{-mimpure-text -mno-impure-text @gol
+@gccoptlist{-mclear-hwcap -mno-clear-hwcap -mimpure-text -mno-impure-text @gol
-pthreads -pthread}
@emph{SPARC Options}
@@ -2977,6 +2980,22 @@ for individual class implementations to be modified during program execution.
The GNU runtime currently always retains calls to @code{objc_get_class("@dots{}")}
regardless of command-line options.
+@item -fno-local-ivars
+@opindex fno-local-ivars
+@opindex flocal-ivars
+By default instance variables in Objective-C can be accessed as if
+they were local variables from within the methods of the class they're
+declared in. This can lead to shadowing between instance variables
+and other variables declared either locally inside a class method or
+globally with the same name. Specifying the @option{-fno-local-ivars}
+flag disables this behavior thus avoiding variable shadowing issues.
+
+@item -fivar-visibility=@var{public|protected|private|package}
+@opindex fivar-visibility
+Set the default instance variable visibility to the specified option
+so that instance variables declared outside the scope of any access
+modifier directives default to the specified visibility.
+
@item -gen-decls
@opindex gen-decls
Dump interface declarations for all classes seen in the source file to a
@@ -4360,10 +4379,17 @@ Do not warn whenever an @samp{#else} or an @samp{#endif} are followed by text.
@item -Wshadow
@opindex Wshadow
@opindex Wno-shadow
-Warn whenever a local variable or type declaration shadows another variable,
-parameter, type, or class member (in C++), or whenever a built-in function
-is shadowed. Note that in C++, the compiler warns if a local variable
-shadows an explicit typedef, but not if it shadows a struct/class/enum.
+Warn whenever a local variable or type declaration shadows another
+variable, parameter, type, class member (in C++), or instance variable
+(in Objective-C) or whenever a built-in function is shadowed. Note
+that in C++, the compiler warns if a local variable shadows an
+explicit typedef, but not if it shadows a struct/class/enum.
+
+@item -Wno-shadow-ivar @r{(Objective-C only)}
+@opindex Wno-shadow-ivar
+@opindex Wshadow-ivar
+Do not warn whenever a local variable shadows an instance variable in an
+Objective-C method.
@item -Wlarger-than=@var{len}
@opindex Wlarger-than=@var{len}
@@ -5401,6 +5427,13 @@ Detect floating-point division by zero. Unlike other similar options,
@option{-fsanitize=undefined}, since floating-point division by zero can
be a legitimate way of obtaining infinities and NaNs.
+@item -fsanitize=float-cast-overflow
+@opindex fsanitize=float-cast-overflow
+
+This option enables floating-point type to integer conversion checking.
+We check that the result of the conversion does not overflow.
+This option does not work well with @code{FE_INVALID} exceptions enabled.
+
@item -fsanitize-recover
@opindex fsanitize-recover
By default @option{-fsanitize=undefined} sanitization (and its suboptions
@@ -7437,7 +7470,8 @@ Attempt to remove redundant extension instructions. This is especially
helpful for the x86-64 architecture, which implicitly zero-extends in 64-bit
registers after writing to their lower 32-bit half.
-Enabled for AArch64 and x86 at levels @option{-O2}, @option{-O3}.
+Enabled for Alpha, AArch64 and x86 at levels @option{-O2},
+@option{-O3}, @option{-Os}.
@item -flive-range-shrinkage
@opindex flive-range-shrinkage
@@ -7707,6 +7741,14 @@ and then tries to find ways to combine them.
Enabled by default at @option{-O1} and higher.
+@item -fuse-caller-save
+Use caller save registers for allocation if those registers are not used by
+any called function. In that case it is not necessary to save and restore
+them around calls. This is only possible if called functions are part of
+same compilation unit as current function and they are compiled before it.
+
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -fconserve-stack
@opindex fconserve-stack
Attempt to minimize stack usage. The compiler attempts to use less
@@ -8753,6 +8795,9 @@ as an algorithm disables partitioning and streaming completely.
The default value is @code{balanced}. While @code{1to1} can be used
as an workaround for various code ordering issues, the @code{max}
partitioning is intended for internal testing only.
+The value @code{one} specifies that exactly one partition should be
+used while the value @code{none} bypasses partitioning and executes
+the link-time optimization step directly from the WPA phase.
@item -flto-compression-level=@var{n}
This option specifies the level of compression used for intermediate
@@ -10049,6 +10094,35 @@ parameter in order to propagate them and perform devirtualization.
@option{ipa-cp-value-list-size} is the maximum number of values and types it
stores per one formal parameter of a function.
+@item ipa-cp-eval-threshold
+IPA-CP calculates its own score of cloning profitability heuristics
+and performs those cloning opportunities with scores that exceed
+@option{ipa-cp-eval-threshold}.
+
+@item ipa-max-agg-items
+IPA-CP is also capable to propagate a number of scalar values passed
+in an aggregate. @option{ipa-max-agg-items} controls the maximum
+number of such values per one parameter.
+
+@item ipa-cp-loop-hint-bonus
+When IPA-CP determines that a cloning candidate would make the number
+of iterations of a loop known, it adds a bonus of
+@option{ipa-cp-loop-hint-bonus} bonus to the profitability score of
+the candidate.
+
+@item ipa-cp-array-index-hint-bonus
+When IPA-CP determines that a cloning candidate would make the index of
+an array access known, it adds a bonus of
+@option{ipa-cp-array-index-hint-bonus} bonus to the profitability
+score of the candidate.
+
+@item ipa-max-aa-steps
+During its analysis of function bodies, IPA-CP employs alias analysis
+in order to track values pointed to by function parameters. In order
+not spend too much time analyzing huge functions, it will give up and
+consider all memory clobbered after examining
+@option{ipa-max-aa-steps} statements modifying memory.
+
@item lto-partitions
Specify desired number of partitions produced during WHOPR compilation.
The number of partitions should exceed the number of CPUs used for compilation.
@@ -15312,6 +15386,8 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
@itemx -mno-aes
@itemx -mpclmul
@itemx -mno-pclmul
+@itemx -mclfushopt
+@itemx -mno-clflsuhopt
@need 800
@itemx -mfsgsbase
@itemx -mno-fsgsbase
@@ -15350,6 +15426,10 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
@itemx -mrtm
@itemx -mtbm
@itemx -mno-tbm
+@itemx -mxsavec
+@itemx -mno-xsavec
+@itemx -mxsaves
+@itemx -mno-xsaves
@opindex mmmx
@opindex mno-mmx
@opindex msse
@@ -18845,6 +18925,14 @@ The @code{g13} option is for the hardware multiply/divide peripheral
only on the RL78/G13 targets. The @code{rl78} option is for the
standard hardware multiplication defined in the RL78 software manual.
+@item -m64bit-doubles
+@itemx -m32bit-doubles
+@opindex m64bit-doubles
+@opindex m32bit-doubles
+Make the @code{double} data type be 64 bits (@option{-m64bit-doubles})
+or 32 bits (@option{-m32bit-doubles}) in size. The default is
+@option{-m32bit-doubles}.
+
@end table
@node RS/6000 and PowerPC Options
@@ -20860,6 +20948,13 @@ patterns. This can result in faster code on the SH4 processor.
These @samp{-m} options are supported on Solaris 2:
@table @gcctabopt
+@item -mclear-hwcap
+@opindex mclear-hwcap
+@option{-mclear-hwcap} tells the compiler to remove the hardware
+capabilities generated by the Solaris assembler. This is only necessary
+when object files use ISA extensions not supported by the current
+machine, but check at runtime whether or not to use them.
+
@item -mimpure-text
@opindex mimpure-text
@option{-mimpure-text}, used in addition to @option{-shared}, tells
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 13e34b5e2a9..7c3d7142aa1 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -1589,7 +1589,10 @@ See, for example, the @samp{mulsi3} insn of the ARM@.
Declares the instruction to be commutative for this operand and the
following operand. This means that the compiler may interchange the
two operands if that is the cheapest way to make all operands fit the
-constraints.
+constraints. @samp{%} applies to all alternatives and must appear as
+the first character in the constraint. Only input operands can use
+@samp{%}.
+
@ifset INTERNALS
This is often used in patterns for addition instructions
that really have only two operands: the result must go in one of the
@@ -4094,11 +4097,11 @@ Unsigned constant valid for BccUI instructions
@subsection Disable insn alternatives using the @code{enabled} attribute
@cindex enabled
-The @code{enabled} insn attribute may be used to disable certain insn
-alternatives for machine-specific reasons. This is useful when adding
-new instructions to an existing pattern which are only available for
-certain cpu architecture levels as specified with the @code{-march=}
-option.
+The @code{enabled} insn attribute may be used to disable insn
+alternatives that are not available for the current subtarget.
+This is useful when adding new instructions to an existing pattern
+which are only available for certain cpu architecture levels as
+specified with the @code{-march=} option.
If an insn alternative is disabled, then it will never be used. The
compiler treats the constraints for the disabled alternative as
@@ -4112,6 +4115,10 @@ in the machine description files:
A definition of the @code{enabled} insn attribute. The attribute is
defined as usual using the @code{define_attr} command. This
definition should be based on other insn attributes and/or target flags.
+The attribute must be a static property of the subtarget; that is, it
+must not depend on the current operands or any other dynamic context
+(for example, the location of the insn within the body of a loop).
+
The @code{enabled} attribute is a numeric attribute and should evaluate to
@code{(const_int 1)} for an enabled alternative and to
@code{(const_int 0)} otherwise.
diff --git a/gcc/doc/passes.texi b/gcc/doc/passes.texi
index fb064db3786..0ab8f21caec 100644
--- a/gcc/doc/passes.texi
+++ b/gcc/doc/passes.texi
@@ -391,11 +391,19 @@ Interprocedural points-to information is located in
@item Profiling
-This pass rewrites the function in order to collect runtime block
+This pass instruments the function in order to collect runtime block
and value profiling data. Such data may be fed back into the compiler
on a subsequent run so as to allow optimization based on expected
-execution frequencies. The pass is located in @file{predict.c} and
-is described by @code{pass_profile}.
+execution frequencies. The pass is located in @file{tree-profile.c} and
+is described by @code{pass_ipa_tree_profile}.
+
+@item Static profile estimation
+
+This pass implements series of heuristics to guess propababilities
+of branches. The resulting predictions are turned into edge profile
+by propagating branches across the control flow graphs.
+The pass is located in @file{tree-profile.c} and is described by
+@code{pass_profile}.
@item Lower complex arithmetic
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 914860813ca..7438980f08e 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1601,6 +1601,13 @@ MIPS target supports @code{-mpaired-single}.
@subsubsection PowerPC-specific attributes
@table @code
+
+@item dfp_hw
+PowerPC target supports executing hardware DFP instructions.
+
+@item p8vector_hw
+PowerPC target supports executing VSX instructions (ISA 2.07).
+
@item powerpc64
Test system supports executing 64-bit instructions.
@@ -1610,12 +1617,24 @@ PowerPC target supports AltiVec.
@item powerpc_altivec_ok
PowerPC target supports @code{-maltivec}.
+@item powerpc_eabi_ok
+PowerPC target supports @code{-meabi}.
+
+@item powerpc_elfv2
+PowerPC target supports @code{-mabi=elfv2}.
+
@item powerpc_fprs
PowerPC target supports floating-point registers.
@item powerpc_hard_double
PowerPC target supports hardware double-precision floating-point.
+@item powerpc_htm_ok
+PowerPC target supports @code{-mhtm}
+
+@item powerpc_p8vector_ok
+PowerPC target supports @code{-mpower8-vector}
+
@item powerpc_ppu_ok
PowerPC target supports @code{-mcpu=cell}.
@@ -1629,9 +1648,6 @@ PowerPC target supports PowerPC SPE.
@item powerpc_spu
PowerPC target supports PowerPC SPU.
-@item spu_auto_overlay
-SPU target has toolchain that supports automatic overlay generation.
-
@item powerpc_vsx_ok
PowerPC target supports @code{-mvsx}.
@@ -1639,8 +1655,17 @@ PowerPC target supports @code{-mvsx}.
Including the options used to compile this particular test, the
PowerPC target supports PowerPC 405.
+@item ppc_recip_hw
+PowerPC target supports executing reciprocal estimate instructions.
+
+@item spu_auto_overlay
+SPU target has toolchain that supports automatic overlay generation.
+
@item vmx_hw
PowerPC target supports executing AltiVec instructions.
+
+@item vsx_hw
+PowerPC target supports executing VSX instructions (ISA 2.06).
@end table
@subsubsection Other hardware attributes
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index fd4e4fd6628..a9613b0f3c3 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -1057,7 +1057,7 @@ the default value is @code{BIGGEST_ALIGNMENT}.
On systems that use ELF, the default (in @file{config/elfos.h}) is
the largest supported 32-bit ELF section alignment representable on
-a 32-bit host e.g. @samp{(((unsigned HOST_WIDEST_INT) 1 << 28) * 8)}.
+a 32-bit host e.g. @samp{(((uint64_t) 1 << 28) * 8)}.
On 32-bit ELF the largest supported section alignment in bits is
@samp{(0x80000000 * 8)}, but this is not representable on 32-bit hosts.
@end defmac
@@ -6716,26 +6716,32 @@ schedules to choose the best one.
The default is no multipass scheduling.
@end deftypefn
-@deftypefn {Target Hook} int TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD (rtx @var{insn})
+@deftypefn {Target Hook} int TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD (rtx @var{insn}, int @var{ready_index})
This hook controls what insns from the ready insn queue will be
considered for the multipass insn scheduling. If the hook returns
-zero for @var{insn}, the insn will be not chosen to
-be issued.
+zero for @var{insn}, the insn will be considered in multipass scheduling.
+Positive return values will remove @var{insn} from consideration on
+the current round of multipass scheduling.
+Negative return values will remove @var{insn} from consideration for given
+number of cycles.
+Backends should be careful about returning non-zero for highest priority
+instruction at position 0 in the ready list. @var{ready_index} is passed
+to allow backends make correct judgements.
The default is that any ready insns can be chosen to be issued.
@end deftypefn
-@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_BEGIN (void *@var{data}, char *@var{ready_try}, int @var{n_ready}, bool @var{first_cycle_insn_p})
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_BEGIN (void *@var{data}, signed char *@var{ready_try}, int @var{n_ready}, bool @var{first_cycle_insn_p})
This hook prepares the target backend for a new round of multipass
scheduling.
@end deftypefn
-@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_ISSUE (void *@var{data}, char *@var{ready_try}, int @var{n_ready}, rtx @var{insn}, const void *@var{prev_data})
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_ISSUE (void *@var{data}, signed char *@var{ready_try}, int @var{n_ready}, rtx @var{insn}, const void *@var{prev_data})
This hook is called when multipass scheduling evaluates instruction INSN.
@end deftypefn
-@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_BACKTRACK (const void *@var{data}, char *@var{ready_try}, int @var{n_ready})
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_BACKTRACK (const void *@var{data}, signed char *@var{ready_try}, int @var{n_ready})
This is called when multipass scheduling backtracks from evaluation of
an instruction.
@end deftypefn
@@ -6843,19 +6849,6 @@ a pattern for a branchy check corresponding to a simple check denoted by
@var{insn} should be generated. In this case @var{label} can't be null.
@end deftypefn
-@deftypefn {Target Hook} bool TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC (const_rtx @var{insn})
-This hook is used as a workaround for
-@samp{TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD} not being
-called on the first instruction of the ready list. The hook is used to
-discard speculative instructions that stand first in the ready list from
-being scheduled on the current cycle. If the hook returns @code{false},
-@var{insn} will not be chosen to be issued.
-For non-speculative instructions,
-the hook should always return @code{true}. For example, in the ia64 backend
-the hook is used to cancel data speculative insns when the ALAT table
-is nearly full.
-@end deftypefn
-
@deftypefn {Target Hook} void TARGET_SCHED_SET_SCHED_FLAGS (struct spec_info_def *@var{spec_info})
This hook is used by the insn scheduler to find out what features should be
enabled/used.
@@ -9725,9 +9718,9 @@ You can have multiple entities that are mode-switched, and select at run time
which entities actually need it. @code{OPTIMIZE_MODE_SWITCHING} should
return nonzero for any @var{entity} that needs mode-switching.
If you define this macro, you also have to define
-@code{NUM_MODES_FOR_MODE_SWITCHING}, @code{MODE_NEEDED},
-@code{MODE_PRIORITY_TO_MODE} and @code{EMIT_MODE_SET}.
-@code{MODE_AFTER}, @code{MODE_ENTRY}, and @code{MODE_EXIT}
+@code{NUM_MODES_FOR_MODE_SWITCHING}, @code{TARGET_MODE_NEEDED},
+@code{TARGET_MODE_PRIORITY} and @code{TARGET_MODE_EMIT}.
+@code{TARGET_MODE_AFTER}, @code{TARGET_MODE_ENTRY}, and @code{TARGET_MODE_EXIT}
are optional.
@end defmac
@@ -9744,51 +9737,29 @@ represented as numbers 0 @dots{} N @minus{} 1. N is used to specify that no mod
switch is needed / supplied.
@end defmac
-@defmac MODE_NEEDED (@var{entity}, @var{insn})
-@var{entity} is an integer specifying a mode-switched entity. If
-@code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this macro to
-return an integer value not larger than the corresponding element in
-@code{NUM_MODES_FOR_MODE_SWITCHING}, to denote the mode that @var{entity} must
-be switched into prior to the execution of @var{insn}.
-@end defmac
+@deftypefn {Target Hook} void TARGET_MODE_EMIT (int @var{entity}, int @var{mode}, HARD_REG_SET @var{regs_live})
+Generate one or more insns to set @var{entity} to @var{mode}. @var{hard_reg_live} is the set of hard registers live at the point where the insn(s) are to be inserted. Sets of a lower numbered entity will be emitted before sets of a higher numbered entity to a mode of the same or lower priority.
+@end deftypefn
-@defmac MODE_AFTER (@var{entity}, @var{mode}, @var{insn})
-@var{entity} is an integer specifying a mode-switched entity. If
-this macro is defined, it is evaluated for every @var{insn} during
-mode switching. It determines the mode that an insn results in (if
-different from the incoming mode).
-@end defmac
+@deftypefn {Target Hook} int TARGET_MODE_NEEDED (int @var{entity}, rtx @var{insn})
+@var{entity} is an integer specifying a mode-switched entity. If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this macro to return an integer value not larger than the corresponding element in @code{NUM_MODES_FOR_MODE_SWITCHING}, to denote the mode that @var{entity} must be switched into prior to the execution of @var{insn}.
+@end deftypefn
-@defmac MODE_ENTRY (@var{entity})
-If this macro is defined, it is evaluated for every @var{entity} that needs
-mode switching. It should evaluate to an integer, which is a mode that
-@var{entity} is assumed to be switched to at function entry. If @code{MODE_ENTRY}
-is defined then @code{MODE_EXIT} must be defined.
-@end defmac
+@deftypefn {Target Hook} int TARGET_MODE_AFTER (int @var{entity}, int @var{mode}, rtx @var{insn})
+@var{entity} is an integer specifying a mode-switched entity. If this macro is defined, it is evaluated for every @var{insn} during mode switching. It determines the mode that an insn results in (if different from the incoming mode).
+@end deftypefn
-@defmac MODE_EXIT (@var{entity})
-If this macro is defined, it is evaluated for every @var{entity} that needs
-mode switching. It should evaluate to an integer, which is a mode that
-@var{entity} is assumed to be switched to at function exit. If @code{MODE_EXIT}
-is defined then @code{MODE_ENTRY} must be defined.
-@end defmac
+@deftypefn {Target Hook} int TARGET_MODE_ENTRY (int @var{entity})
+If this macro is defined, it is evaluated for every @var{entity} that needs mode switching. It should evaluate to an integer, which is a mode that @var{entity} is assumed to be switched to at function entry. If @code{TARGET_MODE_ENTRY} is defined then @code{TARGET_MODE_EXIT} must be defined.
+@end deftypefn
-@defmac MODE_PRIORITY_TO_MODE (@var{entity}, @var{n})
-This macro specifies the order in which modes for @var{entity} are processed.
-0 is the highest priority, @code{NUM_MODES_FOR_MODE_SWITCHING[@var{entity}] - 1} the
-lowest. The value of the macro should be an integer designating a mode
-for @var{entity}. For any fixed @var{entity}, @code{mode_priority_to_mode}
-(@var{entity}, @var{n}) shall be a bijection in 0 @dots{}
-@code{num_modes_for_mode_switching[@var{entity}] - 1}.
-@end defmac
+@deftypefn {Target Hook} int TARGET_MODE_EXIT (int @var{entity})
+If this macro is defined, it is evaluated for every @var{entity} that needs mode switching. It should evaluate to an integer, which is a mode that @var{entity} is assumed to be switched to at function exit. If @code{TARGET_MODE_EXIT} is defined then @code{TARGET_MODE_ENTRY} must be defined.
+@end deftypefn
-@defmac EMIT_MODE_SET (@var{entity}, @var{mode}, @var{hard_regs_live})
-Generate one or more insns to set @var{entity} to @var{mode}.
-@var{hard_reg_live} is the set of hard registers live at the point where
-the insn(s) are to be inserted.
-Sets of a lower numbered entity will be emitted before sets of a higher
-numbered entity to a mode of the same or lower priority.
-@end defmac
+@deftypefn {Target Hook} int TARGET_MODE_PRIORITY (int @var{entity}, int @var{n})
+This macro specifies the order in which modes for @var{entity} are processed. 0 is the highest priority, @code{NUM_MODES_FOR_MODE_SWITCHING[@var{entity}] - 1} the lowest. The value of the macro should be an integer designating a mode for @var{entity}. For any fixed @var{entity}, @code{mode_priority} (@var{entity}, @var{n}) shall be a bijection in 0 @dots{} @code{num_modes_for_mode_switching[@var{entity}] - 1}.
+@end deftypefn
@node Target Attributes
@section Defining target-specific uses of @code{__attribute__}
@@ -10067,9 +10038,6 @@ Another note: according to the MIPS spec, coprocessor 1 (if present) is
the FPU@. One accesses COP1 registers through standard mips
floating-point support; they are not included in this mechanism.
-There is one macro used in defining the MIPS coprocessor interface which
-you may want to override in subtargets; it is described below.
-
@node PCH Target
@section Parameters for Precompiled Header Validity Checking
@cindex parameters, precompiled headers
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 9c030df6990..bc4ae30936a 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -1011,7 +1011,7 @@ the default value is @code{BIGGEST_ALIGNMENT}.
On systems that use ELF, the default (in @file{config/elfos.h}) is
the largest supported 32-bit ELF section alignment representable on
-a 32-bit host e.g. @samp{(((unsigned HOST_WIDEST_INT) 1 << 28) * 8)}.
+a 32-bit host e.g. @samp{(((uint64_t) 1 << 28) * 8)}.
On 32-bit ELF the largest supported section alignment in bits is
@samp{(0x80000000 * 8)}, but this is not representable on 32-bit hosts.
@end defmac
@@ -5019,8 +5019,6 @@ them: try the first ones in this list first.
@hook TARGET_SCHED_GEN_SPEC_CHECK
-@hook TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC
-
@hook TARGET_SCHED_SET_SCHED_FLAGS
@hook TARGET_SCHED_SMS_RES_MII
@@ -7383,9 +7381,9 @@ You can have multiple entities that are mode-switched, and select at run time
which entities actually need it. @code{OPTIMIZE_MODE_SWITCHING} should
return nonzero for any @var{entity} that needs mode-switching.
If you define this macro, you also have to define
-@code{NUM_MODES_FOR_MODE_SWITCHING}, @code{MODE_NEEDED},
-@code{MODE_PRIORITY_TO_MODE} and @code{EMIT_MODE_SET}.
-@code{MODE_AFTER}, @code{MODE_ENTRY}, and @code{MODE_EXIT}
+@code{NUM_MODES_FOR_MODE_SWITCHING}, @code{TARGET_MODE_NEEDED},
+@code{TARGET_MODE_PRIORITY} and @code{TARGET_MODE_EMIT}.
+@code{TARGET_MODE_AFTER}, @code{TARGET_MODE_ENTRY}, and @code{TARGET_MODE_EXIT}
are optional.
@end defmac
@@ -7402,51 +7400,17 @@ represented as numbers 0 @dots{} N @minus{} 1. N is used to specify that no mod
switch is needed / supplied.
@end defmac
-@defmac MODE_NEEDED (@var{entity}, @var{insn})
-@var{entity} is an integer specifying a mode-switched entity. If
-@code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this macro to
-return an integer value not larger than the corresponding element in
-@code{NUM_MODES_FOR_MODE_SWITCHING}, to denote the mode that @var{entity} must
-be switched into prior to the execution of @var{insn}.
-@end defmac
+@hook TARGET_MODE_EMIT
-@defmac MODE_AFTER (@var{entity}, @var{mode}, @var{insn})
-@var{entity} is an integer specifying a mode-switched entity. If
-this macro is defined, it is evaluated for every @var{insn} during
-mode switching. It determines the mode that an insn results in (if
-different from the incoming mode).
-@end defmac
+@hook TARGET_MODE_NEEDED
-@defmac MODE_ENTRY (@var{entity})
-If this macro is defined, it is evaluated for every @var{entity} that needs
-mode switching. It should evaluate to an integer, which is a mode that
-@var{entity} is assumed to be switched to at function entry. If @code{MODE_ENTRY}
-is defined then @code{MODE_EXIT} must be defined.
-@end defmac
+@hook TARGET_MODE_AFTER
-@defmac MODE_EXIT (@var{entity})
-If this macro is defined, it is evaluated for every @var{entity} that needs
-mode switching. It should evaluate to an integer, which is a mode that
-@var{entity} is assumed to be switched to at function exit. If @code{MODE_EXIT}
-is defined then @code{MODE_ENTRY} must be defined.
-@end defmac
+@hook TARGET_MODE_ENTRY
-@defmac MODE_PRIORITY_TO_MODE (@var{entity}, @var{n})
-This macro specifies the order in which modes for @var{entity} are processed.
-0 is the highest priority, @code{NUM_MODES_FOR_MODE_SWITCHING[@var{entity}] - 1} the
-lowest. The value of the macro should be an integer designating a mode
-for @var{entity}. For any fixed @var{entity}, @code{mode_priority_to_mode}
-(@var{entity}, @var{n}) shall be a bijection in 0 @dots{}
-@code{num_modes_for_mode_switching[@var{entity}] - 1}.
-@end defmac
+@hook TARGET_MODE_EXIT
-@defmac EMIT_MODE_SET (@var{entity}, @var{mode}, @var{hard_regs_live})
-Generate one or more insns to set @var{entity} to @var{mode}.
-@var{hard_reg_live} is the set of hard registers live at the point where
-the insn(s) are to be inserted.
-Sets of a lower numbered entity will be emitted before sets of a higher
-numbered entity to a mode of the same or lower priority.
-@end defmac
+@hook TARGET_MODE_PRIORITY
@node Target Attributes
@section Defining target-specific uses of @code{__attribute__}
@@ -7565,9 +7529,6 @@ Another note: according to the MIPS spec, coprocessor 1 (if present) is
the FPU@. One accesses COP1 registers through standard mips
floating-point support; they are not included in this mechanism.
-There is one macro used in defining the MIPS coprocessor interface which
-you may want to override in subtargets; it is described below.
-
@node PCH Target
@section Parameters for Precompiled Header Validity Checking
@cindex parameters, precompiled headers
diff --git a/gcc/double-int.c b/gcc/double-int.c
index 454655d9049..f6e340bebfe 100644
--- a/gcc/double-int.c
+++ b/gcc/double-int.c
@@ -588,7 +588,7 @@ div_and_round_double (unsigned code, int uns,
== (unsigned HOST_WIDE_INT) htwice)
&& (labs_den <= ltwice)))
{
- if (*hquo < 0)
+ if (quo_neg)
/* quo = quo - 1; */
add_double (*lquo, *hquo,
(HOST_WIDE_INT) -1, (HOST_WIDE_INT) -1, lquo, hquo);
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index 41808905bc1..47fd0287a67 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -356,7 +356,7 @@ need_data_align_sf_opcode (HOST_WIDE_INT off)
static inline dw_cfi_ref
new_cfi (void)
{
- dw_cfi_ref cfi = ggc_alloc_dw_cfi_node ();
+ dw_cfi_ref cfi = ggc_alloc<dw_cfi_node> ();
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0;
cfi->dw_cfi_oprnd2.dw_cfi_reg_num = 0;
@@ -369,7 +369,7 @@ new_cfi (void)
static dw_cfi_row *
new_cfi_row (void)
{
- dw_cfi_row *row = ggc_alloc_cleared_dw_cfi_row ();
+ dw_cfi_row *row = ggc_cleared_alloc<dw_cfi_row> ();
row->cfa.reg = INVALID_REGNUM;
@@ -381,7 +381,7 @@ new_cfi_row (void)
static dw_cfi_row *
copy_cfi_row (dw_cfi_row *src)
{
- dw_cfi_row *dst = ggc_alloc_dw_cfi_row ();
+ dw_cfi_row *dst = ggc_alloc<dw_cfi_row> ();
*dst = *src;
dst->reg_save = vec_safe_copy (src->reg_save);
@@ -2892,7 +2892,7 @@ create_cie_data (void)
case 0:
break;
case 1:
- cie_return_save = ggc_alloc_reg_saved_in_data ();
+ cie_return_save = ggc_alloc<reg_saved_in_data> ();
*cie_return_save = cie_trace.regs_saved_in_regs[0];
cie_trace.regs_saved_in_regs.release ();
break;
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 5874d73821b..7c930746e7b 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -992,7 +992,7 @@ dwarf2out_alloc_current_fde (void)
{
dw_fde_ref fde;
- fde = ggc_alloc_cleared_dw_fde_node ();
+ fde = ggc_cleared_alloc<dw_fde_node> ();
fde->decl = current_function_decl;
fde->funcdef_number = current_function_funcdef_no;
fde->fde_index = vec_safe_length (fde_vec);
@@ -1315,7 +1315,7 @@ static inline dw_loc_descr_ref
new_loc_descr (enum dwarf_location_atom op, unsigned HOST_WIDE_INT oprnd1,
unsigned HOST_WIDE_INT oprnd2)
{
- dw_loc_descr_ref descr = ggc_alloc_cleared_dw_loc_descr_node ();
+ dw_loc_descr_ref descr = ggc_cleared_alloc<dw_loc_descr_node> ();
descr->dw_loc_opc = op;
descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
@@ -3814,7 +3814,7 @@ add_AT_wide (dw_die_ref die, enum dwarf_attribute attr_kind,
attr.dw_attr = attr_kind;
attr.dw_attr_val.val_class = dw_val_class_wide_int;
- attr.dw_attr_val.v.val_wide = ggc_alloc_cleared_wide_int ();
+ attr.dw_attr_val.v.val_wide = ggc_cleared_alloc<wide_int> ();
*attr.dw_attr_val.v.val_wide = w;
add_dwarf_attr (die, &attr);
}
@@ -3933,7 +3933,7 @@ find_AT_string_in_table (const char *str, htab_t table)
htab_hash_string (str), INSERT);
if (*slot == NULL)
{
- node = ggc_alloc_cleared_indirect_string_node ();
+ node = ggc_cleared_alloc<indirect_string_node> ();
node->str = ggc_strdup (str);
*slot = node;
}
@@ -4264,7 +4264,7 @@ add_addr_table_entry (void *addr, enum ate_kind kind)
if (*slot == HTAB_EMPTY_ENTRY)
{
- node = ggc_alloc_cleared_addr_table_entry ();
+ node = ggc_cleared_alloc<addr_table_entry> ();
init_addr_table_entry (node, kind, addr);
*slot = node;
}
@@ -4840,7 +4840,7 @@ splice_child_die (dw_die_ref parent, dw_die_ref child)
static inline dw_die_ref
new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
{
- dw_die_ref die = ggc_alloc_cleared_die_node ();
+ dw_die_ref die = ggc_cleared_alloc<die_node> ();
die->die_tag = tag_value;
@@ -4850,7 +4850,7 @@ new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
{
limbo_die_node *limbo_node;
- limbo_node = ggc_alloc_cleared_limbo_die_node ();
+ limbo_node = ggc_cleared_alloc<limbo_die_node> ();
limbo_node->die = die;
limbo_node->created_for = t;
limbo_node->next = limbo_die_list;
@@ -5167,7 +5167,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
slot = htab_find_slot_with_hash (decl_loc_table, decl, decl_id, INSERT);
if (*slot == NULL)
{
- temp = ggc_alloc_cleared_var_loc_list ();
+ temp = ggc_cleared_alloc<var_loc_list> ();
temp->decl_id = decl_id;
*slot = temp;
}
@@ -5192,7 +5192,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
|| (NOTE_VAR_LOCATION_STATUS (temp->first->loc)
!= NOTE_VAR_LOCATION_STATUS (loc_note))))
{
- loc = ggc_alloc_cleared_var_loc_node ();
+ loc = ggc_cleared_alloc<var_loc_node> ();
temp->first->next = loc;
temp->last = loc;
loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
@@ -5282,7 +5282,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
memset (loc, '\0', sizeof (*loc));
}
else
- loc = ggc_alloc_cleared_var_loc_node ();
+ loc = ggc_cleared_alloc<var_loc_node> ();
if (bitsize == -1 || piece_loc == NULL)
loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
else
@@ -5299,7 +5299,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
}
else
{
- loc = ggc_alloc_cleared_var_loc_node ();
+ loc = ggc_cleared_alloc<var_loc_node> ();
temp->first = loc;
temp->last = loc;
loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
@@ -6955,7 +6955,7 @@ clone_die (dw_die_ref die)
dw_attr_ref a;
unsigned ix;
- clone = ggc_alloc_cleared_die_node ();
+ clone = ggc_cleared_alloc<die_node> ();
clone->die_tag = die->die_tag;
FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -7001,7 +7001,7 @@ clone_as_declaration (dw_die_ref die)
return clone;
}
- clone = ggc_alloc_cleared_die_node ();
+ clone = ggc_cleared_alloc<die_node> ();
clone->die_tag = die->die_tag;
FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -7361,7 +7361,7 @@ break_out_comdat_types (dw_die_ref die)
unit = new_die (DW_TAG_type_unit, NULL, NULL);
add_AT_unsigned (unit, DW_AT_language,
get_AT_unsigned (comp_unit_die (), DW_AT_language));
- type_node = ggc_alloc_cleared_comdat_type_node ();
+ type_node = ggc_cleared_alloc<comdat_type_node> ();
type_node->root_die = unit;
type_node->next = comdat_type_list;
comdat_type_list = type_node;
@@ -8455,7 +8455,7 @@ static inline dw_loc_list_ref
new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end,
const char *section)
{
- dw_loc_list_ref retlist = ggc_alloc_cleared_dw_loc_list_node ();
+ dw_loc_list_ref retlist = ggc_cleared_alloc<dw_loc_list_node> ();
retlist->begin = begin;
retlist->begin_entry = NULL;
@@ -12964,8 +12964,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
#endif
{
unsigned int length = GET_MODE_SIZE (mode);
- unsigned char *array
- = (unsigned char*) ggc_alloc_atomic (length);
+ unsigned char *array = ggc_vec_alloc<unsigned char> (length);
insert_float (rtl, array);
mem_loc_result->dw_loc_oprnd2.val_class = dw_val_class_vec;
@@ -12991,7 +12990,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
mem_loc_result->dw_loc_oprnd1.v.val_die_ref.external = 0;
mem_loc_result->dw_loc_oprnd2.val_class
= dw_val_class_wide_int;
- mem_loc_result->dw_loc_oprnd2.v.val_wide = ggc_alloc_cleared_wide_int ();
+ mem_loc_result->dw_loc_oprnd2.v.val_wide = ggc_cleared_alloc<wide_int> ();
*mem_loc_result->dw_loc_oprnd2.v.val_wide = std::make_pair (rtl, mode);
}
break;
@@ -13474,8 +13473,7 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
#endif
{
unsigned int length = GET_MODE_SIZE (mode);
- unsigned char *array
- = (unsigned char*) ggc_alloc_atomic (length);
+ unsigned char *array = ggc_vec_alloc<unsigned char> (length);
insert_float (rtl, array);
loc_result->dw_loc_oprnd2.val_class = dw_val_class_vec;
@@ -13495,7 +13493,7 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
loc_result = new_loc_descr (DW_OP_implicit_value,
GET_MODE_SIZE (mode), 0);
loc_result->dw_loc_oprnd2.val_class = dw_val_class_wide_int;
- loc_result->dw_loc_oprnd2.v.val_wide = ggc_alloc_cleared_wide_int ();
+ loc_result->dw_loc_oprnd2.v.val_wide = ggc_cleared_alloc<wide_int> ();
*loc_result->dw_loc_oprnd2.v.val_wide = std::make_pair (rtl, mode);
}
break;
@@ -13508,8 +13506,8 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
{
unsigned int elt_size = GET_MODE_UNIT_SIZE (GET_MODE (rtl));
unsigned int length = CONST_VECTOR_NUNITS (rtl);
- unsigned char *array = (unsigned char *)
- ggc_alloc_atomic (length * elt_size);
+ unsigned char *array
+ = ggc_vec_alloc<unsigned char> (length * elt_size);
unsigned int i;
unsigned char *p;
enum machine_mode imode = GET_MODE_INNER (mode);
@@ -14058,12 +14056,12 @@ add_loc_descr_to_each (dw_loc_list_ref list, dw_loc_descr_ref ref)
list = list->dw_loc_next;
while (list)
{
- copy = ggc_alloc_dw_loc_descr_node ();
+ copy = ggc_alloc<dw_loc_descr_node> ();
memcpy (copy, ref, sizeof (dw_loc_descr_node));
add_loc_descr (&list->expr, copy);
while (copy->dw_loc_next)
{
- dw_loc_descr_ref new_copy = ggc_alloc_dw_loc_descr_node ();
+ dw_loc_descr_ref new_copy = ggc_alloc<dw_loc_descr_node> ();
memcpy (new_copy, copy->dw_loc_next, sizeof (dw_loc_descr_node));
copy->dw_loc_next = new_copy;
copy = new_copy;
@@ -15247,7 +15245,7 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
else
{
unsigned int length = GET_MODE_SIZE (mode);
- unsigned char *array = (unsigned char *) ggc_alloc_atomic (length);
+ unsigned char *array = ggc_vec_alloc<unsigned char> (length);
insert_float (rtl, array);
add_AT_vec (die, DW_AT_const_value, length / 4, 4, array);
@@ -15260,8 +15258,8 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
enum machine_mode mode = GET_MODE (rtl);
unsigned int elt_size = GET_MODE_UNIT_SIZE (mode);
unsigned int length = CONST_VECTOR_NUNITS (rtl);
- unsigned char *array = (unsigned char *) ggc_alloc_atomic
- (length * elt_size);
+ unsigned char *array
+ = ggc_vec_alloc<unsigned char> (length * elt_size);
unsigned int i;
unsigned char *p;
enum machine_mode imode = GET_MODE_INNER (mode);
@@ -15851,7 +15849,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
{
slot = htab_find_slot_with_hash (cached_dw_loc_list_table, decl,
DECL_UID (decl), INSERT);
- cache = ggc_alloc_cleared_cached_dw_loc_list ();
+ cache = ggc_cleared_alloc<cached_dw_loc_list> ();
cache->decl_id = DECL_UID (decl);
cache->loc_list = list;
*slot = cache;
@@ -16047,8 +16045,7 @@ tree_add_const_value_attribute (dw_die_ref die, tree t)
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (init));
if (size > 0 && (int) size == size)
{
- unsigned char *array = (unsigned char *)
- ggc_alloc_cleared_atomic (size);
+ unsigned char *array = ggc_cleared_vec_alloc<unsigned char> (size);
if (native_encode_initializer (init, array, size))
{
@@ -16316,7 +16313,7 @@ comp_dir_string (void)
int wdlen;
wdlen = strlen (wd);
- wd1 = (char *) ggc_alloc_atomic (wdlen + 2);
+ wd1 = ggc_vec_alloc<char> (wdlen + 2);
strcpy (wd1, wd);
wd1 [wdlen] = DIR_SEPARATOR;
wd1 [wdlen + 1] = 0;
@@ -16811,7 +16808,7 @@ add_linkage_name (dw_die_ref die, tree decl)
{
limbo_die_node *asm_name;
- asm_name = ggc_alloc_cleared_limbo_die_node ();
+ asm_name = ggc_cleared_alloc<limbo_die_node> ();
asm_name->die = die;
asm_name->created_for = decl;
asm_name->next = deferred_asm_name;
@@ -16864,7 +16861,7 @@ dwarf2out_vms_debug_main_pointer (void)
dw_die_ref die;
/* Allocate the VMS debug main subprogram die. */
- die = ggc_alloc_cleared_die_node ();
+ die = ggc_cleared_alloc<die_node> ();
die->die_tag = DW_TAG_subprogram;
add_name_attribute (die, VMS_DEBUG_MAIN_POINTER);
ASM_GENERATE_INTERNAL_LABEL (label, PROLOGUE_END_LABEL,
@@ -17540,6 +17537,11 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die)
TREE_ASM_WRITTEN (type) = 1;
add_byte_size_attribute (type_die, type);
+ if (dwarf_version >= 3 || !dwarf_strict)
+ {
+ tree underlying = lang_hooks.types.enum_underlying_base_type (type);
+ add_type_attribute (type_die, underlying, 0, 0, context_die);
+ }
if (TYPE_STUB_DECL (type) != NULL_TREE)
{
add_src_coords_attributes (type_die, TYPE_STUB_DECL (type));
@@ -21139,7 +21141,7 @@ lookup_filename (const char *file_name)
if (*slot)
return (struct dwarf_file_data *) *slot;
- created = ggc_alloc_dwarf_file_data ();
+ created = ggc_alloc<dwarf_file_data> ();
created->filename = file_name;
created->emitted_number = 0;
*slot = created;
@@ -21449,7 +21451,7 @@ dwarf2out_var_location (rtx loc_note)
if (!var_loc_p)
{
struct call_arg_loc_node *ca_loc
- = ggc_alloc_cleared_call_arg_loc_node ();
+ = ggc_cleared_alloc<call_arg_loc_node> ();
rtx prev = prev_real_insn (loc_note), x;
ca_loc->call_arg_loc_note = loc_note;
ca_loc->next = NULL;
@@ -21524,7 +21526,7 @@ new_line_info_table (void)
{
dw_line_info_table *table;
- table = ggc_alloc_cleared_dw_line_info_table_struct ();
+ table = ggc_cleared_alloc<dw_line_info_table_struct> ();
table->file_num = 1;
table->line_num = 1;
table->is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START;
@@ -22293,7 +22295,7 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
vec_alloc (decl_scope_table, 256);
/* Allocate the initial hunk of the abbrev_die_table. */
- abbrev_die_table = ggc_alloc_cleared_vec_dw_die_ref
+ abbrev_die_table = ggc_cleared_vec_alloc<dw_die_ref>
(ABBREV_DIE_TABLE_INCREMENT);
abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
/* Zero-th entry is allocated, but unused. */
@@ -23198,7 +23200,7 @@ string_cst_pool_decl (tree t)
len = TREE_STRING_LENGTH (t);
vec_safe_push (used_rtx_array, rtl);
ref = new_die (DW_TAG_dwarf_procedure, comp_unit_die (), decl);
- array = (unsigned char *) ggc_alloc_atomic (len);
+ array = ggc_vec_alloc<unsigned char> (len);
memcpy (array, TREE_STRING_POINTER (t), len);
l = new_loc_descr (DW_OP_implicit_value, len, 0);
l->dw_loc_oprnd2.val_class = dw_val_class_vec;
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 1eacb8f6ac6..fe1da9ed8ab 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -57,6 +57,7 @@ along with GCC; see the file COPYING3. If not see
#include "df.h"
#include "params.h"
#include "target.h"
+#include "builtins.h"
struct target_rtl default_target_rtl;
#if SWITCHABLE_TARGET
@@ -145,7 +146,6 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
#define cur_debug_insn_uid (crtl->emit.x_cur_debug_insn_uid)
#define first_label_num (crtl->emit.x_first_label_num)
-static rtx change_address_1 (rtx, enum machine_mode, rtx, int);
static void set_used_decls (tree);
static void mark_label_nuses (rtx);
static hashval_t const_int_htab_hash (const void *);
@@ -320,7 +320,7 @@ set_mem_attrs (rtx mem, mem_attrs *attrs)
if (!MEM_ATTRS (mem)
|| !mem_attrs_eq_p (attrs, MEM_ATTRS (mem)))
{
- MEM_ATTRS (mem) = ggc_alloc_mem_attrs ();
+ MEM_ATTRS (mem) = ggc_alloc<mem_attrs> ();
memcpy (MEM_ATTRS (mem), attrs, sizeof (mem_attrs));
}
}
@@ -367,7 +367,7 @@ get_reg_attrs (tree decl, int offset)
slot = htab_find_slot (reg_attrs_htab, &attrs, INSERT);
if (*slot == 0)
{
- *slot = ggc_alloc_reg_attrs ();
+ *slot = ggc_alloc<reg_attrs> ();
memcpy (*slot, &attrs, sizeof (reg_attrs));
}
@@ -859,6 +859,15 @@ gen_lowpart_SUBREG (enum machine_mode mode, rtx reg)
return gen_rtx_SUBREG (mode, reg,
subreg_lowpart_offset (mode, inmode));
}
+
+rtx
+gen_rtx_VAR_LOCATION (enum machine_mode mode, tree decl, rtx loc,
+ enum var_init_status status)
+{
+ rtx x = gen_rtx_fmt_te (VAR_LOCATION, mode, decl, loc);
+ PAT_VAR_LOCATION_STATUS (x) = status;
+ return x;
+}
/* Create an rtvec and stores within it the RTXen passed in the arguments. */
@@ -2001,11 +2010,15 @@ clear_mem_size (rtx mem)
/* Return a memory reference like MEMREF, but with its mode changed to MODE
and its address changed to ADDR. (VOIDmode means don't change the mode.
NULL for ADDR means don't change the address.) VALIDATE is nonzero if the
- returned memory location is required to be valid. The memory
- attributes are not changed. */
+ returned memory location is required to be valid. INPLACE is true if any
+ changes can be made directly to MEMREF or false if MEMREF must be treated
+ as immutable.
+
+ The memory attributes are not changed. */
static rtx
-change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate)
+change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate,
+ bool inplace)
{
addr_space_t as;
rtx new_rtx;
@@ -2033,6 +2046,12 @@ change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate)
if (rtx_equal_p (addr, XEXP (memref, 0)) && mode == GET_MODE (memref))
return memref;
+ if (inplace)
+ {
+ XEXP (memref, 0) = addr;
+ return memref;
+ }
+
new_rtx = gen_rtx_MEM (mode, addr);
MEM_COPY_ATTRIBUTES (new_rtx, memref);
return new_rtx;
@@ -2044,7 +2063,7 @@ change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate)
rtx
change_address (rtx memref, enum machine_mode mode, rtx addr)
{
- rtx new_rtx = change_address_1 (memref, mode, addr, 1);
+ rtx new_rtx = change_address_1 (memref, mode, addr, 1, false);
enum machine_mode mmode = GET_MODE (new_rtx);
struct mem_attrs attrs, *defattrs;
@@ -2157,7 +2176,7 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset,
addr = plus_constant (address_mode, addr, offset);
}
- new_rtx = change_address_1 (memref, mode, addr, validate);
+ new_rtx = change_address_1 (memref, mode, addr, validate, false);
/* If the address is a REG, change_address_1 rightfully returns memref,
but this would destroy memref's MEM_ATTRS. */
@@ -2227,7 +2246,7 @@ rtx
adjust_automodify_address_1 (rtx memref, enum machine_mode mode, rtx addr,
HOST_WIDE_INT offset, int validate)
{
- memref = change_address_1 (memref, VOIDmode, addr, validate);
+ memref = change_address_1 (memref, VOIDmode, addr, validate, false);
return adjust_address_1 (memref, mode, offset, validate, 0, 0, 0);
}
@@ -2263,7 +2282,7 @@ offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2)
}
update_temp_slot_address (XEXP (memref, 0), new_rtx);
- new_rtx = change_address_1 (memref, VOIDmode, new_rtx, 1);
+ new_rtx = change_address_1 (memref, VOIDmode, new_rtx, 1, false);
/* If there are no changes, just return the original memory reference. */
if (new_rtx == memref)
@@ -2283,23 +2302,25 @@ offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2)
/* Return a memory reference like MEMREF, but with its address changed to
ADDR. The caller is asserting that the actual piece of memory pointed
to is the same, just the form of the address is being changed, such as
- by putting something into a register. */
+ by putting something into a register. INPLACE is true if any changes
+ can be made directly to MEMREF or false if MEMREF must be treated as
+ immutable. */
rtx
-replace_equiv_address (rtx memref, rtx addr)
+replace_equiv_address (rtx memref, rtx addr, bool inplace)
{
/* change_address_1 copies the memory attribute structure without change
and that's exactly what we want here. */
update_temp_slot_address (XEXP (memref, 0), addr);
- return change_address_1 (memref, VOIDmode, addr, 1);
+ return change_address_1 (memref, VOIDmode, addr, 1, inplace);
}
/* Likewise, but the reference is not required to be valid. */
rtx
-replace_equiv_address_nv (rtx memref, rtx addr)
+replace_equiv_address_nv (rtx memref, rtx addr, bool inplace)
{
- return change_address_1 (memref, VOIDmode, addr, 0);
+ return change_address_1 (memref, VOIDmode, addr, 0, inplace);
}
/* Return a memory reference like MEMREF, but with its mode widened to
@@ -2451,7 +2472,7 @@ set_mem_attrs_for_spill (rtx mem)
rtx
gen_label_rtx (void)
{
- return gen_rtx_CODE_LABEL (VOIDmode, 0, NULL_RTX, NULL_RTX,
+ return gen_rtx_CODE_LABEL (VOIDmode, NULL_RTX, NULL_RTX,
NULL, label_num++, NULL);
}
@@ -3570,11 +3591,13 @@ try_split (rtx pat, rtx trial, int last)
may have introduced invalid RTL sharing, so unshare the sequence now. */
unshare_all_rtl_in_chain (seq);
- /* Mark labels. */
+ /* Mark labels and copy flags. */
for (insn = insn_last; insn ; insn = PREV_INSN (insn))
{
if (JUMP_P (insn))
{
+ if (JUMP_P (trial))
+ CROSSING_JUMP_P (insn) = CROSSING_JUMP_P (trial);
mark_jump_label (PATTERN (insn), insn, 0);
njumps++;
if (probability != -1
@@ -3651,7 +3674,6 @@ try_split (rtx pat, rtx trial, int last)
break;
case REG_NON_LOCAL_GOTO:
- case REG_CROSSING_JUMP:
for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn))
{
if (JUMP_P (insn))
@@ -5065,6 +5087,45 @@ gen_use (rtx x)
return seq;
}
+/* Notes like REG_EQUAL and REG_EQUIV refer to a set in an instruction.
+ Return the set in INSN that such notes describe, or NULL if the notes
+ have no meaning for INSN. */
+
+rtx
+set_for_reg_notes (rtx insn)
+{
+ rtx pat, reg;
+
+ if (!INSN_P (insn))
+ return NULL_RTX;
+
+ pat = PATTERN (insn);
+ if (GET_CODE (pat) == PARALLEL)
+ {
+ /* We do not use single_set because that ignores SETs of unused
+ registers. REG_EQUAL and REG_EQUIV notes really do require the
+ PARALLEL to have a single SET. */
+ if (multiple_sets (insn))
+ return NULL_RTX;
+ pat = XVECEXP (pat, 0, 0);
+ }
+
+ if (GET_CODE (pat) != SET)
+ return NULL_RTX;
+
+ reg = SET_DEST (pat);
+
+ /* Notes apply to the contents of a STRICT_LOW_PART. */
+ if (GET_CODE (reg) == STRICT_LOW_PART)
+ reg = XEXP (reg, 0);
+
+ /* Check that we have a register. */
+ if (!(REG_P (reg) || GET_CODE (reg) == SUBREG))
+ return NULL_RTX;
+
+ return pat;
+}
+
/* Place a note of KIND on insn INSN with DATUM as the datum. If a
note of this type already exists, remove it first. */
@@ -5077,39 +5138,26 @@ set_unique_reg_note (rtx insn, enum reg_note kind, rtx datum)
{
case REG_EQUAL:
case REG_EQUIV:
- /* Don't add REG_EQUAL/REG_EQUIV notes if the insn
- has multiple sets (some callers assume single_set
- means the insn only has one set, when in fact it
- means the insn only has one * useful * set). */
- if (GET_CODE (PATTERN (insn)) == PARALLEL && multiple_sets (insn))
- {
- gcc_assert (!note);
- return NULL_RTX;
- }
+ if (!set_for_reg_notes (insn))
+ return NULL_RTX;
/* Don't add ASM_OPERAND REG_EQUAL/REG_EQUIV notes.
It serves no useful purpose and breaks eliminate_regs. */
if (GET_CODE (datum) == ASM_OPERANDS)
return NULL_RTX;
-
- if (note)
- {
- XEXP (note, 0) = datum;
- df_notes_rescan (insn);
- return note;
- }
break;
default:
- if (note)
- {
- XEXP (note, 0) = datum;
- return note;
- }
break;
}
- add_reg_note (insn, kind, datum);
+ if (note)
+ XEXP (note, 0) = datum;
+ else
+ {
+ add_reg_note (insn, kind, datum);
+ note = REG_NOTES (insn);
+ }
switch (kind)
{
@@ -5121,14 +5169,14 @@ set_unique_reg_note (rtx insn, enum reg_note kind, rtx datum)
break;
}
- return REG_NOTES (insn);
+ return note;
}
/* Like set_unique_reg_note, but don't do anything unless INSN sets DST. */
rtx
set_dst_reg_note (rtx insn, enum reg_note kind, rtx datum, rtx dst)
{
- rtx set = single_set (insn);
+ rtx set = set_for_reg_notes (insn);
if (set && SET_DEST (set) == dst)
return set_unique_reg_note (insn, kind, datum);
@@ -5223,7 +5271,7 @@ start_sequence (void)
free_sequence_stack = tem->next;
}
else
- tem = ggc_alloc_sequence_stack ();
+ tem = ggc_alloc<sequence_stack> ();
tem->next = seq_stack;
tem->first = get_insns ();
@@ -5556,7 +5604,7 @@ init_emit (void)
crtl->emit.regno_pointer_align
= XCNEWVEC (unsigned char, crtl->emit.regno_pointer_align_length);
- regno_reg_rtx = ggc_alloc_vec_rtx (crtl->emit.regno_pointer_align_length);
+ regno_reg_rtx = ggc_vec_alloc<rtx> (crtl->emit.regno_pointer_align_length);
/* Put copies of all the hard registers into regno_reg_rtx. */
memcpy (regno_reg_rtx,
@@ -5706,7 +5754,7 @@ init_emit_regs (void)
for (i = 0; i < (int) MAX_MACHINE_MODE; i++)
{
mode = (enum machine_mode) i;
- attrs = ggc_alloc_cleared_mem_attrs ();
+ attrs = ggc_cleared_alloc<mem_attrs> ();
attrs->align = BITS_PER_UNIT;
attrs->addrspace = ADDR_SPACE_GENERIC;
if (mode != BLKmode)
@@ -6006,6 +6054,7 @@ emit_copy_of_insn_after (rtx insn, rtx after)
case JUMP_INSN:
new_rtx = emit_jump_insn_after (copy_insn (PATTERN (insn)), after);
+ CROSSING_JUMP_P (new_rtx) = CROSSING_JUMP_P (insn);
break;
case DEBUG_INSN:
diff --git a/gcc/emit-rtl.h b/gcc/emit-rtl.h
index fe68de94756..c72c24f4d88 100644
--- a/gcc/emit-rtl.h
+++ b/gcc/emit-rtl.h
@@ -52,10 +52,10 @@ extern tree get_spill_slot_decl (bool);
ADDR. The caller is asserting that the actual piece of memory pointed
to is the same, just the form of the address is being changed, such as
by putting something into a register. */
-extern rtx replace_equiv_address (rtx, rtx);
+extern rtx replace_equiv_address (rtx, rtx, bool = false);
/* Likewise, but the reference is not required to be valid. */
-extern rtx replace_equiv_address_nv (rtx, rtx);
+extern rtx replace_equiv_address_nv (rtx, rtx, bool = false);
extern rtx gen_blockage (void);
extern rtvec gen_rtvec (int, ...);
diff --git a/gcc/except.c b/gcc/except.c
index 5b33c9cc301..018439e9e10 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -141,6 +141,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "pointer-set.h"
#include "cfgloop.h"
+#include "builtins.h"
/* Provide defaults for stuff that may not be defined when using
sjlj exceptions. */
@@ -286,9 +287,22 @@ init_eh (void)
tmp = size_int (FIRST_PSEUDO_REGISTER + 2 - 1);
#endif
#else
- /* builtin_setjmp takes a pointer to 5 words. */
- tmp = size_int (5 * BITS_PER_WORD / POINTER_SIZE - 1);
+ /* Compute a minimally sized jump buffer. We need room to store at
+ least 3 pointers - stack pointer, frame pointer and return address.
+ Plus for some targets we need room for an extra pointer - in the
+ case of MIPS this is the global pointer. This makes a total of four
+ pointers, but to be safe we actually allocate room for 5.
+
+ If pointers are smaller than words then we allocate enough room for
+ 5 words, just in case the backend needs this much room. For more
+ discussion on this issue see:
+ http://gcc.gnu.org/ml/gcc-patches/2014-05/msg00313.html. */
+ if (POINTER_SIZE > BITS_PER_WORD)
+ tmp = size_int (5 - 1);
+ else
+ tmp = size_int ((5 * BITS_PER_WORD / POINTER_SIZE) - 1);
#endif
+
tmp = build_index_type (tmp);
tmp = build_array_type (ptr_type_node, tmp);
f_jbuf = build_decl (BUILTINS_LOCATION,
@@ -333,7 +347,7 @@ init_eh (void)
void
init_eh_for_function (void)
{
- cfun->eh = ggc_alloc_cleared_eh_status ();
+ cfun->eh = ggc_cleared_alloc<eh_status> ();
/* Make sure zero'th entries are used. */
vec_safe_push (cfun->eh->region_array, (eh_region)0);
@@ -350,7 +364,7 @@ gen_eh_region (enum eh_region_type type, eh_region outer)
eh_region new_eh;
/* Insert a new blank region as a leaf in the tree. */
- new_eh = ggc_alloc_cleared_eh_region_d ();
+ new_eh = ggc_cleared_alloc<eh_region_d> ();
new_eh->type = type;
new_eh->outer = outer;
if (outer)
@@ -407,7 +421,7 @@ gen_eh_region_catch (eh_region t, tree type_or_list)
add_type_for_runtime (TREE_VALUE (type_node));
}
- c = ggc_alloc_cleared_eh_catch_d ();
+ c = ggc_cleared_alloc<eh_catch_d> ();
c->type_list = type_list;
l = t->u.eh_try.last_catch;
c->prev_catch = l;
@@ -441,7 +455,7 @@ gen_eh_region_must_not_throw (eh_region outer)
eh_landing_pad
gen_eh_landing_pad (eh_region region)
{
- eh_landing_pad lp = ggc_alloc_cleared_eh_landing_pad_d ();
+ eh_landing_pad lp = ggc_cleared_alloc<eh_landing_pad_d> ();
lp->next_lp = region->landing_pads;
lp->region = region;
@@ -949,7 +963,7 @@ static basic_block
emit_to_new_bb_before (rtx seq, rtx insn)
{
rtx last;
- basic_block bb, prev_bb;
+ basic_block bb;
edge e;
edge_iterator ei;
@@ -964,8 +978,7 @@ emit_to_new_bb_before (rtx seq, rtx insn)
last = emit_insn_before (seq, insn);
if (BARRIER_P (last))
last = PREV_INSN (last);
- prev_bb = BLOCK_FOR_INSN (insn)->prev_bb;
- bb = create_basic_block (seq, last, prev_bb);
+ bb = create_basic_block (seq, last, BLOCK_FOR_INSN (insn)->prev_bb);
update_bb_for_insn (bb);
bb->flags |= BB_SUPERBLOCK;
return bb;
@@ -2451,7 +2464,7 @@ add_call_site (rtx landing_pad, int action, int section)
{
call_site_record record;
- record = ggc_alloc_call_site_record_d ();
+ record = ggc_alloc<call_site_record_d> ();
record->landing_pad = landing_pad;
record->action = action;
@@ -2855,12 +2868,12 @@ switch_to_exception_section (const char * ARG_UNUSED (fnname))
#ifdef HAVE_LD_EH_GC_SECTIONS
if (flag_function_sections
- || (DECL_ONE_ONLY (current_function_decl) && HAVE_COMDAT_GROUP))
+ || (DECL_COMDAT_GROUP (current_function_decl) && HAVE_COMDAT_GROUP))
{
char *section_name = XNEWVEC (char, strlen (fnname) + 32);
/* The EH table must match the code section, so only mark
it linkonce if we have COMDAT groups to tie them together. */
- if (DECL_ONE_ONLY (current_function_decl) && HAVE_COMDAT_GROUP)
+ if (DECL_COMDAT_GROUP (current_function_decl) && HAVE_COMDAT_GROUP)
flags |= SECTION_LINKONCE;
sprintf (section_name, ".gcc_except_table.%s", fnname);
s = get_section (section_name, flags, current_function_decl);
diff --git a/gcc/explow.c b/gcc/explow.c
index bc97c964e61..e39db0507db 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -74,10 +74,12 @@ trunc_int_for_mode (HOST_WIDE_INT c, enum machine_mode mode)
}
/* Return an rtx for the sum of X and the integer C, given that X has
- mode MODE. */
+ mode MODE. INPLACE is true if X can be modified inplace or false
+ if it must be treated as immutable. */
rtx
-plus_constant (enum machine_mode mode, rtx x, HOST_WIDE_INT c)
+plus_constant (enum machine_mode mode, rtx x, HOST_WIDE_INT c,
+ bool inplace)
{
RTX_CODE code;
rtx y;
@@ -116,6 +118,8 @@ plus_constant (enum machine_mode mode, rtx x, HOST_WIDE_INT c)
case CONST:
/* If adding to something entirely constant, set a flag
so that we can add a CONST around the result. */
+ if (inplace && shared_const_p (x))
+ inplace = false;
x = XEXP (x, 0);
all_constant = 1;
goto restart;
@@ -136,19 +140,25 @@ plus_constant (enum machine_mode mode, rtx x, HOST_WIDE_INT c)
if (CONSTANT_P (XEXP (x, 1)))
{
- x = gen_rtx_PLUS (mode, XEXP (x, 0),
- plus_constant (mode, XEXP (x, 1), c));
+ rtx term = plus_constant (mode, XEXP (x, 1), c, inplace);
+ if (term == const0_rtx)
+ x = XEXP (x, 0);
+ else if (inplace)
+ XEXP (x, 1) = term;
+ else
+ x = gen_rtx_PLUS (mode, XEXP (x, 0), term);
c = 0;
}
- else if (find_constant_term_loc (&y))
+ else if (rtx *const_loc = find_constant_term_loc (&y))
{
- /* We need to be careful since X may be shared and we can't
- modify it in place. */
- rtx copy = copy_rtx (x);
- rtx *const_loc = find_constant_term_loc (&copy);
-
- *const_loc = plus_constant (mode, *const_loc, c);
- x = copy;
+ if (!inplace)
+ {
+ /* We need to be careful since X may be shared and we can't
+ modify it in place. */
+ x = copy_rtx (x);
+ const_loc = find_constant_term_loc (&x);
+ }
+ *const_loc = plus_constant (mode, *const_loc, c, true);
c = 0;
}
break;
diff --git a/gcc/expr.c b/gcc/expr.c
index 2868d9d3443..512c024e698 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -67,6 +67,7 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "tree-ssa-address.h"
#include "cfgexpand.h"
+#include "builtins.h"
#ifndef STACK_PUSH_CODE
#ifdef STACK_GROWS_DOWNWARD
@@ -4838,15 +4839,29 @@ expand_assignment (tree to, tree from, bool nontemporal)
if (GET_MODE (offset_rtx) != address_mode)
offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
- /* The check for a constant address in TO_RTX not having VOIDmode
- is probably no longer necessary. */
- if (MEM_P (to_rtx)
- && GET_MODE (to_rtx) == BLKmode
- && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
+ /* If we have an expression in OFFSET_RTX and a non-zero
+ byte offset in BITPOS, adding the byte offset before the
+ OFFSET_RTX results in better intermediate code, which makes
+ later rtl optimization passes perform better.
+
+ We prefer intermediate code like this:
+
+ r124:DI=r123:DI+0x18
+ [r124:DI]=r121:DI
+
+ ... instead of ...
+
+ r124:DI=r123:DI+0x10
+ [r124:DI+0x8]=r121:DI
+
+ This is only done for aligned data values, as these can
+ be expected to result in single move instructions. */
+ if (mode1 != VOIDmode
+ && bitpos != 0
&& bitsize > 0
&& (bitpos % bitsize) == 0
&& (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
- && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
+ && MEM_ALIGN (to_rtx) >= GET_MODE_ALIGNMENT (mode1))
{
to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
bitregion_start = 0;
@@ -10090,14 +10105,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
if (GET_MODE (offset_rtx) != address_mode)
offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
- if (GET_MODE (op0) == BLKmode
- /* The check for a constant address in OP0 not having VOIDmode
- is probably no longer necessary. */
- && GET_MODE (XEXP (op0, 0)) != VOIDmode
- && bitsize != 0
+ /* See the comment in expand_assignment for the rationale. */
+ if (mode1 != VOIDmode
+ && bitpos != 0
+ && bitsize > 0
&& (bitpos % bitsize) == 0
&& (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
- && MEM_ALIGN (op0) == GET_MODE_ALIGNMENT (mode1))
+ && MEM_ALIGN (op0) >= GET_MODE_ALIGNMENT (mode1))
{
op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
bitpos = 0;
diff --git a/gcc/expr.h b/gcc/expr.h
index 1823febac26..6a1d3ab5709 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -252,20 +252,6 @@ extern unsigned HOST_WIDE_INT choose_multiplier (unsigned HOST_WIDE_INT, int,
int, unsigned HOST_WIDE_INT *,
int *, int *);
-/* Functions from builtins.c: */
-extern rtx expand_builtin (tree, rtx, rtx, enum machine_mode, int);
-extern tree std_build_builtin_va_list (void);
-extern tree std_fn_abi_va_list (tree);
-extern tree std_canonical_va_list_type (tree);
-
-extern void std_expand_builtin_va_start (tree, rtx);
-extern rtx default_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
-extern void expand_builtin_setjmp_setup (rtx, rtx);
-extern void expand_builtin_setjmp_receiver (rtx);
-extern rtx expand_builtin_saveregs (void);
-extern void expand_builtin_trap (void);
-extern rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
-
/* Functions from expr.c: */
/* This is run during target initialization to set up which modes can be
diff --git a/gcc/final.c b/gcc/final.c
index 327143093fe..c32e177a426 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "varasm.h"
+#include "hard-reg-set.h"
#include "rtl.h"
#include "tm_p.h"
#include "regs.h"
@@ -57,7 +58,6 @@ along with GCC; see the file COPYING3. If not see
#include "recog.h"
#include "conditions.h"
#include "flags.h"
-#include "hard-reg-set.h"
#include "output.h"
#include "except.h"
#include "function.h"
@@ -224,6 +224,7 @@ static int alter_cond (rtx);
static int final_addr_vec_align (rtx);
#endif
static int align_fuzz (rtx, rtx, int, unsigned);
+static void collect_fn_hard_reg_usage (void);
/* Initialize data in final at the beginning of a compilation. */
@@ -371,7 +372,7 @@ init_insn_lengths (void)
/* Obtain the current length of an insn. If branch shortening has been done,
get its actual length. Otherwise, use FALLBACK_FN to calculate the
length. */
-static inline int
+static int
get_attr_length_1 (rtx insn, int (*fallback_fn) (rtx))
{
rtx body;
@@ -1925,7 +1926,7 @@ dump_basic_block_info (FILE *file, rtx insn, basic_block *start_to_bb,
if (bb->frequency)
fprintf (file, " freq:%d", bb->frequency);
if (bb->count)
- fprintf (file, " count:" HOST_WIDEST_INT_PRINT_DEC,
+ fprintf (file, " count:%"PRId64,
bb->count);
fprintf (file, " seq:%d", (*bb_seqn)++);
fprintf (file, "\n%s PRED:", ASM_COMMENT_START);
@@ -4442,6 +4443,8 @@ rest_of_handle_final (void)
assemble_start_function (current_function_decl, fnname);
final_start_function (get_insns (), asm_out_file, optimize);
final (get_insns (), asm_out_file, optimize);
+ if (flag_use_caller_save)
+ collect_fn_hard_reg_usage ();
final_end_function ();
/* The IA-64 ".handlerdata" directive must be issued before the ".endp"
@@ -4740,3 +4743,114 @@ make_pass_clean_state (gcc::context *ctxt)
{
return new pass_clean_state (ctxt);
}
+
+/* Collect hard register usage for the current function. */
+
+static void
+collect_fn_hard_reg_usage (void)
+{
+ rtx insn;
+#ifdef STACK_REGS
+ int i;
+#endif
+ struct cgraph_rtl_info *node;
+
+ /* ??? To be removed when all the ports have been fixed. */
+ if (!targetm.call_fusage_contains_non_callee_clobbers)
+ return;
+
+ node = cgraph_rtl_info (current_function_decl);
+ gcc_assert (node != NULL);
+
+ for (insn = get_insns (); insn != NULL_RTX; insn = next_insn (insn))
+ {
+ HARD_REG_SET insn_used_regs;
+
+ if (!NONDEBUG_INSN_P (insn))
+ continue;
+
+ find_all_hard_reg_sets (insn, &insn_used_regs, false);
+
+ if (CALL_P (insn)
+ && !get_call_reg_set_usage (insn, &insn_used_regs, call_used_reg_set))
+ {
+ CLEAR_HARD_REG_SET (node->function_used_regs);
+ return;
+ }
+
+ IOR_HARD_REG_SET (node->function_used_regs, insn_used_regs);
+ }
+
+ /* Be conservative - mark fixed and global registers as used. */
+ IOR_HARD_REG_SET (node->function_used_regs, fixed_reg_set);
+
+#ifdef STACK_REGS
+ /* Handle STACK_REGS conservatively, since the df-framework does not
+ provide accurate information for them. */
+
+ for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
+ SET_HARD_REG_BIT (node->function_used_regs, i);
+#endif
+
+ node->function_used_regs_valid = 1;
+}
+
+/* Get the declaration of the function called by INSN. */
+
+static tree
+get_call_fndecl (rtx insn)
+{
+ rtx note, datum;
+
+ note = find_reg_note (insn, REG_CALL_DECL, NULL_RTX);
+ if (note == NULL_RTX)
+ return NULL_TREE;
+
+ datum = XEXP (note, 0);
+ if (datum != NULL_RTX)
+ return SYMBOL_REF_DECL (datum);
+
+ return NULL_TREE;
+}
+
+/* Return the cgraph_rtl_info of the function called by INSN. Returns NULL for
+ call targets that can be overwritten. */
+
+static struct cgraph_rtl_info *
+get_call_cgraph_rtl_info (rtx insn)
+{
+ tree fndecl;
+
+ if (insn == NULL_RTX)
+ return NULL;
+
+ fndecl = get_call_fndecl (insn);
+ if (fndecl == NULL_TREE
+ || !decl_binds_to_current_def_p (fndecl))
+ return NULL;
+
+ return cgraph_rtl_info (fndecl);
+}
+
+/* Find hard registers used by function call instruction INSN, and return them
+ in REG_SET. Return DEFAULT_SET in REG_SET if not found. */
+
+bool
+get_call_reg_set_usage (rtx insn, HARD_REG_SET *reg_set,
+ HARD_REG_SET default_set)
+{
+ if (flag_use_caller_save)
+ {
+ struct cgraph_rtl_info *node = get_call_cgraph_rtl_info (insn);
+ if (node != NULL
+ && node->function_used_regs_valid)
+ {
+ COPY_HARD_REG_SET (*reg_set, node->function_used_regs);
+ AND_HARD_REG_SET (*reg_set, default_set);
+ return true;
+ }
+ }
+
+ COPY_HARD_REG_SET (*reg_set, default_set);
+ return false;
+}
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index caf4039f9df..ed00046c8ee 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -229,9 +229,11 @@ enum sanitize_code {
SANITIZE_BOOL = 1 << 10,
SANITIZE_ENUM = 1 << 11,
SANITIZE_FLOAT_DIVIDE = 1 << 12,
+ SANITIZE_FLOAT_CAST = 1 << 13,
SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE
| SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN
- | SANITIZE_SI_OVERFLOW | SANITIZE_BOOL | SANITIZE_ENUM
+ | SANITIZE_SI_OVERFLOW | SANITIZE_BOOL | SANITIZE_ENUM,
+ SANITIZE_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
};
/* flag_vtable_verify initialization levels. */
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 831aaba683c..24daaa32ce3 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -68,6 +68,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify.h"
#include "tree-dfa.h"
#include "hash-table.h" /* Required for ENABLE_FOLD_CHECKING. */
+#include "builtins.h"
/* Nonzero if we are folding constants inside an initializer; zero
otherwise. */
@@ -3444,7 +3445,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
{
HOST_WIDE_INT lbitpos, lbitsize, rbitpos, rbitsize, nbitpos, nbitsize;
tree type = TREE_TYPE (lhs);
- tree signed_type, unsigned_type;
+ tree unsigned_type;
int const_p = TREE_CODE (rhs) == INTEGER_CST;
enum machine_mode lmode, rmode, nmode;
int lunsignedp, runsignedp;
@@ -3489,7 +3490,6 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
/* Set signed and unsigned types of the precision of this mode for the
shifts below. */
- signed_type = lang_hooks.types.type_for_mode (nmode, 0);
unsigned_type = lang_hooks.types.type_for_mode (nmode, 1);
/* Compute the bit position and size for the new reference and our offset
@@ -3538,10 +3538,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
if (lunsignedp)
{
- if (! integer_zerop (const_binop (RSHIFT_EXPR,
- fold_convert_loc (loc,
- unsigned_type, rhs),
- size_int (lbitsize))))
+ if (wi::lrshift (rhs, lbitsize) != 0)
{
warning (0, "comparison is always %d due to width of bit-field",
code == NE_EXPR);
@@ -3550,10 +3547,8 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
}
else
{
- tree tem = const_binop (RSHIFT_EXPR,
- fold_convert_loc (loc, signed_type, rhs),
- size_int (lbitsize - 1));
- if (! integer_zerop (tem) && ! integer_all_onesp (tem))
+ wide_int tem = wi::arshift (rhs, lbitsize - 1);
+ if (tem != 0 && tem != -1)
{
warning (0, "comparison is always %d due to width of bit-field",
code == NE_EXPR);
@@ -5708,7 +5703,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
/* For a constant, we can always simplify if we are a multiply
or (for divide and modulus) if it is a multiple of our constant. */
if (code == MULT_EXPR
- || integer_zerop (const_binop (TRUNC_MOD_EXPR, t, c)))
+ || wi::multiple_of_p (t, c, TYPE_SIGN (type)))
return const_binop (code, fold_convert (ctype, t),
fold_convert (ctype, c));
break;
@@ -5888,7 +5883,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
/* If it's a multiply or a division/modulus operation of a multiple
of our constant, do the operation and verify it doesn't overflow. */
if (code == MULT_EXPR
- || integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
+ || wi::multiple_of_p (op1, c, TYPE_SIGN (type)))
{
op1 = const_binop (code, fold_convert (ctype, op1),
fold_convert (ctype, c));
@@ -5932,7 +5927,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
/* If the multiplication can overflow we cannot optimize this. */
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (t))
&& TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST
- && integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
+ && wi::multiple_of_p (op1, c, TYPE_SIGN (type)))
{
*strict_overflow_p = true;
return omit_one_operand (type, integer_zero_node, op0);
@@ -5989,7 +5984,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
&& code != FLOOR_MOD_EXPR && code != ROUND_MOD_EXPR
&& code != MULT_EXPR)))
{
- if (integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
+ if (wi::multiple_of_p (op1, c, TYPE_SIGN (type)))
{
if (TYPE_OVERFLOW_UNDEFINED (ctype))
*strict_overflow_p = true;
@@ -5998,7 +5993,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
const_binop (TRUNC_DIV_EXPR,
op1, c)));
}
- else if (integer_zerop (const_binop (TRUNC_MOD_EXPR, c, op1)))
+ else if (wi::multiple_of_p (c, op1, TYPE_SIGN (type)))
{
if (TYPE_OVERFLOW_UNDEFINED (ctype))
*strict_overflow_p = true;
@@ -7856,6 +7851,11 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
return fold_convert_loc (loc, type, op0);
return NULL_TREE;
+ case NON_LVALUE_EXPR:
+ if (!maybe_lvalue_p (op0))
+ return fold_convert_loc (loc, type, op0);
+ return NULL_TREE;
+
CASE_CONVERT:
case FLOAT_EXPR:
case FIX_TRUNC_EXPR:
@@ -8119,7 +8119,7 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
}
}
- tem = fold_convert_const (code, type, op0);
+ tem = fold_convert_const (code, type, arg0);
return tem ? tem : NULL_TREE;
case ADDR_SPACE_CONVERT_EXPR:
@@ -8905,6 +8905,7 @@ static tree
fold_comparison (location_t loc, enum tree_code code, tree type,
tree op0, tree op1)
{
+ const bool equality_code = (code == EQ_EXPR || code == NE_EXPR);
tree arg0, arg1, tem;
arg0 = op0;
@@ -8921,28 +8922,24 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
if (tree_swap_operands_p (arg0, arg1, true))
return fold_build2_loc (loc, swap_tree_comparison (code), type, op1, op0);
- /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 +- C1. */
+ /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1. */
if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
- && (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
- && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))
- && (TREE_CODE (arg1) == INTEGER_CST
- && !TREE_OVERFLOW (arg1)))
+ && (equality_code || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)))
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
+ && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
+ && TREE_CODE (arg1) == INTEGER_CST
+ && !TREE_OVERFLOW (arg1))
{
+ const enum tree_code
+ reverse_op = TREE_CODE (arg0) == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR;
tree const1 = TREE_OPERAND (arg0, 1);
- tree const2 = arg1;
+ tree const2 = fold_convert_loc (loc, TREE_TYPE (const1), arg1);
tree variable = TREE_OPERAND (arg0, 0);
- tree lhs;
- int lhs_add;
- lhs_add = TREE_CODE (arg0) != PLUS_EXPR;
-
- lhs = fold_build2_loc (loc, lhs_add ? PLUS_EXPR : MINUS_EXPR,
- TREE_TYPE (arg1), const2, const1);
+ tree new_const = int_const_binop (reverse_op, const2, const1);
/* If the constant operation overflowed this can be
simplified as a comparison against INT_MAX/INT_MIN. */
- if (TREE_CODE (lhs) == INTEGER_CST
- && TREE_OVERFLOW (lhs))
+ if (TREE_OVERFLOW (new_const))
{
int const1_sgn = tree_int_cst_sgn (const1);
enum tree_code code2 = code;
@@ -8962,29 +8959,48 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
/* We now can look at the canonicalized case
VARIABLE + 1 CODE2 INT_MIN
and decide on the result. */
- if (code2 == LT_EXPR
- || code2 == LE_EXPR
- || code2 == EQ_EXPR)
- return omit_one_operand_loc (loc, type, boolean_false_node, variable);
- else if (code2 == NE_EXPR
- || code2 == GE_EXPR
- || code2 == GT_EXPR)
- return omit_one_operand_loc (loc, type, boolean_true_node, variable);
- }
+ switch (code2)
+ {
+ case EQ_EXPR:
+ case LT_EXPR:
+ case LE_EXPR:
+ return
+ omit_one_operand_loc (loc, type, boolean_false_node, variable);
+
+ case NE_EXPR:
+ case GE_EXPR:
+ case GT_EXPR:
+ return
+ omit_one_operand_loc (loc, type, boolean_true_node, variable);
- if (TREE_CODE (lhs) == TREE_CODE (arg1)
- && (TREE_CODE (lhs) != INTEGER_CST
- || !TREE_OVERFLOW (lhs)))
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else
{
- if (code != EQ_EXPR && code != NE_EXPR)
+ if (!equality_code)
fold_overflow_warning ("assuming signed overflow does not occur "
"when changing X +- C1 cmp C2 to "
- "X cmp C1 +- C2",
+ "X cmp C2 -+ C1",
WARN_STRICT_OVERFLOW_COMPARISON);
- return fold_build2_loc (loc, code, type, variable, lhs);
+ return fold_build2_loc (loc, code, type, variable, new_const);
}
}
+ /* Transform comparisons of the form X - Y CMP 0 to X CMP Y. */
+ if (TREE_CODE (arg0) == MINUS_EXPR
+ && (equality_code || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)))
+ && integer_zerop (arg1))
+ {
+ if (!equality_code)
+ fold_overflow_warning ("assuming signed overflow does not occur "
+ "when changing X - Y cmp 0 to X cmp Y",
+ WARN_STRICT_OVERFLOW_COMPARISON);
+ return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg0, 1));
+ }
+
/* For comparisons of pointers we can decompose it to a compile time
comparison of the base objects and the offsets into the object.
This requires at least one operand being an ADDR_EXPR or a
@@ -9112,8 +9128,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
|| POINTER_TYPE_OVERFLOW_UNDEFINED))
{
- if (code != EQ_EXPR
- && code != NE_EXPR
+ if (!equality_code
&& bitpos0 != bitpos1
&& (pointer_may_wrap_p (base0, offset0, bitpos0)
|| pointer_may_wrap_p (base1, offset1, bitpos1)))
@@ -9147,7 +9162,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
object and overflow on pointer differences is undefined as of
6.5.6/8 and /9 with respect to the signed ptrdiff_t. */
else if (bitpos0 == bitpos1
- && ((code == EQ_EXPR || code == NE_EXPR)
+ && (equality_code
|| (indirect_base0 && DECL_P (base0))
|| POINTER_TYPE_OVERFLOW_UNDEFINED))
{
@@ -9165,8 +9180,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
else
offset1 = fold_convert_loc (loc, ssizetype, offset1);
- if (code != EQ_EXPR
- && code != NE_EXPR
+ if (!equality_code
&& (pointer_may_wrap_p (base0, offset0, bitpos0)
|| pointer_may_wrap_p (base1, offset1, bitpos1)))
fold_overflow_warning (("assuming pointer wraparound does not "
@@ -9226,7 +9240,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
/* Transform comparisons of the form X +- C1 CMP Y +- C2 to
X CMP Y +- C2 +- C1 for signed X, Y. This is valid if
the resulting offset is smaller in absolute value than the
- original one. */
+ original one and has the same sign. */
if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
&& (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
&& (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
@@ -9245,32 +9259,35 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
"a comparison");
/* Put the constant on the side where it doesn't overflow and is
- of lower absolute value than before. */
+ of lower absolute value and of same sign than before. */
cst = int_const_binop (TREE_CODE (arg0) == TREE_CODE (arg1)
? MINUS_EXPR : PLUS_EXPR,
const2, const1);
if (!TREE_OVERFLOW (cst)
- && tree_int_cst_compare (const2, cst) == tree_int_cst_sgn (const2))
+ && tree_int_cst_compare (const2, cst) == tree_int_cst_sgn (const2)
+ && tree_int_cst_sgn (cst) == tree_int_cst_sgn (const2))
{
fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_COMPARISON);
return fold_build2_loc (loc, code, type,
- variable1,
- fold_build2_loc (loc,
- TREE_CODE (arg1), TREE_TYPE (arg1),
- variable2, cst));
+ variable1,
+ fold_build2_loc (loc, TREE_CODE (arg1),
+ TREE_TYPE (arg1),
+ variable2, cst));
}
cst = int_const_binop (TREE_CODE (arg0) == TREE_CODE (arg1)
? MINUS_EXPR : PLUS_EXPR,
const1, const2);
if (!TREE_OVERFLOW (cst)
- && tree_int_cst_compare (const1, cst) == tree_int_cst_sgn (const1))
+ && tree_int_cst_compare (const1, cst) == tree_int_cst_sgn (const1)
+ && tree_int_cst_sgn (cst) == tree_int_cst_sgn (const1))
{
fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_COMPARISON);
return fold_build2_loc (loc, code, type,
- fold_build2_loc (loc, TREE_CODE (arg0), TREE_TYPE (arg0),
- variable1, cst),
- variable2);
+ fold_build2_loc (loc, TREE_CODE (arg0),
+ TREE_TYPE (arg0),
+ variable1, cst),
+ variable2);
}
}
@@ -10356,9 +10373,8 @@ fold_binary_loc (location_t loc,
&& TREE_CODE (arg1) == BIT_AND_EXPR
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
- && integer_zerop (const_binop (BIT_AND_EXPR,
- TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1))))
+ && wi::bit_and (TREE_OPERAND (arg0, 1),
+ TREE_OPERAND (arg1, 1)) == 0)
{
code = BIT_IOR_EXPR;
goto bit_ior;
@@ -11358,7 +11374,7 @@ fold_binary_loc (location_t loc,
wide_int c3 = c1.and_not (c2);
for (w = BITS_PER_UNIT; w <= width; w <<= 1)
{
- wide_int mask = wi::mask (width - w, false,
+ wide_int mask = wi::mask (w, false,
TYPE_PRECISION (type));
if (((c1 | c2) & mask) == mask && c1.and_not (mask) == 0)
{
@@ -11478,9 +11494,8 @@ fold_binary_loc (location_t loc,
&& TREE_CODE (arg1) == BIT_AND_EXPR
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
- && integer_zerop (const_binop (BIT_AND_EXPR,
- TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1))))
+ && wi::bit_and (TREE_OPERAND (arg0, 1),
+ TREE_OPERAND (arg1, 1)) == 0)
{
code = BIT_IOR_EXPR;
goto bit_ior;
@@ -11980,11 +11995,17 @@ fold_binary_loc (location_t loc,
/* See if we can shorten the right shift. */
if (shiftc < prec)
shift_type = inner_type;
+ /* Otherwise X >> C1 is all zeros, so we'll optimize
+ it into (X, 0) later on by making sure zerobits
+ is all ones. */
}
}
zerobits = ~(unsigned HOST_WIDE_INT) 0;
- zerobits >>= HOST_BITS_PER_WIDE_INT - shiftc;
- zerobits <<= prec - shiftc;
+ if (shiftc < prec)
+ {
+ zerobits >>= HOST_BITS_PER_WIDE_INT - shiftc;
+ zerobits <<= prec - shiftc;
+ }
/* For arithmetic shift if sign bit could be set, zerobits
can contain actually sign bits, so no transformation is
possible, unless MASK masks them all away. In that
@@ -12002,7 +12023,7 @@ fold_binary_loc (location_t loc,
/* ((X << 16) & 0xff00) is (X, 0). */
if ((mask & zerobits) == mask)
return omit_one_operand_loc (loc, type,
- build_int_cst (type, 0), arg0);
+ build_int_cst (type, 0), arg0);
newmask = mask | zerobits;
if (newmask != mask && (newmask & (newmask + 1)) == 0)
@@ -12885,21 +12906,6 @@ fold_binary_loc (location_t loc,
type);
}
- /* If this is an EQ or NE comparison of a constant with a PLUS_EXPR or
- a MINUS_EXPR of a constant, we can convert it into a comparison with
- a revised constant as long as no overflow occurs. */
- if (TREE_CODE (arg1) == INTEGER_CST
- && (TREE_CODE (arg0) == PLUS_EXPR
- || TREE_CODE (arg0) == MINUS_EXPR)
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
- ? MINUS_EXPR : PLUS_EXPR,
- fold_convert_loc (loc, TREE_TYPE (arg0),
- arg1),
- TREE_OPERAND (arg0, 1)))
- && !TREE_OVERFLOW (tem))
- return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
-
/* Similarly for a NEGATE_EXPR. */
if (TREE_CODE (arg0) == NEGATE_EXPR
&& TREE_CODE (arg1) == INTEGER_CST
@@ -12953,13 +12959,6 @@ fold_binary_loc (location_t loc,
TREE_OPERAND (arg0, 1), arg1);
}
- /* If we have X - Y == 0, we can convert that to X == Y and similarly
- for !=. Don't do this for ordered comparisons due to overflow. */
- if (TREE_CODE (arg0) == MINUS_EXPR
- && integer_zerop (arg1))
- return fold_build2_loc (loc, code, type,
- TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
-
/* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0. */
if (TREE_CODE (arg0) == ABS_EXPR
&& (integer_zerop (arg1) || real_zerop (arg1)))
@@ -15314,8 +15313,8 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
&& (tree_int_cst_sgn (top) < 0
|| tree_int_cst_sgn (bottom) < 0)))
return 0;
- return integer_zerop (int_const_binop (TRUNC_MOD_EXPR,
- top, bottom));
+ return wi::multiple_of_p (wi::to_widest (top), wi::to_widest (bottom),
+ SIGNED);
default:
return 0;
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 023f043853e..dcb97a17a31 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -85,7 +85,6 @@ extern void fold_defer_overflow_warnings (void);
extern void fold_undefer_overflow_warnings (bool, const_gimple, int);
extern void fold_undefer_and_ignore_overflow_warnings (void);
extern bool fold_deferring_overflow_warnings_p (void);
-extern tree fold_fma (location_t, tree, tree, tree, tree);
extern int operand_equal_p (const_tree, const_tree, unsigned int);
extern int multiple_of_p (tree, const_tree, const_tree);
#define omit_one_operand(T1,T2,T3)\
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 5e39b1305b8..5aa0979e563 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,306 @@
+2014-06-02 Andrew MacLeod <amacleod@redhat.com>
+
+ * fortran/trans.c (trans_runtime_error_vararg): Call
+ fold_build_call_array_loc instead of fold_builtin_call_array.
+
+2014-06-02 Bernd Schmidt <bernds@codesourcery.com>
+
+ * trans-decl.c (gfc_build_builtin_function_decls): Correct number of
+ arguments to caf_init.
+
+2014-05-26 Tobias Burnus <burnus@net-b.de>
+
+ * gfortran.texi (Project Status): Fix broken link.
+
+2014-05-26 Janne Blomqvist <jb@gcc.gnu.org>
+
+ PR libfortran/61310
+ * intrinsics.texi (CTIME): Remove mention of locale-dependent
+ behavior.
+
+2014-05-26 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/55117
+ * trans-io.c (nml_full_name, transfer_namelist_element): Insert
+ a '+' rather then '%' to differentiate namelist variable names
+ that are based on extended derived types.
+
+2014-05-25 Tobias Burnus <burnus@net-b.de>
+
+ * check.c (gfc_check_num_images): New.
+ (gfc_check_this_image): Handle distance argument.
+ * intrinsic.c (add_functions): Update this_image and num_images
+ for new distance and failed arguments.
+ * intrinsic.texi (THIS_IMAGE, NUM_IMAGES): Document the new
+ arguments.
+ * intrinsic.h (gfc_check_num_images): New.
+ (gfc_check_this_image, gfc_simplify_num_images,
+ gfc_simplify_this_image, gfc_resolve_this_image): Update prototype.
+ * iresolve.c (gfc_resolve_this_image): Handle distance argument.
+ * simplify.c (gfc_simplify_num_images, gfc_simplify_this_image):
+ Handle new arguments.
+ * trans-intrinsic.c (trans_this_image, trans_num_images): Ditto.
+ (gfc_conv_intrinsic_function): Update trans_num_images call.
+
+2014-05-23 Tobias Burnus <burnus@net-b.de>
+
+ * gfc-internals.texi: Change URLs to HTTPS; fix broken links.
+ * gfortran.texi: Ditto.
+
+2014-05-22 Thomas Schwinge <thomas@codesourcery.com>
+
+ * f95-lang.c (DEF_FUNCTION_TYPE_0, DEF_FUNCTION_TYPE_6)
+ (DEF_FUNCTION_TYPE_7, DEF_FUNCTION_TYPE_8)
+ (DEF_FUNCTION_TYPE_VAR_5): Cosmetic fixes.
+ * types.def: Simplify examples for DEF_FUNCTION_TYPE_*.
+
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * f95-lang.c (pushlevel): Adjust.
+ * trans-decl.c (gfc_allocate_lang_decl): Adjust.
+ (gfc_find_module): Likewise.
+ * trans-types.c (gfc_get_nodesc_array_type): Likewise.
+ (gfc_get_array_type_bounds): Likewise.
+ (gfc_nonrestricted_type): Likewise.
+ * trans.h: Don't use variable_size gty attribute.
+
+2014-05-17 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ * check.c (gfc_check_fn_rc2008): move "argument" to the right
+ place.
+
+2014-05-12 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/60127
+ * openmp.c (resolve_omp_do): Reject do concurrent loops.
+
+2014-05-12 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/60834
+ * frontend-passes.c (in_assoc_list): New variable.
+ (optimize_namespace): Initialize in_assoc_list
+ (combine_array_constructor): Don't try to combine
+ assoc lists.
+ (gfc_code_walker): Keep track of in_assoc_list.
+
+2014-05-11 Jakub Jelinek <jakub@redhat.com>
+
+ * gfortran.h (gfc_statement): Add ST_OMP_CANCEL,
+ ST_OMP_CANCELLATION_POINT, ST_OMP_TASKGROUP, ST_OMP_END_TASKGROUP,
+ ST_OMP_SIMD, ST_OMP_END_SIMD, ST_OMP_DO_SIMD, ST_OMP_END_DO_SIMD,
+ ST_OMP_PARALLEL_DO_SIMD, ST_OMP_END_PARALLEL_DO_SIMD and
+ ST_OMP_DECLARE_SIMD.
+ (gfc_omp_namelist): New typedef.
+ (gfc_get_omp_namelist): Define.
+ (OMP_LIST_UNIFORM, OMP_LIST_ALIGNED, OMP_LIST_LINEAR,
+ OMP_LIST_DEPEND_IN, OMP_LIST_DEPEND_OUT): New clause list kinds.
+ (gfc_omp_proc_bind_kind, gfc_omp_cancel_kind): New enums.
+ (gfc_omp_clauses): Change type of lists to gfc_omp_namelist *.
+ Add inbranch, notinbranch, cancel, proc_bind, safelen_expr and
+ simdlen_expr fields.
+ (gfc_omp_declare_simd): New typedef.
+ (gfc_get_omp_declare_simd): Define.
+ (gfc_namespace): Add omp_declare_simd field.
+ (gfc_exec_op): Add EXEC_OMP_CANCEL, EXEC_OMP_CANCELLATION_POINT,
+ EXEC_OMP_TASKGROUP, EXEC_OMP_SIMD, EXEC_OMP_DO_SIMD and
+ EXEC_OMP_PARALLEL_DO_SIMD.
+ (gfc_omp_atomic_op): Add GFC_OMP_ATOMIC_MASK, GFC_OMP_ATOMIC_SEQ_CST
+ and GFC_OMP_ATOMIC_SWAP.
+ (gfc_code): Change type of omp_namelist field to gfc_omp_namelist *.
+ (gfc_free_omp_namelist, gfc_free_omp_declare_simd,
+ gfc_free_omp_declare_simd_list, gfc_resolve_omp_declare_simd): New
+ prototypes.
+ * trans-stmt.h (gfc_trans_omp_declare_simd): New prototype.
+ * symbol.c (gfc_free_namespace): Call gfc_free_omp_declare_simd.
+ * openmp.c (gfc_free_omp_clauses): Free safelen_expr and
+ simdlen_expr. Use gfc_free_omp_namelist instead of
+ gfc_free_namelist.
+ (gfc_free_omp_declare_simd, gfc_free_omp_declare_simd_list): New
+ functions.
+ (gfc_match_omp_variable_list): Add end_colon, headp and
+ allow_sections arguments. Handle parsing of array sections.
+ Use *omp_namelist* instead of *namelist* data structure and
+ functions/macros. Allow termination at : character.
+ (OMP_CLAUSE_ALIGNED, OMP_CLAUSE_DEPEND, OMP_CLAUSE_INBRANCH,
+ OMP_CLAUSE_LINEAR, OMP_CLAUSE_NOTINBRANCH, OMP_CLAUSE_PROC_BIND,
+ OMP_CLAUSE_SAFELEN, OMP_CLAUSE_SIMDLEN, OMP_CLAUSE_UNIFORM): Define.
+ (gfc_match_omp_clauses): Change first and needs_space variables
+ into arguments with default values. Parse inbranch, notinbranch,
+ proc_bind, safelen, simdlen, uniform, linear, aligned and
+ depend clauses.
+ (OMP_PARALLEL_CLAUSES): Add OMP_CLAUSE_PROC_BIND.
+ (OMP_DECLARE_SIMD_CLAUSES, OMP_SIMD_CLAUSES): Define.
+ (OMP_TASK_CLAUSES): Add OMP_CLAUSE_DEPEND.
+ (gfc_match_omp_do_simd): New function.
+ (gfc_match_omp_flush): Use *omp_namelist* instead of *namelist*
+ data structure and functions/macros.
+ (gfc_match_omp_simd, gfc_match_omp_declare_simd,
+ gfc_match_omp_parallel_do_simd): New functions.
+ (gfc_match_omp_atomic): Handle seq_cst clause. Handle atomic swap.
+ (gfc_match_omp_taskgroup, gfc_match_omp_cancel_kind,
+ gfc_match_omp_cancel, gfc_match_omp_cancellation_point): New
+ functions.
+ (resolve_omp_clauses): Add where, omp_clauses and ns arguments.
+ Use *omp_namelist* instead of *namelist* data structure and
+ functions/macros. Resolve uniform, aligned, linear, depend,
+ safelen and simdlen clauses.
+ (resolve_omp_atomic): Adjust for GFC_OMP_ATOMIC_{MASK,SEQ_CST,SWAP}
+ addition, recognize atomic swap.
+ (gfc_resolve_omp_parallel_blocks): Use gfc_omp_namelist instead
+ of gfc_namelist. Handle EXEC_OMP_PARALLEL_DO_SIMD the same as
+ EXEC_OMP_PARALLEL_DO.
+ (gfc_resolve_do_iterator): Use *omp_namelist* instead of *namelist*
+ data structure and functions/macros.
+ (resolve_omp_do): Likewise. Handle EXEC_OMP_SIMD, EXEC_OMP_DO_SIMD,
+ EXEC_OMP_PARALLEL_DO_SIMD.
+ (gfc_resolve_omp_directive): Handle EXEC_OMP_SIMD, EXEC_OMP_DO_SIMD,
+ EXEC_OMP_PARALLEL_DO_SIMD and EXEC_OMP_CANCEL. Adjust
+ resolve_omp_clauses caller.
+ (gfc_resolve_omp_declare_simd): New function.
+ * parse.c (decode_omp_directive): Parse cancellation point, cancel,
+ declare simd, end do simd, end simd, end parallel do simd,
+ end taskgroup, parallel do simd, simd and taskgroup directives.
+ (case_executable): Add ST_OMP_CANCEL and ST_OMP_CANCELLATION_POINT.
+ (case_exec_markers): Add ST_OMP_TASKGROUP, case ST_OMP_SIMD,
+ ST_OMP_DO_SIMD and ST_OMP_PARALLEL_DO_SIMD.
+ (case_decl): Add ST_OMP_DECLARE_SIMD.
+ (gfc_ascii_statement): Handle ST_OMP_CANCEL,
+ ST_OMP_CANCELLATION_POINT, ST_OMP_TASKGROUP, ST_OMP_END_TASKGROUP,
+ ST_OMP_SIMD, ST_OMP_END_SIMD, ST_OMP_DO_SIMD, ST_OMP_END_DO_SIMD,
+ ST_OMP_PARALLEL_DO_SIMD, ST_OMP_END_PARALLEL_DO_SIMD and
+ ST_OMP_DECLARE_SIMD.
+ (parse_omp_do): Handle ST_OMP_SIMD, ST_OMP_DO_SIMD and
+ ST_OMP_PARALLEL_DO_SIMD.
+ (parse_omp_atomic): Adjust for GFC_OMP_ATOMIC_* additions.
+ (parse_omp_structured_block): Handle ST_OMP_TASKGROUP and
+ ST_OMP_PARALLEL_DO_SIMD.
+ (parse_executable): Handle ST_OMP_SIMD, ST_OMP_DO_SIMD,
+ ST_OMP_PARALLEL_DO_SIMD and ST_OMP_TASKGROUP.
+ * trans-decl.c (gfc_get_extern_function_decl,
+ gfc_create_function_decl): Call gfc_trans_omp_declare_simd if
+ needed.
+ * frontend-passes.c (gfc_code_walker): Handle EXEC_OMP_SIMD,
+ EXEC_OMP_DO_SIMD and EXEC_OMP_PARALLEL_DO_SIMD. Walk
+ safelen_expr and simdlen_expr. Walk expressions in gfc_omp_namelist
+ of depend, aligned and linear clauses.
+ * match.c (match_exit_cycle): Handle EXEC_OMP_SIMD, EXEC_OMP_DO_SIMD
+ and EXEC_OMP_PARALLEL_DO_SIMD.
+ (gfc_free_omp_namelist): New function.
+ * dump-parse-tree.c (show_namelist): Removed.
+ (show_omp_namelist): New function.
+ (show_omp_node): Handle OpenMP 4.0 additions.
+ (show_code_node): Handle EXEC_OMP_CANCEL, EXEC_OMP_CANCELLATION_POINT,
+ EXEC_OMP_DO_SIMD, EXEC_OMP_PARALLEL_DO_SIMD, EXEC_OMP_SIMD and
+ EXEC_OMP_TASKGROUP.
+ * match.h (gfc_match_omp_cancel, gfc_match_omp_cancellation_point,
+ gfc_match_omp_declare_simd, gfc_match_omp_do_simd,
+ gfc_match_omp_parallel_do_simd, gfc_match_omp_simd,
+ gfc_match_omp_taskgroup): New prototypes.
+ * trans-openmp.c (gfc_trans_omp_variable): Add declare_simd
+ argument, handle it. Allow current_function_decl to be NULL.
+ (gfc_trans_omp_variable_list): Add declare_simd argument, pass
+ it through to gfc_trans_omp_variable and disregard whether
+ sym is referenced if declare_simd is true. Work on gfc_omp_namelist
+ instead of gfc_namelist.
+ (gfc_trans_omp_reduction_list): Work on gfc_omp_namelist instead of
+ gfc_namelist. Adjust gfc_trans_omp_variable caller.
+ (gfc_trans_omp_clauses): Add declare_simd argument, pass it through
+ to gfc_trans_omp_variable{,_list} callers. Work on gfc_omp_namelist
+ instead of gfc_namelist. Handle inbranch, notinbranch, safelen,
+ simdlen, depend, uniform, linear, proc_bind and aligned clauses.
+ Handle cancel kind.
+ (gfc_trans_omp_atomic): Handle seq_cst clause, handle atomic swap,
+ adjust for GFC_OMP_ATOMIC_* changes.
+ (gfc_trans_omp_cancel, gfc_trans_omp_cancellation_point): New
+ functions.
+ (gfc_trans_omp_do): Add op argument, handle simd translation into
+ generic.
+ (GFC_OMP_SPLIT_SIMD, GFC_OMP_SPLIT_DO, GFC_OMP_SPLIT_PARALLEL,
+ GFC_OMP_SPLIT_NUM, GFC_OMP_MASK_SIMD, GFC_OMP_MASK_DO,
+ GFC_OMP_MASK_PARALLEL): New.
+ (gfc_split_omp_clauses, gfc_trans_omp_do_simd): New functions.
+ (gfc_trans_omp_parallel_do): Rework to use gfc_split_omp_clauses.
+ (gfc_trans_omp_parallel_do_simd, gfc_trans_omp_taskgroup): New
+ functions.
+ (gfc_trans_omp_directive): Handle EXEC_OMP_CANCEL,
+ EXEC_OMP_CANCELLATION_POINT, EXEC_OMP_DO_SIMD,
+ EXEC_OMP_PARALLEL_DO_SIMD, EXEC_OMP_SIMD and EXEC_OMP_TASKGROUP.
+ Adjust gfc_trans_omp_do caller.
+ (gfc_trans_omp_declare_simd): New function.
+ * st.c (gfc_free_statement): Handle EXEC_OMP_CANCEL,
+ EXEC_OMP_CANCELLATION_POINT, EXEC_OMP_DO_SIMD,
+ EXEC_OMP_PARALLEL_DO_SIMD, EXEC_OMP_SIMD and EXEC_OMP_TASKGROUP.
+ For EXEC_OMP_FLUSH call gfc_free_omp_namelist instead of
+ gfc_free_namelist.
+ * module.c (omp_declare_simd_clauses): New variable.
+ (mio_omp_declare_simd): New function.
+ (mio_symbol): Call it.
+ * trans.c (trans_code): Handle EXEC_OMP_CANCEL,
+ EXEC_OMP_CANCELLATION_POINT, EXEC_OMP_DO_SIMD,
+ EXEC_OMP_PARALLEL_DO_SIMD, EXEC_OMP_SIMD and EXEC_OMP_TASKGROUP.
+ * resolve.c (gfc_resolve_blocks): Handle EXEC_OMP_DO_SIMD,
+ EXEC_OMP_PARALLEL_DO_SIMD, EXEC_OMP_SIMD and EXEC_OMP_TASKGROUP.
+ (resolve_code): Handle EXEC_OMP_CANCEL,
+ EXEC_OMP_CANCELLATION_POINT, EXEC_OMP_DO_SIMD,
+ EXEC_OMP_PARALLEL_DO_SIMD, EXEC_OMP_SIMD and EXEC_OMP_TASKGROUP.
+ (resolve_types): Call gfc_resolve_omp_declare_simd.
+
+2014-05-11 Tobias Burnus <burnus@net-b.de>
+
+ * trans-intrinsic.c (gfc_build_builtin_function_decls):
+ Change type of second argument to int.
+
+2014-05-09 Mike Stump <mikestump@comcast.net>
+
+ PR fortran/61109
+ * trans-array.c (gfc_conv_array_initializer): Fix wide-int
+ conversion bug.
+
+2014-05-08 Tobias Burnus <burnus@net-b.de>
+
+ * gfortran.h (gfc_isym_id): Add GFC_ISYM_CAF_GET
+ and GFC_ISYM_CAF_SEND.
+ * intrinsic.c (add_functions): Add only internally
+ accessible caf_get and caf_send functions.
+ * resolve.c (add_caf_get_intrinsic,
+ remove_caf_get_intrinsic): New functions.
+ (resolve_variable): Resolve expression rank and
+ prepare for add_caf_get_intrinsic call.
+ (gfc_resolve_expr): For variables, remove rank
+ resolution.
+ (resolve_ordinary_assign): Prepare call to
+ GFC_ISYM_CAF_SEND.
+ (resolve_code): Avoid call to GFC_ISYM_CAF_GET for
+ the LHS of an assignment.
+
+2014-05-08 Tobias Burnus <burnus@net-b.de>
+
+ * trans-intrinsic.c (conv_co_minmaxsum): Change condition style.
+
+2014-05-08 Tobias Burnus <burnus@net-b.de>
+
+ * check.c (check_co_minmaxsum, gfc_check_co_minmax,
+ gfc_check_co_sum): New.
+ * error.c (gfc_notify_std): Update -std=f2008ts.
+ * gfortran.h (gfc_isym_id): Add GFC_ISYM_CO_MAX,
+ GFC_ISYM_CO_MIN, GFC_ISYM_CO_SUM.
+ * intrinsic.h (gfc_check_co_minmax,
+ gfc_check_co_sum): Declare.
+ * intrinsic.c (add_subroutines): Add co_min, co_max
+ and co_sum.
+ (gfc_check_intrinsic_standard): Update text for
+ -std=f2008ts.
+ * intrinsic.texi (CO_MIN, CO_MAX, CO_SUM): Document
+ them.
+ * invoke.texi (-std=f2008ts): Update wording.
+ * trans.h (gfor_fndecl_co_max,
+ gfor_fndecl_co_min, gfor_fndecl_co_sum): Define.
+ * trans-decl.c (gfor_fndecl_co_max,
+ gfor_fndecl_co_min, gfor_fndecl_co_sum): Define.
+ (gfc_build_builtin_function_decls): Assign to it.
+ * trans-intrinsic.c (conv_co_minmaxsum): New.
+ (gfc_conv_intrinsic_subroutine): Call it.
+
2014-05-06 Kenneth Zadeck <zadeck@naturalbridge.com>
Mike Stump <mikestump@comcast.net>
Richard Sandiford <rdsandiford@googlemail.com>
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index b83d9da148d..20af75feb44 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -1290,6 +1290,91 @@ gfc_check_cmplx (gfc_expr *x, gfc_expr *y, gfc_expr *kind)
}
+static bool
+check_co_minmaxsum (gfc_expr *a, gfc_expr *result_image, gfc_expr *stat,
+ gfc_expr *errmsg)
+{
+ if (!variable_check (a, 0, false))
+ return false;
+
+ if (result_image != NULL)
+ {
+ if (!type_check (result_image, 1, BT_INTEGER))
+ return false;
+ if (!scalar_check (result_image, 1))
+ return false;
+ }
+
+ if (stat != NULL)
+ {
+ if (!type_check (stat, 2, BT_INTEGER))
+ return false;
+ if (!scalar_check (stat, 2))
+ return false;
+ if (!variable_check (stat, 2, false))
+ return false;
+ if (stat->ts.kind != 4)
+ {
+ gfc_error ("The stat= argument at %L must be a kind=4 integer "
+ "variable", &stat->where);
+ return false;
+ }
+ }
+
+ if (errmsg != NULL)
+ {
+ if (!type_check (errmsg, 3, BT_CHARACTER))
+ return false;
+ if (!scalar_check (errmsg, 3))
+ return false;
+ if (!variable_check (errmsg, 3, false))
+ return false;
+ if (errmsg->ts.kind != 1)
+ {
+ gfc_error ("The errmsg= argument at %L must be a default-kind "
+ "character variable", &errmsg->where);
+ return false;
+ }
+ }
+
+ if (gfc_option.coarray == GFC_FCOARRAY_NONE)
+ {
+ gfc_fatal_error ("Coarrays disabled at %L, use -fcoarray= to enable",
+ &a->where);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool
+gfc_check_co_minmax (gfc_expr *a, gfc_expr *result_image, gfc_expr *stat,
+ gfc_expr *errmsg)
+{
+ if (a->ts.type != BT_INTEGER && a->ts.type != BT_REAL
+ && a->ts.type != BT_CHARACTER)
+ {
+ gfc_error ("'%s' argument of '%s' intrinsic at %L shall be of type "
+ "integer, real or character",
+ gfc_current_intrinsic_arg[0]->name, gfc_current_intrinsic,
+ &a->where);
+ return false;
+ }
+ return check_co_minmaxsum (a, result_image, stat, errmsg);
+}
+
+
+bool
+gfc_check_co_sum (gfc_expr *a, gfc_expr *result_image, gfc_expr *stat,
+ gfc_expr *errmsg)
+{
+ if (!numeric_check (a, 0))
+ return false;
+ return check_co_minmaxsum (a, result_image, stat, errmsg);
+}
+
+
bool
gfc_check_complex (gfc_expr *x, gfc_expr *y)
{
@@ -1737,7 +1822,7 @@ gfc_check_fn_rc2008 (gfc_expr *a)
if (a->ts.type == BT_COMPLEX
&& !gfc_notify_std (GFC_STD_F2008, "COMPLEX argument '%s' "
- "argument of '%s' intrinsic at %L",
+ "of '%s' intrinsic at %L",
gfc_current_intrinsic_arg[0]->name,
gfc_current_intrinsic, &a->where))
return false;
@@ -4467,7 +4552,7 @@ gfc_check_image_index (gfc_expr *coarray, gfc_expr *sub)
bool
-gfc_check_this_image (gfc_expr *coarray, gfc_expr *dim)
+gfc_check_num_images (gfc_expr *distance, gfc_expr *failed)
{
if (gfc_option.coarray == GFC_FCOARRAY_NONE)
{
@@ -4475,16 +4560,96 @@ gfc_check_this_image (gfc_expr *coarray, gfc_expr *dim)
return false;
}
- if (dim != NULL && coarray == NULL)
+ if (distance)
{
- gfc_error ("DIM argument without ARRAY argument not allowed for THIS_IMAGE "
- "intrinsic at %L", &dim->where);
+ if (!type_check (distance, 0, BT_INTEGER))
+ return false;
+
+ if (!nonnegative_check ("DISTANCE", distance))
+ return false;
+
+ if (!scalar_check (distance, 0))
+ return false;
+
+ if (!gfc_notify_std (GFC_STD_F2008_TS, "DISTANCE= argument to "
+ "NUM_IMAGES at %L", &distance->where))
+ return false;
+ }
+
+ if (failed)
+ {
+ if (!type_check (failed, 1, BT_LOGICAL))
+ return false;
+
+ if (!scalar_check (failed, 1))
+ return false;
+
+ if (!gfc_notify_std (GFC_STD_F2008_TS, "FAILED= argument to "
+ "NUM_IMAGES at %L", &distance->where))
+ return false;
+ }
+
+ return true;
+}
+
+
+bool
+gfc_check_this_image (gfc_expr *coarray, gfc_expr *dim, gfc_expr *distance)
+{
+ if (gfc_option.coarray == GFC_FCOARRAY_NONE)
+ {
+ gfc_fatal_error ("Coarrays disabled at %C, use -fcoarray= to enable");
return false;
}
- if (coarray == NULL)
+ if (coarray == NULL && dim == NULL && distance == NULL)
return true;
+ if (dim != NULL && coarray == NULL)
+ {
+ gfc_error ("DIM argument without COARRAY argument not allowed for "
+ "THIS_IMAGE intrinsic at %L", &dim->where);
+ return false;
+ }
+
+ if (distance && (coarray || dim))
+ {
+ gfc_error ("The DISTANCE argument may not be specified together with the "
+ "COARRAY or DIM argument in intrinsic at %L",
+ &distance->where);
+ return false;
+ }
+
+ /* Assume that we have "this_image (distance)". */
+ if (coarray && !gfc_is_coarray (coarray) && coarray->ts.type == BT_INTEGER)
+ {
+ if (dim)
+ {
+ gfc_error ("Unexpected DIM argument with noncoarray argument at %L",
+ &coarray->where);
+ return false;
+ }
+ distance = coarray;
+ }
+
+ if (distance)
+ {
+ if (!type_check (distance, 2, BT_INTEGER))
+ return false;
+
+ if (!nonnegative_check ("DISTANCE", distance))
+ return false;
+
+ if (!scalar_check (distance, 2))
+ return false;
+
+ if (!gfc_notify_std (GFC_STD_F2008_TS, "DISTANCE= argument to "
+ "THIS_IMAGE at %L", &distance->where))
+ return false;
+
+ return true;
+ }
+
if (!coarray_check (coarray, 0))
return false;
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index b1343bc2a86..b5d2537a083 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -1016,11 +1016,19 @@ show_code (int level, gfc_code *c)
}
static void
-show_namelist (gfc_namelist *n)
+show_omp_namelist (gfc_omp_namelist *n)
{
- for (; n->next; n = n->next)
- fprintf (dumpfile, "%s,", n->sym->name);
- fprintf (dumpfile, "%s", n->sym->name);
+ for (; n; n = n->next)
+ {
+ fprintf (dumpfile, "%s", n->sym->name);
+ if (n->expr)
+ {
+ fputc (':', dumpfile);
+ show_expr (n->expr);
+ }
+ if (n->next)
+ fputc (',', dumpfile);
+ }
}
/* Show a single OpenMP directive node and everything underneath it
@@ -1036,18 +1044,24 @@ show_omp_node (int level, gfc_code *c)
{
case EXEC_OMP_ATOMIC: name = "ATOMIC"; break;
case EXEC_OMP_BARRIER: name = "BARRIER"; break;
+ case EXEC_OMP_CANCEL: name = "CANCEL"; break;
+ case EXEC_OMP_CANCELLATION_POINT: name = "CANCELLATION POINT"; break;
case EXEC_OMP_CRITICAL: name = "CRITICAL"; break;
case EXEC_OMP_FLUSH: name = "FLUSH"; break;
case EXEC_OMP_DO: name = "DO"; break;
+ case EXEC_OMP_DO_SIMD: name = "DO SIMD"; break;
case EXEC_OMP_MASTER: name = "MASTER"; break;
case EXEC_OMP_ORDERED: name = "ORDERED"; break;
case EXEC_OMP_PARALLEL: name = "PARALLEL"; break;
case EXEC_OMP_PARALLEL_DO: name = "PARALLEL DO"; break;
+ case EXEC_OMP_PARALLEL_DO_SIMD: name = "PARALLEL DO SIMD"; break;
case EXEC_OMP_PARALLEL_SECTIONS: name = "PARALLEL SECTIONS"; break;
case EXEC_OMP_PARALLEL_WORKSHARE: name = "PARALLEL WORKSHARE"; break;
case EXEC_OMP_SECTIONS: name = "SECTIONS"; break;
+ case EXEC_OMP_SIMD: name = "SIMD"; break;
case EXEC_OMP_SINGLE: name = "SINGLE"; break;
case EXEC_OMP_TASK: name = "TASK"; break;
+ case EXEC_OMP_TASKGROUP: name = "TASKGROUP"; break;
case EXEC_OMP_TASKWAIT: name = "TASKWAIT"; break;
case EXEC_OMP_TASKYIELD: name = "TASKYIELD"; break;
case EXEC_OMP_WORKSHARE: name = "WORKSHARE"; break;
@@ -1057,11 +1071,16 @@ show_omp_node (int level, gfc_code *c)
fprintf (dumpfile, "!$OMP %s", name);
switch (c->op)
{
+ case EXEC_OMP_CANCEL:
+ case EXEC_OMP_CANCELLATION_POINT:
case EXEC_OMP_DO:
+ case EXEC_OMP_DO_SIMD:
case EXEC_OMP_PARALLEL:
case EXEC_OMP_PARALLEL_DO:
+ case EXEC_OMP_PARALLEL_DO_SIMD:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_SECTIONS:
+ case EXEC_OMP_SIMD:
case EXEC_OMP_SINGLE:
case EXEC_OMP_WORKSHARE:
case EXEC_OMP_PARALLEL_WORKSHARE:
@@ -1076,7 +1095,7 @@ show_omp_node (int level, gfc_code *c)
if (c->ext.omp_namelist)
{
fputs (" (", dumpfile);
- show_namelist (c->ext.omp_namelist);
+ show_omp_namelist (c->ext.omp_namelist);
fputc (')', dumpfile);
}
return;
@@ -1091,6 +1110,23 @@ show_omp_node (int level, gfc_code *c)
{
int list_type;
+ switch (omp_clauses->cancel)
+ {
+ case OMP_CANCEL_UNKNOWN:
+ break;
+ case OMP_CANCEL_PARALLEL:
+ fputs (" PARALLEL", dumpfile);
+ break;
+ case OMP_CANCEL_SECTIONS:
+ fputs (" SECTIONS", dumpfile);
+ break;
+ case OMP_CANCEL_DO:
+ fputs (" DO", dumpfile);
+ break;
+ case OMP_CANCEL_TASKGROUP:
+ fputs (" TASKGROUP", dumpfile);
+ break;
+ }
if (omp_clauses->if_expr)
{
fputs (" IF(", dumpfile);
@@ -1156,7 +1192,7 @@ show_omp_node (int level, gfc_code *c)
if (omp_clauses->lists[list_type] != NULL
&& list_type != OMP_LIST_COPYPRIVATE)
{
- const char *type;
+ const char *type = NULL;
if (list_type >= OMP_LIST_REDUCTION_FIRST)
{
switch (list_type)
@@ -1187,14 +1223,53 @@ show_omp_node (int level, gfc_code *c)
case OMP_LIST_LASTPRIVATE: type = "LASTPRIVATE"; break;
case OMP_LIST_SHARED: type = "SHARED"; break;
case OMP_LIST_COPYIN: type = "COPYIN"; break;
+ case OMP_LIST_UNIFORM: type = "UNIFORM"; break;
+ case OMP_LIST_ALIGNED: type = "ALIGNED"; break;
+ case OMP_LIST_LINEAR: type = "LINEAR"; break;
+ case OMP_LIST_DEPEND_IN:
+ fprintf (dumpfile, " DEPEND(IN:");
+ break;
+ case OMP_LIST_DEPEND_OUT:
+ fprintf (dumpfile, " DEPEND(OUT:");
+ break;
default:
gcc_unreachable ();
}
- fprintf (dumpfile, " %s(", type);
+ if (type)
+ fprintf (dumpfile, " %s(", type);
}
- show_namelist (omp_clauses->lists[list_type]);
+ show_omp_namelist (omp_clauses->lists[list_type]);
fputc (')', dumpfile);
}
+ if (omp_clauses->safelen_expr)
+ {
+ fputs (" SAFELEN(", dumpfile);
+ show_expr (omp_clauses->safelen_expr);
+ fputc (')', dumpfile);
+ }
+ if (omp_clauses->simdlen_expr)
+ {
+ fputs (" SIMDLEN(", dumpfile);
+ show_expr (omp_clauses->simdlen_expr);
+ fputc (')', dumpfile);
+ }
+ if (omp_clauses->inbranch)
+ fputs (" INBRANCH", dumpfile);
+ if (omp_clauses->notinbranch)
+ fputs (" NOTINBRANCH", dumpfile);
+ if (omp_clauses->proc_bind != OMP_PROC_BIND_UNKNOWN)
+ {
+ const char *type;
+ switch (omp_clauses->proc_bind)
+ {
+ case OMP_PROC_BIND_MASTER: type = "MASTER"; break;
+ case OMP_PROC_BIND_SPREAD: type = "SPREAD"; break;
+ case OMP_PROC_BIND_CLOSE: type = "CLOSE"; break;
+ default:
+ gcc_unreachable ();
+ }
+ fprintf (dumpfile, " PROC_BIND(%s)", type);
+ }
}
fputc ('\n', dumpfile);
if (c->op == EXEC_OMP_SECTIONS || c->op == EXEC_OMP_PARALLEL_SECTIONS)
@@ -1214,6 +1289,7 @@ show_omp_node (int level, gfc_code *c)
show_code (level + 1, c->block->next);
if (c->op == EXEC_OMP_ATOMIC)
return;
+ fputc ('\n', dumpfile);
code_indent (level, 0);
fprintf (dumpfile, "!$OMP END %s", name);
if (omp_clauses != NULL)
@@ -1221,7 +1297,7 @@ show_omp_node (int level, gfc_code *c)
if (omp_clauses->lists[OMP_LIST_COPYPRIVATE])
{
fputs (" COPYPRIVATE(", dumpfile);
- show_namelist (omp_clauses->lists[OMP_LIST_COPYPRIVATE]);
+ show_omp_namelist (omp_clauses->lists[OMP_LIST_COPYPRIVATE]);
fputc (')', dumpfile);
}
else if (omp_clauses->nowait)
@@ -2195,19 +2271,25 @@ show_code_node (int level, gfc_code *c)
break;
case EXEC_OMP_ATOMIC:
+ case EXEC_OMP_CANCEL:
+ case EXEC_OMP_CANCELLATION_POINT:
case EXEC_OMP_BARRIER:
case EXEC_OMP_CRITICAL:
case EXEC_OMP_FLUSH:
case EXEC_OMP_DO:
+ case EXEC_OMP_DO_SIMD:
case EXEC_OMP_MASTER:
case EXEC_OMP_ORDERED:
case EXEC_OMP_PARALLEL:
case EXEC_OMP_PARALLEL_DO:
+ case EXEC_OMP_PARALLEL_DO_SIMD:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_PARALLEL_WORKSHARE:
case EXEC_OMP_SECTIONS:
+ case EXEC_OMP_SIMD:
case EXEC_OMP_SINGLE:
case EXEC_OMP_TASK:
+ case EXEC_OMP_TASKGROUP:
case EXEC_OMP_TASKWAIT:
case EXEC_OMP_TASKYIELD:
case EXEC_OMP_WORKSHARE:
diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c
index e843fa5a96c..6ae44e87c2f 100644
--- a/gcc/fortran/error.c
+++ b/gcc/fortran/error.c
@@ -878,7 +878,7 @@ gfc_notify_std (int std, const char *gmsgid, ...)
switch (std)
{
case GFC_STD_F2008_TS:
- msg2 = "TS 29113:";
+ msg2 = "TS 29113/TS 18508:";
break;
case GFC_STD_F2008_OBS:
msg2 = _("Fortran 2008 obsolescent feature:");
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index e25e92a5533..f5d57a8e8fc 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -323,7 +323,7 @@ getdecls (void)
void
pushlevel (void)
{
- struct binding_level *newlevel = ggc_alloc_binding_level ();
+ struct binding_level *newlevel = ggc_alloc<binding_level> ();
*newlevel = clear_binding_level;
@@ -620,9 +620,12 @@ gfc_init_builtin_functions (void)
#define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
#define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
#define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME,
-#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) NAME,
-#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) NAME,
-#define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) NAME,
+#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6) NAME,
+#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7) NAME,
+#define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7, ARG8) NAME,
#define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
#include "types.def"
@@ -1020,12 +1023,15 @@ gfc_init_builtin_functions (void)
= build_pointer_type (builtin_types[(int) TYPE]);
#include "types.def"
#undef DEF_PRIMITIVE_TYPE
+#undef DEF_FUNCTION_TYPE_0
#undef DEF_FUNCTION_TYPE_1
#undef DEF_FUNCTION_TYPE_2
#undef DEF_FUNCTION_TYPE_3
#undef DEF_FUNCTION_TYPE_4
#undef DEF_FUNCTION_TYPE_5
#undef DEF_FUNCTION_TYPE_6
+#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_POINTER_TYPE
builtin_types[(int) BT_LAST] = NULL_TREE;
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index 6c67e66108b..564231690c8 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -88,6 +88,10 @@ static int doloop_size, doloop_level;
struct my_struct *evec;
+/* Keep track of association lists. */
+
+static bool in_assoc_list;
+
/* Entry point - run all passes for a namespace. */
void
@@ -820,6 +824,7 @@ optimize_namespace (gfc_namespace *ns)
current_ns = ns;
forall_level = 0;
iterator_level = 0;
+ in_assoc_list = false;
in_omp_workshare = false;
gfc_code_walker (&ns->code, convert_do_while, dummy_expr_callback, NULL);
@@ -1054,6 +1059,11 @@ combine_array_constructor (gfc_expr *e)
if (e->rank != 1)
return false;
+ /* Don't try to combine association lists, this makes no sense
+ and leads to an ICE. */
+ if (in_assoc_list)
+ return false;
+
op1 = e->value.op.op1;
op2 = e->value.op.op2;
@@ -1940,8 +1950,17 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
case EXEC_BLOCK:
WALK_SUBCODE (co->ext.block.ns->code);
- for (alist = co->ext.block.assoc; alist; alist = alist->next)
- WALK_SUBEXPR (alist->target);
+ if (co->ext.block.assoc)
+ {
+ bool saved_in_assoc_list = in_assoc_list;
+
+ in_assoc_list = true;
+ for (alist = co->ext.block.assoc; alist; alist = alist->next)
+ WALK_SUBEXPR (alist->target);
+
+ in_assoc_list = saved_in_assoc_list;
+ }
+
break;
case EXEC_DO:
@@ -2112,6 +2131,7 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
case EXEC_OMP_PARALLEL:
case EXEC_OMP_PARALLEL_DO:
+ case EXEC_OMP_PARALLEL_DO_SIMD:
case EXEC_OMP_PARALLEL_SECTIONS:
in_omp_workshare = false;
@@ -2128,9 +2148,11 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
/* Fall through */
case EXEC_OMP_DO:
+ case EXEC_OMP_DO_SIMD:
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SINGLE:
case EXEC_OMP_END_SINGLE:
+ case EXEC_OMP_SIMD:
case EXEC_OMP_TASK:
/* Come to this label only from the
@@ -2144,7 +2166,24 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
WALK_SUBEXPR (co->ext.omp_clauses->final_expr);
WALK_SUBEXPR (co->ext.omp_clauses->num_threads);
WALK_SUBEXPR (co->ext.omp_clauses->chunk_size);
+ WALK_SUBEXPR (co->ext.omp_clauses->safelen_expr);
+ WALK_SUBEXPR (co->ext.omp_clauses->simdlen_expr);
}
+ {
+ gfc_omp_namelist *n;
+ for (n = co->ext.omp_clauses->lists[OMP_LIST_ALIGNED];
+ n; n = n->next)
+ WALK_SUBEXPR (n->expr);
+ for (n = co->ext.omp_clauses->lists[OMP_LIST_LINEAR];
+ n; n = n->next)
+ WALK_SUBEXPR (n->expr);
+ for (n = co->ext.omp_clauses->lists[OMP_LIST_DEPEND_IN];
+ n; n = n->next)
+ WALK_SUBEXPR (n->expr);
+ for (n = co->ext.omp_clauses->lists[OMP_LIST_DEPEND_OUT];
+ n; n = n->next)
+ WALK_SUBEXPR (n->expr);
+ }
break;
default:
break;
diff --git a/gcc/fortran/gfc-internals.texi b/gcc/fortran/gfc-internals.texi
index 44516a039dd..4fe858d8b60 100644
--- a/gcc/fortran/gfc-internals.texi
+++ b/gcc/fortran/gfc-internals.texi
@@ -743,7 +743,7 @@ further processed.
@node Symbol Versioning
@section Symbol Versioning
-@comment Based on http://gcc.gnu.org/wiki/SymbolVersioning,
+@comment Based on https://gcc.gnu.org/wiki/SymbolVersioning,
@comment as of 2006-11-05, written by Janne Blomqvist.
In general, this capability exists only on a few platforms, thus there
@@ -757,15 +757,15 @@ Also, the map file is used to hide local symbols.
Some relevant references:
@itemize @bullet
@item
-@uref{http://www.gnu.org/software/binutils/manual/ld-2.9.1/html_node/ld_25.html,
+@uref{https://sourceware.org/binutils/docs/ld/VERSION.html,
GNU @command{ld} manual}
@item
-@uref{http://people.redhat.com/drepper/symbol-versioning, ELF Symbol
+@uref{http://www.akkadia.org/drepper/symbol-versioning, ELF Symbol
Versioning - Ulrich Depper}
@item
-@uref{http://people.redhat.com/drepper/dsohowto.pdf, How to Write Shared
+@uref{http://www.akkadia.org/drepper/dsohowto.pdf, How to Write Shared
Libraries - Ulrich Drepper (see Chapter 3)}
@end itemize
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 0707b58bd2b..3e5cdbd7d49 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -211,8 +211,12 @@ typedef enum
ST_OMP_PARALLEL, ST_OMP_PARALLEL_DO, ST_OMP_PARALLEL_SECTIONS,
ST_OMP_PARALLEL_WORKSHARE, ST_OMP_SECTIONS, ST_OMP_SECTION, ST_OMP_SINGLE,
ST_OMP_THREADPRIVATE, ST_OMP_WORKSHARE, ST_OMP_TASK, ST_OMP_END_TASK,
- ST_OMP_TASKWAIT, ST_OMP_TASKYIELD, ST_PROCEDURE, ST_GENERIC, ST_CRITICAL,
- ST_END_CRITICAL, ST_GET_FCN_CHARACTERISTICS, ST_LOCK, ST_UNLOCK, ST_NONE
+ ST_OMP_TASKWAIT, ST_OMP_TASKYIELD, ST_OMP_CANCEL, ST_OMP_CANCELLATION_POINT,
+ ST_OMP_TASKGROUP, ST_OMP_END_TASKGROUP, ST_OMP_SIMD, ST_OMP_END_SIMD,
+ ST_OMP_DO_SIMD, ST_OMP_END_DO_SIMD, ST_OMP_PARALLEL_DO_SIMD,
+ ST_OMP_END_PARALLEL_DO_SIMD, ST_OMP_DECLARE_SIMD, ST_PROCEDURE, ST_GENERIC,
+ ST_CRITICAL, ST_END_CRITICAL, ST_GET_FCN_CHARACTERISTICS, ST_LOCK,
+ ST_UNLOCK, ST_NONE
}
gfc_statement;
@@ -318,11 +322,16 @@ enum gfc_isym_id
GFC_ISYM_BLE,
GFC_ISYM_BLT,
GFC_ISYM_BTEST,
+ GFC_ISYM_CAF_GET,
+ GFC_ISYM_CAF_SEND,
GFC_ISYM_CEILING,
GFC_ISYM_CHAR,
GFC_ISYM_CHDIR,
GFC_ISYM_CHMOD,
GFC_ISYM_CMPLX,
+ GFC_ISYM_CO_MAX,
+ GFC_ISYM_CO_MIN,
+ GFC_ISYM_CO_SUM,
GFC_ISYM_COMMAND_ARGUMENT_COUNT,
GFC_ISYM_COMPILER_OPTIONS,
GFC_ISYM_COMPILER_VERSION,
@@ -1028,6 +1037,19 @@ gfc_namelist;
#define gfc_get_namelist() XCNEW (gfc_namelist)
+/* For use in OpenMP clauses in case we need extra information
+ (aligned clause alignment, linear clause step, etc.). */
+
+typedef struct gfc_omp_namelist
+{
+ struct gfc_symbol *sym;
+ struct gfc_expr *expr;
+ struct gfc_omp_namelist *next;
+}
+gfc_omp_namelist;
+
+#define gfc_get_omp_namelist() XCNEW (gfc_omp_namelist)
+
enum
{
OMP_LIST_PRIVATE,
@@ -1036,6 +1058,11 @@ enum
OMP_LIST_COPYPRIVATE,
OMP_LIST_SHARED,
OMP_LIST_COPYIN,
+ OMP_LIST_UNIFORM,
+ OMP_LIST_ALIGNED,
+ OMP_LIST_LINEAR,
+ OMP_LIST_DEPEND_IN,
+ OMP_LIST_DEPEND_OUT,
OMP_LIST_PLUS,
OMP_LIST_REDUCTION_FIRST = OMP_LIST_PLUS,
OMP_LIST_MULT,
@@ -1075,23 +1102,60 @@ enum gfc_omp_default_sharing
OMP_DEFAULT_FIRSTPRIVATE
};
+enum gfc_omp_proc_bind_kind
+{
+ OMP_PROC_BIND_UNKNOWN,
+ OMP_PROC_BIND_MASTER,
+ OMP_PROC_BIND_SPREAD,
+ OMP_PROC_BIND_CLOSE
+};
+
+enum gfc_omp_cancel_kind
+{
+ OMP_CANCEL_UNKNOWN,
+ OMP_CANCEL_PARALLEL,
+ OMP_CANCEL_SECTIONS,
+ OMP_CANCEL_DO,
+ OMP_CANCEL_TASKGROUP
+};
+
typedef struct gfc_omp_clauses
{
struct gfc_expr *if_expr;
struct gfc_expr *final_expr;
struct gfc_expr *num_threads;
- gfc_namelist *lists[OMP_LIST_NUM];
+ gfc_omp_namelist *lists[OMP_LIST_NUM];
enum gfc_omp_sched_kind sched_kind;
struct gfc_expr *chunk_size;
enum gfc_omp_default_sharing default_sharing;
int collapse;
bool nowait, ordered, untied, mergeable;
+ bool inbranch, notinbranch;
+ enum gfc_omp_cancel_kind cancel;
+ enum gfc_omp_proc_bind_kind proc_bind;
+ struct gfc_expr *safelen_expr;
+ struct gfc_expr *simdlen_expr;
}
gfc_omp_clauses;
#define gfc_get_omp_clauses() XCNEW (gfc_omp_clauses)
+/* Node in the linked list used for storing !$omp declare simd constructs. */
+
+typedef struct gfc_omp_declare_simd
+{
+ struct gfc_omp_declare_simd *next;
+ locus where; /* Where the !$omp declare simd construct occurred. */
+
+ gfc_symbol *proc_name;
+
+ gfc_omp_clauses *clauses;
+}
+gfc_omp_declare_simd;
+#define gfc_get_omp_declare_simd() XCNEW (gfc_omp_declare_simd)
+
+
/* The gfc_st_label structure is a BBT attached to a namespace that
records the usage of statement labels within that space. */
@@ -1464,6 +1528,9 @@ typedef struct gfc_namespace
/* A list of USE statements in this namespace. */
gfc_use_list *use_stmts;
+ /* Linked list of !$omp declare simd constructs. */
+ struct gfc_omp_declare_simd *omp_declare_simd;
+
/* Set to 1 if namespace is a BLOCK DATA program unit. */
unsigned is_block_data:1;
@@ -2111,16 +2178,21 @@ typedef enum
EXEC_OMP_SECTIONS, EXEC_OMP_SINGLE, EXEC_OMP_WORKSHARE,
EXEC_OMP_ATOMIC, EXEC_OMP_BARRIER, EXEC_OMP_END_NOWAIT,
EXEC_OMP_END_SINGLE, EXEC_OMP_TASK, EXEC_OMP_TASKWAIT,
- EXEC_OMP_TASKYIELD
+ EXEC_OMP_TASKYIELD, EXEC_OMP_CANCEL, EXEC_OMP_CANCELLATION_POINT,
+ EXEC_OMP_TASKGROUP, EXEC_OMP_SIMD, EXEC_OMP_DO_SIMD,
+ EXEC_OMP_PARALLEL_DO_SIMD
}
gfc_exec_op;
typedef enum
{
- GFC_OMP_ATOMIC_UPDATE,
- GFC_OMP_ATOMIC_READ,
- GFC_OMP_ATOMIC_WRITE,
- GFC_OMP_ATOMIC_CAPTURE
+ GFC_OMP_ATOMIC_UPDATE = 0,
+ GFC_OMP_ATOMIC_READ = 1,
+ GFC_OMP_ATOMIC_WRITE = 2,
+ GFC_OMP_ATOMIC_CAPTURE = 3,
+ GFC_OMP_ATOMIC_MASK = 3,
+ GFC_OMP_ATOMIC_SEQ_CST = 4,
+ GFC_OMP_ATOMIC_SWAP = 8
}
gfc_omp_atomic_op;
@@ -2172,7 +2244,7 @@ typedef struct gfc_code
gfc_entry_list *entry;
gfc_omp_clauses *omp_clauses;
const char *omp_name;
- gfc_namelist *omp_namelist;
+ gfc_omp_namelist *omp_namelist;
bool omp_bool;
gfc_omp_atomic_op omp_atomic;
}
@@ -2728,6 +2800,7 @@ void gfc_free_iterator (gfc_iterator *, int);
void gfc_free_forall_iterator (gfc_forall_iterator *);
void gfc_free_alloc_list (gfc_alloc *);
void gfc_free_namelist (gfc_namelist *);
+void gfc_free_omp_namelist (gfc_omp_namelist *);
void gfc_free_equiv (gfc_equiv *);
void gfc_free_equiv_until (gfc_equiv *, gfc_equiv *);
void gfc_free_data (gfc_data *);
@@ -2739,10 +2812,13 @@ gfc_expr *gfc_get_parentheses (gfc_expr *);
/* openmp.c */
struct gfc_omp_saved_state { void *ptrs[2]; int ints[1]; };
void gfc_free_omp_clauses (gfc_omp_clauses *);
+void gfc_free_omp_declare_simd (gfc_omp_declare_simd *);
+void gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *);
void gfc_resolve_omp_directive (gfc_code *, gfc_namespace *);
void gfc_resolve_do_iterator (gfc_code *, gfc_symbol *);
void gfc_resolve_omp_parallel_blocks (gfc_code *, gfc_namespace *);
void gfc_resolve_omp_do_blocks (gfc_code *, gfc_namespace *);
+void gfc_resolve_omp_declare_simd (gfc_namespace *);
void gfc_omp_save_and_clear_state (struct gfc_omp_saved_state *);
void gfc_omp_restore_state (struct gfc_omp_saved_state *);
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 773ec62a51c..463195bdb34 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -482,16 +482,16 @@ At present, the GNU Fortran compiler passes the
NIST Fortran 77 Test Suite}, and produces acceptable results on the
@uref{http://www.netlib.org/lapack/faq.html#1.21, LAPACK Test Suite}.
It also provides respectable performance on
-the @uref{http://www.polyhedron.com/pb05.html, Polyhedron Fortran
+the @uref{http://www.polyhedron.com/fortran-compiler-comparisons/polyhedron-benchmark-suite,
+Polyhedron Fortran
compiler benchmarks} and the
-@uref{http://www.llnl.gov/asci_benchmarks/asci/limited/lfk/README.html,
+@uref{http://www.netlib.org/benchmark/livermore,
Livermore Fortran Kernels test}. It has been used to compile a number of
large real-world programs, including
-@uref{http://mysite.verizon.net/serveall/moene.pdf, the HIRLAM
-weather-forecasting code} and
-@uref{http://www.theochem.uwa.edu.au/tonto/, the Tonto quantum
-chemistry package}; see @url{http://gcc.gnu.org/@/wiki/@/GfortranApps} for an
-extended list.
+@uref{http://hirlam.org/, the HARMONIE and HIRLAM weather forecasting code} and
+@uref{http://physical-chemistry.scb.uwa.edu.au/tonto/wiki/index.php/Main_Page,
+the Tonto quantum chemistry package}; see
+@url{https://gcc.gnu.org/@/wiki/@/GfortranApps} for an extended list.
Among other things, the GNU Fortran compiler is intended as a replacement
for G77. At this point, nearly all programs that could be compiled with
@@ -798,7 +798,7 @@ compile option was used.
GNU Fortran supports several Fortran 2003 features; an incomplete
list can be found below. See also the
-@uref{http://gcc.gnu.org/wiki/Fortran2003, wiki page} about Fortran 2003.
+@uref{https://gcc.gnu.org/wiki/Fortran2003, wiki page} about Fortran 2003.
@itemize
@item Procedure pointers including procedure-pointer components with
@@ -984,7 +984,7 @@ Electrotechnical Commission (IEC). This group is known as
@uref{http://www.nag.co.uk/sc22wg5/, WG5}.
The GNU Fortran compiler supports several of the new features of Fortran 2008;
-the @uref{http://gcc.gnu.org/wiki/Fortran2008Status, wiki} has some information
+the @uref{https://gcc.gnu.org/wiki/Fortran2008Status, wiki} has some information
about the current Fortran 2008 implementation status. In particular, the
following is implemented.
@@ -1087,7 +1087,7 @@ arrays are supported for named constants (@code{PARAMETER}).
GNU Fortran supports some of the new features of the Technical
Specification (TS) 29113 on Further Interoperability of Fortran with C.
-The @uref{http://gcc.gnu.org/wiki/TS29113Status, wiki} has some information
+The @uref{https://gcc.gnu.org/wiki/TS29113Status, wiki} has some information
about the current TS 29113 implementation status. In particular, the
following is implemented.
@@ -1967,7 +1967,7 @@ C
@end smallexample
For details refer to the g77 manual
-@uref{http://gcc.gnu.org/@/onlinedocs/@/gcc-3.4.6/@/g77/@/index.html#Top}.
+@uref{https://gcc.gnu.org/@/onlinedocs/@/gcc-3.4.6/@/g77/@/index.html#Top}.
Also, @code{c_by_val.f} and its partner @code{c_by_val.c} of the
GNU Fortran testsuite are worth a look.
@@ -1987,7 +1987,7 @@ aims at listing these extensions and offering advice on how best make
code that uses them running with the GNU Fortran compiler.
@c More can be found here:
-@c -- http://gcc.gnu.org/onlinedocs/gcc-3.4.6/g77/Missing-Features.html
+@c -- https://gcc.gnu.org/onlinedocs/gcc-3.4.6/g77/Missing-Features.html
@c -- the list of Fortran and libgfortran bugs closed as WONTFIX:
@c http://tinyurl.com/2u4h5y
@@ -3303,7 +3303,7 @@ keep code private on request.
Find bugs and write more test cases! Test cases are especially very
welcome, because it allows us to concentrate on fixing bugs instead of
isolating them. Going through the bugzilla database at
-@url{http://gcc.gnu.org/@/bugzilla/} to reduce testcases posted there and
+@url{https://gcc.gnu.org/@/bugzilla/} to reduce testcases posted there and
add more information (for example, for which version does the testcase
work, for which versions does it fail?) is also very helpful.
diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index 19d46202e08..bf784b5e18f 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -1205,7 +1205,7 @@ add_functions (void)
*z = "z", *ln = "len", *ut = "unit", *han = "handler",
*num = "number", *tm = "time", *nm = "name", *md = "mode",
*vl = "values", *p1 = "path1", *p2 = "path2", *com = "command",
- *ca = "coarray", *sub = "sub";
+ *ca = "coarray", *sub = "sub", *dist = "distance", *failed="failed";
int di, dr, dd, dl, dc, dz, ii;
@@ -2477,9 +2477,11 @@ add_functions (void)
make_generic ("null", GFC_ISYM_NULL, GFC_STD_F95);
- add_sym_0 ("num_images", GFC_ISYM_NUM_IMAGES, CLASS_INQUIRY, ACTUAL_NO,
+ add_sym_2 ("num_images", GFC_ISYM_NUM_IMAGES, CLASS_INQUIRY, ACTUAL_NO,
BT_INTEGER, di, GFC_STD_F2008,
- NULL, gfc_simplify_num_images, NULL);
+ gfc_check_num_images, gfc_simplify_num_images, NULL,
+ dist, BT_INTEGER, di, OPTIONAL,
+ failed, BT_LOGICAL, dl, OPTIONAL);
add_sym_3 ("pack", GFC_ISYM_PACK, CLASS_TRANSFORMATIONAL, ACTUAL_NO, BT_REAL, dr, GFC_STD_F95,
gfc_check_pack, gfc_simplify_pack, gfc_resolve_pack,
@@ -2756,7 +2758,7 @@ add_functions (void)
make_generic ("size", GFC_ISYM_SIZE, GFC_STD_F95);
/* Obtain the stride for a given dimensions; to be used only internally.
- "make_from_module" makes inaccessible for external users. */
+ "make_from_module" makes it inaccessible for external users. */
add_sym_2 (GFC_PREFIX ("stride"), GFC_ISYM_STRIDE, CLASS_INQUIRY, ACTUAL_NO,
BT_INTEGER, gfc_index_integer_kind, GFC_STD_GNU,
NULL, NULL, gfc_resolve_stride,
@@ -2892,9 +2894,10 @@ add_functions (void)
make_generic ("tanh", GFC_ISYM_TANH, GFC_STD_F77);
- add_sym_2 ("this_image", GFC_ISYM_THIS_IMAGE, CLASS_INQUIRY, ACTUAL_NO, BT_INTEGER, di, GFC_STD_F2008,
+ add_sym_3 ("this_image", GFC_ISYM_THIS_IMAGE, CLASS_INQUIRY, ACTUAL_NO, BT_INTEGER, di, GFC_STD_F2008,
gfc_check_this_image, gfc_simplify_this_image, gfc_resolve_this_image,
- ca, BT_REAL, dr, OPTIONAL, dm, BT_INTEGER, ii, OPTIONAL);
+ ca, BT_REAL, dr, OPTIONAL, dm, BT_INTEGER, ii, OPTIONAL,
+ dist, BT_INTEGER, di, OPTIONAL);
add_sym_0 ("time", GFC_ISYM_TIME, CLASS_IMPURE, ACTUAL_NO, BT_INTEGER,
di, GFC_STD_GNU, NULL, NULL, gfc_resolve_time);
@@ -2994,6 +2997,13 @@ add_functions (void)
x, BT_UNKNOWN, 0, REQUIRED);
make_generic ("loc", GFC_ISYM_LOC, GFC_STD_GNU);
+
+ /* The following function is internally used for coarray libray functions.
+ "make_from_module" makes it inaccessible for external users. */
+ add_sym_1 (GFC_PREFIX ("caf_get"), GFC_ISYM_CAF_GET, CLASS_IMPURE, ACTUAL_NO,
+ BT_REAL, dr, GFC_STD_GNU, NULL, NULL, NULL,
+ x, BT_REAL, dr, REQUIRED);
+ make_from_module();
}
@@ -3004,7 +3014,7 @@ add_subroutines (void)
{
/* Argument names as in the standard (to be used as argument keywords). */
const char
- *h = "harvest", *dt = "date", *vl = "values", *pt = "put",
+ *a = "a", *h = "harvest", *dt = "date", *vl = "values", *pt = "put",
*c = "count", *tm = "time", *tp = "topos", *gt = "get",
*t = "to", *zn = "zone", *fp = "frompos", *cm = "count_max",
*f = "from", *sz = "size", *ln = "len", *cr = "count_rate",
@@ -3013,7 +3023,8 @@ add_subroutines (void)
*trim_name = "trim_name", *ut = "unit", *han = "handler",
*sec = "seconds", *res = "result", *of = "offset", *md = "mode",
*whence = "whence", *pos = "pos", *ptr = "ptr", *p1 = "path1",
- *p2 = "path2", *msk = "mask", *old = "old";
+ *p2 = "path2", *msk = "mask", *old = "old", *result_image = "result_image",
+ *stat = "stat", *errmsg = "errmsg";
int di, dr, dc, dl, ii;
@@ -3209,6 +3220,40 @@ add_subroutines (void)
"fptr", BT_UNKNOWN, 0, REQUIRED, INTENT_OUT);
make_from_module();
+ /* Coarray collectives. */
+ add_sym_4s ("co_max", GFC_ISYM_CO_MAX, CLASS_IMPURE,
+ BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+ gfc_check_co_minmax, NULL, NULL,
+ a, BT_REAL, dr, REQUIRED, INTENT_INOUT,
+ result_image, BT_INTEGER, di, OPTIONAL, INTENT_IN,
+ stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+ errmsg, BT_CHARACTER, dc, OPTIONAL, INTENT_OUT);
+
+ add_sym_4s ("co_min", GFC_ISYM_CO_MIN, CLASS_IMPURE,
+ BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+ gfc_check_co_minmax, NULL, NULL,
+ a, BT_REAL, dr, REQUIRED, INTENT_INOUT,
+ result_image, BT_INTEGER, di, OPTIONAL, INTENT_IN,
+ stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+ errmsg, BT_CHARACTER, dc, OPTIONAL, INTENT_OUT);
+
+ add_sym_4s ("co_sum", GFC_ISYM_CO_SUM, CLASS_IMPURE,
+ BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+ gfc_check_co_sum, NULL, NULL,
+ a, BT_REAL, dr, REQUIRED, INTENT_INOUT,
+ result_image, BT_INTEGER, di, OPTIONAL, INTENT_IN,
+ stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+ errmsg, BT_CHARACTER, dc, OPTIONAL, INTENT_OUT);
+
+ /* The following subroutine is internally used for coarray libray functions.
+ "make_from_module" makes it inaccessible for external users. */
+ add_sym_2s (GFC_PREFIX ("caf_send"), GFC_ISYM_CAF_SEND, CLASS_IMPURE,
+ BT_UNKNOWN, 0, GFC_STD_GNU, NULL, NULL, NULL,
+ "x", BT_REAL, dr, REQUIRED, INTENT_OUT,
+ "y", BT_REAL, dr, REQUIRED, INTENT_IN);
+ make_from_module();
+
+
/* More G77 compatibility garbage. */
add_sym_3s ("alarm", GFC_ISYM_ALARM, CLASS_IMPURE, BT_UNKNOWN, 0, GFC_STD_GNU,
gfc_check_alarm_sub, NULL, gfc_resolve_alarm_sub,
@@ -4160,7 +4205,7 @@ gfc_check_intrinsic_standard (const gfc_intrinsic_sym* isym,
break;
case GFC_STD_F2008_TS:
- symstd_msg = "new in TS 29113";
+ symstd_msg = "new in TS 29113/TS 18508";
break;
case GFC_STD_GNU:
diff --git a/gcc/fortran/intrinsic.h b/gcc/fortran/intrinsic.h
index d7f795400cd..05cd1464182 100644
--- a/gcc/fortran/intrinsic.h
+++ b/gcc/fortran/intrinsic.h
@@ -49,6 +49,8 @@ bool gfc_check_chdir (gfc_expr *);
bool gfc_check_chmod (gfc_expr *, gfc_expr *);
bool gfc_check_cmplx (gfc_expr *, gfc_expr *, gfc_expr *);
bool gfc_check_complex (gfc_expr *, gfc_expr *);
+bool gfc_check_co_minmax (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
+bool gfc_check_co_sum (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
bool gfc_check_count (gfc_expr *, gfc_expr *, gfc_expr *);
bool gfc_check_cshift (gfc_expr *, gfc_expr *, gfc_expr *);
bool gfc_check_ctime (gfc_expr *);
@@ -115,6 +117,7 @@ bool gfc_check_nearest (gfc_expr *, gfc_expr *);
bool gfc_check_new_line (gfc_expr *);
bool gfc_check_norm2 (gfc_expr *, gfc_expr *);
bool gfc_check_null (gfc_expr *);
+bool gfc_check_num_images (gfc_expr *, gfc_expr *);
bool gfc_check_pack (gfc_expr *, gfc_expr *, gfc_expr *);
bool gfc_check_parity (gfc_expr *, gfc_expr *);
bool gfc_check_precision (gfc_expr *);
@@ -210,7 +213,7 @@ bool gfc_check_signal_sub (gfc_expr *, gfc_expr *, gfc_expr *);
bool gfc_check_sleep_sub (gfc_expr *);
bool gfc_check_stat_sub (gfc_expr *, gfc_expr *, gfc_expr *);
bool gfc_check_system_sub (gfc_expr *, gfc_expr *);
-bool gfc_check_this_image (gfc_expr *, gfc_expr *);
+bool gfc_check_this_image (gfc_expr *, gfc_expr *, gfc_expr *);
bool gfc_check_ttynam_sub (gfc_expr *, gfc_expr *);
bool gfc_check_umask_sub (gfc_expr *, gfc_expr *);
bool gfc_check_unlink_sub (gfc_expr *, gfc_expr *);
@@ -341,7 +344,7 @@ gfc_expr *gfc_simplify_new_line (gfc_expr *);
gfc_expr *gfc_simplify_nint (gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_norm2 (gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_null (gfc_expr *);
-gfc_expr *gfc_simplify_num_images (void);
+gfc_expr *gfc_simplify_num_images (gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_idnint (gfc_expr *);
gfc_expr *gfc_simplify_not (gfc_expr *);
gfc_expr *gfc_simplify_or (gfc_expr *, gfc_expr *);
@@ -385,7 +388,7 @@ gfc_expr *gfc_simplify_sqrt (gfc_expr *);
gfc_expr *gfc_simplify_sum (gfc_expr *, gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_tan (gfc_expr *);
gfc_expr *gfc_simplify_tanh (gfc_expr *);
-gfc_expr *gfc_simplify_this_image (gfc_expr *, gfc_expr *);
+gfc_expr *gfc_simplify_this_image (gfc_expr *, gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_tiny (gfc_expr *);
gfc_expr *gfc_simplify_trailz (gfc_expr *);
gfc_expr *gfc_simplify_transfer (gfc_expr *, gfc_expr *, gfc_expr *);
@@ -566,7 +569,7 @@ void gfc_resolve_symlnk (gfc_expr *, gfc_expr *, gfc_expr *);
void gfc_resolve_system (gfc_expr *, gfc_expr *);
void gfc_resolve_tan (gfc_expr *, gfc_expr *);
void gfc_resolve_tanh (gfc_expr *, gfc_expr *);
-void gfc_resolve_this_image (gfc_expr *, gfc_expr *, gfc_expr *);
+void gfc_resolve_this_image (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
void gfc_resolve_time (gfc_expr *);
void gfc_resolve_time8 (gfc_expr *);
void gfc_resolve_transfer (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index 926ffe954ed..8402a1fc0bf 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -86,6 +86,9 @@ Some basic guidelines for editing this document:
* @code{CHDIR}: CHDIR, Change working directory
* @code{CHMOD}: CHMOD, Change access permissions of files
* @code{CMPLX}: CMPLX, Complex conversion function
+* @code{CO_MAX}: CO_MAX, Maximal value on the current set of images
+* @code{CO_MIN}: CO_MIN, Minimal value on the current set of images
+* @code{CO_SUM}: CO_SUM, Sum of values on the current set of images
* @code{COMMAND_ARGUMENT_COUNT}: COMMAND_ARGUMENT_COUNT, Get number of command line arguments
* @code{COMPILER_OPTIONS}: COMPILER_OPTIONS, Options passed to the compiler
* @code{COMPILER_VERSION}: COMPILER_VERSION, Compiler version string
@@ -2811,6 +2814,168 @@ end program test_cmplx
+@node CO_MAX
+@section @code{CO_MAX} --- Maximal value on the current set of images
+@fnindex CO_MAX
+@cindex Collectives, maximal value
+
+@table @asis
+@item @emph{Description}:
+@code{CO_MAX} determines element-wise the maximal value of @var{A} on all
+images of the current team. If @var{RESULT_IMAGE} is present, the maximum
+values are returned on in @var{A} on the specified image only and the value
+of @var{A} on the other images become undefined. If @var{RESULT_IMAGE} is
+not present, the value is returned on all images. If the execution was
+successful and @var{STAT} is present, it is assigned the value zero. If the
+execution failed, @var{STAT} gets assigned a nonzero value and, if present,
+@var{ERRMSG} gets assigned a value describing the occurred error.
+
+@item @emph{Standard}:
+Technical Specification (TS) 18508 or later
+
+@item @emph{Class}:
+Collective subroutine
+
+@item @emph{Syntax}:
+@code{CALL CO_MAX(A [, RESULT_IMAGE, STAT, ERRMSG])}
+
+@item @emph{Arguments}:
+@multitable @columnfractions .15 .70
+@item @var{A} @tab shall be an integer, real or character variable,
+which has the same type and type parameters on all images of the team.
+@item @var{RESULT_IMAGE} @tab (optional) a scalar integer expression; if
+present, it shall have the same the same value on all images and refer to an
+image of the current team.
+@item @var{STAT} @tab (optional) a scalar integer variable
+@item @var{ERRMSG} @tab (optional) a scalar character variable
+@end multitable
+
+@item @emph{Example}:
+@smallexample
+program test
+ integer :: val
+ val = this_image ()
+ call co_max (val, result_image=1)
+ if (this_image() == 1) then
+ write(*,*) "Maximal value", val ! prints num_images()
+ end if
+end program test
+@end smallexample
+
+@item @emph{See also}:
+@ref{CO_MIN}, @ref{CO_SUM}
+@end table
+
+
+
+@node CO_MIN
+@section @code{CO_MIN} --- Minimal value on the current set of images
+@fnindex CO_MIN
+@cindex Collectives, minimal value
+
+@table @asis
+@item @emph{Description}:
+@code{CO_MIN} determines element-wise the minimal value of @var{A} on all
+images of the current team. If @var{RESULT_IMAGE} is present, the minimal
+values are returned on in @var{A} on the specified image only and the value
+of @var{A} on the other images become undefined. If @var{RESULT_IMAGE} is
+not present, the value is returned on all images. If the execution was
+successful and @var{STAT} is present, it is assigned the value zero. If the
+execution failed, @var{STAT} gets assigned a nonzero value and, if present,
+@var{ERRMSG} gets assigned a value describing the occurred error.
+
+@item @emph{Standard}:
+Technical Specification (TS) 18508 or later
+
+@item @emph{Class}:
+Collective subroutine
+
+@item @emph{Syntax}:
+@code{CALL CO_MIN(A [, RESULT_IMAGE, STAT, ERRMSG])}
+
+@item @emph{Arguments}:
+@multitable @columnfractions .15 .70
+@item @var{A} @tab shall be an integer, real or character variable,
+which has the same type and type parameters on all images of the team.
+@item @var{RESULT_IMAGE} @tab (optional) a scalar integer expression; if
+present, it shall have the same the same value on all images and refer to an
+image of the current team.
+@item @var{STAT} @tab (optional) a scalar integer variable
+@item @var{ERRMSG} @tab (optional) a scalar character variable
+@end multitable
+
+@item @emph{Example}:
+@smallexample
+program test
+ integer :: val
+ val = this_image ()
+ call co_min (val, result_image=1)
+ if (this_image() == 1) then
+ write(*,*) "Minimal value", val ! prints 1
+ end if
+end program test
+@end smallexample
+
+@item @emph{See also}:
+@ref{CO_MAX}, @ref{CO_SUM}
+@end table
+
+
+
+@node CO_SUM
+@section @code{CO_SUM} --- Sum of values on the current set of images
+@fnindex CO_SUM
+@cindex Collectives, sum of values
+
+@table @asis
+@item @emph{Description}:
+@code{CO_SUM} sums up the values of each element of @var{A} on all
+images of the current team. If @var{RESULT_IMAGE} is present, the summed-up
+values are returned on in @var{A} on the specified image only and the value
+of @var{A} on the other images become undefined. If @var{RESULT_IMAGE} is
+not present, the value is returned on all images. If the execution was
+successful and @var{STAT} is present, it is assigned the value zero. If the
+execution failed, @var{STAT} gets assigned a nonzero value and, if present,
+@var{ERRMSG} gets assigned a value describing the occurred error.
+
+@item @emph{Standard}:
+Technical Specification (TS) 18508 or later
+
+@item @emph{Class}:
+Collective subroutine
+
+@item @emph{Syntax}:
+@code{CALL CO_MIN(A [, RESULT_IMAGE, STAT, ERRMSG])}
+
+@item @emph{Arguments}:
+@multitable @columnfractions .15 .70
+@item @var{A} @tab shall be an integer, real or complex variable,
+which has the same type and type parameters on all images of the team.
+@item @var{RESULT_IMAGE} @tab (optional) a scalar integer expression; if
+present, it shall have the same the same value on all images and refer to an
+image of the current team.
+@item @var{STAT} @tab (optional) a scalar integer variable
+@item @var{ERRMSG} @tab (optional) a scalar character variable
+@end multitable
+
+@item @emph{Example}:
+@smallexample
+program test
+ integer :: val
+ val = this_image ()
+ call co_sum (val, result_image=1)
+ if (this_image() == 1) then
+ write(*,*) "The sum is ", val ! prints (n**2 + n)/2, with n = num_images()
+ end if
+end program test
+@end smallexample
+
+@item @emph{See also}:
+@ref{CO_MAX}, @ref{CO_MIN}
+@end table
+
+
+
@node COMMAND_ARGUMENT_COUNT
@section @code{COMMAND_ARGUMENT_COUNT} --- Get number of command line arguments
@fnindex COMMAND_ARGUMENT_COUNT
@@ -3343,10 +3508,8 @@ end program test_cshift
@table @asis
@item @emph{Description}:
@code{CTIME} converts a system time value, such as returned by
-@code{TIME8}, to a string. Unless the application has called
-@code{setlocale}, the output will be in the default locale, of length
-24 and of the form @samp{Sat Aug 19 18:13:14 1995}. In other locales,
-a longer string may result.
+@code{TIME8}, to a string. The output will be of the form @samp{Sat
+Aug 19 18:13:14 1995}.
This intrinsic is provided in both subroutine and function forms; however,
only one form can be used in any given program unit.
@@ -9511,18 +9674,32 @@ REAL, POINTER, DIMENSION(:) :: VEC => NULL ()
Returns the number of images.
@item @emph{Standard}:
-Fortran 2008 and later
+Fortran 2008 and later. With @var{DISTANCE} or @var{FAILED} argument,
+Technical Specification (TS) 18508 or later
+
@item @emph{Class}:
Transformational function
@item @emph{Syntax}:
-@code{RESULT = NUM_IMAGES()}
+@code{RESULT = NUM_IMAGES(DISTANCE, FAILED)}
-@item @emph{Arguments}: None.
+@item @emph{Arguments}:
+@multitable @columnfractions .15 .70
+@item @var{DISTANCE} @tab (optional, intent(in)) Nonnegative scalar integer
+@item @var{FAILED} @tab (optional, intent(in)) Scalar logical expression
+@end multitable
@item @emph{Return value}:
-Scalar default-kind integer.
+Scalar default-kind integer. If @var{DISTANCE} is not present or has value 0,
+the number of images in the current team is returned. For values smaller or
+equal distance to the initial team, it returns the number of images index
+on the ancestor team which has a distance of @var{DISTANCE} from the invoking
+team. If @var{DISTANCE} is larger than the distance to the initial team, the
+number of images of the initial team is returned. If @var{FAILED} is not present
+the total number of images is returned; if it has the value @code{.TRUE.},
+the number of failed images is returned, otherwise, the number of images which
+do have not the failed status.
@item @emph{Example}:
@smallexample
@@ -12257,7 +12434,8 @@ end program test_tanh
Returns the cosubscript for this image.
@item @emph{Standard}:
-Fortran 2008 and later
+Fortran 2008 and later. With @var{DISTANCE} argument,
+Technical Specification (TS) 18508 or later
@item @emph{Class}:
Transformational function
@@ -12265,11 +12443,14 @@ Transformational function
@item @emph{Syntax}:
@multitable @columnfractions .80
@item @code{RESULT = THIS_IMAGE()}
+@item @code{RESULT = THIS_IMAGE(DISTANCE)}
@item @code{RESULT = THIS_IMAGE(COARRAY [, DIM])}
@end multitable
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
+@item @var{DISTANCE} @tab (optional, intent(in)) Nonnegative scalar integer
+(not permitted together with @var{COARRAY}).
@item @var{COARRAY} @tab Coarray of any type (optional; if @var{DIM}
present, required).
@item @var{DIM} @tab default integer scalar (optional). If present,
@@ -12278,12 +12459,17 @@ present, required).
@item @emph{Return value}:
-Default integer. If @var{COARRAY} is not present, it is scalar and its value
-is the index of the invoking image. Otherwise, if @var{DIM} is not present,
-a rank-1 array with corank elements is returned, containing the cosubscripts
-for @var{COARRAY} specifying the invoking image. If @var{DIM} is present,
-a scalar is returned, with the value of the @var{DIM} element of
-@code{THIS_IMAGE(COARRAY)}.
+Default integer. If @var{COARRAY} is not present, it is scalar; if
+@var{DISTANCE} is not present or has value 0, its value is the image index on
+the invoking image for the current team, for values smaller or equal
+distance to the initial team, it returns the image index on the ancestor team
+which has a distance of @var{DISTANCE} from the invoking team. If
+@var{DISTANCE} is larger than the distance to the initial team, the image
+index of the initial team is returned. Otherwise when the @var{COARRAY} is
+present, if @var{DIM} is not present, a rank-1 array with corank elements is
+returned, containing the cosubscripts for @var{COARRAY} specifying the invoking
+image. If @var{DIM} is present, a scalar is returned, with the value of
+the @var{DIM} element of @code{THIS_IMAGE(COARRAY)}.
@item @emph{Example}:
@smallexample
@@ -12296,6 +12482,10 @@ IF (THIS_IMAGE() == 1) THEN
WRITE(*,'(2(a,i0))') 'value[', i, '] is ', value[i]
END DO
END IF
+
+! Check whether the current image is the initial image
+IF (THIS_IMAGE(HUGE(1)) /= THIS_IMAGE())
+ error stop "something is rotten here"
@end smallexample
@item @emph{See also}:
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index b92abfc2f9f..4c7d4a3bef0 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -402,7 +402,7 @@ language standard, and warnings are given for the Fortran 77 features
that are permitted but obsolescent in later standards. @samp{-std=f2008ts}
allows the Fortran 2008 standard including the additions of the
Technical Specification (TS) 29113 on Further Interoperability of Fortran
-with C.
+with C and TS 18508 on Additional Parallel Features in Fortran.
@end table
diff --git a/gcc/fortran/iresolve.c b/gcc/fortran/iresolve.c
index 630d725e173..d029f720a8d 100644
--- a/gcc/fortran/iresolve.c
+++ b/gcc/fortran/iresolve.c
@@ -2590,10 +2590,11 @@ gfc_resolve_image_index (gfc_expr *f, gfc_expr *array ATTRIBUTE_UNUSED,
void
-gfc_resolve_this_image (gfc_expr *f, gfc_expr *array, gfc_expr *dim)
+gfc_resolve_this_image (gfc_expr *f, gfc_expr *array, gfc_expr *dim,
+ gfc_expr *distance ATTRIBUTE_UNUSED)
{
static char this_image[] = "__this_image";
- if (array)
+ if (array && gfc_is_coarray (array))
resolve_bound (f, array, dim, NULL, "__this_image", true);
else
{
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index 4c4609401a0..41915b4118e 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -2595,7 +2595,10 @@ match_exit_cycle (gfc_statement st, gfc_exec_op op)
&& o != NULL
&& o->state == COMP_OMP_STRUCTURED_BLOCK
&& (o->head->op == EXEC_OMP_DO
- || o->head->op == EXEC_OMP_PARALLEL_DO))
+ || o->head->op == EXEC_OMP_PARALLEL_DO
+ || o->head->op == EXEC_OMP_SIMD
+ || o->head->op == EXEC_OMP_DO_SIMD
+ || o->head->op == EXEC_OMP_PARALLEL_DO_SIMD))
{
int collapse = 1;
gcc_assert (o->head->next != NULL
@@ -4564,6 +4567,22 @@ gfc_free_namelist (gfc_namelist *name)
}
+/* Free an OpenMP namelist structure. */
+
+void
+gfc_free_omp_namelist (gfc_omp_namelist *name)
+{
+ gfc_omp_namelist *n;
+
+ for (; name; name = n)
+ {
+ gfc_free_expr (name->expr);
+ n = name->next;
+ free (name);
+ }
+}
+
+
/* Match a NAMELIST statement. */
match
diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h
index 385e84020eb..51c6b728ab4 100644
--- a/gcc/fortran/match.h
+++ b/gcc/fortran/match.h
@@ -126,18 +126,25 @@ gfc_common_head *gfc_get_common (const char *, int);
match gfc_match_omp_eos (void);
match gfc_match_omp_atomic (void);
match gfc_match_omp_barrier (void);
+match gfc_match_omp_cancel (void);
+match gfc_match_omp_cancellation_point (void);
match gfc_match_omp_critical (void);
+match gfc_match_omp_declare_simd (void);
match gfc_match_omp_do (void);
+match gfc_match_omp_do_simd (void);
match gfc_match_omp_flush (void);
match gfc_match_omp_master (void);
match gfc_match_omp_ordered (void);
match gfc_match_omp_parallel (void);
match gfc_match_omp_parallel_do (void);
+match gfc_match_omp_parallel_do_simd (void);
match gfc_match_omp_parallel_sections (void);
match gfc_match_omp_parallel_workshare (void);
match gfc_match_omp_sections (void);
+match gfc_match_omp_simd (void);
match gfc_match_omp_single (void);
match gfc_match_omp_task (void);
+match gfc_match_omp_taskgroup (void);
match gfc_match_omp_taskwait (void);
match gfc_match_omp_taskyield (void);
match gfc_match_omp_threadprivate (void);
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 52fdebe340c..8b374a2e4b0 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -3790,6 +3790,111 @@ mio_full_f2k_derived (gfc_symbol *sym)
mio_rparen ();
}
+static const mstring omp_declare_simd_clauses[] =
+{
+ minit ("INBRANCH", 0),
+ minit ("NOTINBRANCH", 1),
+ minit ("SIMDLEN", 2),
+ minit ("UNIFORM", 3),
+ minit ("LINEAR", 4),
+ minit ("ALIGNED", 5),
+ minit (NULL, -1)
+};
+
+/* Handle !$omp declare simd. */
+
+static void
+mio_omp_declare_simd (gfc_namespace *ns, gfc_omp_declare_simd **odsp)
+{
+ if (iomode == IO_OUTPUT)
+ {
+ if (*odsp == NULL)
+ return;
+ }
+ else if (peek_atom () != ATOM_LPAREN)
+ return;
+
+ gfc_omp_declare_simd *ods = *odsp;
+
+ mio_lparen ();
+ if (iomode == IO_OUTPUT)
+ {
+ write_atom (ATOM_NAME, "OMP_DECLARE_SIMD");
+ if (ods->clauses)
+ {
+ gfc_omp_namelist *n;
+
+ if (ods->clauses->inbranch)
+ mio_name (0, omp_declare_simd_clauses);
+ if (ods->clauses->notinbranch)
+ mio_name (1, omp_declare_simd_clauses);
+ if (ods->clauses->simdlen_expr)
+ {
+ mio_name (2, omp_declare_simd_clauses);
+ mio_expr (&ods->clauses->simdlen_expr);
+ }
+ for (n = ods->clauses->lists[OMP_LIST_UNIFORM]; n; n = n->next)
+ {
+ mio_name (3, omp_declare_simd_clauses);
+ mio_symbol_ref (&n->sym);
+ }
+ for (n = ods->clauses->lists[OMP_LIST_LINEAR]; n; n = n->next)
+ {
+ mio_name (4, omp_declare_simd_clauses);
+ mio_symbol_ref (&n->sym);
+ mio_expr (&n->expr);
+ }
+ for (n = ods->clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
+ {
+ mio_name (5, omp_declare_simd_clauses);
+ mio_symbol_ref (&n->sym);
+ mio_expr (&n->expr);
+ }
+ }
+ }
+ else
+ {
+ gfc_omp_namelist **ptrs[3] = { NULL, NULL, NULL };
+
+ require_atom (ATOM_NAME);
+ *odsp = ods = gfc_get_omp_declare_simd ();
+ ods->where = gfc_current_locus;
+ ods->proc_name = ns->proc_name;
+ if (peek_atom () == ATOM_NAME)
+ {
+ ods->clauses = gfc_get_omp_clauses ();
+ ptrs[0] = &ods->clauses->lists[OMP_LIST_UNIFORM];
+ ptrs[1] = &ods->clauses->lists[OMP_LIST_LINEAR];
+ ptrs[2] = &ods->clauses->lists[OMP_LIST_ALIGNED];
+ }
+ while (peek_atom () == ATOM_NAME)
+ {
+ gfc_omp_namelist *n;
+ int t = mio_name (0, omp_declare_simd_clauses);
+
+ switch (t)
+ {
+ case 0: ods->clauses->inbranch = true; break;
+ case 1: ods->clauses->notinbranch = true; break;
+ case 2: mio_expr (&ods->clauses->simdlen_expr); break;
+ case 3:
+ case 4:
+ case 5:
+ *ptrs[t - 3] = n = gfc_get_omp_namelist ();
+ ptrs[t - 3] = &n->next;
+ mio_symbol_ref (&n->sym);
+ if (t != 3)
+ mio_expr (&n->expr);
+ break;
+ }
+ }
+ }
+
+ mio_omp_declare_simd (ns, &ods->next);
+
+ mio_rparen ();
+}
+
/* Unlike most other routines, the address of the symbol node is already
fixed on input and the name/module has already been filled in.
@@ -3864,6 +3969,11 @@ mio_symbol (gfc_symbol *sym)
if (sym->attr.flavor == FL_DERIVED)
mio_integer (&(sym->hash_value));
+ if (sym->formal_ns
+ && sym->formal_ns->proc_name == sym
+ && sym->formal_ns->entries == NULL)
+ mio_omp_declare_simd (sym->formal_ns, &sym->formal_ns->omp_declare_simd);
+
mio_rparen ();
}
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index dff3ab1ad91..a578ad90288 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -69,19 +69,47 @@ gfc_free_omp_clauses (gfc_omp_clauses *c)
gfc_free_expr (c->final_expr);
gfc_free_expr (c->num_threads);
gfc_free_expr (c->chunk_size);
+ gfc_free_expr (c->safelen_expr);
+ gfc_free_expr (c->simdlen_expr);
for (i = 0; i < OMP_LIST_NUM; i++)
- gfc_free_namelist (c->lists[i]);
+ gfc_free_omp_namelist (c->lists[i]);
free (c);
}
+/* Free an !$omp declare simd construct list. */
+
+void
+gfc_free_omp_declare_simd (gfc_omp_declare_simd *ods)
+{
+ if (ods)
+ {
+ gfc_free_omp_clauses (ods->clauses);
+ free (ods);
+ }
+}
+
+void
+gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *list)
+{
+ while (list)
+ {
+ gfc_omp_declare_simd *current = list;
+ list = list->next;
+ gfc_free_omp_declare_simd (current);
+ }
+}
+
+
/* Match a variable/common block list and construct a namelist from it. */
static match
-gfc_match_omp_variable_list (const char *str, gfc_namelist **list,
- bool allow_common)
+gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list,
+ bool allow_common, bool *end_colon = NULL,
+ gfc_omp_namelist ***headp = NULL,
+ bool allow_sections = false)
{
- gfc_namelist *head, *tail, *p;
- locus old_loc;
+ gfc_omp_namelist *head, *tail, *p;
+ locus old_loc, cur_loc;
char n[GFC_MAX_SYMBOL_LEN+1];
gfc_symbol *sym;
match m;
@@ -97,12 +125,29 @@ gfc_match_omp_variable_list (const char *str, gfc_namelist **list,
for (;;)
{
+ cur_loc = gfc_current_locus;
m = gfc_match_symbol (&sym, 1);
switch (m)
{
case MATCH_YES:
+ gfc_expr *expr;
+ expr = NULL;
+ if (allow_sections && gfc_peek_ascii_char () == '(')
+ {
+ gfc_current_locus = cur_loc;
+ m = gfc_match_variable (&expr, 0);
+ switch (m)
+ {
+ case MATCH_ERROR:
+ goto cleanup;
+ case MATCH_NO:
+ goto syntax;
+ default:
+ break;
+ }
+ }
gfc_set_sym_referenced (sym);
- p = gfc_get_namelist ();
+ p = gfc_get_omp_namelist ();
if (head == NULL)
head = tail = p;
else
@@ -111,6 +156,7 @@ gfc_match_omp_variable_list (const char *str, gfc_namelist **list,
tail = tail->next;
}
tail->sym = sym;
+ tail->expr = expr;
goto next_item;
case MATCH_NO:
break;
@@ -136,7 +182,7 @@ gfc_match_omp_variable_list (const char *str, gfc_namelist **list,
for (sym = st->n.common->head; sym; sym = sym->common_next)
{
gfc_set_sym_referenced (sym);
- p = gfc_get_namelist ();
+ p = gfc_get_omp_namelist ();
if (head == NULL)
head = tail = p;
else
@@ -148,6 +194,11 @@ gfc_match_omp_variable_list (const char *str, gfc_namelist **list,
}
next_item:
+ if (end_colon && gfc_match_char (':') == MATCH_YES)
+ {
+ *end_colon = true;
+ break;
+ }
if (gfc_match_char (')') == MATCH_YES)
break;
if (gfc_match_char (',') != MATCH_YES)
@@ -158,13 +209,15 @@ gfc_match_omp_variable_list (const char *str, gfc_namelist **list,
list = &(*list)->next;
*list = head;
+ if (headp)
+ *headp = list;
return MATCH_YES;
syntax:
gfc_error ("Syntax error in OpenMP variable list at %C");
cleanup:
- gfc_free_namelist (head);
+ gfc_free_omp_namelist (head);
gfc_current_locus = old_loc;
return MATCH_ERROR;
}
@@ -185,16 +238,25 @@ cleanup:
#define OMP_CLAUSE_UNTIED (1 << 13)
#define OMP_CLAUSE_FINAL (1 << 14)
#define OMP_CLAUSE_MERGEABLE (1 << 15)
+#define OMP_CLAUSE_ALIGNED (1 << 16)
+#define OMP_CLAUSE_DEPEND (1 << 17)
+#define OMP_CLAUSE_INBRANCH (1 << 18)
+#define OMP_CLAUSE_LINEAR (1 << 19)
+#define OMP_CLAUSE_NOTINBRANCH (1 << 20)
+#define OMP_CLAUSE_PROC_BIND (1 << 21)
+#define OMP_CLAUSE_SAFELEN (1 << 22)
+#define OMP_CLAUSE_SIMDLEN (1 << 23)
+#define OMP_CLAUSE_UNIFORM (1 << 24)
/* Match OpenMP directive clauses. MASK is a bitmask of
clauses that are allowed for a particular directive. */
static match
-gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask)
+gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask, bool first = true,
+ bool needs_space = true)
{
gfc_omp_clauses *c = gfc_get_omp_clauses ();
locus old_loc;
- bool needs_space = true, first = true;
*cp = NULL;
while (1)
@@ -419,6 +481,115 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask)
continue;
}
}
+ if ((mask & OMP_CLAUSE_INBRANCH) && !c->inbranch
+ && gfc_match ("inbranch") == MATCH_YES)
+ {
+ c->inbranch = needs_space = true;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_NOTINBRANCH) && !c->notinbranch
+ && gfc_match ("notinbranch") == MATCH_YES)
+ {
+ c->notinbranch = needs_space = true;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_PROC_BIND)
+ && c->proc_bind == OMP_PROC_BIND_UNKNOWN)
+ {
+ if (gfc_match ("proc_bind ( master )") == MATCH_YES)
+ c->proc_bind = OMP_PROC_BIND_MASTER;
+ else if (gfc_match ("proc_bind ( spread )") == MATCH_YES)
+ c->proc_bind = OMP_PROC_BIND_SPREAD;
+ else if (gfc_match ("proc_bind ( close )") == MATCH_YES)
+ c->proc_bind = OMP_PROC_BIND_CLOSE;
+ if (c->proc_bind != OMP_PROC_BIND_UNKNOWN)
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_SAFELEN) && c->safelen_expr == NULL
+ && gfc_match ("safelen ( %e )", &c->safelen_expr) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_SIMDLEN) && c->simdlen_expr == NULL
+ && gfc_match ("simdlen ( %e )", &c->simdlen_expr) == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_UNIFORM)
+ && gfc_match_omp_variable_list ("uniform (",
+ &c->lists[OMP_LIST_UNIFORM], false)
+ == MATCH_YES)
+ continue;
+ bool end_colon = false;
+ gfc_omp_namelist **head = NULL;
+ old_loc = gfc_current_locus;
+ if ((mask & OMP_CLAUSE_ALIGNED)
+ && gfc_match_omp_variable_list ("aligned (",
+ &c->lists[OMP_LIST_ALIGNED], false,
+ &end_colon, &head)
+ == MATCH_YES)
+ {
+ gfc_expr *alignment = NULL;
+ gfc_omp_namelist *n;
+
+ if (end_colon
+ && gfc_match (" %e )", &alignment) != MATCH_YES)
+ {
+ gfc_free_omp_namelist (*head);
+ gfc_current_locus = old_loc;
+ *head = NULL;
+ break;
+ }
+ for (n = *head; n; n = n->next)
+ if (n->next && alignment)
+ n->expr = gfc_copy_expr (alignment);
+ else
+ n->expr = alignment;
+ continue;
+ }
+ end_colon = false;
+ head = NULL;
+ old_loc = gfc_current_locus;
+ if ((mask & OMP_CLAUSE_LINEAR)
+ && gfc_match_omp_variable_list ("linear (",
+ &c->lists[OMP_LIST_LINEAR], false,
+ &end_colon, &head)
+ == MATCH_YES)
+ {
+ gfc_expr *step = NULL;
+
+ if (end_colon
+ && gfc_match (" %e )", &step) != MATCH_YES)
+ {
+ gfc_free_omp_namelist (*head);
+ gfc_current_locus = old_loc;
+ *head = NULL;
+ break;
+ }
+ else if (!end_colon)
+ {
+ step = gfc_get_constant_expr (BT_INTEGER,
+ gfc_default_integer_kind,
+ &old_loc);
+ mpz_set_si (step->value.integer, 1);
+ }
+ (*head)->expr = step;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_DEPEND)
+ && gfc_match_omp_variable_list ("depend ( in : ",
+ &c->lists[OMP_LIST_DEPEND_IN], false,
+ NULL, NULL, true)
+ == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_DEPEND)
+ && gfc_match_omp_variable_list ("depend ( out : ",
+ &c->lists[OMP_LIST_DEPEND_OUT], false,
+ NULL, NULL, true)
+ == MATCH_YES)
+ continue;
+ if ((mask & OMP_CLAUSE_DEPEND)
+ && gfc_match_omp_variable_list ("depend ( inout : ",
+ &c->lists[OMP_LIST_DEPEND_OUT], false,
+ NULL, NULL, true)
+ == MATCH_YES)
+ continue;
break;
}
@@ -436,7 +607,10 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask)
#define OMP_PARALLEL_CLAUSES \
(OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED \
| OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF \
- | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT)
+ | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND)
+#define OMP_DECLARE_SIMD_CLAUSES \
+ (OMP_CLAUSE_SIMDLEN | OMP_CLAUSE_LINEAR | OMP_CLAUSE_UNIFORM \
+ | OMP_CLAUSE_ALIGNED)
#define OMP_DO_CLAUSES \
(OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
| OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
@@ -444,10 +618,14 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask)
#define OMP_SECTIONS_CLAUSES \
(OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \
| OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
+#define OMP_SIMD_CLAUSES \
+ (OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \
+ | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN | OMP_CLAUSE_LINEAR \
+ | OMP_CLAUSE_ALIGNED)
#define OMP_TASK_CLAUSES \
(OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED \
| OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED \
- | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE)
+ | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_DEPEND)
match
gfc_match_omp_parallel (void)
@@ -532,14 +710,28 @@ gfc_match_omp_do (void)
match
+gfc_match_omp_do_simd (void)
+{
+ gfc_omp_clauses *c;
+ if (gfc_match_omp_clauses (&c, ((OMP_DO_CLAUSES | OMP_SIMD_CLAUSES)
+ & ~OMP_CLAUSE_ORDERED))
+ != MATCH_YES)
+ return MATCH_ERROR;
+ new_st.op = EXEC_OMP_DO_SIMD;
+ new_st.ext.omp_clauses = c;
+ return MATCH_YES;
+}
+
+
+match
gfc_match_omp_flush (void)
{
- gfc_namelist *list = NULL;
+ gfc_omp_namelist *list = NULL;
gfc_match_omp_variable_list (" (", &list, true);
if (gfc_match_omp_eos () != MATCH_YES)
{
gfc_error ("Unexpected junk after $OMP FLUSH statement at %C");
- gfc_free_namelist (list);
+ gfc_free_omp_namelist (list);
return MATCH_ERROR;
}
new_st.op = EXEC_OMP_FLUSH;
@@ -549,6 +741,43 @@ gfc_match_omp_flush (void)
match
+gfc_match_omp_simd (void)
+{
+ gfc_omp_clauses *c;
+ if (gfc_match_omp_clauses (&c, OMP_SIMD_CLAUSES) != MATCH_YES)
+ return MATCH_ERROR;
+ new_st.op = EXEC_OMP_SIMD;
+ new_st.ext.omp_clauses = c;
+ return MATCH_YES;
+}
+
+
+match
+gfc_match_omp_declare_simd (void)
+{
+ locus where = gfc_current_locus;
+ gfc_symbol *proc_name;
+ gfc_omp_clauses *c;
+ gfc_omp_declare_simd *ods;
+
+ if (gfc_match (" ( %s ) ", &proc_name) != MATCH_YES)
+ return MATCH_ERROR;
+
+ if (gfc_match_omp_clauses (&c, OMP_DECLARE_SIMD_CLAUSES, true,
+ false) != MATCH_YES)
+ return MATCH_ERROR;
+
+ ods = gfc_get_omp_declare_simd ();
+ ods->where = where;
+ ods->proc_name = proc_name;
+ ods->clauses = c;
+ ods->next = gfc_current_ns->omp_declare_simd;
+ gfc_current_ns->omp_declare_simd = ods;
+ return MATCH_YES;
+}
+
+
+match
gfc_match_omp_threadprivate (void)
{
locus old_loc;
@@ -630,6 +859,20 @@ gfc_match_omp_parallel_do (void)
match
+gfc_match_omp_parallel_do_simd (void)
+{
+ gfc_omp_clauses *c;
+ if (gfc_match_omp_clauses (&c, (OMP_PARALLEL_CLAUSES | OMP_DO_CLAUSES
+ | OMP_SIMD_CLAUSES) & ~OMP_CLAUSE_ORDERED)
+ != MATCH_YES)
+ return MATCH_ERROR;
+ new_st.op = EXEC_OMP_PARALLEL_DO_SIMD;
+ new_st.ext.omp_clauses = c;
+ return MATCH_YES;
+}
+
+
+match
gfc_match_omp_parallel_sections (void)
{
gfc_omp_clauses *c;
@@ -725,20 +968,44 @@ match
gfc_match_omp_atomic (void)
{
gfc_omp_atomic_op op = GFC_OMP_ATOMIC_UPDATE;
- if (gfc_match ("% update") == MATCH_YES)
- op = GFC_OMP_ATOMIC_UPDATE;
- else if (gfc_match ("% read") == MATCH_YES)
- op = GFC_OMP_ATOMIC_READ;
- else if (gfc_match ("% write") == MATCH_YES)
- op = GFC_OMP_ATOMIC_WRITE;
- else if (gfc_match ("% capture") == MATCH_YES)
- op = GFC_OMP_ATOMIC_CAPTURE;
+ int seq_cst = 0;
+ if (gfc_match ("% seq_cst") == MATCH_YES)
+ seq_cst = 1;
+ locus old_loc = gfc_current_locus;
+ if (seq_cst && gfc_match_char (',') == MATCH_YES)
+ seq_cst = 2;
+ if (seq_cst == 2
+ || gfc_match_space () == MATCH_YES)
+ {
+ gfc_gobble_whitespace ();
+ if (gfc_match ("update") == MATCH_YES)
+ op = GFC_OMP_ATOMIC_UPDATE;
+ else if (gfc_match ("read") == MATCH_YES)
+ op = GFC_OMP_ATOMIC_READ;
+ else if (gfc_match ("write") == MATCH_YES)
+ op = GFC_OMP_ATOMIC_WRITE;
+ else if (gfc_match ("capture") == MATCH_YES)
+ op = GFC_OMP_ATOMIC_CAPTURE;
+ else
+ {
+ if (seq_cst == 2)
+ gfc_current_locus = old_loc;
+ goto finish;
+ }
+ if (!seq_cst
+ && (gfc_match (", seq_cst") == MATCH_YES
+ || gfc_match ("% seq_cst") == MATCH_YES))
+ seq_cst = 1;
+ }
+ finish:
if (gfc_match_omp_eos () != MATCH_YES)
{
gfc_error ("Unexpected junk after $OMP ATOMIC statement at %C");
return MATCH_ERROR;
}
new_st.op = EXEC_OMP_ATOMIC;
+ if (seq_cst)
+ op = (gfc_omp_atomic_op) (op | GFC_OMP_ATOMIC_SEQ_CST);
new_st.ext.omp_atomic = op;
return MATCH_YES;
}
@@ -759,6 +1026,73 @@ gfc_match_omp_barrier (void)
match
+gfc_match_omp_taskgroup (void)
+{
+ if (gfc_match_omp_eos () != MATCH_YES)
+ {
+ gfc_error ("Unexpected junk after $OMP TASKGROUP statement at %C");
+ return MATCH_ERROR;
+ }
+ new_st.op = EXEC_OMP_TASKGROUP;
+ return MATCH_YES;
+}
+
+
+static enum gfc_omp_cancel_kind
+gfc_match_omp_cancel_kind (void)
+{
+ if (gfc_match_space () != MATCH_YES)
+ return OMP_CANCEL_UNKNOWN;
+ if (gfc_match ("parallel") == MATCH_YES)
+ return OMP_CANCEL_PARALLEL;
+ if (gfc_match ("sections") == MATCH_YES)
+ return OMP_CANCEL_SECTIONS;
+ if (gfc_match ("do") == MATCH_YES)
+ return OMP_CANCEL_DO;
+ if (gfc_match ("taskgroup") == MATCH_YES)
+ return OMP_CANCEL_TASKGROUP;
+ return OMP_CANCEL_UNKNOWN;
+}
+
+
+match
+gfc_match_omp_cancel (void)
+{
+ gfc_omp_clauses *c;
+ enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
+ if (kind == OMP_CANCEL_UNKNOWN)
+ return MATCH_ERROR;
+ if (gfc_match_omp_clauses (&c, OMP_CLAUSE_IF, false) != MATCH_YES)
+ return MATCH_ERROR;
+ c->cancel = kind;
+ new_st.op = EXEC_OMP_CANCEL;
+ new_st.ext.omp_clauses = c;
+ return MATCH_YES;
+}
+
+
+match
+gfc_match_omp_cancellation_point (void)
+{
+ gfc_omp_clauses *c;
+ enum gfc_omp_cancel_kind kind = gfc_match_omp_cancel_kind ();
+ if (kind == OMP_CANCEL_UNKNOWN)
+ return MATCH_ERROR;
+ if (gfc_match_omp_eos () != MATCH_YES)
+ {
+ gfc_error ("Unexpected junk after $OMP CANCELLATION POINT statement "
+ "at %C");
+ return MATCH_ERROR;
+ }
+ c = gfc_get_omp_clauses ();
+ c->cancel = kind;
+ new_st.op = EXEC_OMP_CANCELLATION_POINT;
+ new_st.ext.omp_clauses = c;
+ return MATCH_YES;
+}
+
+
+match
gfc_match_omp_end_nowait (void)
{
bool nowait = false;
@@ -796,14 +1130,15 @@ gfc_match_omp_end_single (void)
/* OpenMP directive resolving routines. */
static void
-resolve_omp_clauses (gfc_code *code)
+resolve_omp_clauses (gfc_code *code, locus *where,
+ gfc_omp_clauses *omp_clauses, gfc_namespace *ns)
{
- gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
- gfc_namelist *n;
+ gfc_omp_namelist *n;
int list;
static const char *clause_names[]
= { "PRIVATE", "FIRSTPRIVATE", "LASTPRIVATE", "COPYPRIVATE", "SHARED",
- "COPYIN", "REDUCTION" };
+ "COPYIN", "UNIFORM", "ALIGNED", "LINEAR", "DEPEND", "DEPEND",
+ "REDUCTION" };
if (omp_clauses == NULL)
return;
@@ -847,8 +1182,15 @@ resolve_omp_clauses (gfc_code *code)
for (n = omp_clauses->lists[list]; n; n = n->next)
{
n->sym->mark = 0;
- if (n->sym->attr.flavor == FL_VARIABLE || n->sym->attr.proc_pointer)
- continue;
+ if (n->sym->attr.flavor == FL_VARIABLE
+ || n->sym->attr.proc_pointer
+ || (!code && (!n->sym->attr.dummy || n->sym->ns != ns)))
+ {
+ if (!code && (!n->sym->attr.dummy || n->sym->ns != ns))
+ gfc_error ("Variable '%s' is not a dummy argument at %L",
+ n->sym->name, where);
+ continue;
+ }
if (n->sym->attr.flavor == FL_PROCEDURE
&& n->sym->result == n->sym
&& n->sym->attr.function)
@@ -878,16 +1220,20 @@ resolve_omp_clauses (gfc_code *code)
}
}
gfc_error ("Object '%s' is not a variable at %L", n->sym->name,
- &code->loc);
+ where);
}
for (list = 0; list < OMP_LIST_NUM; list++)
- if (list != OMP_LIST_FIRSTPRIVATE && list != OMP_LIST_LASTPRIVATE)
+ if (list != OMP_LIST_FIRSTPRIVATE
+ && list != OMP_LIST_LASTPRIVATE
+ && list != OMP_LIST_ALIGNED
+ && list != OMP_LIST_DEPEND_IN
+ && list != OMP_LIST_DEPEND_OUT)
for (n = omp_clauses->lists[list]; n; n = n->next)
{
if (n->sym->mark)
gfc_error ("Symbol '%s' present on multiple clauses at %L",
- n->sym->name, &code->loc);
+ n->sym->name, where);
else
n->sym->mark = 1;
}
@@ -898,7 +1244,7 @@ resolve_omp_clauses (gfc_code *code)
if (n->sym->mark)
{
gfc_error ("Symbol '%s' present on multiple clauses at %L",
- n->sym->name, &code->loc);
+ n->sym->name, where);
n->sym->mark = 0;
}
@@ -906,7 +1252,7 @@ resolve_omp_clauses (gfc_code *code)
{
if (n->sym->mark)
gfc_error ("Symbol '%s' present on multiple clauses at %L",
- n->sym->name, &code->loc);
+ n->sym->name, where);
else
n->sym->mark = 1;
}
@@ -917,10 +1263,23 @@ resolve_omp_clauses (gfc_code *code)
{
if (n->sym->mark)
gfc_error ("Symbol '%s' present on multiple clauses at %L",
- n->sym->name, &code->loc);
+ n->sym->name, where);
+ else
+ n->sym->mark = 1;
+ }
+
+ for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
+ n->sym->mark = 0;
+
+ for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
+ {
+ if (n->sym->mark)
+ gfc_error ("Symbol '%s' present on multiple clauses at %L",
+ n->sym->name, where);
else
n->sym->mark = 1;
}
+
for (list = 0; list < OMP_LIST_NUM; list++)
if ((n = omp_clauses->lists[list]) != NULL)
{
@@ -940,10 +1299,10 @@ resolve_omp_clauses (gfc_code *code)
{
if (!n->sym->attr.threadprivate)
gfc_error ("Non-THREADPRIVATE object '%s' in COPYIN clause"
- " at %L", n->sym->name, &code->loc);
+ " at %L", n->sym->name, where);
if (n->sym->ts.type == BT_DERIVED && n->sym->ts.u.derived->attr.alloc_comp)
gfc_error ("COPYIN clause object '%s' at %L has ALLOCATABLE components",
- n->sym->name, &code->loc);
+ n->sym->name, where);
}
break;
case OMP_LIST_COPYPRIVATE:
@@ -951,10 +1310,10 @@ resolve_omp_clauses (gfc_code *code)
{
if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
gfc_error ("Assumed size array '%s' in COPYPRIVATE clause "
- "at %L", n->sym->name, &code->loc);
+ "at %L", n->sym->name, where);
if (n->sym->ts.type == BT_DERIVED && n->sym->ts.u.derived->attr.alloc_comp)
gfc_error ("COPYPRIVATE clause object '%s' at %L has ALLOCATABLE components",
- n->sym->name, &code->loc);
+ n->sym->name, where);
}
break;
case OMP_LIST_SHARED:
@@ -962,49 +1321,128 @@ resolve_omp_clauses (gfc_code *code)
{
if (n->sym->attr.threadprivate)
gfc_error ("THREADPRIVATE object '%s' in SHARED clause at "
- "%L", n->sym->name, &code->loc);
+ "%L", n->sym->name, where);
if (n->sym->attr.cray_pointee)
gfc_error ("Cray pointee '%s' in SHARED clause at %L",
- n->sym->name, &code->loc);
+ n->sym->name, where);
+ }
+ break;
+ case OMP_LIST_ALIGNED:
+ for (; n != NULL; n = n->next)
+ {
+ if (!n->sym->attr.pointer
+ && !n->sym->attr.allocatable
+ && !n->sym->attr.cray_pointer
+ && (n->sym->ts.type != BT_DERIVED
+ || (n->sym->ts.u.derived->from_intmod
+ != INTMOD_ISO_C_BINDING)
+ || (n->sym->ts.u.derived->intmod_sym_id
+ != ISOCBINDING_PTR)))
+ gfc_error ("'%s' in ALIGNED clause must be POINTER, "
+ "ALLOCATABLE, Cray pointer or C_PTR at %L",
+ n->sym->name, where);
+ else if (n->expr)
+ {
+ gfc_expr *expr = n->expr;
+ int alignment = 0;
+ if (!gfc_resolve_expr (expr)
+ || expr->ts.type != BT_INTEGER
+ || expr->rank != 0
+ || gfc_extract_int (expr, &alignment)
+ || alignment <= 0)
+ gfc_error ("'%s' in ALIGNED clause at %L requires a scalar "
+ "positive constant integer alignment "
+ "expression", n->sym->name, where);
+ }
}
break;
+ case OMP_LIST_DEPEND_IN:
+ case OMP_LIST_DEPEND_OUT:
+ for (; n != NULL; n = n->next)
+ if (n->expr)
+ {
+ if (!gfc_resolve_expr (n->expr)
+ || n->expr->expr_type != EXPR_VARIABLE
+ || n->expr->ref == NULL
+ || n->expr->ref->next
+ || n->expr->ref->type != REF_ARRAY)
+ gfc_error ("'%s' in DEPEND clause at %L is not a proper "
+ "array section", n->sym->name, where);
+ else if (n->expr->ref->u.ar.codimen)
+ gfc_error ("Coarrays not supported in DEPEND clause at %L",
+ where);
+ else
+ {
+ int i;
+ gfc_array_ref *ar = &n->expr->ref->u.ar;
+ for (i = 0; i < ar->dimen; i++)
+ if (ar->stride[i])
+ {
+ gfc_error ("Stride should not be specified for "
+ "array section in DEPEND clause at %L",
+ where);
+ break;
+ }
+ else if (ar->dimen_type[i] != DIMEN_ELEMENT
+ && ar->dimen_type[i] != DIMEN_RANGE)
+ {
+ gfc_error ("'%s' in DEPEND clause at %L is not a "
+ "proper array section",
+ n->sym->name, where);
+ break;
+ }
+ else if (ar->start[i]
+ && ar->start[i]->expr_type == EXPR_CONSTANT
+ && ar->end[i]
+ && ar->end[i]->expr_type == EXPR_CONSTANT
+ && mpz_cmp (ar->start[i]->value.integer,
+ ar->end[i]->value.integer) > 0)
+ {
+ gfc_error ("'%s' in DEPEND clause at %L is a zero "
+ "size array section", n->sym->name,
+ where);
+ break;
+ }
+ }
+ }
+ break;
default:
for (; n != NULL; n = n->next)
{
if (n->sym->attr.threadprivate)
gfc_error ("THREADPRIVATE object '%s' in %s clause at %L",
- n->sym->name, name, &code->loc);
+ n->sym->name, name, where);
if (n->sym->attr.cray_pointee)
gfc_error ("Cray pointee '%s' in %s clause at %L",
- n->sym->name, name, &code->loc);
+ n->sym->name, name, where);
if (list != OMP_LIST_PRIVATE)
{
if (n->sym->attr.pointer
&& list >= OMP_LIST_REDUCTION_FIRST
&& list <= OMP_LIST_REDUCTION_LAST)
gfc_error ("POINTER object '%s' in %s clause at %L",
- n->sym->name, name, &code->loc);
+ n->sym->name, name, where);
/* Variables in REDUCTION-clauses must be of intrinsic type (flagged below). */
if ((list < OMP_LIST_REDUCTION_FIRST || list > OMP_LIST_REDUCTION_LAST)
&& n->sym->ts.type == BT_DERIVED
&& n->sym->ts.u.derived->attr.alloc_comp)
gfc_error ("%s clause object '%s' has ALLOCATABLE components at %L",
- name, n->sym->name, &code->loc);
+ name, n->sym->name, where);
if (n->sym->attr.cray_pointer
&& list >= OMP_LIST_REDUCTION_FIRST
&& list <= OMP_LIST_REDUCTION_LAST)
gfc_error ("Cray pointer '%s' in %s clause at %L",
- n->sym->name, name, &code->loc);
+ n->sym->name, name, where);
}
if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE)
gfc_error ("Assumed size array '%s' in %s clause at %L",
- n->sym->name, name, &code->loc);
+ n->sym->name, name, where);
if (n->sym->attr.in_namelist
&& (list < OMP_LIST_REDUCTION_FIRST
|| list > OMP_LIST_REDUCTION_LAST))
gfc_error ("Variable '%s' in %s clause is used in "
"NAMELIST statement at %L",
- n->sym->name, name, &code->loc);
+ n->sym->name, name, where);
switch (list)
{
case OMP_LIST_PLUS:
@@ -1014,7 +1452,7 @@ resolve_omp_clauses (gfc_code *code)
gfc_error ("%c REDUCTION variable '%s' at %L must be of numeric type, got %s",
list == OMP_LIST_PLUS ? '+'
: list == OMP_LIST_MULT ? '*' : '-',
- n->sym->name, &code->loc,
+ n->sym->name, where,
gfc_typename (&n->sym->ts));
break;
case OMP_LIST_AND:
@@ -1027,7 +1465,7 @@ resolve_omp_clauses (gfc_code *code)
list == OMP_LIST_AND ? ".AND."
: list == OMP_LIST_OR ? ".OR."
: list == OMP_LIST_EQV ? ".EQV." : ".NEQV.",
- n->sym->name, &code->loc);
+ n->sym->name, where);
break;
case OMP_LIST_MAX:
case OMP_LIST_MIN:
@@ -1036,7 +1474,7 @@ resolve_omp_clauses (gfc_code *code)
gfc_error ("%s REDUCTION variable '%s' must be "
"INTEGER or REAL at %L",
list == OMP_LIST_MAX ? "MAX" : "MIN",
- n->sym->name, &code->loc);
+ n->sym->name, where);
break;
case OMP_LIST_IAND:
case OMP_LIST_IOR:
@@ -1046,12 +1484,34 @@ resolve_omp_clauses (gfc_code *code)
"at %L",
list == OMP_LIST_IAND ? "IAND"
: list == OMP_LIST_MULT ? "IOR" : "IEOR",
- n->sym->name, &code->loc);
+ n->sym->name, where);
+ break;
+ case OMP_LIST_LINEAR:
+ if (n->sym->ts.type != BT_INTEGER)
+ gfc_error ("LINEAR variable '%s' must be INTEGER "
+ "at %L", n->sym->name, where);
+ else if (!code && !n->sym->attr.value)
+ gfc_error ("LINEAR dummy argument '%s' must have VALUE "
+ "attribute at %L", n->sym->name, where);
+ else if (n->expr)
+ {
+ gfc_expr *expr = n->expr;
+ if (!gfc_resolve_expr (expr)
+ || expr->ts.type != BT_INTEGER
+ || expr->rank != 0)
+ gfc_error ("'%s' in LINEAR clause at %L requires "
+ "a scalar integer linear-step expression",
+ n->sym->name, where);
+ else if (!code && expr->expr_type != EXPR_CONSTANT)
+ gfc_error ("'%s' in LINEAR clause at %L requires "
+ "a constant integer linear-step expression",
+ n->sym->name, where);
+ }
break;
/* Workaround for PR middle-end/26316, nothing really needs
to be done here for OMP_LIST_PRIVATE. */
case OMP_LIST_PRIVATE:
- gcc_assert (code->op != EXEC_NOP);
+ gcc_assert (code && code->op != EXEC_NOP);
default:
break;
}
@@ -1059,6 +1519,22 @@ resolve_omp_clauses (gfc_code *code)
break;
}
}
+ if (omp_clauses->safelen_expr)
+ {
+ gfc_expr *expr = omp_clauses->safelen_expr;
+ if (!gfc_resolve_expr (expr)
+ || expr->ts.type != BT_INTEGER || expr->rank != 0)
+ gfc_error ("SAFELEN clause at %L requires a scalar "
+ "INTEGER expression", &expr->where);
+ }
+ if (omp_clauses->simdlen_expr)
+ {
+ gfc_expr *expr = omp_clauses->simdlen_expr;
+ if (!gfc_resolve_expr (expr)
+ || expr->ts.type != BT_INTEGER || expr->rank != 0)
+ gfc_error ("SIMDLEN clause at %L requires a scalar "
+ "INTEGER expression", &expr->where);
+ }
}
@@ -1142,12 +1618,13 @@ resolve_omp_atomic (gfc_code *code)
gfc_code *atomic_code = code;
gfc_symbol *var;
gfc_expr *expr2, *expr2_tmp;
+ gfc_omp_atomic_op aop
+ = (gfc_omp_atomic_op) (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK);
code = code->block->next;
gcc_assert (code->op == EXEC_ASSIGN);
- gcc_assert ((atomic_code->ext.omp_atomic != GFC_OMP_ATOMIC_CAPTURE
- && code->next == NULL)
- || (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_CAPTURE
+ gcc_assert (((aop != GFC_OMP_ATOMIC_CAPTURE) && code->next == NULL)
+ || ((aop == GFC_OMP_ATOMIC_CAPTURE)
&& code->next != NULL
&& code->next->op == EXEC_ASSIGN
&& code->next->next == NULL));
@@ -1169,14 +1646,13 @@ resolve_omp_atomic (gfc_code *code)
expr2 = is_conversion (code->expr2, false);
if (expr2 == NULL)
{
- if (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_READ
- || atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_WRITE)
+ if (aop == GFC_OMP_ATOMIC_READ || aop == GFC_OMP_ATOMIC_WRITE)
expr2 = is_conversion (code->expr2, true);
if (expr2 == NULL)
expr2 = code->expr2;
}
- switch (atomic_code->ext.omp_atomic)
+ switch (aop)
{
case GFC_OMP_ATOMIC_READ:
if (expr2->expr_type != EXPR_VARIABLE
@@ -1249,7 +1725,21 @@ resolve_omp_atomic (gfc_code *code)
break;
}
- if (expr2->expr_type == EXPR_OP)
+ if (var->attr.allocatable)
+ {
+ gfc_error ("!$OMP ATOMIC with ALLOCATABLE variable at %L",
+ &code->loc);
+ return;
+ }
+
+ if (aop == GFC_OMP_ATOMIC_CAPTURE
+ && code->next == NULL
+ && code->expr2->rank == 0
+ && !expr_references_sym (code->expr2, var, NULL))
+ atomic_code->ext.omp_atomic
+ = (gfc_omp_atomic_op) (atomic_code->ext.omp_atomic
+ | GFC_OMP_ATOMIC_SWAP);
+ else if (expr2->expr_type == EXPR_OP)
{
gfc_expr *v = NULL, *e, *c;
gfc_intrinsic_op op = expr2->value.op.op;
@@ -1420,11 +1910,18 @@ resolve_omp_atomic (gfc_code *code)
&& arg->expr->symtree->n.sym == var)
var_arg = arg;
else if (expr_references_sym (arg->expr, var, NULL))
- gfc_error ("!$OMP ATOMIC intrinsic arguments except one must not "
- "reference '%s' at %L", var->name, &arg->expr->where);
+ {
+ gfc_error ("!$OMP ATOMIC intrinsic arguments except one must "
+ "not reference '%s' at %L",
+ var->name, &arg->expr->where);
+ return;
+ }
if (arg->expr->rank != 0)
- gfc_error ("!$OMP ATOMIC intrinsic arguments must be scalar "
- "at %L", &arg->expr->where);
+ {
+ gfc_error ("!$OMP ATOMIC intrinsic arguments must be scalar "
+ "at %L", &arg->expr->where);
+ return;
+ }
}
if (var_arg == NULL)
@@ -1447,10 +1944,10 @@ resolve_omp_atomic (gfc_code *code)
}
}
else
- gfc_error ("!$OMP ATOMIC assignment must have an operator or intrinsic "
- "on right hand side at %L", &expr2->where);
+ gfc_error ("!$OMP ATOMIC assignment must have an operator or "
+ "intrinsic on right hand side at %L", &expr2->where);
- if (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_CAPTURE && code->next)
+ if (aop == GFC_OMP_ATOMIC_CAPTURE && code->next)
{
code = code->next;
if (code->expr1->expr_type != EXPR_VARIABLE
@@ -1542,7 +2039,7 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
{
struct omp_context ctx;
gfc_omp_clauses *omp_clauses = code->ext.omp_clauses;
- gfc_namelist *n;
+ gfc_omp_namelist *n;
int list;
ctx.code = code;
@@ -1555,7 +2052,8 @@ gfc_resolve_omp_parallel_blocks (gfc_code *code, gfc_namespace *ns)
for (n = omp_clauses->lists[list]; n; n = n->next)
pointer_set_insert (ctx.sharing_clauses, n->sym);
- if (code->op == EXEC_OMP_PARALLEL_DO)
+ if (code->op == EXEC_OMP_PARALLEL_DO
+ || code->op == EXEC_OMP_PARALLEL_DO_SIMD)
gfc_resolve_omp_do_blocks (code, ns);
else
gfc_resolve_blocks (code->block, ns);
@@ -1624,9 +2122,9 @@ gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym)
if (! pointer_set_insert (omp_current_ctx->private_iterators, sym))
{
gfc_omp_clauses *omp_clauses = omp_current_ctx->code->ext.omp_clauses;
- gfc_namelist *p;
+ gfc_omp_namelist *p;
- p = gfc_get_namelist ();
+ p = gfc_get_omp_namelist ();
p->sym = sym;
p->next = omp_clauses->lists[OMP_LIST_PRIVATE];
omp_clauses->lists[OMP_LIST_PRIVATE] = p;
@@ -1639,11 +2137,25 @@ resolve_omp_do (gfc_code *code)
{
gfc_code *do_code, *c;
int list, i, collapse;
- gfc_namelist *n;
+ gfc_omp_namelist *n;
gfc_symbol *dovar;
+ const char *name;
+ bool is_simd = false;
+
+ switch (code->op)
+ {
+ case EXEC_OMP_DO: name = "!$OMP DO"; break;
+ case EXEC_OMP_DO_SIMD: name = "!$OMP DO SIMD"; is_simd = true; break;
+ case EXEC_OMP_PARALLEL_DO: name = "!$OMP PARALLEL DO"; break;
+ case EXEC_OMP_PARALLEL_DO_SIMD:
+ name = "!$OMP PARALLEL DO SIMD";
+ is_simd = true; break;
+ case EXEC_OMP_SIMD: name = "!$OMP SIMD"; is_simd = true; break;
+ default: gcc_unreachable ();
+ }
if (code->ext.omp_clauses)
- resolve_omp_clauses (code);
+ resolve_omp_clauses (code, &code->loc, code->ext.omp_clauses, NULL);
do_code = code->block->next;
collapse = code->ext.omp_clauses->collapse;
@@ -1653,27 +2165,46 @@ resolve_omp_do (gfc_code *code)
{
if (do_code->op == EXEC_DO_WHILE)
{
- gfc_error ("!$OMP DO cannot be a DO WHILE or DO without loop control "
- "at %L", &do_code->loc);
+ gfc_error ("%s cannot be a DO WHILE or DO without loop control "
+ "at %L", name, &do_code->loc);
+ break;
+ }
+ if (do_code->op == EXEC_DO_CONCURRENT)
+ {
+ gfc_error ("%s cannot be a DO CONCURRENT loop at %L", name,
+ &do_code->loc);
break;
}
gcc_assert (do_code->op == EXEC_DO);
if (do_code->ext.iterator->var->ts.type != BT_INTEGER)
- gfc_error ("!$OMP DO iteration variable must be of type integer at %L",
- &do_code->loc);
+ gfc_error ("%s iteration variable must be of type integer at %L",
+ name, &do_code->loc);
dovar = do_code->ext.iterator->var->symtree->n.sym;
if (dovar->attr.threadprivate)
- gfc_error ("!$OMP DO iteration variable must not be THREADPRIVATE "
- "at %L", &do_code->loc);
+ gfc_error ("%s iteration variable must not be THREADPRIVATE "
+ "at %L", name, &do_code->loc);
if (code->ext.omp_clauses)
for (list = 0; list < OMP_LIST_NUM; list++)
- if (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE)
+ if (!is_simd
+ ? (list != OMP_LIST_PRIVATE && list != OMP_LIST_LASTPRIVATE)
+ : code->ext.omp_clauses->collapse > 1
+ ? (list != OMP_LIST_LASTPRIVATE)
+ : (list != OMP_LIST_LINEAR))
for (n = code->ext.omp_clauses->lists[list]; n; n = n->next)
if (dovar == n->sym)
{
- gfc_error ("!$OMP DO iteration variable present on clause "
- "other than PRIVATE or LASTPRIVATE at %L",
- &do_code->loc);
+ if (!is_simd)
+ gfc_error ("%s iteration variable present on clause "
+ "other than PRIVATE or LASTPRIVATE at %L",
+ name, &do_code->loc);
+ else if (code->ext.omp_clauses->collapse > 1)
+ gfc_error ("%s iteration variable present on clause "
+ "other than LASTPRIVATE at %L",
+ name, &do_code->loc);
+ else
+ gfc_error ("%s iteration variable present on clause "
+ "other than LINEAR at %L",
+ name, &do_code->loc);
break;
}
if (i > 1)
@@ -1689,8 +2220,8 @@ resolve_omp_do (gfc_code *code)
|| gfc_find_sym_in_expr (ivar, do_code->ext.iterator->end)
|| gfc_find_sym_in_expr (ivar, do_code->ext.iterator->step))
{
- gfc_error ("!$OMP DO collapsed loops don't form rectangular iteration space at %L",
- &do_code->loc);
+ gfc_error ("%s collapsed loops don't form rectangular "
+ "iteration space at %L", name, &do_code->loc);
break;
}
if (j < i)
@@ -1703,8 +2234,8 @@ resolve_omp_do (gfc_code *code)
for (c = do_code->next; c; c = c->next)
if (c->op != EXEC_NOP && c->op != EXEC_CONTINUE)
{
- gfc_error ("collapsed !$OMP DO loops not perfectly nested at %L",
- &c->loc);
+ gfc_error ("collapsed %s loops not perfectly nested at %L",
+ name, &c->loc);
break;
}
if (c)
@@ -1712,16 +2243,16 @@ resolve_omp_do (gfc_code *code)
do_code = do_code->block;
if (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE)
{
- gfc_error ("not enough DO loops for collapsed !$OMP DO at %L",
- &code->loc);
+ gfc_error ("not enough DO loops for collapsed %s at %L",
+ name, &code->loc);
break;
}
do_code = do_code->next;
if (do_code == NULL
|| (do_code->op != EXEC_DO && do_code->op != EXEC_DO_WHILE))
{
- gfc_error ("not enough DO loops for collapsed !$OMP DO at %L",
- &code->loc);
+ gfc_error ("not enough DO loops for collapsed %s at %L",
+ name, &code->loc);
break;
}
}
@@ -1740,18 +2271,22 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
switch (code->op)
{
case EXEC_OMP_DO:
+ case EXEC_OMP_DO_SIMD:
case EXEC_OMP_PARALLEL_DO:
+ case EXEC_OMP_PARALLEL_DO_SIMD:
+ case EXEC_OMP_SIMD:
resolve_omp_do (code);
break;
- case EXEC_OMP_WORKSHARE:
+ case EXEC_OMP_CANCEL:
case EXEC_OMP_PARALLEL_WORKSHARE:
case EXEC_OMP_PARALLEL:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SINGLE:
case EXEC_OMP_TASK:
+ case EXEC_OMP_WORKSHARE:
if (code->ext.omp_clauses)
- resolve_omp_clauses (code);
+ resolve_omp_clauses (code, &code->loc, code->ext.omp_clauses, NULL);
break;
case EXEC_OMP_ATOMIC:
resolve_omp_atomic (code);
@@ -1760,3 +2295,20 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
break;
}
}
+
+/* Resolve !$omp declare simd constructs in NS. */
+
+void
+gfc_resolve_omp_declare_simd (gfc_namespace *ns)
+{
+ gfc_omp_declare_simd *ods;
+
+ for (ods = ns->omp_declare_simd; ods; ods = ods->next)
+ {
+ if (ods->proc_name != ns->proc_name)
+ gfc_error ("!$OMP DECLARE SIMD should refer to containing procedure"
+ "'%s' at %L", ns->proc_name->name, &ods->where);
+ if (ods->clauses)
+ resolve_omp_clauses (NULL, &ods->where, ods->clauses, ns);
+ }
+}
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 77667150176..9735714ea9e 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -569,17 +569,27 @@ decode_omp_directive (void)
match ("barrier", gfc_match_omp_barrier, ST_OMP_BARRIER);
break;
case 'c':
+ match ("cancellation% point", gfc_match_omp_cancellation_point,
+ ST_OMP_CANCELLATION_POINT);
+ match ("cancel", gfc_match_omp_cancel, ST_OMP_CANCEL);
match ("critical", gfc_match_omp_critical, ST_OMP_CRITICAL);
break;
case 'd':
+ match ("declare simd", gfc_match_omp_declare_simd,
+ ST_OMP_DECLARE_SIMD);
+ match ("do simd", gfc_match_omp_do_simd, ST_OMP_DO_SIMD);
match ("do", gfc_match_omp_do, ST_OMP_DO);
break;
case 'e':
match ("end atomic", gfc_match_omp_eos, ST_OMP_END_ATOMIC);
match ("end critical", gfc_match_omp_critical, ST_OMP_END_CRITICAL);
+ match ("end do simd", gfc_match_omp_end_nowait, ST_OMP_END_DO_SIMD);
match ("end do", gfc_match_omp_end_nowait, ST_OMP_END_DO);
+ match ("end simd", gfc_match_omp_eos, ST_OMP_END_SIMD);
match ("end master", gfc_match_omp_eos, ST_OMP_END_MASTER);
match ("end ordered", gfc_match_omp_eos, ST_OMP_END_ORDERED);
+ match ("end parallel do simd", gfc_match_omp_eos,
+ ST_OMP_END_PARALLEL_DO_SIMD);
match ("end parallel do", gfc_match_omp_eos, ST_OMP_END_PARALLEL_DO);
match ("end parallel sections", gfc_match_omp_eos,
ST_OMP_END_PARALLEL_SECTIONS);
@@ -588,6 +598,7 @@ decode_omp_directive (void)
match ("end parallel", gfc_match_omp_eos, ST_OMP_END_PARALLEL);
match ("end sections", gfc_match_omp_end_nowait, ST_OMP_END_SECTIONS);
match ("end single", gfc_match_omp_end_single, ST_OMP_END_SINGLE);
+ match ("end taskgroup", gfc_match_omp_eos, ST_OMP_END_TASKGROUP);
match ("end task", gfc_match_omp_eos, ST_OMP_END_TASK);
match ("end workshare", gfc_match_omp_end_nowait,
ST_OMP_END_WORKSHARE);
@@ -602,6 +613,8 @@ decode_omp_directive (void)
match ("ordered", gfc_match_omp_ordered, ST_OMP_ORDERED);
break;
case 'p':
+ match ("parallel do simd", gfc_match_omp_parallel_do_simd,
+ ST_OMP_PARALLEL_DO_SIMD);
match ("parallel do", gfc_match_omp_parallel_do, ST_OMP_PARALLEL_DO);
match ("parallel sections", gfc_match_omp_parallel_sections,
ST_OMP_PARALLEL_SECTIONS);
@@ -612,12 +625,14 @@ decode_omp_directive (void)
case 's':
match ("sections", gfc_match_omp_sections, ST_OMP_SECTIONS);
match ("section", gfc_match_omp_eos, ST_OMP_SECTION);
+ match ("simd", gfc_match_omp_simd, ST_OMP_SIMD);
match ("single", gfc_match_omp_single, ST_OMP_SINGLE);
break;
case 't':
- match ("task", gfc_match_omp_task, ST_OMP_TASK);
+ match ("taskgroup", gfc_match_omp_taskgroup, ST_OMP_TASKGROUP);
match ("taskwait", gfc_match_omp_taskwait, ST_OMP_TASKWAIT);
match ("taskyield", gfc_match_omp_taskyield, ST_OMP_TASKYIELD);
+ match ("task", gfc_match_omp_task, ST_OMP_TASK);
match ("threadprivate", gfc_match_omp_threadprivate,
ST_OMP_THREADPRIVATE);
break;
@@ -1013,6 +1028,7 @@ next_statement (void)
case ST_ASSIGNMENT: case ST_ARITHMETIC_IF: case ST_WHERE: case ST_FORALL: \
case ST_LABEL_ASSIGNMENT: case ST_FLUSH: case ST_OMP_FLUSH: \
case ST_OMP_BARRIER: case ST_OMP_TASKWAIT: case ST_OMP_TASKYIELD: \
+ case ST_OMP_CANCEL: case ST_OMP_CANCELLATION_POINT: \
case ST_ERROR_STOP: case ST_SYNC_ALL: case ST_SYNC_IMAGES: \
case ST_SYNC_MEMORY: case ST_LOCK: case ST_UNLOCK
@@ -1026,14 +1042,15 @@ next_statement (void)
case ST_OMP_CRITICAL: case ST_OMP_MASTER: case ST_OMP_SINGLE: \
case ST_OMP_DO: case ST_OMP_PARALLEL_DO: case ST_OMP_ATOMIC: \
case ST_OMP_WORKSHARE: case ST_OMP_PARALLEL_WORKSHARE: \
- case ST_OMP_TASK: case ST_CRITICAL
+ case ST_OMP_TASK: case ST_OMP_TASKGROUP: case ST_OMP_SIMD: \
+ case ST_OMP_DO_SIMD: case ST_OMP_PARALLEL_DO_SIMD: case ST_CRITICAL
/* Declaration statements */
#define case_decl case ST_ATTR_DECL: case ST_COMMON: case ST_DATA_DECL: \
case ST_EQUIVALENCE: case ST_NAMELIST: case ST_STATEMENT_FUNCTION: \
case ST_TYPE: case ST_INTERFACE: case ST_OMP_THREADPRIVATE: \
- case ST_PROCEDURE
+ case ST_PROCEDURE: case ST_OMP_DECLARE_SIMD
/* Block end statements. Errors associated with interchanging these
are detected in gfc_match_end(). */
@@ -1524,12 +1541,24 @@ gfc_ascii_statement (gfc_statement st)
case ST_OMP_BARRIER:
p = "!$OMP BARRIER";
break;
+ case ST_OMP_CANCEL:
+ p = "!$OMP CANCEL";
+ break;
+ case ST_OMP_CANCELLATION_POINT:
+ p = "!$OMP CANCELLATION POINT";
+ break;
case ST_OMP_CRITICAL:
p = "!$OMP CRITICAL";
break;
+ case ST_OMP_DECLARE_SIMD:
+ p = "!$OMP DECLARE SIMD";
+ break;
case ST_OMP_DO:
p = "!$OMP DO";
break;
+ case ST_OMP_DO_SIMD:
+ p = "!$OMP DO SIMD";
+ break;
case ST_OMP_END_ATOMIC:
p = "!$OMP END ATOMIC";
break;
@@ -1539,6 +1568,12 @@ gfc_ascii_statement (gfc_statement st)
case ST_OMP_END_DO:
p = "!$OMP END DO";
break;
+ case ST_OMP_END_DO_SIMD:
+ p = "!$OMP END DO SIMD";
+ break;
+ case ST_OMP_END_SIMD:
+ p = "!$OMP END SIMD";
+ break;
case ST_OMP_END_MASTER:
p = "!$OMP END MASTER";
break;
@@ -1551,6 +1586,9 @@ gfc_ascii_statement (gfc_statement st)
case ST_OMP_END_PARALLEL_DO:
p = "!$OMP END PARALLEL DO";
break;
+ case ST_OMP_END_PARALLEL_DO_SIMD:
+ p = "!$OMP END PARALLEL DO SIMD";
+ break;
case ST_OMP_END_PARALLEL_SECTIONS:
p = "!$OMP END PARALLEL SECTIONS";
break;
@@ -1566,6 +1604,9 @@ gfc_ascii_statement (gfc_statement st)
case ST_OMP_END_TASK:
p = "!$OMP END TASK";
break;
+ case ST_OMP_END_TASKGROUP:
+ p = "!$OMP END TASKGROUP";
+ break;
case ST_OMP_END_WORKSHARE:
p = "!$OMP END WORKSHARE";
break;
@@ -1584,6 +1625,9 @@ gfc_ascii_statement (gfc_statement st)
case ST_OMP_PARALLEL_DO:
p = "!$OMP PARALLEL DO";
break;
+ case ST_OMP_PARALLEL_DO_SIMD:
+ p = "!$OMP PARALLEL DO SIMD";
+ break;
case ST_OMP_PARALLEL_SECTIONS:
p = "!$OMP PARALLEL SECTIONS";
break;
@@ -1596,12 +1640,18 @@ gfc_ascii_statement (gfc_statement st)
case ST_OMP_SECTION:
p = "!$OMP SECTION";
break;
+ case ST_OMP_SIMD:
+ p = "!$OMP SIMD";
+ break;
case ST_OMP_SINGLE:
p = "!$OMP SINGLE";
break;
case ST_OMP_TASK:
p = "!$OMP TASK";
break;
+ case ST_OMP_TASKGROUP:
+ p = "!$OMP TASKGROUP";
+ break;
case ST_OMP_TASKWAIT:
p = "!$OMP TASKWAIT";
break;
@@ -3578,7 +3628,19 @@ parse_omp_do (gfc_statement omp_st)
pop_state ();
st = next_statement ();
- if (st == (omp_st == ST_OMP_DO ? ST_OMP_END_DO : ST_OMP_END_PARALLEL_DO))
+ gfc_statement omp_end_st = ST_OMP_END_DO;
+ switch (omp_st)
+ {
+ case ST_OMP_SIMD: omp_end_st = ST_OMP_END_SIMD; break;
+ case ST_OMP_DO: omp_end_st = ST_OMP_END_DO; break;
+ case ST_OMP_DO_SIMD: omp_end_st = ST_OMP_END_DO_SIMD; break;
+ case ST_OMP_PARALLEL_DO: omp_end_st = ST_OMP_END_PARALLEL_DO; break;
+ case ST_OMP_PARALLEL_DO_SIMD:
+ omp_end_st = ST_OMP_END_PARALLEL_DO_SIMD;
+ break;
+ default: gcc_unreachable ();
+ }
+ if (st == omp_end_st)
{
if (new_st.op == EXEC_OMP_END_NOWAIT)
cp->ext.omp_clauses->nowait |= new_st.ext.omp_bool;
@@ -3610,7 +3672,8 @@ parse_omp_atomic (void)
np = new_level (cp);
np->op = cp->op;
np->block = NULL;
- count = 1 + (cp->ext.omp_atomic == GFC_OMP_ATOMIC_CAPTURE);
+ count = 1 + ((cp->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
+ == GFC_OMP_ATOMIC_CAPTURE);
while (count)
{
@@ -3636,7 +3699,8 @@ parse_omp_atomic (void)
gfc_warning_check ();
st = next_statement ();
}
- else if (cp->ext.omp_atomic == GFC_OMP_ATOMIC_CAPTURE)
+ else if ((cp->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
+ == GFC_OMP_ATOMIC_CAPTURE)
gfc_error ("Missing !$OMP END ATOMIC after !$OMP ATOMIC CAPTURE at %C");
return st;
}
@@ -3685,6 +3749,9 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
case ST_OMP_TASK:
omp_end_st = ST_OMP_END_TASK;
break;
+ case ST_OMP_TASKGROUP:
+ omp_end_st = ST_OMP_END_TASKGROUP;
+ break;
case ST_OMP_WORKSHARE:
omp_end_st = ST_OMP_END_WORKSHARE;
break;
@@ -3744,6 +3811,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
break;
case ST_OMP_PARALLEL_DO:
+ case ST_OMP_PARALLEL_DO_SIMD:
st = parse_omp_do (st);
continue;
@@ -3917,6 +3985,7 @@ parse_executable (gfc_statement st)
case ST_OMP_MASTER:
case ST_OMP_SINGLE:
case ST_OMP_TASK:
+ case ST_OMP_TASKGROUP:
parse_omp_structured_block (st, false);
break;
@@ -3926,7 +3995,10 @@ parse_executable (gfc_statement st)
break;
case ST_OMP_DO:
+ case ST_OMP_DO_SIMD:
case ST_OMP_PARALLEL_DO:
+ case ST_OMP_PARALLEL_DO_SIMD:
+ case ST_OMP_SIMD:
st = parse_omp_do (st);
if (st == ST_IMPLIED_ENDDO)
return st;
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 15c94635f49..7579573599a 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -4730,6 +4730,50 @@ done:
}
+static void
+add_caf_get_intrinsic (gfc_expr *e)
+{
+ gfc_expr *wrapper, *tmp_expr;
+ gfc_ref *ref;
+ int n;
+
+ for (ref = e->ref; ref; ref = ref->next)
+ if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0)
+ break;
+ if (ref == NULL)
+ return;
+
+ for (n = ref->u.ar.dimen; n < ref->u.ar.dimen + ref->u.ar.codimen; n++)
+ if (ref->u.ar.dimen_type[n] != DIMEN_ELEMENT)
+ return;
+
+ tmp_expr = XCNEW (gfc_expr);
+ *tmp_expr = *e;
+ wrapper = gfc_build_intrinsic_call (gfc_current_ns, GFC_ISYM_CAF_GET,
+ "caf_get", tmp_expr->where, 1, tmp_expr);
+ wrapper->ts = e->ts;
+ wrapper->rank = e->rank;
+ if (e->rank)
+ wrapper->shape = gfc_copy_shape (e->shape, e->rank);
+ *e = *wrapper;
+ free (wrapper);
+}
+
+
+static void
+remove_caf_get_intrinsic (gfc_expr *e)
+{
+ gcc_assert (e->expr_type == EXPR_FUNCTION && e->value.function.isym
+ && e->value.function.isym->id == GFC_ISYM_CAF_GET);
+ gfc_expr *e2 = e->value.function.actual->expr;
+ e->value.function.actual->expr =NULL;
+ gfc_free_actual_arglist (e->value.function.actual);
+ gfc_free_shape (&e->shape, e->rank);
+ *e = *e2;
+ free (e2);
+}
+
+
/* Resolve a variable expression. */
static bool
@@ -5009,6 +5053,12 @@ resolve_procedure:
}
}
+ if (t)
+ expression_rank (e);
+
+ if (0 && t && gfc_option.coarray == GFC_FCOARRAY_LIB && gfc_is_coindexed (e))
+ add_caf_get_intrinsic (e);
+
return t;
}
@@ -6092,11 +6142,7 @@ gfc_resolve_expr (gfc_expr *e)
if (check_host_association (e))
t = resolve_function (e);
else
- {
- t = resolve_variable (e);
- if (t)
- expression_rank (e);
- }
+ t = resolve_variable (e);
if (e->ts.type == BT_CHARACTER && e->ts.u.cl == NULL && e->ref
&& e->ref->type != REF_SUBSTRING)
@@ -8982,15 +9028,19 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
case EXEC_OMP_ATOMIC:
case EXEC_OMP_CRITICAL:
case EXEC_OMP_DO:
+ case EXEC_OMP_DO_SIMD:
case EXEC_OMP_MASTER:
case EXEC_OMP_ORDERED:
case EXEC_OMP_PARALLEL:
case EXEC_OMP_PARALLEL_DO:
+ case EXEC_OMP_PARALLEL_DO_SIMD:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_PARALLEL_WORKSHARE:
case EXEC_OMP_SECTIONS:
+ case EXEC_OMP_SIMD:
case EXEC_OMP_SINGLE:
case EXEC_OMP_TASK:
+ case EXEC_OMP_TASKGROUP:
case EXEC_OMP_TASKWAIT:
case EXEC_OMP_TASKYIELD:
case EXEC_OMP_WORKSHARE:
@@ -9214,8 +9264,10 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
return false;
}
+ bool lhs_coindexed = gfc_is_coindexed (lhs);
+
/* F2008, Section 7.2.1.2. */
- if (gfc_is_coindexed (lhs) && gfc_has_ultimate_allocatable (lhs))
+ if (lhs_coindexed && gfc_has_ultimate_allocatable (lhs))
{
gfc_error ("Coindexed variable must not have an allocatable ultimate "
"component in assignment at %L", &lhs->where);
@@ -9223,6 +9275,25 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns)
}
gfc_check_assign (lhs, rhs, 1);
+
+ if (0 && lhs_coindexed && gfc_option.coarray == GFC_FCOARRAY_LIB)
+ {
+ code->op = EXEC_CALL;
+ gfc_get_sym_tree (GFC_PREFIX ("caf_send"), ns, &code->symtree, true);
+ code->resolved_sym = code->symtree->n.sym;
+ code->resolved_sym->attr.flavor = FL_PROCEDURE;
+ code->resolved_sym->attr.intrinsic = 1;
+ code->resolved_sym->attr.subroutine = 1;
+ code->resolved_isym = gfc_intrinsic_subroutine_by_id (GFC_ISYM_CAF_SEND);
+ gfc_commit_symbol (code->resolved_sym);
+ code->ext.actual = gfc_get_actual_arglist ();
+ code->ext.actual->expr = lhs;
+ code->ext.actual->next = gfc_get_actual_arglist ();
+ code->ext.actual->next->expr = rhs;
+ code->expr1 = NULL;
+ code->expr2 = NULL;
+ }
+
return false;
}
@@ -9735,6 +9806,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
break;
case EXEC_OMP_PARALLEL:
case EXEC_OMP_PARALLEL_DO:
+ case EXEC_OMP_PARALLEL_DO_SIMD:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_TASK:
omp_workshare_save = omp_workshare_flag;
@@ -9742,6 +9814,8 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
gfc_resolve_omp_parallel_blocks (code, ns);
break;
case EXEC_OMP_DO:
+ case EXEC_OMP_DO_SIMD:
+ case EXEC_OMP_SIMD:
gfc_resolve_omp_do_blocks (code, ns);
break;
case EXEC_SELECT_TYPE:
@@ -9845,6 +9919,11 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
if (!t)
break;
+ if (code->expr1->expr_type == EXPR_FUNCTION
+ && code->expr1->value.function.isym
+ && code->expr1->value.function.isym->id == GFC_ISYM_CAF_GET)
+ remove_caf_get_intrinsic (code->expr1);
+
if (!gfc_check_vardef_context (code->expr1, false, false, false,
_("assignment")))
break;
@@ -9858,7 +9937,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
}
/* F03 7.4.1.3 for non-allocatable, non-pointer components. */
- if (code->expr1->ts.type == BT_DERIVED
+ if (code->op != EXEC_CALL && code->expr1->ts.type == BT_DERIVED
&& code->expr1->ts.u.derived->attr.defined_assign_comp)
generate_component_assignments (&code, ns);
@@ -10056,13 +10135,18 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
case EXEC_OMP_ATOMIC:
case EXEC_OMP_BARRIER:
+ case EXEC_OMP_CANCEL:
+ case EXEC_OMP_CANCELLATION_POINT:
case EXEC_OMP_CRITICAL:
case EXEC_OMP_FLUSH:
case EXEC_OMP_DO:
+ case EXEC_OMP_DO_SIMD:
case EXEC_OMP_MASTER:
case EXEC_OMP_ORDERED:
case EXEC_OMP_SECTIONS:
+ case EXEC_OMP_SIMD:
case EXEC_OMP_SINGLE:
+ case EXEC_OMP_TASKGROUP:
case EXEC_OMP_TASKWAIT:
case EXEC_OMP_TASKYIELD:
case EXEC_OMP_WORKSHARE:
@@ -10071,6 +10155,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
case EXEC_OMP_PARALLEL:
case EXEC_OMP_PARALLEL_DO:
+ case EXEC_OMP_PARALLEL_DO_SIMD:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_PARALLEL_WORKSHARE:
case EXEC_OMP_TASK:
@@ -14609,6 +14694,8 @@ resolve_types (gfc_namespace *ns)
gfc_resolve_uops (ns->uop_root);
+ gfc_resolve_omp_declare_simd (ns);
+
gfc_current_ns = old_ns;
}
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 1b6cd5bc4c1..d18bc081088 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -4601,7 +4601,7 @@ gfc_simplify_null (gfc_expr *mold)
gfc_expr *
-gfc_simplify_num_images (void)
+gfc_simplify_num_images (gfc_expr *distance ATTRIBUTE_UNUSED, gfc_expr *failed)
{
gfc_expr *result;
@@ -4614,10 +4614,18 @@ gfc_simplify_num_images (void)
if (gfc_option.coarray != GFC_FCOARRAY_SINGLE)
return NULL;
+ if (failed && failed->expr_type != EXPR_CONSTANT)
+ return NULL;
+
/* FIXME: gfc_current_locus is wrong. */
result = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
&gfc_current_locus);
- mpz_set_si (result->value.integer, 1);
+
+ if (failed && failed->value.logical != 0)
+ mpz_set_si (result->value.integer, 0);
+ else
+ mpz_set_si (result->value.integer, 1);
+
return result;
}
@@ -6389,12 +6397,15 @@ gfc_simplify_image_index (gfc_expr *coarray, gfc_expr *sub)
gfc_expr *
-gfc_simplify_this_image (gfc_expr *coarray, gfc_expr *dim)
+gfc_simplify_this_image (gfc_expr *coarray, gfc_expr *dim,
+ gfc_expr *distance ATTRIBUTE_UNUSED)
{
if (gfc_option.coarray != GFC_FCOARRAY_SINGLE)
return NULL;
- if (coarray == NULL)
+ /* If no coarray argument has been passed or when the first argument
+ is actually a distance argment. */
+ if (coarray == NULL || !gfc_is_coarray (coarray))
{
gfc_expr *result;
/* FIXME: gfc_current_locus is wrong. */
diff --git a/gcc/fortran/st.c b/gcc/fortran/st.c
index 0e1cc705eb4..a3df43ed386 100644
--- a/gcc/fortran/st.c
+++ b/gcc/fortran/st.c
@@ -185,12 +185,17 @@ gfc_free_statement (gfc_code *p)
gfc_free_forall_iterator (p->ext.forall_iterator);
break;
+ case EXEC_OMP_CANCEL:
+ case EXEC_OMP_CANCELLATION_POINT:
case EXEC_OMP_DO:
+ case EXEC_OMP_DO_SIMD:
case EXEC_OMP_END_SINGLE:
case EXEC_OMP_PARALLEL:
case EXEC_OMP_PARALLEL_DO:
+ case EXEC_OMP_PARALLEL_DO_SIMD:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_SECTIONS:
+ case EXEC_OMP_SIMD:
case EXEC_OMP_SINGLE:
case EXEC_OMP_TASK:
case EXEC_OMP_WORKSHARE:
@@ -203,7 +208,7 @@ gfc_free_statement (gfc_code *p)
break;
case EXEC_OMP_FLUSH:
- gfc_free_namelist (p->ext.omp_namelist);
+ gfc_free_omp_namelist (p->ext.omp_namelist);
break;
case EXEC_OMP_ATOMIC:
@@ -211,6 +216,7 @@ gfc_free_statement (gfc_code *p)
case EXEC_OMP_MASTER:
case EXEC_OMP_ORDERED:
case EXEC_OMP_END_NOWAIT:
+ case EXEC_OMP_TASKGROUP:
case EXEC_OMP_TASKWAIT:
case EXEC_OMP_TASKYIELD:
break;
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index 19d792e0862..3785c2e18eb 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -3468,6 +3468,7 @@ gfc_free_namespace (gfc_namespace *ns)
free_tb_tree (ns->tb_sym_root);
free_tb_tree (ns->tb_uop_root);
gfc_free_finalizer_list (ns->finalizers);
+ gfc_free_omp_declare_simd_list (ns->omp_declare_simd);
gfc_free_charlen (ns->cl_list, NULL);
free_st_labels (ns->st_labels);
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index bb648f05891..5255969c84c 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -5405,7 +5405,6 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
gfc_conv_structure (&se, expr, 1);
wtmp = wi::to_offset (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1;
- gcc_assert (wtmp != 0);
/* This will probably eat buckets of memory for large arrays. */
while (wtmp != 0)
{
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index bd1ebab46b2..db468589fcb 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -131,6 +131,9 @@ tree gfor_fndecl_caf_sync_all;
tree gfor_fndecl_caf_sync_images;
tree gfor_fndecl_caf_error_stop;
tree gfor_fndecl_caf_error_stop_str;
+tree gfor_fndecl_co_max;
+tree gfor_fndecl_co_min;
+tree gfor_fndecl_co_sum;
/* Math functions. Many other math functions are handled in
@@ -612,8 +615,7 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
void
gfc_allocate_lang_decl (tree decl)
{
- DECL_LANG_SPECIFIC (decl) = ggc_alloc_cleared_lang_decl(sizeof
- (struct lang_decl));
+ DECL_LANG_SPECIFIC (decl) = ggc_cleared_alloc<struct lang_decl> ();
}
/* Remember a symbol to generate initialization/cleanup code at function
@@ -1847,6 +1849,11 @@ module_sym:
if (DECL_CONTEXT (fndecl) == NULL_TREE)
pushdecl_top_level (fndecl);
+ if (sym->formal_ns
+ && sym->formal_ns->proc_name == sym
+ && sym->formal_ns->omp_declare_simd)
+ gfc_trans_omp_declare_simd (sym->formal_ns);
+
return fndecl;
}
@@ -2552,6 +2559,9 @@ gfc_create_function_decl (gfc_namespace * ns, bool global)
/* Now create the read argument list. */
create_function_arglist (ns->proc_name);
+
+ if (ns->omp_declare_simd)
+ gfc_trans_omp_declare_simd (ns);
}
/* Return the decl used to hold the function return value. If
@@ -3250,7 +3260,7 @@ gfc_build_builtin_function_decls (void)
gfor_fndecl_caf_init = gfc_build_library_function_decl (
get_identifier (PREFIX("caf_init")), void_type_node,
- 4, pint_type, pppchar_type, pint_type, pint_type);
+ 2, pint_type, pppchar_type);
gfor_fndecl_caf_finalize = gfc_build_library_function_decl (
get_identifier (PREFIX("caf_finalize")), void_type_node, 0);
@@ -3261,7 +3271,7 @@ gfc_build_builtin_function_decls (void)
gfor_fndecl_caf_num_images = gfc_build_library_function_decl (
get_identifier (PREFIX("caf_num_images")), integer_type_node,
- 2, integer_type_node, boolean_type_node);
+ 2, integer_type_node, integer_type_node);
gfor_fndecl_caf_register = gfc_build_library_function_decl_with_spec (
get_identifier (PREFIX("caf_register")), "...WWW", pvoid_type_node, 6,
@@ -3280,12 +3290,12 @@ gfc_build_builtin_function_decls (void)
gfor_fndecl_caf_sync_all = gfc_build_library_function_decl_with_spec (
get_identifier (PREFIX("caf_sync_all")), ".WW", void_type_node,
- 3, pint_type, build_pointer_type (pchar_type_node), integer_type_node);
+ 3, pint_type, pchar_type_node, integer_type_node);
gfor_fndecl_caf_sync_images = gfc_build_library_function_decl_with_spec (
get_identifier (PREFIX("caf_sync_images")), ".RRWW", void_type_node,
5, integer_type_node, pint_type, pint_type,
- build_pointer_type (pchar_type_node), integer_type_node);
+ pchar_type_node, integer_type_node);
gfor_fndecl_caf_error_stop = gfc_build_library_function_decl (
get_identifier (PREFIX("caf_error_stop")),
@@ -3298,6 +3308,21 @@ gfc_build_builtin_function_decls (void)
void_type_node, 2, pchar_type_node, gfc_int4_type_node);
/* CAF's ERROR STOP doesn't return. */
TREE_THIS_VOLATILE (gfor_fndecl_caf_error_stop_str) = 1;
+
+ gfor_fndecl_co_max = gfc_build_library_function_decl_with_spec (
+ get_identifier (PREFIX("caf_co_max")), "WR.WW",
+ void_type_node, 7, pvoid_type_node, pvoid_type_node, integer_type_node,
+ pint_type, pchar_type_node, integer_type_node, integer_type_node);
+
+ gfor_fndecl_co_min = gfc_build_library_function_decl_with_spec (
+ get_identifier (PREFIX("caf_co_min")), "WR.WW",
+ void_type_node, 7, pvoid_type_node, pvoid_type_node, integer_type_node,
+ pint_type, pchar_type_node, integer_type_node, integer_type_node);
+
+ gfor_fndecl_co_sum = gfc_build_library_function_decl_with_spec (
+ get_identifier (PREFIX("caf_co_sum")), "WR.WW",
+ void_type_node, 6, pvoid_type_node, pvoid_type_node, integer_type_node,
+ pint_type, pchar_type_node, integer_type_node);
}
gfc_build_intrinsic_function_decls ();
@@ -4134,7 +4159,7 @@ gfc_find_module (const char *name)
htab_hash_string (name), INSERT);
if (*slot == NULL)
{
- struct module_htab_entry *entry = ggc_alloc_cleared_module_htab_entry ();
+ module_htab_entry *entry = ggc_cleared_alloc<module_htab_entry> ();
entry->name = gfc_get_string (name);
entry->decls = htab_create_ggc (10, module_htab_decls_hash,
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index c166c4f0bcf..a76d0f75cc1 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -934,15 +934,30 @@ trans_this_image (gfc_se * se, gfc_expr *expr)
lbound, ubound, extent, ml;
gfc_se argse;
int rank, corank;
+ gfc_expr *distance = expr->value.function.actual->next->next->expr;
+
+ if (expr->value.function.actual->expr
+ && !gfc_is_coarray (expr->value.function.actual->expr))
+ distance = expr->value.function.actual->expr;
/* The case -fcoarray=single is handled elsewhere. */
gcc_assert (gfc_option.coarray != GFC_FCOARRAY_SINGLE);
/* Argument-free version: THIS_IMAGE(). */
- if (expr->value.function.actual->expr == NULL)
+ if (distance || expr->value.function.actual->expr == NULL)
{
+ if (distance)
+ {
+ gfc_init_se (&argse, NULL);
+ gfc_conv_expr_val (&argse, distance);
+ gfc_add_block_to_block (&se->pre, &argse.pre);
+ gfc_add_block_to_block (&se->post, &argse.post);
+ tmp = fold_convert (integer_type_node, argse.expr);
+ }
+ else
+ tmp = integer_zero_node;
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
- integer_zero_node);
+ tmp);
se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind),
tmp);
return;
@@ -1262,11 +1277,35 @@ trans_image_index (gfc_se * se, gfc_expr *expr)
static void
-trans_num_images (gfc_se * se)
+trans_num_images (gfc_se * se, gfc_expr *expr)
{
- tree tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
- integer_zero_node,
- build_int_cst (integer_type_node, -1));
+ tree tmp, distance, failed;
+ gfc_se argse;
+
+ if (expr->value.function.actual->expr)
+ {
+ gfc_init_se (&argse, NULL);
+ gfc_conv_expr_val (&argse, expr->value.function.actual->expr);
+ gfc_add_block_to_block (&se->pre, &argse.pre);
+ gfc_add_block_to_block (&se->post, &argse.post);
+ distance = fold_convert (integer_type_node, argse.expr);
+ }
+ else
+ distance = integer_zero_node;
+
+ if (expr->value.function.actual->next->expr)
+ {
+ gfc_init_se (&argse, NULL);
+ gfc_conv_expr_val (&argse, expr->value.function.actual->next->expr);
+ gfc_add_block_to_block (&se->pre, &argse.pre);
+ gfc_add_block_to_block (&se->post, &argse.post);
+ failed = fold_convert (integer_type_node, argse.expr);
+ }
+ else
+ failed = build_int_cst (integer_type_node, -1);
+
+ tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images, 2,
+ distance, failed);
se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
}
@@ -7099,7 +7138,7 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
break;
case GFC_ISYM_NUM_IMAGES:
- trans_num_images (se);
+ trans_num_images (se, expr);
break;
case GFC_ISYM_ACCESS:
@@ -7509,6 +7548,123 @@ gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
static tree
+conv_co_minmaxsum (gfc_code *code)
+{
+ gfc_se argse;
+ stmtblock_t block, post_block;
+ tree fndecl, array, vec, strlen, image_index, stat, errmsg, errmsg_len;
+
+ gfc_start_block (&block);
+ gfc_init_block (&post_block);
+
+ /* stat. */
+ if (code->ext.actual->next->next->expr)
+ {
+ gfc_init_se (&argse, NULL);
+ gfc_conv_expr (&argse, code->ext.actual->next->next->expr);
+ gfc_add_block_to_block (&block, &argse.pre);
+ gfc_add_block_to_block (&post_block, &argse.post);
+ stat = argse.expr;
+ if (gfc_option.coarray != GFC_FCOARRAY_SINGLE)
+ stat = gfc_build_addr_expr (NULL_TREE, stat);
+ }
+ else if (gfc_option.coarray == GFC_FCOARRAY_SINGLE)
+ stat = NULL_TREE;
+ else
+ stat = null_pointer_node;
+
+ /* Early exit for GFC_FCOARRAY_SINGLE. */
+ if (gfc_option.coarray == GFC_FCOARRAY_SINGLE)
+ {
+ if (stat != NULL_TREE)
+ gfc_add_modify (&block, stat,
+ fold_convert (TREE_TYPE (stat), integer_zero_node));
+ return gfc_finish_block (&block);
+ }
+
+ /* Handle the array. */
+ gfc_init_se (&argse, NULL);
+ if (code->ext.actual->expr->rank == 0)
+ {
+ symbol_attribute attr;
+ gfc_clear_attr (&attr);
+ gfc_init_se (&argse, NULL);
+ gfc_conv_expr (&argse, code->ext.actual->expr);
+ gfc_add_block_to_block (&block, &argse.pre);
+ gfc_add_block_to_block (&post_block, &argse.post);
+ array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr);
+ array = gfc_build_addr_expr (NULL_TREE, array);
+ }
+ else
+ {
+ argse.want_pointer = 1;
+ gfc_conv_expr_descriptor (&argse, code->ext.actual->expr);
+ array = argse.expr;
+ }
+ gfc_add_block_to_block (&block, &argse.pre);
+ gfc_add_block_to_block (&post_block, &argse.post);
+
+ if (code->ext.actual->expr->ts.type == BT_CHARACTER)
+ strlen = argse.string_length;
+ else
+ strlen = integer_zero_node;
+
+ vec = null_pointer_node;
+
+ /* image_index. */
+ if (code->ext.actual->next->expr)
+ {
+ gfc_init_se (&argse, NULL);
+ gfc_conv_expr (&argse, code->ext.actual->next->expr);
+ gfc_add_block_to_block (&block, &argse.pre);
+ gfc_add_block_to_block (&post_block, &argse.post);
+ image_index = fold_convert (integer_type_node, argse.expr);
+ }
+ else
+ image_index = integer_zero_node;
+
+ /* errmsg. */
+ if (code->ext.actual->next->next->next->expr)
+ {
+ gfc_init_se (&argse, NULL);
+ gfc_conv_expr (&argse, code->ext.actual->next->next->next->expr);
+ gfc_add_block_to_block (&block, &argse.pre);
+ gfc_add_block_to_block (&post_block, &argse.post);
+ errmsg = argse.expr;
+ errmsg_len = fold_convert (integer_type_node, argse.string_length);
+ }
+ else
+ {
+ errmsg = null_pointer_node;
+ errmsg_len = integer_zero_node;
+ }
+
+ /* Generate the function call. */
+ if (code->resolved_isym->id == GFC_ISYM_CO_MAX)
+ fndecl = gfor_fndecl_co_max;
+ else if (code->resolved_isym->id == GFC_ISYM_CO_MIN)
+ fndecl = gfor_fndecl_co_min;
+ else if (code->resolved_isym->id == GFC_ISYM_CO_SUM)
+ fndecl = gfor_fndecl_co_sum;
+ else
+ gcc_unreachable ();
+
+ if (code->resolved_isym->id == GFC_ISYM_CO_SUM)
+ fndecl = build_call_expr_loc (input_location, fndecl, 6, array, vec,
+ image_index, stat, errmsg, errmsg_len);
+ else
+ fndecl = build_call_expr_loc (input_location, fndecl, 7, array, vec,
+ image_index, stat, errmsg, strlen,
+ errmsg_len);
+ gfc_add_expr_to_block (&block, fndecl);
+ gfc_add_block_to_block (&block, &post_block);
+
+ /* Add CALL to CO_SUM/MIN/MAX: array descriptor, vector descriptor, stat, errmsg, strlen, errmsglen */
+ return gfc_finish_block (&block);
+}
+
+
+static tree
conv_intrinsic_atomic_def (gfc_code *code)
{
gfc_se atom, value;
@@ -7803,6 +7959,11 @@ gfc_conv_intrinsic_subroutine (gfc_code *code)
res = conv_isocbinding_subroutine (code);
break;
+ case GFC_ISYM_CO_MIN:
+ case GFC_ISYM_CO_MAX:
+ case GFC_ISYM_CO_SUM:
+ res = conv_co_minmaxsum (code);
+ break;
default:
res = NULL_TREE;
diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c
index d15159857d0..fb6f69fa49c 100644
--- a/gcc/fortran/trans-io.c
+++ b/gcc/fortran/trans-io.c
@@ -1452,10 +1452,10 @@ gfc_trans_wait (gfc_code * code)
/* nml_full_name builds up the fully qualified name of a
- derived type component. */
+ derived type component. '+' is used to denote a type extension. */
static char*
-nml_full_name (const char* var_name, const char* cmp_name)
+nml_full_name (const char* var_name, const char* cmp_name, bool parent)
{
int full_name_length;
char * full_name;
@@ -1463,7 +1463,7 @@ nml_full_name (const char* var_name, const char* cmp_name)
full_name_length = strlen (var_name) + strlen (cmp_name) + 1;
full_name = XCNEWVEC (char, full_name_length + 1);
strcpy (full_name, var_name);
- full_name = strcat (full_name, "%");
+ full_name = strcat (full_name, parent ? "+" : "%");
full_name = strcat (full_name, cmp_name);
return full_name;
}
@@ -1634,7 +1634,8 @@ transfer_namelist_element (stmtblock_t * block, const char * var_name,
for (cmp = ts->u.derived->components; cmp; cmp = cmp->next)
{
- char *full_name = nml_full_name (var_name, cmp->name);
+ char *full_name = nml_full_name (var_name, cmp->name,
+ ts->u.derived->attr.extension);
transfer_namelist_element (block,
full_name,
NULL, cmp, expr);
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 41020a836a7..101dfe5594e 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -427,8 +427,33 @@ gfc_trans_add_clause (tree node, tree tail)
}
static tree
-gfc_trans_omp_variable (gfc_symbol *sym)
+gfc_trans_omp_variable (gfc_symbol *sym, bool declare_simd)
{
+ if (declare_simd)
+ {
+ int cnt = 0;
+ gfc_symbol *proc_sym;
+ gfc_formal_arglist *f;
+
+ gcc_assert (sym->attr.dummy);
+ proc_sym = sym->ns->proc_name;
+ if (proc_sym->attr.entry_master)
+ ++cnt;
+ if (gfc_return_by_reference (proc_sym))
+ {
+ ++cnt;
+ if (proc_sym->ts.type == BT_CHARACTER)
+ ++cnt;
+ }
+ for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next)
+ if (f->sym == sym)
+ break;
+ else if (f->sym)
+ ++cnt;
+ gcc_assert (f);
+ return build_int_cst (integer_type_node, cnt);
+ }
+
tree t = gfc_get_symbol_decl (sym);
tree parent_decl;
int parent_flag;
@@ -442,7 +467,8 @@ gfc_trans_omp_variable (gfc_symbol *sym)
entry_master = sym->attr.result
&& sym->ns->proc_name->attr.entry_master
&& !gfc_return_by_reference (sym->ns->proc_name);
- parent_decl = DECL_CONTEXT (current_function_decl);
+ parent_decl = current_function_decl
+ ? DECL_CONTEXT (current_function_decl) : NULL_TREE;
if ((t == parent_decl && return_value)
|| (sym->ns && sym->ns->proc_name
@@ -481,13 +507,14 @@ gfc_trans_omp_variable (gfc_symbol *sym)
}
static tree
-gfc_trans_omp_variable_list (enum omp_clause_code code, gfc_namelist *namelist,
- tree list)
+gfc_trans_omp_variable_list (enum omp_clause_code code,
+ gfc_omp_namelist *namelist, tree list,
+ bool declare_simd)
{
for (; namelist != NULL; namelist = namelist->next)
- if (namelist->sym->attr.referenced)
+ if (namelist->sym->attr.referenced || declare_simd)
{
- tree t = gfc_trans_omp_variable (namelist->sym);
+ tree t = gfc_trans_omp_variable (namelist->sym, declare_simd);
if (t != error_mark_node)
{
tree node = build_omp_clause (input_location, code);
@@ -745,13 +772,13 @@ gfc_trans_omp_array_reduction (tree c, gfc_symbol *sym, locus where)
}
static tree
-gfc_trans_omp_reduction_list (gfc_namelist *namelist, tree list,
+gfc_trans_omp_reduction_list (gfc_omp_namelist *namelist, tree list,
enum tree_code reduction_code, locus where)
{
for (; namelist != NULL; namelist = namelist->next)
if (namelist->sym->attr.referenced)
{
- tree t = gfc_trans_omp_variable (namelist->sym);
+ tree t = gfc_trans_omp_variable (namelist->sym, false);
if (t != error_mark_node)
{
tree node = build_omp_clause (where.lb->location,
@@ -768,7 +795,7 @@ gfc_trans_omp_reduction_list (gfc_namelist *namelist, tree list,
static tree
gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
- locus where)
+ locus where, bool declare_simd = false)
{
tree omp_clauses = NULL_TREE, chunk_size, c;
int list;
@@ -780,7 +807,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
for (list = 0; list < OMP_LIST_NUM; list++)
{
- gfc_namelist *n = clauses->lists[list];
+ gfc_omp_namelist *n = clauses->lists[list];
if (n == NULL)
continue;
@@ -853,10 +880,125 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
goto add_clause;
case OMP_LIST_COPYPRIVATE:
clause_code = OMP_CLAUSE_COPYPRIVATE;
+ goto add_clause;
+ case OMP_LIST_UNIFORM:
+ clause_code = OMP_CLAUSE_UNIFORM;
/* FALLTHROUGH */
add_clause:
omp_clauses
- = gfc_trans_omp_variable_list (clause_code, n, omp_clauses);
+ = gfc_trans_omp_variable_list (clause_code, n, omp_clauses,
+ declare_simd);
+ break;
+ case OMP_LIST_ALIGNED:
+ for (; n != NULL; n = n->next)
+ if (n->sym->attr.referenced || declare_simd)
+ {
+ tree t = gfc_trans_omp_variable (n->sym, declare_simd);
+ if (t != error_mark_node)
+ {
+ tree node = build_omp_clause (input_location,
+ OMP_CLAUSE_ALIGNED);
+ OMP_CLAUSE_DECL (node) = t;
+ if (n->expr)
+ {
+ tree alignment_var;
+
+ if (block == NULL)
+ alignment_var = gfc_conv_constant_to_tree (n->expr);
+ else
+ {
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, n->expr);
+ gfc_add_block_to_block (block, &se.pre);
+ alignment_var = gfc_evaluate_now (se.expr, block);
+ gfc_add_block_to_block (block, &se.post);
+ }
+ OMP_CLAUSE_ALIGNED_ALIGNMENT (node) = alignment_var;
+ }
+ omp_clauses = gfc_trans_add_clause (node, omp_clauses);
+ }
+ }
+ break;
+ case OMP_LIST_LINEAR:
+ {
+ gfc_expr *last_step_expr = NULL;
+ tree last_step = NULL_TREE;
+
+ for (; n != NULL; n = n->next)
+ {
+ if (n->expr)
+ {
+ last_step_expr = n->expr;
+ last_step = NULL_TREE;
+ }
+ if (n->sym->attr.referenced || declare_simd)
+ {
+ tree t = gfc_trans_omp_variable (n->sym, declare_simd);
+ if (t != error_mark_node)
+ {
+ tree node = build_omp_clause (input_location,
+ OMP_CLAUSE_LINEAR);
+ OMP_CLAUSE_DECL (node) = t;
+ if (last_step_expr && last_step == NULL_TREE)
+ {
+ if (block == NULL)
+ last_step
+ = gfc_conv_constant_to_tree (last_step_expr);
+ else
+ {
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, last_step_expr);
+ gfc_add_block_to_block (block, &se.pre);
+ last_step = gfc_evaluate_now (se.expr, block);
+ gfc_add_block_to_block (block, &se.post);
+ }
+ }
+ OMP_CLAUSE_LINEAR_STEP (node) = last_step;
+ omp_clauses = gfc_trans_add_clause (node, omp_clauses);
+ }
+ }
+ }
+ }
+ break;
+ case OMP_LIST_DEPEND_IN:
+ case OMP_LIST_DEPEND_OUT:
+ for (; n != NULL; n = n->next)
+ {
+ if (!n->sym->attr.referenced)
+ continue;
+
+ tree node = build_omp_clause (input_location, OMP_CLAUSE_DEPEND);
+ if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
+ {
+ OMP_CLAUSE_DECL (node) = gfc_get_symbol_decl (n->sym);
+ if (DECL_P (OMP_CLAUSE_DECL (node)))
+ TREE_ADDRESSABLE (OMP_CLAUSE_DECL (node)) = 1;
+ }
+ else
+ {
+ tree ptr;
+ gfc_init_se (&se, NULL);
+ if (n->expr->ref->u.ar.type == AR_ELEMENT)
+ {
+ gfc_conv_expr_reference (&se, n->expr);
+ ptr = se.expr;
+ }
+ else
+ {
+ gfc_conv_expr_descriptor (&se, n->expr);
+ ptr = gfc_conv_array_data (se.expr);
+ }
+ gfc_add_block_to_block (block, &se.pre);
+ gfc_add_block_to_block (block, &se.post);
+ OMP_CLAUSE_DECL (node)
+ = fold_build1_loc (input_location, INDIRECT_REF,
+ TREE_TYPE (TREE_TYPE (ptr)), ptr);
+ }
+ OMP_CLAUSE_DEPEND_KIND (node)
+ = ((list == OMP_LIST_DEPEND_IN)
+ ? OMP_CLAUSE_DEPEND_IN : OMP_CLAUSE_DEPEND_OUT);
+ omp_clauses = gfc_trans_add_clause (node, omp_clauses);
+ }
break;
default:
break;
@@ -1000,6 +1142,83 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
+ if (clauses->inbranch)
+ {
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_INBRANCH);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
+ if (clauses->notinbranch)
+ {
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_NOTINBRANCH);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
+ switch (clauses->cancel)
+ {
+ case OMP_CANCEL_UNKNOWN:
+ break;
+ case OMP_CANCEL_PARALLEL:
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_PARALLEL);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ break;
+ case OMP_CANCEL_SECTIONS:
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_SECTIONS);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ break;
+ case OMP_CANCEL_DO:
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_FOR);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ break;
+ case OMP_CANCEL_TASKGROUP:
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_TASKGROUP);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ break;
+ }
+
+ if (clauses->proc_bind != OMP_PROC_BIND_UNKNOWN)
+ {
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_PROC_BIND);
+ switch (clauses->proc_bind)
+ {
+ case OMP_PROC_BIND_MASTER:
+ OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_MASTER;
+ break;
+ case OMP_PROC_BIND_SPREAD:
+ OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_SPREAD;
+ break;
+ case OMP_PROC_BIND_CLOSE:
+ OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_CLOSE;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
+ if (clauses->safelen_expr)
+ {
+ tree safelen_var;
+
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, clauses->safelen_expr);
+ gfc_add_block_to_block (block, &se.pre);
+ safelen_var = gfc_evaluate_now (se.expr, block);
+ gfc_add_block_to_block (block, &se.post);
+
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_SAFELEN);
+ OMP_CLAUSE_SAFELEN_EXPR (c) = safelen_var;
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
+ if (clauses->simdlen_expr)
+ {
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_SIMDLEN);
+ OMP_CLAUSE_SIMDLEN_EXPR (c)
+ = gfc_conv_constant_to_tree (clauses->simdlen_expr);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
return omp_clauses;
}
@@ -1045,6 +1264,7 @@ gfc_trans_omp_atomic (gfc_code *code)
enum tree_code op = ERROR_MARK;
enum tree_code aop = OMP_ATOMIC;
bool var_on_left = false;
+ bool seq_cst = (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SEQ_CST) != 0;
code = code->block->next;
gcc_assert (code->op == EXEC_ASSIGN);
@@ -1060,7 +1280,7 @@ gfc_trans_omp_atomic (gfc_code *code)
&& expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
expr2 = expr2->value.function.actual->expr;
- switch (atomic_code->ext.omp_atomic)
+ switch (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
{
case GFC_OMP_ATOMIC_READ:
gfc_conv_expr (&vse, code->expr1);
@@ -1072,6 +1292,7 @@ gfc_trans_omp_atomic (gfc_code *code)
lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
x = build1 (OMP_ATOMIC_READ, type, lhsaddr);
+ OMP_ATOMIC_SEQ_CST (x) = seq_cst;
x = convert (TREE_TYPE (vse.expr), x);
gfc_add_modify (&block, vse.expr, x);
@@ -1107,7 +1328,9 @@ gfc_trans_omp_atomic (gfc_code *code)
type = TREE_TYPE (lse.expr);
lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
- if (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_WRITE)
+ if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
+ == GFC_OMP_ATOMIC_WRITE)
+ || (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP))
{
gfc_conv_expr (&rse, expr2);
gfc_add_block_to_block (&block, &rse.pre);
@@ -1229,7 +1452,9 @@ gfc_trans_omp_atomic (gfc_code *code)
lhsaddr = save_expr (lhsaddr);
rhs = gfc_evaluate_now (rse.expr, &block);
- if (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_WRITE)
+ if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
+ == GFC_OMP_ATOMIC_WRITE)
+ || (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP))
x = rhs;
else
{
@@ -1252,6 +1477,7 @@ gfc_trans_omp_atomic (gfc_code *code)
if (aop == OMP_ATOMIC)
{
x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
+ OMP_ATOMIC_SEQ_CST (x) = seq_cst;
gfc_add_expr_to_block (&block, x);
}
else
@@ -1273,6 +1499,7 @@ gfc_trans_omp_atomic (gfc_code *code)
gfc_add_block_to_block (&block, &lse.pre);
}
x = build2 (aop, type, lhsaddr, convert (type, x));
+ OMP_ATOMIC_SEQ_CST (x) = seq_cst;
x = convert (TREE_TYPE (vse.expr), x);
gfc_add_modify (&block, vse.expr, x);
}
@@ -1288,6 +1515,63 @@ gfc_trans_omp_barrier (void)
}
static tree
+gfc_trans_omp_cancel (gfc_code *code)
+{
+ int mask = 0;
+ tree ifc = boolean_true_node;
+ stmtblock_t block;
+ switch (code->ext.omp_clauses->cancel)
+ {
+ case OMP_CANCEL_PARALLEL: mask = 1; break;
+ case OMP_CANCEL_DO: mask = 2; break;
+ case OMP_CANCEL_SECTIONS: mask = 4; break;
+ case OMP_CANCEL_TASKGROUP: mask = 8; break;
+ default: gcc_unreachable ();
+ }
+ gfc_start_block (&block);
+ if (code->ext.omp_clauses->if_expr)
+ {
+ gfc_se se;
+ tree if_var;
+
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, code->ext.omp_clauses->if_expr);
+ gfc_add_block_to_block (&block, &se.pre);
+ if_var = gfc_evaluate_now (se.expr, &block);
+ gfc_add_block_to_block (&block, &se.post);
+ tree type = TREE_TYPE (if_var);
+ ifc = fold_build2_loc (input_location, NE_EXPR,
+ boolean_type_node, if_var,
+ build_zero_cst (type));
+ }
+ tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
+ tree c_bool_type = TREE_TYPE (TREE_TYPE (decl));
+ ifc = fold_convert (c_bool_type, ifc);
+ gfc_add_expr_to_block (&block,
+ build_call_expr_loc (input_location, decl, 2,
+ build_int_cst (integer_type_node,
+ mask), ifc));
+ return gfc_finish_block (&block);
+}
+
+static tree
+gfc_trans_omp_cancellation_point (gfc_code *code)
+{
+ int mask = 0;
+ switch (code->ext.omp_clauses->cancel)
+ {
+ case OMP_CANCEL_PARALLEL: mask = 1; break;
+ case OMP_CANCEL_DO: mask = 2; break;
+ case OMP_CANCEL_SECTIONS: mask = 4; break;
+ case OMP_CANCEL_TASKGROUP: mask = 8; break;
+ default: gcc_unreachable ();
+ }
+ tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
+ return build_call_expr_loc (input_location, decl, 1,
+ build_int_cst (integer_type_node, mask));
+}
+
+static tree
gfc_trans_omp_critical (gfc_code *code)
{
tree name = NULL_TREE, stmt;
@@ -1304,7 +1588,7 @@ typedef struct dovar_init_d {
static tree
-gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
+gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
gfc_omp_clauses *do_clauses, tree par_clauses)
{
gfc_se se;
@@ -1344,14 +1628,15 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
if (clauses)
{
- gfc_namelist *n;
- for (n = clauses->lists[OMP_LIST_LASTPRIVATE]; n != NULL;
- n = n->next)
+ gfc_omp_namelist *n;
+ for (n = clauses->lists[(op == EXEC_OMP_SIMD && collapse == 1)
+ ? OMP_LIST_LINEAR : OMP_LIST_LASTPRIVATE];
+ n != NULL; n = n->next)
if (code->ext.iterator->var->symtree->n.sym == n->sym)
break;
if (n != NULL)
dovar_found = 1;
- else if (n == NULL)
+ else if (n == NULL && op != EXEC_OMP_SIMD)
for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
if (code->ext.iterator->var->symtree->n.sym == n->sym)
break;
@@ -1393,7 +1678,8 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
}
else
dovar_decl
- = gfc_trans_omp_variable (code->ext.iterator->var->symtree->n.sym);
+ = gfc_trans_omp_variable (code->ext.iterator->var->symtree->n.sym,
+ false);
/* Loop body. */
if (simple)
@@ -1447,11 +1733,24 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
if (!dovar_found)
{
- tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
+ if (op == EXEC_OMP_SIMD)
+ {
+ if (collapse == 1)
+ {
+ tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
+ OMP_CLAUSE_LINEAR_STEP (tmp) = step;
+ }
+ else
+ tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
+ if (!simple)
+ dovar_found = 2;
+ }
+ else
+ tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
OMP_CLAUSE_DECL (tmp) = dovar_decl;
omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
}
- else if (dovar_found == 2)
+ if (dovar_found == 2)
{
tree c = NULL;
@@ -1475,8 +1774,14 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
OMP_CLAUSE_LASTPRIVATE_STMT (c) = tmp;
break;
}
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
+ && OMP_CLAUSE_DECL (c) == dovar_decl)
+ {
+ OMP_CLAUSE_LINEAR_STMT (c) = tmp;
+ break;
+ }
}
- if (c == NULL && par_clauses != NULL)
+ if (c == NULL && op == EXEC_OMP_DO && par_clauses != NULL)
{
for (c = par_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
@@ -1496,7 +1801,17 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
}
if (!simple)
{
- tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
+ if (op != EXEC_OMP_SIMD)
+ tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
+ else if (collapse == 1)
+ {
+ tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
+ OMP_CLAUSE_LINEAR_STEP (tmp) = step;
+ OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
+ OMP_CLAUSE_LINEAR_NO_COPYOUT (tmp) = 1;
+ }
+ else
+ tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
OMP_CLAUSE_DECL (tmp) = count;
omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
}
@@ -1538,7 +1853,7 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
}
/* End of loop body. */
- stmt = make_node (OMP_FOR);
+ stmt = make_node (op == EXEC_OMP_SIMD ? OMP_SIMD : OMP_FOR);
TREE_TYPE (stmt) = void_type_node;
OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
@@ -1589,37 +1904,219 @@ gfc_trans_omp_parallel (gfc_code *code)
return gfc_finish_block (&block);
}
+enum
+{
+ GFC_OMP_SPLIT_SIMD,
+ GFC_OMP_SPLIT_DO,
+ GFC_OMP_SPLIT_PARALLEL,
+ GFC_OMP_SPLIT_NUM
+};
+
+enum
+{
+ GFC_OMP_MASK_SIMD = (1 << GFC_OMP_SPLIT_SIMD),
+ GFC_OMP_MASK_DO = (1 << GFC_OMP_SPLIT_DO),
+ GFC_OMP_MASK_PARALLEL = (1 << GFC_OMP_SPLIT_PARALLEL)
+};
+
+static void
+gfc_split_omp_clauses (gfc_code *code,
+ gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])
+{
+ int mask = 0, innermost = 0, i;
+ memset (clausesa, 0, GFC_OMP_SPLIT_NUM * sizeof (gfc_omp_clauses));
+ switch (code->op)
+ {
+ case EXEC_OMP_DO_SIMD:
+ mask = GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
+ innermost = GFC_OMP_SPLIT_SIMD;
+ break;
+ case EXEC_OMP_PARALLEL_DO:
+ mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
+ innermost = GFC_OMP_SPLIT_DO;
+ break;
+ case EXEC_OMP_PARALLEL_DO_SIMD:
+ mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
+ innermost = GFC_OMP_SPLIT_SIMD;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (code->ext.omp_clauses != NULL)
+ {
+ if (mask & GFC_OMP_MASK_PARALLEL)
+ {
+ /* First the clauses that are unique to some constructs. */
+ clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_COPYIN]
+ = code->ext.omp_clauses->lists[OMP_LIST_COPYIN];
+ clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads
+ = code->ext.omp_clauses->num_threads;
+ clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind
+ = code->ext.omp_clauses->proc_bind;
+ /* Shared and default clauses are allowed on parallel and teams. */
+ clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_SHARED]
+ = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
+ clausesa[GFC_OMP_SPLIT_PARALLEL].default_sharing
+ = code->ext.omp_clauses->default_sharing;
+ /* FIXME: This is currently being discussed. */
+ clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
+ = code->ext.omp_clauses->if_expr;
+ }
+ if (mask & GFC_OMP_MASK_DO)
+ {
+ /* First the clauses that are unique to some constructs. */
+ clausesa[GFC_OMP_SPLIT_DO].ordered
+ = code->ext.omp_clauses->ordered;
+ clausesa[GFC_OMP_SPLIT_DO].sched_kind
+ = code->ext.omp_clauses->sched_kind;
+ clausesa[GFC_OMP_SPLIT_DO].chunk_size
+ = code->ext.omp_clauses->chunk_size;
+ clausesa[GFC_OMP_SPLIT_DO].nowait
+ = code->ext.omp_clauses->nowait;
+ /* Duplicate collapse. */
+ clausesa[GFC_OMP_SPLIT_DO].collapse
+ = code->ext.omp_clauses->collapse;
+ }
+ if (mask & GFC_OMP_MASK_SIMD)
+ {
+ clausesa[GFC_OMP_SPLIT_SIMD].safelen_expr
+ = code->ext.omp_clauses->safelen_expr;
+ clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LINEAR]
+ = code->ext.omp_clauses->lists[OMP_LIST_LINEAR];
+ clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_ALIGNED]
+ = code->ext.omp_clauses->lists[OMP_LIST_ALIGNED];
+ /* Duplicate collapse. */
+ clausesa[GFC_OMP_SPLIT_SIMD].collapse
+ = code->ext.omp_clauses->collapse;
+ }
+ /* Private clause is supported on all constructs but target,
+ it is enough to put it on the innermost one. For
+ !$ omp do put it on parallel though,
+ as that's what we did for OpenMP 3.1. */
+ clausesa[innermost == GFC_OMP_SPLIT_DO
+ ? (int) GFC_OMP_SPLIT_PARALLEL
+ : innermost].lists[OMP_LIST_PRIVATE]
+ = code->ext.omp_clauses->lists[OMP_LIST_PRIVATE];
+ /* Firstprivate clause is supported on all constructs but
+ target and simd. Put it on the outermost of those and
+ duplicate on parallel. */
+ if (mask & GFC_OMP_MASK_PARALLEL)
+ clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_FIRSTPRIVATE]
+ = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
+ else if (mask & GFC_OMP_MASK_DO)
+ clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_FIRSTPRIVATE]
+ = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
+ /* Lastprivate is allowed on do and simd. In
+ parallel do{, simd} we actually want to put it on
+ parallel rather than do. */
+ if (mask & GFC_OMP_MASK_PARALLEL)
+ clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_LASTPRIVATE]
+ = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
+ else if (mask & GFC_OMP_MASK_DO)
+ clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_LASTPRIVATE]
+ = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
+ if (mask & GFC_OMP_MASK_SIMD)
+ clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LASTPRIVATE]
+ = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
+ /* Reduction is allowed on simd, do, parallel and teams.
+ Duplicate it on all of them, but omit on do if
+ parallel is present. */
+ for (i = OMP_LIST_REDUCTION_FIRST; i <= OMP_LIST_REDUCTION_LAST; i++)
+ {
+ if (mask & GFC_OMP_MASK_PARALLEL)
+ clausesa[GFC_OMP_SPLIT_PARALLEL].lists[i]
+ = code->ext.omp_clauses->lists[i];
+ else if (mask & GFC_OMP_MASK_DO)
+ clausesa[GFC_OMP_SPLIT_DO].lists[i]
+ = code->ext.omp_clauses->lists[i];
+ if (mask & GFC_OMP_MASK_SIMD)
+ clausesa[GFC_OMP_SPLIT_SIMD].lists[i]
+ = code->ext.omp_clauses->lists[i];
+ }
+ }
+ if ((mask & (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
+ == (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
+ clausesa[GFC_OMP_SPLIT_DO].nowait = true;
+}
+
static tree
-gfc_trans_omp_parallel_do (gfc_code *code)
+gfc_trans_omp_do_simd (gfc_code *code, gfc_omp_clauses *clausesa,
+ tree omp_clauses)
{
stmtblock_t block, *pblock = NULL;
- gfc_omp_clauses parallel_clauses, do_clauses;
- tree stmt, omp_clauses = NULL_TREE;
+ gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
+ tree stmt, body, omp_do_clauses = NULL_TREE;
gfc_start_block (&block);
- memset (&do_clauses, 0, sizeof (do_clauses));
- if (code->ext.omp_clauses != NULL)
+ if (clausesa == NULL)
{
- memcpy (&parallel_clauses, code->ext.omp_clauses,
- sizeof (parallel_clauses));
- do_clauses.sched_kind = parallel_clauses.sched_kind;
- do_clauses.chunk_size = parallel_clauses.chunk_size;
- do_clauses.ordered = parallel_clauses.ordered;
- do_clauses.collapse = parallel_clauses.collapse;
- parallel_clauses.sched_kind = OMP_SCHED_NONE;
- parallel_clauses.chunk_size = NULL;
- parallel_clauses.ordered = false;
- parallel_clauses.collapse = 0;
- omp_clauses = gfc_trans_omp_clauses (&block, &parallel_clauses,
- code->loc);
+ clausesa = clausesa_buf;
+ gfc_split_omp_clauses (code, clausesa);
}
- do_clauses.nowait = true;
- if (!do_clauses.ordered && do_clauses.sched_kind != OMP_SCHED_STATIC)
+ omp_do_clauses
+ = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DO], code->loc);
+ pblock = &block;
+ body = gfc_trans_omp_do (code, EXEC_OMP_SIMD, pblock,
+ &clausesa[GFC_OMP_SPLIT_SIMD], omp_clauses);
+ if (TREE_CODE (body) != BIND_EXPR)
+ body = build3_v (BIND_EXPR, NULL, body, poplevel (1, 0));
+ else
+ poplevel (0, 0);
+ stmt = make_node (OMP_FOR);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_FOR_BODY (stmt) = body;
+ OMP_FOR_CLAUSES (stmt) = omp_do_clauses;
+ gfc_add_expr_to_block (&block, stmt);
+ return gfc_finish_block (&block);
+}
+
+static tree
+gfc_trans_omp_parallel_do (gfc_code *code)
+{
+ stmtblock_t block, *pblock = NULL;
+ gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
+ tree stmt, omp_clauses = NULL_TREE;
+
+ gfc_start_block (&block);
+
+ gfc_split_omp_clauses (code, clausesa);
+ omp_clauses
+ = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
+ code->loc);
+ if (!clausesa[GFC_OMP_SPLIT_DO].ordered
+ && clausesa[GFC_OMP_SPLIT_DO].sched_kind != OMP_SCHED_STATIC)
pblock = &block;
else
pushlevel ();
- stmt = gfc_trans_omp_do (code, pblock, &do_clauses, omp_clauses);
+ stmt = gfc_trans_omp_do (code, EXEC_OMP_DO, pblock,
+ &clausesa[GFC_OMP_SPLIT_DO], omp_clauses);
+ if (TREE_CODE (stmt) != BIND_EXPR)
+ stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
+ else
+ poplevel (0, 0);
+ stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
+ omp_clauses);
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ gfc_add_expr_to_block (&block, stmt);
+ return gfc_finish_block (&block);
+}
+
+static tree
+gfc_trans_omp_parallel_do_simd (gfc_code *code)
+{
+ stmtblock_t block;
+ gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
+ tree stmt, omp_clauses = NULL_TREE;
+
+ gfc_start_block (&block);
+
+ gfc_split_omp_clauses (code, clausesa);
+ omp_clauses
+ = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
+ code->loc);
+ pushlevel ();
+ stmt = gfc_trans_omp_do_simd (code, clausesa, omp_clauses);
if (TREE_CODE (stmt) != BIND_EXPR)
stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
else
@@ -1743,6 +2240,13 @@ gfc_trans_omp_task (gfc_code *code)
}
static tree
+gfc_trans_omp_taskgroup (gfc_code *code)
+{
+ tree stmt = gfc_trans_code (code->block->next);
+ return build1_loc (input_location, OMP_TASKGROUP, void_type_node, stmt);
+}
+
+static tree
gfc_trans_omp_taskwait (void)
{
tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
@@ -1923,10 +2427,18 @@ gfc_trans_omp_directive (gfc_code *code)
return gfc_trans_omp_atomic (code);
case EXEC_OMP_BARRIER:
return gfc_trans_omp_barrier ();
+ case EXEC_OMP_CANCEL:
+ return gfc_trans_omp_cancel (code);
+ case EXEC_OMP_CANCELLATION_POINT:
+ return gfc_trans_omp_cancellation_point (code);
case EXEC_OMP_CRITICAL:
return gfc_trans_omp_critical (code);
case EXEC_OMP_DO:
- return gfc_trans_omp_do (code, NULL, code->ext.omp_clauses, NULL);
+ case EXEC_OMP_SIMD:
+ return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
+ NULL);
+ case EXEC_OMP_DO_SIMD:
+ return gfc_trans_omp_do_simd (code, NULL, NULL_TREE);
case EXEC_OMP_FLUSH:
return gfc_trans_omp_flush ();
case EXEC_OMP_MASTER:
@@ -1937,6 +2449,8 @@ gfc_trans_omp_directive (gfc_code *code)
return gfc_trans_omp_parallel (code);
case EXEC_OMP_PARALLEL_DO:
return gfc_trans_omp_parallel_do (code);
+ case EXEC_OMP_PARALLEL_DO_SIMD:
+ return gfc_trans_omp_parallel_do_simd (code);
case EXEC_OMP_PARALLEL_SECTIONS:
return gfc_trans_omp_parallel_sections (code);
case EXEC_OMP_PARALLEL_WORKSHARE:
@@ -1947,6 +2461,8 @@ gfc_trans_omp_directive (gfc_code *code)
return gfc_trans_omp_single (code, code->ext.omp_clauses);
case EXEC_OMP_TASK:
return gfc_trans_omp_task (code);
+ case EXEC_OMP_TASKGROUP:
+ return gfc_trans_omp_taskgroup (code);
case EXEC_OMP_TASKWAIT:
return gfc_trans_omp_taskwait ();
case EXEC_OMP_TASKYIELD:
@@ -1957,3 +2473,22 @@ gfc_trans_omp_directive (gfc_code *code)
gcc_unreachable ();
}
}
+
+void
+gfc_trans_omp_declare_simd (gfc_namespace *ns)
+{
+ if (ns->entries)
+ return;
+
+ gfc_omp_declare_simd *ods;
+ for (ods = ns->omp_declare_simd; ods; ods = ods->next)
+ {
+ tree c = gfc_trans_omp_clauses (NULL, ods->clauses, ods->where, true);
+ tree fndecl = ns->proc_name->backend_decl;
+ if (c != NULL_TREE)
+ c = tree_cons (NULL_TREE, c, NULL_TREE);
+ c = build_tree_list (get_identifier ("omp declare simd"), c);
+ TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
+ DECL_ATTRIBUTES (fndecl) = c;
+ }
+}
diff --git a/gcc/fortran/trans-stmt.h b/gcc/fortran/trans-stmt.h
index 8a57be4d577..087bafea4b0 100644
--- a/gcc/fortran/trans-stmt.h
+++ b/gcc/fortran/trans-stmt.h
@@ -63,6 +63,7 @@ tree gfc_trans_deallocate_array (tree);
/* trans-openmp.c */
tree gfc_trans_omp_directive (gfc_code *);
+void gfc_trans_omp_declare_simd (gfc_namespace *);
/* trans-io.c */
tree gfc_trans_open (gfc_code *);
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 77d0e785e0b..d9aab474a75 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -1513,8 +1513,7 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
type = build_variant_type_copy (etype);
GFC_ARRAY_TYPE_P (type) = 1;
- TYPE_LANG_SPECIFIC (type)
- = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+ TYPE_LANG_SPECIFIC (type) = ggc_cleared_alloc<struct lang_type> ();
known_stride = (packed != PACKED_NO);
known_offset = 1;
@@ -1816,8 +1815,7 @@ gfc_get_array_type_bounds (tree etype, int dimen, int codimen, tree * lbound,
TYPE_NAMELESS (fat_type) = 1;
GFC_DESCRIPTOR_TYPE_P (fat_type) = 1;
- TYPE_LANG_SPECIFIC (fat_type)
- = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+ TYPE_LANG_SPECIFIC (fat_type) = ggc_cleared_alloc<struct lang_type> ();
GFC_TYPE_ARRAY_RANK (fat_type) = dimen;
GFC_TYPE_ARRAY_CORANK (fat_type) = codimen;
@@ -1991,8 +1989,7 @@ gfc_nonrestricted_type (tree t)
return t;
if (!TYPE_LANG_SPECIFIC (t))
- TYPE_LANG_SPECIFIC (t)
- = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+ TYPE_LANG_SPECIFIC (t) = ggc_cleared_alloc<struct lang_type> ();
/* If we're dealing with this very node already further up
the call chain (recursion via pointers and struct members)
we haven't yet determined if we really need a new type node.
@@ -2044,8 +2041,7 @@ gfc_nonrestricted_type (tree t)
if (dataptr_type != GFC_TYPE_ARRAY_DATAPTR_TYPE (t))
{
TYPE_LANG_SPECIFIC (ret)
- = ggc_alloc_cleared_lang_type (sizeof (struct
- lang_type));
+ = ggc_cleared_alloc<struct lang_type> ();
*TYPE_LANG_SPECIFIC (ret) = *TYPE_LANG_SPECIFIC (t);
GFC_TYPE_ARRAY_DATAPTR_TYPE (ret) = dataptr_type;
}
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 5961c267e8c..cfb8038440b 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -450,13 +450,13 @@ trans_runtime_error_vararg (bool error, locus* where, const char* msgid,
fntype = TREE_TYPE (gfor_fndecl_runtime_warning_at);
loc = where ? where->lb->location : input_location;
- tmp = fold_builtin_call_array (loc, TREE_TYPE (fntype),
- fold_build1_loc (loc, ADDR_EXPR,
+ tmp = fold_build_call_array_loc (loc, TREE_TYPE (fntype),
+ fold_build1_loc (loc, ADDR_EXPR,
build_pointer_type (fntype),
error
? gfor_fndecl_runtime_error_at
: gfor_fndecl_runtime_warning_at),
- nargs + 2, argarray);
+ nargs + 2, argarray);
gfc_add_expr_to_block (&block, tmp);
return gfc_finish_block (&block);
@@ -1848,18 +1848,24 @@ trans_code (gfc_code * code, tree cond)
case EXEC_OMP_ATOMIC:
case EXEC_OMP_BARRIER:
+ case EXEC_OMP_CANCEL:
+ case EXEC_OMP_CANCELLATION_POINT:
case EXEC_OMP_CRITICAL:
case EXEC_OMP_DO:
+ case EXEC_OMP_DO_SIMD:
case EXEC_OMP_FLUSH:
case EXEC_OMP_MASTER:
case EXEC_OMP_ORDERED:
case EXEC_OMP_PARALLEL:
case EXEC_OMP_PARALLEL_DO:
+ case EXEC_OMP_PARALLEL_DO_SIMD:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_PARALLEL_WORKSHARE:
case EXEC_OMP_SECTIONS:
+ case EXEC_OMP_SIMD:
case EXEC_OMP_SINGLE:
case EXEC_OMP_TASK:
+ case EXEC_OMP_TASKGROUP:
case EXEC_OMP_TASKWAIT:
case EXEC_OMP_TASKYIELD:
case EXEC_OMP_WORKSHARE:
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 13b0a000544..def6b9df00c 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -709,6 +709,9 @@ extern GTY(()) tree gfor_fndecl_caf_sync_all;
extern GTY(()) tree gfor_fndecl_caf_sync_images;
extern GTY(()) tree gfor_fndecl_caf_error_stop;
extern GTY(()) tree gfor_fndecl_caf_error_stop_str;
+extern GTY(()) tree gfor_fndecl_co_max;
+extern GTY(()) tree gfor_fndecl_co_min;
+extern GTY(()) tree gfor_fndecl_co_sum;
/* Math functions. Many other math functions are handled in
@@ -790,10 +793,7 @@ enum gfc_array_kind
};
/* Array types only. */
-/* FIXME: the variable_size annotation here is needed because these types are
- variable-sized in some other frontends. Due to gengtype deficiency the GTY
- options of such types have to agree across all frontends. */
-struct GTY((variable_size)) lang_type {
+struct GTY(()) lang_type {
int rank, corank;
enum gfc_array_kind akind;
tree lbound[GFC_MAX_DIMENSIONS];
@@ -810,7 +810,7 @@ struct GTY((variable_size)) lang_type {
tree caf_offset;
};
-struct GTY((variable_size)) lang_decl {
+struct GTY(()) lang_decl {
/* Dummy variables. */
tree saved_descriptor;
/* Assigned integer nodes. Stringlength is the IO format string's length.
diff --git a/gcc/fortran/types.def b/gcc/fortran/types.def
index 78fc679f183..99198e9b7d3 100644
--- a/gcc/fortran/types.def
+++ b/gcc/fortran/types.def
@@ -29,13 +29,7 @@ along with GCC; see the file COPYING3. If not see
DEF_FUNCTION_TYPE_0 (ENUM, RETURN)
DEF_FUNCTION_TYPE_1 (ENUM, RETURN, ARG1)
DEF_FUNCTION_TYPE_2 (ENUM, RETURN, ARG1, ARG2)
- DEF_FUNCTION_TYPE_3 (ENUM, RETURN, ARG1, ARG2, ARG3)
- DEF_FUNCTION_TYPE_4 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4)
- DEF_FUNCTION_TYPE_5 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5)
- DEF_FUNCTION_TYPE_6 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6)
- DEF_FUNCTION_TYPE_7 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7)
- DEF_FUNCTION_TYPE_8 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7,
- ARG8)
+ [...]
These macros describe function types. ENUM is as above. The
RETURN type is one of the enumerals already defined. ARG1, ARG2,
diff --git a/gcc/function.c b/gcc/function.c
index 38ccb133988..ec2ea26628b 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see
#include "df.h"
#include "params.h"
#include "bb-reorder.h"
+#include "shrink-wrap.h"
/* So we can assign to cfun in this file. */
#undef cfun
@@ -306,7 +307,7 @@ try_fit_stack_local (HOST_WIDE_INT start, HOST_WIDE_INT length,
static void
add_frame_space (HOST_WIDE_INT start, HOST_WIDE_INT end)
{
- struct frame_space *space = ggc_alloc_frame_space ();
+ struct frame_space *space = ggc_alloc<frame_space> ();
space->next = crtl->frame_space_list;
crtl->frame_space_list = space;
space->start = start;
@@ -654,7 +655,7 @@ static void
insert_temp_slot_address (rtx address, struct temp_slot *temp_slot)
{
void **slot;
- struct temp_slot_address_entry *t = ggc_alloc_temp_slot_address_entry ();
+ struct temp_slot_address_entry *t = ggc_alloc<temp_slot_address_entry> ();
t->address = address;
t->temp_slot = temp_slot;
t->hash = temp_slot_address_compute_hash (t);
@@ -801,7 +802,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
if (best_p->size - rounded_size >= alignment)
{
- p = ggc_alloc_temp_slot ();
+ p = ggc_alloc<temp_slot> ();
p->in_use = 0;
p->size = best_p->size - rounded_size;
p->base_offset = best_p->base_offset + rounded_size;
@@ -825,7 +826,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
{
HOST_WIDE_INT frame_offset_old = frame_offset;
- p = ggc_alloc_temp_slot ();
+ p = ggc_alloc<temp_slot> ();
/* We are passing an explicit alignment request to assign_stack_local.
One side effect of that is assign_stack_local will not round SIZE
@@ -1253,10 +1254,10 @@ get_hard_reg_initial_val (enum machine_mode mode, unsigned int regno)
ivs = crtl->hard_reg_initial_vals;
if (ivs == 0)
{
- ivs = ggc_alloc_initial_value_struct ();
+ ivs = ggc_alloc<initial_value_struct> ();
ivs->num_entries = 0;
ivs->max_entries = 5;
- ivs->entries = ggc_alloc_vec_initial_value_pair (5);
+ ivs->entries = ggc_vec_alloc<initial_value_pair> (5);
crtl->hard_reg_initial_vals = ivs;
}
@@ -1458,8 +1459,8 @@ instantiate_virtual_regs_in_rtx (rtx *loc, void *data)
new_rtx = instantiate_new_reg (XEXP (x, 0), &offset);
if (new_rtx)
{
- new_rtx = plus_constant (GET_MODE (x), new_rtx, offset);
- *loc = simplify_gen_binary (PLUS, GET_MODE (x), new_rtx, XEXP (x, 1));
+ XEXP (x, 0) = new_rtx;
+ *loc = plus_constant (GET_MODE (x), x, offset, true);
if (changed)
*changed = true;
return -1;
@@ -1621,7 +1622,7 @@ instantiate_virtual_regs_in_insn (rtx insn)
continue;
start_sequence ();
- x = replace_equiv_address (x, addr);
+ x = replace_equiv_address (x, addr, true);
/* It may happen that the address with the virtual reg
was valid (e.g. based on the virtual stack reg, which might
be acceptable to the predicates with all offsets), whereas
@@ -1634,7 +1635,7 @@ instantiate_virtual_regs_in_insn (rtx insn)
if (!safe_insn_predicate (insn_code, i, x))
{
addr = force_reg (GET_MODE (addr), addr);
- x = replace_equiv_address (x, addr);
+ x = replace_equiv_address (x, addr, true);
}
seq = get_insns ();
end_sequence ();
@@ -4498,7 +4499,7 @@ allocate_struct_function (tree fndecl, bool abstract_p)
{
tree fntype = fndecl ? TREE_TYPE (fndecl) : NULL_TREE;
- cfun = ggc_alloc_cleared_function ();
+ cfun = ggc_cleared_alloc<function> ();
init_eh_for_function ();
@@ -4572,7 +4573,7 @@ prepare_function_start (void)
if (flag_stack_usage_info)
{
- cfun->su = ggc_alloc_cleared_stack_usage ();
+ cfun->su = ggc_cleared_alloc<stack_usage> ();
cfun->su->static_stack_size = -1;
}
@@ -5321,265 +5322,6 @@ prologue_epilogue_contains (const_rtx insn)
return 0;
}
-#ifdef HAVE_simple_return
-
-/* Return true if INSN requires the stack frame to be set up.
- PROLOGUE_USED contains the hard registers used in the function
- prologue. SET_UP_BY_PROLOGUE is the set of registers we expect the
- prologue to set up for the function. */
-bool
-requires_stack_frame_p (rtx insn, HARD_REG_SET prologue_used,
- HARD_REG_SET set_up_by_prologue)
-{
- df_ref *df_rec;
- HARD_REG_SET hardregs;
- unsigned regno;
-
- if (CALL_P (insn))
- return !SIBLING_CALL_P (insn);
-
- /* We need a frame to get the unique CFA expected by the unwinder. */
- if (cfun->can_throw_non_call_exceptions && can_throw_internal (insn))
- return true;
-
- CLEAR_HARD_REG_SET (hardregs);
- for (df_rec = DF_INSN_DEFS (insn); *df_rec; df_rec++)
- {
- rtx dreg = DF_REF_REG (*df_rec);
-
- if (!REG_P (dreg))
- continue;
-
- add_to_hard_reg_set (&hardregs, GET_MODE (dreg),
- REGNO (dreg));
- }
- if (hard_reg_set_intersect_p (hardregs, prologue_used))
- return true;
- AND_COMPL_HARD_REG_SET (hardregs, call_used_reg_set);
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- if (TEST_HARD_REG_BIT (hardregs, regno)
- && df_regs_ever_live_p (regno))
- return true;
-
- for (df_rec = DF_INSN_USES (insn); *df_rec; df_rec++)
- {
- rtx reg = DF_REF_REG (*df_rec);
-
- if (!REG_P (reg))
- continue;
-
- add_to_hard_reg_set (&hardregs, GET_MODE (reg),
- REGNO (reg));
- }
- if (hard_reg_set_intersect_p (hardregs, set_up_by_prologue))
- return true;
-
- return false;
-}
-
-/* See whether BB has a single successor that uses [REGNO, END_REGNO),
- and if BB is its only predecessor. Return that block if so,
- otherwise return null. */
-
-static basic_block
-next_block_for_reg (basic_block bb, int regno, int end_regno)
-{
- edge e, live_edge;
- edge_iterator ei;
- bitmap live;
- int i;
-
- live_edge = NULL;
- FOR_EACH_EDGE (e, ei, bb->succs)
- {
- live = df_get_live_in (e->dest);
- for (i = regno; i < end_regno; i++)
- if (REGNO_REG_SET_P (live, i))
- {
- if (live_edge && live_edge != e)
- return NULL;
- live_edge = e;
- }
- }
-
- /* We can sometimes encounter dead code. Don't try to move it
- into the exit block. */
- if (!live_edge || live_edge->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
- return NULL;
-
- /* Reject targets of abnormal edges. This is needed for correctness
- on ports like Alpha and MIPS, whose pic_offset_table_rtx can die on
- exception edges even though it is generally treated as call-saved
- for the majority of the compilation. Moving across abnormal edges
- isn't going to be interesting for shrink-wrap usage anyway. */
- if (live_edge->flags & EDGE_ABNORMAL)
- return NULL;
-
- if (EDGE_COUNT (live_edge->dest->preds) > 1)
- return NULL;
-
- return live_edge->dest;
-}
-
-/* Try to move INSN from BB to a successor. Return true on success.
- USES and DEFS are the set of registers that are used and defined
- after INSN in BB. */
-
-static bool
-move_insn_for_shrink_wrap (basic_block bb, rtx insn,
- const HARD_REG_SET uses,
- const HARD_REG_SET defs)
-{
- rtx set, src, dest;
- bitmap live_out, live_in, bb_uses, bb_defs;
- unsigned int i, dregno, end_dregno, sregno, end_sregno;
- basic_block next_block;
-
- /* Look for a simple register copy. */
- set = single_set (insn);
- if (!set)
- return false;
- src = SET_SRC (set);
- dest = SET_DEST (set);
- if (!REG_P (dest) || !REG_P (src))
- return false;
-
- /* Make sure that the source register isn't defined later in BB. */
- sregno = REGNO (src);
- end_sregno = END_REGNO (src);
- if (overlaps_hard_reg_set_p (defs, GET_MODE (src), sregno))
- return false;
-
- /* Make sure that the destination register isn't referenced later in BB. */
- dregno = REGNO (dest);
- end_dregno = END_REGNO (dest);
- if (overlaps_hard_reg_set_p (uses, GET_MODE (dest), dregno)
- || overlaps_hard_reg_set_p (defs, GET_MODE (dest), dregno))
- return false;
-
- /* See whether there is a successor block to which we could move INSN. */
- next_block = next_block_for_reg (bb, dregno, end_dregno);
- if (!next_block)
- return false;
-
- /* At this point we are committed to moving INSN, but let's try to
- move it as far as we can. */
- do
- {
- live_out = df_get_live_out (bb);
- live_in = df_get_live_in (next_block);
- bb = next_block;
-
- /* Check whether BB uses DEST or clobbers DEST. We need to add
- INSN to BB if so. Either way, DEST is no longer live on entry,
- except for any part that overlaps SRC (next loop). */
- bb_uses = &DF_LR_BB_INFO (bb)->use;
- bb_defs = &DF_LR_BB_INFO (bb)->def;
- if (df_live)
- {
- for (i = dregno; i < end_dregno; i++)
- {
- if (REGNO_REG_SET_P (bb_uses, i) || REGNO_REG_SET_P (bb_defs, i)
- || REGNO_REG_SET_P (&DF_LIVE_BB_INFO (bb)->gen, i))
- next_block = NULL;
- CLEAR_REGNO_REG_SET (live_out, i);
- CLEAR_REGNO_REG_SET (live_in, i);
- }
-
- /* Check whether BB clobbers SRC. We need to add INSN to BB if so.
- Either way, SRC is now live on entry. */
- for (i = sregno; i < end_sregno; i++)
- {
- if (REGNO_REG_SET_P (bb_defs, i)
- || REGNO_REG_SET_P (&DF_LIVE_BB_INFO (bb)->gen, i))
- next_block = NULL;
- SET_REGNO_REG_SET (live_out, i);
- SET_REGNO_REG_SET (live_in, i);
- }
- }
- else
- {
- /* DF_LR_BB_INFO (bb)->def does not comprise the DF_REF_PARTIAL and
- DF_REF_CONDITIONAL defs. So if DF_LIVE doesn't exist, i.e.
- at -O1, just give up searching NEXT_BLOCK. */
- next_block = NULL;
- for (i = dregno; i < end_dregno; i++)
- {
- CLEAR_REGNO_REG_SET (live_out, i);
- CLEAR_REGNO_REG_SET (live_in, i);
- }
-
- for (i = sregno; i < end_sregno; i++)
- {
- SET_REGNO_REG_SET (live_out, i);
- SET_REGNO_REG_SET (live_in, i);
- }
- }
-
- /* If we don't need to add the move to BB, look for a single
- successor block. */
- if (next_block)
- next_block = next_block_for_reg (next_block, dregno, end_dregno);
- }
- while (next_block);
-
- /* BB now defines DEST. It only uses the parts of DEST that overlap SRC
- (next loop). */
- for (i = dregno; i < end_dregno; i++)
- {
- CLEAR_REGNO_REG_SET (bb_uses, i);
- SET_REGNO_REG_SET (bb_defs, i);
- }
-
- /* BB now uses SRC. */
- for (i = sregno; i < end_sregno; i++)
- SET_REGNO_REG_SET (bb_uses, i);
-
- emit_insn_after (PATTERN (insn), bb_note (bb));
- delete_insn (insn);
- return true;
-}
-
-/* Look for register copies in the first block of the function, and move
- them down into successor blocks if the register is used only on one
- path. This exposes more opportunities for shrink-wrapping. These
- kinds of sets often occur when incoming argument registers are moved
- to call-saved registers because their values are live across one or
- more calls during the function. */
-
-static void
-prepare_shrink_wrap (basic_block entry_block)
-{
- rtx insn, curr, x;
- HARD_REG_SET uses, defs;
- df_ref *ref;
-
- CLEAR_HARD_REG_SET (uses);
- CLEAR_HARD_REG_SET (defs);
- FOR_BB_INSNS_REVERSE_SAFE (entry_block, insn, curr)
- if (NONDEBUG_INSN_P (insn)
- && !move_insn_for_shrink_wrap (entry_block, insn, uses, defs))
- {
- /* Add all defined registers to DEFs. */
- for (ref = DF_INSN_DEFS (insn); *ref; ref++)
- {
- x = DF_REF_REG (*ref);
- if (REG_P (x) && HARD_REGISTER_P (x))
- SET_HARD_REG_BIT (defs, REGNO (x));
- }
-
- /* Add all used registers to USESs. */
- for (ref = DF_INSN_USES (insn); *ref; ref++)
- {
- x = DF_REF_REG (*ref);
- if (REG_P (x) && HARD_REGISTER_P (x))
- SET_HARD_REG_BIT (uses, REGNO (x));
- }
- }
-}
-
-#endif
-
#ifdef HAVE_return
/* Insert use of return register before the end of BB. */
@@ -5618,7 +5360,7 @@ gen_return_pattern (bool simple_p)
also means updating block_for_insn appropriately. SIMPLE_P is
the same as in gen_return_pattern and passed to it. */
-static void
+void
emit_return_into_block (bool simple_p, basic_block bb)
{
rtx jump, pat;
@@ -5645,61 +5387,9 @@ set_return_jump_label (rtx returnjump)
JUMP_LABEL (returnjump) = ret_rtx;
}
-#ifdef HAVE_simple_return
-/* Create a copy of BB instructions and insert at BEFORE. Redirect
- preds of BB to COPY_BB if they don't appear in NEED_PROLOGUE. */
-static void
-dup_block_and_redirect (basic_block bb, basic_block copy_bb, rtx before,
- bitmap_head *need_prologue)
-{
- edge_iterator ei;
- edge e;
- rtx insn = BB_END (bb);
-
- /* We know BB has a single successor, so there is no need to copy a
- simple jump at the end of BB. */
- if (simplejump_p (insn))
- insn = PREV_INSN (insn);
-
- start_sequence ();
- duplicate_insn_chain (BB_HEAD (bb), insn);
- if (dump_file)
- {
- unsigned count = 0;
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (active_insn_p (insn))
- ++count;
- fprintf (dump_file, "Duplicating bb %d to bb %d, %u active insns.\n",
- bb->index, copy_bb->index, count);
- }
- insn = get_insns ();
- end_sequence ();
- emit_insn_before (insn, before);
-
- /* Redirect all the paths that need no prologue into copy_bb. */
- for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
- if (!bitmap_bit_p (need_prologue, e->src->index))
- {
- int freq = EDGE_FREQUENCY (e);
- copy_bb->count += e->count;
- copy_bb->frequency += EDGE_FREQUENCY (e);
- e->dest->count -= e->count;
- if (e->dest->count < 0)
- e->dest->count = 0;
- e->dest->frequency -= freq;
- if (e->dest->frequency < 0)
- e->dest->frequency = 0;
- redirect_edge_and_branch_force (e, copy_bb);
- continue;
- }
- else
- ei_next (&ei);
-}
-#endif
-
#if defined (HAVE_return) || defined (HAVE_simple_return)
/* Return true if there are any active insns between HEAD and TAIL. */
-static bool
+bool
active_insn_between (rtx head, rtx tail)
{
while (tail)
@@ -5716,7 +5406,7 @@ active_insn_between (rtx head, rtx tail)
/* LAST_BB is a block that exits, and empty of active instructions.
Examine its predecessors for jumps that can be converted to
(conditional) returns. */
-static vec<edge>
+vec<edge>
convert_jumps_to_returns (basic_block last_bb, bool simple_p,
vec<edge> unconverted ATTRIBUTE_UNUSED)
{
@@ -5816,7 +5506,7 @@ convert_jumps_to_returns (basic_block last_bb, bool simple_p,
}
/* Emit a return insn for the exit fallthru block. */
-static basic_block
+basic_block
emit_return_for_exit (edge exit_fallthru_edge, bool simple_p)
{
basic_block last_bb = exit_fallthru_edge->src;
@@ -5888,9 +5578,7 @@ thread_prologue_and_epilogue_insns (void)
bool inserted;
#ifdef HAVE_simple_return
vec<edge> unconverted_simple_returns = vNULL;
- bool nonempty_prologue;
bitmap_head bb_flags;
- unsigned max_grow_size;
#endif
rtx returnjump;
rtx seq ATTRIBUTE_UNUSED, epilogue_end ATTRIBUTE_UNUSED;
@@ -5970,350 +5658,7 @@ thread_prologue_and_epilogue_insns (void)
prologue/epilogue is emitted only around those parts of the
function that require it. */
- nonempty_prologue = false;
- for (seq = prologue_seq; seq; seq = NEXT_INSN (seq))
- if (!NOTE_P (seq) || NOTE_KIND (seq) != NOTE_INSN_PROLOGUE_END)
- {
- nonempty_prologue = true;
- break;
- }
-
- if (flag_shrink_wrap && HAVE_simple_return
- && (targetm.profile_before_prologue () || !crtl->profile)
- && nonempty_prologue && !crtl->calls_eh_return)
- {
- HARD_REG_SET prologue_clobbered, prologue_used, live_on_edge;
- struct hard_reg_set_container set_up_by_prologue;
- rtx p_insn;
- vec<basic_block> vec;
- basic_block bb;
- bitmap_head bb_antic_flags;
- bitmap_head bb_on_list;
- bitmap_head bb_tail;
-
- if (dump_file)
- fprintf (dump_file, "Attempting shrink-wrapping optimization.\n");
-
- /* Compute the registers set and used in the prologue. */
- CLEAR_HARD_REG_SET (prologue_clobbered);
- CLEAR_HARD_REG_SET (prologue_used);
- for (p_insn = prologue_seq; p_insn; p_insn = NEXT_INSN (p_insn))
- {
- HARD_REG_SET this_used;
- if (!NONDEBUG_INSN_P (p_insn))
- continue;
-
- CLEAR_HARD_REG_SET (this_used);
- note_uses (&PATTERN (p_insn), record_hard_reg_uses,
- &this_used);
- AND_COMPL_HARD_REG_SET (this_used, prologue_clobbered);
- IOR_HARD_REG_SET (prologue_used, this_used);
- note_stores (PATTERN (p_insn), record_hard_reg_sets,
- &prologue_clobbered);
- }
-
- prepare_shrink_wrap (entry_edge->dest);
-
- bitmap_initialize (&bb_antic_flags, &bitmap_default_obstack);
- bitmap_initialize (&bb_on_list, &bitmap_default_obstack);
- bitmap_initialize (&bb_tail, &bitmap_default_obstack);
-
- /* Find the set of basic blocks that require a stack frame,
- and blocks that are too big to be duplicated. */
-
- vec.create (n_basic_blocks_for_fn (cfun));
-
- CLEAR_HARD_REG_SET (set_up_by_prologue.set);
- add_to_hard_reg_set (&set_up_by_prologue.set, Pmode,
- STACK_POINTER_REGNUM);
- add_to_hard_reg_set (&set_up_by_prologue.set, Pmode, ARG_POINTER_REGNUM);
- if (frame_pointer_needed)
- add_to_hard_reg_set (&set_up_by_prologue.set, Pmode,
- HARD_FRAME_POINTER_REGNUM);
- if (pic_offset_table_rtx)
- add_to_hard_reg_set (&set_up_by_prologue.set, Pmode,
- PIC_OFFSET_TABLE_REGNUM);
- if (crtl->drap_reg)
- add_to_hard_reg_set (&set_up_by_prologue.set,
- GET_MODE (crtl->drap_reg),
- REGNO (crtl->drap_reg));
- if (targetm.set_up_by_prologue)
- targetm.set_up_by_prologue (&set_up_by_prologue);
-
- /* We don't use a different max size depending on
- optimize_bb_for_speed_p because increasing shrink-wrapping
- opportunities by duplicating tail blocks can actually result
- in an overall decrease in code size. */
- max_grow_size = get_uncond_jump_length ();
- max_grow_size *= PARAM_VALUE (PARAM_MAX_GROW_COPY_BB_INSNS);
-
- FOR_EACH_BB_FN (bb, cfun)
- {
- rtx insn;
- unsigned size = 0;
-
- FOR_BB_INSNS (bb, insn)
- if (NONDEBUG_INSN_P (insn))
- {
- if (requires_stack_frame_p (insn, prologue_used,
- set_up_by_prologue.set))
- {
- if (bb == entry_edge->dest)
- goto fail_shrinkwrap;
- bitmap_set_bit (&bb_flags, bb->index);
- vec.quick_push (bb);
- break;
- }
- else if (size <= max_grow_size)
- {
- size += get_attr_min_length (insn);
- if (size > max_grow_size)
- bitmap_set_bit (&bb_on_list, bb->index);
- }
- }
- }
-
- /* Blocks that really need a prologue, or are too big for tails. */
- bitmap_ior_into (&bb_on_list, &bb_flags);
-
- /* For every basic block that needs a prologue, mark all blocks
- reachable from it, so as to ensure they are also seen as
- requiring a prologue. */
- while (!vec.is_empty ())
- {
- basic_block tmp_bb = vec.pop ();
-
- FOR_EACH_EDGE (e, ei, tmp_bb->succs)
- if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
- && bitmap_set_bit (&bb_flags, e->dest->index))
- vec.quick_push (e->dest);
- }
-
- /* Find the set of basic blocks that need no prologue, have a
- single successor, can be duplicated, meet a max size
- requirement, and go to the exit via like blocks. */
- vec.quick_push (EXIT_BLOCK_PTR_FOR_FN (cfun));
- while (!vec.is_empty ())
- {
- basic_block tmp_bb = vec.pop ();
-
- FOR_EACH_EDGE (e, ei, tmp_bb->preds)
- if (single_succ_p (e->src)
- && !bitmap_bit_p (&bb_on_list, e->src->index)
- && can_duplicate_block_p (e->src))
- {
- edge pe;
- edge_iterator pei;
-
- /* If there is predecessor of e->src which doesn't
- need prologue and the edge is complex,
- we might not be able to redirect the branch
- to a copy of e->src. */
- FOR_EACH_EDGE (pe, pei, e->src->preds)
- if ((pe->flags & EDGE_COMPLEX) != 0
- && !bitmap_bit_p (&bb_flags, pe->src->index))
- break;
- if (pe == NULL && bitmap_set_bit (&bb_tail, e->src->index))
- vec.quick_push (e->src);
- }
- }
-
- /* Now walk backwards from every block that is marked as needing
- a prologue to compute the bb_antic_flags bitmap. Exclude
- tail blocks; They can be duplicated to be used on paths not
- needing a prologue. */
- bitmap_clear (&bb_on_list);
- bitmap_and_compl (&bb_antic_flags, &bb_flags, &bb_tail);
- FOR_EACH_BB_FN (bb, cfun)
- {
- if (!bitmap_bit_p (&bb_antic_flags, bb->index))
- continue;
- FOR_EACH_EDGE (e, ei, bb->preds)
- if (!bitmap_bit_p (&bb_antic_flags, e->src->index)
- && bitmap_set_bit (&bb_on_list, e->src->index))
- vec.quick_push (e->src);
- }
- while (!vec.is_empty ())
- {
- basic_block tmp_bb = vec.pop ();
- bool all_set = true;
-
- bitmap_clear_bit (&bb_on_list, tmp_bb->index);
- FOR_EACH_EDGE (e, ei, tmp_bb->succs)
- if (!bitmap_bit_p (&bb_antic_flags, e->dest->index))
- {
- all_set = false;
- break;
- }
-
- if (all_set)
- {
- bitmap_set_bit (&bb_antic_flags, tmp_bb->index);
- FOR_EACH_EDGE (e, ei, tmp_bb->preds)
- if (!bitmap_bit_p (&bb_antic_flags, e->src->index)
- && bitmap_set_bit (&bb_on_list, e->src->index))
- vec.quick_push (e->src);
- }
- }
- /* Find exactly one edge that leads to a block in ANTIC from
- a block that isn't. */
- if (!bitmap_bit_p (&bb_antic_flags, entry_edge->dest->index))
- FOR_EACH_BB_FN (bb, cfun)
- {
- if (!bitmap_bit_p (&bb_antic_flags, bb->index))
- continue;
- FOR_EACH_EDGE (e, ei, bb->preds)
- if (!bitmap_bit_p (&bb_antic_flags, e->src->index))
- {
- if (entry_edge != orig_entry_edge)
- {
- entry_edge = orig_entry_edge;
- if (dump_file)
- fprintf (dump_file, "More than one candidate edge.\n");
- goto fail_shrinkwrap;
- }
- if (dump_file)
- fprintf (dump_file, "Found candidate edge for "
- "shrink-wrapping, %d->%d.\n", e->src->index,
- e->dest->index);
- entry_edge = e;
- }
- }
-
- if (entry_edge != orig_entry_edge)
- {
- /* Test whether the prologue is known to clobber any register
- (other than FP or SP) which are live on the edge. */
- CLEAR_HARD_REG_BIT (prologue_clobbered, STACK_POINTER_REGNUM);
- if (frame_pointer_needed)
- CLEAR_HARD_REG_BIT (prologue_clobbered, HARD_FRAME_POINTER_REGNUM);
- REG_SET_TO_HARD_REG_SET (live_on_edge,
- df_get_live_in (entry_edge->dest));
- if (hard_reg_set_intersect_p (live_on_edge, prologue_clobbered))
- {
- entry_edge = orig_entry_edge;
- if (dump_file)
- fprintf (dump_file,
- "Shrink-wrapping aborted due to clobber.\n");
- }
- }
- if (entry_edge != orig_entry_edge)
- {
- crtl->shrink_wrapped = true;
- if (dump_file)
- fprintf (dump_file, "Performing shrink-wrapping.\n");
-
- /* Find tail blocks reachable from both blocks needing a
- prologue and blocks not needing a prologue. */
- if (!bitmap_empty_p (&bb_tail))
- FOR_EACH_BB_FN (bb, cfun)
- {
- bool some_pro, some_no_pro;
- if (!bitmap_bit_p (&bb_tail, bb->index))
- continue;
- some_pro = some_no_pro = false;
- FOR_EACH_EDGE (e, ei, bb->preds)
- {
- if (bitmap_bit_p (&bb_flags, e->src->index))
- some_pro = true;
- else
- some_no_pro = true;
- }
- if (some_pro && some_no_pro)
- vec.quick_push (bb);
- else
- bitmap_clear_bit (&bb_tail, bb->index);
- }
- /* Find the head of each tail. */
- while (!vec.is_empty ())
- {
- basic_block tbb = vec.pop ();
-
- if (!bitmap_bit_p (&bb_tail, tbb->index))
- continue;
-
- while (single_succ_p (tbb))
- {
- tbb = single_succ (tbb);
- bitmap_clear_bit (&bb_tail, tbb->index);
- }
- }
- /* Now duplicate the tails. */
- if (!bitmap_empty_p (&bb_tail))
- FOR_EACH_BB_REVERSE_FN (bb, cfun)
- {
- basic_block copy_bb, tbb;
- rtx insert_point;
- int eflags;
-
- if (!bitmap_clear_bit (&bb_tail, bb->index))
- continue;
-
- /* Create a copy of BB, instructions and all, for
- use on paths that don't need a prologue.
- Ideal placement of the copy is on a fall-thru edge
- or after a block that would jump to the copy. */
- FOR_EACH_EDGE (e, ei, bb->preds)
- if (!bitmap_bit_p (&bb_flags, e->src->index)
- && single_succ_p (e->src))
- break;
- if (e)
- {
- /* Make sure we insert after any barriers. */
- rtx end = get_last_bb_insn (e->src);
- copy_bb = create_basic_block (NEXT_INSN (end),
- NULL_RTX, e->src);
- BB_COPY_PARTITION (copy_bb, e->src);
- }
- else
- {
- /* Otherwise put the copy at the end of the function. */
- copy_bb = create_basic_block (NULL_RTX, NULL_RTX,
- EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
- BB_COPY_PARTITION (copy_bb, bb);
- }
-
- insert_point = emit_note_after (NOTE_INSN_DELETED,
- BB_END (copy_bb));
- emit_barrier_after (BB_END (copy_bb));
-
- tbb = bb;
- while (1)
- {
- dup_block_and_redirect (tbb, copy_bb, insert_point,
- &bb_flags);
- tbb = single_succ (tbb);
- if (tbb == EXIT_BLOCK_PTR_FOR_FN (cfun))
- break;
- e = split_block (copy_bb, PREV_INSN (insert_point));
- copy_bb = e->dest;
- }
-
- /* Quiet verify_flow_info by (ab)using EDGE_FAKE.
- We have yet to add a simple_return to the tails,
- as we'd like to first convert_jumps_to_returns in
- case the block is no longer used after that. */
- eflags = EDGE_FAKE;
- if (CALL_P (PREV_INSN (insert_point))
- && SIBLING_CALL_P (PREV_INSN (insert_point)))
- eflags = EDGE_SIBCALL | EDGE_ABNORMAL;
- make_single_succ_edge (copy_bb, EXIT_BLOCK_PTR_FOR_FN (cfun),
- eflags);
-
- /* verify_flow_info doesn't like a note after a
- sibling call. */
- delete_insn (insert_point);
- if (bitmap_empty_p (&bb_tail))
- break;
- }
- }
-
- fail_shrinkwrap:
- bitmap_clear (&bb_tail);
- bitmap_clear (&bb_antic_flags);
- bitmap_clear (&bb_on_list);
- vec.release ();
- }
+ try_shrink_wrapping (&entry_edge, orig_entry_edge, &bb_flags, prologue_seq);
#endif
if (split_prologue_seq != NULL_RTX)
@@ -6339,44 +5684,12 @@ thread_prologue_and_epilogue_insns (void)
exit_fallthru_edge = find_fallthru_edge (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds);
- /* If we're allowed to generate a simple return instruction, then by
- definition we don't need a full epilogue. If the last basic
- block before the exit block does not contain active instructions,
- examine its predecessors and try to emit (conditional) return
- instructions. */
#ifdef HAVE_simple_return
if (entry_edge != orig_entry_edge)
- {
- if (optimize)
- {
- unsigned i, last;
-
- /* convert_jumps_to_returns may add to preds of the exit block
- (but won't remove). Stop at end of current preds. */
- last = EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds);
- for (i = 0; i < last; i++)
- {
- e = EDGE_I (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds, i);
- if (LABEL_P (BB_HEAD (e->src))
- && !bitmap_bit_p (&bb_flags, e->src->index)
- && !active_insn_between (BB_HEAD (e->src), BB_END (e->src)))
- unconverted_simple_returns
- = convert_jumps_to_returns (e->src, true,
- unconverted_simple_returns);
- }
- }
-
- if (exit_fallthru_edge != NULL
- && EDGE_COUNT (exit_fallthru_edge->src->preds) != 0
- && !bitmap_bit_p (&bb_flags, exit_fallthru_edge->src->index))
- {
- basic_block last_bb;
-
- last_bb = emit_return_for_exit (exit_fallthru_edge, true);
- returnjump = BB_END (last_bb);
- exit_fallthru_edge = NULL;
- }
- }
+ exit_fallthru_edge
+ = get_unconverted_simple_return (exit_fallthru_edge, bb_flags,
+ &unconverted_simple_returns,
+ &returnjump);
#endif
#ifdef HAVE_return
if (HAVE_return)
@@ -6520,104 +5833,8 @@ epilogue_done:
}
#ifdef HAVE_simple_return
- /* If there were branches to an empty LAST_BB which we tried to
- convert to conditional simple_returns, but couldn't for some
- reason, create a block to hold a simple_return insn and redirect
- those remaining edges. */
- if (!unconverted_simple_returns.is_empty ())
- {
- basic_block simple_return_block_hot = NULL;
- basic_block simple_return_block_cold = NULL;
- edge pending_edge_hot = NULL;
- edge pending_edge_cold = NULL;
- basic_block exit_pred;
- int i;
-
- gcc_assert (entry_edge != orig_entry_edge);
-
- /* See if we can reuse the last insn that was emitted for the
- epilogue. */
- if (returnjump != NULL_RTX
- && JUMP_LABEL (returnjump) == simple_return_rtx)
- {
- e = split_block (BLOCK_FOR_INSN (returnjump), PREV_INSN (returnjump));
- if (BB_PARTITION (e->src) == BB_HOT_PARTITION)
- simple_return_block_hot = e->dest;
- else
- simple_return_block_cold = e->dest;
- }
-
- /* Also check returns we might need to add to tail blocks. */
- FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
- if (EDGE_COUNT (e->src->preds) != 0
- && (e->flags & EDGE_FAKE) != 0
- && !bitmap_bit_p (&bb_flags, e->src->index))
- {
- if (BB_PARTITION (e->src) == BB_HOT_PARTITION)
- pending_edge_hot = e;
- else
- pending_edge_cold = e;
- }
-
- /* Save a pointer to the exit's predecessor BB for use in
- inserting new BBs at the end of the function. Do this
- after the call to split_block above which may split
- the original exit pred. */
- exit_pred = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb;
-
- FOR_EACH_VEC_ELT (unconverted_simple_returns, i, e)
- {
- basic_block *pdest_bb;
- edge pending;
-
- if (BB_PARTITION (e->src) == BB_HOT_PARTITION)
- {
- pdest_bb = &simple_return_block_hot;
- pending = pending_edge_hot;
- }
- else
- {
- pdest_bb = &simple_return_block_cold;
- pending = pending_edge_cold;
- }
-
- if (*pdest_bb == NULL && pending != NULL)
- {
- emit_return_into_block (true, pending->src);
- pending->flags &= ~(EDGE_FALLTHRU | EDGE_FAKE);
- *pdest_bb = pending->src;
- }
- else if (*pdest_bb == NULL)
- {
- basic_block bb;
- rtx start;
-
- bb = create_basic_block (NULL, NULL, exit_pred);
- BB_COPY_PARTITION (bb, e->src);
- start = emit_jump_insn_after (gen_simple_return (),
- BB_END (bb));
- JUMP_LABEL (start) = simple_return_rtx;
- emit_barrier_after (start);
-
- *pdest_bb = bb;
- make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
- }
- redirect_edge_and_branch_force (e, *pdest_bb);
- }
- unconverted_simple_returns.release ();
- }
-
- if (entry_edge != orig_entry_edge)
- {
- FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
- if (EDGE_COUNT (e->src->preds) != 0
- && (e->flags & EDGE_FAKE) != 0
- && !bitmap_bit_p (&bb_flags, e->src->index))
- {
- emit_return_into_block (true, e->src);
- e->flags &= ~(EDGE_FALLTHRU | EDGE_FAKE);
- }
- }
+ convert_to_simple_return (entry_edge, orig_entry_edge, bb_flags, returnjump,
+ unconverted_simple_returns);
#endif
#ifdef HAVE_sibcall_epilogue
@@ -6936,7 +6153,7 @@ types_used_by_var_decl_insert (tree type, tree var_decl)
if (*slot == NULL)
{
struct types_used_by_vars_entry *entry;
- entry = ggc_alloc_types_used_by_vars_entry ();
+ entry = ggc_alloc<types_used_by_vars_entry> ();
entry->type = type;
entry->var_decl = var_decl;
*slot = entry;
diff --git a/gcc/function.h b/gcc/function.h
index 0aa6c9a1545..a8294b26752 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -809,10 +809,6 @@ extern void used_types_insert (tree);
extern int get_next_funcdef_no (void);
extern int get_last_funcdef_no (void);
-#ifdef HAVE_simple_return
-extern bool requires_stack_frame_p (rtx, HARD_REG_SET, HARD_REG_SET);
-#endif
-
extern rtx get_hard_reg_initial_val (enum machine_mode, unsigned int);
extern rtx has_hard_reg_initial_val (enum machine_mode, unsigned int);
extern rtx get_hard_reg_initial_reg (rtx);
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 7bea6d79ac2..9ac18e60d80 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -8170,7 +8170,7 @@ sanitize_spec_function (int argc, const char **argv)
if (strcmp (argv[0], "thread") == 0)
return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL;
if (strcmp (argv[0], "undefined") == 0)
- return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_FLOAT_DIVIDE))
+ return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT))
&& !flag_sanitize_undefined_trap_on_error) ? "" : NULL;
if (strcmp (argv[0], "leak") == 0)
return ((flag_sanitize
diff --git a/gcc/gcov-dump.c b/gcc/gcov-dump.c
index f21878dd116..22298ec3c30 100644
--- a/gcc/gcov-dump.c
+++ b/gcc/gcov-dump.c
@@ -444,7 +444,7 @@ tag_counters (const char *filename ATTRIBUTE_UNUSED,
count = gcov_read_counter ();
printf (" ");
- printf (HOST_WIDEST_INT_PRINT_DEC, count);
+ printf ("%"PRId64, count);
}
}
}
@@ -467,12 +467,12 @@ tag_summary (const char *filename ATTRIBUTE_UNUSED,
printf ("\t\tcounts=%u, runs=%u",
summary.ctrs[ix].num, summary.ctrs[ix].runs);
- printf (", sum_all=" HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT)summary.ctrs[ix].sum_all);
- printf (", run_max=" HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT)summary.ctrs[ix].run_max);
- printf (", sum_max=" HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT)summary.ctrs[ix].sum_max);
+ printf (", sum_all=%"PRId64,
+ (int64_t)summary.ctrs[ix].sum_all);
+ printf (", run_max=%"PRId64,
+ (int64_t)summary.ctrs[ix].run_max);
+ printf (", sum_max=%"PRId64,
+ (int64_t)summary.ctrs[ix].sum_max);
if (ix != GCOV_COUNTER_ARCS)
continue;
printf ("\n");
@@ -486,11 +486,11 @@ tag_summary (const char *filename ATTRIBUTE_UNUSED,
printf ("\n");
print_prefix (filename, 0, 0);
printf ("\t\t%d: num counts=%u, min counter="
- HOST_WIDEST_INT_PRINT_DEC ", cum_counter="
- HOST_WIDEST_INT_PRINT_DEC,
+ "%"PRId64 ", cum_counter="
+ "%"PRId64,
h_ix, histo_bucket->num_counters,
- (HOST_WIDEST_INT)histo_bucket->min_value,
- (HOST_WIDEST_INT)histo_bucket->cum_value);
+ (int64_t)histo_bucket->min_value,
+ (int64_t)histo_bucket->cum_value);
}
if (flag_dump_working_sets)
dump_working_sets (filename, &summary.ctrs[ix]);
@@ -522,9 +522,9 @@ dump_working_sets (const char *filename ATTRIBUTE_UNUSED,
printf ("\n");
print_prefix (filename, 0, 0);
printf ("\t\t%u.%02u%%: num counts=%u, min counter="
- HOST_WIDEST_INT_PRINT_DEC,
+ "%"PRId64,
pct / 100, pct - (pct / 100 * 100),
ws_info->num_counters,
- (HOST_WIDEST_INT)ws_info->min_counter);
+ (int64_t)ws_info->min_counter);
}
}
diff --git a/gcc/gcov-io.c b/gcc/gcov-io.c
index 5ef82f68372..1fdb9583ee8 100644
--- a/gcc/gcov-io.c
+++ b/gcc/gcov-io.c
@@ -67,7 +67,7 @@ GCOV_LINKAGE struct gcov_var
static inline gcov_position_t
gcov_position (void)
{
- gcc_assert (gcov_var.mode > 0);
+ gcov_nonruntime_assert (gcov_var.mode > 0);
return gcov_var.start + gcov_var.offset;
}
@@ -83,7 +83,6 @@ gcov_is_error (void)
GCOV_LINKAGE inline void
gcov_rewrite (void)
{
- gcc_assert (gcov_var.mode > 0);
gcov_var.mode = -1;
gcov_var.start = 0;
gcov_var.offset = 0;
@@ -133,7 +132,7 @@ gcov_open (const char *name, int mode)
s_flock.l_pid = getpid ();
#endif
- gcc_assert (!gcov_var.file);
+ gcov_nonruntime_assert (!gcov_var.file);
gcov_var.start = 0;
gcov_var.offset = gcov_var.length = 0;
gcov_var.overread = -1u;
@@ -297,14 +296,13 @@ gcov_write_words (unsigned words)
{
gcov_unsigned_t *result;
- gcc_assert (gcov_var.mode < 0);
+ gcov_nonruntime_assert (gcov_var.mode < 0);
#if IN_LIBGCOV
if (gcov_var.offset >= GCOV_BLOCK_SIZE)
{
gcov_write_block (GCOV_BLOCK_SIZE);
if (gcov_var.offset)
{
- gcc_assert (gcov_var.offset == 1);
memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4);
}
}
@@ -399,9 +397,9 @@ gcov_write_length (gcov_position_t position)
gcov_unsigned_t length;
gcov_unsigned_t *buffer;
- gcc_assert (gcov_var.mode < 0);
- gcc_assert (position + 2 <= gcov_var.start + gcov_var.offset);
- gcc_assert (position >= gcov_var.start);
+ gcov_nonruntime_assert (gcov_var.mode < 0);
+ gcov_nonruntime_assert (position + 2 <= gcov_var.start + gcov_var.offset);
+ gcov_nonruntime_assert (position >= gcov_var.start);
offset = position - gcov_var.start;
length = gcov_var.offset - offset - 2;
buffer = (gcov_unsigned_t *) &gcov_var.buffer[offset];
@@ -487,14 +485,13 @@ gcov_read_words (unsigned words)
const gcov_unsigned_t *result;
unsigned excess = gcov_var.length - gcov_var.offset;
- gcc_assert (gcov_var.mode > 0);
+ gcov_nonruntime_assert (gcov_var.mode > 0);
if (excess < words)
{
gcov_var.start += gcov_var.offset;
#if IN_LIBGCOV
if (excess)
{
- gcc_assert (excess == 1);
memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4);
}
#else
@@ -503,7 +500,6 @@ gcov_read_words (unsigned words)
gcov_var.offset = 0;
gcov_var.length = excess;
#if IN_LIBGCOV
- gcc_assert (!gcov_var.length || gcov_var.length == 1);
excess = GCOV_BLOCK_SIZE;
#else
if (gcov_var.length + words > gcov_var.alloc)
@@ -620,7 +616,9 @@ gcov_read_summary (struct gcov_summary *summary)
while (!cur_bitvector)
{
h_ix = bv_ix * 32;
- gcc_assert (bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE);
+ if (bv_ix >= GCOV_HISTOGRAM_BITVECTOR_SIZE)
+ gcov_error ("corrupted profile info: summary histogram "
+ "bitvector is corrupt");
cur_bitvector = histo_bitvector[bv_ix++];
}
while (!(cur_bitvector & 0x1))
@@ -628,7 +626,9 @@ gcov_read_summary (struct gcov_summary *summary)
h_ix++;
cur_bitvector >>= 1;
}
- gcc_assert (h_ix < GCOV_HISTOGRAM_SIZE);
+ if (h_ix >= GCOV_HISTOGRAM_SIZE)
+ gcov_error ("corrupted profile info: summary histogram "
+ "index is corrupt");
csum->histogram[h_ix].num_counters = gcov_read_unsigned ();
csum->histogram[h_ix].min_value = gcov_read_counter ();
@@ -648,7 +648,7 @@ gcov_read_summary (struct gcov_summary *summary)
GCOV_LINKAGE void
gcov_sync (gcov_position_t base, gcov_unsigned_t length)
{
- gcc_assert (gcov_var.mode > 0);
+ gcov_nonruntime_assert (gcov_var.mode > 0);
base += length;
if (base - gcov_var.start <= gcov_var.length)
gcov_var.offset = base - gcov_var.start;
@@ -667,7 +667,6 @@ gcov_sync (gcov_position_t base, gcov_unsigned_t length)
GCOV_LINKAGE void
gcov_seek (gcov_position_t base)
{
- gcc_assert (gcov_var.mode < 0);
if (gcov_var.offset)
gcov_write_block (gcov_var.offset);
fseek (gcov_var.file, base << 2, SEEK_SET);
@@ -719,20 +718,8 @@ gcov_histo_index (gcov_type value)
r = sizeof (long long) * __CHAR_BIT__ - 1 - __builtin_clzll (v);
#else
/* We use floor_log2 from hwint.c, which takes a HOST_WIDE_INT
- that is either 32 or 64 bits, and gcov_type_unsigned may be 64 bits.
- Need to check for the case where gcov_type_unsigned is 64 bits
- and HOST_WIDE_INT is 32 bits and handle it specially. */
-#if HOST_BITS_PER_WIDEST_INT == HOST_BITS_PER_WIDE_INT
+ that is 64 bits and gcov_type_unsigned is 64 bits. */
r = floor_log2 (v);
-#elif HOST_BITS_PER_WIDEST_INT == 2 * HOST_BITS_PER_WIDE_INT
- HOST_WIDE_INT hwi_v = v >> HOST_BITS_PER_WIDE_INT;
- if (hwi_v)
- r = floor_log2 (hwi_v) + HOST_BITS_PER_WIDE_INT;
- else
- r = floor_log2 ((HOST_WIDE_INT)v);
-#else
- gcc_unreachable ();
-#endif
#endif
}
@@ -742,7 +729,7 @@ gcov_histo_index (gcov_type value)
if (r < 2)
return (unsigned)value;
- gcc_assert (r < 64);
+ gcov_nonruntime_assert (r < 64);
/* Find the two next most significant bits to determine which
of the four linear sub-buckets to select. */
@@ -859,7 +846,7 @@ static void gcov_histogram_merge (gcov_bucket_type *tgt_histo,
/* The merged counters get placed in the new merged histogram
at the entry for the merged min_value. */
tmp_i = gcov_histo_index (merge_min);
- gcc_assert (tmp_i < GCOV_HISTOGRAM_SIZE);
+ gcov_nonruntime_assert (tmp_i < GCOV_HISTOGRAM_SIZE);
tmp_histo[tmp_i].num_counters += merge_num;
tmp_histo[tmp_i].cum_value += merge_cum;
if (!tmp_histo[tmp_i].min_value ||
@@ -873,7 +860,7 @@ static void gcov_histogram_merge (gcov_bucket_type *tgt_histo,
}
}
- gcc_assert (tgt_i < 0);
+ gcov_nonruntime_assert (tgt_i < 0);
/* In the case where there were more counters in the source histogram,
accumulate the remaining unmerged cumulative counter values. Add
@@ -890,8 +877,8 @@ static void gcov_histogram_merge (gcov_bucket_type *tgt_histo,
}
/* At this point, tmp_i should be the smallest non-zero entry in the
tmp_histo. */
- gcc_assert (tmp_i >= 0 && tmp_i < GCOV_HISTOGRAM_SIZE
- && tmp_histo[tmp_i].num_counters > 0);
+ gcov_nonruntime_assert (tmp_i >= 0 && tmp_i < GCOV_HISTOGRAM_SIZE
+ && tmp_histo[tmp_i].num_counters > 0);
tmp_histo[tmp_i].cum_value += src_cum;
/* Finally, copy the merged histogram into tgt_histo. */
@@ -1003,6 +990,6 @@ compute_working_sets (const struct gcov_ctr_summary *summary,
using a temporary above. */
cum += histo_bucket->cum_value;
}
- gcc_assert (ws_ix == NUM_GCOV_WORKING_SETS);
+ gcov_nonruntime_assert (ws_ix == NUM_GCOV_WORKING_SETS);
}
#endif /* IN_GCOV <= 0 && !IN_LIBGCOV */
diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h
index cbf95cfc552..58884dce94d 100644
--- a/gcc/gcov-io.h
+++ b/gcc/gcov-io.h
@@ -172,8 +172,8 @@ typedef unsigned gcov_position_t;
/* gcov_type is typedef'd elsewhere for the compiler */
#if IN_GCOV
#define GCOV_LINKAGE static
-typedef HOST_WIDEST_INT gcov_type;
-typedef unsigned HOST_WIDEST_INT gcov_type_unsigned;
+typedef int64_t gcov_type;
+typedef uint64_t gcov_type_unsigned;
#if IN_GCOV > 0
#include <sys/types.h>
#endif
@@ -195,6 +195,13 @@ typedef unsigned HOST_WIDEST_INT gcov_type_unsigned;
#define GCOV_LINKAGE extern
#endif
+#if IN_LIBGCOV
+#define gcov_nonruntime_assert(EXPR) ((void)(0 && (EXPR)))
+#else
+#define gcov_nonruntime_assert(EXPR) gcc_assert (EXPR)
+#define gcov_error(...) fatal_error (__VA_ARGS__)
+#endif
+
/* File suffixes. */
#define GCOV_DATA_SUFFIX ".gcda"
#define GCOV_NOTE_SUFFIX ".gcno"
diff --git a/gcc/gcov.c b/gcc/gcov.c
index b0e59e853f5..8bce0ae8c84 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -1846,7 +1846,7 @@ format_gcov (gcov_type top, gcov_type bottom, int dp)
}
}
else
- sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
+ sprintf (buffer, "%"PRId64, (int64_t)top);
return buffer;
}
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c
index 99b1b83f4cb..c5ce51c12f2 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -139,6 +139,7 @@ struct insn_def
rtx def; /* The DEFINE_... */
int insn_code; /* Instruction number. */
int insn_index; /* Expression number in file, for errors. */
+ const char *filename; /* Filename. */
int lineno; /* Line number. */
int num_alternatives; /* Number of alternatives. */
int vec_idx; /* Index of attribute vector in `def'. */
@@ -472,10 +473,7 @@ attr_rtx_1 (enum rtx_code code, va_list p)
rt_val = rtx_alloc (code);
XSTR (rt_val, 0) = arg0;
if (code == SYMBOL_REF)
- {
- X0EXP (rt_val, 1) = NULL_RTX;
- X0EXP (rt_val, 2) = NULL_RTX;
- }
+ X0EXP (rt_val, 1) = NULL_RTX;
}
}
else if (GET_RTX_LENGTH (code) == 2
@@ -1066,7 +1064,8 @@ convert_set_attr_alternative (rtx exp, struct insn_def *id)
if (XVECLEN (exp, 1) != num_alt)
{
error_with_line (id->lineno,
- "bad number of entries in SET_ATTR_ALTERNATIVE");
+ "bad number of entries in SET_ATTR_ALTERNATIVE, was %d expected %d",
+ XVECLEN (exp, 1), num_alt);
return NULL_RTX;
}
@@ -1137,6 +1136,7 @@ check_defs (void)
if (XVEC (id->def, id->vec_idx) == NULL)
continue;
+ read_md_filename = id->filename;
for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
{
value = XVECEXP (id->def, id->vec_idx, i);
@@ -3280,6 +3280,7 @@ gen_insn (rtx exp, int lineno)
id->next = defs;
defs = id;
id->def = exp;
+ id->filename = read_md_filename;
id->lineno = lineno;
switch (GET_CODE (exp))
diff --git a/gcc/gencodes.c b/gcc/gencodes.c
index b34381f9268..207b7eeb8f4 100644
--- a/gcc/gencodes.c
+++ b/gcc/gencodes.c
@@ -50,6 +50,7 @@ int
main (int argc, char **argv)
{
rtx desc;
+ int last = 1;
progname = "gencodes";
@@ -82,13 +83,16 @@ enum insn_code {\n\
break;
if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
- gen_insn (desc, insn_code_number);
+ {
+ gen_insn (desc, insn_code_number);
+ last = insn_code_number + 1;
+ }
}
- puts (" LAST_INSN_CODE\n\
+ printf (" LAST_INSN_CODE = %d\n\
};\n\
\n\
-#endif /* GCC_INSN_CODES_H */");
+#endif /* GCC_INSN_CODES_H */\n", last);
if (ferror (stdout) || fflush (stdout) || fclose (stdout))
return FATAL_EXIT_CODE;
diff --git a/gcc/gengenrtl.c b/gcc/gengenrtl.c
index d82ee39e7ee..550efb8e170 100644
--- a/gcc/gengenrtl.c
+++ b/gcc/gengenrtl.c
@@ -141,9 +141,10 @@ special_rtx (int idx)
static int
excluded_rtx (int idx)
{
- return ((strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0)
- || (strcmp (defs[idx].enumname, "CONST_WIDE_INT") == 0)
- || (strcmp (defs[idx].enumname, "CONST_FIXED") == 0));
+ return (strcmp (defs[idx].enumname, "VAR_LOCATION") == 0
+ || strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0
+ || strcmp (defs[idx].enumname, "CONST_WIDE_INT") == 0
+ || strcmp (defs[idx].enumname, "CONST_FIXED") == 0);
}
/* Place a list of all format specifiers we use into the array FORMAT. */
diff --git a/gcc/gengtype-lex.l b/gcc/gengtype-lex.l
index 936b28cdc4a..5e12885c63f 100644
--- a/gcc/gengtype-lex.l
+++ b/gcc/gengtype-lex.l
@@ -52,7 +52,7 @@ update_lineno (const char *l, size_t len)
CID [[:alpha:]_][[:alnum:]_]*
WS [[:space:]]+
HWS [ \t\r\v\f]*
-IWORD short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD|CPPCHAR_SIGNED_T|ino_t|dev_t|HARD_REG_SET
+IWORD short|long|(un)?signed|char|int|HOST_WIDE_INT|uint64_t|int64_t|bool|size_t|BOOL_BITFIELD|CPPCHAR_SIGNED_T|ino_t|dev_t|HARD_REG_SET
ITYPE {IWORD}({WS}{IWORD})*
/* Include '::' in identifiers to capture C++ scope qualifiers. */
ID {CID}({HWS}::{HWS}{CID})*
diff --git a/gcc/gengtype-parse.c b/gcc/gengtype-parse.c
index 96f04764c58..0f11cec7c41 100644
--- a/gcc/gengtype-parse.c
+++ b/gcc/gengtype-parse.c
@@ -197,18 +197,19 @@ require2 (int t1, int t2)
return v;
}
-/* If the next token does not have one of the codes T1, T2 or T3, report a
+/* If the next token does not have one of the codes T1, T2, T3 or T4, report a
parse error; otherwise return the token's value. */
static const char *
-require3 (int t1, int t2, int t3)
+require4 (int t1, int t2, int t3, int t4)
{
int u = token ();
const char *v = advance ();
- if (u != t1 && u != t2 && u != t3)
+ if (u != t1 && u != t2 && u != t3 && u != t4)
{
- parse_error ("expected %s, %s or %s, have %s",
+ parse_error ("expected %s, %s, %s or %s, have %s",
print_token (t1, 0), print_token (t2, 0),
- print_token (t3, 0), print_token (u, v));
+ print_token (t3, 0), print_token (t4, 0),
+ print_token (u, v));
return 0;
}
return v;
@@ -245,7 +246,9 @@ string_seq (void)
/* The caller has detected a template declaration that starts
with TMPL_NAME. Parse up to the closing '>'. This recognizes
- simple template declarations of the form ID<ID1,ID2,...,IDn>.
+ simple template declarations of the form ID<ID1,ID2,...,IDn>,
+ potentially with a single level of indirection e.g.
+ ID<ID1 *, ID2, ID3 *, ..., IDn>.
It does not try to parse anything more sophisticated than that.
Returns the template declaration string "ID<ID1,ID2,...,IDn>". */
@@ -254,6 +257,7 @@ static const char *
require_template_declaration (const char *tmpl_name)
{
char *str;
+ int num_indirections = 0;
/* Recognize the opening '<'. */
require ('<');
@@ -294,9 +298,21 @@ require_template_declaration (const char *tmpl_name)
depth -= 1;
continue;
}
- const char *id = require3 (SCALAR, ID, ',');
+ const char *id = require4 (SCALAR, ID, '*', ',');
if (id == NULL)
- id = ",";
+ {
+ if (T.code == '*')
+ {
+ id = "*";
+ if (num_indirections++)
+ parse_error ("only one level of indirection is supported"
+ " in template arguments");
+ }
+ else
+ id = ",";
+ }
+ else
+ num_indirections = 0;
str = concat (str, id, (char *) 0);
}
return str;
diff --git a/gcc/gengtype-state.c b/gcc/gengtype-state.c
index 2ca0e1de1e7..5b7017f1e3e 100644
--- a/gcc/gengtype-state.c
+++ b/gcc/gengtype-state.c
@@ -282,7 +282,7 @@ state_writer::state_writer ()
/* Fatal message while reading state. */
-static inline void
+static void
fatal_reading_state (struct state_token_st* tok, const char*msg)
{
if (tok)
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 1c13eeaf7d4..bc8f7010e83 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -145,6 +145,14 @@ get_ultimate_base_class (const_type_p s)
s = s->u.s.base_class;
return s;
}
+
+static type_p
+get_ultimate_base_class (type_p s)
+{
+ while (s->u.s.base_class)
+ s = s->u.s.base_class;
+ return s;
+}
/* Input file handling. */
@@ -589,7 +597,7 @@ create_user_defined_type (const char *type_name, struct fileloc *pos)
/* We only accept simple template declarations (see
require_template_declaration), so we only need to parse a
comma-separated list of strings, implicitly assumed to
- be type names. */
+ be type names, potentially with "*" characters. */
char *arg = open_bracket + 1;
char *type_id = strtok (arg, ",>");
pair_p fields = 0;
@@ -597,8 +605,28 @@ create_user_defined_type (const char *type_name, struct fileloc *pos)
{
/* Create a new field for every type found inside the template
parameter list. */
- const char *field_name = xstrdup (type_id);
- type_p arg_type = resolve_typedef (field_name, pos);
+
+ /* Support a single trailing "*" character. */
+ const char *star = strchr (type_id, '*');
+ int is_ptr = (star != NULL);
+ size_t offset_to_star = star - type_id;
+ if (is_ptr)
+ offset_to_star = star - type_id;
+
+ char *field_name = xstrdup (type_id);
+
+ type_p arg_type;
+ if (is_ptr)
+ {
+ /* Strip off the first '*' character (and any subsequent text). */
+ *(field_name + offset_to_star) = '\0';
+
+ arg_type = find_structure (field_name, TYPE_STRUCT);
+ arg_type = create_pointer (arg_type);
+ }
+ else
+ arg_type = resolve_typedef (field_name, pos);
+
fields = create_field_at (fields, arg_type, field_name, 0, pos);
type_id = strtok (0, ",>");
}
@@ -1086,8 +1114,8 @@ gen_rtx_next (void)
int k;
rtx_next_new[i] = -1;
- if (strncmp (rtx_format[i], "iuu", 3) == 0)
- rtx_next_new[i] = 2;
+ if (strncmp (rtx_format[i], "uu", 2) == 0)
+ rtx_next_new[i] = 1;
else if (i == COND_EXEC || i == SET || i == EXPR_LIST || i == INSN_LIST)
rtx_next_new[i] = 1;
else
@@ -1227,19 +1255,19 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
case '0':
if (i == MEM && aindex == 1)
t = mem_attrs_tp, subname = "rt_mem";
- else if (i == JUMP_INSN && aindex == 8)
+ else if (i == JUMP_INSN && aindex == 7)
t = rtx_tp, subname = "rt_rtx";
- else if (i == CODE_LABEL && aindex == 5)
- t = scalar_tp, subname = "rt_int";
else if (i == CODE_LABEL && aindex == 4)
+ t = scalar_tp, subname = "rt_int";
+ else if (i == CODE_LABEL && aindex == 3)
t = rtx_tp, subname = "rt_rtx";
else if (i == LABEL_REF && (aindex == 1 || aindex == 2))
t = rtx_tp, subname = "rt_rtx";
- else if (i == NOTE && aindex == 4)
+ else if (i == NOTE && aindex == 3)
t = note_union_tp, subname = "";
- else if (i == NOTE && aindex == 5)
+ else if (i == NOTE && aindex == 4)
t = scalar_tp, subname = "rt_int";
- else if (i == NOTE && aindex >= 7)
+ else if (i == NOTE && aindex >= 6)
t = scalar_tp, subname = "rt_int";
else if (i == ADDR_DIFF_VEC && aindex == 4)
t = scalar_tp, subname = "rt_int";
@@ -1248,18 +1276,12 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
else if (i == DEBUG_EXPR && aindex == 0)
t = tree_tp, subname = "rt_tree";
else if (i == REG && aindex == 1)
- t = scalar_tp, subname = "rt_int";
- else if (i == REG && aindex == 2)
t = reg_attrs_tp, subname = "rt_reg";
- else if (i == SCRATCH && aindex == 0)
- t = scalar_tp, subname = "rt_int";
else if (i == SYMBOL_REF && aindex == 1)
- t = scalar_tp, subname = "rt_int";
- else if (i == SYMBOL_REF && aindex == 2)
t = symbol_union_tp, subname = "";
- else if (i == JUMP_TABLE_DATA && aindex >= 5)
+ else if (i == JUMP_TABLE_DATA && aindex >= 4)
t = scalar_tp, subname = "rt_int";
- else if (i == BARRIER && aindex >= 3)
+ else if (i == BARRIER && aindex >= 2)
t = scalar_tp, subname = "rt_int";
else if (i == ENTRY_VALUE && aindex == 0)
t = rtx_tp, subname = "rt_rtx";
@@ -2467,6 +2489,7 @@ struct write_types_data
const char *reorder_note_routine;
const char *comment;
int skip_hooks; /* skip hook generation if non zero */
+ enum write_types_kinds kind;
};
static void output_escaped_param (struct walk_type_data *d,
@@ -2543,7 +2566,8 @@ filter_type_name (const char *type_name)
size_t i;
char *s = xstrdup (type_name);
for (i = 0; i < strlen (s); i++)
- if (s[i] == '<' || s[i] == '>' || s[i] == ':' || s[i] == ',')
+ if (s[i] == '<' || s[i] == '>' || s[i] == ':' || s[i] == ','
+ || s[i] == '*')
s[i] = '_';
return s;
}
@@ -3507,10 +3531,10 @@ write_marker_function_name (outf_p of, type_p s, const char *prefix)
/* Write on OF a user-callable routine to act as an entry point for
the marking routine for S, generated by write_func_for_structure.
- PREFIX is the prefix to use to distinguish ggc and pch markers. */
+ WTD distinguishes between ggc and pch markers. */
static void
-write_user_func_for_structure_ptr (outf_p of, type_p s, const char *prefix)
+write_user_func_for_structure_ptr (outf_p of, type_p s, const write_types_data *wtd)
{
/* Parameterized structures are not supported in user markers. There
is no way for the marker function to know which specific type
@@ -3540,13 +3564,23 @@ write_user_func_for_structure_ptr (outf_p of, type_p s, const char *prefix)
break;
}
+ DBGPRINTF ("write_user_func_for_structure_ptr: %s %s", s->u.s.tag,
+ wtd->prefix);
+
+ /* Only write the function once. */
+ if (s->u.s.wrote_user_func_for_ptr[wtd->kind])
+ return;
+ s->u.s.wrote_user_func_for_ptr[wtd->kind] = true;
+
oprintf (of, "\nvoid\n");
- oprintf (of, "gt_%sx (", prefix);
+ oprintf (of, "gt_%sx (", wtd->prefix);
write_type_decl (of, s);
oprintf (of, " *& x)\n");
oprintf (of, "{\n");
oprintf (of, " if (x)\n ");
- write_marker_function_name (of, alias_of ? alias_of : s, prefix);
+ write_marker_function_name (of,
+ alias_of ? alias_of : get_ultimate_base_class (s),
+ wtd->prefix);
oprintf (of, " ((void *) x);\n");
oprintf (of, "}\n");
}
@@ -3584,7 +3618,8 @@ write_user_func_for_structure_body (type_p s, const char *prefix,
which just marks the fields of T. */
static void
-write_user_marking_functions (type_p s, const char *prefix,
+write_user_marking_functions (type_p s,
+ const write_types_data *w,
struct walk_type_data *d)
{
gcc_assert (s->kind == TYPE_USER_STRUCT);
@@ -3596,10 +3631,10 @@ write_user_marking_functions (type_p s, const char *prefix,
{
type_p pointed_to_type = fld_type->u.p;
if (union_or_struct_p (pointed_to_type))
- write_user_func_for_structure_ptr (d->of, pointed_to_type, prefix);
+ write_user_func_for_structure_ptr (d->of, pointed_to_type, w);
}
else if (union_or_struct_p (fld_type))
- write_user_func_for_structure_body (fld_type, prefix, d);
+ write_user_func_for_structure_body (fld_type, w->prefix, d);
}
}
@@ -3797,7 +3832,7 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param,
oprintf (d.of, "}\n");
if (orig_s->kind == TYPE_USER_STRUCT)
- write_user_marking_functions (orig_s, wtd->prefix, &d);
+ write_user_marking_functions (orig_s, wtd, &d);
}
@@ -3975,14 +4010,14 @@ write_types (outf_p output_header, type_p structures, type_p param_structs,
static const struct write_types_data ggc_wtd = {
"ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL,
"GC marker procedures. ",
- FALSE
+ FALSE, WTK_GGC
};
static const struct write_types_data pch_wtd = {
"pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object",
"gt_pch_note_reorder",
"PCH type-walking procedures. ",
- TRUE
+ TRUE, WTK_PCH
};
/* Write out the local pointer-walking routines. */
@@ -4937,130 +4972,6 @@ write_roots (pair_p variables, bool emit_pch)
"gt_pch_scalar_rtab");
}
-/* TRUE if type S has the GTY variable_size annotation. */
-
-static bool
-variable_size_p (const type_p s)
-{
- options_p o;
- for (o = s->u.s.opt; o; o = o->next)
- if (strcmp (o->name, "variable_size") == 0)
- return true;
- return false;
-}
-
-enum alloc_quantity
-{ single, vector };
-
-/* Writes one typed allocator definition into output F for type
- identifier TYPE_NAME with optional type specifier TYPE_SPECIFIER.
- The allocator name will contain ALLOCATOR_TYPE. If VARIABLE_SIZE
- is true, the allocator will have an extra parameter specifying
- number of bytes to allocate. If QUANTITY is set to VECTOR, a
- vector allocator will be output. */
-
-static void
-write_typed_alloc_def (outf_p f,
- bool variable_size, const char *type_specifier,
- const char *type_name, const char *allocator_type,
- enum alloc_quantity quantity)
-{
- bool two_args = variable_size && (quantity == vector);
- gcc_assert (f != NULL);
- const char *type_name_as_id = filter_type_name (type_name);
- oprintf (f, "#define ggc_alloc_%s%s", allocator_type, type_name_as_id);
- oprintf (f, "(%s%s%s) ",
- (variable_size ? "SIZE" : ""),
- (two_args ? ", " : ""),
- (quantity == vector) ? "n" : "");
- oprintf (f, "((%s%s *)", type_specifier, type_name);
- oprintf (f, "(ggc_internal_%salloc_stat (", allocator_type);
- if (variable_size)
- oprintf (f, "SIZE");
- else
- oprintf (f, "sizeof (%s%s)", type_specifier, type_name);
- if (quantity == vector)
- oprintf (f, ", n");
- oprintf (f, " MEM_STAT_INFO)))\n");
- if (type_name_as_id != type_name)
- free (CONST_CAST (char *, type_name_as_id));
-}
-
-/* Writes a typed allocator definition into output F for a struct or
- union S, with a given ALLOCATOR_TYPE and QUANTITY for ZONE. */
-
-static void
-write_typed_struct_alloc_def (outf_p f,
- const type_p s, const char *allocator_type,
- enum alloc_quantity quantity)
-{
- gcc_assert (union_or_struct_p (s));
- write_typed_alloc_def (f, variable_size_p (s), get_type_specifier (s),
- s->u.s.tag, allocator_type, quantity);
-}
-
-/* Writes a typed allocator definition into output F for a typedef P,
- with a given ALLOCATOR_TYPE and QUANTITY for ZONE. */
-
-static void
-write_typed_typedef_alloc_def (outf_p f,
- const pair_p p, const char *allocator_type,
- enum alloc_quantity quantity)
-{
- write_typed_alloc_def (f, variable_size_p (p->type), "", p->name,
- allocator_type, quantity);
-}
-
-/* Writes typed allocator definitions into output F for the types in
- STRUCTURES and TYPEDEFS that are used by GC. */
-
-static void
-write_typed_alloc_defns (outf_p f,
- const type_p structures, const pair_p typedefs)
-{
- type_p s;
- pair_p p;
-
- gcc_assert (f != NULL);
- oprintf (f,
- "\n/* Allocators for known structs and unions. */\n\n");
- for (s = structures; s; s = s->next)
- {
- if (!USED_BY_TYPED_GC_P (s))
- continue;
- gcc_assert (union_or_struct_p (s));
- /* In plugin mode onput output ggc_alloc macro definitions
- relevant to plugin input files. */
- if (nb_plugin_files > 0
- && ((s->u.s.line.file == NULL) || !s->u.s.line.file->inpisplugin))
- continue;
- write_typed_struct_alloc_def (f, s, "", single);
- write_typed_struct_alloc_def (f, s, "cleared_", single);
- write_typed_struct_alloc_def (f, s, "vec_", vector);
- write_typed_struct_alloc_def (f, s, "cleared_vec_", vector);
- }
-
- oprintf (f, "\n/* Allocators for known typedefs. */\n");
- for (p = typedefs; p; p = p->next)
- {
- s = p->type;
- if (!USED_BY_TYPED_GC_P (s) || (strcmp (p->name, s->u.s.tag) == 0))
- continue;
- /* In plugin mode onput output ggc_alloc macro definitions
- relevant to plugin input files. */
- if (nb_plugin_files > 0)
- {
- struct fileloc* filoc = type_fileloc (s);
- if (!filoc || !filoc->file->inpisplugin)
- continue;
- };
- write_typed_typedef_alloc_def (f, p, "", single);
- write_typed_typedef_alloc_def (f, p, "cleared_", single);
- write_typed_typedef_alloc_def (f, p, "vec_", vector);
- write_typed_typedef_alloc_def (f, p, "cleared_vec_", vector);
- }
-}
-
/* Prints not-as-ugly version of a typename of T to OF. Trades the uniquness
guaranteee for somewhat increased readability. If name conflicts do happen,
this funcion will have to be adjusted to be more like
@@ -5671,6 +5582,7 @@ main (int argc, char **argv)
POS_HERE (do_scalar_typedef ("double_int", &pos));
POS_HERE (do_scalar_typedef ("offset_int", &pos));
POS_HERE (do_scalar_typedef ("widest_int", &pos));
+ POS_HERE (do_scalar_typedef ("int64_t", &pos));
POS_HERE (do_scalar_typedef ("uint64_t", &pos));
POS_HERE (do_scalar_typedef ("uint8", &pos));
POS_HERE (do_scalar_typedef ("uintptr_t", &pos));
@@ -5773,7 +5685,6 @@ main (int argc, char **argv)
open_base_files ();
output_header = plugin_output ? plugin_output : header_file;
- write_typed_alloc_defns (output_header, structures, typedefs);
DBGPRINT_COUNT_TYPE ("structures before write_types outputheader",
structures);
DBGPRINT_COUNT_TYPE ("param_structs before write_types outputheader",
diff --git a/gcc/gengtype.h b/gcc/gengtype.h
index 345a545d294..6369001e038 100644
--- a/gcc/gengtype.h
+++ b/gcc/gengtype.h
@@ -127,7 +127,15 @@ extern type_p structures;
extern type_p param_structs;
extern pair_p variables;
+/* An enum for distinguishing GGC vs PCH. */
+enum write_types_kinds
+{
+ WTK_GGC,
+ WTK_PCH,
+
+ NUM_WTK
+};
/* Discrimating kind of types we can understand. */
@@ -302,6 +310,10 @@ struct type {
type_p first_subclass;
/* The next in that list. */
type_p next_sibling_class;
+
+ /* Have we already written ggc/pch user func for ptr to this?
+ (in write_user_func_for_structure_ptr). */
+ bool wrote_user_func_for_ptr[NUM_WTK];
} s;
/* when TYPE_SCALAR: */
diff --git a/gcc/genoutput.c b/gcc/genoutput.c
index 26fb1acfde7..b3ce120f33a 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -781,6 +781,11 @@ validate_insn_alternatives (struct data *d)
for (p = d->operand[start].constraint; (c = *p); p += len)
{
+ if ((c == '%' || c == '=' || c == '+')
+ && p != d->operand[start].constraint)
+ error_with_line (d->lineno,
+ "character '%c' can only be used at the"
+ " beginning of a constraint string", c);
#ifdef USE_MD_CONSTRAINTS
if (ISSPACE (c) || strchr (indep_constraints, c))
len = 1;
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index 97c9b87fc16..b11a10c0072 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -174,22 +174,23 @@ ggc_mark_roots (void)
/* Allocate a block of memory, then clear it. */
void *
-ggc_internal_cleared_alloc_stat (size_t size MEM_STAT_DECL)
+ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t s, size_t n
+ MEM_STAT_DECL)
{
- void *buf = ggc_internal_alloc_stat (size PASS_MEM_STAT);
+ void *buf = ggc_internal_alloc (size, f, s, n PASS_MEM_STAT);
memset (buf, 0, size);
return buf;
}
/* Resize a block of memory, possibly re-allocating it. */
void *
-ggc_realloc_stat (void *x, size_t size MEM_STAT_DECL)
+ggc_realloc (void *x, size_t size MEM_STAT_DECL)
{
void *r;
size_t old_size;
if (x == NULL)
- return ggc_internal_alloc_stat (size PASS_MEM_STAT);
+ return ggc_internal_alloc (size PASS_MEM_STAT);
old_size = ggc_get_size (x);
@@ -211,7 +212,7 @@ ggc_realloc_stat (void *x, size_t size MEM_STAT_DECL)
return x;
}
- r = ggc_internal_alloc_stat (size PASS_MEM_STAT);
+ r = ggc_internal_alloc (size PASS_MEM_STAT);
/* Since ggc_get_size returns the size of the pool, not the size of the
individually allocated object, we'd access parts of the old object
@@ -232,7 +233,7 @@ ggc_cleared_alloc_htab_ignore_args (size_t c ATTRIBUTE_UNUSED,
size_t n ATTRIBUTE_UNUSED)
{
gcc_assert (c * n == sizeof (struct htab));
- return ggc_alloc_cleared_htab ();
+ return ggc_cleared_alloc<htab> ();
}
/* TODO: once we actually use type information in GGC, create a new tag
@@ -241,7 +242,7 @@ void *
ggc_cleared_alloc_ptr_array_two_args (size_t c, size_t n)
{
gcc_assert (sizeof (PTR *) == n);
- return ggc_internal_cleared_vec_alloc (sizeof (PTR *), c);
+ return ggc_cleared_vec_alloc<PTR *> (c);
}
/* These are for splay_tree_new_ggc. */
diff --git a/gcc/ggc-none.c b/gcc/ggc-none.c
index e6900195457..29a7b2f767a 100644
--- a/gcc/ggc-none.c
+++ b/gcc/ggc-none.c
@@ -41,14 +41,18 @@ ggc_round_alloc_size (size_t requested_size)
}
void *
-ggc_internal_alloc_stat (size_t size MEM_STAT_DECL)
+ggc_internal_alloc (size_t size, void (*f)(void *), size_t, size_t
+ MEM_STAT_DECL)
{
+ gcc_assert (!f); // ggc-none doesn't support finalizers
return xmalloc (size);
}
void *
-ggc_internal_cleared_alloc_stat (size_t size MEM_STAT_DECL)
+ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t, size_t
+ MEM_STAT_DECL)
{
+ gcc_assert (!f); // ggc-none doesn't support finalizers
return xcalloc (size, 1);
}
@@ -63,3 +67,8 @@ ggc_free (void *p)
{
free (p);
}
+
+void
+ggc_grow (void)
+{
+}
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index ccc87eaa5be..393954089f8 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -156,7 +156,7 @@ along with GCC; see the file COPYING3. If not see
struct max_alignment {
char c;
union {
- HOST_WIDEST_INT i;
+ int64_t i;
void *p;
} u;
};
@@ -332,6 +332,41 @@ typedef struct page_table_chain
#endif
+class finalizer
+{
+public:
+ finalizer (void *addr, void (*f)(void *)) : m_addr (addr), m_function (f) {}
+
+ void *addr () const { return m_addr; }
+
+ void call () const { m_function (m_addr); }
+
+private:
+ void *m_addr;
+ void (*m_function)(void *);
+};
+
+class vec_finalizer
+{
+public:
+ vec_finalizer (uintptr_t addr, void (*f)(void *), size_t s, size_t n) :
+ m_addr (addr), m_function (f), m_object_size (s), m_n_objects (n) {}
+
+ void call () const
+ {
+ for (size_t i = 0; i < m_n_objects; i++)
+ m_function (reinterpret_cast<void *> (m_addr + (i * m_object_size)));
+ }
+
+ void *addr () const { return reinterpret_cast<void *> (m_addr); }
+
+private:
+ uintptr_t m_addr;
+ void (*m_function)(void *);
+ size_t m_object_size;
+ size_t m_n_objects;
+ };
+
#ifdef ENABLE_GC_ALWAYS_COLLECT
/* List of free objects to be verified as actually free on the
next collection. */
@@ -425,6 +460,12 @@ static struct globals
better runtime data access pattern. */
unsigned long **save_in_use;
+ /* Finalizers for single objects. */
+ vec<finalizer> finalizers;
+
+ /* Finalizers for vectors of objects. */
+ vec<vec_finalizer> vec_finalizers;
+
#ifdef ENABLE_GC_ALWAYS_COLLECT
/* List of free objects to be verified as actually free on the
next collection. */
@@ -1202,7 +1243,8 @@ ggc_round_alloc_size (size_t requested_size)
/* Allocate a chunk of memory of SIZE bytes. Its contents are undefined. */
void *
-ggc_internal_alloc_stat (size_t size MEM_STAT_DECL)
+ggc_internal_alloc (size_t size, void (*f)(void *), size_t s, size_t n
+ MEM_STAT_DECL)
{
size_t order, word, bit, object_offset, object_size;
struct page_entry *entry;
@@ -1345,6 +1387,12 @@ ggc_internal_alloc_stat (size_t size MEM_STAT_DECL)
/* For timevar statistics. */
timevar_ggc_mem_total += object_size;
+ if (f && n == 1)
+ G.finalizers.safe_push (finalizer (result, f));
+ else if (f)
+ G.vec_finalizers.safe_push
+ (vec_finalizer (reinterpret_cast<uintptr_t> (result), f, s, n));
+
if (GATHER_STATISTICS)
{
size_t overhead = object_size - size;
@@ -1811,6 +1859,47 @@ clear_marks (void)
}
}
+/* Check if any blocks with a registered finalizer have become unmarked. If so
+ run the finalizer and unregister it because the block is about to be freed.
+ Note that no garantee is made about what order finalizers will run in so
+ touching other objects in gc memory is extremely unwise. */
+
+static void
+ggc_handle_finalizers ()
+{
+ if (G.context_depth != 0)
+ return;
+
+ unsigned length = G.finalizers.length ();
+ for (unsigned int i = 0; i < length;)
+ {
+ finalizer &f = G.finalizers[i];
+ if (!ggc_marked_p (f.addr ()))
+ {
+ f.call ();
+ G.finalizers.unordered_remove (i);
+ length--;
+ }
+ else
+ i++;
+ }
+
+
+ length = G.vec_finalizers.length ();
+ for (unsigned int i = 0; i < length;)
+ {
+ vec_finalizer &f = G.vec_finalizers[i];
+ if (!ggc_marked_p (f.addr ()))
+ {
+ f.call ();
+ G.vec_finalizers.unordered_remove (i);
+ length--;
+ }
+ else
+ i++;
+ }
+}
+
/* Free all empty pages. Partially empty pages need no attention
because the `mark' bit doubles as an `unused' bit. */
@@ -2075,6 +2164,7 @@ ggc_collect (void)
clear_marks ();
ggc_mark_roots ();
+ ggc_handle_finalizers ();
if (GATHER_STATISTICS)
ggc_prune_overhead_list ();
@@ -2095,6 +2185,23 @@ ggc_collect (void)
fprintf (G.debug_file, "END COLLECTING\n");
}
+/* Assume that all GGC memory is reachable and grow the limits for next collection.
+ With checking, trigger GGC so -Q compilation outputs how much of memory really is
+ reachable. */
+
+void
+ggc_grow (void)
+{
+#ifndef ENABLE_CHECKING
+ G.allocated_last_gc = MAX (G.allocated_last_gc,
+ G.allocated);
+#else
+ ggc_collect ();
+#endif
+ if (!quiet_flag)
+ fprintf (stderr, " {GC start %luk} ", (unsigned long) G.allocated / 1024);
+}
+
/* Print allocation statistics. */
#define SCALE(x) ((unsigned long) ((x) < 1024*10 \
? (x) \
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 55f3fe9b0bc..1c0fd3d1ba5 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -136,58 +136,117 @@ extern void gt_pch_save (FILE *f);
/* Allocation. */
/* The internal primitive. */
-extern void *ggc_internal_alloc_stat (size_t MEM_STAT_DECL)
- ATTRIBUTE_MALLOC;
+extern void *ggc_internal_alloc (size_t, void (*)(void *), size_t,
+ size_t CXX_MEM_STAT_INFO)
+ ATTRIBUTE_MALLOC;
-extern size_t ggc_round_alloc_size (size_t requested_size);
+ static inline
+ void *
+ ggc_internal_alloc (size_t s CXX_MEM_STAT_INFO)
+{
+ return ggc_internal_alloc (s, NULL, 0, 1 PASS_MEM_STAT);
+}
-#define ggc_internal_alloc(s) ggc_internal_alloc_stat (s MEM_STAT_INFO)
+extern size_t ggc_round_alloc_size (size_t requested_size);
/* Allocates cleared memory. */
-extern void *ggc_internal_cleared_alloc_stat (size_t MEM_STAT_DECL)
- ATTRIBUTE_MALLOC;
-#define ggc_internal_cleared_alloc(s) ggc_internal_cleared_alloc_stat (s MEM_STAT_INFO)
+extern void *ggc_internal_cleared_alloc (size_t, void (*)(void *),
+ size_t, size_t
+ CXX_MEM_STAT_INFO) ATTRIBUTE_MALLOC;
+
+static inline
+void *
+ggc_internal_cleared_alloc (size_t s CXX_MEM_STAT_INFO)
+{
+ return ggc_internal_cleared_alloc (s, NULL, 0, 1 PASS_MEM_STAT);
+}
/* Resize a block. */
-extern void *ggc_realloc_stat (void *, size_t MEM_STAT_DECL);
+extern void *ggc_realloc (void *, size_t CXX_MEM_STAT_INFO);
/* Free a block. To be used when known for certain it's not reachable. */
extern void ggc_free (void *);
extern void dump_ggc_loc_statistics (bool);
-/* Reallocators. */
+/* Reallocator. */
#define GGC_RESIZEVEC(T, P, N) \
- ((T *) ggc_realloc_stat ((P), (N) * sizeof (T) MEM_STAT_INFO))
+ ((T *) ggc_realloc ((P), (N) * sizeof (T) MEM_STAT_INFO))
-#define GGC_RESIZEVAR(T, P, N) \
- ((T *) ggc_realloc_stat ((P), (N) MEM_STAT_INFO))
+template<typename T>
+void
+finalize (void *p)
+{
+ static_cast<T *> (p)->~T ();
+}
-static inline void *
-ggc_internal_vec_alloc_stat (size_t s, size_t c MEM_STAT_DECL)
+template<typename T>
+static inline bool
+need_finalization_p ()
{
- return ggc_internal_alloc_stat (c * s PASS_MEM_STAT);
+#if GCC_VERSION >= 4003
+ return !__has_trivial_destructor (T);
+#else
+ return true;
+#endif
}
-static inline void *
-ggc_internal_cleared_vec_alloc_stat (size_t s, size_t c MEM_STAT_DECL)
+template<typename T>
+static inline T *
+ggc_alloc (ALONE_CXX_MEM_STAT_INFO)
{
- return ggc_internal_cleared_alloc_stat (c * s PASS_MEM_STAT);
+ if (need_finalization_p<T> ())
+ return static_cast<T *> (ggc_internal_alloc (sizeof (T), finalize<T>, 0, 1
+ PASS_MEM_STAT));
+ else
+ return static_cast<T *> (ggc_internal_alloc (sizeof (T), NULL, 0, 1
+ PASS_MEM_STAT));
}
-#define ggc_internal_cleared_vec_alloc(s, c) \
- (ggc_internal_cleared_vec_alloc_stat ((s), (c) MEM_STAT_INFO))
+template<typename T>
+static inline T *
+ggc_cleared_alloc (ALONE_CXX_MEM_STAT_INFO)
+{
+ if (need_finalization_p<T> ())
+ return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T),
+ finalize<T>, 0, 1
+ PASS_MEM_STAT));
+ else
+ return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T), NULL, 0, 1
+ PASS_MEM_STAT));
+}
-static inline void *
-ggc_alloc_atomic_stat (size_t s MEM_STAT_DECL)
+template<typename T>
+static inline T *
+ggc_vec_alloc (size_t c CXX_MEM_STAT_INFO)
{
- return ggc_internal_alloc_stat (s PASS_MEM_STAT);
+ if (need_finalization_p<T> ())
+ return static_cast<T *> (ggc_internal_alloc (c * sizeof (T), finalize<T>,
+ sizeof (T), c PASS_MEM_STAT));
+ else
+ return static_cast<T *> (ggc_internal_alloc (c * sizeof (T), NULL, 0, 0
+ PASS_MEM_STAT));
}
-#define ggc_alloc_atomic(S) (ggc_alloc_atomic_stat ((S) MEM_STAT_INFO))
+template<typename T>
+static inline T *
+ggc_cleared_vec_alloc (size_t c CXX_MEM_STAT_INFO)
+{
+ if (need_finalization_p<T> ())
+ return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T),
+ finalize<T>,
+ sizeof (T), c
+ PASS_MEM_STAT));
+ else
+ return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T), NULL,
+ 0, 0 PASS_MEM_STAT));
+}
-#define ggc_alloc_cleared_atomic(S) \
- (ggc_internal_cleared_alloc_stat ((S) MEM_STAT_INFO))
+static inline void *
+ggc_alloc_atomic (size_t s CXX_MEM_STAT_INFO)
+{
+ return ggc_internal_alloc (s PASS_MEM_STAT);
+}
extern void *ggc_cleared_alloc_htab_ignore_args (size_t, size_t)
ATTRIBUTE_MALLOC;
@@ -213,18 +272,19 @@ extern void ggc_splay_dont_free (void *, void *);
/* Allocate a gc-able string, and fill it with LENGTH bytes from CONTENTS.
If LENGTH is -1, then CONTENTS is assumed to be a
null-terminated string and the memory sized accordingly. */
-extern const char *ggc_alloc_string_stat (const char *contents, int length
- MEM_STAT_DECL);
-
-#define ggc_alloc_string(c, l) ggc_alloc_string_stat (c, l MEM_STAT_INFO)
+extern const char *ggc_alloc_string (const char *contents, int length
+ CXX_MEM_STAT_INFO);
/* Make a copy of S, in GC-able memory. */
-#define ggc_strdup(S) ggc_alloc_string_stat ((S), -1 MEM_STAT_INFO)
+#define ggc_strdup(S) ggc_alloc_string ((S), -1 MEM_STAT_INFO)
/* Invoke the collector. Garbage collection occurs only when this
function is called, not during allocations. */
extern void ggc_collect (void);
+/* Assume that all GGC memory is reachable and grow the limits for next collection. */
+extern void ggc_grow (void);
+
/* Register an additional root table. This can be useful for some
plugins. Does nothing if the passed pointer is NULL. */
extern void ggc_register_root_tab (const struct ggc_root_tab *);
@@ -247,41 +307,34 @@ extern void stringpool_statistics (void);
extern void init_ggc_heuristics (void);
#define ggc_alloc_rtvec_sized(NELT) \
- ggc_alloc_rtvec_def (sizeof (struct rtvec_def) \
+ (rtvec_def *) ggc_internal_alloc (sizeof (struct rtvec_def) \
+ ((NELT) - 1) * sizeof (rtx)) \
/* Memory statistics passing versions of some allocators. Too few of them to
make gengtype produce them, so just define the needed ones here. */
static inline struct rtx_def *
-ggc_alloc_rtx_def_stat (size_t s MEM_STAT_DECL)
+ggc_alloc_rtx_def_stat (size_t s CXX_MEM_STAT_INFO)
{
- return (struct rtx_def *) ggc_internal_alloc_stat (s PASS_MEM_STAT);
+ return (struct rtx_def *) ggc_internal_alloc (s PASS_MEM_STAT);
}
static inline union tree_node *
-ggc_alloc_tree_node_stat (size_t s MEM_STAT_DECL)
+ggc_alloc_tree_node_stat (size_t s CXX_MEM_STAT_INFO)
{
- return (union tree_node *) ggc_internal_alloc_stat (s PASS_MEM_STAT);
+ return (union tree_node *) ggc_internal_alloc (s PASS_MEM_STAT);
}
static inline union tree_node *
-ggc_alloc_cleared_tree_node_stat (size_t s MEM_STAT_DECL)
+ggc_alloc_cleared_tree_node_stat (size_t s CXX_MEM_STAT_INFO)
{
- return (union tree_node *) ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
+ return (union tree_node *) ggc_internal_cleared_alloc (s PASS_MEM_STAT);
}
static inline struct gimple_statement_base *
-ggc_alloc_cleared_gimple_statement_stat (size_t s MEM_STAT_DECL)
+ggc_alloc_cleared_gimple_statement_stat (size_t s CXX_MEM_STAT_INFO)
{
return (struct gimple_statement_base *)
- ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
-}
-
-static inline struct simd_clone *
-ggc_alloc_cleared_simd_clone_stat (size_t s MEM_STAT_DECL)
-{
- return (struct simd_clone *)
- ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
+ ggc_internal_cleared_alloc (s PASS_MEM_STAT);
}
#endif
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 9d42e6af685..403dee707a3 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -52,6 +52,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-address.h"
#include "langhooks.h"
#include "gimplify-me.h"
+#include "dbgcnt.h"
+#include "builtins.h"
/* Return true when DECL can be referenced from current unit.
FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
@@ -93,8 +95,12 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl)
/* Static objects can be referred only if they was not optimized out yet. */
if (!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
{
+ /* Before we start optimizing unreachable code we can be sure all
+ static objects are defined. */
+ if (cgraph_function_flags_ready)
+ return true;
snode = symtab_get_node (decl);
- if (!snode)
+ if (!snode || !snode->definition)
return false;
node = dyn_cast <cgraph_node *> (snode);
return !node || !node->global.inlined_to;
@@ -102,12 +108,15 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl)
/* We will later output the initializer, so we can refer to it.
So we are concerned only when DECL comes from initializer of
- external var. */
+ external var or var that has been optimized out. */
if (!from_decl
|| TREE_CODE (from_decl) != VAR_DECL
- || !DECL_EXTERNAL (from_decl)
+ || (!DECL_EXTERNAL (from_decl)
+ && (vnode = varpool_get_node (from_decl)) != NULL
+ && vnode->definition)
|| (flag_ltrans
- && symtab_get_node (from_decl)->in_other_partition))
+ && (vnode = varpool_get_node (from_decl)) != NULL
+ && vnode->in_other_partition))
return true;
/* We are folding reference from external vtable. The vtable may reffer
to a symbol keyed to other compilation unit. The other compilation
@@ -122,9 +131,9 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl)
reference imply need to include function body in the curren tunit. */
if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
return true;
- /* We are not at ltrans stage; so don't worry about WHOPR.
- Also when still gimplifying all referred comdat functions will be
- produced.
+ /* We have COMDAT. We are going to check if we still have definition
+ or if the definition is going to be output in other partition.
+ Bypass this when gimplifying; all needed functions will be produced.
As observed in PR20991 for already optimized out comdat virtual functions
it may be tempting to not necessarily give up because the copy will be
@@ -133,35 +142,17 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl)
units where they are used and when the other unit was compiled with LTO
it is possible that vtable was kept public while the function itself
was privatized. */
- if (!flag_ltrans && (!DECL_COMDAT (decl) || !cgraph_function_flags_ready))
+ if (!cgraph_function_flags_ready)
return true;
- /* OK we are seeing either COMDAT or static variable. In this case we must
- check that the definition is still around so we can refer it. */
- if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- node = cgraph_get_node (decl);
- /* Check that we still have function body and that we didn't took
- the decision to eliminate offline copy of the function yet.
- The second is important when devirtualization happens during final
- compilation stage when making a new reference no longer makes callee
- to be compiled. */
- if (!node || !node->definition || node->global.inlined_to)
- {
- gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
- return false;
- }
- }
- else if (TREE_CODE (decl) == VAR_DECL)
- {
- vnode = varpool_get_node (decl);
- if (!vnode || !vnode->definition)
- {
- gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
- return false;
- }
- }
- return true;
+ snode = symtab_get_node (decl);
+ if (!snode
+ || ((!snode->definition || DECL_EXTERNAL (decl))
+ && (!snode->in_other_partition
+ || (!snode->forced_by_abi && !snode->force_output))))
+ return false;
+ node = dyn_cast <cgraph_node *> (snode);
+ return !node || !node->global.inlined_to;
}
/* CVAL is value taken from DECL_INITIAL of variable. Try to transform it into
@@ -386,13 +377,24 @@ fold_gimple_assign (gimple_stmt_iterator *si)
bool final;
vec <cgraph_node *>targets
= possible_polymorphic_call_targets (val, &final);
- if (final && targets.length () <= 1)
+ if (final && targets.length () <= 1 && dbg_cnt (devirt))
{
tree fndecl;
+
if (targets.length () == 1)
fndecl = targets[0]->decl;
else
fndecl = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
+ if (dump_enabled_p ())
+ {
+ location_t loc = gimple_location (stmt);
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+ "resolving virtual function address "
+ "reference to function %s\n",
+ targets.length () == 1
+ ? targets[0]->name ()
+ : "__builtin_unreachable");
+ }
val = fold_convert (TREE_TYPE (val), fndecl);
STRIP_USELESS_TYPE_CONVERSION (val);
return val;
@@ -1124,9 +1126,18 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
bool final;
vec <cgraph_node *>targets
= possible_polymorphic_call_targets (callee, &final);
- if (final && targets.length () <= 1)
+ if (final && targets.length () <= 1 && dbg_cnt (devirt))
{
tree lhs = gimple_call_lhs (stmt);
+ if (dump_enabled_p ())
+ {
+ location_t loc = gimple_location (stmt);
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+ "folding virtual function call to %s\n",
+ targets.length () == 1
+ ? targets[0]->name ()
+ : "__builtin_unreachable");
+ }
if (targets.length () == 1)
{
gimple_call_set_fndecl (stmt, targets[0]->decl);
@@ -2635,23 +2646,8 @@ gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree))
/* Handle unary operators that can appear in GIMPLE form.
Note that we know the single operand must be a constant,
so this should almost always return a simplified RHS. */
- tree lhs = gimple_assign_lhs (stmt);
tree op0 = (*valueize) (gimple_assign_rhs1 (stmt));
- /* Conversions are useless for CCP purposes if they are
- value-preserving. Thus the restrictions that
- useless_type_conversion_p places for restrict qualification
- of pointer types should not apply here.
- Substitution later will only substitute to allowed places. */
- if (CONVERT_EXPR_CODE_P (subcode)
- && POINTER_TYPE_P (TREE_TYPE (lhs))
- && POINTER_TYPE_P (TREE_TYPE (op0))
- && TYPE_ADDR_SPACE (TREE_TYPE (lhs))
- == TYPE_ADDR_SPACE (TREE_TYPE (op0))
- && TYPE_MODE (TREE_TYPE (lhs))
- == TYPE_MODE (TREE_TYPE (op0)))
- return op0;
-
return
fold_unary_ignore_overflow_loc (loc, subcode,
gimple_expr_type (stmt), op0);
diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c
index a41d9722dae..fae2c562b32 100644
--- a/gcc/gimple-ssa-strength-reduction.c
+++ b/gcc/gimple-ssa-strength-reduction.c
@@ -64,6 +64,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-address.h"
#include "tree-affine.h"
#include "wide-int-print.h"
+#include "builtins.h"
/* Information about a strength reduction candidate. Each statement
in the candidate table represents an expression of one of the
diff --git a/gcc/gimple.c b/gcc/gimple.c
index d6bc15bf424..03a84fb44f6 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -835,9 +835,7 @@ gimple_build_omp_for (gimple_seq body, int kind, tree clauses, size_t collapse,
gimple_omp_for_set_clauses (p, clauses);
gimple_omp_for_set_kind (p, kind);
p->collapse = collapse;
- p->iter = static_cast <struct gimple_omp_for_iter *> (
- ggc_internal_cleared_vec_alloc_stat (sizeof (*p->iter),
- collapse MEM_STAT_INFO));
+ p->iter = ggc_cleared_vec_alloc<gimple_omp_for_iter> (collapse);
if (pre_body)
gimple_omp_for_set_pre_body (p, pre_body);
@@ -1665,11 +1663,8 @@ gimple_copy (gimple stmt)
{
gimple_statement_omp_for *omp_for_copy =
as_a <gimple_statement_omp_for *> (copy);
- omp_for_copy->iter =
- static_cast <struct gimple_omp_for_iter *> (
- ggc_internal_vec_alloc_stat (sizeof (struct gimple_omp_for_iter),
- gimple_omp_for_collapse (stmt)
- MEM_STAT_INFO));
+ omp_for_copy->iter = ggc_vec_alloc<gimple_omp_for_iter>
+ ( gimple_omp_for_collapse (stmt));
}
for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
{
@@ -2376,7 +2371,7 @@ validate_type (tree type1, tree type2)
a decl of a builtin function. */
bool
-gimple_builtin_call_types_compatible_p (gimple stmt, tree fndecl)
+gimple_builtin_call_types_compatible_p (const_gimple stmt, tree fndecl)
{
gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN);
@@ -2405,7 +2400,7 @@ gimple_builtin_call_types_compatible_p (gimple stmt, tree fndecl)
/* Return true when STMT is builtins call. */
bool
-gimple_call_builtin_p (gimple stmt)
+gimple_call_builtin_p (const_gimple stmt)
{
tree fndecl;
if (is_gimple_call (stmt)
@@ -2418,7 +2413,7 @@ gimple_call_builtin_p (gimple stmt)
/* Return true when STMT is builtins call to CLASS. */
bool
-gimple_call_builtin_p (gimple stmt, enum built_in_class klass)
+gimple_call_builtin_p (const_gimple stmt, enum built_in_class klass)
{
tree fndecl;
if (is_gimple_call (stmt)
@@ -2431,7 +2426,7 @@ gimple_call_builtin_p (gimple stmt, enum built_in_class klass)
/* Return true when STMT is builtins call to CODE of CLASS. */
bool
-gimple_call_builtin_p (gimple stmt, enum built_in_function code)
+gimple_call_builtin_p (const_gimple stmt, enum built_in_function code)
{
tree fndecl;
if (is_gimple_call (stmt)
diff --git a/gcc/gimple.h b/gcc/gimple.h
index edb46351ea6..ceefbc0890f 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -91,17 +91,19 @@ enum gf_mask {
GF_CALL_ALLOCA_FOR_VAR = 1 << 5,
GF_CALL_INTERNAL = 1 << 6,
GF_OMP_PARALLEL_COMBINED = 1 << 0,
- GF_OMP_FOR_KIND_MASK = 3 << 0,
- GF_OMP_FOR_KIND_FOR = 0 << 0,
- GF_OMP_FOR_KIND_DISTRIBUTE = 1 << 0,
- GF_OMP_FOR_KIND_SIMD = 2 << 0,
- GF_OMP_FOR_KIND_CILKSIMD = 3 << 0,
+ GF_OMP_FOR_KIND_MASK = (1 << 2) - 1,
+ GF_OMP_FOR_KIND_FOR = 0,
+ GF_OMP_FOR_KIND_DISTRIBUTE = 1,
+ /* Flag for SIMD variants of OMP_FOR kinds. */
+ GF_OMP_FOR_SIMD = 1 << 1,
+ GF_OMP_FOR_KIND_SIMD = GF_OMP_FOR_SIMD | 0,
+ GF_OMP_FOR_KIND_CILKSIMD = GF_OMP_FOR_SIMD | 1,
GF_OMP_FOR_COMBINED = 1 << 2,
GF_OMP_FOR_COMBINED_INTO = 1 << 3,
- GF_OMP_TARGET_KIND_MASK = 3 << 0,
- GF_OMP_TARGET_KIND_REGION = 0 << 0,
- GF_OMP_TARGET_KIND_DATA = 1 << 0,
- GF_OMP_TARGET_KIND_UPDATE = 2 << 0,
+ GF_OMP_TARGET_KIND_MASK = (1 << 2) - 1,
+ GF_OMP_TARGET_KIND_REGION = 0,
+ GF_OMP_TARGET_KIND_DATA = 1,
+ GF_OMP_TARGET_KIND_UPDATE = 2,
/* True on an GIMPLE_OMP_RETURN statement if the return does not require
a thread synchronization via some sort of barrier. The exact barrier
@@ -1256,10 +1258,10 @@ extern tree gimple_unsigned_type (tree);
extern tree gimple_signed_type (tree);
extern alias_set_type gimple_get_alias_set (tree);
extern bool gimple_ior_addresses_taken (bitmap, gimple);
-extern bool gimple_builtin_call_types_compatible_p (gimple, tree);
-extern bool gimple_call_builtin_p (gimple);
-extern bool gimple_call_builtin_p (gimple, enum built_in_class);
-extern bool gimple_call_builtin_p (gimple, enum built_in_function);
+extern bool gimple_builtin_call_types_compatible_p (const_gimple, tree);
+extern bool gimple_call_builtin_p (const_gimple);
+extern bool gimple_call_builtin_p (const_gimple, enum built_in_class);
+extern bool gimple_call_builtin_p (const_gimple, enum built_in_function);
extern bool gimple_asm_clobbers_memory_p (const_gimple);
extern void dump_decl_set (FILE *, bitmap);
extern bool nonfreeing_call_p (gimple);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 37c3778624f..92714b59549 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name */
#include "tree-pass.h" /* FIXME: only for PROP_gimple_any */
+#include "builtins.h"
enum gimplify_omp_var_data
{
@@ -2329,8 +2330,8 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
parms = NULL_TREE;
if (fndecl)
parms = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
- else if (POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_FN (*expr_p))))
- parms = TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (*expr_p))));
+ else
+ parms = TYPE_ARG_TYPES (TREE_TYPE (fnptrtype));
if (fndecl && DECL_ARGUMENTS (fndecl))
p = DECL_ARGUMENTS (fndecl);
@@ -5683,7 +5684,13 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
switch (default_kind)
{
case OMP_CLAUSE_DEFAULT_NONE:
- if ((ctx->region_type & ORT_TASK) != 0)
+ if ((ctx->region_type & ORT_PARALLEL) != 0)
+ {
+ error ("%qE not specified in enclosing parallel",
+ DECL_NAME (lang_hooks.decls.omp_report_decl (decl)));
+ error_at (ctx->location, "enclosing parallel");
+ }
+ else if ((ctx->region_type & ORT_TASK) != 0)
{
error ("%qE not specified in enclosing task",
DECL_NAME (lang_hooks.decls.omp_report_decl (decl)));
@@ -5696,11 +5703,7 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
error_at (ctx->location, "enclosing teams construct");
}
else
- {
- error ("%qE not specified in enclosing parallel",
- DECL_NAME (lang_hooks.decls.omp_report_decl (decl)));
- error_at (ctx->location, "enclosing parallel");
- }
+ gcc_unreachable ();
/* FALLTHRU */
case OMP_CLAUSE_DEFAULT_SHARED:
flags |= GOVD_SHARED;
@@ -6069,6 +6072,27 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
gimplify_omp_ctxp = outer_ctx;
}
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
+ && OMP_CLAUSE_LINEAR_STMT (c))
+ {
+ gimplify_omp_ctxp = ctx;
+ push_gimplify_context ();
+ if (TREE_CODE (OMP_CLAUSE_LINEAR_STMT (c)) != BIND_EXPR)
+ {
+ tree bind = build3 (BIND_EXPR, void_type_node, NULL,
+ NULL, NULL);
+ TREE_SIDE_EFFECTS (bind) = 1;
+ BIND_EXPR_BODY (bind) = OMP_CLAUSE_LINEAR_STMT (c);
+ OMP_CLAUSE_LINEAR_STMT (c) = bind;
+ }
+ gimplify_and_add (OMP_CLAUSE_LINEAR_STMT (c),
+ &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
+ pop_gimplify_context
+ (gimple_seq_first_stmt (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c)));
+ OMP_CLAUSE_LINEAR_STMT (c) = NULL_TREE;
+
+ gimplify_omp_ctxp = outer_ctx;
+ }
if (notice_outer)
goto do_notice;
break;
diff --git a/gcc/ginclude/stddef.h b/gcc/ginclude/stddef.h
index cfa8df3097c..62e893a011e 100644
--- a/gcc/ginclude/stddef.h
+++ b/gcc/ginclude/stddef.h
@@ -133,6 +133,7 @@ _TYPE_wchar_t;
#ifndef _BSD_PTRDIFF_T_
#ifndef ___int_ptrdiff_t_h
#ifndef _GCC_PTRDIFF_T
+#ifndef _PTRDIFF_T_DECLARED /* DragonFly */
#define _PTRDIFF_T
#define _T_PTRDIFF_
#define _T_PTRDIFF
@@ -141,10 +142,12 @@ _TYPE_wchar_t;
#define _BSD_PTRDIFF_T_
#define ___int_ptrdiff_t_h
#define _GCC_PTRDIFF_T
+#define _PTRDIFF_T_DECLARED
#ifndef __PTRDIFF_TYPE__
#define __PTRDIFF_TYPE__ long int
#endif
typedef __PTRDIFF_TYPE__ ptrdiff_t;
+#endif /* _PTRDIFF_T_DECLARED */
#endif /* _GCC_PTRDIFF_T */
#endif /* ___int_ptrdiff_t_h */
#endif /* _BSD_PTRDIFF_T_ */
@@ -198,6 +201,7 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t;
#define _GCC_SIZE_T
#define _SIZET_
#if (defined (__FreeBSD__) && (__FreeBSD__ >= 5)) \
+ || defined(__DragonFly__) \
|| defined(__FreeBSD_kernel__)
/* __size_t is a typedef on FreeBSD 5, must not trash it. */
#elif defined (__VMS__)
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 26a1c45791c..d66b753a68b 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,11 @@
+2014-06-02 Andrew MacLeod <amacleod@redhat.com>
+
+ * go-gcc.cc: Include builtins.h.
+
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * go-lang.c (struct GTY): Don't use variable_size gty attribute.
+
2014-05-06 Chris Manghane <cmang@google.com>
* go-gcc.cc (Gcc_backend::nil_pointer_expression): New method.
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index fc100e2389c..5b95e5d133a 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -39,6 +39,7 @@
#include "output.h"
#include "real.h"
#include "realmpfr.h"
+#include "builtins.h"
#include "go-c.h"
diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
index f6e865e08cf..24b64375469 100644
--- a/gcc/go/go-lang.c
+++ b/gcc/go/go-lang.c
@@ -51,7 +51,7 @@ struct GTY(()) lang_type
/* Language-dependent contents of a decl. */
-struct GTY((variable_size)) lang_decl
+struct GTY(()) lang_decl
{
char dummy;
};
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 5d16b4d0f94..0e1800a6332 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -345,7 +345,7 @@ size_t dfa_state_size;
/* The following array is used to find the best insn from ready when
the automaton pipeline interface is used. */
-char *ready_try = NULL;
+signed char *ready_try = NULL;
/* The ready list. */
struct ready_list ready = {NULL, 0, 0, 0, 0};
@@ -859,8 +859,6 @@ static rtx ready_remove_first_dispatch (struct ready_list *ready);
static void queue_to_ready (struct ready_list *);
static int early_queue_to_ready (state_t, struct ready_list *);
-static void debug_ready_list (struct ready_list *);
-
/* The following functions are used to implement multi-pass scheduling
on the first cycle. */
static rtx ready_remove (struct ready_list *, int);
@@ -2971,7 +2969,7 @@ HAIFA_INLINE static void
advance_one_cycle (void)
{
advance_state (curr_state);
- if (sched_verbose >= 6)
+ if (sched_verbose >= 4)
fprintf (sched_dump, ";;\tAdvanced a state.\n");
}
@@ -3750,7 +3748,7 @@ schedule_insn (rtx insn)
if (sched_verbose >= 1)
{
struct reg_pressure_data *pressure_info;
- fprintf (sched_dump, ";;\t%3i--> %s%-40s:",
+ fprintf (sched_dump, ";;\t%3i--> %s %-40s:",
clock_var, (*current_sched_info->print_insn) (insn, 1),
str_pattern_slim (PATTERN (insn)));
@@ -3944,6 +3942,10 @@ schedule_insn (rtx insn)
last_clock_var = clock_var;
}
+ if (nonscheduled_insns_begin != NULL_RTX)
+ /* Indicate to debug counters that INSN is scheduled. */
+ nonscheduled_insns_begin = insn;
+
return advance;
}
@@ -4048,6 +4050,7 @@ struct haifa_saved_data
rtx last_scheduled_insn;
rtx last_nondebug_scheduled_insn;
+ rtx nonscheduled_insns_begin;
int cycle_issued_insns;
/* Copies of state used in the inner loop of schedule_block. */
@@ -4120,6 +4123,7 @@ save_backtrack_point (struct delay_pair *pair,
save->cycle_issued_insns = cycle_issued_insns;
save->last_scheduled_insn = last_scheduled_insn;
save->last_nondebug_scheduled_insn = last_nondebug_scheduled_insn;
+ save->nonscheduled_insns_begin = nonscheduled_insns_begin;
save->sched_block = sched_block;
@@ -4375,6 +4379,7 @@ restore_last_backtrack_point (struct sched_block_state *psched_block)
cycle_issued_insns = save->cycle_issued_insns;
last_scheduled_insn = save->last_scheduled_insn;
last_nondebug_scheduled_insn = save->last_nondebug_scheduled_insn;
+ nonscheduled_insns_begin = save->nonscheduled_insns_begin;
*psched_block = save->sched_block;
@@ -4843,6 +4848,24 @@ undo_all_replacements (void)
}
}
+/* Return first non-scheduled insn in the current scheduling block.
+ This is mostly used for debug-counter purposes. */
+static rtx
+first_nonscheduled_insn (void)
+{
+ rtx insn = (nonscheduled_insns_begin != NULL_RTX
+ ? nonscheduled_insns_begin
+ : current_sched_info->prev_head);
+
+ do
+ {
+ insn = next_nonnote_nondebug_insn (insn);
+ }
+ while (QUEUE_INDEX (insn) == QUEUE_SCHEDULED);
+
+ return insn;
+}
+
/* Move insns that became ready to fire from queue to ready list. */
static void
@@ -4855,16 +4878,9 @@ queue_to_ready (struct ready_list *ready)
q_ptr = NEXT_Q (q_ptr);
if (dbg_cnt (sched_insn) == false)
- {
- /* If debug counter is activated do not requeue the first
- nonscheduled insn. */
- skip_insn = nonscheduled_insns_begin;
- do
- {
- skip_insn = next_nonnote_nondebug_insn (skip_insn);
- }
- while (QUEUE_INDEX (skip_insn) == QUEUE_SCHEDULED);
- }
+ /* If debug counter is activated do not requeue the first
+ nonscheduled insn. */
+ skip_insn = first_nonscheduled_insn ();
else
skip_insn = NULL_RTX;
@@ -4894,7 +4910,11 @@ queue_to_ready (struct ready_list *ready)
&& model_index (insn) == model_curr_point)
&& !SCHED_GROUP_P (insn)
&& insn != skip_insn)
- queue_insn (insn, 1, "ready full");
+ {
+ if (sched_verbose >= 2)
+ fprintf (sched_dump, "keeping in queue, ready full\n");
+ queue_insn (insn, 1, "ready full");
+ }
else
{
ready_add (ready, insn, false);
@@ -4939,6 +4959,9 @@ queue_to_ready (struct ready_list *ready)
q_ptr = NEXT_Q_AFTER (q_ptr, stalls);
clock_var += stalls;
+ if (sched_verbose >= 2)
+ fprintf (sched_dump, ";;\tAdvancing clock by %d cycle[s] to %d\n",
+ stalls, clock_var);
}
}
@@ -5099,10 +5122,11 @@ early_queue_to_ready (state_t state, struct ready_list *ready)
}
-/* Print the ready list for debugging purposes. Callable from debugger. */
-
+/* Print the ready list for debugging purposes.
+ If READY_TRY is non-zero then only print insns that max_issue
+ will consider. */
static void
-debug_ready_list (struct ready_list *ready)
+debug_ready_list_1 (struct ready_list *ready, signed char *ready_try)
{
rtx *p;
int i;
@@ -5116,12 +5140,16 @@ debug_ready_list (struct ready_list *ready)
p = ready_lastpos (ready);
for (i = 0; i < ready->n_ready; i++)
{
+ if (ready_try != NULL && ready_try[ready->n_ready - i - 1])
+ continue;
+
fprintf (sched_dump, " %s:%d",
(*current_sched_info->print_insn) (p[i], 0),
INSN_LUID (p[i]));
if (sched_pressure != SCHED_PRESSURE_NONE)
fprintf (sched_dump, "(cost=%d",
INSN_REG_PRESSURE_EXCESS_COST_CHANGE (p[i]));
+ fprintf (sched_dump, ":prio=%d", INSN_PRIORITY (p[i]));
if (INSN_TICK (p[i]) > clock_var)
fprintf (sched_dump, ":delay=%d", INSN_TICK (p[i]) - clock_var);
if (sched_pressure != SCHED_PRESSURE_NONE)
@@ -5130,6 +5158,13 @@ debug_ready_list (struct ready_list *ready)
fprintf (sched_dump, "\n");
}
+/* Print the ready list. Callable from debugger. */
+static void
+debug_ready_list (struct ready_list *ready)
+{
+ debug_ready_list_1 (ready, NULL);
+}
+
/* Search INSN for REG_SAVE_NOTE notes and convert them back into insn
NOTEs. This is used for NOTE_INSN_EPILOGUE_BEG, so that sched-ebb
replaces the epilogue note in the correct basic block. */
@@ -5359,6 +5394,12 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
if (!ready_try [i])
all++;
+ if (sched_verbose >= 2)
+ {
+ fprintf (sched_dump, ";;\t\tmax_issue among %d insns:", all);
+ debug_ready_list_1 (ready, ready_try);
+ }
+
/* I is the index of the insn to try next. */
i = 0;
tries_num = 0;
@@ -5491,23 +5532,21 @@ choose_ready (struct ready_list *ready, bool first_cycle_insn_p,
if (dbg_cnt (sched_insn) == false)
{
- rtx insn = nonscheduled_insns_begin;
- do
- {
- insn = next_nonnote_insn (insn);
- }
- while (QUEUE_INDEX (insn) == QUEUE_SCHEDULED);
+ if (nonscheduled_insns_begin == NULL_RTX)
+ nonscheduled_insns_begin = current_sched_info->prev_head;
+
+ rtx insn = first_nonscheduled_insn ();
if (QUEUE_INDEX (insn) == QUEUE_READY)
/* INSN is in the ready_list. */
{
- nonscheduled_insns_begin = insn;
ready_remove_insn (insn);
*insn_ptr = insn;
return 0;
}
/* INSN is in the queue. Advance cycle to move it to the ready list. */
+ gcc_assert (QUEUE_INDEX (insn) >= 0);
return -1;
}
@@ -5527,11 +5566,9 @@ choose_ready (struct ready_list *ready, bool first_cycle_insn_p,
}
else
{
- /* Try to choose the better insn. */
- int index = 0, i, n;
+ /* Try to choose the best insn. */
+ int index = 0, i;
rtx insn;
- int try_data = 1, try_control = 1;
- ds_t ts;
insn = ready_element (ready, 0);
if (INSN_CODE (insn) < 0)
@@ -5540,84 +5577,57 @@ choose_ready (struct ready_list *ready, bool first_cycle_insn_p,
return 0;
}
- if (spec_info
- && spec_info->flags & (PREFER_NON_DATA_SPEC
- | PREFER_NON_CONTROL_SPEC))
+ /* Filter the search space. */
+ for (i = 0; i < ready->n_ready; i++)
{
- for (i = 0, n = ready->n_ready; i < n; i++)
- {
- rtx x;
- ds_t s;
+ ready_try[i] = 0;
- x = ready_element (ready, i);
- s = TODO_SPEC (x);
+ insn = ready_element (ready, i);
- if (spec_info->flags & PREFER_NON_DATA_SPEC
- && !(s & DATA_SPEC))
- {
- try_data = 0;
- if (!(spec_info->flags & PREFER_NON_CONTROL_SPEC)
- || !try_control)
- break;
- }
+ /* If this insn is recognizable we should have already
+ recognized it earlier.
+ ??? Not very clear where this is supposed to be done.
+ See dep_cost_1. */
+ gcc_checking_assert (INSN_CODE (insn) >= 0
+ || recog_memoized (insn) < 0);
+ if (INSN_CODE (insn) < 0)
+ {
+ /* Non-recognized insns at position 0 are handled above. */
+ gcc_assert (i > 0);
+ ready_try[i] = 1;
+ continue;
+ }
- if (spec_info->flags & PREFER_NON_CONTROL_SPEC
- && !(s & CONTROL_SPEC))
+ if (targetm.sched.first_cycle_multipass_dfa_lookahead_guard)
+ {
+ ready_try[i]
+ = (targetm.sched.first_cycle_multipass_dfa_lookahead_guard
+ (insn, i));
+
+ if (ready_try[i] < 0)
+ /* Queue instruction for several cycles.
+ We need to restart choose_ready as we have changed
+ the ready list. */
{
- try_control = 0;
- if (!(spec_info->flags & PREFER_NON_DATA_SPEC) || !try_data)
- break;
+ change_queue_index (insn, -ready_try[i]);
+ return 1;
}
- }
- }
- ts = TODO_SPEC (insn);
- if ((ts & SPECULATIVE)
- && (((!try_data && (ts & DATA_SPEC))
- || (!try_control && (ts & CONTROL_SPEC)))
- || (targetm.sched.first_cycle_multipass_dfa_lookahead_guard_spec
- && !targetm.sched
- .first_cycle_multipass_dfa_lookahead_guard_spec (insn))))
- /* Discard speculative instruction that stands first in the ready
- list. */
- {
- change_queue_index (insn, 1);
- return 1;
- }
-
- ready_try[0] = 0;
-
- for (i = 1; i < ready->n_ready; i++)
- {
- insn = ready_element (ready, i);
+ /* Make sure that we didn't end up with 0'th insn filtered out.
+ Don't be tempted to make life easier for backends and just
+ requeue 0'th insn if (ready_try[0] == 0) and restart
+ choose_ready. Backends should be very considerate about
+ requeueing instructions -- especially the highest priority
+ one at position 0. */
+ gcc_assert (ready_try[i] == 0 || i > 0);
+ if (ready_try[i])
+ continue;
+ }
- ready_try [i]
- = ((!try_data && (TODO_SPEC (insn) & DATA_SPEC))
- || (!try_control && (TODO_SPEC (insn) & CONTROL_SPEC)));
+ gcc_assert (ready_try[i] == 0);
+ /* INSN made it through the scrutiny of filters! */
}
- /* Let the target filter the search space. */
- for (i = 1; i < ready->n_ready; i++)
- if (!ready_try[i])
- {
- insn = ready_element (ready, i);
-
- /* If this insn is recognizable we should have already
- recognized it earlier.
- ??? Not very clear where this is supposed to be done.
- See dep_cost_1. */
- gcc_checking_assert (INSN_CODE (insn) >= 0
- || recog_memoized (insn) < 0);
-
- ready_try [i]
- = (/* INSN_CODE check can be omitted here as it is also done later
- in max_issue (). */
- INSN_CODE (insn) < 0
- || (targetm.sched.first_cycle_multipass_dfa_lookahead_guard
- && !targetm.sched.first_cycle_multipass_dfa_lookahead_guard
- (insn)));
- }
-
if (max_issue (ready, 1, curr_state, first_cycle_insn_p, &index) == 0)
{
*insn_ptr = ready_remove_first (ready);
@@ -5865,6 +5875,35 @@ verify_shadows (void)
return earliest_fail;
}
+/* Print instructions together with useful scheduling information between
+ HEAD and TAIL (inclusive). */
+static void
+dump_insn_stream (rtx head, rtx tail)
+{
+ fprintf (sched_dump, ";;\t| insn | prio |\n");
+
+ rtx next_tail = NEXT_INSN (tail);
+ for (rtx insn = head; insn != next_tail; insn = NEXT_INSN (insn))
+ {
+ int priority = NOTE_P (insn) ? 0 : INSN_PRIORITY (insn);
+ const char *pattern = (NOTE_P (insn)
+ ? "note"
+ : str_pattern_slim (PATTERN (insn)));
+
+ fprintf (sched_dump, ";;\t| %4d | %4d | %-30s ",
+ INSN_UID (insn), priority, pattern);
+
+ if (sched_verbose >= 4)
+ {
+ if (NOTE_P (insn) || recog_memoized (insn) < 0)
+ fprintf (sched_dump, "nothing");
+ else
+ print_reservation (sched_dump, insn);
+ }
+ fprintf (sched_dump, "\n");
+ }
+}
+
/* Use forward list scheduling to rearrange insns of block pointed to by
TARGET_BB, possibly bringing insns from subsequent blocks in the same
region. */
@@ -5903,7 +5942,12 @@ schedule_block (basic_block *target_bb, state_t init_state)
/* Debug info. */
if (sched_verbose)
- dump_new_block_header (0, *target_bb, head, tail);
+ {
+ dump_new_block_header (0, *target_bb, head, tail);
+
+ if (sched_verbose >= 2)
+ dump_insn_stream (head, tail);
+ }
if (init_state == NULL)
state_reset (curr_state);
@@ -5922,8 +5966,9 @@ schedule_block (basic_block *target_bb, state_t init_state)
targetm.sched.init (sched_dump, sched_verbose, ready.veclen);
/* We start inserting insns after PREV_HEAD. */
- last_scheduled_insn = nonscheduled_insns_begin = prev_head;
+ last_scheduled_insn = prev_head;
last_nondebug_scheduled_insn = NULL_RTX;
+ nonscheduled_insns_begin = NULL_RTX;
gcc_assert ((NOTE_P (last_scheduled_insn)
|| DEBUG_INSN_P (last_scheduled_insn))
@@ -5976,7 +6021,7 @@ schedule_block (basic_block *target_bb, state_t init_state)
rtx skip_insn;
if (dbg_cnt (sched_insn) == false)
- skip_insn = next_nonnote_insn (nonscheduled_insns_begin);
+ skip_insn = first_nonscheduled_insn ();
else
skip_insn = NULL_RTX;
@@ -6030,7 +6075,7 @@ schedule_block (basic_block *target_bb, state_t init_state)
if (sched_verbose >= 2)
{
- fprintf (sched_dump, ";;\t\tReady list after queue_to_ready: ");
+ fprintf (sched_dump, ";;\t\tReady list after queue_to_ready:");
debug_ready_list (&ready);
}
advance -= clock_var - start_clock_var;
@@ -6097,7 +6142,8 @@ schedule_block (basic_block *target_bb, state_t init_state)
if (sched_verbose >= 2)
{
- fprintf (sched_dump, ";;\t\tReady list after ready_sort: ");
+ fprintf (sched_dump,
+ ";;\t\tReady list after ready_sort: ");
debug_ready_list (&ready);
}
}
@@ -6486,14 +6532,21 @@ schedule_block (basic_block *target_bb, state_t init_state)
sched_extend_luids ();
}
- if (sched_verbose)
- fprintf (sched_dump, ";; new head = %d\n;; new tail = %d\n\n",
- INSN_UID (head), INSN_UID (tail));
-
/* Update head/tail boundaries. */
head = NEXT_INSN (prev_head);
tail = last_scheduled_insn;
+ if (sched_verbose)
+ {
+ fprintf (sched_dump, ";; new head = %d\n;; new tail = %d\n",
+ INSN_UID (head), INSN_UID (tail));
+
+ if (sched_verbose >= 2)
+ dump_insn_stream (head, tail);
+
+ fprintf (sched_dump, "\n");
+ }
+
head = restore_other_notes (head, NULL);
current_sched_info->head = head;
@@ -7153,8 +7206,9 @@ sched_extend_ready_list (int new_sched_ready_n_insns)
gcc_assert (new_sched_ready_n_insns >= sched_ready_n_insns);
- ready_try = (char *) xrecalloc (ready_try, new_sched_ready_n_insns,
- sched_ready_n_insns, sizeof (*ready_try));
+ ready_try = (signed char *) xrecalloc (ready_try, new_sched_ready_n_insns,
+ sched_ready_n_insns,
+ sizeof (*ready_try));
/* We allocate +1 element to save initial state in the choice_stack[0]
entry. */
@@ -7653,7 +7707,7 @@ sched_create_recovery_edges (basic_block first_bb, basic_block rec,
{
/* We don't need the same note for the check because
any_condjump_p (check) == true. */
- add_reg_note (jump, REG_CROSSING_JUMP, NULL_RTX);
+ CROSSING_JUMP_P (jump) = 1;
}
edge_flags = EDGE_CROSSING;
}
@@ -8532,7 +8586,7 @@ sched_create_empty_bb_1 (basic_block after)
rtx
sched_emit_insn (rtx pat)
{
- rtx insn = emit_insn_before (pat, nonscheduled_insns_begin);
+ rtx insn = emit_insn_before (pat, first_nonscheduled_insn ());
haifa_init_insn (insn);
if (current_sched_info->add_remove_insn)
diff --git a/gcc/hw-doloop.c b/gcc/hw-doloop.c
index cc8f9b77505..d18276103b4 100644
--- a/gcc/hw-doloop.c
+++ b/gcc/hw-doloop.c
@@ -636,7 +636,9 @@ reorg_loops (bool do_reorder, struct hw_doloop_hooks *hooks)
loops = discover_loops (&loop_stack, hooks);
- if (do_reorder)
+ /* We can't enter cfglayout mode anymore if basic block partitioning
+ already happened. */
+ if (do_reorder && !flag_reorder_blocks_and_partition)
{
reorder_loops (loops);
free_loops (loops);
diff --git a/gcc/hwint.h b/gcc/hwint.h
index ac9c9a295b4..e3b8a8aa7d7 100644
--- a/gcc/hwint.h
+++ b/gcc/hwint.h
@@ -44,72 +44,26 @@ extern char sizeof_long_long_must_be_8[sizeof (long long) == 8 ? 1 : -1];
#ifdef HAVE_LONG_LONG
# define HOST_BITS_PER_LONGLONG (CHAR_BIT * SIZEOF_LONG_LONG)
#endif
-#ifdef HAVE___INT64
-# define HOST_BITS_PER___INT64 (CHAR_BIT * SIZEOF___INT64)
-#endif
-/* Set HOST_WIDE_INT. This should be the widest efficient host
- integer type. It can be 32 or 64 bits, except that if we are
- targeting a machine with 64-bit size_t then it has to be 64 bits.
+/* Set HOST_WIDE_INT, this should be always 64 bits.
With a sane ABI, 'long' is the largest efficient host integer type.
- Thus, we use that unless we have to use 'long long' or '__int64'
- because we're targeting a 64-bit machine from a 32-bit host. */
+ Thus, we use that unless we have to use 'long long'
+ because we're on a 32-bit host. */
-#if HOST_BITS_PER_LONG >= 64 || !defined NEED_64BIT_HOST_WIDE_INT
-# define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG
+#define HOST_BITS_PER_WIDE_INT 64
+#if HOST_BITS_PER_LONG == 64
# define HOST_WIDE_INT long
# define HOST_WIDE_INT_C(X) X ## L
#else
-# if HOST_BITS_PER_LONGLONG >= 64
-# define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONGLONG
+# if HOST_BITS_PER_LONGLONG == 64
# define HOST_WIDE_INT long long
# define HOST_WIDE_INT_C(X) X ## LL
# else
-# if HOST_BITS_PER___INT64 >= 64
-# define HOST_BITS_PER_WIDE_INT HOST_BITS_PER___INT64
-# define HOST_WIDE_INT __int64
-# define HOST_WIDE_INT_C(X) X ## i64
-# else
- #error "Unable to find a suitable type for HOST_WIDE_INT"
-# endif
+ #error "Unable to find a suitable type for HOST_WIDE_INT"
# endif
#endif
-/* Print support for half a host wide int. */
-#define HOST_BITS_PER_HALF_WIDE_INT (HOST_BITS_PER_WIDE_INT / 2)
-#if HOST_BITS_PER_HALF_WIDE_INT == HOST_BITS_PER_LONG
-# define HOST_HALF_WIDE_INT long
-# define HOST_HALF_WIDE_INT_PRINT HOST_LONG_FORMAT
-# define HOST_HALF_WIDE_INT_PRINT_C "L"
-# define HOST_HALF_WIDE_INT_PRINT_DEC "%" HOST_HALF_WIDE_INT_PRINT "d"
-# define HOST_HALF_WIDE_INT_PRINT_DEC_C HOST_HALF_WIDE_INT_PRINT_DEC HOST_HALF_WIDE_INT_PRINT_C
-# define HOST_HALF_WIDE_INT_PRINT_UNSIGNED "%" HOST_HALF_WIDE_INT_PRINT "u"
-# define HOST_HALF_WIDE_INT_PRINT_HEX "%#" HOST_HALF_WIDE_INT_PRINT "x"
-# define HOST_HALF_WIDE_INT_PRINT_HEX_PURE "%" HOST_HALF_WIDE_INT_PRINT "x"
-#elif HOST_BITS_PER_HALF_WIDE_INT == HOST_BITS_PER_INT
-# define HOST_HALF_WIDE_INT int
-# define HOST_HALF_WIDE_INT_PRINT ""
-# define HOST_HALF_WIDE_INT_PRINT_C ""
-# define HOST_HALF_WIDE_INT_PRINT_DEC "%" HOST_HALF_WIDE_INT_PRINT "d"
-# define HOST_HALF_WIDE_INT_PRINT_DEC_C HOST_HALF_WIDE_INT_PRINT_DEC HOST_HALF_WIDE_INT_PRINT_C
-# define HOST_HALF_WIDE_INT_PRINT_UNSIGNED "%" HOST_HALF_WIDE_INT_PRINT "u"
-# define HOST_HALF_WIDE_INT_PRINT_HEX "%#" HOST_HALF_WIDE_INT_PRINT "x"
-# define HOST_HALF_WIDE_INT_PRINT_HEX_PURE "%" HOST_HALF_WIDE_INT_PRINT "x"
-#elif HOST_BITS_PER_HALF_WIDE_INT == HOST_BITS_PER_SHORT
-# define HOST_HALF_WIDE_INT short
-# define HOST_HALF_WIDE_INT_PRINT ""
-# define HOST_HALF_WIDE_INT_PRINT_C ""
-# define HOST_HALF_WIDE_INT_PRINT_DEC "%" HOST_HALF_WIDE_INT_PRINT "d"
-# define HOST_HALF_WIDE_INT_PRINT_DEC_C HOST_HALF_WIDE_INT_PRINT_DEC HOST_HALF_WIDE_INT_PRINT_C
-# define HOST_HALF_WIDE_INT_PRINT_UNSIGNED "%" HOST_HALF_WIDE_INT_PRINT "u"
-# define HOST_HALF_WIDE_INT_PRINT_HEX "%#" HOST_HALF_WIDE_INT_PRINT "x"
-# define HOST_HALF_WIDE_INT_PRINT_HEX_PURE "%" HOST_HALF_WIDE_INT_PRINT "x"
-#else
-#error Please add support for HOST_HALF_WIDE_INT
-#endif
-
-
#define HOST_WIDE_INT_UC(X) HOST_WIDE_INT_C (X ## U)
#define HOST_WIDE_INT_1 HOST_WIDE_INT_C (1)
#define HOST_WIDE_INT_1U HOST_WIDE_INT_UC (1)
@@ -126,23 +80,15 @@ typedef HOST_WIDE_INT __gcc_host_wide_int__;
#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
# define HOST_WIDE_INT_PRINT HOST_LONG_FORMAT
# define HOST_WIDE_INT_PRINT_C "L"
- /* 'long' might be 32 or 64 bits, and the number of leading zeroes
- must be tweaked accordingly. */
-# if HOST_BITS_PER_WIDE_INT == 64
-# define HOST_WIDE_INT_PRINT_DOUBLE_HEX \
- "0x%" HOST_LONG_FORMAT "x%016" HOST_LONG_FORMAT "x"
-# define HOST_WIDE_INT_PRINT_PADDED_HEX \
- "%016" HOST_LONG_FORMAT "x"
-# else
-# define HOST_WIDE_INT_PRINT_DOUBLE_HEX \
- "0x%" HOST_LONG_FORMAT "x%08" HOST_LONG_FORMAT "x"
-# define HOST_WIDE_INT_PRINT_PADDED_HEX \
- "%08" HOST_LONG_FORMAT "x"
-# endif
+ /* HOST_BITS_PER_WIDE_INT is 64 bits. */
+# define HOST_WIDE_INT_PRINT_DOUBLE_HEX \
+ "0x%" HOST_LONG_FORMAT "x%016" HOST_LONG_FORMAT "x"
+# define HOST_WIDE_INT_PRINT_PADDED_HEX \
+ "%016" HOST_LONG_FORMAT "x"
#else
# define HOST_WIDE_INT_PRINT HOST_LONG_LONG_FORMAT
# define HOST_WIDE_INT_PRINT_C "LL"
- /* We can assume that 'long long' is at least 64 bits. */
+ /* HOST_BITS_PER_WIDE_INT is 64 bits. */
# define HOST_WIDE_INT_PRINT_DOUBLE_HEX \
"0x%" HOST_LONG_LONG_FORMAT "x%016" HOST_LONG_LONG_FORMAT "x"
# define HOST_WIDE_INT_PRINT_PADDED_HEX \
@@ -155,41 +101,20 @@ typedef HOST_WIDE_INT __gcc_host_wide_int__;
#define HOST_WIDE_INT_PRINT_HEX "%#" HOST_WIDE_INT_PRINT "x"
#define HOST_WIDE_INT_PRINT_HEX_PURE "%" HOST_WIDE_INT_PRINT "x"
-/* Set HOST_WIDEST_INT. This is a 64-bit type unless the compiler
- in use has no 64-bit type at all; in that case it's 32 bits. */
-
-#if HOST_BITS_PER_WIDE_INT >= 64 \
- || (HOST_BITS_PER_LONGLONG < 64 && HOST_BITS_PER___INT64 < 64)
-# define HOST_WIDEST_INT HOST_WIDE_INT
-# define HOST_BITS_PER_WIDEST_INT HOST_BITS_PER_WIDE_INT
-# define HOST_WIDEST_INT_PRINT HOST_WIDE_INT_PRINT
-# define HOST_WIDEST_INT_PRINT_DEC HOST_WIDE_INT_PRINT_DEC
-# define HOST_WIDEST_INT_PRINT_DEC_C HOST_WIDE_INT_PRINT_DEC_C
-# define HOST_WIDEST_INT_PRINT_UNSIGNED HOST_WIDE_INT_PRINT_UNSIGNED
-# define HOST_WIDEST_INT_PRINT_HEX HOST_WIDE_INT_PRINT_HEX
-# define HOST_WIDEST_INT_PRINT_DOUBLE_HEX HOST_WIDE_INT_PRINT_DOUBLE_HEX
-# define HOST_WIDEST_INT_C(X) HOST_WIDE_INT (X)
-#else
-# if HOST_BITS_PER_LONGLONG >= 64
-# define HOST_BITS_PER_WIDEST_INT HOST_BITS_PER_LONGLONG
-# define HOST_WIDEST_INT long long
-# define HOST_WIDEST_INT_C(X) X ## LL
-# else
-# if HOST_BITS_PER___INT64 >= 64
-# define HOST_BITS_PER_WIDEST_INT HOST_BITS_PER___INT64
-# define HOST_WIDEST_INT __int64
-# define HOST_WIDEST_INT_C(X) X ## i64
-# else
- #error "This line should be impossible to reach"
-# endif
-# endif
-# define HOST_WIDEST_INT_PRINT HOST_LONG_LONG_FORMAT
-# define HOST_WIDEST_INT_PRINT_DEC "%" HOST_LONG_LONG_FORMAT "d"
-# define HOST_WIDEST_INT_PRINT_DEC_C "%" HOST_LONG_LONG_FORMAT "dLL"
-# define HOST_WIDEST_INT_PRINT_UNSIGNED "%" HOST_LONG_LONG_FORMAT "u"
-# define HOST_WIDEST_INT_PRINT_HEX "%#" HOST_LONG_LONG_FORMAT "x"
-# define HOST_WIDEST_INT_PRINT_DOUBLE_HEX \
- "0x%" HOST_LONG_LONG_FORMAT "x%016" HOST_LONG_LONG_FORMAT "x"
+/* Provide C99 <inttypes.h> style format definitions for 64bits. */
+#ifndef HAVE_INTTYPES_H
+#undef PRId64
+#define PRId64 HOST_WIDE_INT_PRINT "d"
+#undef PRIi64
+#define PRIi64 HOST_WIDE_INT_PRINT "i"
+#undef PRIo64
+#define PRIo64 HOST_WIDE_INT_PRINT "o"
+#undef PRIu64
+#define PRIu64 HOST_WIDE_INT_PRINT "u"
+#undef PRIx64
+#define PRIx64 HOST_WIDE_INT_PRINT "x"
+#undef PRIX64
+#define PRIX64 HOST_WIDE_INT_PRINT "X"
#endif
/* Define HOST_WIDEST_FAST_INT to the widest integer type supported
@@ -203,12 +128,8 @@ typedef HOST_WIDE_INT __gcc_host_wide_int__;
# ifdef HAVE_LONG_LONG
# define HOST_WIDEST_FAST_INT long long
# define HOST_BITS_PER_WIDEST_FAST_INT HOST_BITS_PER_LONGLONG
-# elif defined (HAVE___INT64)
-# define HOST_WIDEST_FAST_INT __int64
-# define HOST_BITS_PER_WIDEST_FAST_INT HOST_BITS_PER___INT64
# else
-# error "Your host said it wanted to use long long or __int64 but neither"
-# error "exist"
+# error "Your host said it wanted to use long long but that does not exist"
# endif
#else
# define HOST_WIDEST_FAST_INT long
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index cd2b5dcda03..2ca2278709d 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -3877,12 +3877,14 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
if ((BB_END (then_bb)
- && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX))
+ && JUMP_P (BB_END (then_bb))
+ && CROSSING_JUMP_P (BB_END (then_bb)))
|| (BB_END (test_bb)
- && find_reg_note (BB_END (test_bb), REG_CROSSING_JUMP, NULL_RTX))
+ && JUMP_P (BB_END (test_bb))
+ && CROSSING_JUMP_P (BB_END (test_bb)))
|| (BB_END (else_bb)
- && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP,
- NULL_RTX)))
+ && JUMP_P (BB_END (else_bb))
+ && CROSSING_JUMP_P (BB_END (else_bb))))
return FALSE;
/* THEN has one successor. */
@@ -4000,12 +4002,14 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
if ((BB_END (then_bb)
- && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX))
+ && JUMP_P (BB_END (then_bb))
+ && CROSSING_JUMP_P (BB_END (then_bb)))
|| (BB_END (test_bb)
- && find_reg_note (BB_END (test_bb), REG_CROSSING_JUMP, NULL_RTX))
+ && JUMP_P (BB_END (test_bb))
+ && CROSSING_JUMP_P (BB_END (test_bb)))
|| (BB_END (else_bb)
- && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP,
- NULL_RTX)))
+ && JUMP_P (BB_END (else_bb))
+ && CROSSING_JUMP_P (BB_END (else_bb))))
return FALSE;
/* ELSE has one successor. */
diff --git a/gcc/ipa-comdats.c b/gcc/ipa-comdats.c
new file mode 100644
index 00000000000..41e27fd42ab
--- /dev/null
+++ b/gcc/ipa-comdats.c
@@ -0,0 +1,388 @@
+/* Localize comdats.
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* This is very simple pass that looks for static symbols that are used
+ exlusively by symbol within one comdat group. In this case it makes
+ sense to bring the symbol itself into the group to avoid dead code
+ that would arrise when the comdat group from current unit is replaced
+ by a different copy. Consider for example:
+
+ static int q(void)
+ {
+ ....
+ }
+ inline int t(void)
+ {
+ return q();
+ }
+
+ if Q is used only by T, it makes sense to put Q into T's comdat group.
+
+ The pass solve simple dataflow across the callgraph trying to prove what
+ symbols are used exclusively from a given comdat group.
+
+ The implementation maintains a queue linked by AUX pointer terminated by
+ pointer value 1. Lattice values are NULL for TOP, actual comdat group, or
+ ERROR_MARK_NODE for bottom.
+
+ TODO: When symbol is used only by comdat symbols, but from different groups,
+ it would make sense to produce a new comdat group for it with anonymous name.
+
+ TODO2: We can't mix variables and functions within one group. Currently
+ we just give up on references of symbols of different types. We also should
+ handle this by anonymous comdat group section. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "cgraph.h"
+#include "tree-pass.h"
+#include "pointer-set.h"
+
+/* Main dataflow loop propagating comdat groups across
+ the symbol table. All references to SYMBOL are examined
+ and NEWGROUP is updated accordingly. MAP holds current lattice
+ values for individual symbols. */
+
+tree
+propagate_comdat_group (struct symtab_node *symbol,
+ tree newgroup, pointer_map <tree> &map)
+{
+ int i;
+ struct ipa_ref *ref;
+
+ /* Walk all references to SYMBOL, recursively dive into aliases. */
+
+ for (i = 0;
+ ipa_ref_list_referring_iterate (&symbol->ref_list, i, ref)
+ && newgroup != error_mark_node; i++)
+ {
+ struct symtab_node *symbol2 = ref->referring;
+
+ if (ref->use == IPA_REF_ALIAS)
+ {
+ newgroup = propagate_comdat_group (symbol2, newgroup, map);
+ continue;
+ }
+
+ /* One COMDAT group can not hold both variables and functions at
+ a same time. For now we just go to BOTTOM, in future we may
+ invent special comdat groups for this case. */
+
+ if (symbol->type != symbol2->type)
+ {
+ newgroup = error_mark_node;
+ break;
+ }
+
+ /* If we see inline clone, its comdat group actually
+ corresponds to the comdat group of the function it is inlined
+ to. */
+
+ if (cgraph_node * cn = dyn_cast <cgraph_node *> (symbol2))
+ {
+ if (cn->global.inlined_to)
+ symbol2 = cn->global.inlined_to;
+ }
+
+ /* The actual merge operation. */
+
+ tree *val2 = map.contains (symbol2);
+
+ if (val2 && *val2 != newgroup)
+ {
+ if (!newgroup)
+ newgroup = *val2;
+ else
+ newgroup = error_mark_node;
+ }
+ }
+
+ /* If we analyze function, walk also callers. */
+
+ cgraph_node *cnode = dyn_cast <cgraph_node *> (symbol);
+
+ if (cnode)
+ for (struct cgraph_edge * edge = cnode->callers;
+ edge && newgroup != error_mark_node; edge = edge->next_caller)
+ {
+ struct symtab_node *symbol2 = edge->caller;
+
+ /* If we see inline clone, its comdat group actually
+ corresponds to the comdat group of the function it is inlined
+ to. */
+
+ if (cgraph_node * cn = dyn_cast <cgraph_node *> (symbol2))
+ {
+ if (cn->global.inlined_to)
+ symbol2 = cn->global.inlined_to;
+ }
+
+ /* The actual merge operation. */
+
+ tree *val2 = map.contains (symbol2);
+
+ if (val2 && *val2 != newgroup)
+ {
+ if (!newgroup)
+ newgroup = *val2;
+ else
+ newgroup = error_mark_node;
+ }
+ }
+ return newgroup;
+}
+
+
+/* Add all references of SYMBOL that are defined into queue started by FIRST
+ and linked by AUX pointer (unless they are already enqueued).
+ Walk recursively inlined functions. */
+
+void
+enqueue_references (symtab_node **first,
+ symtab_node *symbol)
+{
+ int i;
+ struct ipa_ref *ref;
+
+ for (i = 0; ipa_ref_list_reference_iterate (&symbol->ref_list, i, ref); i++)
+ {
+ symtab_node *node = symtab_alias_ultimate_target (ref->referred, NULL);
+ if (!node->aux && node->definition)
+ {
+ node->aux = *first;
+ *first = node;
+ }
+ }
+
+ if (cgraph_node *cnode = dyn_cast <cgraph_node *> (symbol))
+ {
+ struct cgraph_edge *edge;
+
+ for (edge = cnode->callees; edge; edge = edge->next_callee)
+ if (!edge->inline_failed)
+ enqueue_references (first, edge->callee);
+ else
+ {
+ symtab_node *node = symtab_alias_ultimate_target (edge->callee,
+ NULL);
+ if (!node->aux && node->definition)
+ {
+ node->aux = *first;
+ *first = node;
+ }
+ }
+ }
+}
+
+/* Set comdat group of SYMBOL to GROUP.
+ Callback for symtab_for_node_and_aliases. */
+
+bool
+set_comdat_group (symtab_node *symbol,
+ void *head_p)
+{
+ symtab_node *head = (symtab_node *)head_p;
+
+ gcc_assert (!symbol->get_comdat_group ());
+ symbol->set_comdat_group (head->get_comdat_group ());
+ symtab_add_to_same_comdat_group (symbol, head);
+ return false;
+}
+
+/* The actual pass with the main dataflow loop. */
+
+static unsigned int
+ipa_comdats (void)
+{
+ pointer_map<tree> map;
+ pointer_map<symtab_node *> comdat_head_map;
+ symtab_node *symbol;
+ bool comdat_group_seen = false;
+ symtab_node *first = (symtab_node *) (void *) 1;
+ tree group;
+
+ /* Start the dataflow by assigning comdat group to symbols that are in comdat
+ groups already. All other externally visible symbols must stay, we use
+ ERROR_MARK_NODE as bottom for the propagation. */
+
+ FOR_EACH_DEFINED_SYMBOL (symbol)
+ if (!symtab_real_symbol_p (symbol))
+ ;
+ else if ((group = symbol->get_comdat_group ()) != NULL)
+ {
+ *map.insert (symbol) = group;
+ *comdat_head_map.insert (group) = symbol;
+ comdat_group_seen = true;
+
+ /* Mark the symbol so we won't waste time visiting it for dataflow. */
+ symbol->aux = (symtab_node *) (void *) 1;
+ }
+ /* See symbols that can not be privatized to comdats; that is externally
+ visible symbols or otherwise used ones. We also do not want to mangle
+ user section names. */
+ else if (symbol->externally_visible
+ || symbol->force_output
+ || symbol->used_from_other_partition
+ || TREE_THIS_VOLATILE (symbol->decl)
+ || DECL_SECTION_NAME (symbol->decl)
+ || (TREE_CODE (symbol->decl) == FUNCTION_DECL
+ && (DECL_STATIC_CONSTRUCTOR (symbol->decl)
+ || DECL_STATIC_DESTRUCTOR (symbol->decl))))
+ {
+ *map.insert (symtab_alias_ultimate_target (symbol, NULL)) = error_mark_node;
+
+ /* Mark the symbol so we won't waste time visiting it for dataflow. */
+ symbol->aux = (symtab_node *) (void *) 1;
+ }
+ else
+ {
+ /* Enqueue symbol for dataflow. */
+ symbol->aux = first;
+ first = symbol;
+ }
+
+ if (!comdat_group_seen)
+ {
+ FOR_EACH_DEFINED_SYMBOL (symbol)
+ symbol->aux = NULL;
+ return 0;
+ }
+
+ /* The actual dataflow. */
+
+ while (first != (void *) 1)
+ {
+ tree group = NULL;
+ tree newgroup, *val;
+
+ symbol = first;
+ first = (symtab_node *)first->aux;
+
+ /* Get current lattice value of SYMBOL. */
+ val = map.contains (symbol);
+ if (val)
+ group = *val;
+
+ /* If it is bottom, there is nothing to do; do not clear AUX
+ so we won't re-queue the symbol. */
+ if (group == error_mark_node)
+ continue;
+
+ newgroup = propagate_comdat_group (symbol, group, map);
+
+ /* If nothing changed, proceed to next symbol. */
+ if (newgroup == group)
+ {
+ symbol->aux = NULL;
+ continue;
+ }
+
+ /* Update lattice value and enqueue all references for re-visiting. */
+ gcc_assert (newgroup);
+ if (val)
+ *val = newgroup;
+ else
+ *map.insert (symbol) = newgroup;
+ enqueue_references (&first, symbol);
+
+ /* We may need to revisit the symbol unless it is BOTTOM. */
+ if (newgroup != error_mark_node)
+ symbol->aux = NULL;
+ }
+
+ /* Finally assign symbols to the sections. */
+
+ FOR_EACH_DEFINED_SYMBOL (symbol)
+ {
+ symbol->aux = NULL;
+ if (!symbol->get_comdat_group ()
+ && !symbol->alias
+ && symtab_real_symbol_p (symbol))
+ {
+ tree group = *map.contains (symbol);
+
+ if (group == error_mark_node)
+ continue;
+ if (dump_file)
+ {
+ fprintf (dump_file, "Localizing symbol\n");
+ dump_symtab_node (dump_file, symbol);
+ fprintf (dump_file, "To group: %s\n", IDENTIFIER_POINTER (group));
+ }
+ symtab_for_node_and_aliases (symbol, set_comdat_group,
+ *comdat_head_map.contains (group), true);
+ }
+ }
+ return 0;
+}
+
+namespace {
+
+const pass_data pass_data_ipa_comdats =
+{
+ IPA_PASS, /* type */
+ "comdats", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ true, /* has_execute */
+ TV_IPA_COMDATS, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_ipa_comdats : public ipa_opt_pass_d
+{
+public:
+ pass_ipa_comdats (gcc::context *ctxt)
+ : ipa_opt_pass_d (pass_data_ipa_comdats, ctxt,
+ NULL, /* generate_summary */
+ NULL, /* write_summary */
+ NULL, /* read_summary */
+ NULL, /* write_optimization_summary */
+ NULL, /* read_optimization_summary */
+ NULL, /* stmt_fixup */
+ 0, /* function_transform_todo_flags_start */
+ NULL, /* function_transform */
+ NULL) /* variable_transform */
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *);
+ virtual unsigned int execute (function *) { return ipa_comdats (); }
+
+}; // class pass_ipa_comdats
+
+bool
+pass_ipa_comdats::gate (function *)
+{
+ return optimize;
+}
+
+} // anon namespace
+
+ipa_opt_pass_d *
+make_pass_ipa_comdats (gcc::context *ctxt)
+{
+ return new pass_ipa_comdats (ctxt);
+}
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 479963cdb6b..08fb73e0e93 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -1748,13 +1748,13 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
if (max_count)
{
int factor = (count_sum * 1000) / max_count;
- HOST_WIDEST_INT evaluation = (((HOST_WIDEST_INT) time_benefit * factor)
+ int64_t evaluation = (((int64_t) time_benefit * factor)
/ size_cost);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
"size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC
- ") -> evaluation: " HOST_WIDEST_INT_PRINT_DEC
+ ") -> evaluation: " "%"PRId64
", threshold: %i\n",
time_benefit, size_cost, (HOST_WIDE_INT) count_sum,
evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
@@ -1763,13 +1763,13 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
}
else
{
- HOST_WIDEST_INT evaluation = (((HOST_WIDEST_INT) time_benefit * freq_sum)
+ int64_t evaluation = (((int64_t) time_benefit * freq_sum)
/ size_cost);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " good_cloning_opportunity_p (time: %i, "
"size: %i, freq_sum: %i) -> evaluation: "
- HOST_WIDEST_INT_PRINT_DEC ", threshold: %i\n",
+ "%"PRId64 ", threshold: %i\n",
time_benefit, size_cost, freq_sum, evaluation,
PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD));
@@ -2459,7 +2459,7 @@ ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
parameter with the given INDEX. */
static tree
-get_clone_agg_value (struct cgraph_node *node, HOST_WIDEST_INT offset,
+get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
int index)
{
struct ipa_agg_replacement_value *aggval;
@@ -2599,7 +2599,7 @@ get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
struct ipa_replace_map *replace_map;
- replace_map = ggc_alloc_ipa_replace_map ();
+ replace_map = ggc_alloc<ipa_replace_map> ();
if (dump_file)
{
fprintf (dump_file, " replacing ");
@@ -3182,7 +3182,7 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node,
if (!item->value)
continue;
- v = ggc_alloc_ipa_agg_replacement_value ();
+ v = ggc_alloc<ipa_agg_replacement_value> ();
v->index = i;
v->offset = item->offset;
v->value = item->value;
@@ -3212,7 +3212,7 @@ known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
{
struct ipa_agg_replacement_value *v;
- v = ggc_alloc_ipa_agg_replacement_value ();
+ v = ggc_alloc<ipa_agg_replacement_value> ();
v->index = i;
v->offset = item->offset;
v->value = item->value;
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index d0296e7e4c7..d733461f34a 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -129,6 +129,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h"
#include "tree-dfa.h"
#include "demangle.h"
+#include "dbgcnt.h"
static bool odr_violation_reported = false;
@@ -491,7 +492,7 @@ get_odr_type (tree type, bool insert)
tree binfo = TYPE_BINFO (type);
unsigned int i;
- val = ggc_alloc_cleared_odr_type_d ();
+ val = ggc_cleared_alloc<odr_type_d> ();
val->type = type;
val->bases = vNULL;
val->derived_types = vNULL;
@@ -2067,14 +2068,17 @@ ipa_devirt (void)
noverwritable++;
continue;
}
- else
+ else if (dbg_cnt (devirt))
{
- if (dump_file)
- fprintf (dump_file,
- "Speculatively devirtualizing call in %s/%i to %s/%i\n\n",
- n->name (), n->order,
- likely_target->name (),
- likely_target->order);
+ if (dump_enabled_p ())
+ {
+ location_t locus = gimple_location (e->call_stmt);
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, locus,
+ "speculatively devirtualizing call in %s/%i to %s/%i\n",
+ n->name (), n->order,
+ likely_target->name (),
+ likely_target->order);
+ }
if (!symtab_can_be_discarded (likely_target))
{
cgraph_node *alias;
diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c
index a45aab118fd..4cfd87b1015 100644
--- a/gcc/ipa-inline-transform.c
+++ b/gcc/ipa-inline-transform.c
@@ -183,8 +183,9 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
if (freq_scale == -1)
freq_scale = e->frequency;
n = cgraph_clone_node (e->callee, e->callee->decl,
- e->count, freq_scale, update_original,
- vNULL, true, inlining_into, NULL);
+ MIN (e->count, e->callee->count), freq_scale,
+ update_original, vNULL, true, inlining_into,
+ NULL);
cgraph_redirect_edge_callee (e, n);
}
}
@@ -214,6 +215,7 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
it is NULL. If UPDATE_OVERALL_SUMMARY is false, do not bother to recompute overall
size of caller after inlining. Caller is required to eventually do it via
inline_update_overall_summary.
+ If callee_removed is non-NULL, set it to true if we removed callee node.
Return true iff any new callgraph edges were discovered as a
result of inlining. */
@@ -221,7 +223,8 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
bool
inline_call (struct cgraph_edge *e, bool update_original,
vec<cgraph_edge_p> *new_edges,
- int *overall_size, bool update_overall_summary)
+ int *overall_size, bool update_overall_summary,
+ bool *callee_removed)
{
int old_size = 0, new_size = 0;
struct cgraph_node *to = NULL;
@@ -260,6 +263,8 @@ inline_call (struct cgraph_edge *e, bool update_original,
{
next_alias = cgraph_alias_target (alias);
cgraph_remove_node (alias);
+ if (callee_removed)
+ *callee_removed = true;
alias = next_alias;
}
else
@@ -336,7 +341,7 @@ save_inline_function_body (struct cgraph_node *node)
/* first_clone will be turned into real function. */
first_clone = node->clones;
first_clone->decl = copy_node (node->decl);
- symtab_insert_node_to_hashtable (first_clone);
+ first_clone->decl->decl_with_vis.symtab_node = first_clone;
gcc_assert (first_clone == cgraph_get_node (first_clone->decl));
/* Now reshape the clone tree, so all other clones descends from
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 07922018e88..ebc663dfae5 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -127,6 +127,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-iterator.h"
#include "tree-phinodes.h"
#include "ssa-iterators.h"
+#include "builtins.h"
/* Statistics we collect about inlining algorithm. */
static int overall_size;
@@ -2101,7 +2102,7 @@ compute_max_insns (int insns)
if (max_insns < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
max_insns = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS);
- return ((HOST_WIDEST_INT) max_insns
+ return ((int64_t) max_insns
* (100 + PARAM_VALUE (PARAM_INLINE_UNIT_GROWTH)) / 100);
}
@@ -2397,7 +2398,7 @@ inline_small_functions (void)
badness,
edge->frequency / (double)CGRAPH_FREQ_BASE);
if (edge->count)
- fprintf (dump_file," Called "HOST_WIDEST_INT_PRINT_DEC"x\n",
+ fprintf (dump_file," Called %"PRId64"x\n",
edge->count);
if (dump_flags & TDF_DETAILS)
edge_badness (edge, true);
@@ -2631,6 +2632,8 @@ static bool
inline_to_all_callers (struct cgraph_node *node, void *data)
{
int *num_calls = (int *)data;
+ bool callee_removed = false;
+
while (node->callers && !node->global.inlined_to)
{
struct cgraph_node *caller = node->callers->caller;
@@ -2647,7 +2650,7 @@ inline_to_all_callers (struct cgraph_node *node, void *data)
inline_summary (node->callers->caller)->size);
}
- inline_call (node->callers, true, NULL, NULL, true);
+ inline_call (node->callers, true, NULL, NULL, true, &callee_removed);
if (dump_file)
fprintf (dump_file,
" Inlined into %s which now has %i size\n",
@@ -2657,8 +2660,10 @@ inline_to_all_callers (struct cgraph_node *node, void *data)
{
if (dump_file)
fprintf (dump_file, "New calls found; giving up.\n");
- return true;
+ return callee_removed;
}
+ if (callee_removed)
+ return true;
}
return false;
}
@@ -2667,7 +2672,7 @@ inline_to_all_callers (struct cgraph_node *node, void *data)
static void
dump_overall_stats (void)
{
- HOST_WIDEST_INT sum_weighted = 0, sum = 0;
+ int64_t sum_weighted = 0, sum = 0;
struct cgraph_node *node;
FOR_EACH_DEFINED_FUNCTION (node)
@@ -2679,8 +2684,8 @@ dump_overall_stats (void)
sum_weighted += time * node->count;
}
fprintf (dump_file, "Overall time estimate: "
- HOST_WIDEST_INT_PRINT_DEC" weighted by profile: "
- HOST_WIDEST_INT_PRINT_DEC"\n", sum, sum_weighted);
+ "%"PRId64" weighted by profile: "
+ "%"PRId64"\n", sum, sum_weighted);
}
/* Output some useful stats about inlining. */
@@ -2688,13 +2693,13 @@ dump_overall_stats (void)
static void
dump_inline_stats (void)
{
- HOST_WIDEST_INT inlined_cnt = 0, inlined_indir_cnt = 0;
- HOST_WIDEST_INT inlined_virt_cnt = 0, inlined_virt_indir_cnt = 0;
- HOST_WIDEST_INT noninlined_cnt = 0, noninlined_indir_cnt = 0;
- HOST_WIDEST_INT noninlined_virt_cnt = 0, noninlined_virt_indir_cnt = 0;
- HOST_WIDEST_INT inlined_speculative = 0, inlined_speculative_ply = 0;
- HOST_WIDEST_INT indirect_poly_cnt = 0, indirect_cnt = 0;
- HOST_WIDEST_INT reason[CIF_N_REASONS][3];
+ int64_t inlined_cnt = 0, inlined_indir_cnt = 0;
+ int64_t inlined_virt_cnt = 0, inlined_virt_indir_cnt = 0;
+ int64_t noninlined_cnt = 0, noninlined_indir_cnt = 0;
+ int64_t noninlined_virt_cnt = 0, noninlined_virt_indir_cnt = 0;
+ int64_t inlined_speculative = 0, inlined_speculative_ply = 0;
+ int64_t indirect_poly_cnt = 0, indirect_cnt = 0;
+ int64_t reason[CIF_N_REASONS][3];
int i;
struct cgraph_node *node;
@@ -2758,31 +2763,31 @@ dump_inline_stats (void)
if (max_count)
{
fprintf (dump_file,
- "Inlined " HOST_WIDEST_INT_PRINT_DEC " + speculative "
- HOST_WIDEST_INT_PRINT_DEC " + speculative polymorphic "
- HOST_WIDEST_INT_PRINT_DEC " + previously indirect "
- HOST_WIDEST_INT_PRINT_DEC " + virtual "
- HOST_WIDEST_INT_PRINT_DEC " + virtual and previously indirect "
- HOST_WIDEST_INT_PRINT_DEC "\n" "Not inlined "
- HOST_WIDEST_INT_PRINT_DEC " + previously indirect "
- HOST_WIDEST_INT_PRINT_DEC " + virtual "
- HOST_WIDEST_INT_PRINT_DEC " + virtual and previously indirect "
- HOST_WIDEST_INT_PRINT_DEC " + stil indirect "
- HOST_WIDEST_INT_PRINT_DEC " + still indirect polymorphic "
- HOST_WIDEST_INT_PRINT_DEC "\n", inlined_cnt,
+ "Inlined %"PRId64 " + speculative "
+ "%"PRId64 " + speculative polymorphic "
+ "%"PRId64 " + previously indirect "
+ "%"PRId64 " + virtual "
+ "%"PRId64 " + virtual and previously indirect "
+ "%"PRId64 "\n" "Not inlined "
+ "%"PRId64 " + previously indirect "
+ "%"PRId64 " + virtual "
+ "%"PRId64 " + virtual and previously indirect "
+ "%"PRId64 " + stil indirect "
+ "%"PRId64 " + still indirect polymorphic "
+ "%"PRId64 "\n", inlined_cnt,
inlined_speculative, inlined_speculative_ply,
inlined_indir_cnt, inlined_virt_cnt, inlined_virt_indir_cnt,
noninlined_cnt, noninlined_indir_cnt, noninlined_virt_cnt,
noninlined_virt_indir_cnt, indirect_cnt, indirect_poly_cnt);
fprintf (dump_file,
- "Removed speculations " HOST_WIDEST_INT_PRINT_DEC "\n",
+ "Removed speculations %"PRId64 "\n",
spec_rem);
}
dump_overall_stats ();
fprintf (dump_file, "\nWhy inlining failed?\n");
for (i = 0; i < CIF_N_REASONS; i++)
if (reason[i][2])
- fprintf (dump_file, "%-50s: %8i calls, %8i freq, "HOST_WIDEST_INT_PRINT_DEC" count\n",
+ fprintf (dump_file, "%-50s: %8i calls, %8i freq, %"PRId64" count\n",
cgraph_inline_failed_string ((cgraph_inline_failed_t) i),
(int) reason[i][2], (int) reason[i][1], reason[i][0]);
}
@@ -2904,8 +2909,9 @@ ipa_inline (void)
int num_calls = 0;
cgraph_for_node_and_aliases (node, sum_callers,
&num_calls, true);
- cgraph_for_node_and_aliases (node, inline_to_all_callers,
- &num_calls, true);
+ while (cgraph_for_node_and_aliases (node, inline_to_all_callers,
+ &num_calls, true))
+ ;
remove_functions = true;
}
}
diff --git a/gcc/ipa-inline.h b/gcc/ipa-inline.h
index 1e9ff4ca0a8..bddf29a2430 100644
--- a/gcc/ipa-inline.h
+++ b/gcc/ipa-inline.h
@@ -236,7 +236,8 @@ void compute_inline_parameters (struct cgraph_node *, bool);
bool speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining);
/* In ipa-inline-transform.c */
-bool inline_call (struct cgraph_edge *, bool, vec<cgraph_edge_p> *, int *, bool);
+bool inline_call (struct cgraph_edge *, bool, vec<cgraph_edge_p> *, int *, bool,
+ bool *callee_removed = NULL);
unsigned int inline_transform (struct cgraph_node *);
void clone_inlined_nodes (struct cgraph_edge *e, bool, bool, int *,
int freq_scale);
diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c
index 71bd61b1212..339f38ea0db 100644
--- a/gcc/ipa-profile.c
+++ b/gcc/ipa-profile.c
@@ -163,8 +163,8 @@ dump_histogram (FILE *file, vec<histogram_entry *> histogram)
{
cumulated_time += histogram[i]->count * histogram[i]->time;
cumulated_size += histogram[i]->size;
- fprintf (file, " "HOST_WIDEST_INT_PRINT_DEC": time:%i (%2.2f) size:%i (%2.2f)\n",
- (HOST_WIDEST_INT) histogram[i]->count,
+ fprintf (file, " %"PRId64": time:%i (%2.2f) size:%i (%2.2f)\n",
+ (int64_t) histogram[i]->count,
histogram[i]->time,
cumulated_time * 100.0 / overall_time,
histogram[i]->size,
@@ -516,8 +516,8 @@ ipa_profile (void)
{
gcov_type min, cumulated_time = 0, cumulated_size = 0;
- fprintf (dump_file, "Overall time: "HOST_WIDEST_INT_PRINT_DEC"\n",
- (HOST_WIDEST_INT)overall_time);
+ fprintf (dump_file, "Overall time: %"PRId64"\n",
+ (int64_t)overall_time);
min = get_hot_bb_threshold ();
for (i = 0; i < (int)histogram.length () && histogram[i]->count >= min;
i++)
@@ -525,9 +525,9 @@ ipa_profile (void)
cumulated_time += histogram[i]->count * histogram[i]->time;
cumulated_size += histogram[i]->size;
}
- fprintf (dump_file, "GCOV min count: "HOST_WIDEST_INT_PRINT_DEC
+ fprintf (dump_file, "GCOV min count: %"PRId64
" Time:%3.2f%% Size:%3.2f%%\n",
- (HOST_WIDEST_INT)min,
+ (int64_t)min,
cumulated_time * 100.0 / overall_time,
cumulated_size * 100.0 / overall_size);
}
@@ -551,9 +551,9 @@ ipa_profile (void)
cumulated_time += histogram[i]->count * histogram[i]->time;
cumulated_size += histogram[i]->size;
}
- fprintf (dump_file, "Determined min count: "HOST_WIDEST_INT_PRINT_DEC
+ fprintf (dump_file, "Determined min count: %"PRId64
" Time:%3.2f%% Size:%3.2f%%\n",
- (HOST_WIDEST_INT)threshold,
+ (int64_t)threshold,
cumulated_time * 100.0 / overall_time,
cumulated_size * 100.0 / overall_size);
}
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index da6ffe86169..167082160eb 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -59,14 +59,59 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-utils.h"
#include "stringpool.h"
#include "tree-ssanames.h"
+#include "dbgcnt.h"
+#include "domwalk.h"
+#include "builtins.h"
-/* Intermediate information about a parameter that is only useful during the
- run of ipa_analyze_node and is not kept afterwards. */
+/* Intermediate information that we get from alias analysis about a particular
+ parameter in a particular basic_block. When a parameter or the memory it
+ references is marked modified, we use that information in all dominatd
+ blocks without cosulting alias analysis oracle. */
-struct param_analysis_info
+struct param_aa_status
{
+ /* Set when this structure contains meaningful information. If not, the
+ structure describing a dominating BB should be used instead. */
+ bool valid;
+
+ /* Whether we have seen something which might have modified the data in
+ question. PARM is for the parameter itself, REF is for data it points to
+ but using the alias type of individual accesses and PT is the same thing
+ but for computing aggregate pass-through functions using a very inclusive
+ ao_ref. */
bool parm_modified, ref_modified, pt_modified;
- bitmap parm_visited_statements, pt_visited_statements;
+};
+
+/* Information related to a given BB that used only when looking at function
+ body. */
+
+struct ipa_bb_info
+{
+ /* Call graph edges going out of this BB. */
+ vec<cgraph_edge_p> cg_edges;
+ /* Alias analysis statuses of each formal parameter at this bb. */
+ vec<param_aa_status> param_aa_statuses;
+};
+
+/* Structure with global information that is only used when looking at function
+ body. */
+
+struct func_body_info
+{
+ /* The node that is being analyzed. */
+ cgraph_node *node;
+
+ /* Its info. */
+ struct ipa_node_params *info;
+
+ /* Information about individual BBs. */
+ vec<ipa_bb_info> bb_infos;
+
+ /* Number of parameters. */
+ int param_count;
+
+ /* Number of statements already walked by when analyzing this function. */
+ unsigned int aa_walked;
};
/* Vector where the parameter infos are actually stored. */
@@ -510,6 +555,16 @@ ipa_binfo_from_known_type_jfunc (struct ipa_jump_func *jfunc)
jfunc->value.known_type.component_type);
}
+/* Get IPA BB information about the given BB. FBI is the context of analyzis
+ of this function body. */
+
+static struct ipa_bb_info *
+ipa_get_bb_info (struct func_body_info *fbi, basic_block bb)
+{
+ gcc_checking_assert (fbi);
+ return &fbi->bb_infos[bb->index];
+}
+
/* Structure to be passed in between detect_type_change and
check_stmt_for_type_change. */
@@ -769,34 +824,101 @@ mark_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
return true;
}
+/* Return true if we have already walked so many statements in AA that we
+ should really just start giving up. */
+
+static bool
+aa_overwalked (struct func_body_info *fbi)
+{
+ gcc_checking_assert (fbi);
+ return fbi->aa_walked > (unsigned) PARAM_VALUE (PARAM_IPA_MAX_AA_STEPS);
+}
+
+/* Find the nearest valid aa status for parameter specified by INDEX that
+ dominates BB. */
+
+static struct param_aa_status *
+find_dominating_aa_status (struct func_body_info *fbi, basic_block bb,
+ int index)
+{
+ while (true)
+ {
+ bb = get_immediate_dominator (CDI_DOMINATORS, bb);
+ if (!bb)
+ return NULL;
+ struct ipa_bb_info *bi = ipa_get_bb_info (fbi, bb);
+ if (!bi->param_aa_statuses.is_empty ()
+ && bi->param_aa_statuses[index].valid)
+ return &bi->param_aa_statuses[index];
+ }
+}
+
+/* Get AA status structure for the given BB and parameter with INDEX. Allocate
+ structures and/or intialize the result with a dominating description as
+ necessary. */
+
+static struct param_aa_status *
+parm_bb_aa_status_for_bb (struct func_body_info *fbi, basic_block bb,
+ int index)
+{
+ gcc_checking_assert (fbi);
+ struct ipa_bb_info *bi = ipa_get_bb_info (fbi, bb);
+ if (bi->param_aa_statuses.is_empty ())
+ bi->param_aa_statuses.safe_grow_cleared (fbi->param_count);
+ struct param_aa_status *paa = &bi->param_aa_statuses[index];
+ if (!paa->valid)
+ {
+ gcc_checking_assert (!paa->parm_modified
+ && !paa->ref_modified
+ && !paa->pt_modified);
+ struct param_aa_status *dom_paa;
+ dom_paa = find_dominating_aa_status (fbi, bb, index);
+ if (dom_paa)
+ *paa = *dom_paa;
+ else
+ paa->valid = true;
+ }
+
+ return paa;
+}
+
/* Return true if a load from a formal parameter PARM_LOAD is known to retrieve
a value known not to be modified in this function before reaching the
- statement STMT. PARM_AINFO is a pointer to a structure containing temporary
- information about the parameter. */
+ statement STMT. FBI holds information about the function we have so far
+ gathered but do not survive the summary building stage. */
static bool
-parm_preserved_before_stmt_p (struct param_analysis_info *parm_ainfo,
- gimple stmt, tree parm_load)
+parm_preserved_before_stmt_p (struct func_body_info *fbi, int index,
+ gimple stmt, tree parm_load)
{
+ struct param_aa_status *paa;
bool modified = false;
- bitmap *visited_stmts;
ao_ref refd;
- if (parm_ainfo && parm_ainfo->parm_modified)
- return false;
+ /* FIXME: FBI can be NULL if we are being called from outside
+ ipa_node_analysis or ipcp_transform_function, which currently happens
+ during inlining analysis. It would be great to extend fbi's lifetime and
+ always have it. Currently, we are just not afraid of too much walking in
+ that case. */
+ if (fbi)
+ {
+ if (aa_overwalked (fbi))
+ return false;
+ paa = parm_bb_aa_status_for_bb (fbi, gimple_bb (stmt), index);
+ if (paa->parm_modified)
+ return false;
+ }
+ else
+ paa = NULL;
gcc_checking_assert (gimple_vuse (stmt) != NULL_TREE);
ao_ref_init (&refd, parm_load);
- /* We can cache visited statements only when parm_ainfo is available and when
- we are looking at a naked load of the whole parameter. */
- if (!parm_ainfo || TREE_CODE (parm_load) != PARM_DECL)
- visited_stmts = NULL;
- else
- visited_stmts = &parm_ainfo->parm_visited_statements;
- walk_aliased_vdefs (&refd, gimple_vuse (stmt), mark_modified, &modified,
- visited_stmts);
- if (parm_ainfo && modified)
- parm_ainfo->parm_modified = true;
+ int walked = walk_aliased_vdefs (&refd, gimple_vuse (stmt), mark_modified,
+ &modified, NULL);
+ if (fbi)
+ fbi->aa_walked += walked;
+ if (paa && modified)
+ paa->parm_modified = true;
return !modified;
}
@@ -805,8 +927,8 @@ parm_preserved_before_stmt_p (struct param_analysis_info *parm_ainfo,
modified. Otherwise return -1. */
static int
-load_from_unmodified_param (vec<ipa_param_descriptor> descriptors,
- struct param_analysis_info *parms_ainfo,
+load_from_unmodified_param (struct func_body_info *fbi,
+ vec<ipa_param_descriptor> descriptors,
gimple stmt)
{
int index;
@@ -821,45 +943,58 @@ load_from_unmodified_param (vec<ipa_param_descriptor> descriptors,
index = ipa_get_param_decl_index_1 (descriptors, op1);
if (index < 0
- || !parm_preserved_before_stmt_p (parms_ainfo ? &parms_ainfo[index]
- : NULL, stmt, op1))
+ || !parm_preserved_before_stmt_p (fbi, index, stmt, op1))
return -1;
return index;
}
-/* Return true if memory reference REF loads data that are known to be
- unmodified in this function before reaching statement STMT. PARM_AINFO, if
- non-NULL, is a pointer to a structure containing temporary information about
- PARM. */
+/* Return true if memory reference REF (which must be a load through parameter
+ with INDEX) loads data that are known to be unmodified in this function
+ before reaching statement STMT. */
static bool
-parm_ref_data_preserved_p (struct param_analysis_info *parm_ainfo,
- gimple stmt, tree ref)
+parm_ref_data_preserved_p (struct func_body_info *fbi,
+ int index, gimple stmt, tree ref)
{
+ struct param_aa_status *paa;
bool modified = false;
ao_ref refd;
- gcc_checking_assert (gimple_vuse (stmt));
- if (parm_ainfo && parm_ainfo->ref_modified)
- return false;
+ /* FIXME: FBI can be NULL if we are being called from outside
+ ipa_node_analysis or ipcp_transform_function, which currently happens
+ during inlining analysis. It would be great to extend fbi's lifetime and
+ always have it. Currently, we are just not afraid of too much walking in
+ that case. */
+ if (fbi)
+ {
+ if (aa_overwalked (fbi))
+ return false;
+ paa = parm_bb_aa_status_for_bb (fbi, gimple_bb (stmt), index);
+ if (paa->ref_modified)
+ return false;
+ }
+ else
+ paa = NULL;
+ gcc_checking_assert (gimple_vuse (stmt));
ao_ref_init (&refd, ref);
- walk_aliased_vdefs (&refd, gimple_vuse (stmt), mark_modified, &modified,
- NULL);
- if (parm_ainfo && modified)
- parm_ainfo->ref_modified = true;
+ int walked = walk_aliased_vdefs (&refd, gimple_vuse (stmt), mark_modified,
+ &modified, NULL);
+ if (fbi)
+ fbi->aa_walked += walked;
+ if (paa && modified)
+ paa->ref_modified = true;
return !modified;
}
-/* Return true if the data pointed to by PARM is known to be unmodified in this
- function before reaching call statement CALL into which it is passed.
- PARM_AINFO is a pointer to a structure containing temporary information
- about PARM. */
+/* Return true if the data pointed to by PARM (which is a parameter with INDEX)
+ is known to be unmodified in this function before reaching call statement
+ CALL into which it is passed. FBI describes the function body. */
static bool
-parm_ref_data_pass_through_p (struct param_analysis_info *parm_ainfo,
- gimple call, tree parm)
+parm_ref_data_pass_through_p (struct func_body_info *fbi, int index,
+ gimple call, tree parm)
{
bool modified = false;
ao_ref refd;
@@ -868,17 +1003,21 @@ parm_ref_data_pass_through_p (struct param_analysis_info *parm_ainfo,
function because it is not goin to use it. But do not cache the result
either. Also, no such calculations for non-pointers. */
if (!gimple_vuse (call)
- || !POINTER_TYPE_P (TREE_TYPE (parm)))
+ || !POINTER_TYPE_P (TREE_TYPE (parm))
+ || aa_overwalked (fbi))
return false;
- if (parm_ainfo->pt_modified)
+ struct param_aa_status *paa = parm_bb_aa_status_for_bb (fbi, gimple_bb (call),
+ index);
+ if (paa->pt_modified)
return false;
ao_ref_init_from_ptr_and_size (&refd, parm, NULL_TREE);
- walk_aliased_vdefs (&refd, gimple_vuse (call), mark_modified, &modified,
- parm_ainfo ? &parm_ainfo->pt_visited_statements : NULL);
+ int walked = walk_aliased_vdefs (&refd, gimple_vuse (call), mark_modified,
+ &modified, NULL);
+ fbi->aa_walked += walked;
if (modified)
- parm_ainfo->pt_modified = true;
+ paa->pt_modified = true;
return !modified;
}
@@ -893,10 +1032,11 @@ parm_ref_data_pass_through_p (struct param_analysis_info *parm_ainfo,
reference respectively. */
static bool
-ipa_load_from_parm_agg_1 (vec<ipa_param_descriptor> descriptors,
- struct param_analysis_info *parms_ainfo, gimple stmt,
- tree op, int *index_p, HOST_WIDE_INT *offset_p,
- HOST_WIDE_INT *size_p, bool *by_ref_p)
+ipa_load_from_parm_agg_1 (struct func_body_info *fbi,
+ vec<ipa_param_descriptor> descriptors,
+ gimple stmt, tree op, int *index_p,
+ HOST_WIDE_INT *offset_p, HOST_WIDE_INT *size_p,
+ bool *by_ref_p)
{
int index;
HOST_WIDE_INT size, max_size;
@@ -909,8 +1049,7 @@ ipa_load_from_parm_agg_1 (vec<ipa_param_descriptor> descriptors,
{
int index = ipa_get_param_decl_index_1 (descriptors, base);
if (index >= 0
- && parm_preserved_before_stmt_p (parms_ainfo ? &parms_ainfo[index]
- : NULL, stmt, op))
+ && parm_preserved_before_stmt_p (fbi, index, stmt, op))
{
*index_p = index;
*by_ref_p = false;
@@ -949,12 +1088,11 @@ ipa_load_from_parm_agg_1 (vec<ipa_param_descriptor> descriptors,
*/
gimple def = SSA_NAME_DEF_STMT (TREE_OPERAND (base, 0));
- index = load_from_unmodified_param (descriptors, parms_ainfo, def);
+ index = load_from_unmodified_param (fbi, descriptors, def);
}
if (index >= 0
- && parm_ref_data_preserved_p (parms_ainfo ? &parms_ainfo[index] : NULL,
- stmt, op))
+ && parm_ref_data_preserved_p (fbi, index, stmt, op))
{
*index_p = index;
*by_ref_p = true;
@@ -973,7 +1111,7 @@ ipa_load_from_parm_agg (struct ipa_node_params *info, gimple stmt,
tree op, int *index_p, HOST_WIDE_INT *offset_p,
bool *by_ref_p)
{
- return ipa_load_from_parm_agg_1 (info->descriptors, NULL, stmt, op, index_p,
+ return ipa_load_from_parm_agg_1 (NULL, info->descriptors, stmt, op, index_p,
offset_p, NULL, by_ref_p);
}
@@ -1031,8 +1169,8 @@ ipa_load_from_parm_agg (struct ipa_node_params *info, gimple stmt,
only needed for intraprocedural analysis. */
static void
-compute_complex_assign_jump_func (struct ipa_node_params *info,
- struct param_analysis_info *parms_ainfo,
+compute_complex_assign_jump_func (struct func_body_info *fbi,
+ struct ipa_node_params *info,
struct ipa_jump_func *jfunc,
gimple call, gimple stmt, tree name,
tree param_type)
@@ -1048,13 +1186,13 @@ compute_complex_assign_jump_func (struct ipa_node_params *info,
if (SSA_NAME_IS_DEFAULT_DEF (op1))
index = ipa_get_param_decl_index (info, SSA_NAME_VAR (op1));
else
- index = load_from_unmodified_param (info->descriptors, parms_ainfo,
+ index = load_from_unmodified_param (fbi, info->descriptors,
SSA_NAME_DEF_STMT (op1));
tc_ssa = op1;
}
else
{
- index = load_from_unmodified_param (info->descriptors, parms_ainfo, stmt);
+ index = load_from_unmodified_param (fbi, info->descriptors, stmt);
tc_ssa = gimple_assign_lhs (stmt);
}
@@ -1075,8 +1213,7 @@ compute_complex_assign_jump_func (struct ipa_node_params *info,
}
else if (gimple_assign_single_p (stmt))
{
- bool agg_p = parm_ref_data_pass_through_p (&parms_ainfo[index],
- call, tc_ssa);
+ bool agg_p = parm_ref_data_pass_through_p (fbi, index, call, tc_ssa);
bool type_p = false;
if (param_type && POINTER_TYPE_P (param_type))
@@ -1115,7 +1252,7 @@ compute_complex_assign_jump_func (struct ipa_node_params *info,
if (type_p || jfunc->type == IPA_JF_UNKNOWN)
ipa_set_ancestor_jf (jfunc, offset,
type_p ? TREE_TYPE (param_type) : NULL, index,
- parm_ref_data_pass_through_p (&parms_ainfo[index],
+ parm_ref_data_pass_through_p (fbi, index,
call, ssa), type_p);
}
}
@@ -1187,8 +1324,8 @@ get_ancestor_addr_info (gimple assign, tree *obj_p, HOST_WIDE_INT *offset)
return D.1879_6; */
static void
-compute_complex_ancestor_jump_func (struct ipa_node_params *info,
- struct param_analysis_info *parms_ainfo,
+compute_complex_ancestor_jump_func (struct func_body_info *fbi,
+ struct ipa_node_params *info,
struct ipa_jump_func *jfunc,
gimple call, gimple phi, tree param_type)
{
@@ -1247,9 +1384,10 @@ compute_complex_ancestor_jump_func (struct ipa_node_params *info,
type_p = !detect_type_change (obj, expr, TREE_TYPE (param_type),
call, jfunc, offset);
if (type_p || jfunc->type == IPA_JF_UNKNOWN)
- ipa_set_ancestor_jf (jfunc, offset, type_p ? TREE_TYPE (param_type) : NULL, index,
- parm_ref_data_pass_through_p (&parms_ainfo[index],
- call, parm), type_p);
+ ipa_set_ancestor_jf (jfunc, offset, type_p ? TREE_TYPE (param_type) : NULL,
+ index,
+ parm_ref_data_pass_through_p (fbi, index, call, parm),
+ type_p);
}
/* Given OP which is passed as an actual argument to a called function,
@@ -1594,7 +1732,7 @@ ipa_get_callee_param_type (struct cgraph_edge *e, int i)
to this callsite. */
static void
-ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_ainfo,
+ipa_compute_jump_functions_for_edge (struct func_body_info *fbi,
struct cgraph_edge *cs)
{
struct ipa_node_params *info = IPA_NODE_REF (cs->caller);
@@ -1628,7 +1766,7 @@ ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_ainfo,
/* Aggregate passed by value, check for pass-through, otherwise we
will attempt to fill in aggregate contents later in this
for cycle. */
- if (parm_preserved_before_stmt_p (&parms_ainfo[index], call, arg))
+ if (parm_preserved_before_stmt_p (fbi, index, call, arg))
{
ipa_set_jf_simple_pass_through (jfunc, index, false, false);
continue;
@@ -1642,8 +1780,7 @@ ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_ainfo,
if (index >= 0)
{
bool agg_p, type_p;
- agg_p = parm_ref_data_pass_through_p (&parms_ainfo[index],
- call, arg);
+ agg_p = parm_ref_data_pass_through_p (fbi, index, call, arg);
if (param_type && POINTER_TYPE_P (param_type))
type_p = !detect_type_change_ssa (arg, TREE_TYPE (param_type),
call, jfunc);
@@ -1658,10 +1795,10 @@ ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_ainfo,
{
gimple stmt = SSA_NAME_DEF_STMT (arg);
if (is_gimple_assign (stmt))
- compute_complex_assign_jump_func (info, parms_ainfo, jfunc,
+ compute_complex_assign_jump_func (fbi, info, jfunc,
call, stmt, arg, param_type);
else if (gimple_code (stmt) == GIMPLE_PHI)
- compute_complex_ancestor_jump_func (info, parms_ainfo, jfunc,
+ compute_complex_ancestor_jump_func (fbi, info, jfunc,
call, stmt, param_type);
}
}
@@ -1692,27 +1829,29 @@ ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_ainfo,
}
/* Compute jump functions for all edges - both direct and indirect - outgoing
- from NODE. Also count the actual arguments in the process. */
+ from BB. */
static void
-ipa_compute_jump_functions (struct cgraph_node *node,
- struct param_analysis_info *parms_ainfo)
+ipa_compute_jump_functions_for_bb (struct func_body_info *fbi, basic_block bb)
{
+ struct ipa_bb_info *bi = ipa_get_bb_info (fbi, bb);
+ int i;
struct cgraph_edge *cs;
- for (cs = node->callees; cs; cs = cs->next_callee)
+ FOR_EACH_VEC_ELT_REVERSE (bi->cg_edges, i, cs)
{
- struct cgraph_node *callee = cgraph_function_or_thunk_node (cs->callee,
- NULL);
- /* We do not need to bother analyzing calls to unknown
- functions unless they may become known during lto/whopr. */
- if (!callee->definition && !flag_lto)
- continue;
- ipa_compute_jump_functions_for_edge (parms_ainfo, cs);
- }
+ struct cgraph_node *callee = cs->callee;
- for (cs = node->indirect_calls; cs; cs = cs->next_callee)
- ipa_compute_jump_functions_for_edge (parms_ainfo, cs);
+ if (callee)
+ {
+ cgraph_function_or_thunk_node (callee, NULL);
+ /* We do not need to bother analyzing calls to unknown functions
+ unless they may become known during lto/whopr. */
+ if (!callee->definition && !flag_lto)
+ continue;
+ }
+ ipa_compute_jump_functions_for_edge (fbi, cs);
+ }
}
/* If STMT looks like a statement loading a value from a member pointer formal
@@ -1855,37 +1994,30 @@ ipa_note_param_call (struct cgraph_node *node, int param_index, gimple stmt)
passed by value or reference. */
static void
-ipa_analyze_indirect_call_uses (struct cgraph_node *node,
- struct ipa_node_params *info,
- struct param_analysis_info *parms_ainfo,
- gimple call, tree target)
+ipa_analyze_indirect_call_uses (struct func_body_info *fbi, gimple call,
+ tree target)
{
- gimple def;
- tree n1, n2;
- gimple d1, d2;
- tree rec, rec2, cond;
- gimple branch;
- int index;
- basic_block bb, virt_bb, join;
+ struct ipa_node_params *info = fbi->info;
HOST_WIDE_INT offset;
bool by_ref;
if (SSA_NAME_IS_DEFAULT_DEF (target))
{
tree var = SSA_NAME_VAR (target);
- index = ipa_get_param_decl_index (info, var);
+ int index = ipa_get_param_decl_index (info, var);
if (index >= 0)
- ipa_note_param_call (node, index, call);
+ ipa_note_param_call (fbi->node, index, call);
return;
}
- def = SSA_NAME_DEF_STMT (target);
+ int index;
+ gimple def = SSA_NAME_DEF_STMT (target);
if (gimple_assign_single_p (def)
- && ipa_load_from_parm_agg_1 (info->descriptors, parms_ainfo, def,
+ && ipa_load_from_parm_agg_1 (fbi, info->descriptors, def,
gimple_assign_rhs1 (def), &index, &offset,
NULL, &by_ref))
{
- struct cgraph_edge *cs = ipa_note_param_call (node, index, call);
+ struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call);
if (cs->indirect_info->offset != offset)
cs->indirect_info->outer_type = NULL;
cs->indirect_info->offset = offset;
@@ -1904,14 +2036,16 @@ ipa_analyze_indirect_call_uses (struct cgraph_node *node,
/* First, we need to check whether one of these is a load from a member
pointer that is a parameter to this function. */
- n1 = PHI_ARG_DEF (def, 0);
- n2 = PHI_ARG_DEF (def, 1);
+ tree n1 = PHI_ARG_DEF (def, 0);
+ tree n2 = PHI_ARG_DEF (def, 1);
if (!ipa_is_ssa_with_stmt_def (n1) || !ipa_is_ssa_with_stmt_def (n2))
return;
- d1 = SSA_NAME_DEF_STMT (n1);
- d2 = SSA_NAME_DEF_STMT (n2);
+ gimple d1 = SSA_NAME_DEF_STMT (n1);
+ gimple d2 = SSA_NAME_DEF_STMT (n2);
- join = gimple_bb (def);
+ tree rec;
+ basic_block bb, virt_bb;
+ basic_block join = gimple_bb (def);
if ((rec = ipa_get_stmt_member_ptr_load_param (d1, false, &offset)))
{
if (ipa_get_stmt_member_ptr_load_param (d2, false, NULL))
@@ -1939,7 +2073,7 @@ ipa_analyze_indirect_call_uses (struct cgraph_node *node,
/* Third, let's see that the branching is done depending on the least
significant bit of the pfn. */
- branch = last_stmt (bb);
+ gimple branch = last_stmt (bb);
if (!branch || gimple_code (branch) != GIMPLE_COND)
return;
@@ -1948,7 +2082,7 @@ ipa_analyze_indirect_call_uses (struct cgraph_node *node,
|| !integer_zerop (gimple_cond_rhs (branch)))
return;
- cond = gimple_cond_lhs (branch);
+ tree cond = gimple_cond_lhs (branch);
if (!ipa_is_ssa_with_stmt_def (cond))
return;
@@ -1973,6 +2107,7 @@ ipa_analyze_indirect_call_uses (struct cgraph_node *node,
def = SSA_NAME_DEF_STMT (cond);
}
+ tree rec2;
rec2 = ipa_get_stmt_member_ptr_load_param (def,
(TARGET_PTRMEMFUNC_VBIT_LOCATION
== ptrmemfunc_vbit_in_delta),
@@ -1982,9 +2117,9 @@ ipa_analyze_indirect_call_uses (struct cgraph_node *node,
index = ipa_get_param_decl_index (info, rec);
if (index >= 0
- && parm_preserved_before_stmt_p (&parms_ainfo[index], call, rec))
+ && parm_preserved_before_stmt_p (fbi, index, call, rec))
{
- struct cgraph_edge *cs = ipa_note_param_call (node, index, call);
+ struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call);
if (cs->indirect_info->offset != offset)
cs->indirect_info->outer_type = NULL;
cs->indirect_info->offset = offset;
@@ -1997,16 +2132,13 @@ ipa_analyze_indirect_call_uses (struct cgraph_node *node,
/* Analyze a CALL to an OBJ_TYPE_REF which is passed in TARGET and if the
object referenced in the expression is a formal parameter of the caller
- (described by INFO), create a call note for the statement. */
+ FBI->node (described by FBI->info), create a call note for the
+ statement. */
static void
-ipa_analyze_virtual_call_uses (struct cgraph_node *node,
- struct ipa_node_params *info, gimple call,
- tree target)
+ipa_analyze_virtual_call_uses (struct func_body_info *fbi,
+ gimple call, tree target)
{
- struct cgraph_edge *cs;
- struct cgraph_indirect_call_info *ii;
- struct ipa_jump_func jfunc;
tree obj = OBJ_TYPE_REF_OBJECT (target);
int index;
HOST_WIDE_INT anc_offset;
@@ -2017,8 +2149,10 @@ ipa_analyze_virtual_call_uses (struct cgraph_node *node,
if (TREE_CODE (obj) != SSA_NAME)
return;
+ struct ipa_node_params *info = fbi->info;
if (SSA_NAME_IS_DEFAULT_DEF (obj))
{
+ struct ipa_jump_func jfunc;
if (TREE_CODE (SSA_NAME_VAR (obj)) != PARM_DECL)
return;
@@ -2031,6 +2165,7 @@ ipa_analyze_virtual_call_uses (struct cgraph_node *node,
}
else
{
+ struct ipa_jump_func jfunc;
gimple stmt = SSA_NAME_DEF_STMT (obj);
tree expr;
@@ -2045,8 +2180,8 @@ ipa_analyze_virtual_call_uses (struct cgraph_node *node,
return;
}
- cs = ipa_note_param_call (node, index, call);
- ii = cs->indirect_info;
+ struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call);
+ struct cgraph_indirect_call_info *ii = cs->indirect_info;
ii->offset = anc_offset;
ii->otr_token = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target));
ii->otr_type = obj_type_ref_class (target);
@@ -2058,12 +2193,9 @@ ipa_analyze_virtual_call_uses (struct cgraph_node *node,
containing intermediate information about each formal parameter. */
static void
-ipa_analyze_call_uses (struct cgraph_node *node,
- struct ipa_node_params *info,
- struct param_analysis_info *parms_ainfo, gimple call)
+ipa_analyze_call_uses (struct func_body_info *fbi, gimple call)
{
tree target = gimple_call_fn (call);
- struct cgraph_edge *cs;
if (!target
|| (TREE_CODE (target) != SSA_NAME
@@ -2072,27 +2204,25 @@ ipa_analyze_call_uses (struct cgraph_node *node,
/* If we previously turned the call into a direct call, there is
no need to analyze. */
- cs = cgraph_edge (node, call);
+ struct cgraph_edge *cs = cgraph_edge (fbi->node, call);
if (cs && !cs->indirect_unknown_callee)
return;
if (TREE_CODE (target) == SSA_NAME)
- ipa_analyze_indirect_call_uses (node, info, parms_ainfo, call, target);
+ ipa_analyze_indirect_call_uses (fbi, call, target);
else if (virtual_method_call_p (target))
- ipa_analyze_virtual_call_uses (node, info, call, target);
+ ipa_analyze_virtual_call_uses (fbi, call, target);
}
/* Analyze the call statement STMT with respect to formal parameters (described
- in INFO) of caller given by NODE. Currently it only checks whether formal
- parameters are called. PARMS_AINFO is a pointer to a vector containing
- intermediate information about each formal parameter. */
+ in INFO) of caller given by FBI->NODE. Currently it only checks whether
+ formal parameters are called. */
static void
-ipa_analyze_stmt_uses (struct cgraph_node *node, struct ipa_node_params *info,
- struct param_analysis_info *parms_ainfo, gimple stmt)
+ipa_analyze_stmt_uses (struct func_body_info *fbi, gimple stmt)
{
if (is_gimple_call (stmt))
- ipa_analyze_call_uses (node, info, parms_ainfo, stmt);
+ ipa_analyze_call_uses (fbi, stmt);
}
/* Callback of walk_stmt_load_store_addr_ops for the visit_load.
@@ -2116,37 +2246,43 @@ visit_ref_for_mod_analysis (gimple, tree op, tree, void *data)
return false;
}
-/* Scan the function body of NODE and inspect the uses of formal parameters.
- Store the findings in various structures of the associated ipa_node_params
- structure, such as parameter flags, notes etc. PARMS_AINFO is a pointer to a
- vector containing intermediate information about each formal parameter. */
+/* Scan the statements in BB and inspect the uses of formal parameters. Store
+ the findings in various structures of the associated ipa_node_params
+ structure, such as parameter flags, notes etc. FBI holds various data about
+ the function being analyzed. */
static void
-ipa_analyze_params_uses (struct cgraph_node *node,
- struct param_analysis_info *parms_ainfo)
+ipa_analyze_params_uses_in_bb (struct func_body_info *fbi, basic_block bb)
{
- tree decl = node->decl;
- basic_block bb;
- struct function *func;
gimple_stmt_iterator gsi;
- struct ipa_node_params *info = IPA_NODE_REF (node);
- int i;
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
- if (ipa_get_param_count (info) == 0 || info->uses_analysis_done)
- return;
+ if (is_gimple_debug (stmt))
+ continue;
- info->uses_analysis_done = 1;
- if (ipa_func_spec_opts_forbid_analysis_p (node))
- {
- for (i = 0; i < ipa_get_param_count (info); i++)
- {
- ipa_set_param_used (info, i, true);
- ipa_set_controlled_uses (info, i, IPA_UNDESCRIBED_USE);
- }
- return;
+ ipa_analyze_stmt_uses (fbi, stmt);
+ walk_stmt_load_store_addr_ops (stmt, fbi->info,
+ visit_ref_for_mod_analysis,
+ visit_ref_for_mod_analysis,
+ visit_ref_for_mod_analysis);
}
+ for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ walk_stmt_load_store_addr_ops (gsi_stmt (gsi), fbi->info,
+ visit_ref_for_mod_analysis,
+ visit_ref_for_mod_analysis,
+ visit_ref_for_mod_analysis);
+}
+
+/* Calculate controlled uses of parameters of NODE. */
- for (i = 0; i < ipa_get_param_count (info); i++)
+static void
+ipa_analyze_controlled_uses (struct cgraph_node *node)
+{
+ struct ipa_node_params *info = IPA_NODE_REF (node);
+
+ for (int i = 0; i < ipa_get_param_count (info); i++)
{
tree parm = ipa_get_param (info, i);
int controlled_uses = 0;
@@ -2182,45 +2318,36 @@ ipa_analyze_params_uses (struct cgraph_node *node,
controlled_uses = IPA_UNDESCRIBED_USE;
ipa_set_controlled_uses (info, i, controlled_uses);
}
+}
- func = DECL_STRUCT_FUNCTION (decl);
- FOR_EACH_BB_FN (bb, func)
- {
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gimple stmt = gsi_stmt (gsi);
-
- if (is_gimple_debug (stmt))
- continue;
+/* Free stuff in BI. */
- ipa_analyze_stmt_uses (node, info, parms_ainfo, stmt);
- walk_stmt_load_store_addr_ops (stmt, info,
- visit_ref_for_mod_analysis,
- visit_ref_for_mod_analysis,
- visit_ref_for_mod_analysis);
- }
- for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- walk_stmt_load_store_addr_ops (gsi_stmt (gsi), info,
- visit_ref_for_mod_analysis,
- visit_ref_for_mod_analysis,
- visit_ref_for_mod_analysis);
- }
+static void
+free_ipa_bb_info (struct ipa_bb_info *bi)
+{
+ bi->cg_edges.release ();
+ bi->param_aa_statuses.release ();
}
-/* Free stuff in PARMS_AINFO, assume there are PARAM_COUNT parameters. */
+/* Dominator walker driving the analysis. */
-static void
-free_parms_ainfo (struct param_analysis_info *parms_ainfo, int param_count)
+class analysis_dom_walker : public dom_walker
{
- int i;
+public:
+ analysis_dom_walker (struct func_body_info *fbi)
+ : dom_walker (CDI_DOMINATORS), m_fbi (fbi) {}
- for (i = 0; i < param_count; i++)
- {
- if (parms_ainfo[i].parm_visited_statements)
- BITMAP_FREE (parms_ainfo[i].parm_visited_statements);
- if (parms_ainfo[i].pt_visited_statements)
- BITMAP_FREE (parms_ainfo[i].pt_visited_statements);
- }
+ virtual void before_dom_children (basic_block);
+
+private:
+ struct func_body_info *m_fbi;
+};
+
+void
+analysis_dom_walker::before_dom_children (basic_block bb)
+{
+ ipa_analyze_params_uses_in_bb (m_fbi, bb);
+ ipa_compute_jump_functions_for_bb (m_fbi, bb);
}
/* Initialize the array describing properties of of formal parameters
@@ -2230,24 +2357,60 @@ free_parms_ainfo (struct param_analysis_info *parms_ainfo, int param_count)
void
ipa_analyze_node (struct cgraph_node *node)
{
+ struct func_body_info fbi;
struct ipa_node_params *info;
- struct param_analysis_info *parms_ainfo;
- int param_count;
ipa_check_create_node_params ();
ipa_check_create_edge_args ();
info = IPA_NODE_REF (node);
- push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+
+ if (info->analysis_done)
+ return;
+ info->analysis_done = 1;
+
+ if (ipa_func_spec_opts_forbid_analysis_p (node))
+ {
+ for (int i = 0; i < ipa_get_param_count (info); i++)
+ {
+ ipa_set_param_used (info, i, true);
+ ipa_set_controlled_uses (info, i, IPA_UNDESCRIBED_USE);
+ }
+ return;
+ }
+
+ struct function *func = DECL_STRUCT_FUNCTION (node->decl);
+ push_cfun (func);
+ calculate_dominance_info (CDI_DOMINATORS);
ipa_initialize_node_params (node);
+ ipa_analyze_controlled_uses (node);
- param_count = ipa_get_param_count (info);
- parms_ainfo = XALLOCAVEC (struct param_analysis_info, param_count);
- memset (parms_ainfo, 0, sizeof (struct param_analysis_info) * param_count);
+ fbi.node = node;
+ fbi.info = IPA_NODE_REF (node);
+ fbi.bb_infos = vNULL;
+ fbi.bb_infos.safe_grow_cleared (last_basic_block_for_fn (cfun));
+ fbi.param_count = ipa_get_param_count (info);
+ fbi.aa_walked = 0;
- ipa_analyze_params_uses (node, parms_ainfo);
- ipa_compute_jump_functions (node, parms_ainfo);
+ for (struct cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
+ {
+ ipa_bb_info *bi = ipa_get_bb_info (&fbi, gimple_bb (cs->call_stmt));
+ bi->cg_edges.safe_push (cs);
+ }
- free_parms_ainfo (parms_ainfo, param_count);
+ for (struct cgraph_edge *cs = node->indirect_calls; cs; cs = cs->next_callee)
+ {
+ ipa_bb_info *bi = ipa_get_bb_info (&fbi, gimple_bb (cs->call_stmt));
+ bi->cg_edges.safe_push (cs);
+ }
+
+ analysis_dom_walker (&fbi).walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+
+ int i;
+ struct ipa_bb_info *bi;
+ FOR_EACH_VEC_ELT (fbi.bb_infos, i, bi)
+ free_ipa_bb_info (bi);
+ fbi.bb_infos.release ();
+ free_dominance_info (CDI_DOMINATORS);
pop_cfun ();
}
@@ -2490,10 +2653,15 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
/* Member pointer call that goes through a VMT lookup. */
return NULL;
- if (dump_file)
- fprintf (dump_file, "ipa-prop: Discovered direct call to non-function"
- " in %s/%i, making it unreachable.\n",
- ie->caller->name (), ie->caller->order);
+ if (dump_enabled_p ())
+ {
+ location_t loc = gimple_location (ie->call_stmt);
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+ "discovered direct call to non-function in %s/%i, "
+ "making it __builtin_unreachable\n",
+ ie->caller->name (),
+ ie->caller->order);
+ }
target = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
callee = cgraph_get_create_node (target);
unreachable = true;
@@ -2527,6 +2695,10 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
}
callee = cgraph_get_create_node (target);
}
+
+ if (!dbg_cnt (devirt))
+ return NULL;
+
ipa_check_create_node_params ();
/* We can not make edges to inline clones. It is bug that someone removed
@@ -2547,6 +2719,13 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
else
fprintf (dump_file, "with uid %i\n", ie->lto_stmt_uid);
}
+ if (dump_enabled_p ())
+ {
+ location_t loc = gimple_location (ie->call_stmt);
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+ "converting indirect call in %s to direct call to %s\n",
+ ie->caller->name (), callee->name ());
+ }
ie = cgraph_make_edge_direct (ie, callee);
es = inline_edge_summary (ie);
es->call_stmt_size -= (eni_size_weights.indirect_call_cost
@@ -2877,16 +3056,20 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs,
else if (jfunc->type == IPA_JF_PASS_THROUGH
&& ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
{
- if (ici->agg_contents
- && !ipa_get_jf_pass_through_agg_preserved (jfunc))
+ if ((ici->agg_contents
+ && !ipa_get_jf_pass_through_agg_preserved (jfunc))
+ || (ici->polymorphic
+ && !ipa_get_jf_pass_through_type_preserved (jfunc)))
ici->param_index = -1;
else
ici->param_index = ipa_get_jf_pass_through_formal_id (jfunc);
}
else if (jfunc->type == IPA_JF_ANCESTOR)
{
- if (ici->agg_contents
- && !ipa_get_jf_ancestor_agg_preserved (jfunc))
+ if ((ici->agg_contents
+ && !ipa_get_jf_ancestor_agg_preserved (jfunc))
+ || (ici->polymorphic
+ && !ipa_get_jf_ancestor_type_preserved (jfunc)))
ici->param_index = -1;
else
{
@@ -3299,7 +3482,7 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
new_info->lattices = NULL;
new_info->ipcp_orig_node = old_info->ipcp_orig_node;
- new_info->uses_analysis_done = old_info->uses_analysis_done;
+ new_info->analysis_done = old_info->analysis_done;
new_info->node_enqueued = old_info->node_enqueued;
old_av = ipa_get_agg_replacements_for_node (src);
@@ -3311,7 +3494,7 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
{
struct ipa_agg_replacement_value *v;
- v = ggc_alloc_ipa_agg_replacement_value ();
+ v = ggc_alloc<ipa_agg_replacement_value> ();
memcpy (v, old_av, sizeof (*v));
v->next = new_av;
new_av = v;
@@ -3650,6 +3833,7 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments)
TREE_TYPE (fndecl) = new_type;
DECL_VIRTUAL_P (fndecl) = 0;
+ DECL_LANG_SPECIFIC (fndecl) = NULL;
otypes.release ();
oparms.release ();
}
@@ -4423,7 +4607,7 @@ ipa_write_node_info (struct output_block *ob, struct cgraph_node *node)
for (j = 0; j < ipa_get_param_count (info); j++)
streamer_write_uhwi (ob, ipa_get_param_move_cost (info, j));
bp = bitpack_create (ob->main_stream);
- gcc_assert (info->uses_analysis_done
+ gcc_assert (info->analysis_done
|| ipa_get_param_count (info) == 0);
gcc_assert (!info->node_enqueued);
gcc_assert (!info->ipcp_orig_node);
@@ -4469,7 +4653,7 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node,
bp = streamer_read_bitpack (ib);
if (ipa_get_param_count (info) != 0)
- info->uses_analysis_done = true;
+ info->analysis_done = true;
info->node_enqueued = false;
for (k = 0; k < ipa_get_param_count (info); k++)
ipa_set_param_used (info, k, bp_unpack_value (&bp, 1));
@@ -4669,7 +4853,7 @@ read_agg_replacement_chain (struct lto_input_block *ib,
struct ipa_agg_replacement_value *av;
struct bitpack_d bp;
- av = ggc_alloc_ipa_agg_replacement_value ();
+ av = ggc_alloc<ipa_agg_replacement_value> ();
av->offset = streamer_read_uhwi (ib);
av->index = streamer_read_uhwi (ib);
av->value = stream_read_tree (ib, data_in);
@@ -4819,17 +5003,129 @@ adjust_agg_replacement_values (struct cgraph_node *node,
v->index = adj[v->index];
}
+/* Dominator walker driving the ipcp modification phase. */
-/* Function body transformation phase. */
+class ipcp_modif_dom_walker : public dom_walker
+{
+public:
+ ipcp_modif_dom_walker (struct func_body_info *fbi,
+ vec<ipa_param_descriptor> descs,
+ struct ipa_agg_replacement_value *av,
+ bool *sc, bool *cc)
+ : dom_walker (CDI_DOMINATORS), m_fbi (fbi), m_descriptors (descs),
+ m_aggval (av), m_something_changed (sc), m_cfg_changed (cc) {}
+
+ virtual void before_dom_children (basic_block);
+
+private:
+ struct func_body_info *m_fbi;
+ vec<ipa_param_descriptor> m_descriptors;
+ struct ipa_agg_replacement_value *m_aggval;
+ bool *m_something_changed, *m_cfg_changed;
+};
+
+void
+ipcp_modif_dom_walker::before_dom_children (basic_block bb)
+{
+ gimple_stmt_iterator gsi;
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ struct ipa_agg_replacement_value *v;
+ gimple stmt = gsi_stmt (gsi);
+ tree rhs, val, t;
+ HOST_WIDE_INT offset, size;
+ int index;
+ bool by_ref, vce;
+
+ if (!gimple_assign_load_p (stmt))
+ continue;
+ rhs = gimple_assign_rhs1 (stmt);
+ if (!is_gimple_reg_type (TREE_TYPE (rhs)))
+ continue;
+
+ vce = false;
+ t = rhs;
+ while (handled_component_p (t))
+ {
+ /* V_C_E can do things like convert an array of integers to one
+ bigger integer and similar things we do not handle below. */
+ if (TREE_CODE (rhs) == VIEW_CONVERT_EXPR)
+ {
+ vce = true;
+ break;
+ }
+ t = TREE_OPERAND (t, 0);
+ }
+ if (vce)
+ continue;
+
+ if (!ipa_load_from_parm_agg_1 (m_fbi, m_descriptors, stmt, rhs, &index,
+ &offset, &size, &by_ref))
+ continue;
+ for (v = m_aggval; v; v = v->next)
+ if (v->index == index
+ && v->offset == offset)
+ break;
+ if (!v
+ || v->by_ref != by_ref
+ || tree_to_shwi (TYPE_SIZE (TREE_TYPE (v->value))) != size)
+ continue;
+
+ gcc_checking_assert (is_gimple_ip_invariant (v->value));
+ if (!useless_type_conversion_p (TREE_TYPE (rhs), TREE_TYPE (v->value)))
+ {
+ if (fold_convertible_p (TREE_TYPE (rhs), v->value))
+ val = fold_build1 (NOP_EXPR, TREE_TYPE (rhs), v->value);
+ else if (TYPE_SIZE (TREE_TYPE (rhs))
+ == TYPE_SIZE (TREE_TYPE (v->value)))
+ val = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (rhs), v->value);
+ else
+ {
+ if (dump_file)
+ {
+ fprintf (dump_file, " const ");
+ print_generic_expr (dump_file, v->value, 0);
+ fprintf (dump_file, " can't be converted to type of ");
+ print_generic_expr (dump_file, rhs, 0);
+ fprintf (dump_file, "\n");
+ }
+ continue;
+ }
+ }
+ else
+ val = v->value;
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Modifying stmt:\n ");
+ print_gimple_stmt (dump_file, stmt, 0, 0);
+ }
+ gimple_assign_set_rhs_from_tree (&gsi, val);
+ update_stmt (stmt);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "into:\n ");
+ print_gimple_stmt (dump_file, stmt, 0, 0);
+ fprintf (dump_file, "\n");
+ }
+
+ *m_something_changed = true;
+ if (maybe_clean_eh_stmt (stmt)
+ && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
+ *m_cfg_changed = true;
+ }
+
+}
+
+/* IPCP transformation phase doing propagation of aggregate values. */
unsigned int
ipcp_transform_function (struct cgraph_node *node)
{
vec<ipa_param_descriptor> descriptors = vNULL;
- struct param_analysis_info *parms_ainfo;
+ struct func_body_info fbi;
struct ipa_agg_replacement_value *aggval;
- gimple_stmt_iterator gsi;
- basic_block bb;
int param_count;
bool cfg_changed = false, something_changed = false;
@@ -4849,102 +5145,27 @@ ipcp_transform_function (struct cgraph_node *node)
adjust_agg_replacement_values (node, aggval);
if (dump_file)
ipa_dump_agg_replacement_values (dump_file, aggval);
- parms_ainfo = XALLOCAVEC (struct param_analysis_info, param_count);
- memset (parms_ainfo, 0, sizeof (struct param_analysis_info) * param_count);
- descriptors.safe_grow_cleared (param_count);
- ipa_populate_param_decls (node, descriptors);
- FOR_EACH_BB_FN (bb, cfun)
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- struct ipa_agg_replacement_value *v;
- gimple stmt = gsi_stmt (gsi);
- tree rhs, val, t;
- HOST_WIDE_INT offset, size;
- int index;
- bool by_ref, vce;
-
- if (!gimple_assign_load_p (stmt))
- continue;
- rhs = gimple_assign_rhs1 (stmt);
- if (!is_gimple_reg_type (TREE_TYPE (rhs)))
- continue;
+ fbi.node = node;
+ fbi.info = NULL;
+ fbi.bb_infos = vNULL;
+ fbi.bb_infos.safe_grow_cleared (last_basic_block_for_fn (cfun));
+ fbi.param_count = param_count;
+ fbi.aa_walked = 0;
- vce = false;
- t = rhs;
- while (handled_component_p (t))
- {
- /* V_C_E can do things like convert an array of integers to one
- bigger integer and similar things we do not handle below. */
- if (TREE_CODE (rhs) == VIEW_CONVERT_EXPR)
- {
- vce = true;
- break;
- }
- t = TREE_OPERAND (t, 0);
- }
- if (vce)
- continue;
-
- if (!ipa_load_from_parm_agg_1 (descriptors, parms_ainfo, stmt,
- rhs, &index, &offset, &size, &by_ref))
- continue;
- for (v = aggval; v; v = v->next)
- if (v->index == index
- && v->offset == offset)
- break;
- if (!v
- || v->by_ref != by_ref
- || tree_to_shwi (TYPE_SIZE (TREE_TYPE (v->value))) != size)
- continue;
-
- gcc_checking_assert (is_gimple_ip_invariant (v->value));
- if (!useless_type_conversion_p (TREE_TYPE (rhs), TREE_TYPE (v->value)))
- {
- if (fold_convertible_p (TREE_TYPE (rhs), v->value))
- val = fold_build1 (NOP_EXPR, TREE_TYPE (rhs), v->value);
- else if (TYPE_SIZE (TREE_TYPE (rhs))
- == TYPE_SIZE (TREE_TYPE (v->value)))
- val = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (rhs), v->value);
- else
- {
- if (dump_file)
- {
- fprintf (dump_file, " const ");
- print_generic_expr (dump_file, v->value, 0);
- fprintf (dump_file, " can't be converted to type of ");
- print_generic_expr (dump_file, rhs, 0);
- fprintf (dump_file, "\n");
- }
- continue;
- }
- }
- else
- val = v->value;
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Modifying stmt:\n ");
- print_gimple_stmt (dump_file, stmt, 0, 0);
- }
- gimple_assign_set_rhs_from_tree (&gsi, val);
- update_stmt (stmt);
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "into:\n ");
- print_gimple_stmt (dump_file, stmt, 0, 0);
- fprintf (dump_file, "\n");
- }
-
- something_changed = true;
- if (maybe_clean_eh_stmt (stmt)
- && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
- cfg_changed = true;
- }
+ descriptors.safe_grow_cleared (param_count);
+ ipa_populate_param_decls (node, descriptors);
+ calculate_dominance_info (CDI_DOMINATORS);
+ ipcp_modif_dom_walker (&fbi, descriptors, aggval, &something_changed,
+ &cfg_changed).walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ int i;
+ struct ipa_bb_info *bi;
+ FOR_EACH_VEC_ELT (fbi.bb_infos, i, bi)
+ free_ipa_bb_info (bi);
+ fbi.bb_infos.release ();
+ free_dominance_info (CDI_DOMINATORS);
(*ipa_node_agg_replacements)[node->uid] = NULL;
- free_parms_ainfo (parms_ainfo, param_count);
descriptors.release ();
if (!something_changed)
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index 8fdd92c14ef..cb23698df63 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -371,8 +371,9 @@ struct ipa_node_params
/* If this node is an ipa-cp clone, these are the known values that describe
what it has been specialized for. */
vec<tree> known_vals;
- /* Whether the param uses analysis has already been performed. */
- unsigned uses_analysis_done : 1;
+ /* Whether the param uses analysis and jump function computation has already
+ been performed. */
+ unsigned analysis_done : 1;
/* Whether the function is enqueued in ipa-cp propagation stack. */
unsigned node_enqueued : 1;
/* Whether we should create a specialized version based on values that are
diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
new file mode 100644
index 00000000000..dc22b2e981e
--- /dev/null
+++ b/gcc/ipa-visibility.c
@@ -0,0 +1,816 @@
+/* IPA visibility pass
+ Copyright (C) 2003-2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* This file implements two related passes:
+
+ - pass_data_ipa_function_and_variable_visibility run just after
+ symbol table, references and callgraph are built
+
+ - pass_data_ipa_function_and_variable_visibility run as first
+ proper IPA pass (that is after early optimization, or, (with LTO)
+ as a first pass done at link-time.
+
+ Purpose of both passes is to set correctly visibility properties
+ of all symbols. This includes:
+
+ - Symbol privatization:
+
+ Some symbols that are declared public by frontend may be
+ turned local (either by -fwhole-program flag, by linker plugin feedback
+ or by other reasons)
+
+ - Discovery of local functions:
+
+ A local function is one whose calls can occur only in the current
+ compilation unit and all its calls are explicit, so we can change
+ its calling convention. We simply mark all static functions whose
+ address is not taken as local.
+
+ externally_visible flag is set for symbols that can not be privatized.
+ For privatized symbols we clear TREE_PUBLIC flag and dismantle comdat
+ group.
+
+ - Dismantling of comdat groups:
+
+ Comdat group represent a section that may be replaced by linker by
+ a different copy of the same section from other unit.
+ If we have resolution information (from linker plugin) and we know that
+ a given comdat gorup is prevailing, we can dismantle it and turn symbols
+ into normal symbols. If the resolution information says that the
+ section was previaled by copy from non-LTO code, we can also dismantle
+ it and turn all symbols into external.
+
+ - Local aliases:
+
+ Some symbols can be interposed by dynamic linker. Refering to these
+ symbols is expensive, since it needs to be overwritable by the dynamic
+ linker. In some cases we know that the interposition does not change
+ semantic and we can always refer to a local copy (as in the case of
+ inline function). In this case we produce a local alias and redirect
+ calls to it.
+
+ TODO: This should be done for references, too.
+
+ - Removal of static ocnstructors and destructors that have no side effects.
+
+ - Regularization of several oddities introduced by frontends that may
+ be impractical later in the optimization queue. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "cgraph.h"
+#include "tree-pass.h"
+#include "pointer-set.h"
+#include "calls.h"
+#include "gimple-expr.h"
+
+/* Return true when NODE can not be local. Worker for cgraph_local_node_p. */
+
+static bool
+cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
+{
+ /* FIXME: Aliases can be local, but i386 gets thunks wrong then. */
+ return !(cgraph_only_called_directly_or_aliased_p (node)
+ && !ipa_ref_has_aliases_p (&node->ref_list)
+ && node->definition
+ && !DECL_EXTERNAL (node->decl)
+ && !node->externally_visible
+ && !node->used_from_other_partition
+ && !node->in_other_partition);
+}
+
+/* Return true when function can be marked local. */
+
+bool
+cgraph_local_node_p (struct cgraph_node *node)
+{
+ struct cgraph_node *n = cgraph_function_or_thunk_node (node, NULL);
+
+ /* FIXME: thunks can be considered local, but we need prevent i386
+ from attempting to change calling convention of them. */
+ if (n->thunk.thunk_p)
+ return false;
+ return !cgraph_for_node_and_aliases (n,
+ cgraph_non_local_node_p_1, NULL, true);
+
+}
+
+/* Return true when there is a reference to node and it is not vtable. */
+static bool
+address_taken_from_non_vtable_p (symtab_node *node)
+{
+ int i;
+ struct ipa_ref *ref;
+ for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
+ i, ref); i++)
+ if (ref->use == IPA_REF_ADDR)
+ {
+ varpool_node *node;
+ if (is_a <cgraph_node *> (ref->referring))
+ return true;
+ node = ipa_ref_referring_varpool_node (ref);
+ if (!DECL_VIRTUAL_P (node->decl))
+ return true;
+ }
+ return false;
+}
+
+/* A helper for comdat_can_be_unshared_p. */
+
+static bool
+comdat_can_be_unshared_p_1 (symtab_node *node)
+{
+ if (!node->externally_visible)
+ return true;
+ /* When address is taken, we don't know if equality comparison won't
+ break eventually. Exception are virutal functions, C++
+ constructors/destructors and vtables, where this is not possible by
+ language standard. */
+ if (!DECL_VIRTUAL_P (node->decl)
+ && (TREE_CODE (node->decl) != FUNCTION_DECL
+ || (!DECL_CXX_CONSTRUCTOR_P (node->decl)
+ && !DECL_CXX_DESTRUCTOR_P (node->decl)))
+ && address_taken_from_non_vtable_p (node))
+ return false;
+
+ /* If the symbol is used in some weird way, better to not touch it. */
+ if (node->force_output)
+ return false;
+
+ /* Explicit instantiations needs to be output when possibly
+ used externally. */
+ if (node->forced_by_abi
+ && TREE_PUBLIC (node->decl)
+ && (node->resolution != LDPR_PREVAILING_DEF_IRONLY
+ && !flag_whole_program))
+ return false;
+
+ /* Non-readonly and volatile variables can not be duplicated. */
+ if (is_a <varpool_node *> (node)
+ && (!TREE_READONLY (node->decl)
+ || TREE_THIS_VOLATILE (node->decl)))
+ return false;
+ return true;
+}
+
+/* COMDAT functions must be shared only if they have address taken,
+ otherwise we can produce our own private implementation with
+ -fwhole-program.
+ Return true when turning COMDAT functoin static can not lead to wrong
+ code when the resulting object links with a library defining same COMDAT.
+
+ Virtual functions do have their addresses taken from the vtables,
+ but in C++ there is no way to compare their addresses for equality. */
+
+static bool
+comdat_can_be_unshared_p (symtab_node *node)
+{
+ if (!comdat_can_be_unshared_p_1 (node))
+ return false;
+ if (node->same_comdat_group)
+ {
+ symtab_node *next;
+
+ /* If more than one function is in the same COMDAT group, it must
+ be shared even if just one function in the comdat group has
+ address taken. */
+ for (next = node->same_comdat_group;
+ next != node; next = next->same_comdat_group)
+ if (!comdat_can_be_unshared_p_1 (next))
+ return false;
+ }
+ return true;
+}
+
+/* Return true when function NODE should be considered externally visible. */
+
+static bool
+cgraph_externally_visible_p (struct cgraph_node *node,
+ bool whole_program)
+{
+ if (!node->definition)
+ return false;
+ if (!TREE_PUBLIC (node->decl)
+ || DECL_EXTERNAL (node->decl))
+ return false;
+
+ /* Do not try to localize built-in functions yet. One of problems is that we
+ end up mangling their asm for WHOPR that makes it impossible to call them
+ using the implicit built-in declarations anymore. Similarly this enables
+ us to remove them as unreachable before actual calls may appear during
+ expansion or folding. */
+ if (DECL_BUILT_IN (node->decl))
+ return true;
+
+ /* If linker counts on us, we must preserve the function. */
+ if (symtab_used_from_object_file_p (node))
+ return true;
+ if (DECL_PRESERVE_P (node->decl))
+ return true;
+ if (lookup_attribute ("externally_visible",
+ DECL_ATTRIBUTES (node->decl)))
+ return true;
+ if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+ && lookup_attribute ("dllexport",
+ DECL_ATTRIBUTES (node->decl)))
+ return true;
+ if (node->resolution == LDPR_PREVAILING_DEF_IRONLY)
+ return false;
+ /* When doing LTO or whole program, we can bring COMDAT functoins static.
+ This improves code quality and we know we will duplicate them at most twice
+ (in the case that we are not using plugin and link with object file
+ implementing same COMDAT) */
+ if ((in_lto_p || whole_program)
+ && DECL_COMDAT (node->decl)
+ && comdat_can_be_unshared_p (node))
+ return false;
+
+ /* When doing link time optimizations, hidden symbols become local. */
+ if (in_lto_p
+ && (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
+ || DECL_VISIBILITY (node->decl) == VISIBILITY_INTERNAL)
+ /* Be sure that node is defined in IR file, not in other object
+ file. In that case we don't set used_from_other_object_file. */
+ && node->definition)
+ ;
+ else if (!whole_program)
+ return true;
+
+ if (MAIN_NAME_P (DECL_NAME (node->decl)))
+ return true;
+
+ return false;
+}
+
+/* Return true when variable VNODE should be considered externally visible. */
+
+bool
+varpool_externally_visible_p (varpool_node *vnode)
+{
+ if (DECL_EXTERNAL (vnode->decl))
+ return true;
+
+ if (!TREE_PUBLIC (vnode->decl))
+ return false;
+
+ /* If linker counts on us, we must preserve the function. */
+ if (symtab_used_from_object_file_p (vnode))
+ return true;
+
+ if (DECL_HARD_REGISTER (vnode->decl))
+ return true;
+ if (DECL_PRESERVE_P (vnode->decl))
+ return true;
+ if (lookup_attribute ("externally_visible",
+ DECL_ATTRIBUTES (vnode->decl)))
+ return true;
+ if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+ && lookup_attribute ("dllexport",
+ DECL_ATTRIBUTES (vnode->decl)))
+ return true;
+
+ /* See if we have linker information about symbol not being used or
+ if we need to make guess based on the declaration.
+
+ Even if the linker clams the symbol is unused, never bring internal
+ symbols that are declared by user as used or externally visible.
+ This is needed for i.e. references from asm statements. */
+ if (symtab_used_from_object_file_p (vnode))
+ return true;
+ if (vnode->resolution == LDPR_PREVAILING_DEF_IRONLY)
+ return false;
+
+ /* As a special case, the COMDAT virtual tables can be unshared.
+ In LTO mode turn vtables into static variables. The variable is readonly,
+ so this does not enable more optimization, but referring static var
+ is faster for dynamic linking. Also this match logic hidding vtables
+ from LTO symbol tables. */
+ if ((in_lto_p || flag_whole_program)
+ && DECL_COMDAT (vnode->decl)
+ && comdat_can_be_unshared_p (vnode))
+ return false;
+
+ /* When doing link time optimizations, hidden symbols become local. */
+ if (in_lto_p
+ && (DECL_VISIBILITY (vnode->decl) == VISIBILITY_HIDDEN
+ || DECL_VISIBILITY (vnode->decl) == VISIBILITY_INTERNAL)
+ /* Be sure that node is defined in IR file, not in other object
+ file. In that case we don't set used_from_other_object_file. */
+ && vnode->definition)
+ ;
+ else if (!flag_whole_program)
+ return true;
+
+ /* Do not attempt to privatize COMDATS by default.
+ This would break linking with C++ libraries sharing
+ inline definitions.
+
+ FIXME: We can do so for readonly vars with no address taken and
+ possibly also for vtables since no direct pointer comparsion is done.
+ It might be interesting to do so to reduce linking overhead. */
+ if (DECL_COMDAT (vnode->decl) || DECL_WEAK (vnode->decl))
+ return true;
+ return false;
+}
+
+/* Return true if reference to NODE can be replaced by a local alias.
+ Local aliases save dynamic linking overhead and enable more optimizations.
+ */
+
+bool
+can_replace_by_local_alias (symtab_node *node)
+{
+ return (symtab_node_availability (node) > AVAIL_OVERWRITABLE
+ && !symtab_can_be_discarded (node));
+}
+
+/* Return true if we can replace refernece to NODE by local alias
+ within a virtual table. Generally we can replace function pointers
+ and virtual table pointers. */
+
+bool
+can_replace_by_local_alias_in_vtable (symtab_node *node)
+{
+ if (is_a <varpool_node *> (node)
+ && !DECL_VIRTUAL_P (node->decl))
+ return false;
+ return can_replace_by_local_alias (node);
+}
+
+/* walk_tree callback that rewrites initializer references. */
+
+static tree
+update_vtable_references (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
+{
+ if (TREE_CODE (*tp) == VAR_DECL
+ || TREE_CODE (*tp) == FUNCTION_DECL)
+ {
+ if (can_replace_by_local_alias_in_vtable (symtab_get_node (*tp)))
+ *tp = symtab_nonoverwritable_alias (symtab_get_node (*tp))->decl;
+ *walk_subtrees = 0;
+ }
+ else if (IS_TYPE_OR_DECL_P (*tp))
+ *walk_subtrees = 0;
+ return NULL;
+}
+
+/* In LTO we can remove COMDAT groups and weak symbols.
+ Either turn them into normal symbols or external symbol depending on
+ resolution info. */
+
+static void
+update_visibility_by_resolution_info (symtab_node * node)
+{
+ bool define;
+
+ if (!node->externally_visible
+ || (!DECL_WEAK (node->decl) && !DECL_ONE_ONLY (node->decl))
+ || node->resolution == LDPR_UNKNOWN)
+ return;
+
+ define = (node->resolution == LDPR_PREVAILING_DEF_IRONLY
+ || node->resolution == LDPR_PREVAILING_DEF
+ || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
+
+ /* The linker decisions ought to agree in the whole group. */
+ if (node->same_comdat_group)
+ for (symtab_node *next = node->same_comdat_group;
+ next != node; next = next->same_comdat_group)
+ gcc_assert (!node->externally_visible
+ || define == (next->resolution == LDPR_PREVAILING_DEF_IRONLY
+ || next->resolution == LDPR_PREVAILING_DEF
+ || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP));
+
+ if (node->same_comdat_group)
+ for (symtab_node *next = node->same_comdat_group;
+ next != node; next = next->same_comdat_group)
+ {
+ next->set_comdat_group (NULL);
+ DECL_WEAK (next->decl) = false;
+ if (next->externally_visible
+ && !define)
+ DECL_EXTERNAL (next->decl) = true;
+ }
+ node->set_comdat_group (NULL);
+ DECL_WEAK (node->decl) = false;
+ if (!define)
+ DECL_EXTERNAL (node->decl) = true;
+ symtab_dissolve_same_comdat_group_list (node);
+}
+
+/* Decide on visibility of all symbols. */
+
+static unsigned int
+function_and_variable_visibility (bool whole_program)
+{
+ struct cgraph_node *node;
+ varpool_node *vnode;
+
+ /* All aliases should be procssed at this point. */
+ gcc_checking_assert (!alias_pairs || !alias_pairs->length ());
+
+ FOR_EACH_FUNCTION (node)
+ {
+ int flags = flags_from_decl_or_type (node->decl);
+
+ /* Optimize away PURE and CONST constructors and destructors. */
+ if (optimize
+ && (flags & (ECF_CONST | ECF_PURE))
+ && !(flags & ECF_LOOPING_CONST_OR_PURE))
+ {
+ DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
+ DECL_STATIC_DESTRUCTOR (node->decl) = 0;
+ }
+
+ /* Frontends and alias code marks nodes as needed before parsing is finished.
+ We may end up marking as node external nodes where this flag is meaningless
+ strip it. */
+ if (DECL_EXTERNAL (node->decl) || !node->definition)
+ {
+ node->force_output = 0;
+ node->forced_by_abi = 0;
+ }
+
+ /* C++ FE on lack of COMDAT support create local COMDAT functions
+ (that ought to be shared but can not due to object format
+ limitations). It is necessary to keep the flag to make rest of C++ FE
+ happy. Clear the flag here to avoid confusion in middle-end. */
+ if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl))
+ DECL_COMDAT (node->decl) = 0;
+
+ /* For external decls stop tracking same_comdat_group. It doesn't matter
+ what comdat group they are in when they won't be emitted in this TU. */
+ if (node->same_comdat_group && DECL_EXTERNAL (node->decl))
+ {
+#ifdef ENABLE_CHECKING
+ symtab_node *n;
+
+ for (n = node->same_comdat_group;
+ n != node;
+ n = n->same_comdat_group)
+ /* If at least one of same comdat group functions is external,
+ all of them have to be, otherwise it is a front-end bug. */
+ gcc_assert (DECL_EXTERNAL (n->decl));
+#endif
+ symtab_dissolve_same_comdat_group_list (node);
+ }
+ gcc_assert ((!DECL_WEAK (node->decl)
+ && !DECL_COMDAT (node->decl))
+ || TREE_PUBLIC (node->decl)
+ || node->weakref
+ || DECL_EXTERNAL (node->decl));
+ if (cgraph_externally_visible_p (node, whole_program))
+ {
+ gcc_assert (!node->global.inlined_to);
+ node->externally_visible = true;
+ }
+ else
+ {
+ node->externally_visible = false;
+ node->forced_by_abi = false;
+ }
+ if (!node->externally_visible
+ && node->definition && !node->weakref
+ && !DECL_EXTERNAL (node->decl))
+ {
+ gcc_assert (whole_program || in_lto_p
+ || !TREE_PUBLIC (node->decl));
+ node->unique_name = ((node->resolution == LDPR_PREVAILING_DEF_IRONLY
+ || node->unique_name
+ || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
+ && TREE_PUBLIC (node->decl));
+ node->resolution = LDPR_PREVAILING_DEF_IRONLY;
+ if (node->same_comdat_group && TREE_PUBLIC (node->decl))
+ {
+ symtab_node *next = node;
+
+ /* Set all members of comdat group local. */
+ if (node->same_comdat_group)
+ for (next = node->same_comdat_group;
+ next != node;
+ next = next->same_comdat_group)
+ {
+ next->set_comdat_group (NULL);
+ symtab_make_decl_local (next->decl);
+ next->unique_name = ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
+ || next->unique_name
+ || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
+ && TREE_PUBLIC (next->decl));
+ }
+ /* cgraph_externally_visible_p has already checked all other nodes
+ in the group and they will all be made local. We need to
+ dissolve the group at once so that the predicate does not
+ segfault though. */
+ symtab_dissolve_same_comdat_group_list (node);
+ }
+ if (TREE_PUBLIC (node->decl))
+ node->set_comdat_group (NULL);
+ symtab_make_decl_local (node->decl);
+ }
+
+ if (node->thunk.thunk_p
+ && TREE_PUBLIC (node->decl))
+ {
+ struct cgraph_node *decl_node = node;
+
+ decl_node = cgraph_function_node (decl_node->callees->callee, NULL);
+
+ /* Thunks have the same visibility as function they are attached to.
+ Make sure the C++ front end set this up properly. */
+ if (DECL_ONE_ONLY (decl_node->decl))
+ {
+ gcc_checking_assert (DECL_COMDAT (node->decl)
+ == DECL_COMDAT (decl_node->decl));
+ gcc_checking_assert (symtab_in_same_comdat_p (node, decl_node));
+ gcc_checking_assert (node->same_comdat_group);
+ }
+ node->forced_by_abi = decl_node->forced_by_abi;
+ if (DECL_EXTERNAL (decl_node->decl))
+ DECL_EXTERNAL (node->decl) = 1;
+ }
+
+ update_visibility_by_resolution_info (node);
+ }
+ FOR_EACH_DEFINED_FUNCTION (node)
+ {
+ node->local.local |= cgraph_local_node_p (node);
+
+ /* If we know that function can not be overwritten by a different semantics
+ and moreover its section can not be discarded, replace all direct calls
+ by calls to an nonoverwritable alias. This make dynamic linking
+ cheaper and enable more optimization.
+
+ TODO: We can also update virtual tables. */
+ if (node->callers && can_replace_by_local_alias (node))
+ {
+ struct cgraph_node *alias = cgraph (symtab_nonoverwritable_alias (node));
+
+ if (alias && alias != node)
+ {
+ while (node->callers)
+ {
+ struct cgraph_edge *e = node->callers;
+
+ cgraph_redirect_edge_callee (e, alias);
+ if (gimple_has_body_p (e->caller->decl))
+ {
+ push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
+ cgraph_redirect_edge_call_stmt_to_callee (e);
+ pop_cfun ();
+ }
+ }
+ }
+ }
+ }
+ FOR_EACH_VARIABLE (vnode)
+ {
+ /* weak flag makes no sense on local variables. */
+ gcc_assert (!DECL_WEAK (vnode->decl)
+ || vnode->weakref
+ || TREE_PUBLIC (vnode->decl)
+ || DECL_EXTERNAL (vnode->decl));
+ /* In several cases declarations can not be common:
+
+ - when declaration has initializer
+ - when it is in weak
+ - when it has specific section
+ - when it resides in non-generic address space.
+ - if declaration is local, it will get into .local common section
+ so common flag is not needed. Frontends still produce these in
+ certain cases, such as for:
+
+ static int a __attribute__ ((common))
+
+ Canonicalize things here and clear the redundant flag. */
+ if (DECL_COMMON (vnode->decl)
+ && (!(TREE_PUBLIC (vnode->decl)
+ || DECL_EXTERNAL (vnode->decl))
+ || (DECL_INITIAL (vnode->decl)
+ && DECL_INITIAL (vnode->decl) != error_mark_node)
+ || DECL_WEAK (vnode->decl)
+ || DECL_SECTION_NAME (vnode->decl) != NULL
+ || ! (ADDR_SPACE_GENERIC_P
+ (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
+ DECL_COMMON (vnode->decl) = 0;
+ }
+ FOR_EACH_DEFINED_VARIABLE (vnode)
+ {
+ if (!vnode->definition)
+ continue;
+ if (varpool_externally_visible_p (vnode))
+ vnode->externally_visible = true;
+ else
+ {
+ vnode->externally_visible = false;
+ vnode->forced_by_abi = false;
+ }
+ if (!vnode->externally_visible
+ && !vnode->weakref)
+ {
+ gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
+ vnode->unique_name = ((vnode->resolution == LDPR_PREVAILING_DEF_IRONLY
+ || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
+ && TREE_PUBLIC (vnode->decl));
+ if (vnode->same_comdat_group && TREE_PUBLIC (vnode->decl))
+ {
+ symtab_node *next = vnode;
+
+ /* Set all members of comdat group local. */
+ if (vnode->same_comdat_group)
+ for (next = vnode->same_comdat_group;
+ next != vnode;
+ next = next->same_comdat_group)
+ {
+ next->set_comdat_group (NULL);
+ symtab_make_decl_local (next->decl);
+ next->unique_name = ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
+ || next->unique_name
+ || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
+ && TREE_PUBLIC (next->decl));
+ }
+ symtab_dissolve_same_comdat_group_list (vnode);
+ }
+ if (TREE_PUBLIC (vnode->decl))
+ vnode->set_comdat_group (NULL);
+ symtab_make_decl_local (vnode->decl);
+ vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
+ }
+ update_visibility_by_resolution_info (vnode);
+
+ /* Update virutal tables to point to local aliases where possible. */
+ if (DECL_VIRTUAL_P (vnode->decl)
+ && !DECL_EXTERNAL (vnode->decl))
+ {
+ int i;
+ struct ipa_ref *ref;
+ bool found = false;
+
+ /* See if there is something to update. */
+ for (i = 0; ipa_ref_list_referring_iterate (&vnode->ref_list,
+ i, ref); i++)
+ if (ref->use == IPA_REF_ADDR
+ && can_replace_by_local_alias_in_vtable (ref->referred))
+ {
+ found = true;
+ break;
+ }
+ if (found)
+ {
+ struct pointer_set_t *visited_nodes = pointer_set_create ();
+ walk_tree (&DECL_INITIAL (vnode->decl),
+ update_vtable_references, NULL, visited_nodes);
+ pointer_set_destroy (visited_nodes);
+ ipa_remove_all_references (&vnode->ref_list);
+ record_references_in_initializer (vnode->decl, false);
+ }
+ }
+ }
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "\nMarking local functions:");
+ FOR_EACH_DEFINED_FUNCTION (node)
+ if (node->local.local)
+ fprintf (dump_file, " %s", node->name ());
+ fprintf (dump_file, "\n\n");
+ fprintf (dump_file, "\nMarking externally visible functions:");
+ FOR_EACH_DEFINED_FUNCTION (node)
+ if (node->externally_visible)
+ fprintf (dump_file, " %s", node->name ());
+ fprintf (dump_file, "\n\n");
+ fprintf (dump_file, "\nMarking externally visible variables:");
+ FOR_EACH_DEFINED_VARIABLE (vnode)
+ if (vnode->externally_visible)
+ fprintf (dump_file, " %s", vnode->name ());
+ fprintf (dump_file, "\n\n");
+ }
+ cgraph_function_flags_ready = true;
+ return 0;
+}
+
+/* Local function pass handling visibilities. This happens before LTO streaming
+ so in particular -fwhole-program should be ignored at this level. */
+
+namespace {
+
+const pass_data pass_data_ipa_function_and_variable_visibility =
+{
+ SIMPLE_IPA_PASS, /* type */
+ "visibility", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ true, /* has_execute */
+ TV_CGRAPHOPT, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
+};
+
+/* Bring functions local at LTO time with -fwhole-program. */
+
+static unsigned int
+whole_program_function_and_variable_visibility (void)
+{
+ function_and_variable_visibility (flag_whole_program);
+ if (optimize)
+ ipa_discover_readonly_nonaddressable_vars ();
+ return 0;
+}
+
+} // anon namespace
+
+namespace {
+
+const pass_data pass_data_ipa_whole_program_visibility =
+{
+ IPA_PASS, /* type */
+ "whole-program", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ true, /* has_execute */
+ TV_CGRAPHOPT, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
+};
+
+class pass_ipa_whole_program_visibility : public ipa_opt_pass_d
+{
+public:
+ pass_ipa_whole_program_visibility (gcc::context *ctxt)
+ : ipa_opt_pass_d (pass_data_ipa_whole_program_visibility, ctxt,
+ NULL, /* generate_summary */
+ NULL, /* write_summary */
+ NULL, /* read_summary */
+ NULL, /* write_optimization_summary */
+ NULL, /* read_optimization_summary */
+ NULL, /* stmt_fixup */
+ 0, /* function_transform_todo_flags_start */
+ NULL, /* function_transform */
+ NULL) /* variable_transform */
+ {}
+
+ /* opt_pass methods: */
+
+ virtual bool gate (function *)
+ {
+ /* Do not re-run on ltrans stage. */
+ return !flag_ltrans;
+ }
+ virtual unsigned int execute (function *)
+ {
+ return whole_program_function_and_variable_visibility ();
+ }
+
+}; // class pass_ipa_whole_program_visibility
+
+} // anon namespace
+
+ipa_opt_pass_d *
+make_pass_ipa_whole_program_visibility (gcc::context *ctxt)
+{
+ return new pass_ipa_whole_program_visibility (ctxt);
+}
+
+class pass_ipa_function_and_variable_visibility : public simple_ipa_opt_pass
+{
+public:
+ pass_ipa_function_and_variable_visibility (gcc::context *ctxt)
+ : simple_ipa_opt_pass (pass_data_ipa_function_and_variable_visibility,
+ ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual unsigned int execute (function *)
+ {
+ return function_and_variable_visibility (flag_whole_program && !flag_lto);
+ }
+
+}; // class pass_ipa_function_and_variable_visibility
+
+simple_ipa_opt_pass *
+make_pass_ipa_function_and_variable_visibility (gcc::context *ctxt)
+{
+ return new pass_ipa_function_and_variable_visibility (ctxt);
+}
diff --git a/gcc/ipa.c b/gcc/ipa.c
index a14f0241820..5850d281829 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -37,37 +37,11 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "profile.h"
#include "params.h"
+#include "internal-fn.h"
+#include "tree-ssa-alias.h"
+#include "gimple.h"
+#include "dbgcnt.h"
-/* Return true when NODE can not be local. Worker for cgraph_local_node_p. */
-
-static bool
-cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
-{
- /* FIXME: Aliases can be local, but i386 gets thunks wrong then. */
- return !(cgraph_only_called_directly_or_aliased_p (node)
- && !ipa_ref_has_aliases_p (&node->ref_list)
- && node->definition
- && !DECL_EXTERNAL (node->decl)
- && !node->externally_visible
- && !node->used_from_other_partition
- && !node->in_other_partition);
-}
-
-/* Return true when function can be marked local. */
-
-static bool
-cgraph_local_node_p (struct cgraph_node *node)
-{
- struct cgraph_node *n = cgraph_function_or_thunk_node (node, NULL);
-
- /* FIXME: thunks can be considered local, but we need prevent i386
- from attempting to change calling convention of them. */
- if (n->thunk.thunk_p)
- return false;
- return !cgraph_for_node_and_aliases (n,
- cgraph_non_local_node_p_1, NULL, true);
-
-}
/* Return true when NODE has ADDR reference. */
@@ -213,7 +187,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
make the edge direct. */
if (final)
{
- if (targets.length () <= 1)
+ if (targets.length () <= 1 && dbg_cnt (devirt))
{
cgraph_node *target, *node = edge->caller;
if (targets.length () == 1)
@@ -222,12 +196,15 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
target = cgraph_get_create_node
(builtin_decl_implicit (BUILT_IN_UNREACHABLE));
- if (dump_file)
- fprintf (dump_file,
- "Devirtualizing call in %s/%i to %s/%i\n",
- edge->caller->name (),
- edge->caller->order,
- target->name (), target->order);
+ if (dump_enabled_p ())
+ {
+ location_t locus = gimple_location (edge->call_stmt);
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, locus,
+ "devirtualizing call in %s/%i to %s/%i\n",
+ edge->caller->name (), edge->caller->order,
+ target->name (),
+ target->order);
+ }
edge = cgraph_make_edge_direct (edge, target);
if (inline_summary_vec)
inline_update_overall_summary (node);
@@ -517,6 +494,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
if (!node->in_other_partition)
node->local.local = false;
cgraph_node_remove_callees (node);
+ symtab_remove_from_same_comdat_group (node);
ipa_remove_all_references (&node->ref_list);
changed = true;
}
@@ -572,6 +550,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
vnode->analyzed = false;
vnode->aux = NULL;
+ symtab_remove_from_same_comdat_group (vnode);
+
/* Keep body if it may be useful for constant folding. */
if ((init = ctor_for_folding (vnode->decl)) == error_mark_node)
varpool_remove_initializer (vnode);
@@ -624,613 +604,131 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
return changed;
}
-/* Discover variables that have no longer address taken or that are read only
- and update their flags.
-
- FIXME: This can not be done in between gimplify and omp_expand since
- readonly flag plays role on what is shared and what is not. Currently we do
- this transformation as part of whole program visibility and re-do at
- ipa-reference pass (to take into account clonning), but it would
- make sense to do it before early optimizations. */
+/* Process references to VNODE and set flags WRITTEN, ADDRESS_TAKEN, READ
+ as needed, also clear EXPLICIT_REFS if the references to given variable
+ do not need to be explicit. */
void
-ipa_discover_readonly_nonaddressable_vars (void)
-{
- varpool_node *vnode;
- if (dump_file)
- fprintf (dump_file, "Clearing variable flags:");
- FOR_EACH_VARIABLE (vnode)
- if (vnode->definition && varpool_all_refs_explicit_p (vnode)
- && (TREE_ADDRESSABLE (vnode->decl)
- || !TREE_READONLY (vnode->decl)))
- {
- bool written = false;
- bool address_taken = false;
- int i;
- struct ipa_ref *ref;
- for (i = 0; ipa_ref_list_referring_iterate (&vnode->ref_list,
- i, ref)
- && (!written || !address_taken); i++)
- switch (ref->use)
- {
- case IPA_REF_ADDR:
- address_taken = true;
- break;
- case IPA_REF_LOAD:
- break;
- case IPA_REF_STORE:
- written = true;
- break;
- }
- if (TREE_ADDRESSABLE (vnode->decl) && !address_taken)
- {
- if (dump_file)
- fprintf (dump_file, " %s (addressable)", vnode->name ());
- TREE_ADDRESSABLE (vnode->decl) = 0;
- }
- if (!TREE_READONLY (vnode->decl) && !address_taken && !written
- /* Making variable in explicit section readonly can cause section
- type conflict.
- See e.g. gcc.c-torture/compile/pr23237.c */
- && DECL_SECTION_NAME (vnode->decl) == NULL)
- {
- if (dump_file)
- fprintf (dump_file, " %s (read-only)", vnode->name ());
- TREE_READONLY (vnode->decl) = 1;
- }
- }
- if (dump_file)
- fprintf (dump_file, "\n");
-}
-
-/* Return true when there is a reference to node and it is not vtable. */
-static bool
-address_taken_from_non_vtable_p (symtab_node *node)
+process_references (varpool_node *vnode,
+ bool *written, bool *address_taken,
+ bool *read, bool *explicit_refs)
{
int i;
struct ipa_ref *ref;
- for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
- i, ref); i++)
- if (ref->use == IPA_REF_ADDR)
+
+ if (!varpool_all_refs_explicit_p (vnode)
+ || TREE_THIS_VOLATILE (vnode->decl))
+ *explicit_refs = false;
+
+ for (i = 0; ipa_ref_list_referring_iterate (&vnode->ref_list,
+ i, ref)
+ && *explicit_refs && (!*written || !*address_taken || !*read); i++)
+ switch (ref->use)
{
- varpool_node *node;
- if (is_a <cgraph_node *> (ref->referring))
- return true;
- node = ipa_ref_referring_varpool_node (ref);
- if (!DECL_VIRTUAL_P (node->decl))
- return true;
+ case IPA_REF_ADDR:
+ *address_taken = true;
+ break;
+ case IPA_REF_LOAD:
+ *read = true;
+ break;
+ case IPA_REF_STORE:
+ *written = true;
+ break;
+ case IPA_REF_ALIAS:
+ process_references (varpool (ref->referring), written, address_taken,
+ read, explicit_refs);
+ break;
}
- return false;
}
-/* A helper for comdat_can_be_unshared_p. */
+/* Set TREE_READONLY bit. */
-static bool
-comdat_can_be_unshared_p_1 (symtab_node *node)
+bool
+set_readonly_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED)
{
- /* When address is taken, we don't know if equality comparison won't
- break eventually. Exception are virutal functions, C++
- constructors/destructors and vtables, where this is not possible by
- language standard. */
- if (!DECL_VIRTUAL_P (node->decl)
- && (TREE_CODE (node->decl) != FUNCTION_DECL
- || (!DECL_CXX_CONSTRUCTOR_P (node->decl)
- && !DECL_CXX_DESTRUCTOR_P (node->decl)))
- && address_taken_from_non_vtable_p (node))
- return false;
-
- /* If the symbol is used in some weird way, better to not touch it. */
- if (node->force_output)
- return false;
-
- /* Explicit instantiations needs to be output when possibly
- used externally. */
- if (node->forced_by_abi
- && TREE_PUBLIC (node->decl)
- && (node->resolution != LDPR_PREVAILING_DEF_IRONLY
- && !flag_whole_program))
- return false;
-
- /* Non-readonly and volatile variables can not be duplicated. */
- if (is_a <varpool_node *> (node)
- && (!TREE_READONLY (node->decl)
- || TREE_THIS_VOLATILE (node->decl)))
- return false;
- return true;
+ TREE_READONLY (vnode->decl) = true;
+ return false;
}
-/* COMDAT functions must be shared only if they have address taken,
- otherwise we can produce our own private implementation with
- -fwhole-program.
- Return true when turning COMDAT functoin static can not lead to wrong
- code when the resulting object links with a library defining same COMDAT.
+/* Set writeonly bit and clear the initalizer, since it will not be needed. */
- Virtual functions do have their addresses taken from the vtables,
- but in C++ there is no way to compare their addresses for equality. */
-
-static bool
-comdat_can_be_unshared_p (symtab_node *node)
+bool
+set_writeonly_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED)
{
- if (!comdat_can_be_unshared_p_1 (node))
- return false;
- if (node->same_comdat_group)
+ vnode->writeonly = true;
+ if (optimize)
{
- symtab_node *next;
-
- /* If more than one function is in the same COMDAT group, it must
- be shared even if just one function in the comdat group has
- address taken. */
- for (next = node->same_comdat_group;
- next != node; next = next->same_comdat_group)
- if (!comdat_can_be_unshared_p_1 (next))
- return false;
+ DECL_INITIAL (vnode->decl) = NULL;
+ if (!vnode->alias)
+ ipa_remove_all_references (&vnode->ref_list);
}
- return true;
-}
-
-/* Return true when function NODE should be considered externally visible. */
-
-static bool
-cgraph_externally_visible_p (struct cgraph_node *node,
- bool whole_program)
-{
- if (!node->definition)
- return false;
- if (!TREE_PUBLIC (node->decl)
- || DECL_EXTERNAL (node->decl))
- return false;
-
- /* Do not try to localize built-in functions yet. One of problems is that we
- end up mangling their asm for WHOPR that makes it impossible to call them
- using the implicit built-in declarations anymore. Similarly this enables
- us to remove them as unreachable before actual calls may appear during
- expansion or folding. */
- if (DECL_BUILT_IN (node->decl))
- return true;
-
- /* If linker counts on us, we must preserve the function. */
- if (symtab_used_from_object_file_p (node))
- return true;
- if (DECL_PRESERVE_P (node->decl))
- return true;
- if (lookup_attribute ("externally_visible",
- DECL_ATTRIBUTES (node->decl)))
- return true;
- if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
- && lookup_attribute ("dllexport",
- DECL_ATTRIBUTES (node->decl)))
- return true;
- if (node->resolution == LDPR_PREVAILING_DEF_IRONLY)
- return false;
- /* When doing LTO or whole program, we can bring COMDAT functoins static.
- This improves code quality and we know we will duplicate them at most twice
- (in the case that we are not using plugin and link with object file
- implementing same COMDAT) */
- if ((in_lto_p || whole_program)
- && DECL_COMDAT (node->decl)
- && comdat_can_be_unshared_p (node))
- return false;
-
- /* When doing link time optimizations, hidden symbols become local. */
- if (in_lto_p
- && (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
- || DECL_VISIBILITY (node->decl) == VISIBILITY_INTERNAL)
- /* Be sure that node is defined in IR file, not in other object
- file. In that case we don't set used_from_other_object_file. */
- && node->definition)
- ;
- else if (!whole_program)
- return true;
-
- if (MAIN_NAME_P (DECL_NAME (node->decl)))
- return true;
-
return false;
}
-/* Return true when variable VNODE should be considered externally visible. */
+/* Clear addressale bit of VNODE. */
bool
-varpool_externally_visible_p (varpool_node *vnode)
+clear_addressable_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED)
{
- if (DECL_EXTERNAL (vnode->decl))
- return true;
-
- if (!TREE_PUBLIC (vnode->decl))
- return false;
-
- /* If linker counts on us, we must preserve the function. */
- if (symtab_used_from_object_file_p (vnode))
- return true;
-
- if (DECL_HARD_REGISTER (vnode->decl))
- return true;
- if (DECL_PRESERVE_P (vnode->decl))
- return true;
- if (lookup_attribute ("externally_visible",
- DECL_ATTRIBUTES (vnode->decl)))
- return true;
- if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
- && lookup_attribute ("dllexport",
- DECL_ATTRIBUTES (vnode->decl)))
- return true;
-
- /* See if we have linker information about symbol not being used or
- if we need to make guess based on the declaration.
-
- Even if the linker clams the symbol is unused, never bring internal
- symbols that are declared by user as used or externally visible.
- This is needed for i.e. references from asm statements. */
- if (symtab_used_from_object_file_p (vnode))
- return true;
- if (vnode->resolution == LDPR_PREVAILING_DEF_IRONLY)
- return false;
-
- /* As a special case, the COMDAT virtual tables can be unshared.
- In LTO mode turn vtables into static variables. The variable is readonly,
- so this does not enable more optimization, but referring static var
- is faster for dynamic linking. Also this match logic hidding vtables
- from LTO symbol tables. */
- if ((in_lto_p || flag_whole_program)
- && DECL_COMDAT (vnode->decl)
- && comdat_can_be_unshared_p (vnode))
- return false;
-
- /* When doing link time optimizations, hidden symbols become local. */
- if (in_lto_p
- && (DECL_VISIBILITY (vnode->decl) == VISIBILITY_HIDDEN
- || DECL_VISIBILITY (vnode->decl) == VISIBILITY_INTERNAL)
- /* Be sure that node is defined in IR file, not in other object
- file. In that case we don't set used_from_other_object_file. */
- && vnode->definition)
- ;
- else if (!flag_whole_program)
- return true;
-
- /* Do not attempt to privatize COMDATS by default.
- This would break linking with C++ libraries sharing
- inline definitions.
-
- FIXME: We can do so for readonly vars with no address taken and
- possibly also for vtables since no direct pointer comparsion is done.
- It might be interesting to do so to reduce linking overhead. */
- if (DECL_COMDAT (vnode->decl) || DECL_WEAK (vnode->decl))
- return true;
+ vnode->address_taken = false;
+ TREE_ADDRESSABLE (vnode->decl) = 0;
return false;
}
-/* Return true if reference to NODE can be replaced by a local alias.
- Local aliases save dynamic linking overhead and enable more optimizations.
- */
-
-bool
-can_replace_by_local_alias (symtab_node *node)
-{
- return (symtab_node_availability (node) > AVAIL_OVERWRITABLE
- && !symtab_can_be_discarded (node));
-}
-
-/* Mark visibility of all functions.
-
- A local function is one whose calls can occur only in the current
- compilation unit and all its calls are explicit, so we can change
- its calling convention. We simply mark all static functions whose
- address is not taken as local.
+/* Discover variables that have no longer address taken or that are read only
+ and update their flags.
- We also change the TREE_PUBLIC flag of all declarations that are public
- in language point of view but we want to overwrite this default
- via visibilities for the backend point of view. */
+ FIXME: This can not be done in between gimplify and omp_expand since
+ readonly flag plays role on what is shared and what is not. Currently we do
+ this transformation as part of whole program visibility and re-do at
+ ipa-reference pass (to take into account clonning), but it would
+ make sense to do it before early optimizations. */
-static unsigned int
-function_and_variable_visibility (bool whole_program)
+void
+ipa_discover_readonly_nonaddressable_vars (void)
{
- struct cgraph_node *node;
varpool_node *vnode;
-
- /* All aliases should be procssed at this point. */
- gcc_checking_assert (!alias_pairs || !alias_pairs->length ());
-
- FOR_EACH_FUNCTION (node)
- {
- int flags = flags_from_decl_or_type (node->decl);
-
- /* Optimize away PURE and CONST constructors and destructors. */
- if (optimize
- && (flags & (ECF_CONST | ECF_PURE))
- && !(flags & ECF_LOOPING_CONST_OR_PURE))
- {
- DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
- DECL_STATIC_DESTRUCTOR (node->decl) = 0;
- }
-
- /* Frontends and alias code marks nodes as needed before parsing is finished.
- We may end up marking as node external nodes where this flag is meaningless
- strip it. */
- if (DECL_EXTERNAL (node->decl) || !node->definition)
- {
- node->force_output = 0;
- node->forced_by_abi = 0;
- }
-
- /* C++ FE on lack of COMDAT support create local COMDAT functions
- (that ought to be shared but can not due to object format
- limitations). It is necessary to keep the flag to make rest of C++ FE
- happy. Clear the flag here to avoid confusion in middle-end. */
- if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl))
- DECL_COMDAT (node->decl) = 0;
-
- /* For external decls stop tracking same_comdat_group. It doesn't matter
- what comdat group they are in when they won't be emitted in this TU. */
- if (node->same_comdat_group && DECL_EXTERNAL (node->decl))
- {
-#ifdef ENABLE_CHECKING
- symtab_node *n;
-
- for (n = node->same_comdat_group;
- n != node;
- n = n->same_comdat_group)
- /* If at least one of same comdat group functions is external,
- all of them have to be, otherwise it is a front-end bug. */
- gcc_assert (DECL_EXTERNAL (n->decl));
-#endif
- symtab_dissolve_same_comdat_group_list (node);
- }
- gcc_assert ((!DECL_WEAK (node->decl)
- && !DECL_COMDAT (node->decl))
- || TREE_PUBLIC (node->decl)
- || node->weakref
- || DECL_EXTERNAL (node->decl));
- if (cgraph_externally_visible_p (node, whole_program))
- {
- gcc_assert (!node->global.inlined_to);
- node->externally_visible = true;
- }
- else
- {
- node->externally_visible = false;
- node->forced_by_abi = false;
- }
- if (!node->externally_visible
- && node->definition && !node->weakref
- && !DECL_EXTERNAL (node->decl))
- {
- gcc_assert (whole_program || in_lto_p
- || !TREE_PUBLIC (node->decl));
- node->unique_name = ((node->resolution == LDPR_PREVAILING_DEF_IRONLY
- || node->unique_name
- || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
- && TREE_PUBLIC (node->decl));
- node->resolution = LDPR_PREVAILING_DEF_IRONLY;
- if (node->same_comdat_group && TREE_PUBLIC (node->decl))
- {
- symtab_node *next = node;
-
- /* Set all members of comdat group local. */
- if (node->same_comdat_group)
- for (next = node->same_comdat_group;
- next != node;
- next = next->same_comdat_group)
- {
- symtab_make_decl_local (next->decl);
- next->unique_name = ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
- || next->unique_name
- || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
- && TREE_PUBLIC (next->decl));
- }
- /* cgraph_externally_visible_p has already checked all other nodes
- in the group and they will all be made local. We need to
- dissolve the group at once so that the predicate does not
- segfault though. */
- symtab_dissolve_same_comdat_group_list (node);
- }
- symtab_make_decl_local (node->decl);
- }
-
- if (node->thunk.thunk_p
- && TREE_PUBLIC (node->decl))
- {
- struct cgraph_node *decl_node = node;
-
- decl_node = cgraph_function_node (decl_node->callees->callee, NULL);
-
- /* Thunks have the same visibility as function they are attached to.
- Make sure the C++ front end set this up properly. */
- if (DECL_ONE_ONLY (decl_node->decl))
- {
- gcc_checking_assert (DECL_COMDAT (node->decl)
- == DECL_COMDAT (decl_node->decl));
- gcc_checking_assert (DECL_COMDAT_GROUP (node->decl)
- == DECL_COMDAT_GROUP (decl_node->decl));
- gcc_checking_assert (node->same_comdat_group);
- }
- node->forced_by_abi = decl_node->forced_by_abi;
- if (DECL_EXTERNAL (decl_node->decl))
- DECL_EXTERNAL (node->decl) = 1;
- }
-
- /* If whole comdat group is used only within LTO code, we can dissolve it,
- we handle the unification ourselves.
- We keep COMDAT and weak so visibility out of DSO does not change.
- Later we may bring the symbols static if they are not exported. */
- if (DECL_ONE_ONLY (node->decl)
- && (node->resolution == LDPR_PREVAILING_DEF_IRONLY
- || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP))
- {
- symtab_node *next = node;
-
- if (node->same_comdat_group)
- for (next = node->same_comdat_group;
- next != node;
- next = next->same_comdat_group)
- if (next->externally_visible
- && (next->resolution != LDPR_PREVAILING_DEF_IRONLY
- && next->resolution != LDPR_PREVAILING_DEF_IRONLY_EXP))
- break;
- if (node == next)
- {
- if (node->same_comdat_group)
- for (next = node->same_comdat_group;
- next != node;
- next = next->same_comdat_group)
- {
- DECL_COMDAT_GROUP (next->decl) = NULL;
- DECL_WEAK (next->decl) = false;
- }
- DECL_COMDAT_GROUP (node->decl) = NULL;
- symtab_dissolve_same_comdat_group_list (node);
- }
- }
- }
- FOR_EACH_DEFINED_FUNCTION (node)
- {
- node->local.local |= cgraph_local_node_p (node);
-
- /* If we know that function can not be overwritten by a different semantics
- and moreover its section can not be discarded, replace all direct calls
- by calls to an nonoverwritable alias. This make dynamic linking
- cheaper and enable more optimization.
-
- TODO: We can also update virtual tables. */
- if (node->callers && can_replace_by_local_alias (node))
- {
- struct cgraph_node *alias = cgraph (symtab_nonoverwritable_alias (node));
-
- if (alias && alias != node)
- {
- while (node->callers)
- {
- struct cgraph_edge *e = node->callers;
-
- cgraph_redirect_edge_callee (e, alias);
- if (gimple_has_body_p (e->caller->decl))
- {
- push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
- cgraph_redirect_edge_call_stmt_to_callee (e);
- pop_cfun ();
- }
- }
- }
- }
- }
+ if (dump_file)
+ fprintf (dump_file, "Clearing variable flags:");
FOR_EACH_VARIABLE (vnode)
- {
- /* weak flag makes no sense on local variables. */
- gcc_assert (!DECL_WEAK (vnode->decl)
- || vnode->weakref
- || TREE_PUBLIC (vnode->decl)
- || DECL_EXTERNAL (vnode->decl));
- /* In several cases declarations can not be common:
-
- - when declaration has initializer
- - when it is in weak
- - when it has specific section
- - when it resides in non-generic address space.
- - if declaration is local, it will get into .local common section
- so common flag is not needed. Frontends still produce these in
- certain cases, such as for:
-
- static int a __attribute__ ((common))
-
- Canonicalize things here and clear the redundant flag. */
- if (DECL_COMMON (vnode->decl)
- && (!(TREE_PUBLIC (vnode->decl)
- || DECL_EXTERNAL (vnode->decl))
- || (DECL_INITIAL (vnode->decl)
- && DECL_INITIAL (vnode->decl) != error_mark_node)
- || DECL_WEAK (vnode->decl)
- || DECL_SECTION_NAME (vnode->decl) != NULL
- || ! (ADDR_SPACE_GENERIC_P
- (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
- DECL_COMMON (vnode->decl) = 0;
- }
- FOR_EACH_DEFINED_VARIABLE (vnode)
- {
- if (!vnode->definition)
- continue;
- if (varpool_externally_visible_p (vnode))
- vnode->externally_visible = true;
- else
- {
- vnode->externally_visible = false;
- vnode->forced_by_abi = false;
- }
- if (!vnode->externally_visible
- && !vnode->weakref)
- {
- gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
- vnode->unique_name = ((vnode->resolution == LDPR_PREVAILING_DEF_IRONLY
- || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
- && TREE_PUBLIC (vnode->decl));
- symtab_make_decl_local (vnode->decl);
- if (vnode->same_comdat_group)
- symtab_dissolve_same_comdat_group_list (vnode);
- vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
- }
- }
+ if (!vnode->alias
+ && (TREE_ADDRESSABLE (vnode->decl)
+ || !vnode->writeonly
+ || !TREE_READONLY (vnode->decl)))
+ {
+ bool written = false;
+ bool address_taken = false;
+ bool read = false;
+ bool explicit_refs = true;
+ process_references (vnode, &written, &address_taken, &read, &explicit_refs);
+ if (!explicit_refs)
+ continue;
+ if (!address_taken)
+ {
+ if (TREE_ADDRESSABLE (vnode->decl) && dump_file)
+ fprintf (dump_file, " %s (non-addressable)", vnode->name ());
+ varpool_for_node_and_aliases (vnode, clear_addressable_bit, NULL, true);
+ }
+ if (!address_taken && !written
+ /* Making variable in explicit section readonly can cause section
+ type conflict.
+ See e.g. gcc.c-torture/compile/pr23237.c */
+ && DECL_SECTION_NAME (vnode->decl) == NULL)
+ {
+ if (!TREE_READONLY (vnode->decl) && dump_file)
+ fprintf (dump_file, " %s (read-only)", vnode->name ());
+ varpool_for_node_and_aliases (vnode, set_readonly_bit, NULL, true);
+ }
+ if (!vnode->writeonly && !read && !address_taken && written)
+ {
+ if (dump_file)
+ fprintf (dump_file, " %s (write-only)", vnode->name ());
+ varpool_for_node_and_aliases (vnode, set_writeonly_bit, NULL, true);
+ }
+ }
if (dump_file)
- {
- fprintf (dump_file, "\nMarking local functions:");
- FOR_EACH_DEFINED_FUNCTION (node)
- if (node->local.local)
- fprintf (dump_file, " %s", node->name ());
- fprintf (dump_file, "\n\n");
- fprintf (dump_file, "\nMarking externally visible functions:");
- FOR_EACH_DEFINED_FUNCTION (node)
- if (node->externally_visible)
- fprintf (dump_file, " %s", node->name ());
- fprintf (dump_file, "\n\n");
- fprintf (dump_file, "\nMarking externally visible variables:");
- FOR_EACH_DEFINED_VARIABLE (vnode)
- if (vnode->externally_visible)
- fprintf (dump_file, " %s", vnode->name ());
- fprintf (dump_file, "\n\n");
- }
- cgraph_function_flags_ready = true;
- return 0;
-}
-
-/* Local function pass handling visibilities. This happens before LTO streaming
- so in particular -fwhole-program should be ignored at this level. */
-
-namespace {
-
-const pass_data pass_data_ipa_function_and_variable_visibility =
-{
- SIMPLE_IPA_PASS, /* type */
- "visibility", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_execute */
- TV_CGRAPHOPT, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
-};
-
-class pass_ipa_function_and_variable_visibility : public simple_ipa_opt_pass
-{
-public:
- pass_ipa_function_and_variable_visibility (gcc::context *ctxt)
- : simple_ipa_opt_pass (pass_data_ipa_function_and_variable_visibility,
- ctxt)
- {}
-
- /* opt_pass methods: */
- virtual unsigned int execute (function *)
- {
- return function_and_variable_visibility (flag_whole_program && !flag_lto);
- }
-
-}; // class pass_ipa_function_and_variable_visibility
-
-} // anon namespace
-
-simple_ipa_opt_pass *
-make_pass_ipa_function_and_variable_visibility (gcc::context *ctxt)
-{
- return new pass_ipa_function_and_variable_visibility (ctxt);
+ fprintf (dump_file, "\n");
}
/* Free inline summary. */
@@ -1275,71 +773,6 @@ make_pass_ipa_free_inline_summary (gcc::context *ctxt)
return new pass_ipa_free_inline_summary (ctxt);
}
-/* Bring functionss local at LTO time with -fwhole-program. */
-
-static unsigned int
-whole_program_function_and_variable_visibility (void)
-{
- function_and_variable_visibility (flag_whole_program);
- if (optimize)
- ipa_discover_readonly_nonaddressable_vars ();
- return 0;
-}
-
-namespace {
-
-const pass_data pass_data_ipa_whole_program_visibility =
-{
- IPA_PASS, /* type */
- "whole-program", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_execute */
- TV_CGRAPHOPT, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
-};
-
-class pass_ipa_whole_program_visibility : public ipa_opt_pass_d
-{
-public:
- pass_ipa_whole_program_visibility (gcc::context *ctxt)
- : ipa_opt_pass_d (pass_data_ipa_whole_program_visibility, ctxt,
- NULL, /* generate_summary */
- NULL, /* write_summary */
- NULL, /* read_summary */
- NULL, /* write_optimization_summary */
- NULL, /* read_optimization_summary */
- NULL, /* stmt_fixup */
- 0, /* function_transform_todo_flags_start */
- NULL, /* function_transform */
- NULL) /* variable_transform */
- {}
-
- /* opt_pass methods: */
-
- virtual bool gate (function *)
- {
- /* Do not re-run on ltrans stage. */
- return !flag_ltrans;
- }
- virtual unsigned int execute (function *)
- {
- return whole_program_function_and_variable_visibility ();
- }
-
-}; // class pass_ipa_whole_program_visibility
-
-} // anon namespace
-
-ipa_opt_pass_d *
-make_pass_ipa_whole_program_visibility (gcc::context *ctxt)
-{
- return new pass_ipa_whole_program_visibility (ctxt);
-}
-
/* Generate and emit a static constructor or destructor. WHICH must
be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
diff --git a/gcc/ira-build.c b/gcc/ira-build.c
index 0396f379f00..000c25c83a7 100644
--- a/gcc/ira-build.c
+++ b/gcc/ira-build.c
@@ -515,6 +515,7 @@ ira_create_allocno (int regno, bool cap_p,
ALLOCNO_CALL_FREQ (a) = 0;
ALLOCNO_CALLS_CROSSED_NUM (a) = 0;
ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a) = 0;
+ CLEAR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a));
#ifdef STACK_REGS
ALLOCNO_NO_STACK_REG_P (a) = false;
ALLOCNO_TOTAL_NO_STACK_REG_P (a) = false;
@@ -913,6 +914,8 @@ create_cap_allocno (ira_allocno_t a)
ALLOCNO_CALLS_CROSSED_NUM (cap) = ALLOCNO_CALLS_CROSSED_NUM (a);
ALLOCNO_CHEAP_CALLS_CROSSED_NUM (cap) = ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a);
+ IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (cap),
+ ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a));
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
{
fprintf (ira_dump_file, " Creating cap ");
@@ -2048,6 +2051,8 @@ propagate_allocno_info (void)
+= ALLOCNO_CALLS_CROSSED_NUM (a);
ALLOCNO_CHEAP_CALLS_CROSSED_NUM (parent_a)
+= ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a);
+ IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (parent_a),
+ ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a));
ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a)
+= ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
aclass = ALLOCNO_CLASS (a);
@@ -2428,6 +2433,9 @@ propagate_some_info_from_allocno (ira_allocno_t a, ira_allocno_t from_a)
ALLOCNO_CALLS_CROSSED_NUM (a) += ALLOCNO_CALLS_CROSSED_NUM (from_a);
ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a)
+= ALLOCNO_CHEAP_CALLS_CROSSED_NUM (from_a);
+ IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a),
+ ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (from_a));
+
ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a)
+= ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (from_a);
if (! ALLOCNO_BAD_SPILL_P (from_a))
@@ -3059,6 +3067,8 @@ copy_info_to_removed_store_destinations (int regno)
+= ALLOCNO_CALLS_CROSSED_NUM (a);
ALLOCNO_CHEAP_CALLS_CROSSED_NUM (parent_a)
+= ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a);
+ IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (parent_a),
+ ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a));
ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a)
+= ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
merged_p = true;
diff --git a/gcc/ira-color.c b/gcc/ira-color.c
index 28a6d40eb1d..36e7e879952 100644
--- a/gcc/ira-color.c
+++ b/gcc/ira-color.c
@@ -53,7 +53,7 @@ struct allocno_hard_regs
HARD_REG_SET set;
/* Overall (spilling) cost of all allocnos with given register
set. */
- HOST_WIDEST_INT cost;
+ int64_t cost;
};
typedef struct allocno_hard_regs_node *allocno_hard_regs_node_t;
@@ -254,7 +254,7 @@ init_allocno_hard_regs (void)
/* Add (or update info about) allocno hard registers with SET and
COST. */
static allocno_hard_regs_t
-add_allocno_hard_regs (HARD_REG_SET set, HOST_WIDEST_INT cost)
+add_allocno_hard_regs (HARD_REG_SET set, int64_t cost)
{
struct allocno_hard_regs temp;
allocno_hard_regs_t hv;
@@ -519,7 +519,7 @@ print_hard_regs_subforest (FILE *f, allocno_hard_regs_node_t roots,
fprintf (f, " ");
fprintf (f, "%d:(", node->preorder_num);
print_hard_reg_set (f, node->hard_regs->set, false);
- fprintf (f, ")@" HOST_WIDEST_INT_PRINT_DEC "\n", node->hard_regs->cost);
+ fprintf (f, ")@%"PRId64"\n", node->hard_regs->cost);
print_hard_regs_subforest (f, node->first, level + 1);
}
}
diff --git a/gcc/ira-conflicts.c b/gcc/ira-conflicts.c
index c0b4f049950..870162223f7 100644
--- a/gcc/ira-conflicts.c
+++ b/gcc/ira-conflicts.c
@@ -115,8 +115,8 @@ build_conflict_bit_table (void)
= ((OBJECT_MAX (obj) - OBJECT_MIN (obj) + IRA_INT_BITS)
/ IRA_INT_BITS);
allocated_words_num += conflict_bit_vec_words_num;
- if ((unsigned HOST_WIDEST_INT) allocated_words_num * sizeof (IRA_INT_TYPE)
- > (unsigned HOST_WIDEST_INT) IRA_MAX_CONFLICT_TABLE_SIZE * 1024 * 1024)
+ if ((uint64_t) allocated_words_num * sizeof (IRA_INT_TYPE)
+ > (uint64_t) IRA_MAX_CONFLICT_TABLE_SIZE * 1024 * 1024)
{
if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
fprintf
diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c
index 648806bc182..4ecf75f124d 100644
--- a/gcc/ira-costs.c
+++ b/gcc/ira-costs.c
@@ -407,6 +407,8 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
int alt;
int i, j, k;
int insn_allows_mem[MAX_RECOG_OPERANDS];
+ move_table *move_in_cost, *move_out_cost;
+ short (*mem_cost)[2];
for (i = 0; i < n_ops; i++)
insn_allows_mem[i] = 0;
@@ -421,7 +423,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
int alt_fail = 0;
int alt_cost = 0, op_cost_add;
- if (!recog_data.alternative_enabled_p[alt])
+ if (!TEST_BIT (recog_data.enabled_alternatives, alt))
{
for (i = 0; i < recog_data.n_operands; i++)
constraints[i] = skip_alternative (constraints[i]);
@@ -517,41 +519,78 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
bool in_p = recog_data.operand_type[i] != OP_OUT;
bool out_p = recog_data.operand_type[i] != OP_IN;
enum reg_class op_class = classes[i];
- move_table *move_in_cost, *move_out_cost;
ira_init_register_move_cost_if_necessary (mode);
if (! in_p)
{
ira_assert (out_p);
- move_out_cost = ira_may_move_out_cost[mode];
- for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ if (op_class == NO_REGS)
{
- rclass = cost_classes[k];
- pp_costs[k]
- = move_out_cost[op_class][rclass] * frequency;
+ mem_cost = ira_memory_move_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k] = mem_cost[rclass][0] * frequency;
+ }
+ }
+ else
+ {
+ move_out_cost = ira_may_move_out_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k]
+ = move_out_cost[op_class][rclass] * frequency;
+ }
}
}
else if (! out_p)
{
ira_assert (in_p);
- move_in_cost = ira_may_move_in_cost[mode];
- for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ if (op_class == NO_REGS)
{
- rclass = cost_classes[k];
- pp_costs[k]
- = move_in_cost[rclass][op_class] * frequency;
+ mem_cost = ira_memory_move_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k] = mem_cost[rclass][1] * frequency;
+ }
+ }
+ else
+ {
+ move_in_cost = ira_may_move_in_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k]
+ = move_in_cost[rclass][op_class] * frequency;
+ }
}
}
else
{
- move_in_cost = ira_may_move_in_cost[mode];
- move_out_cost = ira_may_move_out_cost[mode];
- for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ if (op_class == NO_REGS)
+ {
+ mem_cost = ira_memory_move_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k] = ((mem_cost[rclass][0]
+ + mem_cost[rclass][1])
+ * frequency);
+ }
+ }
+ else
{
- rclass = cost_classes[k];
- pp_costs[k] = ((move_in_cost[rclass][op_class]
- + move_out_cost[op_class][rclass])
- * frequency);
+ move_in_cost = ira_may_move_in_cost[mode];
+ move_out_cost = ira_may_move_out_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k] = ((move_in_cost[rclass][op_class]
+ + move_out_cost[op_class][rclass])
+ * frequency);
+ }
}
}
@@ -762,10 +801,11 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
into that class. */
if (REG_P (op) && REGNO (op) >= FIRST_PSEUDO_REGISTER)
{
- if (classes[i] == NO_REGS)
+ if (classes[i] == NO_REGS && ! allows_mem[i])
{
/* We must always fail if the operand is a REG, but
- we did not find a suitable class.
+ we did not find a suitable class and memory is
+ not allowed.
Otherwise we may perform an uninitialized read
from this_op_costs after the `continue' statement
@@ -782,51 +822,94 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
bool in_p = recog_data.operand_type[i] != OP_OUT;
bool out_p = recog_data.operand_type[i] != OP_IN;
enum reg_class op_class = classes[i];
- move_table *move_in_cost, *move_out_cost;
ira_init_register_move_cost_if_necessary (mode);
if (! in_p)
{
ira_assert (out_p);
- move_out_cost = ira_may_move_out_cost[mode];
- for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ if (op_class == NO_REGS)
+ {
+ mem_cost = ira_memory_move_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k] = mem_cost[rclass][0] * frequency;
+ }
+ }
+ else
{
- rclass = cost_classes[k];
- pp_costs[k]
- = move_out_cost[op_class][rclass] * frequency;
+ move_out_cost = ira_may_move_out_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k]
+ = move_out_cost[op_class][rclass] * frequency;
+ }
}
}
else if (! out_p)
{
ira_assert (in_p);
- move_in_cost = ira_may_move_in_cost[mode];
- for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ if (op_class == NO_REGS)
+ {
+ mem_cost = ira_memory_move_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k] = mem_cost[rclass][1] * frequency;
+ }
+ }
+ else
{
- rclass = cost_classes[k];
- pp_costs[k]
- = move_in_cost[rclass][op_class] * frequency;
+ move_in_cost = ira_may_move_in_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k]
+ = move_in_cost[rclass][op_class] * frequency;
+ }
}
}
else
{
- move_in_cost = ira_may_move_in_cost[mode];
- move_out_cost = ira_may_move_out_cost[mode];
- for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ if (op_class == NO_REGS)
{
- rclass = cost_classes[k];
- pp_costs[k] = ((move_in_cost[rclass][op_class]
- + move_out_cost[op_class][rclass])
- * frequency);
+ mem_cost = ira_memory_move_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k] = ((mem_cost[rclass][0]
+ + mem_cost[rclass][1])
+ * frequency);
+ }
+ }
+ else
+ {
+ move_in_cost = ira_may_move_in_cost[mode];
+ move_out_cost = ira_may_move_out_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k] = ((move_in_cost[rclass][op_class]
+ + move_out_cost[op_class][rclass])
+ * frequency);
+ }
}
}
- /* If the alternative actually allows memory, make
- things a bit cheaper since we won't need an extra
- insn to load it. */
- pp->mem_cost
- = ((out_p ? ira_memory_move_cost[mode][op_class][0] : 0)
- + (in_p ? ira_memory_move_cost[mode][op_class][1] : 0)
- - allows_mem[i]) * frequency;
+ if (op_class == NO_REGS)
+ /* Although we don't need insn to reload from
+ memory, still accessing memory is usually more
+ expensive than a register. */
+ pp->mem_cost = frequency;
+ else
+ /* If the alternative actually allows memory, make
+ things a bit cheaper since we won't need an
+ extra insn to load it. */
+ pp->mem_cost
+ = ((out_p ? ira_memory_move_cost[mode][op_class][0] : 0)
+ + (in_p ? ira_memory_move_cost[mode][op_class][1] : 0)
+ - allows_mem[i]) * frequency;
/* If we have assigned a class to this allocno in
our first pass, add a cost to this alternative
corresponding to what we would add if this
@@ -836,15 +919,28 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
enum reg_class pref_class = pref[COST_INDEX (REGNO (op))];
if (pref_class == NO_REGS)
+ {
+ if (op_class != NO_REGS)
+ alt_cost
+ += ((out_p
+ ? ira_memory_move_cost[mode][op_class][0]
+ : 0)
+ + (in_p
+ ? ira_memory_move_cost[mode][op_class][1]
+ : 0));
+ }
+ else if (op_class == NO_REGS)
alt_cost
+= ((out_p
- ? ira_memory_move_cost[mode][op_class][0] : 0)
+ ? ira_memory_move_cost[mode][pref_class][1]
+ : 0)
+ (in_p
- ? ira_memory_move_cost[mode][op_class][1]
+ ? ira_memory_move_cost[mode][pref_class][0]
: 0));
else if (ira_reg_class_intersect[pref_class][op_class]
== NO_REGS)
- alt_cost += ira_register_move_cost[mode][pref_class][op_class];
+ alt_cost += (ira_register_move_cost
+ [mode][pref_class][op_class]);
}
}
}
@@ -1855,7 +1951,7 @@ find_costs_and_classes (FILE *dump_file)
/* Process moves involving hard regs to modify allocno hard register
costs. We can do this only after determining allocno class. If a
- hard register forms a register class, than moves with the hard
+ hard register forms a register class, then moves with the hard
register are already taken into account in class costs for the
allocno. */
static void
@@ -2142,6 +2238,7 @@ ira_tune_allocno_costs (void)
ira_allocno_object_iterator oi;
ira_object_t obj;
bool skip_p;
+ HARD_REG_SET *crossed_calls_clobber_regs;
FOR_EACH_ALLOCNO (a, ai)
{
@@ -2176,17 +2273,24 @@ ira_tune_allocno_costs (void)
continue;
rclass = REGNO_REG_CLASS (regno);
cost = 0;
- if (ira_hard_reg_set_intersection_p (regno, mode, call_used_reg_set)
- || HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
- cost += (ALLOCNO_CALL_FREQ (a)
- * (ira_memory_move_cost[mode][rclass][0]
- + ira_memory_move_cost[mode][rclass][1]));
+ crossed_calls_clobber_regs
+ = &(ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a));
+ if (ira_hard_reg_set_intersection_p (regno, mode,
+ *crossed_calls_clobber_regs))
+ {
+ if (ira_hard_reg_set_intersection_p (regno, mode,
+ call_used_reg_set)
+ || HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+ cost += (ALLOCNO_CALL_FREQ (a)
+ * (ira_memory_move_cost[mode][rclass][0]
+ + ira_memory_move_cost[mode][rclass][1]));
#ifdef IRA_HARD_REGNO_ADD_COST_MULTIPLIER
- cost += ((ira_memory_move_cost[mode][rclass][0]
- + ira_memory_move_cost[mode][rclass][1])
- * ALLOCNO_FREQ (a)
- * IRA_HARD_REGNO_ADD_COST_MULTIPLIER (regno) / 2);
+ cost += ((ira_memory_move_cost[mode][rclass][0]
+ + ira_memory_move_cost[mode][rclass][1])
+ * ALLOCNO_FREQ (a)
+ * IRA_HARD_REGNO_ADD_COST_MULTIPLIER (regno) / 2);
#endif
+ }
if (INT_MAX - cost < reg_costs[j])
reg_costs[j] = INT_MAX;
else
diff --git a/gcc/ira-int.h b/gcc/ira-int.h
index e36bb9217d9..413c8239b91 100644
--- a/gcc/ira-int.h
+++ b/gcc/ira-int.h
@@ -42,9 +42,8 @@ along with GCC; see the file COPYING3. If not see
profile driven feedback is available and the function is never
executed, frequency is always equivalent. Otherwise rescale the
edge frequency. */
-#define REG_FREQ_FROM_EDGE_FREQ(freq) \
- (optimize_size || (flag_branch_probabilities \
- && !ENTRY_BLOCK_PTR_FOR_FN (cfun)->count) \
+#define REG_FREQ_FROM_EDGE_FREQ(freq) \
+ (optimize_function_for_size_p (cfun) \
? REG_FREQ_MAX : (freq * REG_FREQ_MAX / BB_FREQ_MAX) \
? (freq * REG_FREQ_MAX / BB_FREQ_MAX) : 1)
@@ -375,6 +374,8 @@ struct ira_allocno
/* The number of calls across which it is live, but which should not
affect register preferences. */
int cheap_calls_crossed_num;
+ /* Registers clobbered by intersected calls. */
+ HARD_REG_SET crossed_calls_clobbered_regs;
/* Array of usage costs (accumulated and the one updated during
coloring) for each hard register of the allocno class. The
member value can be NULL if all costs are the same and equal to
@@ -418,6 +419,8 @@ struct ira_allocno
#define ALLOCNO_CALL_FREQ(A) ((A)->call_freq)
#define ALLOCNO_CALLS_CROSSED_NUM(A) ((A)->calls_crossed_num)
#define ALLOCNO_CHEAP_CALLS_CROSSED_NUM(A) ((A)->cheap_calls_crossed_num)
+#define ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS(A) \
+ ((A)->crossed_calls_clobbered_regs)
#define ALLOCNO_MEM_OPTIMIZED_DEST(A) ((A)->mem_optimized_dest)
#define ALLOCNO_MEM_OPTIMIZED_DEST_P(A) ((A)->mem_optimized_dest_p)
#define ALLOCNO_SOMEWHERE_RENAMED_P(A) ((A)->somewhere_renamed_p)
diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c
index 906d6db58f6..0dccee30af2 100644
--- a/gcc/ira-lives.c
+++ b/gcc/ira-lives.c
@@ -743,22 +743,17 @@ mark_hard_reg_early_clobbers (rtx insn, bool live_p)
static enum reg_class
single_reg_class (const char *constraints, rtx op, rtx equiv_const)
{
- int curr_alt, c;
- bool ignore_p;
+ int c;
enum reg_class cl, next_cl;
cl = NO_REGS;
- for (ignore_p = false, curr_alt = 0;
- (c = *constraints);
- constraints += CONSTRAINT_LEN (c, constraints))
- if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
- ignore_p = true;
+ alternative_mask enabled = recog_data.enabled_alternatives;
+ for (; (c = *constraints); constraints += CONSTRAINT_LEN (c, constraints))
+ if (c == '#')
+ enabled &= ~ALTERNATIVE_BIT (0);
else if (c == ',')
- {
- curr_alt++;
- ignore_p = false;
- }
- else if (! ignore_p)
+ enabled >>= 1;
+ else if (enabled & 1)
switch (c)
{
case ' ':
@@ -887,8 +882,7 @@ single_reg_operand_class (int op_num)
void
ira_implicitly_set_insn_hard_regs (HARD_REG_SET *set)
{
- int i, curr_alt, c, regno = 0;
- bool ignore_p;
+ int i, c, regno = 0;
enum reg_class cl;
rtx op;
enum machine_mode mode;
@@ -909,17 +903,13 @@ ira_implicitly_set_insn_hard_regs (HARD_REG_SET *set)
mode = (GET_CODE (op) == SCRATCH
? GET_MODE (op) : PSEUDO_REGNO_MODE (regno));
cl = NO_REGS;
- for (ignore_p = false, curr_alt = 0;
- (c = *p);
- p += CONSTRAINT_LEN (c, p))
- if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
- ignore_p = true;
+ alternative_mask enabled = recog_data.enabled_alternatives;
+ for (; (c = *p); p += CONSTRAINT_LEN (c, p))
+ if (c == '#')
+ enabled &= ~ALTERNATIVE_BIT (0);
else if (c == ',')
- {
- curr_alt++;
- ignore_p = false;
- }
- else if (! ignore_p)
+ enabled >>= 1;
+ else if (enabled & 1)
switch (c)
{
case 'r':
@@ -1273,6 +1263,10 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
ira_object_t obj = ira_object_id_map[i];
ira_allocno_t a = OBJECT_ALLOCNO (obj);
int num = ALLOCNO_NUM (a);
+ HARD_REG_SET this_call_used_reg_set;
+
+ get_call_reg_set_usage (insn, &this_call_used_reg_set,
+ call_used_reg_set);
/* Don't allocate allocnos that cross setjmps or any
call, if this function receives a nonlocal
@@ -1287,9 +1281,9 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
if (can_throw_internal (insn))
{
IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
- call_used_reg_set);
+ this_call_used_reg_set);
IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
- call_used_reg_set);
+ this_call_used_reg_set);
}
if (sparseset_bit_p (allocnos_processed, num))
@@ -1306,6 +1300,8 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
/* Mark it as saved at the next call. */
allocno_saved_at_call[num] = last_call_num + 1;
ALLOCNO_CALLS_CROSSED_NUM (a)++;
+ IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a),
+ this_call_used_reg_set);
if (cheap_reg != NULL_RTX
&& ALLOCNO_REGNO (a) == (int) REGNO (cheap_reg))
ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a)++;
diff --git a/gcc/ira.c b/gcc/ira.c
index d9730011c03..eebd4100bc3 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1744,7 +1744,7 @@ setup_prohibited_mode_move_regs (void)
test_reg1 = gen_rtx_REG (VOIDmode, 0);
test_reg2 = gen_rtx_REG (VOIDmode, 0);
move_pat = gen_rtx_SET (VOIDmode, test_reg1, test_reg2);
- move_insn = gen_rtx_INSN (VOIDmode, 0, 0, 0, 0, move_pat, 0, -1, 0);
+ move_insn = gen_rtx_INSN (VOIDmode, 0, 0, 0, move_pat, 0, -1, 0);
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
SET_HARD_REG_SET (ira_prohibited_mode_move_regs[i]);
@@ -1770,37 +1770,6 @@ setup_prohibited_mode_move_regs (void)
-/* Return TRUE if the operand constraint STR is commutative. */
-static bool
-commutative_constraint_p (const char *str)
-{
- int curr_alt, c;
- bool ignore_p;
-
- for (ignore_p = false, curr_alt = 0;;)
- {
- c = *str;
- if (c == '\0')
- break;
- str += CONSTRAINT_LEN (c, str);
- if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
- ignore_p = true;
- else if (c == ',')
- {
- curr_alt++;
- ignore_p = false;
- }
- else if (! ignore_p)
- {
- /* Usually `%' is the first constraint character but the
- documentation does not require this. */
- if (c == '%')
- return true;
- }
- }
- return false;
-}
-
/* Setup possible alternatives in ALTS for INSN. */
void
ira_setup_alts (rtx insn, HARD_REG_SET &alts)
@@ -1844,7 +1813,8 @@ ira_setup_alts (rtx insn, HARD_REG_SET &alts)
}
for (nalt = 0; nalt < recog_data.n_alternatives; nalt++)
{
- if (! recog_data.alternative_enabled_p[nalt] || TEST_HARD_REG_BIT (alts, nalt))
+ if (!TEST_BIT (recog_data.enabled_alternatives, nalt)
+ || TEST_HARD_REG_BIT (alts, nalt))
continue;
for (nop = 0; nop < recog_data.n_operands; nop++)
@@ -2009,33 +1979,33 @@ ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
if (op_num < 0 || recog_data.n_alternatives == 0)
return -1;
- use_commut_op_p = false;
+ /* We should find duplications only for input operands. */
+ if (recog_data.operand_type[op_num] != OP_IN)
+ return -1;
str = recog_data.constraints[op_num];
+ use_commut_op_p = false;
for (;;)
{
#ifdef EXTRA_CONSTRAINT_STR
op = recog_data.operand[op_num];
#endif
- for (ignore_p = false, original = -1, curr_alt = 0;;)
+ for (curr_alt = 0, ignore_p = !TEST_HARD_REG_BIT (alts, curr_alt),
+ original = -1;;)
{
c = *str;
if (c == '\0')
break;
- if (c == '#' || !TEST_HARD_REG_BIT (alts, curr_alt))
+ if (c == '#')
ignore_p = true;
else if (c == ',')
{
curr_alt++;
- ignore_p = false;
+ ignore_p = !TEST_HARD_REG_BIT (alts, curr_alt);
}
else if (! ignore_p)
switch (c)
{
- /* We should find duplications only for input operands. */
- case '=':
- case '+':
- goto fail;
case 'X':
case 'p':
case 'g':
@@ -2101,10 +2071,9 @@ ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
if (use_commut_op_p)
break;
use_commut_op_p = true;
- if (commutative_constraint_p (recog_data.constraints[op_num]))
+ if (recog_data.constraints[op_num][0] == '%')
str = recog_data.constraints[op_num + 1];
- else if (op_num > 0 && commutative_constraint_p (recog_data.constraints
- [op_num - 1]))
+ else if (op_num > 0 && recog_data.constraints[op_num - 1][0] == '%')
str = recog_data.constraints[op_num - 1];
else
break;
@@ -4979,17 +4948,6 @@ split_live_ranges_for_shrink_wrap (void)
use;
use = DF_REF_NEXT_REG (use))
{
- if (NONDEBUG_INSN_P (DF_REF_INSN (use))
- && GET_CODE (DF_REF_REG (use)) == SUBREG)
- {
- /* This is necessary to avoid hitting an assert at
- postreload.c:2294 in libstc++ testcases on x86_64-linux. I'm
- not really sure what the probblem actually is there. */
- bitmap_clear (&need_new);
- bitmap_clear (&reachable);
- return false;
- }
-
int ubbi = DF_REF_BB (use)->index;
if (bitmap_bit_p (&reachable, ubbi))
bitmap_set_bit (&need_new, ubbi);
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 1c357fe25a5..70991cc4693 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,26 @@
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * class.c (add_method_1): Adjust.
+ (java_treetreehash_new): Likewise.
+ * constants.c (set_constant_entry): Likewise.
+ (cpool_for_class): Likewise.
+ * decl.c (make_binding_level): Likewise.
+ (java_dup_lang_specific_decl): Likewise.
+ * expr.c (add_type_assertion): Likewise.
+ * java-tree.h (MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC): Likewise.
+ (lang_decl): don't use variable_size gty attribute.
+ (MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC): Adjust.
+ (lang_type): Don't use variable_size gty attribute.
+ * jcf-parse.c (java_parse_file): Adjust.
+ (process_zip_dir): Likewise.
+ * jcf.h: Remove usage of variable_size gty attribute.
+ * jcf-reader.c (jcf_parse_constant_pool): Adjust.
+ (jcf_parse_bootstrap_methods): Likewise.
+
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * constants.c (set_constant_entry): Adjust.
+
2014-05-06 Richard Sandiford <r.sandiford@uk.ibm.com>
* boehm.c (mark_reference_fields): Don't update the mask when
diff --git a/gcc/java/class.c b/gcc/java/class.c
index bbe7c863177..a1e4a86033b 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -764,8 +764,7 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
fndecl = build_decl (input_location, FUNCTION_DECL, name, method_type);
DECL_CONTEXT (fndecl) = this_class;
- DECL_LANG_SPECIFIC (fndecl)
- = ggc_alloc_cleared_lang_decl(sizeof (struct lang_decl));
+ DECL_LANG_SPECIFIC (fndecl) = ggc_cleared_alloc<struct lang_decl> ();
DECL_LANG_SPECIFIC (fndecl)->desc = LANG_DECL_FUNC;
/* Initialize the static initializer test table. */
@@ -3194,7 +3193,7 @@ java_treetreehash_new (htab_t ht, tree t)
e = htab_find_slot_with_hash (ht, t, hv, INSERT);
if (*e == NULL)
{
- tthe = ggc_alloc_cleared_treetreehash_entry ();
+ tthe = ggc_cleared_alloc<treetreehash_entry> ();
tthe->key = t;
*e = tthe;
}
diff --git a/gcc/java/constants.c b/gcc/java/constants.c
index 7e9cf2e7552..2e317c91bb6 100644
--- a/gcc/java/constants.c
+++ b/gcc/java/constants.c
@@ -46,11 +46,8 @@ set_constant_entry (CPool *cpool, int index, int tag, jword value)
if (cpool->data == NULL)
{
cpool->capacity = 100;
- cpool->tags = (uint8 *) ggc_alloc_cleared_atomic (sizeof (uint8)
- * cpool->capacity);
- cpool->data = ggc_alloc_cleared_vec_cpool_entry (sizeof
- (union cpool_entry),
- cpool->capacity);
+ cpool->tags = ggc_cleared_vec_alloc<uint8> (cpool->capacity);
+ cpool->data = ggc_cleared_vec_alloc<cpool_entry> (cpool->capacity);
cpool->count = 1;
}
if (index >= cpool->capacity)
@@ -338,7 +335,7 @@ cpool_for_class (tree klass)
if (cpool == NULL)
{
- cpool = ggc_alloc_cleared_CPool ();
+ cpool = ggc_cleared_alloc<CPool> ();
TYPE_CPOOL (klass) = cpool;
}
return cpool;
diff --git a/gcc/java/decl.c b/gcc/java/decl.c
index 53d6f89b2d5..841fb4cbad1 100644
--- a/gcc/java/decl.c
+++ b/gcc/java/decl.c
@@ -1307,7 +1307,7 @@ static struct binding_level *
make_binding_level (void)
{
/* NOSTRICT */
- return ggc_alloc_cleared_binding_level ();
+ return ggc_cleared_alloc<binding_level> ();
}
void
@@ -1646,7 +1646,7 @@ java_dup_lang_specific_decl (tree node)
return;
lang_decl_size = sizeof (struct lang_decl);
- x = ggc_alloc_lang_decl (lang_decl_size);
+ x = ggc_alloc<struct lang_decl> ();
memcpy (x, DECL_LANG_SPECIFIC (node), lang_decl_size);
DECL_LANG_SPECIFIC (node) = x;
}
diff --git a/gcc/java/expr.c b/gcc/java/expr.c
index e66bdb152ab..51b8f0f7c8f 100644
--- a/gcc/java/expr.c
+++ b/gcc/java/expr.c
@@ -471,7 +471,7 @@ add_type_assertion (tree klass, int assertion_code, tree op1, tree op2)
if (*as_pp)
return;
- *as_pp = ggc_alloc_type_assertion ();
+ *as_pp = ggc_alloc<type_assertion> ();
**(type_assertion **)as_pp = as;
}
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index 806d2d7a54d..e832f44fb0f 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -699,8 +699,7 @@ union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
#define MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC(T) \
if (DECL_LANG_SPECIFIC (T) == NULL) \
{ \
- DECL_LANG_SPECIFIC ((T)) \
- = ggc_alloc_cleared_lang_decl (sizeof (struct lang_decl)); \
+ DECL_LANG_SPECIFIC ((T)) = ggc_cleared_alloc<struct lang_decl> (); \
DECL_LANG_SPECIFIC (T)->desc = LANG_DECL_VAR; \
}
@@ -808,7 +807,7 @@ struct GTY(()) lang_decl_var {
enum lang_decl_desc {LANG_DECL_FUNC, LANG_DECL_VAR};
-struct GTY((variable_size)) lang_decl {
+struct GTY(()) lang_decl {
enum lang_decl_desc desc;
union lang_decl_u
{
@@ -825,8 +824,7 @@ struct GTY((variable_size)) lang_decl {
#define TYPE_CPOOL_DATA_REF(T) (TYPE_LANG_SPECIFIC (T)->cpool_data_ref)
#define MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC(T) \
if (TYPE_LANG_SPECIFIC ((T)) == NULL) \
- TYPE_LANG_SPECIFIC ((T)) \
- = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+ TYPE_LANG_SPECIFIC ((T)) = ggc_cleared_alloc<struct lang_type> ();
#define TYPE_DUMMY(T) (TYPE_LANG_SPECIFIC(T)->dummy_class)
@@ -869,10 +867,7 @@ typedef struct GTY(()) method_entry_d {
} method_entry;
-/* FIXME: the variable_size annotation here is needed because these types are
- variable-sized in some other frontends. Due to gengtype deficiency the GTY
- options of such types have to agree across all frontends. */
-struct GTY((variable_size)) lang_type {
+struct GTY(()) lang_type {
tree signature;
struct JCF *jcf;
struct CPool *cpool;
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index 748f7c3e061..7425b4e05e3 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -1905,7 +1905,7 @@ java_parse_file (void)
if (magic == 0xcafebabe)
{
CLASS_FILE_P (node) = 1;
- current_jcf = ggc_alloc_cleared_JCF ();
+ current_jcf = ggc_cleared_alloc<JCF> ();
current_jcf->read_state = finput;
current_jcf->filbuf = jcf_filbuf_from_stdio;
jcf_parse (current_jcf);
@@ -1922,7 +1922,7 @@ java_parse_file (void)
}
else if (magic == (JCF_u4)ZIPMAGIC)
{
- main_jcf = ggc_alloc_cleared_JCF ();
+ main_jcf = ggc_cleared_alloc<JCF> ();
main_jcf->read_state = finput;
main_jcf->filbuf = jcf_filbuf_from_stdio;
linemap_add (line_table, LC_ENTER, false, filename, 0);
@@ -2178,7 +2178,7 @@ process_zip_dir (FILE *finput)
class_name = compute_class_name (zdir);
file_name = XNEWVEC (char, zdir->filename_length+1);
- jcf = ggc_alloc_cleared_JCF ();
+ jcf = ggc_cleared_alloc<JCF> ();
strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
file_name [zdir->filename_length] = '\0';
diff --git a/gcc/java/jcf-reader.c b/gcc/java/jcf-reader.c
index 10def13ca96..ed175cb24c1 100644
--- a/gcc/java/jcf-reader.c
+++ b/gcc/java/jcf-reader.c
@@ -341,7 +341,8 @@ jcf_parse_constant_pool (JCF* jcf)
int i, n;
JPOOL_SIZE (jcf) = (JCF_FILL (jcf, 2), JCF_readu2 (jcf));
jcf->cpool.tags = (uint8 *) ggc_alloc_atomic (JPOOL_SIZE (jcf));
- jcf->cpool.data = ggc_alloc_cpool_entry (sizeof (jword) * JPOOL_SIZE (jcf));
+ jcf->cpool.data = (cpool_entry *) ggc_internal_cleared_alloc
+ (sizeof (jword) * JPOOL_SIZE (jcf));
jcf->cpool.tags[0] = 0;
#ifdef HANDLE_START_CONSTANT_POOL
HANDLE_START_CONSTANT_POOL (JPOOL_SIZE (jcf));
@@ -551,9 +552,7 @@ jcf_parse_bootstrap_methods (JCF* jcf, int attribute_length ATTRIBUTE_UNUSED)
int i;
uint16 num_methods = JCF_readu2 (jcf);
jcf->bootstrap_methods.count = num_methods;
- jcf->bootstrap_methods.methods
- = (bootstrap_method *) ggc_alloc_atomic (num_methods
- * sizeof (bootstrap_method));
+ jcf->bootstrap_methods.methods = ggc_vec_alloc<bootstrap_method> (num_methods);
#ifdef HANDLE_START_BOOTSTRAP_METHODS
HANDLE_START_BOOTSTRAP_METHODS (jcf, num_methods);
#endif
@@ -564,9 +563,7 @@ jcf_parse_bootstrap_methods (JCF* jcf, int attribute_length ATTRIBUTE_UNUSED)
bootstrap_method *m = &jcf->bootstrap_methods.methods[i];
m->method_ref = JCF_readu2 (jcf);
m->num_arguments = JCF_readu2 (jcf);
- m->bootstrap_arguments
- = (unsigned *) ggc_alloc_atomic (m->num_arguments
- * sizeof (unsigned));
+ m->bootstrap_arguments = ggc_vec_alloc<unsigned> (m->num_arguments);
for (j = 0; j < m->num_arguments; j++)
m->bootstrap_arguments[j] = JCF_readu2 (jcf);
}
diff --git a/gcc/java/jcf.h b/gcc/java/jcf.h
index 8aa077e4c87..0988d658dcc 100644
--- a/gcc/java/jcf.h
+++ b/gcc/java/jcf.h
@@ -65,7 +65,7 @@ jcf_open_exact_case (const char* filename, int oflag);
struct JCF;
typedef int (*jcf_filbuf_t) (struct JCF*, int needed);
-union GTY((variable_size)) cpool_entry {
+union GTY(()) cpool_entry {
jword GTY ((tag ("0"))) w;
tree GTY ((tag ("1"))) t;
};
diff --git a/gcc/jump.c b/gcc/jump.c
index cdea8d5b885..9418f6529fa 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -1590,11 +1590,7 @@ redirect_jump_2 (rtx jump, rtx olabel, rtx nlabel, int delete_unused,
label and are now changing it into a direct conditional return.
The jump is no longer crossing in that case. */
if (ANY_RETURN_P (nlabel))
- {
- note = find_reg_note (jump, REG_CROSSING_JUMP, NULL_RTX);
- if (note)
- remove_note (jump, note);
- }
+ CROSSING_JUMP_P (jump) = 0;
if (!ANY_RETURN_P (olabel)
&& --LABEL_NUSES (olabel) == 0 && delete_unused > 0
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index 95bd3793329..d9a1dfdc194 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -60,6 +60,7 @@ extern size_t lhd_tree_size (enum tree_code);
extern HOST_WIDE_INT lhd_to_target_charset (HOST_WIDE_INT);
extern tree lhd_expr_to_decl (tree, bool *, bool *);
extern tree lhd_builtin_function (tree);
+extern tree lhd_enum_underlying_base_type (const_tree);
/* Declarations of default tree inlining hooks. */
extern void lhd_initialize_diagnostics (diagnostic_context *);
@@ -173,6 +174,7 @@ extern tree lhd_make_node (enum tree_code);
#define LANG_HOOKS_GET_SUBRANGE_BOUNDS NULL
#define LANG_HOOKS_DESCRIPTIVE_TYPE NULL
#define LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE reconstruct_complex_type
+#define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE lhd_enum_underlying_base_type
#define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
LANG_HOOKS_MAKE_TYPE, \
@@ -191,7 +193,8 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_GET_ARRAY_DESCR_INFO, \
LANG_HOOKS_GET_SUBRANGE_BOUNDS, \
LANG_HOOKS_DESCRIPTIVE_TYPE, \
- LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE \
+ LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE, \
+ LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE \
}
/* Declaration hooks. */
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index d00ebd8a08c..8f65c6860a5 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -678,3 +678,12 @@ lhd_end_section (void)
saved_section = NULL;
}
}
+
+/* Default implementation of enum_underlying_base_type using type_for_size. */
+
+tree
+lhd_enum_underlying_base_type (const_tree enum_type)
+{
+ return lang_hooks.types.type_for_size (TYPE_PRECISION (enum_type),
+ TYPE_UNSIGNED (enum_type));
+}
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index c848b0c5911..35b47bc6574 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -137,6 +137,12 @@ struct lang_hooks_for_types
return values from functions. The argument TYPE is the top of the
chain, and BOTTOM is the new type which we will point to. */
tree (*reconstruct_complex_type) (tree, tree);
+
+ /* Returns the tree that represents the underlying data type used to
+ implement the enumeration. The default implementation will just use
+ type_for_size. Used in dwarf2out.c to add a DW_AT_type base type
+ reference to a DW_TAG_enumeration. */
+ tree (*enum_underlying_base_type) (const_tree);
};
/* Language hooks related to decls and the symbol table. */
diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c
index d03d13c648e..0e843938134 100644
--- a/gcc/loop-doloop.c
+++ b/gcc/loop-doloop.c
@@ -417,7 +417,7 @@ doloop_modify (struct loop *loop, struct niter_desc *desc,
{
fprintf (dump_file, "Doloop: Inserting doloop pattern (");
if (desc->const_iter)
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, desc->niter);
+ fprintf (dump_file, "%"PRId64, desc->niter);
else
fputs ("runtime", dump_file);
fputs (" iterations).\n", dump_file);
diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
index 796bd59f2d6..ee6c71e8a47 100644
--- a/gcc/loop-iv.c
+++ b/gcc/loop-iv.c
@@ -1308,12 +1308,12 @@ iv_analysis_done (void)
/* Computes inverse to X modulo (1 << MOD). */
-static unsigned HOST_WIDEST_INT
-inverse (unsigned HOST_WIDEST_INT x, int mod)
+static uint64_t
+inverse (uint64_t x, int mod)
{
- unsigned HOST_WIDEST_INT mask =
- ((unsigned HOST_WIDEST_INT) 1 << (mod - 1) << 1) - 1;
- unsigned HOST_WIDEST_INT rslt = 1;
+ uint64_t mask =
+ ((uint64_t) 1 << (mod - 1) << 1) - 1;
+ uint64_t rslt = 1;
int i;
for (i = 0; i < mod - 1; i++)
@@ -2263,13 +2263,13 @@ canonicalize_iv_subregs (struct rtx_iv *iv0, struct rtx_iv *iv1,
a number of fields in DESC already filled in. OLD_NITER is the original
expression for the number of iterations, before we tried to simplify it. */
-static unsigned HOST_WIDEST_INT
+static uint64_t
determine_max_iter (struct loop *loop, struct niter_desc *desc, rtx old_niter)
{
rtx niter = desc->niter_expr;
rtx mmin, mmax, cmp;
- unsigned HOST_WIDEST_INT nmax, inc;
- unsigned HOST_WIDEST_INT andmax = 0;
+ uint64_t nmax, inc;
+ uint64_t andmax = 0;
/* We used to look for constant operand 0 of AND,
but canonicalization should always make this impossible. */
@@ -2312,7 +2312,7 @@ determine_max_iter (struct loop *loop, struct niter_desc *desc, rtx old_niter)
if (andmax)
nmax = MIN (nmax, andmax);
if (dump_file)
- fprintf (dump_file, ";; Determined upper bound "HOST_WIDEST_INT_PRINT_DEC".\n",
+ fprintf (dump_file, ";; Determined upper bound %"PRId64".\n",
nmax);
return nmax;
}
@@ -2331,8 +2331,8 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
enum rtx_code cond;
enum machine_mode mode, comp_mode;
rtx mmin, mmax, mode_mmin, mode_mmax;
- unsigned HOST_WIDEST_INT s, size, d, inv, max;
- HOST_WIDEST_INT up, down, inc, step_val;
+ uint64_t s, size, d, inv, max;
+ int64_t up, down, inc, step_val;
int was_sharp = false;
rtx old_niter;
bool step_is_pow2;
@@ -2679,7 +2679,7 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
d *= 2;
size--;
}
- bound = GEN_INT (((unsigned HOST_WIDEST_INT) 1 << (size - 1 ) << 1) - 1);
+ bound = GEN_INT (((uint64_t) 1 << (size - 1 ) << 1) - 1);
tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
tmp = simplify_gen_binary (UMOD, mode, tmp1, gen_int_mode (d, mode));
@@ -2833,7 +2833,7 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
if (CONST_INT_P (desc->niter_expr))
{
- unsigned HOST_WIDEST_INT val = INTVAL (desc->niter_expr);
+ uint64_t val = INTVAL (desc->niter_expr);
desc->const_iter = true;
desc->niter = val & GET_MODE_MASK (desc->mode);
@@ -3032,7 +3032,7 @@ get_simple_loop_desc (struct loop *loop)
/* At least desc->infinite is not always initialized by
find_simple_loop_exit. */
- desc = ggc_alloc_cleared_niter_desc ();
+ desc = ggc_cleared_alloc<niter_desc> ();
iv_analysis_loop_init (loop);
find_simple_exit (loop, desc);
loop->simple_loop_desc = desc;
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index 5797d200d95..4ce0830c4ca 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -548,7 +548,7 @@ decide_peel_completely (struct loop *loop, int flags ATTRIBUTE_UNUSED)
{
fprintf (dump_file,
";; Not peeling loop completely, rolls too much (");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, desc->niter);
+ fprintf (dump_file, "%"PRId64, desc->niter);
fprintf (dump_file, " iterations > %d [maximum peelings])\n", npeel);
}
return;
@@ -1429,8 +1429,8 @@ decide_peel_simple (struct loop *loop, int flags)
if (dump_file)
{
fprintf (dump_file, ";; Not peeling loop, rolls too much (");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) (iterations.to_shwi () + 1));
+ fprintf (dump_file, "%"PRId64,
+ (int64_t) (iterations.to_shwi () + 1));
fprintf (dump_file, " iterations > %d [maximum peelings])\n",
npeel);
}
diff --git a/gcc/lra-assigns.c b/gcc/lra-assigns.c
index f7bb86b2160..03c2506d826 100644
--- a/gcc/lra-assigns.c
+++ b/gcc/lra-assigns.c
@@ -1460,12 +1460,13 @@ lra_assign (void)
create_live_range_start_chains ();
setup_live_pseudos_and_spill_after_risky_transforms (&all_spilled_pseudos);
#ifdef ENABLE_CHECKING
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
- && lra_reg_info[i].call_p
- && overlaps_hard_reg_set_p (call_used_reg_set,
- PSEUDO_REGNO_MODE (i), reg_renumber[i]))
- gcc_unreachable ();
+ if (!flag_use_caller_save)
+ for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+ if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
+ && lra_reg_info[i].call_p
+ && overlaps_hard_reg_set_p (call_used_reg_set,
+ PSEUDO_REGNO_MODE (i), reg_renumber[i]))
+ gcc_unreachable ();
#endif
/* Setup insns to process on the next constraint pass. */
bitmap_initialize (&changed_pseudo_bitmap, &reg_obstack);
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index aac50876d21..147f1214a8d 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -1557,19 +1557,16 @@ process_alt_operands (int only_alternative)
together, the second alternatives go together, etc.
First loop over alternatives. */
+ alternative_mask enabled = curr_id->enabled_alternatives;
+ if (only_alternative >= 0)
+ enabled &= ALTERNATIVE_BIT (only_alternative);
+
for (nalt = 0; nalt < n_alternatives; nalt++)
{
/* Loop over operands for one constraint alternative. */
-#if HAVE_ATTR_enabled
- if (curr_id->alternative_enabled_p != NULL
- && ! curr_id->alternative_enabled_p[nalt])
+ if (!TEST_BIT (enabled, nalt))
continue;
-#endif
- if (only_alternative >= 0 && nalt != only_alternative)
- continue;
-
-
overall = losers = reject = reload_nregs = reload_sum = 0;
for (nop = 0; nop < n_operands; nop++)
{
@@ -2787,9 +2784,14 @@ equiv_address_substitution (struct address_info *ad)
Add reloads to the lists *BEFORE and *AFTER. We might need to add
reloads to *AFTER because of inc/dec, {pre, post} modify in the
- address. Return true for any RTL change. */
+ address. Return true for any RTL change.
+
+ The function is a helper function which does not produce all
+ transformations which can be necessary. It does just basic steps.
+ To do all necessary transformations use function
+ process_address. */
static bool
-process_address (int nop, rtx *before, rtx *after)
+process_address_1 (int nop, rtx *before, rtx *after)
{
struct address_info ad;
rtx new_reg;
@@ -2989,6 +2991,18 @@ process_address (int nop, rtx *before, rtx *after)
return true;
}
+/* Do address reloads until it is necessary. Use process_address_1 as
+ a helper function. Return true for any RTL changes. */
+static bool
+process_address (int nop, rtx *before, rtx *after)
+{
+ bool res = false;
+
+ while (process_address_1 (nop, before, after))
+ res = true;
+ return res;
+}
+
/* Emit insns to reload VALUE into a new register. VALUE is an
auto-increment or auto-decrement RTX whose operand is a register or
memory location; so reloading involves incrementing that location.
@@ -3273,7 +3287,7 @@ curr_insn_transform (void)
change_p = true;
lra_update_dup (curr_id, i);
}
-
+
if (change_p)
/* If we've changed the instruction then any alternative that
we chose previously may no longer be valid. */
@@ -4608,7 +4622,10 @@ need_for_call_save_p (int regno)
lra_assert (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0);
return (usage_insns[regno].calls_num < calls_num
&& (overlaps_hard_reg_set_p
- (call_used_reg_set,
+ ((flag_use_caller_save &&
+ ! hard_reg_set_empty_p (lra_reg_info[regno].actual_call_used_reg_set))
+ ? lra_reg_info[regno].actual_call_used_reg_set
+ : call_used_reg_set,
PSEUDO_REGNO_MODE (regno), reg_renumber[regno])
|| HARD_REGNO_CALL_PART_CLOBBERED (reg_renumber[regno],
PSEUDO_REGNO_MODE (regno))));
diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c
index abdf6973310..27878203555 100644
--- a/gcc/lra-eliminations.c
+++ b/gcc/lra-eliminations.c
@@ -565,6 +565,16 @@ lra_eliminate_regs_1 (rtx insn, rtx x, enum machine_mode mem_mode,
alter_subreg (&x, false);
return x;
}
+ else if (! subst_p)
+ {
+ /* LRA can transform subregs itself. So don't call
+ simplify_gen_subreg until LRA transformations are
+ finished. Function simplify_gen_subreg can do
+ non-trivial transformations (like truncation) which
+ might make LRA work to fail. */
+ SUBREG_REG (x) = new_rtx;
+ return x;
+ }
else
return simplify_gen_subreg (GET_MODE (x), new_rtx,
GET_MODE (new_rtx), SUBREG_BYTE (x));
diff --git a/gcc/lra-int.h b/gcc/lra-int.h
index b2f5cf7d05e..3c8973479fd 100644
--- a/gcc/lra-int.h
+++ b/gcc/lra-int.h
@@ -77,6 +77,10 @@ struct lra_reg
/* The following fields are defined only for pseudos. */
/* Hard registers with which the pseudo conflicts. */
HARD_REG_SET conflict_hard_regs;
+ /* Call used registers with which the pseudo conflicts, taking into account
+ the registers used by functions called from calls which cross the
+ pseudo. */
+ HARD_REG_SET actual_call_used_reg_set;
/* We assign hard registers to reload pseudos which can occur in few
places. So two hard register preferences are enough for them.
The following fields define the preferred hard registers. If
@@ -227,7 +231,7 @@ struct lra_insn_recog_data
ending with a negative value. */
int *arg_hard_regs;
/* Alternative enabled for the insn. NULL for debug insns. */
- bool *alternative_enabled_p;
+ alternative_mask enabled_alternatives;
/* The following member value is always NULL for a debug insn. */
struct lra_insn_reg *regs;
};
diff --git a/gcc/lra-lives.c b/gcc/lra-lives.c
index 8444adee6d8..26ba0d259c0 100644
--- a/gcc/lra-lives.c
+++ b/gcc/lra-lives.c
@@ -624,6 +624,17 @@ process_bb_lives (basic_block bb, int &curr_point)
if (call_p)
{
+ if (flag_use_caller_save)
+ {
+ HARD_REG_SET this_call_used_reg_set;
+ get_call_reg_set_usage (curr_insn, &this_call_used_reg_set,
+ call_used_reg_set);
+
+ EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, j)
+ IOR_HARD_REG_SET (lra_reg_info[j].actual_call_used_reg_set,
+ this_call_used_reg_set);
+ }
+
sparseset_ior (pseudos_live_through_calls,
pseudos_live_through_calls, pseudos_live);
if (cfun->has_nonlocal_label
diff --git a/gcc/lra.c b/gcc/lra.c
index c1b92d8eee4..d199a813fbe 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -724,8 +724,6 @@ free_insn_recog_data (lra_insn_recog_data_t data)
free (data->dup_loc);
if (data->arg_hard_regs != NULL)
free (data->arg_hard_regs);
- if (HAVE_ATTR_enabled && data->alternative_enabled_p != NULL)
- free (data->alternative_enabled_p);
if (data->icode < 0 && NONDEBUG_INSN_P (data->insn))
{
if (data->insn_static_data->operand_alternative != NULL)
@@ -1072,7 +1070,7 @@ lra_set_insn_recog_data (rtx insn)
data->insn_static_data = &debug_insn_static_data;
data->dup_loc = NULL;
data->arg_hard_regs = NULL;
- data->alternative_enabled_p = NULL;
+ data->enabled_alternatives = ALL_ALTERNATIVES;
data->operand_loc = XNEWVEC (rtx *, 1);
data->operand_loc[0] = &INSN_VAR_LOCATION_LOC (insn);
return data;
@@ -1132,7 +1130,7 @@ lra_set_insn_recog_data (rtx insn)
= (insn_static_data->operand[i].constraint[0] == '=' ? OP_OUT
: insn_static_data->operand[i].constraint[0] == '+' ? OP_INOUT
: OP_IN);
- data->alternative_enabled_p = NULL;
+ data->enabled_alternatives = ALL_ALTERNATIVES;
}
else
{
@@ -1159,27 +1157,7 @@ lra_set_insn_recog_data (rtx insn)
memcpy (locs, recog_data.dup_loc, n * sizeof (rtx *));
}
data->dup_loc = locs;
- if (HAVE_ATTR_enabled)
- {
- bool *bp;
-
- n = insn_static_data->n_alternatives;
- lra_assert (n >= 0);
- data->alternative_enabled_p = bp = XNEWVEC (bool, n);
- /* Cache the insn because we don't want to call extract_insn
- from get_attr_enabled as extract_insn modifies
- which_alternative. The attribute enabled should not depend
- on insn operands, operand modes, operand types, and operand
- constraints. It should depend on the architecture. If it
- is not true, we should rewrite this file code to use
- extract_insn instead of less expensive insn_extract. */
- recog_data.insn = insn;
- for (i = 0; i < n; i++)
- {
- which_alternative = i;
- bp[i] = get_attr_enabled (insn);
- }
- }
+ data->enabled_alternatives = get_enabled_alternatives (insn);
}
if (GET_CODE (PATTERN (insn)) == CLOBBER || GET_CODE (PATTERN (insn)) == USE)
insn_static_data->hard_regs = NULL;
@@ -1370,18 +1348,19 @@ lra_update_insn_recog_data (rtx insn)
#ifdef ENABLE_CHECKING
{
int i;
- bool *bp;
+ alternative_mask enabled;
n = insn_static_data->n_alternatives;
- bp = data->alternative_enabled_p;
- lra_assert (n >= 0 && bp != NULL);
+ enabled = data->enabled_alternatives;
+ lra_assert (n >= 0);
/* Cache the insn to prevent extract_insn call from
get_attr_enabled. */
recog_data.insn = insn;
for (i = 0; i < n; i++)
{
which_alternative = i;
- lra_assert (bp[i] == get_attr_enabled (insn));
+ lra_assert (TEST_BIT (enabled, i)
+ == (bool) get_attr_enabled (insn));
}
}
#endif
@@ -1448,6 +1427,7 @@ initialize_lra_reg_info_element (int i)
lra_reg_info[i].no_stack_p = false;
#endif
CLEAR_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs);
+ CLEAR_HARD_REG_SET (lra_reg_info[i].actual_call_used_reg_set);
lra_reg_info[i].preferred_hard_regno1 = -1;
lra_reg_info[i].preferred_hard_regno2 = -1;
lra_reg_info[i].preferred_hard_regno_profit1 = 0;
@@ -2365,7 +2345,18 @@ lra (FILE *f)
lra_eliminate (false, false);
/* Do inheritance only for regular algorithms. */
if (! lra_simple_p)
- lra_inheritance ();
+ {
+ if (flag_use_caller_save)
+ {
+ if (live_p)
+ lra_clear_live_ranges ();
+ /* As a side-effect of lra_create_live_ranges, we calculate
+ actual_call_used_reg_set, which is needed during
+ lra_inheritance. */
+ lra_create_live_ranges (true);
+ }
+ lra_inheritance ();
+ }
if (live_p)
lra_clear_live_ranges ();
/* We need live ranges for lra_assign -- so build them. */
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 121614a9428..4f8d5b701ff 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -395,6 +395,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
ipa_opt_pass_d *pass;
int i;
bool alias_p;
+ const char *comdat;
+ tree group;
boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node);
@@ -478,15 +480,24 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
streamer_write_hwi_stream (ob->main_stream, ref);
}
- if (node->same_comdat_group && !boundary_p)
+ group = node->get_comdat_group ();
+ if (group)
+ comdat = IDENTIFIER_POINTER (group);
+ else
+ comdat = "";
+ lto_output_data_stream (ob->main_stream, comdat, strlen (comdat) + 1);
+ if (group)
{
- ref = lto_symtab_encoder_lookup (encoder,
- node->same_comdat_group);
- gcc_assert (ref != LCC_NOT_FOUND);
+ if (node->same_comdat_group && !boundary_p)
+ {
+ ref = lto_symtab_encoder_lookup (encoder,
+ node->same_comdat_group);
+ gcc_assert (ref != LCC_NOT_FOUND);
+ }
+ else
+ ref = LCC_NOT_FOUND;
+ streamer_write_hwi_stream (ob->main_stream, ref);
}
- else
- ref = LCC_NOT_FOUND;
- streamer_write_hwi_stream (ob->main_stream, ref);
streamer_write_hwi_stream (ob->main_stream, node->tp_first_run);
@@ -551,6 +562,8 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
struct bitpack_d bp;
int ref;
bool alias_p;
+ const char *comdat;
+ tree group;
streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
LTO_symtab_variable);
@@ -562,6 +575,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
bp_pack_value (&bp, node->forced_by_abi, 1);
bp_pack_value (&bp, node->unique_name, 1);
bp_pack_value (&bp, node->body_removed, 1);
+ bp_pack_value (&bp, node->writeonly, 1);
bp_pack_value (&bp, node->definition, 1);
alias_p = node->alias && (!boundary_p || node->weakref);
bp_pack_value (&bp, alias_p, 1);
@@ -586,15 +600,24 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
/* in_other_partition. */
}
streamer_write_bitpack (&bp);
- if (node->same_comdat_group && !boundary_p)
+ group = node->get_comdat_group ();
+ if (group)
+ comdat = IDENTIFIER_POINTER (group);
+ else
+ comdat = "";
+ lto_output_data_stream (ob->main_stream, comdat, strlen (comdat) + 1);
+ if (group)
{
- ref = lto_symtab_encoder_lookup (encoder,
- node->same_comdat_group);
- gcc_assert (ref != LCC_NOT_FOUND);
+ if (node->same_comdat_group && !boundary_p)
+ {
+ ref = lto_symtab_encoder_lookup (encoder,
+ node->same_comdat_group);
+ gcc_assert (ref != LCC_NOT_FOUND);
+ }
+ else
+ ref = LCC_NOT_FOUND;
+ streamer_write_hwi_stream (ob->main_stream, ref);
}
- else
- ref = LCC_NOT_FOUND;
- streamer_write_hwi_stream (ob->main_stream, ref);
streamer_write_enum (ob->main_stream, ld_plugin_symbol_resolution,
LDPR_NUM_KNOWN, node->resolution);
}
@@ -945,6 +968,26 @@ output_symtab (void)
output_refs (encoder);
}
+/* Return COMDAT_GROUP encoded in IB as a plain string. */
+
+static tree
+read_comdat_group (struct lto_input_block *ib)
+{
+ unsigned int len = strnlen (ib->data + ib->p, ib->len - ib->p - 1);
+ tree group;
+
+ if (ib->data[ib->p + len])
+ lto_section_overrun (ib);
+ if (!len)
+ {
+ ib->p++;
+ return NULL;
+ }
+ group = get_identifier (ib->data + ib->p);
+ ib->p += len + 1;
+ return group;
+}
+
/* Overwrite the information in NODE based on FILE_DATA, TAG, FLAGS,
STACK_SIZE, SELF_TIME and SELF_SIZE. This is called either to initialize
NODE or to replace the values in it, for instance because the first
@@ -1033,6 +1076,7 @@ input_node (struct lto_file_decl_data *file_data,
int clone_ref;
int order;
int i, count;
+ tree group;
order = streamer_read_hwi (ib) + order_base;
clone_ref = streamer_read_hwi (ib);
@@ -1078,7 +1122,9 @@ input_node (struct lto_file_decl_data *file_data,
if (tag == LTO_symtab_analyzed_node)
ref = streamer_read_hwi (ib);
- ref2 = streamer_read_hwi (ib);
+ group = read_comdat_group (ib);
+ if (group)
+ ref2 = streamer_read_hwi (ib);
/* Make sure that we have not read this node before. Nodes that
have already been read will have their tag stored in the 'aux'
@@ -1097,8 +1143,14 @@ input_node (struct lto_file_decl_data *file_data,
/* Store a reference for now, and fix up later to be a pointer. */
node->global.inlined_to = (cgraph_node_ptr) (intptr_t) ref;
- /* Store a reference for now, and fix up later to be a pointer. */
- node->same_comdat_group = (symtab_node *) (intptr_t) ref2;
+ if (group)
+ {
+ node->set_comdat_group (group);
+ /* Store a reference for now, and fix up later to be a pointer. */
+ node->same_comdat_group = (symtab_node *) (intptr_t) ref2;
+ }
+ else
+ node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND;
if (node->thunk.thunk_p)
{
@@ -1130,6 +1182,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
struct bitpack_d bp;
int ref = LCC_NOT_FOUND;
int order;
+ tree group;
order = streamer_read_hwi (ib) + order_base;
decl_index = streamer_read_uhwi (ib);
@@ -1153,6 +1206,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
node->forced_by_abi = bp_unpack_value (&bp, 1);
node->unique_name = bp_unpack_value (&bp, 1);
node->body_removed = bp_unpack_value (&bp, 1);
+ node->writeonly = bp_unpack_value (&bp, 1);
node->definition = bp_unpack_value (&bp, 1);
node->alias = bp_unpack_value (&bp, 1);
node->weakref = bp_unpack_value (&bp, 1);
@@ -1166,9 +1220,16 @@ input_varpool_node (struct lto_file_decl_data *file_data,
}
if (node->alias && !node->analyzed && node->weakref)
node->alias_target = get_alias_symbol (node->decl);
- ref = streamer_read_hwi (ib);
- /* Store a reference for now, and fix up later to be a pointer. */
- node->same_comdat_group = (symtab_node *) (intptr_t) ref;
+ group = read_comdat_group (ib);
+ if (group)
+ {
+ node->set_comdat_group (group);
+ ref = streamer_read_hwi (ib);
+ /* Store a reference for now, and fix up later to be a pointer. */
+ node->same_comdat_group = (symtab_node *) (intptr_t) ref;
+ }
+ else
+ node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND;
node->resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution,
LDPR_NUM_KNOWN);
gcc_assert (flag_ltrans
@@ -1754,7 +1815,7 @@ input_node_opt_summary (struct cgraph_node *node,
count = streamer_read_uhwi (ib_main);
for (i = 0; i < count; i++)
{
- struct ipa_replace_map *map = ggc_alloc_ipa_replace_map ();
+ struct ipa_replace_map *map = ggc_alloc<ipa_replace_map> ();
vec_safe_push (node->clone.tree_map, map);
map->parm_num = streamer_read_uhwi (ib_main);
diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c
index 9aa7639099c..d88776398ba 100644
--- a/gcc/lto-section-in.c
+++ b/gcc/lto-section-in.c
@@ -364,7 +364,7 @@ lto_get_decl_name_mapping (struct lto_file_decl_data *decl_data,
struct lto_in_decl_state *
lto_new_in_decl_state (void)
{
- return ggc_alloc_cleared_lto_in_decl_state ();
+ return ggc_cleared_alloc<lto_in_decl_state> ();
}
/* Delete STATE and its components. */
diff --git a/gcc/lto-section-names.h b/gcc/lto-section-names.h
new file mode 100644
index 00000000000..19a992d0b63
--- /dev/null
+++ b/gcc/lto-section-names.h
@@ -0,0 +1,28 @@
+/* Definitions for LTO section names.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* The string that is the prefix on the section names we make for lto.
+ For decls the DECL_ASSEMBLER_NAME is appended to make the section
+ name for the functions and static_initializers. For other types of
+ sections a '.' and the section type are appended. */
+#define LTO_SECTION_NAME_PREFIX ".gnu.lto_"
+
+/* Segment name for LTO sections. This is only used for Mach-O. */
+
+#define LTO_SEGMENT_NAME "__GNU_LTO"
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index d0c86626c66..a18c64e060d 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -279,7 +279,7 @@ lto_input_eh_catch_list (struct lto_input_block *ib, struct data_in *data_in,
lto_tag_check_range (tag, LTO_eh_catch, LTO_eh_catch);
/* Read the catch node. */
- n = ggc_alloc_cleared_eh_catch_d ();
+ n = ggc_cleared_alloc<eh_catch_d> ();
n->type_list = stream_read_tree (ib, data_in);
n->filter_list = stream_read_tree (ib, data_in);
n->label = stream_read_tree (ib, data_in);
@@ -319,7 +319,7 @@ input_eh_region (struct lto_input_block *ib, struct data_in *data_in, int ix)
if (tag == LTO_null)
return NULL;
- r = ggc_alloc_cleared_eh_region_d ();
+ r = ggc_cleared_alloc<eh_region_d> ();
r->index = streamer_read_hwi (ib);
gcc_assert (r->index == ix);
@@ -396,7 +396,7 @@ input_eh_lp (struct lto_input_block *ib, struct data_in *data_in, int ix)
lto_tag_check_range (tag, LTO_eh_landing_pad, LTO_eh_landing_pad);
- lp = ggc_alloc_cleared_eh_landing_pad_d ();
+ lp = ggc_cleared_alloc<eh_landing_pad_d> ();
lp->index = streamer_read_hwi (ib);
gcc_assert (lp->index == ix);
lp->next_lp = (eh_landing_pad) (intptr_t) streamer_read_hwi (ib);
@@ -697,7 +697,7 @@ input_cfg (struct lto_input_block *ib, struct data_in *data_in,
if (n_loops == 0)
return;
- struct loops *loops = ggc_alloc_cleared_loops ();
+ struct loops *loops = ggc_cleared_alloc<struct loops> ();
init_loops_structure (fn, loops, n_loops);
set_loops_for_fn (fn, loops);
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 6f2bf9c307d..64e4f4b4530 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-streamer.h"
#include "streamer-hooks.h"
#include "cfgloop.h"
+#include "builtins.h"
static void lto_write_tree (struct output_block*, tree, bool);
@@ -535,7 +536,6 @@ DFS_write_tree_body (struct output_block *ob,
if (DECL_ASSEMBLER_NAME_SET_P (expr))
DFS_follow_tree_edge (DECL_ASSEMBLER_NAME (expr));
DFS_follow_tree_edge (DECL_SECTION_NAME (expr));
- DFS_follow_tree_edge (DECL_COMDAT_GROUP (expr));
}
if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
@@ -974,7 +974,6 @@ hash_tree (struct streamer_tree_cache_d *cache, tree t)
if (DECL_ASSEMBLER_NAME_SET_P (t))
visit (DECL_ASSEMBLER_NAME (t));
visit (DECL_SECTION_NAME (t));
- visit (DECL_COMDAT_GROUP (t));
}
if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
@@ -2243,7 +2242,7 @@ write_symbol (struct streamer_tree_cache_d *cache,
enum gcc_plugin_symbol_kind kind;
enum gcc_plugin_symbol_visibility visibility;
unsigned slot_num;
- unsigned HOST_WIDEST_INT size;
+ uint64_t size;
const char *comdat;
unsigned char c;
@@ -2331,7 +2330,7 @@ write_symbol (struct streamer_tree_cache_d *cache,
size = 0;
if (DECL_ONE_ONLY (t))
- comdat = IDENTIFIER_POINTER (DECL_COMDAT_GROUP (t));
+ comdat = IDENTIFIER_POINTER (decl_comdat_group_id (t));
else
comdat = "";
diff --git a/gcc/lto-streamer.c b/gcc/lto-streamer.c
index e94b7873892..a352adfe948 100644
--- a/gcc/lto-streamer.c
+++ b/gcc/lto-streamer.c
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "tree-streamer.h"
#include "lto-streamer.h"
+#include "lto-section-names.h"
#include "streamer-hooks.h"
/* Statistics gathered during LTO, WPA and LTRANS. */
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index ca664658589..521d78dacc9 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -134,12 +134,6 @@ along with GCC; see the file COPYING3. If not see
String are represented in the table as pairs, a length in ULEB128
form followed by the data for the string. */
-/* The string that is the prefix on the section names we make for lto.
- For decls the DECL_ASSEMBLER_NAME is appended to make the section
- name for the functions and static_initializers. For other types of
- sections a '.' and the section type are appended. */
-#define LTO_SECTION_NAME_PREFIX ".gnu.lto_"
-
#define LTO_major_version 4
#define LTO_minor_version 0
diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index fd604b0bdb1..f59d74e4fa5 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -46,13 +46,7 @@ along with GCC; see the file COPYING3. If not see
#include "opts.h"
#include "options.h"
#include "simple-object.h"
-
-/* From lto-streamer.h which we cannot include with -fkeep-inline-functions.
- ??? Split out a lto-streamer-core.h. */
-
-#define LTO_SECTION_NAME_PREFIX ".gnu.lto_"
-
-/* End of lto-streamer.h copy. */
+#include "lto-section-names.h"
int debug; /* true if -save-temps. */
int verbose; /* true if -v. */
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 038f8a95a52..87a8deafaf1 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,48 @@
+2014-06-02 Andrew MacLeod <amacleod@redhat.com>
+
+ * lto-symtab.c: Include builtins.h.
+
+2014-05-26 Richard Biener <rguenther@suse.de>
+
+ * lto.c (lto_parse_hex): Use int64_t.
+ (lto_resolution_read): Likewise.
+
+2014-05-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * lto.c (read_cgraph_and_symbols): Grow ggc memory after streaming.
+
+2014-05-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * lto-symtab.c (lto_symtab_merge_symbols): Update code setting
+ symtab pointer.
+ * lto.c (compare_tree_sccs_1): Do not compare comdat groups.
+
+2014-05-22 Thomas Schwinge <thomas@codesourcery.com>
+
+ * lto-lang.c (DEF_FUNCTION_TYPE_0, DEF_FUNCTION_TYPE_6)
+ (DEF_FUNCTION_TYPE_7, DEF_FUNCTION_TYPE_8)
+ (DEF_FUNCTION_TYPE_VAR_5): Cosmetic fixes.
+
+2012-05-22 Bernd Schmidt <bernds@codesourcery.com>
+
+ * lto-object.c: Include "lto-section-names.h".
+ (LTO_SEGMENT_NAME): Don't define.
+ * lto.c: Include "lto-section-names.h".
+
+2014-05-17 Jan Hubicka <hubicka@ucw.cz>
+
+ PR lto/61012
+ * lto-symtab.c (lto_symtab_merge_decls_1): Do not ICE on undefined externals
+ mixed with variables.
+
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * lto-tree.h: Don't use variable_size gty attribute.
+ * lto.c (lto_read_in_decl_state): Adjust.
+ (create_subid_section_table): Likewise.
+ (lto_flatten_files): Likewise.
+ (read_cgraph_and_symbols): Likewise.
+
2014-05-06 Kenneth Zadeck <zadeck@naturalbridge.com>
Mike Stump <mikestump@comcast.net>
Richard Sandiford <rdsandiford@googlemail.com>
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index e213e923318..937b7e5753f 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -146,9 +146,12 @@ enum lto_builtin_type
#define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
#define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
#define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME,
-#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) NAME,
-#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) NAME,
-#define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) NAME,
+#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6) NAME,
+#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7) NAME,
+#define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7, ARG8) NAME,
#define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
#define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
#define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
@@ -663,12 +666,15 @@ lto_define_builtins (tree va_list_ref_type_node ATTRIBUTE_UNUSED,
#include "builtin-types.def"
#undef DEF_PRIMITIVE_TYPE
+#undef DEF_FUNCTION_TYPE_0
#undef DEF_FUNCTION_TYPE_1
#undef DEF_FUNCTION_TYPE_2
#undef DEF_FUNCTION_TYPE_3
#undef DEF_FUNCTION_TYPE_4
#undef DEF_FUNCTION_TYPE_5
#undef DEF_FUNCTION_TYPE_6
+#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
#undef DEF_FUNCTION_TYPE_VAR_2
diff --git a/gcc/lto/lto-object.c b/gcc/lto/lto-object.c
index f43fb3a30d6..c406efb3c30 100644
--- a/gcc/lto/lto-object.c
+++ b/gcc/lto/lto-object.c
@@ -32,13 +32,9 @@ along with GCC; see the file COPYING3. If not see
#include "lto.h"
#include "tm.h"
#include "lto-streamer.h"
+#include "lto-section-names.h"
#include "simple-object.h"
-/* Segment name for LTO sections. This is only used for Mach-O.
- FIXME: This needs to be kept in sync with darwin.c. */
-
-#define LTO_SEGMENT_NAME "__GNU_LTO"
-
/* An LTO file wrapped around an simple_object. */
struct lto_simple_object
diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
index 5486e737f76..571b2dd386d 100644
--- a/gcc/lto/lto-symtab.c
+++ b/gcc/lto/lto-symtab.c
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
#include "lto-streamer.h"
#include "ipa-utils.h"
#include "ipa-inline.h"
+#include "builtins.h"
/* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
all edges and removing the old node. */
@@ -447,7 +448,12 @@ lto_symtab_merge_decls_1 (symtab_node *first)
cgraph or a varpool node. */
if (!prevailing)
{
- prevailing = first;
+ for (prevailing = first;
+ prevailing; prevailing = prevailing->next_sharing_asm_name)
+ if (lto_symtab_symbol_p (prevailing))
+ break;
+ if (!prevailing)
+ return;
/* For variables chose with a priority variant with vnode
attached (i.e. from unit where external declaration of
variable is actually used).
@@ -639,7 +645,7 @@ lto_symtab_merge_symbols (void)
&& cnode2 != cnode)
cgraph_remove_node (cnode2);
- symtab_insert_node_to_hashtable (node);
+ node->decl->decl_with_vis.symtab_node = node;
}
}
}
diff --git a/gcc/lto/lto-tree.h b/gcc/lto/lto-tree.h
index b1c3d2a848a..4e3f5d612eb 100644
--- a/gcc/lto/lto-tree.h
+++ b/gcc/lto/lto-tree.h
@@ -28,12 +28,12 @@ struct GTY(()) lang_identifier
struct tree_identifier base;
};
-struct GTY((variable_size)) lang_decl
+struct GTY(()) lang_decl
{
int dummy; /* Added because ggc does not like empty structs. */
};
-struct GTY((variable_size)) lang_type
+struct GTY(()) lang_type
{
int dummy; /* Added because ggc does not like empty structs. */
};
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 4c60521f76a..b8078d58012 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "lto.h"
#include "lto-tree.h"
#include "lto-streamer.h"
+#include "lto-section-names.h"
#include "tree-streamer.h"
#include "splay-tree.h"
#include "lto-partition.h"
@@ -254,7 +255,7 @@ lto_read_in_decl_state (struct data_in *data_in, const uint32_t *data,
for (i = 0; i < LTO_N_DECL_STREAMS; i++)
{
uint32_t size = *data++;
- tree *decls = ggc_alloc_vec_tree (size);
+ tree *decls = ggc_vec_alloc<tree> (size);
for (j = 0; j < size; j++)
decls[j] = streamer_tree_cache_get_tree (data_in->reader_cache, data[j]);
@@ -1539,7 +1540,6 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
compare_tree_edges (DECL_ASSEMBLER_NAME (t1),
DECL_ASSEMBLER_NAME (t2));
compare_tree_edges (DECL_SECTION_NAME (t1), DECL_SECTION_NAME (t2));
- compare_tree_edges (DECL_COMDAT_GROUP (t1), DECL_COMDAT_GROUP (t2));
}
if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
@@ -2012,10 +2012,10 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
/* Custom version of strtoll, which is not portable. */
-static HOST_WIDEST_INT
+static int64_t
lto_parse_hex (const char *p)
{
- HOST_WIDEST_INT ret = 0;
+ int64_t ret = 0;
for (; *p != '\0'; ++p)
{
@@ -2067,7 +2067,7 @@ lto_resolution_read (splay_tree file_ids, FILE *resolution, lto_file *file)
{
int t;
char offset_p[17];
- HOST_WIDEST_INT offset;
+ int64_t offset;
t = fscanf (resolution, "@0x%16s", offset_p);
if (t != 1)
internal_error ("could not parse file offset");
@@ -2169,7 +2169,7 @@ create_subid_section_table (struct lto_section_slot *ls, splay_tree file_ids,
}
else
{
- file_data = ggc_alloc_lto_file_decl_data ();
+ file_data = ggc_alloc<lto_file_decl_data> ();
memset(file_data, 0, sizeof (struct lto_file_decl_data));
file_data->id = id;
file_data->section_hash_table = lto_obj_create_section_hash_table ();;
@@ -2870,7 +2870,7 @@ lto_flatten_files (struct lto_file_decl_data **orig, int count, int last_file_ix
lto_stats.num_input_files = count;
all_file_decl_data
- = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (count + 1);
+ = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (count + 1);
/* Set the hooks so that all of the ipa passes can read in their data. */
lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data);
for (i = 0, k = 0; i < last_file_ix; i++)
@@ -2913,7 +2913,7 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
timevar_push (TV_IPA_LTO_DECL_IN);
real_file_decl_data
- = decl_data = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (nfiles + 1);
+ = decl_data = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (nfiles + 1);
real_file_count = nfiles;
/* Read the resolution file. */
@@ -3011,6 +3011,10 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
gimple_canonical_types = NULL;
delete canonical_type_hash_cache;
canonical_type_hash_cache = NULL;
+
+ /* At this stage we know that majority of GGC memory is reachable.
+ Growing the limits prevents unnecesary invocation of GGC. */
+ ggc_grow ();
ggc_collect ();
/* Set the hooks so that all of the ipa passes can read in their data. */
diff --git a/gcc/mcf.c b/gcc/mcf.c
index 9a766399e32..709092352f0 100644
--- a/gcc/mcf.c
+++ b/gcc/mcf.c
@@ -51,7 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "dumpfile.h"
/* CAP_INFINITY: Constant to represent infinite capacity. */
-#define CAP_INFINITY INTTYPE_MAXIMUM (HOST_WIDEST_INT)
+#define CAP_INFINITY INTTYPE_MAXIMUM (int64_t)
/* COST FUNCTION. */
#define K_POS(b) ((b))
@@ -203,12 +203,12 @@ dump_fixup_edge (FILE *file, fixup_graph_type *fixup_graph, fixup_edge_p fedge)
if (fedge->type)
{
- fprintf (file, "flow/capacity=" HOST_WIDEST_INT_PRINT_DEC "/",
+ fprintf (file, "flow/capacity=%"PRId64 "/",
fedge->flow);
if (fedge->max_capacity == CAP_INFINITY)
fputs ("+oo,", file);
else
- fprintf (file, "" HOST_WIDEST_INT_PRINT_DEC ",", fedge->max_capacity);
+ fprintf (file, "%"PRId64 ",", fedge->max_capacity);
}
if (fedge->is_rflow_valid)
@@ -216,10 +216,10 @@ dump_fixup_edge (FILE *file, fixup_graph_type *fixup_graph, fixup_edge_p fedge)
if (fedge->rflow == CAP_INFINITY)
fputs (" rflow=+oo.", file);
else
- fprintf (file, " rflow=" HOST_WIDEST_INT_PRINT_DEC ",", fedge->rflow);
+ fprintf (file, " rflow=%"PRId64 ",", fedge->rflow);
}
- fprintf (file, " cost=" HOST_WIDEST_INT_PRINT_DEC ".", fedge->cost);
+ fprintf (file, " cost=%"PRId64 ".", fedge->cost);
fprintf (file, "\t(%d->%d)", fedge->src, fedge->dest);
@@ -626,9 +626,9 @@ create_fixup_graph (fixup_graph_type *fixup_graph)
if (dump_file)
{
fprintf (dump_file, "\nAdjust supply and demand:\n");
- fprintf (dump_file, "supply_value=" HOST_WIDEST_INT_PRINT_DEC "\n",
+ fprintf (dump_file, "supply_value=%"PRId64 "\n",
supply_value);
- fprintf (dump_file, "demand_value=" HOST_WIDEST_INT_PRINT_DEC "\n",
+ fprintf (dump_file, "demand_value=%"PRId64 "\n",
demand_value);
}
@@ -898,10 +898,10 @@ cancel_negative_cycle (fixup_graph_type *fixup_graph,
{
fprintf (dump_file, "%d", cycle[k]);
fprintf (dump_file,
- ": (" HOST_WIDEST_INT_PRINT_DEC ", " HOST_WIDEST_INT_PRINT_DEC
+ ": (%"PRId64 ", %"PRId64
")\n", sum_cost, cycle_flow);
fprintf (dump_file,
- "Augment cycle with " HOST_WIDEST_INT_PRINT_DEC "\n",
+ "Augment cycle with %"PRId64 "\n",
cycle_flow);
}
@@ -1093,10 +1093,10 @@ find_max_flow (fixup_graph_type *fixup_graph, int source, int sink)
fprintf (dump_file, "<-");
}
fprintf (dump_file,
- "ENTRY (path_capacity=" HOST_WIDEST_INT_PRINT_DEC ")\n",
+ "ENTRY (path_capacity=%"PRId64 ")\n",
increment);
fprintf (dump_file,
- "Network flow is " HOST_WIDEST_INT_PRINT_DEC ".\n",
+ "Network flow is %"PRId64 ".\n",
max_flow);
}
}
@@ -1133,7 +1133,7 @@ adjust_cfg_counts (fixup_graph_type *fixup_graph)
/* Fixup BB. */
if (dump_file)
fprintf (dump_file,
- "BB%d: " HOST_WIDEST_INT_PRINT_DEC "", bb->index, bb->count);
+ "BB%d: %"PRId64 "", bb->index, bb->count);
pfedge = find_fixup_edge (fixup_graph, i, i + 1);
if (pfedge->flow)
@@ -1141,7 +1141,7 @@ adjust_cfg_counts (fixup_graph_type *fixup_graph)
bb->count += pfedge->flow;
if (dump_file)
{
- fprintf (dump_file, " + " HOST_WIDEST_INT_PRINT_DEC "(",
+ fprintf (dump_file, " + %"PRId64 "(",
pfedge->flow);
print_edge (dump_file, fixup_graph, i, i + 1);
fprintf (dump_file, ")");
@@ -1156,7 +1156,7 @@ adjust_cfg_counts (fixup_graph_type *fixup_graph)
bb->count -= pfedge_n->flow;
if (dump_file)
{
- fprintf (dump_file, " - " HOST_WIDEST_INT_PRINT_DEC "(",
+ fprintf (dump_file, " - %"PRId64 "(",
pfedge_n->flow);
print_edge (dump_file, fixup_graph, i + 1,
pfedge->norm_vertex_index);
@@ -1164,7 +1164,7 @@ adjust_cfg_counts (fixup_graph_type *fixup_graph)
}
}
if (dump_file)
- fprintf (dump_file, " = " HOST_WIDEST_INT_PRINT_DEC "\n", bb->count);
+ fprintf (dump_file, " = %"PRId64 "\n", bb->count);
/* Fixup edge. */
FOR_EACH_EDGE (e, ei, bb->succs)
@@ -1175,7 +1175,7 @@ adjust_cfg_counts (fixup_graph_type *fixup_graph)
j = 2 * e->dest->index;
if (dump_file)
- fprintf (dump_file, "%d->%d: " HOST_WIDEST_INT_PRINT_DEC "",
+ fprintf (dump_file, "%d->%d: %"PRId64 "",
bb->index, e->dest->index, e->count);
pfedge = find_fixup_edge (fixup_graph, i + 1, j);
@@ -1188,7 +1188,7 @@ adjust_cfg_counts (fixup_graph_type *fixup_graph)
e->count += pfedge->flow;
if (dump_file)
{
- fprintf (dump_file, " + " HOST_WIDEST_INT_PRINT_DEC "(",
+ fprintf (dump_file, " + %"PRId64 "(",
pfedge->flow);
print_edge (dump_file, fixup_graph, i + 1, j);
fprintf (dump_file, ")");
@@ -1203,7 +1203,7 @@ adjust_cfg_counts (fixup_graph_type *fixup_graph)
e->count -= pfedge_n->flow;
if (dump_file)
{
- fprintf (dump_file, " - " HOST_WIDEST_INT_PRINT_DEC "(",
+ fprintf (dump_file, " - %"PRId64 "(",
pfedge_n->flow);
print_edge (dump_file, fixup_graph, j,
pfedge->norm_vertex_index);
@@ -1223,7 +1223,7 @@ adjust_cfg_counts (fixup_graph_type *fixup_graph)
if (dump_file)
{
fprintf (dump_file, "(self edge)");
- fprintf (dump_file, " + " HOST_WIDEST_INT_PRINT_DEC "(",
+ fprintf (dump_file, " + %"PRId64 "(",
pfedge_n->flow);
print_edge (dump_file, fixup_graph, i + 1,
pfedge->norm_vertex_index);
@@ -1234,7 +1234,7 @@ adjust_cfg_counts (fixup_graph_type *fixup_graph)
if (bb->count)
e->probability = REG_BR_PROB_BASE * e->count / bb->count;
if (dump_file)
- fprintf (dump_file, " = " HOST_WIDEST_INT_PRINT_DEC "\t(%.1f%%)\n",
+ fprintf (dump_file, " = %"PRId64 "\t(%.1f%%)\n",
e->count, e->probability * 100.0 / REG_BR_PROB_BASE);
}
}
@@ -1287,14 +1287,14 @@ adjust_cfg_counts (fixup_graph_type *fixup_graph)
|| (bb->count != sum_edge_counts (bb->succs)))
{
fprintf (dump_file,
- "BB%d(" HOST_WIDEST_INT_PRINT_DEC ") **INVALID**: ",
+ "BB%d(%"PRId64 ") **INVALID**: ",
bb->index, bb->count);
fprintf (stderr,
- "******** BB%d(" HOST_WIDEST_INT_PRINT_DEC
+ "******** BB%d(%"PRId64
") **INVALID**: \n", bb->index, bb->count);
- fprintf (dump_file, "in_edges=" HOST_WIDEST_INT_PRINT_DEC " ",
+ fprintf (dump_file, "in_edges=%"PRId64 " ",
sum_edge_counts (bb->preds));
- fprintf (dump_file, "out_edges=" HOST_WIDEST_INT_PRINT_DEC "\n",
+ fprintf (dump_file, "out_edges=%"PRId64 "\n",
sum_edge_counts (bb->succs));
}
}
diff --git a/gcc/mode-switching.c b/gcc/mode-switching.c
index 1ae8120ee4d..c06f113328d 100644
--- a/gcc/mode-switching.c
+++ b/gcc/mode-switching.c
@@ -195,13 +195,6 @@ reg_becomes_live (rtx reg, const_rtx setter ATTRIBUTE_UNUSED, void *live)
add_to_hard_reg_set ((HARD_REG_SET *) live, GET_MODE (reg), regno);
}
-/* Make sure if MODE_ENTRY is defined the MODE_EXIT is defined
- and vice versa. */
-#if defined (MODE_ENTRY) != defined (MODE_EXIT)
- #error "Both MODE_ENTRY and MODE_EXIT must be defined"
-#endif
-
-#if defined (MODE_ENTRY) && defined (MODE_EXIT)
/* Split the fallthrough edge to the exit block, so that we can note
that there NORMAL_MODE is required. Return the new block if it's
inserted before the exit block. Otherwise return null. */
@@ -349,9 +342,11 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
for (j = n_entities - 1; j >= 0; j--)
{
int e = entity_map[j];
- int mode = MODE_NEEDED (e, return_copy);
+ int mode =
+ targetm.mode_switching.needed (e, return_copy);
- if (mode != num_modes[e] && mode != MODE_EXIT (e))
+ if (mode != num_modes[e]
+ && mode != targetm.mode_switching.exit (e))
break;
}
if (j >= 0)
@@ -450,7 +445,6 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
return pre_exit;
}
-#endif
/* Find all insns that need a particular mode setting, and insert the
necessary mode switches. Return true if we did work. */
@@ -472,7 +466,8 @@ optimize_mode_switching (void)
int n_entities;
int max_num_modes = 0;
bool emitted ATTRIBUTE_UNUSED = false;
- basic_block post_entry ATTRIBUTE_UNUSED, pre_exit ATTRIBUTE_UNUSED;
+ basic_block post_entry = 0;
+ basic_block pre_exit = 0;
for (e = N_ENTITIES - 1, n_entities = 0; e >= 0; e--)
if (OPTIMIZE_MODE_SWITCHING (e))
@@ -482,9 +477,9 @@ optimize_mode_switching (void)
/* Create the list of segments within each basic block.
If NORMAL_MODE is defined, allow for two extra
blocks split from the entry and exit block. */
-#if defined (MODE_ENTRY) && defined (MODE_EXIT)
- entry_exit_extra = 3;
-#endif
+ if (targetm.mode_switching.entry && targetm.mode_switching.exit)
+ entry_exit_extra = 3;
+
bb_info[n_entities]
= XCNEWVEC (struct bb_info,
last_basic_block_for_fn (cfun) + entry_exit_extra);
@@ -496,12 +491,17 @@ optimize_mode_switching (void)
if (! n_entities)
return 0;
-#if defined (MODE_ENTRY) && defined (MODE_EXIT)
- /* Split the edge from the entry block, so that we can note that
- there NORMAL_MODE is supplied. */
- post_entry = split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
- pre_exit = create_pre_exit (n_entities, entity_map, num_modes);
-#endif
+ /* Make sure if MODE_ENTRY is defined the MODE_EXIT is defined and vice versa. */
+ gcc_assert ((targetm.mode_switching.entry && targetm.mode_switching.exit)
+ || (!targetm.mode_switching.entry && !targetm.mode_switching.exit));
+
+ if (targetm.mode_switching.entry && targetm.mode_switching.exit)
+ {
+ /* Split the edge from the entry block, so that we can note that
+ there NORMAL_MODE is supplied. */
+ post_entry = split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
+ pre_exit = create_pre_exit (n_entities, entity_map, num_modes);
+ }
df_analyze ();
@@ -556,7 +556,7 @@ optimize_mode_switching (void)
{
if (INSN_P (insn))
{
- int mode = MODE_NEEDED (e, insn);
+ int mode = targetm.mode_switching.needed (e, insn);
rtx link;
if (mode != no_mode && mode != last_mode)
@@ -567,9 +567,10 @@ optimize_mode_switching (void)
add_seginfo (info + bb->index, ptr);
bitmap_clear_bit (transp[bb->index], j);
}
-#ifdef MODE_AFTER
- last_mode = MODE_AFTER (e, last_mode, insn);
-#endif
+
+ if (targetm.mode_switching.after)
+ last_mode = targetm.mode_switching.after (e, last_mode, insn);
+
/* Update LIVE_NOW. */
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == REG_DEAD)
@@ -595,30 +596,30 @@ optimize_mode_switching (void)
bitmap_clear_bit (transp[bb->index], j);
}
}
-#if defined (MODE_ENTRY) && defined (MODE_EXIT)
- {
- int mode = MODE_ENTRY (e);
-
- if (mode != no_mode)
- {
- bb = post_entry;
-
- /* By always making this nontransparent, we save
- an extra check in make_preds_opaque. We also
- need this to avoid confusing pre_edge_lcm when
- antic is cleared but transp and comp are set. */
- bitmap_clear_bit (transp[bb->index], j);
-
- /* Insert a fake computing definition of MODE into entry
- blocks which compute no mode. This represents the mode on
- entry. */
- info[bb->index].computing = mode;
+ if (targetm.mode_switching.entry && targetm.mode_switching.exit)
+ {
+ int mode = targetm.mode_switching.entry (e);
- if (pre_exit)
- info[pre_exit->index].seginfo->mode = MODE_EXIT (e);
- }
- }
-#endif /* NORMAL_MODE */
+ if (mode != no_mode)
+ {
+ bb = post_entry;
+
+ /* By always making this nontransparent, we save
+ an extra check in make_preds_opaque. We also
+ need this to avoid confusing pre_edge_lcm when
+ antic is cleared but transp and comp are set. */
+ bitmap_clear_bit (transp[bb->index], j);
+
+ /* Insert a fake computing definition of MODE into entry
+ blocks which compute no mode. This represents the mode on
+ entry. */
+ info[bb->index].computing = mode;
+
+ if (pre_exit)
+ info[pre_exit->index].seginfo->mode =
+ targetm.mode_switching.exit (e);
+ }
+ }
}
kill = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_entities);
@@ -633,7 +634,8 @@ optimize_mode_switching (void)
bitmap_vector_clear (comp, last_basic_block_for_fn (cfun));
for (j = n_entities - 1; j >= 0; j--)
{
- int m = current_mode[j] = MODE_PRIORITY_TO_MODE (entity_map[j], i);
+ int m = current_mode[j] =
+ targetm.mode_switching.priority (entity_map[j], i);
struct bb_info *info = bb_info[j];
FOR_EACH_BB_FN (bb, cfun)
@@ -688,7 +690,7 @@ optimize_mode_switching (void)
rtl_profile_for_edge (eg);
start_sequence ();
- EMIT_MODE_SET (entity_map[j], mode, live_at_edge);
+ targetm.mode_switching.emit (entity_map[j], mode, live_at_edge);
mode_set = get_insns ();
end_sequence ();
default_rtl_profile ();
@@ -736,7 +738,9 @@ optimize_mode_switching (void)
rtl_profile_for_bb (bb);
start_sequence ();
- EMIT_MODE_SET (entity_map[j], ptr->mode, ptr->regs_live);
+ targetm.mode_switching.emit (entity_map[j],
+ ptr->mode,
+ ptr->regs_live);
mode_set = get_insns ();
end_sequence ();
@@ -750,7 +754,7 @@ optimize_mode_switching (void)
point ends up first in the instruction steam.
Because we made sure that NOTE_INSN_BASIC_BLOCK is
only used for initially empty basic blocks, we
- can archive this by appending at the end of
+ can achieve this by appending at the end of
the block. */
emit_insn_after
(mode_set, BB_END (NOTE_BASIC_BLOCK (ptr->insn_ptr)));
@@ -777,12 +781,10 @@ optimize_mode_switching (void)
if (need_commit)
commit_edge_insertions ();
-#if defined (MODE_ENTRY) && defined (MODE_EXIT)
- cleanup_cfg (CLEANUP_NO_INSN_DEL);
-#else
- if (!need_commit && !emitted)
+ if (targetm.mode_switching.entry && targetm.mode_switching.exit)
+ cleanup_cfg (CLEANUP_NO_INSN_DEL);
+ else if (!need_commit && !emitted)
return 0;
-#endif
return 1;
}
diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c
index d3c65c2e78a..16caa8fe64f 100644
--- a/gcc/modulo-sched.c
+++ b/gcc/modulo-sched.c
@@ -396,7 +396,7 @@ doloop_register_get (rtx head ATTRIBUTE_UNUSED, rtx tail ATTRIBUTE_UNUSED)
this constant. Otherwise return 0. */
static rtx
const_iteration_count (rtx count_reg, basic_block pre_header,
- HOST_WIDEST_INT * count)
+ int64_t * count)
{
rtx insn;
rtx head, tail;
@@ -1450,16 +1450,16 @@ sms_schedule (void)
if (profile_info && flag_branch_probabilities)
{
fprintf (dump_file, "SMS loop-count ");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) bb->count);
+ fprintf (dump_file, "%"PRId64,
+ (int64_t) bb->count);
fprintf (dump_file, "\n");
fprintf (dump_file, "SMS trip-count ");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) trip_count);
+ fprintf (dump_file, "%"PRId64,
+ (int64_t) trip_count);
fprintf (dump_file, "\n");
fprintf (dump_file, "SMS profile-sum-max ");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) profile_info->sum_max);
+ fprintf (dump_file, "%"PRId64,
+ (int64_t) profile_info->sum_max);
fprintf (dump_file, "\n");
}
}
@@ -1540,7 +1540,7 @@ sms_schedule (void)
rtx head, tail;
rtx count_reg, count_init;
int mii, rec_mii, stage_count, min_cycle;
- HOST_WIDEST_INT loop_count = 0;
+ int64_t loop_count = 0;
bool opt_sc_p;
if (! (g = g_arr[loop->num]))
@@ -1571,12 +1571,12 @@ sms_schedule (void)
if (profile_info && flag_branch_probabilities)
{
fprintf (dump_file, "SMS loop-count ");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) bb->count);
+ fprintf (dump_file, "%"PRId64,
+ (int64_t) bb->count);
fprintf (dump_file, "\n");
fprintf (dump_file, "SMS profile-sum-max ");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) profile_info->sum_max);
+ fprintf (dump_file, "%"PRId64,
+ (int64_t) profile_info->sum_max);
fprintf (dump_file, "\n");
}
fprintf (dump_file, "SMS doloop\n");
@@ -1602,7 +1602,7 @@ sms_schedule (void)
if (dump_file && count_init)
{
fprintf (dump_file, "SMS const-doloop ");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
+ fprintf (dump_file, "%"PRId64,
loop_count);
fprintf (dump_file, "\n");
}
@@ -1663,9 +1663,9 @@ sms_schedule (void)
fprintf (dump_file, "SMS failed... \n");
fprintf (dump_file, "SMS sched-failed (stage-count=%d,"
" loop-count=", stage_count);
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, loop_count);
+ fprintf (dump_file, "%"PRId64, loop_count);
fprintf (dump_file, ", trip-count=");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, trip_count);
+ fprintf (dump_file, "%"PRId64, trip_count);
fprintf (dump_file, ")\n");
}
break;
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index bcc5b82f97b..73a41b6bcea 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,14 @@
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * objc-act.c (objc_build_string_object): Adjust.
+ (continue_class): Likewise.
+ * objc-act.h (ALLOC_OBJC_TYPE_LANG_SPECIFIC): Likewise.
+ * objc-map.c (objc_map_alloc_ggc): Likewise.
+ (objc_map_private_resize): Likewise.
+ * objc-next-runtime-abi-02.c (objc_next_runtime_abi_02_init):
+ Likewise.
+ (hash_name_enter): Likewise.
+
2014-05-06 Kenneth Zadeck <zadeck@naturalbridge.com>
Mike Stump <mikestump@comcast.net>
Richard Sandiford <rdsandiford@googlemail.com>
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index ff5d1e5d7aa..03b41504c4a 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -3199,7 +3199,7 @@ objc_build_string_object (tree string)
if (!desc)
{
- *loc = desc = ggc_alloc_string_descriptor ();
+ *loc = desc = ggc_alloc<string_descriptor> ();
desc->literal = string;
desc->constructor =
(*runtime.build_const_string_constructor) (input_location, string, length);
@@ -7032,7 +7032,7 @@ continue_class (tree klass)
uprivate_record = CLASS_STATIC_TEMPLATE (implementation_template);
objc_instance_type = build_pointer_type (uprivate_record);
- imp_entry = ggc_alloc_imp_entry ();
+ imp_entry = ggc_alloc<struct imp_entry> ();
imp_entry->next = imp_list;
imp_entry->imp_context = klass;
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 0c7fa0456d3..7e1e265bf08 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -192,8 +192,7 @@ typedef enum objc_property_assign_semantics {
#define SIZEOF_OBJC_TYPE_LANG_SPECIFIC sizeof (struct lang_type)
#define ALLOC_OBJC_TYPE_LANG_SPECIFIC(NODE) \
do { \
- TYPE_LANG_SPECIFIC (NODE) \
- = ggc_alloc_cleared_lang_type (sizeof (struct lang_type)); \
+ TYPE_LANG_SPECIFIC (NODE) = ggc_cleared_alloc<struct lang_type> (); \
} while (0)
#define TYPE_HAS_OBJC_INFO(TYPE) \
diff --git a/gcc/objc/objc-map.c b/gcc/objc/objc-map.c
index 386d2c5f6a8..aaee7295a9f 100644
--- a/gcc/objc/objc-map.c
+++ b/gcc/objc/objc-map.c
@@ -56,7 +56,7 @@ next_power_of_two (size_t x)
objc_map_t
objc_map_alloc_ggc (size_t initial_capacity)
{
- objc_map_t map = (objc_map_t) ggc_internal_cleared_vec_alloc (1, sizeof (struct objc_map_private));
+ objc_map_t map = ggc_cleared_alloc<objc_map_private> ();
if (map == NULL)
OUT_OF_MEMORY;
@@ -67,8 +67,8 @@ objc_map_alloc_ggc (size_t initial_capacity)
map->maximum_load_factor = 70;
map->max_number_of_non_empty_slots = (initial_capacity * map->maximum_load_factor) / 100;
- map->slots = (tree *)ggc_internal_cleared_vec_alloc (initial_capacity, sizeof (tree));
- map->values = (tree *)ggc_internal_cleared_vec_alloc (initial_capacity, sizeof (tree));
+ map->slots = ggc_cleared_vec_alloc<tree> (initial_capacity);
+ map->values = ggc_cleared_vec_alloc<tree> (initial_capacity);
if (map->slots == NULL)
OUT_OF_MEMORY;
@@ -112,8 +112,8 @@ objc_map_private_resize (objc_map_t map, size_t new_number_of_slots)
map->max_number_of_non_empty_slots = (map->number_of_slots * map->maximum_load_factor) / 100;
- map->slots = (tree *)ggc_internal_cleared_vec_alloc (map->number_of_slots, sizeof (tree));
- map->values = (tree *)ggc_internal_cleared_vec_alloc (map->number_of_slots, sizeof (tree));
+ map->slots = ggc_cleared_vec_alloc<tree> (map->number_of_slots);
+ map->values = ggc_cleared_vec_alloc<tree> (map->number_of_slots);
if (map->slots == NULL)
OUT_OF_MEMORY;
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index ee43d2d0ce8..85033a3074c 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -238,7 +238,7 @@ static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
bool
objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
{
- extern_names = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
+ extern_names = ggc_cleared_vec_alloc<hash> (SIZEHASHTABLE);
if (flag_objc_exceptions && flag_objc_sjlj_exceptions)
{
@@ -857,7 +857,7 @@ hash_name_enter (hash *hashlist, tree id)
hash obj;
int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
- obj = ggc_alloc_hashed_entry ();
+ obj = ggc_alloc<hashed_entry> ();
obj->list = 0;
obj->next = hashlist[slot];
obj->key = id;
diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog
index 63b37304887..24711382084 100644
--- a/gcc/objcp/ChangeLog
+++ b/gcc/objcp/ChangeLog
@@ -1,3 +1,7 @@
+2014-05-17 Trevor Saunders <tsaunders@mozilla.com>
+
+ * objcp-decl.h: Adjust.
+
2014-04-14 Paolo Carlini <paolo.carlini@oracle.com>
* objcp-decl.h (OBJC_TYPE_NAME, OBJC_SET_TYPE_NAME): Use
diff --git a/gcc/objcp/objcp-decl.h b/gcc/objcp/objcp-decl.h
index 652f9933895..46eb4f3314c 100644
--- a/gcc/objcp/objcp-decl.h
+++ b/gcc/objcp/objcp-decl.h
@@ -66,8 +66,8 @@ extern tree objcp_end_compound_stmt (tree, int);
#undef ALLOC_OBJC_TYPE_LANG_SPECIFIC
#define ALLOC_OBJC_TYPE_LANG_SPECIFIC(NODE) \
do { \
- TYPE_LANG_SPECIFIC (NODE) = ggc_alloc_cleared_lang_type \
- (sizeof (struct lang_type_class)); \
+ TYPE_LANG_SPECIFIC (NODE) = (struct lang_type *) \
+ ggc_internal_cleared_alloc (sizeof (struct lang_type_class)); \
TYPE_LANG_SPECIFIC (NODE)->u.c.h.is_lang_type_class = 1; \
} while (0)
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 453f580a838..129d513d12c 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -298,7 +298,7 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
int i;
struct omp_for_data_loop dummy_loop;
location_t loc = gimple_location (for_stmt);
- bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_KIND_SIMD;
+ bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
bool distribute = gimple_omp_for_kind (for_stmt)
== GF_OMP_FOR_KIND_DISTRIBUTE;
@@ -1020,7 +1020,7 @@ build_outer_var_ref (tree var, omp_context *ctx)
x = build_receiver_ref (var, by_ref, ctx);
}
else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
- && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
+ && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
{
/* #pragma omp simd isn't a worksharing construct, and can reference even
private vars in its linear etc. clauses. */
@@ -2249,7 +2249,7 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
if (ctx != NULL)
{
if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
- && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
+ && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
{
error_at (gimple_location (stmt),
"OpenMP constructs may not be nested inside simd region");
@@ -2272,7 +2272,7 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
switch (gimple_code (stmt))
{
case GIMPLE_OMP_FOR:
- if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_KIND_SIMD)
+ if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
return true;
if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
{
@@ -2598,7 +2598,7 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
if (setjmp_or_longjmp_p (fndecl)
&& ctx
&& gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
- && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
+ && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
{
remove = true;
error_at (gimple_location (stmt),
@@ -2998,6 +2998,27 @@ lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
return true;
}
+/* Helper function of lower_rec_input_clauses. For a reference
+ in simd reduction, add an underlying variable it will reference. */
+
+static void
+handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
+{
+ tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
+ if (TREE_CONSTANT (z))
+ {
+ const char *name = NULL;
+ if (DECL_NAME (new_vard))
+ name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
+
+ z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
+ gimple_add_tmp_var (z);
+ TREE_ADDRESSABLE (z) = 1;
+ z = build_fold_addr_expr_loc (loc, z);
+ gimplify_assign (new_vard, z, ilist);
+ }
+}
+
/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
from the receiver (aka child) side and initializers for REFERENCE_TYPE
private variables. Initialization statements go in ILIST, while calls
@@ -3013,7 +3034,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bool reduction_omp_orig_ref = false;
int pass;
bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
- && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD);
+ && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
int max_vf = 0;
tree lane = NULL_TREE, idx = NULL_TREE;
tree ivar = NULL_TREE, lvar = NULL_TREE;
@@ -3189,13 +3210,11 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
}
else if (TREE_CONSTANT (x))
{
- /* For reduction with placeholder in SIMD loop,
- defer adding the initialization of the reference,
- because if we decide to use SIMD array for it,
- the initilization could cause expansion ICE. */
- if (c_kind == OMP_CLAUSE_REDUCTION
- && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
- && is_simd)
+ /* For reduction in SIMD loop, defer adding the
+ initialization of the reference, because if we decide
+ to use SIMD array for it, the initilization could cause
+ expansion ICE. */
+ if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
x = NULL_TREE;
else
{
@@ -3405,8 +3424,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
= gimple_build_assign (unshare_expr (lvar), iv);
gsi_insert_before_without_update (&gsi, g,
GSI_SAME_STMT);
- tree stept = POINTER_TYPE_P (TREE_TYPE (x))
- ? sizetype : TREE_TYPE (x);
+ tree stept = POINTER_TYPE_P (TREE_TYPE (iv))
+ ? sizetype : TREE_TYPE (iv);
tree t = fold_convert (stept,
OMP_CLAUSE_LINEAR_STEP (c));
enum tree_code code = PLUS_EXPR;
@@ -3524,23 +3543,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
But if they aren't used, we need to emit the deferred
initialization now. */
else if (is_reference (var) && is_simd)
- {
- tree z
- = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
- if (TREE_CONSTANT (z))
- {
- const char *name = NULL;
- if (DECL_NAME (var))
- name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
-
- z = create_tmp_var_raw
- (TREE_TYPE (TREE_TYPE (new_vard)), name);
- gimple_add_tmp_var (z);
- TREE_ADDRESSABLE (z) = 1;
- z = build_fold_addr_expr_loc (clause_loc, z);
- gimplify_assign (new_vard, z, ilist);
- }
- }
+ handle_simd_reference (clause_loc, new_vard, ilist);
x = lang_hooks.decls.omp_clause_default_ctor
(c, new_var, unshare_expr (x));
if (x)
@@ -3573,6 +3576,13 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (code == MINUS_EXPR)
code = PLUS_EXPR;
+ tree new_vard = new_var;
+ if (is_simd && is_reference (var))
+ {
+ gcc_assert (TREE_CODE (new_var) == MEM_REF);
+ new_vard = TREE_OPERAND (new_var, 0);
+ gcc_assert (DECL_P (new_vard));
+ }
if (is_simd
&& lower_rec_simd_input_clauses (new_var, ctx, max_vf,
idx, lane, ivar, lvar))
@@ -3584,9 +3594,18 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
x = build2 (code, TREE_TYPE (ref), ref, ivar);
ref = build_outer_var_ref (var, ctx);
gimplify_assign (ref, x, &llist[1]);
+
+ if (new_vard != new_var)
+ {
+ SET_DECL_VALUE_EXPR (new_vard,
+ build_fold_addr_expr (lvar));
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
+ }
}
else
{
+ if (is_reference (var) && is_simd)
+ handle_simd_reference (clause_loc, new_vard, ilist);
gimplify_assign (new_var, x, ilist);
if (is_simd)
{
@@ -3755,7 +3774,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
}
if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
- && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
+ && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
{
simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
if (simduid)
@@ -3858,7 +3877,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
/* SIMD reductions are handled in lower_rec_input_clauses. */
if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
- && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_KIND_SIMD)
+ && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
return;
/* First see if there is exactly one reduction clause. Use OMP_ATOMIC
@@ -4227,8 +4246,6 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
(cond != 0) or (cond ? val : 1u). */
if (cond)
{
- gimple_stmt_iterator gsi;
-
cond = gimple_boolify (cond);
if (integer_zerop (val))
@@ -4672,7 +4689,6 @@ expand_omp_taskreg (struct omp_region *region)
the region, in which case all we need to do is make the
sub-graph unreachable and emit the parallel call. */
edge entry_succ_e, exit_succ_e;
- gimple_stmt_iterator gsi;
entry_succ_e = single_succ_edge (entry_bb);
@@ -4709,7 +4725,6 @@ expand_omp_taskreg (struct omp_region *region)
if (gimple_omp_taskreg_data_arg (entry_stmt))
{
basic_block entry_succ_bb = single_succ (entry_bb);
- gimple_stmt_iterator gsi;
tree arg, narg;
gimple parcopy_stmt = NULL;
@@ -6151,10 +6166,10 @@ expand_omp_for_static_chunk (struct omp_region *region,
{
tree n, s0, e0, e, t;
tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
- tree type, itype, v_main, v_back, v_extra;
+ tree type, itype, vmain, vback, vextra;
basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
- gimple_stmt_iterator si;
+ gimple_stmt_iterator gsi;
gimple stmt;
edge se;
enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
@@ -6187,8 +6202,8 @@ expand_omp_for_static_chunk (struct omp_region *region,
exit_bb = region->exit;
/* Trip and adjustment setup goes in ENTRY_BB. */
- si = gsi_last_bb (entry_bb);
- gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
+ gsi = gsi_last_bb (entry_bb);
+ gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
{
@@ -6202,7 +6217,7 @@ expand_omp_for_static_chunk (struct omp_region *region,
basic_block l2_dom_bb = NULL;
counts = XALLOCAVEC (tree, fd->collapse);
- expand_omp_for_init_counts (fd, &si, entry_bb, counts,
+ expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
fin_bb, first_zero_iter,
l2_dom_bb);
t = NULL_TREE;
@@ -6218,21 +6233,21 @@ expand_omp_for_static_chunk (struct omp_region *region,
&& (t == NULL_TREE || !integer_onep (t)))
{
n1 = fold_convert (type, unshare_expr (fd->loop.n1));
- n1 = force_gimple_operand_gsi (&si, n1, true, NULL_TREE,
+ n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
true, GSI_SAME_STMT);
n2 = fold_convert (type, unshare_expr (fd->loop.n2));
- n2 = force_gimple_operand_gsi (&si, n2, true, NULL_TREE,
+ n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
true, GSI_SAME_STMT);
stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
NULL_TREE, NULL_TREE);
- gsi_insert_before (&si, stmt, GSI_SAME_STMT);
+ gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
if (walk_tree (gimple_cond_lhs_ptr (stmt),
expand_omp_regimplify_p, NULL, NULL)
|| walk_tree (gimple_cond_rhs_ptr (stmt),
expand_omp_regimplify_p, NULL, NULL))
{
- si = gsi_for_stmt (stmt);
- gimple_regimplify_operands (stmt, &si);
+ gsi = gsi_for_stmt (stmt);
+ gimple_regimplify_operands (stmt, &gsi);
}
se = split_block (entry_bb, stmt);
se->flags = EDGE_TRUE_VALUE;
@@ -6243,25 +6258,25 @@ expand_omp_for_static_chunk (struct omp_region *region,
if (gimple_in_ssa_p (cfun))
{
int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
- for (si = gsi_start_phis (fin_bb);
- !gsi_end_p (si); gsi_next (&si))
+ for (gsi = gsi_start_phis (fin_bb);
+ !gsi_end_p (gsi); gsi_next (&gsi))
{
- gimple phi = gsi_stmt (si);
+ gimple phi = gsi_stmt (gsi);
add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
se, UNKNOWN_LOCATION);
}
}
- si = gsi_last_bb (entry_bb);
+ gsi = gsi_last_bb (entry_bb);
}
t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
t = fold_convert (itype, t);
- nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
+ nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
true, GSI_SAME_STMT);
t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
t = fold_convert (itype, t);
- threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
+ threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
true, GSI_SAME_STMT);
n1 = fd->loop.n1;
@@ -6278,14 +6293,14 @@ expand_omp_for_static_chunk (struct omp_region *region,
gcc_assert (innerc);
n2 = OMP_CLAUSE_DECL (innerc);
}
- n1 = force_gimple_operand_gsi (&si, fold_convert (type, n1),
+ n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
true, NULL_TREE, true, GSI_SAME_STMT);
- n2 = force_gimple_operand_gsi (&si, fold_convert (itype, n2),
+ n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
true, NULL_TREE, true, GSI_SAME_STMT);
- step = force_gimple_operand_gsi (&si, fold_convert (itype, step),
+ step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
true, NULL_TREE, true, GSI_SAME_STMT);
fd->chunk_size
- = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
+ = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
true, NULL_TREE, true, GSI_SAME_STMT);
t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
@@ -6299,7 +6314,7 @@ expand_omp_for_static_chunk (struct omp_region *region,
else
t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
t = fold_convert (itype, t);
- n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
+ n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
true, GSI_SAME_STMT);
trip_var = create_tmp_reg (itype, ".trip");
@@ -6317,7 +6332,7 @@ expand_omp_for_static_chunk (struct omp_region *region,
}
stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
- gsi_insert_before (&si, stmt, GSI_SAME_STMT);
+ gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
t = fold_build2 (MULT_EXPR, itype, t, step);
@@ -6325,31 +6340,31 @@ expand_omp_for_static_chunk (struct omp_region *region,
t = fold_build_pointer_plus (n1, t);
else
t = fold_build2 (PLUS_EXPR, type, t, n1);
- v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
- true, GSI_SAME_STMT);
+ vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
+ true, GSI_SAME_STMT);
/* Remove the GIMPLE_OMP_FOR. */
- gsi_remove (&si, true);
+ gsi_remove (&gsi, true);
/* Iteration space partitioning goes in ITER_PART_BB. */
- si = gsi_last_bb (iter_part_bb);
+ gsi = gsi_last_bb (iter_part_bb);
t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
t = fold_build2 (PLUS_EXPR, itype, t, threadid);
t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
- s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
+ s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
t = fold_build2 (MIN_EXPR, itype, t, n);
- e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
+ e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
t = build2 (LT_EXPR, boolean_type_node, s0, n);
- gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
+ gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
/* Setup code for sequential iteration goes in SEQ_START_BB. */
- si = gsi_start_bb (seq_start_bb);
+ gsi = gsi_start_bb (seq_start_bb);
tree startvar = fd->loop.v;
tree endvar = NULL_TREE;
@@ -6375,12 +6390,12 @@ expand_omp_for_static_chunk (struct omp_region *region,
else
t = fold_build2 (PLUS_EXPR, type, t, n1);
t = fold_convert (TREE_TYPE (startvar), t);
- t = force_gimple_operand_gsi (&si, t,
+ t = force_gimple_operand_gsi (&gsi, t,
DECL_P (startvar)
&& TREE_ADDRESSABLE (startvar),
NULL_TREE, false, GSI_CONTINUE_LINKING);
stmt = gimple_build_assign (startvar, t);
- gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
+ gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
t = fold_convert (itype, e0);
t = fold_build2 (MULT_EXPR, itype, t, step);
@@ -6389,73 +6404,73 @@ expand_omp_for_static_chunk (struct omp_region *region,
else
t = fold_build2 (PLUS_EXPR, type, t, n1);
t = fold_convert (TREE_TYPE (startvar), t);
- e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
+ e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
if (endvar)
{
stmt = gimple_build_assign (endvar, e);
- gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
+ gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
stmt = gimple_build_assign (fd->loop.v, e);
else
stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e,
NULL_TREE);
- gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
+ gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
}
if (fd->collapse > 1)
- expand_omp_for_init_vars (fd, &si, counts, inner_stmt, startvar);
+ expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
if (!broken_loop)
{
/* The code controlling the sequential loop goes in CONT_BB,
replacing the GIMPLE_OMP_CONTINUE. */
- si = gsi_last_bb (cont_bb);
- stmt = gsi_stmt (si);
+ gsi = gsi_last_bb (cont_bb);
+ stmt = gsi_stmt (gsi);
gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
- v_main = gimple_omp_continue_control_use (stmt);
- v_back = gimple_omp_continue_control_def (stmt);
+ vmain = gimple_omp_continue_control_use (stmt);
+ vback = gimple_omp_continue_control_def (stmt);
if (!gimple_omp_for_combined_p (fd->for_stmt))
{
if (POINTER_TYPE_P (type))
- t = fold_build_pointer_plus (v_main, step);
+ t = fold_build_pointer_plus (vmain, step);
else
- t = fold_build2 (PLUS_EXPR, type, v_main, step);
- if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
- t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
+ t = fold_build2 (PLUS_EXPR, type, vmain, step);
+ if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
+ t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
true, GSI_SAME_STMT);
- stmt = gimple_build_assign (v_back, t);
- gsi_insert_before (&si, stmt, GSI_SAME_STMT);
+ stmt = gimple_build_assign (vback, t);
+ gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
t = build2 (fd->loop.cond_code, boolean_type_node,
- DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
- ? t : v_back, e);
- gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
+ DECL_P (vback) && TREE_ADDRESSABLE (vback)
+ ? t : vback, e);
+ gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
}
/* Remove GIMPLE_OMP_CONTINUE. */
- gsi_remove (&si, true);
+ gsi_remove (&gsi, true);
if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
/* Trip update code goes into TRIP_UPDATE_BB. */
- si = gsi_start_bb (trip_update_bb);
+ gsi = gsi_start_bb (trip_update_bb);
t = build_int_cst (itype, 1);
t = build2 (PLUS_EXPR, itype, trip_main, t);
stmt = gimple_build_assign (trip_back, t);
- gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
+ gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
}
/* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
- si = gsi_last_bb (exit_bb);
- if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
+ gsi = gsi_last_bb (exit_bb);
+ if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
{
- t = gimple_omp_return_lhs (gsi_stmt (si));
- gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
+ t = gimple_omp_return_lhs (gsi_stmt (gsi));
+ gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
}
- gsi_remove (&si, true);
+ gsi_remove (&gsi, true);
/* Connect the new blocks. */
find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
@@ -6517,9 +6532,9 @@ expand_omp_for_static_chunk (struct omp_region *region,
locus = gimple_phi_arg_location_from_edge (phi, se);
/* A special case -- fd->loop.v is not yet computed in
- iter_part_bb, we need to use v_extra instead. */
+ iter_part_bb, we need to use vextra instead. */
if (t == fd->loop.v)
- t = v_extra;
+ t = vextra;
add_phi_arg (nphi, t, ene, locus);
locus = redirect_edge_var_map_location (vm);
add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
@@ -6910,7 +6925,7 @@ expand_omp_for (struct omp_region *region, gimple inner_stmt)
original loops from being detected. Fix that up. */
loops_state_set (LOOPS_NEED_FIXUP);
- if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_KIND_SIMD)
+ if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
expand_omp_simd (region, &fd);
else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
&& !fd.have_ordered)
@@ -8416,10 +8431,14 @@ maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
&& gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
&& ctx->outer->cancellable)
{
- tree lhs = create_tmp_var (boolean_type_node, NULL);
+ tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
+ tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
+ tree lhs = create_tmp_var (c_bool_type, NULL);
gimple_omp_return_set_lhs (omp_return, lhs);
tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
- gimple g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
+ gimple g = gimple_build_cond (NE_EXPR, lhs,
+ fold_convert (c_bool_type,
+ boolean_false_node),
ctx->outer->cancel_label, fallthru_label);
gimple_seq_add_stmt (body, g);
gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
@@ -10125,21 +10144,23 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
}
break;
}
- tree lhs;
- lhs = create_tmp_var (boolean_type_node, NULL);
if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
{
fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
gimple_call_set_fndecl (stmt, fndecl);
gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
}
+ tree lhs;
+ lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
gimple_call_set_lhs (stmt, lhs);
tree fallthru_label;
fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
gimple g;
g = gimple_build_label (fallthru_label);
gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
- g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
+ g = gimple_build_cond (NE_EXPR, lhs,
+ fold_convert (TREE_TYPE (lhs),
+ boolean_false_node),
cctx->cancel_label, fallthru_label);
gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
break;
diff --git a/gcc/optabs.c b/gcc/optabs.c
index abc36ed41f8..ca1c1945c37 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -228,7 +228,7 @@ add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
return 0;
}
- set = single_set (last_insn);
+ set = set_for_reg_notes (last_insn);
if (set == NULL_RTX)
return 1;
@@ -297,6 +297,25 @@ widened_mode (enum machine_mode to_mode, rtx op0, rtx op1)
return result;
}
+/* Like optab_handler, but for widening_operations that have a
+ TO_MODE and a FROM_MODE. */
+
+enum insn_code
+widening_optab_handler (optab op, enum machine_mode to_mode,
+ enum machine_mode from_mode)
+{
+ unsigned scode = (op << 16) | to_mode;
+ if (to_mode != from_mode && from_mode != VOIDmode)
+ {
+ /* ??? Why does find_widening_optab_handler_and_mode attempt to
+ widen things that can't be widened? E.g. add_optab... */
+ if (op > LAST_CONV_OPTAB)
+ return CODE_FOR_nothing;
+ scode |= from_mode << 8;
+ }
+ return raw_optab_handler (scode);
+}
+
/* Find a widening optab even if it doesn't widen as much as we want.
E.g. if from_mode is HImode, and to_mode is DImode, and there is no
direct HI->SI insn, then return SI->DI, if that exists.
@@ -6153,7 +6172,7 @@ set_optab_libfunc (optab op, enum machine_mode mode, const char *name)
val = 0;
slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
if (*slot == NULL)
- *slot = ggc_alloc_libfunc_entry ();
+ *slot = ggc_alloc<libfunc_entry> ();
(*slot)->op = op;
(*slot)->mode1 = mode;
(*slot)->mode2 = VOIDmode;
@@ -6181,7 +6200,7 @@ set_conv_libfunc (convert_optab optab, enum machine_mode tmode,
val = 0;
slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
if (*slot == NULL)
- *slot = ggc_alloc_libfunc_entry ();
+ *slot = ggc_alloc<libfunc_entry> ();
(*slot)->op = optab;
(*slot)->mode1 = tmode;
(*slot)->mode2 = fmode;
@@ -6274,8 +6293,7 @@ init_tree_optimization_optabs (tree optnode)
if (tmp_optabs)
memset (tmp_optabs, 0, sizeof (struct target_optabs));
else
- tmp_optabs = (struct target_optabs *)
- ggc_alloc_atomic (sizeof (struct target_optabs));
+ tmp_optabs = ggc_alloc<target_optabs> ();
/* Generate a new set of optabs into tmp_optabs. */
init_all_optabs (tmp_optabs);
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 8ecaa41f1dd..089b15a6fcd 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -144,6 +144,8 @@ extern enum insn_code find_widening_optab_handler_and_mode (optab,
enum machine_mode,
int,
enum machine_mode *);
+extern enum insn_code widening_optab_handler (optab, enum machine_mode,
+ enum machine_mode);
/* An extra flag to control optab_for_tree_code's behavior. This is needed to
distinguish between machines with a vector shift that takes a scalar for the
@@ -275,25 +277,6 @@ convert_optab_handler (convert_optab op, enum machine_mode to_mode,
return raw_optab_handler (scode);
}
-/* Like optab_handler, but for widening_operations that have a
- TO_MODE and a FROM_MODE. */
-
-static inline enum insn_code
-widening_optab_handler (optab op, enum machine_mode to_mode,
- enum machine_mode from_mode)
-{
- unsigned scode = (op << 16) | to_mode;
- if (to_mode != from_mode && from_mode != VOIDmode)
- {
- /* ??? Why does find_widening_optab_handler_and_mode attempt to
- widen things that can't be widened? E.g. add_optab... */
- if (op > LAST_CONV_OPTAB)
- return CODE_FOR_nothing;
- scode |= from_mode << 8;
- }
- return raw_optab_handler (scode);
-}
-
/* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
if the target does not have such an insn. */
diff --git a/gcc/optc-gen.awk b/gcc/optc-gen.awk
index a091b72af4b..b70e4fe3aad 100644
--- a/gcc/optc-gen.awk
+++ b/gcc/optc-gen.awk
@@ -406,11 +406,13 @@ for (i = 0; i < n_enabledby; i++) {
if (opt_var_name != "") {
condition = "!opts_set->x_" opt_var_name
if (thisenableif[j] != "") {
- condition = condition " && (" thisenableif[j] ")"
+ value = "(" thisenableif[j] ")"
+ } else {
+ value = "value"
}
print " if (" condition ")"
print " handle_generated_option (opts, opts_set,"
- print " " opt_enum(thisenable[j]) ", NULL, value,"
+ print " " opt_enum(thisenable[j]) ", NULL, " value ","
print " lang_mask, kind, loc, handlers, dc);"
} else {
print "#error " thisenable[j] " does not have a Var() flag"
diff --git a/gcc/opts.c b/gcc/opts.c
index f15852d69a0..2b1280a76ff 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -497,6 +497,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_foptimize_strlen, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fhoist_adjacent_loads, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fisolate_erroneous_paths_dereference, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fuse_caller_save, NULL, 1 },
/* -O3 optimizations. */
{ OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
@@ -857,9 +858,9 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
maybe_set_param_value (PARAM_MAX_STORES_TO_SINK, 0,
opts->x_param_values, opts_set->x_param_values);
- /* The -gsplit-dwarf option requires -gpubnames. */
+ /* The -gsplit-dwarf option requires -ggnu-pubnames. */
if (opts->x_dwarf_split_debug_info)
- opts->x_debug_generate_pub_sections = 1;
+ opts->x_debug_generate_pub_sections = 2;
}
#define LEFT_COLUMN 27
@@ -1463,6 +1464,8 @@ common_handle_option (struct gcc_options *opts,
{ "enum", SANITIZE_ENUM, sizeof "enum" - 1 },
{ "float-divide-by-zero", SANITIZE_FLOAT_DIVIDE,
sizeof "float-divide-by-zero" - 1 },
+ { "float-cast-overflow", SANITIZE_FLOAT_CAST,
+ sizeof "float-cast-overflow" - 1 },
{ NULL, 0, 0 }
};
const char *comma;
@@ -1814,13 +1817,8 @@ common_handle_option (struct gcc_options *opts,
break;
case OPT_g:
- /* -g by itself should force -g2. */
- if (*arg == '\0')
- set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, "2", opts, opts_set,
- loc);
- else
- set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set,
- loc);
+ set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set,
+ loc);
break;
case OPT_gcoff:
@@ -2070,10 +2068,12 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg,
opts_set->x_write_symbols = type;
}
- /* A debug flag without a level defaults to level 2. */
+ /* A debug flag without a level defaults to level 2.
+ If off or at level 1, set it to level 2, but if already
+ at level 3, don't lower it. */
if (*arg == '\0')
{
- if (!opts->x_debug_info_level)
+ if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL)
opts->x_debug_info_level = DINFO_LEVEL_NORMAL;
}
else
diff --git a/gcc/params.def b/gcc/params.def
index f51c29a48e2..b24071da751 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -986,6 +986,12 @@ DEFPARAM (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS,
"index known.",
48, 0, 0)
+DEFPARAM (PARAM_IPA_MAX_AA_STEPS,
+ "ipa-max-aa-steps",
+ "Maximum number of statements that will be visited by IPA formal "
+ "parameter analysis based on alias analysis in any given function",
+ 25000, 0, 0)
+
/* WHOPR partitioning configuration. */
DEFPARAM (PARAM_LTO_PARTITIONS,
diff --git a/gcc/passes.c b/gcc/passes.c
index 223b693d2cf..43662513e9a 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -1532,7 +1532,7 @@ do_per_function_toporder (void (*callback) (function *, void *data), void *data)
else
{
gcc_assert (!order);
- order = ggc_alloc_vec_cgraph_node_ptr (cgraph_n_nodes);
+ order = ggc_vec_alloc<cgraph_node_ptr> (cgraph_n_nodes);
nnodes = ipa_reverse_postorder (order);
for (i = nnodes - 1; i >= 0; i--)
order[i]->process = 1;
diff --git a/gcc/passes.def b/gcc/passes.def
index 506b65789f6..2f889e88905 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -110,6 +110,10 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_ipa_inline);
NEXT_PASS (pass_ipa_pure_const);
NEXT_PASS (pass_ipa_reference);
+ /* Comdat privatization come last, as direct references to comdat local
+ symbols are not allowed outside of the comdat group. Privatizing early
+ would result in missed optimizations due to this restriction. */
+ NEXT_PASS (pass_ipa_comdats);
TERMINATE_PASS_LIST ()
/* Simple IPA passes executed after the regular passes. In WHOPR mode the
diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog
index a25a90eb438..1896481ddfd 100644
--- a/gcc/po/ChangeLog
+++ b/gcc/po/ChangeLog
@@ -1,3 +1,7 @@
+2014-05-14 Joseph Myers <joseph@codesourcery.com>
+
+ * zh_CN.po: Update.
+
2014-05-01 Jeff Law <law@redhat.com>
* Revert:
diff --git a/gcc/po/zh_CN.po b/gcc/po/zh_CN.po
index 7edfcb45770..e20e43f8ca4 100644
--- a/gcc/po/zh_CN.po
+++ b/gcc/po/zh_CN.po
@@ -1,14 +1,14 @@
# Simplified Chinese translation for gcc.
# Copyright (C) 2005 Free Software Foundation, Inc.
# This file is distributed under the same license as the gcc package.
-# Meng Jie <zuxy.meng@gmail.com>, 2005-2011.
+# Meng Jie <zuxy.meng@gmail.com>, 2005-2014.
#
msgid ""
msgstr ""
-"Project-Id-Version: gcc 4.6.0\n"
+"Project-Id-Version: gcc 4.9-b20140202\n"
"Report-Msgid-Bugs-To: http://gcc.gnu.org/bugs.html\n"
"POT-Creation-Date: 2014-02-02 17:35+0000\n"
-"PO-Revision-Date: 2011-05-19 15:04+0800\n"
+"PO-Revision-Date: 2014-05-14 14:25-0800\n"
"Last-Translator: Meng Jie <zuxy.meng@gmail.com>\n"
"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
"Language: zh_CN\n"
@@ -38,7 +38,6 @@ msgstr "return åŽæ²¡æœ‰å±éšœ"
#: collect2.c:1578
#, fuzzy, c-format
-#| msgid "collect2 version %s"
msgid "collect2 version %s\n"
msgstr "collect2 版本 %s"
@@ -94,13 +93,11 @@ msgstr "常é‡/å¤åˆ¶ä¼ é€’被ç¦ç”¨"
#: diagnostic.c:170
#, fuzzy, c-format
-#| msgid "%s: all warnings being treated as errors\n"
msgid "%s: all warnings being treated as errors"
msgstr "%s:所有的警告都被当作是错误\n"
#: diagnostic.c:175
#, fuzzy, c-format
-#| msgid "%s: some warnings being treated as errors\n"
msgid "%s: some warnings being treated as errors"
msgstr "%s:有些警告被当作是错误\n"
@@ -120,10 +117,6 @@ msgstr "编译中止因为 -fmax-errors=%u。\n"
#: diagnostic.c:479
#, fuzzy, c-format
-#| msgid ""
-#| "Please submit a full bug report,\n"
-#| "with preprocessed source if appropriate.\n"
-#| "See %s for instructions.\n"
msgid ""
"Please submit a full bug report,\n"
"with preprocessed source if appropriate.\n"
@@ -134,7 +127,6 @@ msgstr ""
#: diagnostic.c:485
#, fuzzy, c-format
-#| msgid "Use fp double instructions"
msgid "See %s for instructions.\n"
msgstr "使用浮点åŒç²¾åº¦æŒ‡ä»¤"
@@ -293,7 +285,6 @@ msgstr " --target-help 显示目标机器特定的命令行选项\n"
#: gcc.c:3073
#, fuzzy
-#| msgid " --help={target|optimizers|warnings|params|[^]{joined|separate|undocumented}}[,...]\n"
msgid " --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...]\n"
msgstr " --help={target|optimizers|warnings|params|[^]{joined|separate|undocumented}}[,...]\n"
@@ -339,9 +330,6 @@ msgstr " -print-prog-name=<程åº> 显示编译器组件 <程åº> 的完整路
#: gcc.c:3085
#, fuzzy
-#| msgid ""
-#| " -print-multi-lib Display the mapping between command line options and\n"
-#| " multiple library search directories\n"
msgid ""
" -print-multiarch Display the target's normalized GNU triplet, used as\n"
" a component in the library path\n"
@@ -461,13 +449,11 @@ msgstr " -o <文件> 输出到 <文件>\n"
#: gcc.c:3120
#, fuzzy
-#| msgid "Create a position independent executable"
msgid " -pie Create a position independent executable\n"
msgstr "生æˆä½ç½®æ— å…³å¯æ‰§è¡Œæ–‡ä»¶"
#: gcc.c:3121
#, fuzzy
-#| msgid "Create a shared library"
msgid " -shared Create a shared library\n"
msgstr "生æˆä¸€ä¸ªå…±äº«åº“"
@@ -497,7 +483,6 @@ msgstr ""
#: gcc.c:5402
#, fuzzy, c-format
-#| msgid "Processing spec %c%s%c, which is '%s'\n"
msgid "Processing spec (%s), which is '%s'\n"
msgstr "å¤„ç† spec %c%s%c,å³â€˜%s’\n"
@@ -613,9 +598,6 @@ msgstr ""
#: gcov.c:472
#, fuzzy, c-format
-#| msgid ""
-#| "Usage: gcov [OPTION]... SOURCEFILE...\n"
-#| "\n"
msgid ""
"Usage: gcov [OPTION]... SOURCE|OBJ...\n"
"\n"
@@ -649,9 +631,6 @@ msgstr " -b, --branch-probabilities 输出包å«åˆ†æ”¯æ¦‚率\n"
#: gcov.c:477
#, fuzzy, c-format
-#| msgid ""
-#| " -c, --branch-counts Given counts of branches taken\n"
-#| " rather than percentages\n"
msgid ""
" -c, --branch-counts Output counts of branches taken\n"
" rather than percentages\n"
@@ -701,7 +680,6 @@ msgstr " -p, --preserve-paths ä¿ç•™æ‰€æœ‰è·¯å¾„å\n"
#: gcov.c:488
#, fuzzy, c-format
-#| msgid " -a, --all-blocks Show information for every basic block\n"
msgid " -r, --relative-only Only show data for relative sources\n"
msgstr " -a, --all-blocks 显示æ¯ä¸ªåŸºæœ¬å—çš„ä¿¡æ¯\n"
@@ -749,25 +727,21 @@ msgstr ""
#: gcov.c:794
#, fuzzy, c-format
-#| msgid "%s:creating '%s'\n"
msgid "Creating '%s'\n"
msgstr "%s:正在创建‘%s’\n"
#: gcov.c:797
#, fuzzy, c-format
-#| msgid "%s:error writing output file '%s'\n"
msgid "Error writing output file '%s'\n"
msgstr "%s:写入输出文件‘%s’时出错\n"
#: gcov.c:801
#, fuzzy, c-format
-#| msgid "%s:could not open output file '%s'\n"
msgid "Could not open output file '%s'\n"
msgstr "%s:ä¸èƒ½æ‰“开输出文件‘%s’\n"
#: gcov.c:806
#, fuzzy, c-format
-#| msgid "[Leaving %s]\n"
msgid "Removing '%s'\n"
msgstr "[离开 %s]\n"
@@ -778,13 +752,11 @@ msgstr "\n"
#: gcov.c:856
#, fuzzy, c-format
-#| msgid "%s: Cannot open output file: %s\n"
msgid "Cannot open intermediate output file %s\n"
msgstr "%s:无法打开输出文件:%s\n"
#: gcov.c:1139
#, fuzzy, c-format
-#| msgid "%s:source file is newer than graph file '%s'\n"
msgid "%s:source file is newer than notes file '%s'\n"
msgstr "%s:æºæ–‡ä»¶è¾ƒå›¾æ–‡ä»¶â€˜%s’新\n"
@@ -795,13 +767,11 @@ msgstr "(æ¯ä¸ªæºæ–‡ä»¶åªæ˜¾ç¤ºä¸€æ¡ä¿¡æ¯)\n"
#: gcov.c:1169
#, fuzzy, c-format
-#| msgid "%s:cannot open source file\n"
msgid "%s:cannot open notes file\n"
msgstr "%s:无法打开æºæ–‡ä»¶\n"
#: gcov.c:1175
#, fuzzy, c-format
-#| msgid "%s:not a gcov data file\n"
msgid "%s:not a gcov notes file\n"
msgstr "%s:ä¸æ˜¯ä¸€ä¸ª gcov æ•°æ®æ–‡ä»¶\n"
@@ -842,7 +812,6 @@ msgstr "%s:版本‘%.4s’,首选版本‘%.4s’\n"
#: gcov.c:1417
#, fuzzy, c-format
-#| msgid "%s:stamp mismatch with graph file\n"
msgid "%s:stamp mismatch with notes file\n"
msgstr "%s:时间戳与图文件ä¸åŒ¹é…\n"
@@ -958,7 +927,6 @@ msgstr "æ— æ¡ä»¶ %2d 从未执行\n"
#: gcov.c:2424
#, fuzzy, c-format
-#| msgid "%s:cannot open source file\n"
msgid "Cannot open source file %s\n"
msgstr "%s:无法打开æºæ–‡ä»¶\n"
@@ -1109,13 +1077,11 @@ msgstr "在函数%qs中"
#: langhooks.c:456 cp/error.c:3131
#, fuzzy
-#| msgid " inlined from %qs at %s:%d:%d"
msgid " inlined from %qs at %r%s:%d:%d%R"
msgstr " 内è”自%qs于 %s:%d:%d"
#: langhooks.c:461 cp/error.c:3136
#, fuzzy
-#| msgid " inlined from %qs at %s:%d"
msgid " inlined from %qs at %r%s:%d%R"
msgstr " 内è”自%qs于 %s:%d"
@@ -1419,7 +1385,6 @@ msgstr "ä¸è€ƒè™‘内è”函数"
#: cif-code.def:43
#, fuzzy
-#| msgid "%qE is not initialized"
msgid "caller is not optimized"
msgstr "%qE未ç»åˆå§‹åŒ–"
@@ -1437,7 +1402,6 @@ msgstr "函数ä¸èƒ½å†…è”"
#: cif-code.def:60
#, fuzzy
-#| msgid "function body can be overwriten at linktime"
msgid "function body can be overwritten at link time"
msgstr "函数体å¯èƒ½åœ¨é“¾æŽ¥æ—¶è¢«æ”¹å†™"
@@ -1499,7 +1463,6 @@ msgstr ""
#: cif-code.def:113
#, fuzzy
-#| msgid "Enable exception handling"
msgid "non-call exception handling mismatch"
msgstr "å¯ç”¨å¼‚常处ç†"
@@ -1602,7 +1565,6 @@ msgstr "早期内è”器å¯ä»¥è¿›è¡Œçš„嵌套间接内è”的最大数é‡"
#: params.def:117
#, fuzzy
-#| msgid "Probability that COMDAT function will be shared with different compilatoin unit"
msgid "Probability that COMDAT function will be shared with different compilation unit"
msgstr "与其他编译å•å…ƒå…±äº« COMDAT 函数的概率"
@@ -1632,7 +1594,6 @@ msgstr "调度候选æ“作列表的最大长度"
#: params.def:175
#, fuzzy
-#| msgid "The maximum number of instructions to consider to unroll in a loop"
msgid "The maximum number of backtrack attempts the scheduler should make when modulo scheduling a loop"
msgstr "å•ä¸ªå¾ªçŽ¯ä¸­è€ƒè™‘展开的最大指令数"
@@ -1719,7 +1680,6 @@ msgstr "å•ä¸ªå¾ªçŽ¯æœ€å¤§çš„剥离数"
#: params.def:300
#, fuzzy
-#| msgid "The maximum number of iterations through CFG to extend regions"
msgid "The maximum number of branches on the path through the peeled sequence"
msgstr "通过 CFG 以扩展区域的最大循环次数"
@@ -2152,7 +2112,6 @@ msgstr "为实现跳转æ示æ’入的 nop 的最大数(默认 2)"
#: params.def:980
#, fuzzy
-#| msgid "Maximum number of times that an insn could be scheduled"
msgid "Maximum number of conditional store pairs that can be sunk"
msgstr "指定一æ¡æŒ‡ä»¤æœ€å¤šèƒ½è¢«è°ƒåº¦å‡ æ¬¡"
@@ -2170,13 +2129,11 @@ msgstr ""
#: params.def:1006
#, fuzzy
-#| msgid "Allow branches to be packed with other instructions"
msgid "Allow new data races on packed data loads to be introduced"
msgstr "å…许跳转与其他指令打包在一起"
#: params.def:1011
#, fuzzy
-#| msgid "Allow branches to be packed with other instructions"
msgid "Allow new data races on packed data stores to be introduced"
msgstr "å…许跳转与其他指令打包在一起"
@@ -2206,31 +2163,26 @@ msgstr ""
#: params.def:1054
#, fuzzy
-#| msgid "Enable stack probing"
msgid "Enable asan stack protection"
msgstr "å¯ç”¨å †æ ˆæŽ¢æµ‹"
#: params.def:1059
#, fuzzy
-#| msgid "Enable all optional instructions"
msgid "Enable asan globals protection"
msgstr "å¯ç”¨æ‰€æœ‰å¯é€‰æŒ‡ä»¤"
#: params.def:1064
#, fuzzy
-#| msgid "Enable saturation instructions"
msgid "Enable asan store operations protection"
msgstr "å¯ç”¨é¥±å’ŒæŒ‡ä»¤"
#: params.def:1069
#, fuzzy
-#| msgid "Enable all optional instructions"
msgid "Enable asan load operations protection"
msgstr "å¯ç”¨æ‰€æœ‰å¯é€‰æŒ‡ä»¤"
#: params.def:1074 params.def:1079
#, fuzzy
-#| msgid "Enable saturation instructions"
msgid "Enable asan builtin functions protection"
msgstr "å¯ç”¨é¥±å’ŒæŒ‡ä»¤"
@@ -2510,7 +2462,6 @@ msgstr "<命令行>"
#: config/aarch64/aarch64.c:3487 config/arm/arm.c:21114 config/arm/arm.c:21127
#: config/nios2/nios2.c:1885
#, fuzzy, c-format
-#| msgid "invalid operand for code '%c'"
msgid "Unsupported operand for code '%c'"
msgstr "代ç â€˜%c’的æ“作数无效"
@@ -2519,7 +2470,6 @@ msgstr "代ç â€˜%c’的æ“作数无效"
#: config/aarch64/aarch64.c:3551 config/aarch64/aarch64.c:3567
#: config/aarch64/aarch64.c:3586 config/aarch64/aarch64.c:3625
#, fuzzy, c-format
-#| msgid "invalid operand for code '%c'"
msgid "invalid operand for '%%%c'"
msgstr "代ç â€˜%c’的æ“作数无效"
@@ -2535,19 +2485,16 @@ msgstr "缺少æ“作数"
#: config/aarch64/aarch64.c:3724
#, fuzzy, c-format
-#| msgid "invalid insn:"
msgid "invalid constant"
msgstr "无效指令:"
#: config/aarch64/aarch64.c:3727
#, fuzzy, c-format
-#| msgid "invalid %%d operand"
msgid "invalid operand"
msgstr "无效的 %%d æ“作数"
#: config/aarch64/aarch64.c:3815
#, fuzzy, c-format
-#| msgid "invalid operand code '%c'"
msgid "invalid operand prefix '%%%c'"
msgstr "无效的æ“作数代ç â€˜%c’"
@@ -2637,19 +2584,16 @@ msgstr "无效的 %%xn 代ç "
#: config/arc/arc.c:2782
#, fuzzy, c-format
-#| msgid "invalid operand to %%R code"
msgid "invalid operand to %%Z code"
msgstr "%%R 代ç çš„æ“作数无效"
#: config/arc/arc.c:2790
#, fuzzy, c-format
-#| msgid "invalid operand to %%R code"
msgid "invalid operand to %%z code"
msgstr "%%R 代ç çš„æ“作数无效"
#: config/arc/arc.c:2798
#, fuzzy, c-format
-#| msgid "invalid operand to %%R code"
msgid "invalid operand to %%M code"
msgstr "%%R 代ç çš„æ“作数无效"
@@ -2675,7 +2619,6 @@ msgstr "%%V 代ç çš„æ“作数无效"
#: config/arc/arc.c:3099
#, fuzzy, c-format
-#| msgid "invalid operand to %%R code"
msgid "invalid operand to %%O code"
msgstr "%%R 代ç çš„æ“作数无效"
@@ -2689,7 +2632,6 @@ msgstr "无效的æ“作数输出代ç "
#: config/arc/arc.c:4676
#, fuzzy, c-format
-#| msgid "invalid UNSPEC as operand"
msgid "invalid UNSPEC as operand: %d"
msgstr "无效的 UNSPEC 用作æ“作数"
@@ -2749,19 +2691,16 @@ msgstr "地å€æ“ä½œæ•°éœ€è¦ Xã€Y 或 Z 寄存器约æŸ"
#: config/avr/avr.c:2140
#, fuzzy
-#| msgid "output operand %d must use %<&%> constraint"
msgid "operands to %T/%t must be reg + const_int:"
msgstr "输出æ“作数 %d 必须使用%<&%>约æŸ"
#: config/avr/avr.c:2180 config/avr/avr.c:2235
#, fuzzy
-#| msgid "bad address, not (reg+disp):"
msgid "bad address, not an I/O address:"
msgstr "地å€é”™è¯¯ï¼Œä¸æ˜¯(reg+disp):"
#: config/avr/avr.c:2189
#, fuzzy
-#| msgid "bad address, not a constant):"
msgid "bad address, not a constant:"
msgstr "错误的地å€ï¼Œä¸æ˜¯ä¸€ä¸ªå¸¸é‡):"
@@ -2813,7 +2752,6 @@ msgstr "编译器内部错误。ä¸æ­£ç¡®çš„移ä½é‡ï¼š"
#: config/avr/avr.c:7100
#, fuzzy
-#| msgid "invalid types in fixed-point conversion"
msgid "unsupported fixed-point conversion"
msgstr "整点转æ¢ä¸­ç±»åž‹æ— æ•ˆ"
@@ -3058,25 +2996,21 @@ msgstr "无效的 UNSPEC 用作æ“作数"
#: config/i386/i386.c:14839
#, fuzzy, c-format
-#| msgid "invalid operand size for operand code '%c'"
msgid "invalid operand size for operand code 'O'"
msgstr "æ“作数代ç â€˜%c’的æ“作数大å°æ— æ•ˆ"
#: config/i386/i386.c:14874
#, fuzzy, c-format
-#| msgid "invalid operand size for operand code '%c'"
msgid "invalid operand size for operand code 'z'"
msgstr "æ“作数代ç â€˜%c’的æ“作数大å°æ— æ•ˆ"
#: config/i386/i386.c:14944
#, fuzzy, c-format
-#| msgid "invalid operand type used with operand code '%c'"
msgid "invalid operand type used with operand code 'Z'"
msgstr "æ“作数代ç â€˜%c’的æ“作数类型无效"
#: config/i386/i386.c:14949
#, fuzzy, c-format
-#| msgid "invalid operand size for operand code '%c'"
msgid "invalid operand size for operand code 'Z'"
msgstr "æ“作数代ç â€˜%c’的æ“作数大å°æ— æ•ˆ"
@@ -3092,13 +3026,11 @@ msgstr "æ“作数ä¸æ˜¯ä¸€ä¸ªæ¡ä»¶ç ï¼Œæ— æ•ˆçš„æ“作数代ç â€˜D’"
#: config/i386/i386.c:15115
#, fuzzy, c-format
-#| msgid "operand is not a condition code, invalid operand code 'D'"
msgid "operand is not a condition code, invalid operand code '%c'"
msgstr "æ“作数ä¸æ˜¯ä¸€ä¸ªæ¡ä»¶ç ï¼Œæ— æ•ˆçš„æ“作数代ç â€˜D’"
#: config/i386/i386.c:15128
#, fuzzy, c-format
-#| msgid "operand is not a condition code, invalid operand code 'D'"
msgid "operand is not an offsettable memory reference, invalid operand code 'H'"
msgstr "æ“作数ä¸æ˜¯ä¸€ä¸ªæ¡ä»¶ç ï¼Œæ— æ•ˆçš„æ“作数代ç â€˜D’"
@@ -3127,7 +3059,6 @@ msgstr "使用本地 (MS) ä½æ®µå­˜å‚¨æ–¹å¼"
#: config/i386/i386-interix.h:78
#, fuzzy
-#| msgid "Use native (MS) bitfield layout"
msgid "Use gcc default bitfield layout"
msgstr "使用本地 (MS) ä½æ®µå­˜å‚¨æ–¹å¼"
@@ -3343,7 +3274,6 @@ msgstr "MMIX 内部错误:这ä¸æ˜¯ä¸€ä¸ªå¸¸é‡ï¼š"
#: config/msp430/msp430.c:2130
#, fuzzy, c-format
-#| msgid "invalid reference prefix"
msgid "invalid operand prefix"
msgstr "无效的引用å‰ç¼€"
@@ -3404,7 +3334,6 @@ msgstr "-mno-altivec ç¦ç”¨äº† VSX"
#: config/rs6000/rs6000.c:3363
#, fuzzy
-#| msgid "--resource requires -o"
msgid "-mquad-memory requires 64-bit mode"
msgstr "--resource éœ€è¦ -o"
@@ -3414,7 +3343,6 @@ msgstr ""
#: config/rs6000/rs6000.c:3378
#, fuzzy
-#| msgid "Generate code in little endian mode"
msgid "-mquad-memory is not available in little endian mode"
msgstr "生æˆå°ç«¯åœ¨å‰çš„代ç "
@@ -3503,13 +3431,11 @@ msgstr "传递 AltiVec å‚数给无原型的函数"
#: config/rs6000/rs6000.c:32382
#, fuzzy
-#| msgid "Do not generate a single exit point for each function"
msgid "Could not generate addis value for fusion"
msgstr "ä¸ä¸ºæ¯ä¸ªå‡½æ•°ç”Ÿæˆå•ä¸€çš„退出点"
#: config/rs6000/rs6000.c:32441
#, fuzzy
-#| msgid "unable to generate reloads for:"
msgid "Unable to generate load offset for fusion"
msgstr "无法生æˆé‡æ–°è½½å…¥ï¼Œä¸ºï¼š"
@@ -3638,13 +3564,11 @@ msgstr "无效的 %%B æ“作数"
#: config/sparc/sparc.c:8830 config/tilegx/tilegx.c:5061
#: config/tilepro/tilepro.c:4516
#, fuzzy, c-format
-#| msgid "invalid %%P operand"
msgid "invalid %%C operand"
msgstr "无效的 %%P æ“作数"
#: config/sparc/sparc.c:8847 config/tilegx/tilegx.c:5094
#, fuzzy, c-format
-#| msgid "invalid %%P operand"
msgid "invalid %%D operand"
msgstr "无效的 %%P æ“作数"
@@ -3700,49 +3624,41 @@ msgstr "无效的 %%d æ“作数"
#: config/tilegx/tilegx.c:5174
#, fuzzy, c-format
-#| msgid "invalid %%L code"
msgid "invalid %%H specifier"
msgstr "无效 %%L 代ç "
#: config/tilegx/tilegx.c:5216 config/tilepro/tilepro.c:4530
#, fuzzy, c-format
-#| msgid "invalid %%P operand"
msgid "invalid %%h operand"
msgstr "无效的 %%P æ“作数"
#: config/tilegx/tilegx.c:5228 config/tilepro/tilepro.c:4594
#, fuzzy, c-format
-#| msgid "invalid %%P operand"
msgid "invalid %%I operand"
msgstr "无效的 %%P æ“作数"
#: config/tilegx/tilegx.c:5242 config/tilepro/tilepro.c:4608
#, fuzzy, c-format
-#| msgid "invalid %%P operand"
msgid "invalid %%i operand"
msgstr "无效的 %%P æ“作数"
#: config/tilegx/tilegx.c:5265 config/tilepro/tilepro.c:4631
#, fuzzy, c-format
-#| msgid "invalid %%P operand"
msgid "invalid %%j operand"
msgstr "无效的 %%P æ“作数"
#: config/tilegx/tilegx.c:5296
#, fuzzy, c-format
-#| msgid "invalid %%c operand"
msgid "invalid %%%c operand"
msgstr "无效的 %%c æ“作数"
#: config/tilegx/tilegx.c:5311 config/tilepro/tilepro.c:4745
#, fuzzy, c-format
-#| msgid "invalid %%P operand"
msgid "invalid %%N operand"
msgstr "无效的 %%P æ“作数"
#: config/tilegx/tilegx.c:5355
#, fuzzy, c-format
-#| msgid "invalid operand for 'b' modifier"
msgid "invalid operand for 'r' specifier"
msgstr "‘b’修饰符的æ“作数无效"
@@ -3753,37 +3669,31 @@ msgstr ""
#: config/tilepro/tilepro.c:4566
#, fuzzy, c-format
-#| msgid "invalid %%P operand"
msgid "invalid %%H operand"
msgstr "无效的 %%P æ“作数"
#: config/tilepro/tilepro.c:4670
#, fuzzy, c-format
-#| msgid "invalid %%P operand"
msgid "invalid %%L operand"
msgstr "无效的 %%P æ“作数"
#: config/tilepro/tilepro.c:4730
#, fuzzy, c-format
-#| msgid "invalid %%P operand"
msgid "invalid %%M operand"
msgstr "无效的 %%P æ“作数"
#: config/tilepro/tilepro.c:4773
#, fuzzy, c-format
-#| msgid "invalid %%P operand"
msgid "invalid %%t operand"
msgstr "无效的 %%P æ“作数"
#: config/tilepro/tilepro.c:4780
#, fuzzy, c-format
-#| msgid "invalid %%P operand"
msgid "invalid %%t operand '"
msgstr "无效的 %%P æ“作数"
#: config/tilepro/tilepro.c:4801
#, fuzzy, c-format
-#| msgid "invalid %%P operand"
msgid "invalid %%r operand"
msgstr "无效的 %%P æ“作数"
@@ -4057,13 +3967,11 @@ msgstr "{匿å}"
#: cp/error.c:1060
#, fuzzy
-#| msgid "(anonymous)"
msgid "(anonymous namespace)"
msgstr "(匿å)"
#: cp/error.c:1169
#, fuzzy
-#| msgid "<template parameter error>"
msgid "<template arguments error>"
msgstr "<模æ¿å‚数数错误>"
@@ -4104,7 +4012,6 @@ msgstr "<未解æž>"
#: cp/error.c:2616
#, fuzzy
-#| msgid "<lambda"
msgid "<lambda>"
msgstr "<lambda"
@@ -4150,13 +4057,11 @@ msgstr "在 lambda 函数中"
#: cp/error.c:3196
#, fuzzy, c-format
-#| msgid "%s: In instantiation of %qs:\n"
msgid "%s: In substitution of %qS:\n"
msgstr "%s:在%qs的实例化中:\n"
#: cp/error.c:3197
#, fuzzy
-#| msgid "%s: In instantiation of %qs:\n"
msgid "%s: In instantiation of %q#D:\n"
msgstr "%s:在%qs的实例化中:\n"
@@ -4185,7 +4090,6 @@ msgstr " 内è”自%qs于 %s:%d:%d"
#: cp/error.c:3240
#, fuzzy
-#| msgid "provided for %q+D"
msgid "required from %q#D\n"
msgstr "æ供给%q+D"
@@ -4196,31 +4100,26 @@ msgstr "%s:%d:从此处实例化"
#: cp/error.c:3248
#, fuzzy
-#| msgid "called from here"
msgid "required from here"
msgstr "从此处调用"
#: cp/error.c:3300
#, fuzzy
-#| msgid "%s:%d:%d: [ skipping %d instantiation contexts ]\n"
msgid "%r%s:%d:%d:%R [ skipping %d instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]\n"
msgstr "%s:%d:%d:[ 跳过 %d 个实例化上下文 ]\n"
#: cp/error.c:3306
#, fuzzy
-#| msgid "%s:%d:%d: [ skipping %d instantiation contexts ]\n"
msgid "%r%s:%d:%R [ skipping %d instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]\n"
msgstr "%s:%d:%d:[ 跳过 %d 个实例化上下文 ]\n"
#: cp/error.c:3371
#, fuzzy
-#| msgid "%s:%d:%d: in constexpr expansion of %qs"
msgid "%r%s:%d:%d:%R in constexpr expansion of %qs"
msgstr "%s:%d:%d:在%qs的广义常表达å¼æ‰©å±•ä¸­"
#: cp/error.c:3375
#, fuzzy
-#| msgid "%s:%d: in constexpr expansion of %qs"
msgid "%r%s:%d:%R in constexpr expansion of %qs"
msgstr "%s:%d:在%qs的广义常表达å¼æ‰©å±•ä¸­"
@@ -4390,13 +4289,11 @@ msgstr ""
#: fortran/error.c:899
#, fuzzy
-#| msgid "Obsolescent feature: Computed GOTO at %C"
msgid "Obsolescent feature:"
msgstr "已过时的特性:%C处的计算转移 GOTO 语å¥"
#: fortran/error.c:902
#, fuzzy
-#| msgid "expected operator"
msgid "Deleted feature:"
msgstr "需è¦æ“作符"
@@ -4647,61 +4544,51 @@ msgstr "基本过程"
#: fortran/resolve.c:2225
#, fuzzy
-#| msgid "no arguments"
msgid "allocatable argument"
msgstr "没有å‚æ•°"
#: fortran/resolve.c:2230
#, fuzzy
-#| msgid "not enough arguments"
msgid "asynchronous argument"
msgstr "实å‚太少"
#: fortran/resolve.c:2235
#, fuzzy
-#| msgid "invalid PHI argument"
msgid "optional argument"
msgstr "无效的 PHI 实å‚"
#: fortran/resolve.c:2240
#, fuzzy
-#| msgid "pointer assignment"
msgid "pointer argument"
msgstr "指针赋值"
#: fortran/resolve.c:2245
#, fuzzy
-#| msgid "no arguments"
msgid "target argument"
msgstr "没有å‚æ•°"
#: fortran/resolve.c:2250
#, fuzzy
-#| msgid "invalid PHI argument"
msgid "value argument"
msgstr "无效的 PHI 实å‚"
#: fortran/resolve.c:2255
#, fuzzy
-#| msgid "no arguments"
msgid "volatile argument"
msgstr "没有å‚æ•°"
#: fortran/resolve.c:2260
#, fuzzy
-#| msgid "mismatched arguments"
msgid "assumed-shape argument"
msgstr "å‚æ•°ä¸åŒ¹é…"
#: fortran/resolve.c:2265
#, fuzzy
-#| msgid "mismatched arguments"
msgid "assumed-rank argument"
msgstr "å‚æ•°ä¸åŒ¹é…"
#: fortran/resolve.c:2270
#, fuzzy
-#| msgid "array assignment"
msgid "coarray argument"
msgstr "数组赋值"
@@ -4711,7 +4598,6 @@ msgstr ""
#: fortran/resolve.c:2280
#, fuzzy
-#| msgid "no arguments"
msgid "polymorphic argument"
msgstr "没有å‚æ•°"
@@ -4723,7 +4609,6 @@ msgstr ""
#. See also TS 29113, Note 6.1.
#: fortran/resolve.c:2292
#, fuzzy
-#| msgid "mismatched arguments"
msgid "assumed-type argument"
msgstr "å‚æ•°ä¸åŒ¹é…"
@@ -4738,13 +4623,11 @@ msgstr "%3$L 处“%1$sâ€åˆ†å¥å¯¹è±¡â€œ%2$sâ€æœ‰ ALLOCATABLE 组件"
#: fortran/resolve.c:2315
#, fuzzy
-#| msgid "'%s' at %L must have constant character length in this context"
msgid "result with non-constant character length"
msgstr "å˜é‡â€˜%s’在%L处上下文中字符长度必须为常é‡"
#: fortran/resolve.c:2327
#, fuzzy
-#| msgid "module procedure"
msgid "bind(c) procedure"
msgstr "模å—过程"
@@ -4894,7 +4777,6 @@ msgstr "%3$s 中字符长度ä¸ç›¸ç­‰ (%1$ld/%2$ld)"
#: fortran/trans-intrinsic.c:6165
#, fuzzy, c-format
-#| msgid "Argument NCOPIES of REPEAT intrinsic is negative (its value is %lld)"
msgid "Argument NCOPIES of REPEAT intrinsic is negative (its value is %ld)"
msgstr "内建函数 REPEAT çš„ NCOPIES å‚数为负(其值是 %lld)"
@@ -4964,7 +4846,6 @@ msgstr ""
#: go/go-backend.c:171
#, fuzzy
-#| msgid "Memory allocation failed"
msgid "memory allocation failed while reading export data"
msgstr "内存分é…失败"
@@ -5230,13 +5111,11 @@ msgstr "Ada 需è¦æŒ‡å®š -c 或 -S"
#: ada/gcc-interface/lang-specs.h:52
#, fuzzy
-#| msgid "-c or -S required for Ada"
msgid "-c required for gnat2why"
msgstr "Ada 需è¦æŒ‡å®š -c 或 -S"
#: ada/gcc-interface/lang-specs.h:65
#, fuzzy
-#| msgid "-c or -S required for Ada"
msgid "-c required for gnat2scil"
msgstr "Ada 需è¦æŒ‡å®š -c 或 -S"
@@ -5266,7 +5145,6 @@ msgstr "ä¸èƒ½åŒæ—¶ä½¿ç”¨ -EB å’Œ -EL"
#: config/avr/avr.h:526
#, fuzzy
-#| msgid "-fpic is not supported"
msgid "shared is not supported"
msgstr "ä¸æ”¯æŒ -fpic"
@@ -5284,7 +5162,6 @@ msgstr "-mas100-syntax 与 -gdwarf ä¸å…¼å®¹"
#: config/rx/rx.h:76
#, fuzzy
-#| msgid "rx200 cpu does not have FPU hardware"
msgid "rx100 cpu does not have FPU hardware"
msgstr "RX200 CPU 没有 FPU 硬件"
@@ -5306,7 +5183,6 @@ msgstr "-femit-class-file 应当与 -fsyntax-only 一起使用"
#: config/rs6000/freebsd64.h:161 config/rs6000/freebsd64.h:173
#, fuzzy
-#| msgid "consider using `-pg' instead of `-p' with gprof(1) "
msgid "consider using `-pg' instead of `-p' with gprof(1)"
msgstr "与 gprof(1) 一起使用时请考虑使用‘-pg’以代替‘-p’"
@@ -5321,7 +5197,6 @@ msgstr ""
#: gcc.c:731
#, fuzzy
-#| msgid "-fdirectives-only is incompatible with -traditional"
msgid "-fsanitize=address is incompatible with -fsanitize=thread"
msgstr "-fdirectives-only 与 -traditional ä¸å…¼å®¹"
@@ -5339,7 +5214,6 @@ msgstr "当输入æ¥è‡ªæ ‡å‡†è¾“å…¥è®¾å¤‡æ—¶ï¼Œéœ€è¦ -E 或 -x"
#: config/arm/arm.h:217
#, fuzzy
-#| msgid "-msoft-float and -mhard_float may not be used together"
msgid "-mfloat-abi=soft and -mfloat-abi=hard may not be used together"
msgstr "-msoft-float å’Œ -mhard_float ä¸èƒ½ä¸€èµ·ä½¿ç”¨"
@@ -5410,7 +5284,6 @@ msgstr "打å°é¢å¤–(å¯èƒ½æ‚¨å¹¶ä¸æƒ³è¦)的警告信æ¯"
#: fortran/lang.opt:242
#, fuzzy
-#| msgid "Warn about implicit function declarations"
msgid "Warn about function call elimination"
msgstr "对éšå¼å‡½æ•°å£°æ˜Žç»™å‡ºè­¦å‘Š"
@@ -5436,13 +5309,11 @@ msgstr ""
#: fortran/lang.opt:270
#, fuzzy
-#| msgid "Warn when a register variable is declared volatile"
msgid "Warn when a left-hand-side array variable is reallocated"
msgstr "当一个寄存器å˜é‡è¢«å£°æ˜Žä¸º volatile 时给出警告"
#: fortran/lang.opt:274
#, fuzzy
-#| msgid "Warn when a register variable is declared volatile"
msgid "Warn when a left-hand-side variable is reallocated"
msgstr "当一个寄存器å˜é‡è¢«å£°æ˜Žä¸º volatile 时给出警告"
@@ -5473,7 +5344,6 @@ msgstr "对未使用的哑元给出警告。"
#: fortran/lang.opt:306
#, fuzzy
-#| msgid "Warn about zero-length formats"
msgid "Warn about zero-trip DO loops"
msgstr "对长度为 0 çš„æ ¼å¼å­—符串给出警告"
@@ -5616,7 +5486,6 @@ msgstr "-ffpe-trap=[...]\t在以下浮点异常的情况下åœæ­¢"
#: fortran/lang.opt:458
#, fuzzy
-#| msgid "-ffpe-trap=[...]\tStop on following floating point exceptions"
msgid "-ffpe-summary=[...]\tPrint summary of floating point exceptions"
msgstr "-ffpe-trap=[...]\t在以下浮点异常的情况下åœæ­¢"
@@ -5634,7 +5503,6 @@ msgstr "-ffree-line-length-<n>\t在自由模å¼ä¸‹ä»¥ n 作为字符行宽"
#: fortran/lang.opt:474
#, fuzzy
-#| msgid "Enable linker optimizations"
msgid "Enable front end optimization"
msgstr "å¯ç”¨é“¾æŽ¥å™¨ä¼˜åŒ–"
@@ -5784,7 +5652,6 @@ msgstr "éµå¾ª ISO Fortran 2008 标准"
#: fortran/lang.opt:670
#, fuzzy
-#| msgid "Conform to the ISO Fortran 2008 standard"
msgid "Conform to the ISO Fortran 2008 standard including TS 29113"
msgstr "éµå¾ª ISO Fortran 2008 标准"
@@ -5937,13 +5804,11 @@ msgstr "当在 C 语言中使用了 C 与 C++ 交集以外的构造时给出警å
#: c-family/c.opt:296
#, fuzzy
-#| msgid "Deprecated in favor of -std=c99"
msgid "Deprecated in favor of -Wc++11-compat"
msgstr "ä¸å»ºè®®ä½¿ç”¨ï¼Œè¯·æ”¹ç”¨ -std=c99"
#: c-family/c.opt:300
#, fuzzy
-#| msgid "Warn about C++ constructs whose meaning differs between ISO C++ 1998 and ISO C++ 200x"
msgid "Warn about C++ constructs whose meaning differs between ISO C++ 1998 and ISO C++ 2011"
msgstr "当 C++ 构造的æ„义在 ISO C++ 1998 å’Œ ISO C++ 200x 中ä¸åŒæ—¶ç»™å‡ºè­¦å‘Š"
@@ -5989,13 +5854,11 @@ msgstr "当声明出现在语å¥åŽæ—¶ç»™å‡ºè­¦å‘Š"
#: c-family/c.opt:344
#, fuzzy
-#| msgid "dereferencing pointer to incomplete type"
msgid "Warn when deleting a pointer to incomplete type"
msgstr "æ领指å‘ä¸å®Œå…¨ç±»åž‹çš„指针"
#: c-family/c.opt:348
#, fuzzy
-#| msgid "Warn about non-virtual destructors"
msgid "Warn about deleting polymorphic objects with non-virtual destructors"
msgstr "当æžæž„函数ä¸æ˜¯è™šå‡½æ•°æ—¶ç»™å‡ºè­¦å‘Š"
@@ -6029,7 +5892,6 @@ msgstr "ä¸å»ºè®®ä½¿ç”¨æ­¤å¼€å…³ï¼›è¯·æ”¹ç”¨ -Werror=implicit-function-declarati
#: c-family/c.opt:392
#, fuzzy
-#| msgid "Warn for implicit type conversions that may change a value"
msgid "Warn for implicit type conversions that cause loss of floating point precision"
msgstr "当éšå¼ç±»åž‹è½¬æ¢å¯èƒ½æ”¹å˜å€¼æ—¶ç»™å‡ºè­¦å‘Š"
@@ -6286,7 +6148,6 @@ msgstr "编译器将代ç é‡æ–°æŽ’åºæ—¶ç»™å‡ºè­¦å‘Š"
#: c-family/c.opt:673
#, fuzzy
-#| msgid "returning reference to temporary"
msgid "Warn about returning a pointer/reference to a local or temporary variable."
msgstr "返回临时å˜é‡çš„引用"
@@ -6364,7 +6225,6 @@ msgstr "对ä¸å¸¦åŽç¼€çš„浮点常é‡ç»™å‡ºè­¦å‘Š"
#: c-family/c.opt:777
#, fuzzy
-#| msgid "Warn about macros defined in the main file that are not used"
msgid "Warn when typedefs locally defined in a function are not used"
msgstr "当定义在主文件中的å®æœªè¢«ä½¿ç”¨æ—¶ç»™å‡ºè­¦å‘Š"
@@ -6378,7 +6238,6 @@ msgstr "当一个带有 warn_unused_result 属性的函数的调用者未使用å
#: c-family/c.opt:789
#, fuzzy
-#| msgid "Do not warn about using variadic macros when -pedantic"
msgid "Warn about using variadic macros"
msgstr "指定 -pedantic æ—¶ä¸ä¸ºå¯å˜å‚æ•°å®ç»™å‡ºè­¦å‘Š"
@@ -6404,13 +6263,11 @@ msgstr "在 C++ 中,éžé›¶å€¼è¡¨ç¤ºå°†å­—é¢å­—符串转æ¢ä¸ºâ€˜char *’时ç
#: c-family/c.opt:813
#, fuzzy
-#| msgid "Warn when a label is unused"
msgid "Warn when a literal '0' is used as null pointer"
msgstr "有未使用的标å·æ—¶è­¦å‘Š"
#: c-family/c.opt:817
#, fuzzy
-#| msgid "Warn about misuses of pragmas"
msgid "Warn about useless casts"
msgstr "对错误使用的 pragma 加以警告"
@@ -6467,25 +6324,21 @@ msgstr "-fconst-string-class=<åå­—>\t使用å字作为常é‡å­—符串类的å
#: c-family/c.opt:883
#, fuzzy
-#| msgid "-ftemplate-depth=<number>\tSpecify maximum template instantiation depth"
msgid "-fconstexpr-depth=<number>\tSpecify maximum constexpr recursion depth"
msgstr "-ftemplate-depth=<N>\t指定模æ¿å®žä¾‹åŒ–的最大深度"
#: c-family/c.opt:887
#, fuzzy
-#| msgid "Enable traditional preprocessing"
msgid "Emit debug annotations during preprocessing"
msgstr "å¯ç”¨ä¼ ç»Ÿé¢„处ç†"
#: c-family/c.opt:891
#, fuzzy
-#| msgid "-fno-deduce-init-list\tdisable deduction of std::initializer_list for a template type parameter from a brace-enclosed initializer-list"
msgid "-fdeduce-init-list\tenable deduction of std::initializer_list for a template type parameter from a brace-enclosed initializer-list"
msgstr "-fno-deduce-init-list\tç¦ç”¨ä¸ºæ¨¡æ¿ç±»åž‹å‚数从花括å·ä¸­çš„åˆå§‹å€¼è®¾å®šåˆ—表演绎 std::initializer_list"
#: c-family/c.opt:895
#, fuzzy
-#| msgid "Warn when all constructors and destructors are private"
msgid "Factor complex constructors and destructors to favor space over speed"
msgstr "当所有构造函数和æžæž„函数都是ç§æœ‰æ—¶ç»™å‡ºè­¦å‘Š"
@@ -6632,7 +6485,6 @@ msgstr "å¯ç”¨ OpenMP(对 Fortran 而言也åŒæ—¶è®¾å®š -frecursive)"
#: c-family/c.opt:1090
#, fuzzy
-#| msgid "Unclassifiable OpenMP directive at %C"
msgid "Enable OpenMP's SIMD directives"
msgstr "%C处的 OpenMP 指示无法分类"
@@ -6710,7 +6562,6 @@ msgstr "-ftabstop=<N>\t指定报告列å·æ—¶åˆ¶è¡¨ä½é—´çš„è·ç¦»"
#: c-family/c.opt:1183
#, fuzzy
-#| msgid "The maximum number of peelings of a single loop"
msgid "Set the maximum number of template instantiation notes for a single warning or error"
msgstr "å•ä¸ªå¾ªçŽ¯æœ€å¤§çš„剥离数"
@@ -6740,7 +6591,6 @@ msgstr "在异常处ç†ä¸­ä½¿ç”¨ __cxa_get_exception_ptr"
#: c-family/c.opt:1217
#, fuzzy
-#| msgid "Marks all inlined methods as having hidden visibility"
msgid "Marks all inlined functions and methods as having hidden visibility"
msgstr "将所有内è”函数标记为具有éšè—çš„å¯è§æ€§"
@@ -6842,37 +6692,31 @@ msgstr "包å«æ–‡ä»¶æ—¶æ˜ å°„短文件å"
#: c-family/c.opt:1344 c-family/c.opt:1348
#, fuzzy
-#| msgid "Conform to the ISO 1998 C++ standard with GNU extensions"
msgid "Conform to the ISO 1998 C++ standard revised by the 2003 technical corrigendum"
msgstr "éµå¾ª ISO 1998 C++ æ ‡å‡†ï¼Œä¹Ÿæ”¯æŒ GNU 扩展"
#: c-family/c.opt:1352
#, fuzzy
-#| msgid "Conform to the ISO 201X C standard draft (experimental and incomplete support)"
msgid "Conform to the ISO 2011 C++ standard (experimental and incomplete support)"
msgstr "éµå¾ª ISO 201X C 标准è‰æ¡ˆ(试验性质的ä¸å®Œå…¨æ”¯æŒ)"
#: c-family/c.opt:1356
#, fuzzy
-#| msgid "Deprecated in favor of -std=c99"
msgid "Deprecated in favor of -std=c++11"
msgstr "ä¸å»ºè®®ä½¿ç”¨ï¼Œè¯·æ”¹ç”¨ -std=c99"
#: c-family/c.opt:1360
#, fuzzy
-#| msgid "Conform to the ISO 201X C standard draft (experimental and incomplete support)"
msgid "Conform to the ISO 201y(7?) C++ draft standard (experimental and incomplete support)"
msgstr "éµå¾ª ISO 201X C 标准è‰æ¡ˆ(试验性质的ä¸å®Œå…¨æ”¯æŒ)"
#: c-family/c.opt:1364 c-family/c.opt:1450
#, fuzzy
-#| msgid "Conform to the ISO 201X C standard draft (experimental and incomplete support)"
msgid "Conform to the ISO 2011 C standard (experimental and incomplete support)"
msgstr "éµå¾ª ISO 201X C 标准è‰æ¡ˆ(试验性质的ä¸å®Œå…¨æ”¯æŒ)"
#: c-family/c.opt:1368
#, fuzzy
-#| msgid "Deprecated in favor of -std=c99"
msgid "Deprecated in favor of -std=c11"
msgstr "ä¸å»ºè®®ä½¿ç”¨ï¼Œè¯·æ”¹ç”¨ -std=c99"
@@ -6890,37 +6734,31 @@ msgstr "ä¸å»ºè®®ä½¿ç”¨ï¼Œè¯·æ”¹ç”¨ -std=c99"
#: c-family/c.opt:1388 c-family/c.opt:1393
#, fuzzy
-#| msgid "Conform to the ISO 1998 C++ standard with GNU extensions"
msgid "Conform to the ISO 1998 C++ standard revised by the 2003 technical"
msgstr "éµå¾ª ISO 1998 C++ æ ‡å‡†ï¼Œä¹Ÿæ”¯æŒ GNU 扩展"
#: c-family/c.opt:1398
#, fuzzy
-#| msgid "Conform to the ISO 201X C standard draft with GNU extensions (experimental and incomplete support)"
msgid "Conform to the ISO 2011 C++ standard with GNU extensions (experimental and incomplete support)"
msgstr "éµå¾ª ISO 201X C 标准è‰æ¡ˆå’Œ GNU 扩展(试验性质的ä¸å®Œå…¨æ”¯æŒ)"
#: c-family/c.opt:1402
#, fuzzy
-#| msgid "Deprecated in favor of -std=gnu99"
msgid "Deprecated in favor of -std=gnu++11"
msgstr "ä¸å»ºè®®ä½¿ç”¨ï¼Œè¯·æ”¹ç”¨ -std=gnu99"
#: c-family/c.opt:1406
#, fuzzy
-#| msgid "Conform to the ISO 201X C standard draft with GNU extensions (experimental and incomplete support)"
msgid "Conform to the ISO 201y(7?) C++ draft standard with GNU extensions (experimental and incomplete support)"
msgstr "éµå¾ª ISO 201X C 标准è‰æ¡ˆå’Œ GNU 扩展(试验性质的ä¸å®Œå…¨æ”¯æŒ)"
#: c-family/c.opt:1410
#, fuzzy
-#| msgid "Conform to the ISO 201X C standard draft with GNU extensions (experimental and incomplete support)"
msgid "Conform to the ISO 2011 C standard with GNU extensions (experimental and incomplete support)"
msgstr "éµå¾ª ISO 201X C 标准è‰æ¡ˆå’Œ GNU 扩展(试验性质的ä¸å®Œå…¨æ”¯æŒ)"
#: c-family/c.opt:1414
#, fuzzy
-#| msgid "Deprecated in favor of -std=gnu99"
msgid "Deprecated in favor of -std=gnu11"
msgstr "ä¸å»ºè®®ä½¿ç”¨ï¼Œè¯·æ”¹ç”¨ -std=gnu99"
@@ -6958,7 +6796,6 @@ msgstr "ä¸é¢„定义系统或 GCC 特定的å®"
#: ada/gcc-interface/lang.opt:61
#, fuzzy
-#| msgid "Synonym for -Wcomment"
msgid "Synonym of -gnatk8"
msgstr "-Wcomment çš„åŒä¹‰è¯"
@@ -6968,7 +6805,6 @@ msgstr ""
#: ada/gcc-interface/lang.opt:73
#, fuzzy
-#| msgid "Select code model"
msgid "Select the runtime"
msgstr "选择代ç æ¨¡åž‹"
@@ -7036,7 +6872,6 @@ msgstr ""
#: config/vms/vms.opt:42
#, fuzzy, c-format
-#| msgid "unknown TLS model %qs"
msgid "unknown pointer size model %qs"
msgstr "未知的 TLS 模型%qs"
@@ -7547,7 +7382,6 @@ msgstr "å‡å®šç›®æ ‡ CPU 被é…置为大端在å‰"
#: config/aarch64/aarch64.opt:68
#, fuzzy
-#| msgid "Generate code which uses hardware floating point instructions"
msgid "Generate code which uses only the general registers"
msgstr "生æˆä½¿ç”¨ç¡¬ä»¶æµ®ç‚¹æŒ‡ä»¤çš„代ç "
@@ -7558,7 +7392,6 @@ msgstr "å‡å®šç›®æ ‡ CPU 被é…置为å°ç«¯åœ¨å‰"
#: config/aarch64/aarch64.opt:76
#, fuzzy
-#| msgid "Select code model"
msgid "Specify the code model"
msgstr "选择代ç æ¨¡åž‹"
@@ -7576,13 +7409,11 @@ msgstr ""
#: config/aarch64/aarch64.opt:92
#, fuzzy
-#| msgid "-mcpu=\tUse features of and schedule code for given CPU"
msgid "-march=ARCH\tUse features of architecture ARCH"
msgstr "-mcpu=\t使用指定 CPU 的特性和调度代ç "
#: config/aarch64/aarch64.opt:96
#, fuzzy
-#| msgid "-mcpu=\tUse features of and schedule code for given CPU"
msgid "-mcpu=CPU\tUse features of and optimize for CPU"
msgstr "-mcpu=\t使用指定 CPU 的特性和调度代ç "
@@ -7592,7 +7423,6 @@ msgstr ""
#: config/aarch64/aarch64.opt:104
#, fuzzy
-#| msgid "-mabi=ABI\tGenerate code that conforms to the given ABI"
msgid "-mabi=ABI\tGenerate code that conforms to the specified ABI"
msgstr "-mabi=ABI\t生æˆéµå¾ªç»™å®š ABI 的代ç "
@@ -7874,25 +7704,21 @@ msgstr ""
#: config/epiphany/epiphany.opt:32
#, fuzzy
-#| msgid "Relax branches"
msgid "Set branch cost"
msgstr "放宽跳转"
#: config/epiphany/epiphany.opt:36
#, fuzzy
-#| msgid "Enable all optional instructions"
msgid "enable conditional move instruction usage."
msgstr "å¯ç”¨æ‰€æœ‰å¯é€‰æŒ‡ä»¤"
#: config/epiphany/epiphany.opt:40
#, fuzzy
-#| msgid "The number of insns executed before prefetch is completed"
msgid "set number of nops to emit before each insn pattern"
msgstr "预å–æ“作完æˆå‰æ‰§è¡ŒæŒ‡ä»¤çš„æ•°ç›®"
#: config/epiphany/epiphany.opt:52
#, fuzzy
-#| msgid "Use software floating point"
msgid "Use software floating point comparisons"
msgstr "使用软件浮点å•å…ƒ"
@@ -7918,13 +7744,11 @@ msgstr ""
#: config/epiphany/epiphany.opt:76
#, fuzzy
-#| msgid "Generate call insns as indirect calls, if necessary"
msgid "Generate call insns as indirect calls"
msgstr "如有必须,为调用指令生æˆé—´æŽ¥è°ƒç”¨"
#: config/epiphany/epiphany.opt:80
#, fuzzy
-#| msgid "Generate call insns as indirect calls, if necessary"
msgid "Generate call insns as direct calls"
msgstr "如有必须,为调用指令生æˆé—´æŽ¥è°ƒç”¨"
@@ -7938,7 +7762,6 @@ msgstr ""
#: config/epiphany/epiphany.opt:112
#, fuzzy
-#| msgid "Use structs on stronger alignment for double-word copies"
msgid "Vectorize for double-word operations."
msgstr "为结构使用更强的对é½ä»¥ä½¿ç”¨åŒå­—å¤åˆ¶"
@@ -7948,7 +7771,6 @@ msgstr ""
#: config/epiphany/epiphany.opt:132
#, fuzzy
-#| msgid "Use hardware floating point conversion instructions"
msgid "Use the floating point unit for integer add/subtract."
msgstr "使用浮点转æ¢æŒ‡ä»¤"
@@ -8184,7 +8006,6 @@ msgstr "sizeof(long double) 等于 12"
#: config/i386/i386.opt:190
#, fuzzy
-#| msgid "Use 128-bit long double"
msgid "Use 80-bit long double"
msgstr "使用 128 ä½ long double"
@@ -8244,7 +8065,6 @@ msgstr ""
#: config/i386/i386.opt:271
#, fuzzy
-#| msgid "Use given x86-64 code model"
msgid "Use given address mode"
msgstr "使用给定的 x86-64 代ç æ¨¡å¼"
@@ -8291,19 +8111,16 @@ msgstr "ä¸å»ºè®®ä½¿ç”¨%<-mintel-syntax%>å’Œ %<-mno-intel-syntax%>;请改用%<
#: config/i386/i386.opt:369
#, fuzzy
-#| msgid "Set 80387 floating-point precision (-mpc32, -mpc64, -mpc80)"
msgid "Set 80387 floating-point precision to 32-bit"
msgstr "设定 80387 浮点精度(-mpc32ã€-mpc64ã€-mpc80)"
#: config/i386/i386.opt:373
#, fuzzy
-#| msgid "Set 80387 floating-point precision (-mpc32, -mpc64, -mpc80)"
msgid "Set 80387 floating-point precision to 64-bit"
msgstr "设定 80387 浮点精度(-mpc32ã€-mpc64ã€-mpc80)"
#: config/i386/i386.opt:377
#, fuzzy
-#| msgid "Set 80387 floating-point precision (-mpc32, -mpc64, -mpc80)"
msgid "Set 80387 floating-point precision to 80-bit"
msgstr "设定 80387 浮点精度(-mpc32ã€-mpc64ã€-mpc80)"
@@ -8361,7 +8178,6 @@ msgstr "选择生æˆå­—符串æ“作的策略"
#: config/i386/i386.opt:433
#, fuzzy
-#| msgid "bad value (%s) for %sstringop-strategy=%s %s"
msgid "Valid arguments to -mstringop-strategy=:"
msgstr "%2$sstringop-strategy=%3$s %4$s所带å‚æ•°(%1$s)ä¸æ­£ç¡®"
@@ -8425,7 +8241,6 @@ msgstr ""
#: config/i386/i386.opt:543
#, fuzzy
-#| msgid "Do dispatch scheduling if processor is bdver1 and Haifa scheduling"
msgid "Do dispatch scheduling if processor is bdver1 or bdver2 or bdver3 or bdver4 and Haifa scheduling"
msgstr "进行海法调度,当处ç†å™¨æ˜¯ bdver1 时也进行派é£è°ƒåº¦"
@@ -8443,13 +8258,11 @@ msgstr "ç”Ÿæˆ 64 ä½ x86-64 代ç "
#: config/i386/i386.opt:562
#, fuzzy
-#| msgid "Generate 64bit x86-64 code"
msgid "Generate 32bit x86-64 code"
msgstr "ç”Ÿæˆ 64 ä½ x86-64 代ç "
#: config/i386/i386.opt:566
#, fuzzy
-#| msgid "Generate 32bit i386 code"
msgid "Generate 16bit i386 code"
msgstr "ç”Ÿæˆ 32 ä½ i386 代ç "
@@ -8503,31 +8316,26 @@ msgstr "æ”¯æŒ MMXã€SSEã€SSE2ã€SSE3ã€SSSE3ã€SSE4.1ã€SSE4.2 å’Œ AVX 内建å
#: config/i386/i386.opt:622
#, fuzzy
-#| msgid "Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and FMA built-in functions and code generation"
msgid "Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and AVX2 built-in functions and code generation"
msgstr "æ”¯æŒ MMXã€SSEã€SSE2ã€SSE3ã€SSSE3ã€SSE4.1ã€SSE4.2ã€AVX å’Œ FMA 内建函数åŠä»£ç ç”Ÿæˆ"
#: config/i386/i386.opt:626
#, fuzzy
-#| msgid "Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and FMA built-in functions and code generation"
msgid "Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F built-in functions and code generation"
msgstr "æ”¯æŒ MMXã€SSEã€SSE2ã€SSE3ã€SSSE3ã€SSE4.1ã€SSE4.2ã€AVX å’Œ FMA 内建函数åŠä»£ç ç”Ÿæˆ"
#: config/i386/i386.opt:630
#, fuzzy
-#| msgid "Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and FMA built-in functions and code generation"
msgid "Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512PF built-in functions and code generation"
msgstr "æ”¯æŒ MMXã€SSEã€SSE2ã€SSE3ã€SSSE3ã€SSE4.1ã€SSE4.2ã€AVX å’Œ FMA 内建函数åŠä»£ç ç”Ÿæˆ"
#: config/i386/i386.opt:634
#, fuzzy
-#| msgid "Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and FMA built-in functions and code generation"
msgid "Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512ER built-in functions and code generation"
msgstr "æ”¯æŒ MMXã€SSEã€SSE2ã€SSE3ã€SSSE3ã€SSE4.1ã€SSE4.2ã€AVX å’Œ FMA 内建函数åŠä»£ç ç”Ÿæˆ"
#: config/i386/i386.opt:638
#, fuzzy
-#| msgid "Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and FMA built-in functions and code generation"
msgid "Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512CD built-in functions and code generation"
msgstr "æ”¯æŒ MMXã€SSEã€SSE2ã€SSE3ã€SSSE3ã€SSE4.1ã€SSE4.2ã€AVX å’Œ FMA 内建函数åŠä»£ç ç”Ÿæˆ"
@@ -8565,13 +8373,11 @@ msgstr "æ”¯æŒ BMI 内建函数åŠä»£ç ç”Ÿæˆ"
#: config/i386/i386.opt:674
#, fuzzy
-#| msgid "Support BMI built-in functions and code generation"
msgid "Support BMI2 built-in functions and code generation"
msgstr "æ”¯æŒ BMI 内建函数åŠä»£ç ç”Ÿæˆ"
#: config/i386/i386.opt:678
#, fuzzy
-#| msgid "Support TBM built-in functions and code generation"
msgid "Support LZCNT built-in function and code generation"
msgstr "æ”¯æŒ TBM 内建函数åŠä»£ç ç”Ÿæˆ"
@@ -8581,7 +8387,6 @@ msgstr ""
#: config/i386/i386.opt:686
#, fuzzy
-#| msgid "Use SmartMIPS instructions"
msgid "Support RDSEED instruction"
msgstr "使用 SmartMIPS 指令"
@@ -8591,7 +8396,6 @@ msgstr ""
#: config/i386/i386.opt:694
#, fuzzy
-#| msgid "Support code generation of crc32 instruction."
msgid "Support flag-preserving add-carry instructions"
msgstr "支æŒç”Ÿæˆ crc32 指令。"
@@ -8601,13 +8405,11 @@ msgstr ""
#: config/i386/i386.opt:702
#, fuzzy
-#| msgid "Support calls between Thumb and ARM instruction sets"
msgid "Support XSAVE and XRSTOR instructions"
msgstr "æ”¯æŒ Thumb å’Œ ARM 指令集间互相调用g"
#: config/i386/i386.opt:706
#, fuzzy
-#| msgid "Support MMX built-in functions"
msgid "Support XSAVEOPT instruction"
msgstr "æ”¯æŒ MMX 内建函数"
@@ -8637,7 +8439,6 @@ msgstr "æ”¯æŒ AES 内建函数åŠä»£ç ç”Ÿæˆ"
#: config/i386/i386.opt:734
#, fuzzy
-#| msgid "Support MMX and SSE built-in functions and code generation"
msgid "Support SHA1 and SHA256 built-in functions and code generation"
msgstr "æ”¯æŒ MMX å’Œ SSE 内建函数åŠä»£ç ç”Ÿæˆ"
@@ -8680,13 +8481,11 @@ msgstr ""
#: config/i386/i386.opt:774
#, fuzzy
-#| msgid "Support TBM built-in functions and code generation"
msgid "Support RTM built-in functions and code generation"
msgstr "æ”¯æŒ TBM 内建函数åŠä»£ç ç”Ÿæˆ"
#: config/i386/i386.opt:778
#, fuzzy
-#| msgid "Use propolice as a stack protection method"
msgid "Use given stack-protector guard"
msgstr "使用 propolice æ¥ä¿æŠ¤å †æ ˆ"
@@ -8805,7 +8604,6 @@ msgstr "å¯ç”¨åŽç«¯è°ƒè¯•"
#: config/v850/v850.opt:41
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the callt instruction (default)"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -8871,13 +8669,11 @@ msgstr "为 v850e2v3 处ç†å™¨ç¼–译"
#: config/v850/v850.opt:117
#, fuzzy
-#| msgid "Compile for the v850e processor"
msgid "Compile for the v850e3v5 processor"
msgstr "为 v850e 处ç†å™¨ç¼–译"
#: config/v850/v850.opt:124
#, fuzzy
-#| msgid "Enable clip instructions"
msgid "Enable v850e3v5 loop instructions"
msgstr "å¯ç”¨ clip 指令"
@@ -8887,37 +8683,31 @@ msgstr "为 ZDA 区域åˆæ ¼çš„æ•°æ®è®¾ç½®æœ€å¤§å°ºå¯¸"
#: config/v850/v850.opt:135
#, fuzzy
-#| msgid "Enable the rank heuristic in the scheduler"
msgid "Enable relaxing in the assembler"
msgstr "在调度器中å¯ç”¨ç§©å¯å‘"
#: config/v850/v850.opt:139
#, fuzzy
-#| msgid "Prohibit PC relative function calls"
msgid "Prohibit PC relative jumps"
msgstr "ç¦æ­¢ç›¸å¯¹ PC 的函数调用"
#: config/v850/v850.opt:143
#, fuzzy
-#| msgid "Prevent the use of all hardware floating-point instructions"
msgid "Inhibit the use of hardware floating point instructions"
msgstr "ä¸å…许使用任何硬件浮点指令"
#: config/v850/v850.opt:147
#, fuzzy
-#| msgid "Allow the use of hardware floating-point ABI and instructions"
msgid "Allow the use of hardware floating point instructions for V850E2V3 and up"
msgstr "å…许使用硬件浮点 ABI 和指令"
#: config/v850/v850.opt:151
#, fuzzy
-#| msgid "Enable the use of RX FPU instructions. This is the default."
msgid "Enable support for the RH850 ABI. This is the default"
msgstr "å¯ç”¨ä½¿ç”¨ RX FPU 指令。这是默认值。"
#: config/v850/v850.opt:155
#, fuzzy
-#| msgid "Enable support for huge objects"
msgid "Enable support for the old GCC ABI"
msgstr "å¯ç”¨å¯¹å·¨åž‹å¯¹è±¡çš„支æŒ"
@@ -8951,13 +8741,11 @@ msgstr "å‡å®š VxWorks vThreads 环境"
#: config/cr16/cr16.opt:23
#, fuzzy
-#| msgid "-msim\tUse simulator runtime"
msgid "-msim Use simulator runtime"
msgstr "-msim\t使用仿真器è¿è¡Œæ—¶"
#: config/cr16/cr16.opt:27
#, fuzzy
-#| msgid "Generate bit instructions"
msgid "Generate SBIT, CBIT instructions"
msgstr "生æˆä½æŒ‡ä»¤"
@@ -8971,19 +8759,16 @@ msgstr ""
#: config/cr16/cr16.opt:42
#, fuzzy
-#| msgid "Generate code for a cpu32"
msgid "Generate code for CR16C architecture"
msgstr "为 cpu32 生æˆä»£ç "
#: config/cr16/cr16.opt:46
#, fuzzy
-#| msgid "Generate code for GNU assembler (gas)"
msgid "Generate code for CR16C+ architecture (Default)"
msgstr "为 GNU 汇编器(gas)生æˆä»£ç "
#: config/cr16/cr16.opt:50
#, fuzzy
-#| msgid "Pointers are 32-bit"
msgid "Treat integers as 32-bit."
msgstr "指针是 32 ä½"
@@ -9038,7 +8823,6 @@ msgstr ""
#: config/avr/avr.opt:80
#, fuzzy
-#| msgid "taking the address of a label is non-standard"
msgid "Warn if the address space of an address is changed."
msgstr "å–æ ‡å·çš„地å€ä¸ç¬¦åˆæ ‡å‡†"
@@ -9157,7 +8941,6 @@ msgstr "使用 128 ä½ long double"
#: config/s390/s390.opt:117
#, fuzzy
-#| msgid "Use hardware floating point instructions"
msgid "Use hardware transactional execution instructions"
msgstr "使用硬件浮点指令"
@@ -9203,7 +8986,6 @@ msgstr ""
#: config/s390/s390.opt:167 config/rs6000/rs6000.opt:470
#, fuzzy
-#| msgid "Use ROM instead of RAM"
msgid "Use LRA instead of reload"
msgstr "使用 ROM 而ä¸æ˜¯ RAM"
@@ -9217,7 +8999,6 @@ msgstr ""
#: config/rl78/rl78.opt:47
#, fuzzy
-#| msgid "Specifies the number of registers to reserve for interrupt handlers."
msgid "Use all registers, reserving none for interrupt handlers."
msgstr "指定ä¿ç•™ç»™ä¸­æ–­å¤„ç†å‡½æ•°ä½¿ç”¨çš„寄存器的数é‡"
@@ -9227,7 +9008,6 @@ msgstr ""
#: config/rl78/rl78.opt:55
#, fuzzy
-#| msgid "Target the AM33/2.0 processor"
msgid "Target the RL78/G10 series"
msgstr "目标为 AM33/2.0 处ç†å™¨"
@@ -9277,7 +9057,6 @@ msgstr "生æˆå¯é‡å…¥çš„ PIC 代ç "
#: config/arm/arm.opt:90
#, fuzzy
-#| msgid "Generate code for 32 bit addressing"
msgid "Generate code in 32 bit ARM state."
msgstr "为 32 ä½å¯»å€ç”Ÿæˆä»£ç "
@@ -9303,7 +9082,6 @@ msgstr "指定 __fp16 浮点格å¼"
#: config/arm/arm.opt:131
#, fuzzy
-#| msgid "invalid __fp16 format option: -mfp16-format=%s"
msgid "Known __fp16 formats (for use with the -mfp16-format= option):"
msgstr "无效的 __fp16 浮点选项:-mfp16-format=%s"
@@ -9317,7 +9095,6 @@ msgstr "如有必须,为调用指令生æˆé—´æŽ¥è°ƒç”¨"
#: config/arm/arm.opt:163
#, fuzzy
-#| msgid "Assume arguments alias no other storage"
msgid "Assume data segments are relative to text segment."
msgstr "å‡å®šå®žå‚ä¸ä¸Žå…¶ä»–存储é‡å "
@@ -9343,7 +9120,6 @@ msgstr "为结构指定最å°ä½å¯¹é½"
#: config/arm/arm.opt:190
#, fuzzy
-#| msgid "Generate code for GNU as"
msgid "Generate code for Thumb state"
msgstr "为 GNU as 生æˆä»£ç "
@@ -9353,7 +9129,6 @@ msgstr "æ”¯æŒ Thumb å’Œ ARM 指令集间互相调用g"
#: config/arm/arm.opt:198
#, fuzzy
-#| msgid "Use given thread-local storage dialect"
msgid "Specify thread local storage scheme"
msgstr "使用给定的线程局部存储模å¼"
@@ -9380,7 +9155,6 @@ msgstr "为指定的处ç†å™¨ä¼˜åŒ–代ç "
#: config/arm/arm.opt:236
#, fuzzy
-#| msgid "Assume big endian bytes, little endian words"
msgid "Assume big endian bytes, little endian words. This option is deprecated."
msgstr "å‡å®šé«˜ä½å­—节在å‰ï¼Œä½Žä½å­—在å‰"
@@ -9390,7 +9164,6 @@ msgstr "使用 Neon 四字(而éžåŒå­—)寄存器æ¥è¿›è¡Œå‘é‡åŒ–"
#: config/arm/arm.opt:244
#, fuzzy
-#| msgid "Use Neon quad-word (rather than double-word) registers for vectorization"
msgid "Use Neon double-word (rather than quad-word) registers for vectorization"
msgstr "使用 Neon 四字(而éžåŒå­—)寄存器æ¥è¿›è¡Œå‘é‡åŒ–"
@@ -9436,7 +9209,6 @@ msgstr "ä¸ä½¿ç”¨ç¡¬ä»¶æµ®ç‚¹å•å…ƒ"
#: config/sparc/sparc.opt:42
#, fuzzy
-#| msgid "Use alternate register names"
msgid "Use flat register window model"
msgstr "使用å¦ä¸€å¥—寄存器å"
@@ -9462,37 +9234,31 @@ msgstr "为 V8+ ABI 编译"
#: config/sparc/sparc.opt:66
#, fuzzy
-#| msgid "Use UltraSPARC Visual Instruction Set extensions"
msgid "Use UltraSPARC Visual Instruction Set version 1.0 extensions"
msgstr "使用 UltraSPARC å¯è§†åŒ–指令集"
#: config/sparc/sparc.opt:70
#, fuzzy
-#| msgid "Use UltraSPARC Visual Instruction Set extensions"
msgid "Use UltraSPARC Visual Instruction Set version 2.0 extensions"
msgstr "使用 UltraSPARC å¯è§†åŒ–指令集"
#: config/sparc/sparc.opt:74
#, fuzzy
-#| msgid "Use UltraSPARC Visual Instruction Set extensions"
msgid "Use UltraSPARC Visual Instruction Set version 3.0 extensions"
msgstr "使用 UltraSPARC å¯è§†åŒ–指令集"
#: config/sparc/sparc.opt:78
#, fuzzy
-#| msgid "Use UltraSPARC Visual Instruction Set extensions"
msgid "Use UltraSPARC Compare-and-Branch extensions"
msgstr "使用 UltraSPARC å¯è§†åŒ–指令集"
#: config/sparc/sparc.opt:82
#, fuzzy
-#| msgid "Use UltraSPARC Visual Instruction Set extensions"
msgid "Use UltraSPARC Fused Multiply-Add extensions"
msgstr "使用 UltraSPARC å¯è§†åŒ–指令集"
#: config/sparc/sparc.opt:86
#, fuzzy
-#| msgid "Use hardware floating point instructions"
msgid "Use UltraSPARC Population-Count instruction"
msgstr "使用硬件浮点指令"
@@ -9534,7 +9300,6 @@ msgstr "使用给定的 SPARC-V9 代ç æ¨¡åž‹"
#: config/sparc/sparc.opt:196
#, fuzzy
-#| msgid "-mdebug=\tEnable debug output"
msgid "Enable debug output"
msgstr "-mdebug=\tå¯ç”¨è°ƒè¯•è¾“出"
@@ -9628,13 +9393,11 @@ msgstr "使用 AltiVec 指令"
#: config/rs6000/rs6000.opt:145
#, fuzzy
-#| msgid "Generate code in little endian mode"
msgid "Generate Altivec instructions using little-endian element order"
msgstr "生æˆå°ç«¯åœ¨å‰çš„代ç "
#: config/rs6000/rs6000.opt:149
#, fuzzy
-#| msgid "Generate VRSAVE instructions when generating AltiVec code"
msgid "Generate Altivec instructions using big-endian element order"
msgstr "ç”Ÿæˆ AltiVec 代ç æ—¶ç”Ÿæˆ VRSAVE 指令"
@@ -9741,13 +9504,11 @@ msgstr "ç”Ÿæˆ AltiVec 代ç æ—¶ç”Ÿæˆ VRSAVE 指令"
#: config/rs6000/rs6000.opt:322
#, fuzzy
-#| msgid "-mvrsave=yes/no\tDeprecated option. Use -mvrsave/-mno-vrsave instead"
msgid "Deprecated option. Use -mno-vrsave instead"
msgstr "-mvrsave=yes/no\tä¸å»ºè®®ä½¿ç”¨çš„选项。请改用 -mvrsave/-mno-vrsave"
#: config/rs6000/rs6000.opt:326
#, fuzzy
-#| msgid "Deprecated. Use -Os instead"
msgid "Deprecated option. Use -mvrsave instead"
msgstr "ä¸å»ºè®®ä½¿ç”¨ã€‚请改用 -Os"
@@ -9761,13 +9522,11 @@ msgstr "ç”Ÿæˆ isel 指令"
#: config/rs6000/rs6000.opt:338
#, fuzzy
-#| msgid "-misel=yes/no\tDeprecated option. Use -misel/-mno-isel instead"
msgid "Deprecated option. Use -mno-isel instead"
msgstr "-misel=yes/no\tä¸å»ºè®®ä½¿ç”¨çš„选项。请改用 -misel/-mno-isel"
#: config/rs6000/rs6000.opt:342
#, fuzzy
-#| msgid "Deprecated. Use -Os instead"
msgid "Deprecated option. Use -misel instead"
msgstr "ä¸å»ºè®®ä½¿ç”¨ã€‚请改用 -Os"
@@ -9781,13 +9540,11 @@ msgstr "ç”Ÿæˆ PPC750CL é…对å•ç²¾åº¦æŒ‡ä»¤"
#: config/rs6000/rs6000.opt:354
#, fuzzy
-#| msgid "-mspe=yes/no\tDeprecated option. Use -mspe/-mno-spe instead"
msgid "Deprecated option. Use -mno-spe instead"
msgstr "-mspe=yes/no\tä¸å»ºè®®ä½¿ç”¨çš„选项。请改用 -mspe/-mno-spe"
#: config/rs6000/rs6000.opt:358
#, fuzzy
-#| msgid "Deprecated. Use -Os instead"
msgid "Deprecated option. Use -mspe instead"
msgstr "ä¸å»ºè®®ä½¿ç”¨ã€‚请改用 -Os"
@@ -9797,37 +9554,31 @@ msgstr "-mdebug=\tå¯ç”¨è°ƒè¯•è¾“出"
#: config/rs6000/rs6000.opt:366
#, fuzzy
-#| msgid "Use the Cray Pointer extension"
msgid "Use the AltiVec ABI extensions"
msgstr "使用 Cray 指针扩展"
#: config/rs6000/rs6000.opt:370
#, fuzzy
-#| msgid "Do not use the bit-field instructions"
msgid "Do not use the AltiVec ABI extensions"
msgstr "ä¸ä½¿ç”¨ä½æ®µæŒ‡ä»¤"
#: config/rs6000/rs6000.opt:374
#, fuzzy
-#| msgid "Use the Cray Pointer extension"
msgid "Use the SPE ABI extensions"
msgstr "使用 Cray 指针扩展"
#: config/rs6000/rs6000.opt:378
#, fuzzy
-#| msgid "Do not use the bit-field instructions"
msgid "Do not use the SPE ABI extensions"
msgstr "ä¸ä½¿ç”¨ä½æ®µæŒ‡ä»¤"
#: config/rs6000/rs6000.opt:382
#, fuzzy
-#| msgid "Use EABI"
msgid "Use the ELFv1 ABI"
msgstr "使用 EABI"
#: config/rs6000/rs6000.opt:386
#, fuzzy
-#| msgid "Use EABI"
msgid "Use the ELFv2 ABI"
msgstr "使用 EABI"
@@ -9947,7 +9698,6 @@ msgstr ""
#: config/rs6000/rs6000.opt:554
#, fuzzy
-#| msgid "Align destination of the string operations"
msgid "Allow sign extension in fusion operations"
msgstr "对é½å­—符串æ“作的目标"
@@ -9957,7 +9707,6 @@ msgstr ""
#: config/rs6000/rs6000.opt:562
#, fuzzy
-#| msgid "Use SmartMIPS instructions"
msgid "Use ISA 2.07 crypto instructions"
msgstr "使用 SmartMIPS 指令"
@@ -9967,13 +9716,11 @@ msgstr ""
#: config/rs6000/rs6000.opt:570
#, fuzzy
-#| msgid "Use vector/scalar (VSX) instructions"
msgid "Use ISA 2.07 transactional memory (HTM) instructions"
msgstr "使用å‘é‡/æ ‡é‡(VSX)指令"
#: config/rs6000/rs6000.opt:574
#, fuzzy
-#| msgid "Generate load/store multiple instructions"
msgid "Generate the quad word memory instructions (lq/stq)."
msgstr "生æˆåŠ è½½/存储乘法指令"
@@ -10165,7 +9912,6 @@ msgstr ""
#: config/tilepro/tilepro.opt:28 config/tilegx/tilegx.opt:26
#, fuzzy
-#| msgid "-mcpu=\tUse features of and schedule code for given CPU"
msgid "-mcpu=CPU\tUse features of and schedule code for given CPU"
msgstr "-mcpu=\t使用指定 CPU 的特性和调度代ç "
@@ -10195,7 +9941,6 @@ msgstr "å¯ç”¨ç”¨æˆ·è‡ªå®šä¹‰æŒ‡ä»¤"
#: config/nios2/elf.opt:26
#, fuzzy
-#| msgid "Link with the fast floating-point library"
msgid "Link with a limited version of the C library"
msgstr "与快速浮点库链接"
@@ -10217,7 +9962,6 @@ msgstr ""
#: config/nios2/nios2.opt:39
#, fuzzy
-#| msgid "Enable clip instructions"
msgid "Enable MUL instructions"
msgstr "å¯ç”¨ clip 指令"
@@ -10227,19 +9971,16 @@ msgstr ""
#: config/nios2/nios2.opt:47
#, fuzzy
-#| msgid "Use the software emulation for divides (default)"
msgid "Use table based fast divide (default at -O3)"
msgstr "使用软件模拟除法(默认)"
#: config/nios2/nios2.opt:51
#, fuzzy
-#| msgid "Enable unaligned load/store instruction"
msgid "All memory accesses use I/O load/store instructions"
msgstr "å¯ç”¨ä¸å¯¹é½çš„载入/存储指令"
#: config/nios2/nios2.opt:55
#, fuzzy
-#| msgid "Enable unaligned load/store instruction"
msgid "Volatile memory accesses use I/O load/store instructions"
msgstr "å¯ç”¨ä¸å¯¹é½çš„载入/存储指令"
@@ -10268,7 +10009,6 @@ msgstr "大定点常é‡éšå¼æˆªæ–­ä¸ºå®šç‚¹ç±»åž‹"
#: config/nios2/nios2.opt:79
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the ftruncds custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10278,7 +10018,6 @@ msgstr ""
#: config/nios2/nios2.opt:87
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fextsd custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10288,19 +10027,16 @@ msgstr ""
#: config/nios2/nios2.opt:95
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fixdu custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
#: config/nios2/nios2.opt:99
#, fuzzy
-#| msgid "Enable divide and modulus instructions"
msgid "Integer id (N) of fixdu custom instruction"
msgstr "å¯ç”¨é™¤æ³•å’Œæ±‚余指令"
#: config/nios2/nios2.opt:103
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fixdi custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10310,7 +10046,6 @@ msgstr ""
#: config/nios2/nios2.opt:111
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fixsu custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10320,7 +10055,6 @@ msgstr ""
#: config/nios2/nios2.opt:119
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fixsi custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10330,31 +10064,26 @@ msgstr ""
#: config/nios2/nios2.opt:127
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the floatud custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
#: config/nios2/nios2.opt:131
#, fuzzy
-#| msgid "Enable unaligned load/store instruction"
msgid "Integer id (N) of floatud custom instruction"
msgstr "å¯ç”¨ä¸å¯¹é½çš„载入/存储指令"
#: config/nios2/nios2.opt:135
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the floatid custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
#: config/nios2/nios2.opt:139
#, fuzzy
-#| msgid "Enable unaligned load/store instruction"
msgid "Integer id (N) of floatid custom instruction"
msgstr "å¯ç”¨ä¸å¯¹é½çš„载入/存储指令"
#: config/nios2/nios2.opt:143
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the floatus custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10364,7 +10093,6 @@ msgstr ""
#: config/nios2/nios2.opt:151
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the floatis custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10374,7 +10102,6 @@ msgstr ""
#: config/nios2/nios2.opt:159
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fcmpned custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10384,7 +10111,6 @@ msgstr ""
#: config/nios2/nios2.opt:167
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fcmpeqd custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10394,7 +10120,6 @@ msgstr ""
#: config/nios2/nios2.opt:175
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fcmpged custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10404,7 +10129,6 @@ msgstr ""
#: config/nios2/nios2.opt:183
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fcmpgtd custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10414,7 +10138,6 @@ msgstr ""
#: config/nios2/nios2.opt:191
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fcmpled custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10424,7 +10147,6 @@ msgstr ""
#: config/nios2/nios2.opt:199
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fcmpltd custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10434,7 +10156,6 @@ msgstr ""
#: config/nios2/nios2.opt:207
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the flogd custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10444,7 +10165,6 @@ msgstr ""
#: config/nios2/nios2.opt:215
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fexpd custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10454,7 +10174,6 @@ msgstr ""
#: config/nios2/nios2.opt:223
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fatand custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10464,19 +10183,16 @@ msgstr ""
#: config/nios2/nios2.opt:231
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the ftand custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
#: config/nios2/nios2.opt:235
#, fuzzy
-#| msgid "Enable divide and modulus instructions"
msgid "Integer id (N) of ftand custom instruction"
msgstr "å¯ç”¨é™¤æ³•å’Œæ±‚余指令"
#: config/nios2/nios2.opt:239
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fsind custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10486,7 +10202,6 @@ msgstr ""
#: config/nios2/nios2.opt:247
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fcosd custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10496,7 +10211,6 @@ msgstr ""
#: config/nios2/nios2.opt:255
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fsqrtd custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10506,7 +10220,6 @@ msgstr ""
#: config/nios2/nios2.opt:263
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fabsd custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10516,7 +10229,6 @@ msgstr ""
#: config/nios2/nios2.opt:271
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fnegd custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10526,7 +10238,6 @@ msgstr ""
#: config/nios2/nios2.opt:279
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fmaxd custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10536,7 +10247,6 @@ msgstr ""
#: config/nios2/nios2.opt:287
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fmind custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10546,7 +10256,6 @@ msgstr ""
#: config/nios2/nios2.opt:295
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fdivd custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10556,19 +10265,16 @@ msgstr ""
#: config/nios2/nios2.opt:303
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fmuld custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
#: config/nios2/nios2.opt:307
#, fuzzy
-#| msgid "Enable divide and modulus instructions"
msgid "Integer id (N) of fmuld custom instruction"
msgstr "å¯ç”¨é™¤æ³•å’Œæ±‚余指令"
#: config/nios2/nios2.opt:311
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fsubd custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10578,7 +10284,6 @@ msgstr ""
#: config/nios2/nios2.opt:319
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the faddd custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10588,7 +10293,6 @@ msgstr ""
#: config/nios2/nios2.opt:327
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fcmpnes custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10598,7 +10302,6 @@ msgstr ""
#: config/nios2/nios2.opt:335
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fcmpeqs custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10608,7 +10311,6 @@ msgstr ""
#: config/nios2/nios2.opt:343
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fcmpges custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10618,7 +10320,6 @@ msgstr ""
#: config/nios2/nios2.opt:351
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fcmpgts custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10628,7 +10329,6 @@ msgstr ""
#: config/nios2/nios2.opt:359
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fcmples custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10638,7 +10338,6 @@ msgstr ""
#: config/nios2/nios2.opt:367
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fcmplts custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10648,7 +10347,6 @@ msgstr ""
#: config/nios2/nios2.opt:375
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the flogs custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10658,7 +10356,6 @@ msgstr ""
#: config/nios2/nios2.opt:383
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fexps custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10668,7 +10365,6 @@ msgstr ""
#: config/nios2/nios2.opt:391
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fatans custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10678,7 +10374,6 @@ msgstr ""
#: config/nios2/nios2.opt:399
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the ftans custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10688,7 +10383,6 @@ msgstr ""
#: config/nios2/nios2.opt:407
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fsins custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10698,7 +10392,6 @@ msgstr ""
#: config/nios2/nios2.opt:415
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fcoss custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10708,7 +10401,6 @@ msgstr ""
#: config/nios2/nios2.opt:423
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fsqrts custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10718,7 +10410,6 @@ msgstr ""
#: config/nios2/nios2.opt:431
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fabss custom instr"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10728,7 +10419,6 @@ msgstr ""
#: config/nios2/nios2.opt:439
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fnegs custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10738,7 +10428,6 @@ msgstr ""
#: config/nios2/nios2.opt:447
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fmaxs custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10748,7 +10437,6 @@ msgstr ""
#: config/nios2/nios2.opt:455
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fmins custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10758,7 +10446,6 @@ msgstr ""
#: config/nios2/nios2.opt:463
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fdivs custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10768,19 +10455,16 @@ msgstr ""
#: config/nios2/nios2.opt:471
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fmuls custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
#: config/nios2/nios2.opt:475
#, fuzzy
-#| msgid "Enable divide and modulus instructions"
msgid "Integer id (N) of fmuls custom instruction"
msgstr "å¯ç”¨é™¤æ³•å’Œæ±‚余指令"
#: config/nios2/nios2.opt:479
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fsubs custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10790,7 +10474,6 @@ msgstr ""
#: config/nios2/nios2.opt:487
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fadds custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10800,7 +10483,6 @@ msgstr ""
#: config/nios2/nios2.opt:495
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the frdy custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10810,7 +10492,6 @@ msgstr ""
#: config/nios2/nios2.opt:503
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the frdxhi custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10820,7 +10501,6 @@ msgstr ""
#: config/nios2/nios2.opt:511
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the frdxlo custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10830,7 +10510,6 @@ msgstr ""
#: config/nios2/nios2.opt:519
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fwry custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10840,7 +10519,6 @@ msgstr ""
#: config/nios2/nios2.opt:527
#, fuzzy
-#| msgid "Do not use the callt instruction"
msgid "Do not use the fwrx custom instruction"
msgstr "ä¸ä½¿ç”¨ callt 指令"
@@ -10882,7 +10560,6 @@ msgstr "能被放在å°å†…存区的全局和é™æ€å˜é‡çš„最大尺寸。"
#: config/rx/rx.opt:93
#, fuzzy
-#| msgid "Generate assembler output that is compatible with the Renesas AS100 assembler. This may restrict some of the compiler's capabilities. The default is to generate GAS compatable syntax."
msgid "Generate assembler output that is compatible with the Renesas AS100 assembler. This may restrict some of the compiler's capabilities. The default is to generate GAS compatible syntax."
msgstr "生æˆä¸Ž Renesas AS100 兼容的汇编输出。这å¯èƒ½ä¼šé™åˆ¶ç¼–译器的æŸäº›åŠŸèƒ½ã€‚默认是使用与 GAS 兼容的语法。"
@@ -10920,7 +10597,6 @@ msgstr ""
#: config/rx/rx.opt:141
#, fuzzy
-#| msgid "Enable the use of the short load instructions"
msgid "Enable the use of the LRA register allocator."
msgstr "å¯ç”¨å¯¹çŸ­åŠ è½½æŒ‡ä»¤çš„使用"
@@ -10977,7 +10653,6 @@ msgstr "使用浮点åŒç²¾åº¦æŒ‡ä»¤"
#: config/microblaze/microblaze.opt:87
#, fuzzy, c-format
-#| msgid "%qE is deprecated: %s"
msgid "%qs is deprecated; use -fstack-check"
msgstr "ä¸å»ºè®®ä½¿ç”¨%qE:%s"
@@ -10991,7 +10666,6 @@ msgstr "使用相对 GP 的 sdata/sbss 节"
#: config/microblaze/microblaze.opt:95
#, fuzzy, c-format
-#| msgid "-mno-clearbss is deprecated; use -fno-zero-initialized-in-bss"
msgid "%qs is deprecated; use -fno-zero-initialized-in-bss"
msgstr "-mno-clearbsså·²ä¸å»ºè®®ä½¿ç”¨ï¼›è¯·æ”¹ç”¨ -fno-zero-initialized-in-bss"
@@ -11225,61 +10899,51 @@ msgstr "å…许 gcc ç”Ÿæˆ LIW 指令"
#: config/mn10300/mn10300.opt:67
#, fuzzy
-#| msgid "Allow gcc to generate LIW instructions"
msgid "Allow gcc to generate the SETLB and Lcc instructions"
msgstr "å…许 gcc ç”Ÿæˆ LIW 指令"
#: config/nds32/nds32.opt:26
#, fuzzy
-#| msgid "Generate code in big endian mode"
msgid "Generate code in big-endian mode."
msgstr "生æˆå¤§ç«¯åœ¨å‰çš„代ç "
#: config/nds32/nds32.opt:30
#, fuzzy
-#| msgid "Generate code in little endian mode"
msgid "Generate code in little-endian mode."
msgstr "生æˆå°ç«¯åœ¨å‰çš„代ç "
#: config/nds32/nds32.opt:34
#, fuzzy
-#| msgid "Reschedule instructions before register allocation"
msgid "Use reduced-set registers for register allocation."
msgstr "分é…寄存器å‰é‡æ–°è°ƒåº¦æŒ‡ä»¤"
#: config/nds32/nds32.opt:38
#, fuzzy
-#| msgid "Reschedule instructions before register allocation"
msgid "Use full-set registers for register allocation."
msgstr "分é…寄存器å‰é‡æ–°è°ƒåº¦æŒ‡ä»¤"
#: config/nds32/nds32.opt:42
#, fuzzy
-#| msgid "Generate bit instructions"
msgid "Generate conditional move instructions."
msgstr "生æˆä½æŒ‡ä»¤"
#: config/nds32/nds32.opt:46
#, fuzzy
-#| msgid "Generate bit instructions"
msgid "Generate performance extension instructions."
msgstr "生æˆä½æŒ‡ä»¤"
#: config/nds32/nds32.opt:50
#, fuzzy
-#| msgid "Generate isel instructions"
msgid "Generate v3 push25/pop25 instructions."
msgstr "ç”Ÿæˆ isel 指令"
#: config/nds32/nds32.opt:54
#, fuzzy
-#| msgid "Generate bit instructions"
msgid "Generate 16-bit instructions."
msgstr "生æˆä½æŒ‡ä»¤"
#: config/nds32/nds32.opt:58
#, fuzzy
-#| msgid "Generate isel instructions"
msgid "Generate GP base instructions directly."
msgstr "ç”Ÿæˆ isel 指令"
@@ -11293,7 +10957,6 @@ msgstr ""
#: config/nds32/nds32.opt:70
#, fuzzy
-#| msgid "Specify the name of the target architecture"
msgid "Specify the name of the target architecture."
msgstr "指定目标架构的å称"
@@ -11307,19 +10970,16 @@ msgstr ""
#: config/nds32/nds32.opt:94
#, fuzzy
-#| msgid "Run predictive commoning optimization."
msgid "Use special directives to guide linker doing ex9 optimization."
msgstr "å¯ç”¨é¢„测公因å­ä¼˜åŒ–。"
#: config/nds32/nds32.opt:98
#, fuzzy
-#| msgid "Warn when all constructors and destructors are private"
msgid "Enable constructor/destructor feature."
msgstr "当所有构造函数和æžæž„函数都是ç§æœ‰æ—¶ç»™å‡ºè­¦å‘Š"
#: config/nds32/nds32.opt:102
#, fuzzy
-#| msgid "Generate isel instructions"
msgid "Guide linker to relax instructions."
msgstr "ç”Ÿæˆ isel 指令"
@@ -11353,13 +11013,11 @@ msgstr ""
#: config/c6x/c6x.opt:46
#, fuzzy
-#| msgid "alias argument not a string"
msgid "Valid arguments for the -msdata= option"
msgstr "alias çš„å‚æ•°ä¸æ˜¯ä¸€ä¸ªå­—符串"
#: config/c6x/c6x.opt:59
#, fuzzy
-#| msgid "Create a shared library"
msgid "Compile for the DSBT shared library ABI"
msgstr "生æˆä¸€ä¸ªå…±äº«åº“"
@@ -11633,7 +11291,6 @@ msgstr ""
#: config/sh/sh.opt:236 config/sh/sh.opt:240
#, fuzzy, c-format
-#| msgid "Deprecated. This switch has no effect"
msgid "%qs is deprecated and has no effect"
msgstr "ä¸å»ºè®®ä½¿ç”¨ã€‚此开关ä¸èµ·ä½œç”¨ã€‚"
@@ -11675,7 +11332,6 @@ msgstr "é’循 Renesas(å…ˆå‰è¢«ç§°ä½œ Hitachi)/SuperH 调用约定"
#: config/sh/sh.opt:277
#, fuzzy
-#| msgid "Increase the IEEE compliance for floating-point code"
msgid "Increase the IEEE compliance for floating-point comparisons"
msgstr "让浮点代ç æ›´åŠ éµå¾ª IEEE 标准"
@@ -11725,7 +11381,6 @@ msgstr ""
#: config/sh/sh.opt:331
#, fuzzy
-#| msgid "Generate code for built-in atomic operations"
msgid "Specify the model for atomic operations"
msgstr "为内建原å­æ“作生æˆä»£ç "
@@ -11751,13 +11406,11 @@ msgstr "将数æ®ä¼ è¾“周围的跳转认为是æ¡ä»¶è½¬ç§»ã€‚"
#: config/sh/sh.opt:357
#, fuzzy
-#| msgid "Enable the use of the short load instructions"
msgid "Enable the use of the fsca instruction"
msgstr "å¯ç”¨å¯¹çŸ­åŠ è½½æŒ‡ä»¤çš„使用"
#: config/sh/sh.opt:361
#, fuzzy
-#| msgid "Enable the use of the short load instructions"
msgid "Enable the use of the fsrra instruction"
msgstr "å¯ç”¨å¯¹çŸ­åŠ è½½æŒ‡ä»¤çš„使用"
@@ -11895,7 +11548,6 @@ msgstr "使用 PMC 风格的‘mad’指令"
#: config/mips/mips.opt:63
#, fuzzy
-#| msgid "Use multiply add/subtract instructions"
msgid "Use integer madd/msub instructions"
msgstr "使用乘加/å‡æŒ‡ä»¤"
@@ -11925,7 +11577,6 @@ msgstr "-mcode-readable=SETTING\t指定何时指令å…许被访问代ç "
#: config/mips/mips.opt:91
#, fuzzy
-#| msgid "invalid argument %qs to -fdebug-prefix-map"
msgid "Valid arguments to -mcode-readable=:"
msgstr "-fdebug-prefix-map çš„å‚æ•°%qs无效"
@@ -11955,7 +11606,6 @@ msgstr "使用 MIPS-DSP REV 2指令"
#: config/mips/mips.opt:146
#, fuzzy
-#| msgid "Use the bit-field instructions"
msgid "Use Enhanced Virtual Addressing instructions"
msgstr "使用ä½æ®µæŒ‡ä»¤"
@@ -11969,7 +11619,6 @@ msgstr "为未被当å‰å¯¹è±¡æ‰€å®šä¹‰çš„æ•°æ®ä½¿ç”¨ -G"
#: config/mips/mips.opt:158
#, fuzzy
-#| msgid "Work around certain R4000 errata"
msgid "Work around certain 24K errata"
msgstr "为æŸäº› R4000 缺陷æä¾›å˜é€š"
@@ -11983,7 +11632,6 @@ msgstr "为æŸäº› R4400 缺陷æä¾›å˜é€š"
#: config/mips/mips.opt:170
#, fuzzy
-#| msgid "Work around certain R4000 errata"
msgid "Work around certain RM7000 errata"
msgstr "为æŸäº› R4000 缺陷æä¾›å˜é€š"
@@ -12057,13 +11705,11 @@ msgstr "å…许使用硬件浮点 ABI 和指令"
#: config/mips/mips.opt:252
#, fuzzy
-#| msgid "Generate code that can be safely linked with MIPS16 code."
msgid "Generate code that is link-compatible with MIPS16 and microMIPS code."
msgstr "生æˆèƒ½ä¸Ž MIPS16 代ç å®‰å…¨é“¾æŽ¥çš„代ç ã€‚"
#: config/mips/mips.opt:256
#, fuzzy
-#| msgid "Does nothing. Preserved for backward compatibility."
msgid "An alias for minterlink-compressed provided for backward-compatibility."
msgstr "ä¸èµ·ä½œç”¨ã€‚为å‘å‰å…¼å®¹ä¿ç•™çš„选项。"
@@ -12109,7 +11755,6 @@ msgstr "ä¸ä¼˜åŒ–å—移动"
#: config/mips/mips.opt:300
#, fuzzy
-#| msgid "Use SmartMIPS instructions"
msgid "Use microMIPS instructions"
msgstr "使用 SmartMIPS 指令"
@@ -12123,7 +11768,6 @@ msgstr "ä¸å…许使用任何浮点æ“作"
#: config/mips/mips.opt:312
#, fuzzy
-#| msgid "Use MIPS-3D instructions"
msgid "Use MCU instructions"
msgstr "使用 MIPS-3D 指令"
@@ -12214,31 +11858,26 @@ msgstr ""
#: config/tilegx/tilegx.opt:37
#, fuzzy
-#| msgid "Compile for 32-bit pointers"
msgid "Compile with 32 bit longs and pointers."
msgstr "为 32 ä½æŒ‡é’ˆç¼–译"
#: config/tilegx/tilegx.opt:41
#, fuzzy
-#| msgid "Compile for 64-bit pointers"
msgid "Compile with 64 bit longs and pointers."
msgstr "为 64 ä½æŒ‡é’ˆç¼–译"
#: config/tilegx/tilegx.opt:45
#, fuzzy
-#| msgid "Use given x86-64 code model"
msgid "Use given TILE-Gx code model"
msgstr "使用给定的 x86-64 代ç æ¨¡å¼"
#: config/arc/arc.opt:26
#, fuzzy
-#| msgid "Generate code in big endian mode"
msgid "Compile code for big endian mode"
msgstr "生æˆå¤§ç«¯åœ¨å‰çš„代ç "
#: config/arc/arc.opt:30
#, fuzzy
-#| msgid "Stores doubles in 32 bits. This is the default."
msgid "Compile code for little endian mode. This is the default"
msgstr "以 32 ä½åŒç²¾åº¦æ•°å­˜å‚¨ã€‚这是默认值。"
@@ -12284,31 +11923,26 @@ msgstr ""
#: config/arc/arc.opt:80
#, fuzzy
-#| msgid "Generate string instructions for block moves"
msgid "Generate instructions supported by barrel shifter"
msgstr "为å—移动使用字符串指令"
#: config/arc/arc.opt:84
#, fuzzy
-#| msgid "Generate bit instructions"
msgid "Generate norm instruction"
msgstr "生æˆä½æŒ‡ä»¤"
#: config/arc/arc.opt:88
#, fuzzy
-#| msgid "Generate isel instructions"
msgid "Generate swap instruction"
msgstr "ç”Ÿæˆ isel 指令"
#: config/arc/arc.opt:92
#, fuzzy
-#| msgid "Generate load/store multiple instructions"
msgid "Generate mul64 and mulu64 instructions"
msgstr "生æˆåŠ è½½/存储乘法指令"
#: config/arc/arc.opt:96
#, fuzzy
-#| msgid "Do not generate fused multiply/add instructions"
msgid "Do not generate mpy instructions for ARC700"
msgstr "ä¸ç”Ÿæˆèžåˆçš„乘/加指令"
@@ -12322,13 +11956,11 @@ msgstr ""
#: config/arc/arc.opt:108
#, fuzzy
-#| msgid "Generate call insns as indirect calls, if necessary"
msgid "Generate call insns as register indirect calls"
msgstr "如有必须,为调用指令生æˆé—´æŽ¥è°ƒç”¨"
#: config/arc/arc.opt:112
#, fuzzy
-#| msgid "Generate cld instruction in the function prologue."
msgid "Do no generate BRcc instructions in arc_reorg."
msgstr "在函数åºè¨€ä¸­ç”Ÿæˆ cld 指令"
@@ -12346,7 +11978,6 @@ msgstr ""
#: config/arc/arc.opt:132
#, fuzzy
-#| msgid "Generate bit instructions"
msgid "FPX: Generate Single Precision FPX (fast) instructions."
msgstr "生æˆä½æŒ‡ä»¤"
@@ -12356,13 +11987,11 @@ msgstr ""
#: config/arc/arc.opt:140 config/arc/arc.opt:144
#, fuzzy
-#| msgid "Generate bit instructions"
msgid "FPX: Generate Double Precision FPX (compact) instructions."
msgstr "生æˆä½æŒ‡ä»¤"
#: config/arc/arc.opt:148
#, fuzzy
-#| msgid "Generate bit instructions"
msgid "FPX: Generate Double Precision FPX (fast) instructions."
msgstr "生æˆä½æŒ‡ä»¤"
@@ -12384,7 +12013,6 @@ msgstr ""
#: config/arc/arc.opt:187
#, fuzzy
-#| msgid "Cost to assume for a multiply insn"
msgid "Cost to assume for a multiply instruction, with 4 being equal to a normal insn."
msgstr "为乘法指令设定的开销"
@@ -12406,7 +12034,6 @@ msgstr ""
#: config/arc/arc.opt:215
#, fuzzy
-#| msgid "Enable the use of the short load instructions"
msgid "Enable the use of indexed loads"
msgstr "å¯ç”¨å¯¹çŸ­åŠ è½½æŒ‡ä»¤çš„使用"
@@ -12416,7 +12043,6 @@ msgstr ""
#: config/arc/arc.opt:223
#, fuzzy
-#| msgid "Generate fused multiply/add instructions"
msgid "Generate 32x16 multiply and mac instructions"
msgstr "生æˆèžåˆçš„乘/加指令"
@@ -12434,7 +12060,6 @@ msgstr ""
#: config/arc/arc.opt:241
#, fuzzy
-#| msgid "Avoid all range limits on call instructions"
msgid "Do alignment optimizations for call instructions."
msgstr "为调用指令é¿å…一切范围é™åˆ¶"
@@ -12448,7 +12073,6 @@ msgstr ""
#: config/arc/arc.opt:253
#, fuzzy
-#| msgid "Enable cbranchdi4 pattern"
msgid "Enable pre-reload use of cbranchsi pattern"
msgstr "å¯ç”¨ cbranchdi4 æ ·å¼"
@@ -12462,13 +12086,11 @@ msgstr ""
#: config/arc/arc.opt:265
#, fuzzy
-#| msgid "Enable cbranchdi4 pattern"
msgid "Enable compact casesi pattern"
msgstr "å¯ç”¨ cbranchdi4 æ ·å¼"
#: config/arc/arc.opt:269
#, fuzzy
-#| msgid "Enable clip instructions"
msgid "Enable 'q' instruction alternatives."
msgstr "å¯ç”¨ clip 指令"
@@ -12478,25 +12100,21 @@ msgstr ""
#: config/arc/arc.opt:280
#, fuzzy
-#| msgid "Enable Plan 9 language extensions"
msgid "Enable variable polynomial CRC extension"
msgstr "å¯ç”¨ä¹å·è®¡åˆ’语言扩展"
#: config/arc/arc.opt:284
#, fuzzy
-#| msgid "Enable Plan 9 language extensions"
msgid "Enable DSP 3.1 Pack A extensions"
msgstr "å¯ç”¨ä¹å·è®¡åˆ’语言扩展"
#: config/arc/arc.opt:288
#, fuzzy
-#| msgid "Enable Plan 9 language extensions"
msgid "Enable dual viterbi butterfly extension"
msgstr "å¯ç”¨ä¹å·è®¡åˆ’语言扩展"
#: config/arc/arc.opt:298
#, fuzzy
-#| msgid "Enable leading zero instructions"
msgid "Enable Dual and Single Operand Instructions for Telephony"
msgstr "å¯ç”¨å‰å¯¼é›¶æŒ‡ä»¤"
@@ -12506,19 +12124,16 @@ msgstr ""
#: config/arc/arc.opt:307
#, fuzzy
-#| msgid "Enable dead store elimination"
msgid "Enable Locked Load/Store Conditional extension"
msgstr "删除死存储"
#: config/arc/arc.opt:311
#, fuzzy
-#| msgid "Enable sign extend instructions"
msgid "Enable swap byte ordering extension instruction"
msgstr "å¯ç”¨ç¬¦å·æ‰©å±•æŒ‡ä»¤"
#: config/arc/arc.opt:315
#, fuzzy
-#| msgid "Enable bit manipulation instructions"
msgid "Enable 64-bit Time-Stamp Counter extension instruction"
msgstr "å¯ç”¨ä½æ“作指令"
@@ -12532,19 +12147,16 @@ msgstr ""
#: config/arc/arc.opt:327
#, fuzzy
-#| msgid "Pass -z text to linker"
msgid "Pass -EB option through to linker."
msgstr "将 -z text 传递给链接器"
#: config/arc/arc.opt:331
#, fuzzy
-#| msgid "Pass -z text to linker"
msgid "Pass -EL option through to linker."
msgstr "将 -z text 传递给链接器"
#: config/arc/arc.opt:335
#, fuzzy
-#| msgid "Pass -z text to linker"
msgid "Pass -marclinux option through to linker."
msgstr "将 -z text 传递给链接器"
@@ -12722,7 +12334,6 @@ msgstr "为速度优化,ä¸ä¸¥æ ¼éµå®ˆæ ‡å‡†"
#: common.opt:457
#, fuzzy
-#| msgid "Optimize for space rather than speed"
msgid "Optimize for debugging experience rather than speed or size"
msgstr "为最å°ç©ºé—´è€Œä¸æ˜¯æœ€å¤§é€Ÿåº¦ä¼˜åŒ–"
@@ -12781,7 +12392,6 @@ msgstr "-Wframe-larger-than=<N>\t当一个函数的堆栈框架需è¦å¤šäºŽ N å­
#: common.opt:562
#, fuzzy
-#| msgid "%Kattempt to free a non-heap object"
msgid "Warn when attempting to free a non-heap object"
msgstr "%K试图 free 一个ä¸åœ¨å †ä¸Šçš„对象"
@@ -12870,7 +12480,6 @@ msgstr "自动å˜é‡æœªåˆå§‹åŒ–时警告"
#: common.opt:660
#, fuzzy
-#| msgid "Warn about uninitialized automatic variables"
msgid "Warn about maybe uninitialized automatic variables"
msgstr "自动å˜é‡æœªåˆå§‹åŒ–时警告"
@@ -13007,7 +12616,6 @@ msgstr "比较几个数æ®ä¾èµ–分æžçš„结果。"
#: common.opt:918
#, fuzzy
-#| msgid "Check the return value of new"
msgid "Check the return value of new in C++"
msgstr "检查 new 的返回值"
@@ -13094,7 +12702,6 @@ msgstr "删除无用的空指针检查"
#: common.opt:1012
#, fuzzy
-#| msgid "Perform superblock formation via tail duplication"
msgid "Perform speculative devirtualization"
msgstr "通过尾å¤åˆ¶è¿›è¡Œè¶…å—åˆæˆ"
@@ -13145,7 +12752,6 @@ msgstr "在调试转储中ä¸è¾“出地å€"
#: common.opt:1096
#, fuzzy
-#| msgid "Do the full register move optimization pass"
msgid "Dump optimization passes"
msgstr "进行全寄存器传é€ä¼˜åŒ–"
@@ -13265,7 +12871,6 @@ msgstr "å¯ç”¨ Graphite 身份转æ¢"
#: common.opt:1243
#, fuzzy
-#| msgid "Enable hoisting loads from conditional pointers."
msgid "Enable hoisting adjacent loads to encourage generating conditional move"
msgstr "为æ¡ä»¶æŒ‡é’ˆå¤–æ内存读å–æ“作。"
@@ -13319,7 +12924,6 @@ msgstr ""
#: common.opt:1303
#, fuzzy, c-format
-#| msgid "unknown TLS model %qs"
msgid "unknown Stack Reuse Level %qs"
msgstr "未知的 TLS 模型%qs"
@@ -13346,19 +12950,16 @@ msgstr ""
#: common.opt:1342
#, fuzzy
-#| msgid "Integrate simple functions into their callers when code size is known to not growth"
msgid "Integrate functions into their callers when code size is known not to grow"
msgstr "在ä¸å¯¼è‡´ä»£ç è†¨èƒ€çš„情况下将简å•å‡½æ•°é›†æˆåˆ°å®ƒä»¬çš„调用者中"
#: common.opt:1346
#, fuzzy
-#| msgid "Integrate functions called once into their callers"
msgid "Integrate functions not declared \"inline\" into their callers when profitable"
msgstr "å°†åªè¢«è°ƒç”¨ä¸€æ¬¡çš„函数集æˆåˆ°å®ƒä»¬çš„调用者中"
#: common.opt:1350
#, fuzzy
-#| msgid "Integrate functions called once into their callers"
msgid "Integrate functions only required by their single caller"
msgstr "å°†åªè¢«è°ƒç”¨ä¸€æ¬¡çš„函数集æˆåˆ°å®ƒä»¬çš„调用者中"
@@ -13384,7 +12985,6 @@ msgstr "-finstrument-functions-exclude-file-list=文件å,... å–样时排除å
#: common.opt:1377
#, fuzzy
-#| msgid "Perform Interprocedural constant propagation"
msgid "Perform interprocedural constant propagation"
msgstr "进行进程间的å¤å†™ä¼ é€’"
@@ -13407,7 +13007,6 @@ msgstr "å‘现纯函数和常函数"
#: common.opt:1397
#, fuzzy
-#| msgid "unimplemented functionality"
msgid "Perform Semantic function equality"
msgstr "未实现的功能"
@@ -13504,7 +13103,6 @@ msgstr "报告å„ç§é“¾æŽ¥æ—¶ä¼˜åŒ–统计"
#: common.opt:1521
#, fuzzy
-#| msgid "Report various link-time optimization statistics"
msgid "Report various link-time optimization statistics for WPA only"
msgstr "报告å„ç§é“¾æŽ¥æ—¶ä¼˜åŒ–统计"
@@ -13522,7 +13120,6 @@ msgstr "报告永久性内存分é…"
#: common.opt:1537
#, fuzzy
-#| msgid "Report on permanent memory allocation"
msgid "Report on permanent memory allocation in WPA only"
msgstr "报告永久性内存分é…"
@@ -13576,7 +13173,6 @@ msgstr "å°½å¯èƒ½ä¸ç”Ÿæˆæ ˆå¸§"
#: common.opt:1592
#, fuzzy
-#| msgid "Enable loop optimizations on tree level"
msgid "Enable all optimization info dumps on stderr"
msgstr "在树级别进行循环优化"
@@ -13690,13 +13286,11 @@ msgstr "为å–样表达å¼çš„值æ’入相关代ç "
#: common.opt:1713
#, fuzzy
-#| msgid "internal consistency failure"
msgid "Report on consistency of profile"
msgstr "内部一致性错误"
#: common.opt:1717
#, fuzzy
-#| msgid "Reorder functions to improve code placement"
msgid "Enable function reordering that improves code placement"
msgstr "函数é‡æ–°æŽ’åºä»¥æ”¹å–„代ç å¸ƒå±€"
@@ -13714,7 +13308,6 @@ msgstr "在寄存器中返回å°èšåˆ"
#: common.opt:1746
#, fuzzy
-#| msgid "Enable register pressure sensitive insn scheduling"
msgid "Relief of register pressure through live range shrinkage"
msgstr "å¯ç”¨å¯¹å¯„存器压力æ•æ„Ÿçš„指令调度"
@@ -13909,7 +13502,6 @@ msgstr "为æ¯ä¸ªå‡½æ•°ä½¿ç”¨å †æ ˆä¿æŠ¤æœºåˆ¶"
#: common.opt:1967
#, fuzzy
-#| msgid "Use a stack protection method for every function"
msgid "Use a smart stack protection method for certain functions"
msgstr "为æ¯ä¸ªå‡½æ•°ä½¿ç”¨å †æ ˆä¿æŠ¤æœºåˆ¶"
@@ -13986,7 +13578,6 @@ msgstr "å¯ç”¨æ ‘上的循环ä¸å˜é‡è½¬ç§»"
#: common.opt:2065
#, fuzzy
-#| msgid "Perform variable tracking and also tag variables that are uninitialized"
msgid "Enable coalescing of copy-related user variables that are inlined"
msgstr "进行å˜é‡è¿½è¸ªå¹¶ä¸”标记未被åˆå§‹åŒ–çš„å˜é‡"
@@ -14020,7 +13611,6 @@ msgstr "å¯ç”¨ä¸»å¯¼ä¼˜åŒ–"
#: common.opt:2101
#, fuzzy
-#| msgid "Enable loop header copying on trees"
msgid "Enable tail merging on trees"
msgstr "å¯ç”¨æ ‘上的循环ä¸å˜é‡è½¬ç§»"
@@ -14038,13 +13628,11 @@ msgstr "å¯ç”¨æ ‘上的完全冗余消除(FRE)"
#: common.opt:2117
#, fuzzy
-#| msgid "Enable SSA-CCP optimization on trees"
msgid "Enable string length optimizations on trees"
msgstr "å¯ç”¨æ ‘上的 SSA-CCP 优化"
#: common.opt:2121
#, fuzzy
-#| msgid "comparison with string literal results in unspecified behaviour"
msgid "Detect paths which trigger erroneous or undefined behaviour due to"
msgstr "与字é¢å­—符串比较的结构是ä¸å¯é¢„测的"
@@ -14164,13 +13752,11 @@ msgstr "仅为异常处ç†ç”Ÿæˆå †æ ˆå±•å¼€è¡¨"
#: common.opt:2254
#, fuzzy
-#| msgid "Use the hardware barrel shifter instead of emulation"
msgid "Use the bfd linker instead of the default linker"
msgstr "使用硬件桶型移ä½å™¨ä»£æ›¿ä»¿çœŸ"
#: common.opt:2258
#, fuzzy
-#| msgid "Use the hardware barrel shifter instead of emulation"
msgid "Use the gold linker instead of the default linker"
msgstr "使用硬件桶型移ä½å™¨ä»£æ›¿ä»¿çœŸ"
@@ -14192,7 +13778,6 @@ msgstr "进行å˜é‡è¿½è¸ªå¹¶ä¸”标记未被åˆå§‹åŒ–çš„å˜é‡"
#: common.opt:2296
#, fuzzy
-#| msgid "Enable loop vectorization on trees"
msgid "Enable vectorization on trees"
msgstr "在树上进行循环å‘é‡åŒ–"
@@ -14206,7 +13791,6 @@ msgstr "在树上进行基本å—å‘é‡åŒ–(SLP)"
#: common.opt:2312
#, fuzzy
-#| msgid "Enable use of cost model in vectorization"
msgid "Specifies the cost model for vectorization"
msgstr "å¯ç”¨å‘é‡åŒ–开销模型"
@@ -14216,19 +13800,16 @@ msgstr ""
#: common.opt:2319
#, fuzzy, c-format
-#| msgid "unknown TLS model %qs"
msgid "unknown vectorizer cost model %qs"
msgstr "未知的 TLS 模型%qs"
#: common.opt:2332
#, fuzzy
-#| msgid "Does nothing. Preserved for backward compatibility."
msgid "Enables the dynamic vectorizer cost model. Preserved for backward compatibility."
msgstr "ä¸èµ·ä½œç”¨ã€‚为å‘å‰å…¼å®¹ä¿ç•™çš„选项。"
#: common.opt:2336
#, fuzzy
-#| msgid "Does nothing. Preserved for backward compatibility."
msgid "Enables the unlimited vectorizer cost model. Preserved for backward compatibility."
msgstr "ä¸èµ·ä½œç”¨ã€‚为å‘å‰å…¼å®¹ä¿ç•™çš„选项。"
@@ -14255,7 +13836,6 @@ msgstr ""
#: common.opt:2380
#, fuzzy, c-format
-#| msgid "(near initialization for %qs)"
msgid "unknown vtable verify initialization priority %qs"
msgstr "(在%qsçš„åˆå§‹åŒ–附近)"
@@ -14301,7 +13881,6 @@ msgstr "ç”Ÿæˆ COFF æ ¼å¼çš„调试信æ¯"
#: common.opt:2433
#, fuzzy
-#| msgid "Generate debug information in default format"
msgid "Generate debug information in default version of DWARF format"
msgstr "生æˆé»˜è®¤æ ¼å¼çš„调试信æ¯"
@@ -14327,25 +13906,21 @@ msgstr ""
#: common.opt:2457
#, fuzzy
-#| msgid "Record gcc command line switches in the object file."
msgid "Don't record gcc command line switches in DWARF DW_AT_producer."
msgstr "在目标文件中记录 gcc 命令行开关。"
#: common.opt:2461
#, fuzzy
-#| msgid "Record gcc command line switches in the object file."
msgid "Record gcc command line switches in DWARF DW_AT_producer."
msgstr "在目标文件中记录 gcc 命令行开关。"
#: common.opt:2465
#, fuzzy
-#| msgid "Generate debug information in default format"
msgid "Don't generate debug information in separate .dwo files"
msgstr "生æˆé»˜è®¤æ ¼å¼çš„调试信æ¯"
#: common.opt:2469
#, fuzzy
-#| msgid "Generate debug information in default format"
msgid "Generate debug information in separate .dwo files"
msgstr "生æˆé»˜è®¤æ ¼å¼çš„调试信æ¯"
@@ -14387,7 +13962,6 @@ msgstr "-iplugindir=<目录>\t将目录设定为默认的æ’件å­ç›®å½•"
#: common.opt:2512
#, fuzzy
-#| msgid "-imultilib <dir>\tSet <dir> to be the multilib include subdirectory"
msgid "-imultiarch <dir>\tSet <dir> to be the multiarch include subdirectory"
msgstr "-imultilib <目录>\t将目录设定为 multilib 的包å«å­ç›®å½•"
@@ -14450,7 +14024,6 @@ msgstr "需è¦æ•°å­—类型"
#: go/gofrontend/expressions.cc:4157
#, fuzzy
-#| msgid "expected integer or boolean type"
msgid "expected boolean type"
msgstr "需è¦æ•´æ•°æˆ–布尔类型"
@@ -14469,7 +14042,6 @@ msgstr "需è¦æŒ‡é’ˆ"
#: go/gofrontend/expressions.cc:5925
#, fuzzy
-#| msgid "invalid comparison code in gimple cond"
msgid "invalid comparison of nil with nil"
msgstr "gimple æ¡ä»¶ä¸­æ¯”较代ç æ— æ•ˆ"
@@ -14480,7 +14052,6 @@ msgstr "二元表达å¼ä¸­ç±»åž‹ä¸åŒ¹é…"
#: go/gofrontend/expressions.cc:5969
#, fuzzy
-#| msgid "division by zero"
msgid "integer division by zero"
msgstr "被零除"
@@ -14508,13 +14079,11 @@ msgstr "方法类型ä¸åŒ¹é…对象类型"
#: go/gofrontend/expressions.cc:7156
#, fuzzy
-#| msgid "invalid argument to built-in function"
msgid "invalid use of %<...%> with builtin function"
msgstr "内建函数实å‚无效"
#: go/gofrontend/expressions.cc:7167
#, fuzzy
-#| msgid "invalid use of template-name %qE without an argument list"
msgid "invalid use of method value as argument of Offsetof"
msgstr "使用模æ¿å%qEæ—¶ä¸å¸¦å®žå‚表无效"
@@ -14540,7 +14109,6 @@ msgstr "实å‚太多"
#: go/gofrontend/expressions.cc:7271
#, fuzzy
-#| msgid "argument must be a constant"
msgid "argument 1 must be a map"
msgstr "实å‚必须是常数"
@@ -14551,7 +14119,6 @@ msgstr "函数%q+#D的抽象返回类型无效"
#: go/gofrontend/expressions.cc:7384
#, fuzzy
-#| msgid "bad length when making slice"
msgid "length required when allocating a slice"
msgstr "生æˆåˆ‡ç‰‡æ—¶é•¿åº¦é”™è¯¯"
@@ -14561,7 +14128,6 @@ msgstr ""
#: go/gofrontend/expressions.cc:7435
#, fuzzy
-#| msgid "too many arguments to %qE"
msgid "too many arguments to make"
msgstr "%qE实å‚太多"
@@ -14603,19 +14169,16 @@ msgstr "元素类型必须一样"
#: go/gofrontend/expressions.cc:8317
#, fuzzy
-#| msgid "left argument must be a slice"
msgid "first argument must be []byte"
msgstr "左实å‚必须是一个切片"
#: go/gofrontend/expressions.cc:8320
#, fuzzy
-#| msgid "right argument must be a slice or a string"
msgid "second argument must be slice or string"
msgstr "å³å®žå‚必须是一个切片或字符串"
#: go/gofrontend/expressions.cc:8361
#, fuzzy
-#| msgid "parameter %u has void type"
msgid "argument 2 has invalid type"
msgstr "第 %u 个å‚数类型为 void"
@@ -14638,7 +14201,6 @@ msgstr "需è¦å‡½æ•°"
#: go/gofrontend/expressions.cc:9332
#, fuzzy
-#| msgid "invalid use of %<this%> at top level"
msgid "invalid use of %<...%> with non-slice"
msgstr "在文件作用域使用%<this%>无效"
@@ -14648,7 +14210,6 @@ msgstr "接收器类型ä¸å…¼å®¹"
#: go/gofrontend/expressions.cc:9623
#, fuzzy
-#| msgid "invalid use of %<this%> in non-member function"
msgid "invalid use of %<...%> calling non-variadic function"
msgstr "在éžæˆå‘˜å‡½æ•°ä¸­ä½¿ç”¨%<this%>无效"
@@ -14666,7 +14227,6 @@ msgstr "切片结尾必须是整数"
#: go/gofrontend/expressions.cc:10474
#, fuzzy
-#| msgid "slice end must be integer"
msgid "slice capacity must be integer"
msgstr "切片结尾必须是整数"
@@ -14741,7 +14301,6 @@ msgstr "需è¦è¡Œå°¾"
#: go/gofrontend/statements.cc:2654 go/gofrontend/statements.cc:2683
#, fuzzy
-#| msgid "not enough arguments"
msgid "not enough arguments to return"
msgstr "实å‚太少"
@@ -14783,49 +14342,41 @@ msgstr "å³å®žå‚必须是一个切片或字符串"
#: go/gofrontend/types.cc:514
#, fuzzy
-#| msgid "invalid comparison code in gimple cond"
msgid "invalid comparison of non-ordered type"
msgstr "gimple æ¡ä»¶ä¸­æ¯”较代ç æ— æ•ˆ"
#: go/gofrontend/types.cc:530
#, fuzzy
-#| msgid "duplicate class will only be compiled once"
msgid "slice can only be compared to nil"
msgstr "é‡å¤çš„ç±»åªä¼šè¢«ç¼–译一次"
#: go/gofrontend/types.cc:532
#, fuzzy
-#| msgid "duplicate class will only be compiled once"
msgid "map can only be compared to nil"
msgstr "é‡å¤çš„ç±»åªä¼šè¢«ç¼–译一次"
#: go/gofrontend/types.cc:534
#, fuzzy
-#| msgid "duplicate class will only be compiled once"
msgid "func can only be compared to nil"
msgstr "é‡å¤çš„ç±»åªä¼šè¢«ç¼–译一次"
#: go/gofrontend/types.cc:540
#, fuzzy, c-format
-#| msgid "invalid operand to %%R"
msgid "invalid operation (%s)"
msgstr "%%R çš„æ“作数无效"
#: go/gofrontend/types.cc:563
#, fuzzy
-#| msgid "invalid comparison code in gimple cond"
msgid "invalid comparison of non-comparable type"
msgstr "gimple æ¡ä»¶ä¸­æ¯”较代ç æ— æ•ˆ"
#: go/gofrontend/types.cc:581
#, fuzzy
-#| msgid "invalid comparison code in gimple cond"
msgid "invalid comparison of non-comparable struct"
msgstr "gimple æ¡ä»¶ä¸­æ¯”较代ç æ— æ•ˆ"
#: go/gofrontend/types.cc:592
#, fuzzy
-#| msgid "invalid use of non-lvalue array"
msgid "invalid comparison of non-comparable array"
msgstr "对éžå·¦å€¼æ•°ç»„的使用无效"
@@ -14911,13 +14462,11 @@ msgstr "缺少方法%s%s%s"
#: go/gofrontend/types.cc:7240
#, fuzzy, c-format
-#| msgid "method %s%s%s requires a pointer"
msgid "method %s%s%s requires a pointer receiver"
msgstr "方法%s%s%s需è¦ä¸€ä¸ªæŒ‡é’ˆ"
#: go/gofrontend/types.cc:7258
#, fuzzy, c-format
-#| msgid "method %s%s%s requires a pointer"
msgid "method %s%s%s is marked go:nointerface"
msgstr "方法%s%s%s需è¦ä¸€ä¸ªæŒ‡é’ˆ"
@@ -14930,7 +14479,6 @@ msgstr "%qE属性指定被忽略"
#: attribs.c:450
#, fuzzy, gcc-internal-format
-#| msgid "%qE attribute directive ignored"
msgid "%<%E::%E%> scoped attribute directive ignored"
msgstr "%qE属性指定被忽略"
@@ -14944,7 +14492,6 @@ msgstr "为%qE属性给定的实å‚数目错误"
#. type. Ignore it.
#: attribs.c:472
#, fuzzy, gcc-internal-format
-#| msgid "%qE attribute ignored"
msgid "attribute ignored"
msgstr "%qE属性被忽略"
@@ -15045,7 +14592,6 @@ msgstr ""
#: builtins.c:5248
#, fuzzy, gcc-internal-format
-#| msgid "invalid argument to built-in function"
msgid "invalid memory model argument to builtin"
msgstr "内建函数实å‚无效"
@@ -15066,13 +14612,11 @@ msgstr ""
#: builtins.c:5360
#, fuzzy, gcc-internal-format
-#| msgid "invalid use of %<auto%>"
msgid "invalid memory model for %<__atomic_load%>"
msgstr "错误地使用了%<auto%>"
#: builtins.c:5390 builtins.c:5497
#, fuzzy, gcc-internal-format
-#| msgid "invalid use of %<auto%>"
msgid "invalid memory model for %<__atomic_store%>"
msgstr "错误地使用了%<auto%>"
@@ -15088,13 +14632,11 @@ msgstr ""
#: builtins.c:5709
#, fuzzy, gcc-internal-format
-#| msgid "__builtin_eh_return not supported on this target"
msgid "__builtin_thread_pointer is not supported on this target"
msgstr "__builtin_eh_return 在此目标机上ä¸å—支æŒ"
#: builtins.c:5729
#, fuzzy, gcc-internal-format
-#| msgid "__builtin_eh_return not supported on this target"
msgid "__builtin_set_thread_pointer is not supported on this target"
msgstr "__builtin_eh_return 在此目标机上ä¸å—支æŒ"
@@ -15189,7 +14731,6 @@ msgstr "函数调用有èšåˆç±»åž‹"
#: calls.c:3055
#, fuzzy, gcc-internal-format
-#| msgid "missing argument to %qs"
msgid "passing too large argument on stack"
msgstr "%qs缺少å‚æ•°"
@@ -15335,7 +14876,6 @@ msgstr "verify_flow_info 失败"
#: cfghooks.c:310
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%s does not support duplicate_block"
msgid "%s does not support dump_bb_for_graph"
msgstr "%s ä¸æ”¯æŒ duplicate_block"
@@ -15406,7 +14946,6 @@ msgstr "%s ä¸æ”¯æŒ make_forwarder_block"
#: cfghooks.c:984
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%s does not support move_block_after"
msgid "%s does not support force_nonfallthru"
msgstr "%s ä¸æ”¯æŒt move_block_after"
@@ -15447,7 +14986,6 @@ msgstr ""
#: cfgloop.c:1356
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Enable loop header copying on trees"
msgid "loop with header %d not in loop tree"
msgstr "å¯ç”¨æ ‘上的循环ä¸å˜é‡è½¬ç§»"
@@ -15468,13 +15006,11 @@ msgstr "循环 %d 的大å°åº”该为 %d,而ä¸æ˜¯%d"
#: cfgloop.c:1395
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "bb %d do not belong to loop %d"
msgid "bb %d does not belong to loop %d"
msgstr "åŸºæœ¬å— %d ä¸å±žäºŽå¾ªçŽ¯ %d"
#: cfgloop.c:1407
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "size of loop %d should be %d, not %d"
msgid "bb %d has father loop %d, should be loop %d"
msgstr "循环 %d 的大å°åº”该为 %d,而ä¸æ˜¯%d"
@@ -15595,7 +15131,6 @@ msgstr ""
#: cfgrtl.c:2428
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "verify_flow_info: REG_BR_PROB does not match cfg %wi %i"
msgid "verify_flow_info: REG_BR_PROB does not match cfg %i %i"
msgstr "verify_flow_info:REG_BR_PROB ä¸åŒ¹é… cfg %wi %i"
@@ -15606,19 +15141,16 @@ msgstr ""
#: cfgrtl.c:2454
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "fallthru edge crosses section boundary (bb %i)"
msgid "fallthru edge crosses section boundary in bb %i"
msgstr "直通边越过了节分界(åŸºæœ¬å— %i)"
#: cfgrtl.c:2460
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "fallthru edge crosses section boundary (bb %i)"
msgid "EH edge crosses section boundary in bb %i"
msgstr "直通边越过了节分界(åŸºæœ¬å— %i)"
#: cfgrtl.c:2467
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "fallthru edge crosses section boundary (bb %i)"
msgid "No region crossing jump at section boundary in bb %i"
msgstr "直通边越过了节分界(åŸºæœ¬å— %i)"
@@ -15634,13 +15166,11 @@ msgstr ""
#: cfgrtl.c:2510
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "missing REG_EH_REGION note in the end of bb %i"
msgid "missing REG_EH_REGION note at the end of bb %i"
msgstr "åŸºæœ¬å— %i 结尾缺少 REG_EH_REGION 记录"
#: cfgrtl.c:2515
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "too many outgoing branch edges from bb %i"
msgid "too many exception handling edges in bb %i"
msgstr "ä»ŽåŸºæœ¬å— %i 分出太多的分支边"
@@ -15651,31 +15181,26 @@ msgstr "ä»ŽåŸºæœ¬å— %i 分出太多的分支边"
#: cfgrtl.c:2528
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "fallthru edge after unconditional jump %i"
msgid "fallthru edge after unconditional jump in bb %i"
msgstr "éžæ¡ä»¶è·³è½¬ %i 之åŽçš„直通边"
#: cfgrtl.c:2533
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "wrong number of branch edges after unconditional jump %i"
msgid "wrong number of branch edges after unconditional jump in bb %i"
msgstr "éžæ¡ä»¶è·³è½¬ %i 之åŽçš„分支边数ä¸å¯¹"
#: cfgrtl.c:2540
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "wrong amount of branch edges after conditional jump %i"
msgid "wrong amount of branch edges after conditional jump in bb %i"
msgstr "æ¡ä»¶è·³è½¬ %i 之åŽçš„分支边数ä¸å¯¹"
#: cfgrtl.c:2546
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "call edges for non-call insn in bb %i"
msgid "abnormal call edges for non-call insn in bb %i"
msgstr "åœ¨åŸºæœ¬å— %i 中éžè°ƒç”¨æŒ‡ä»¤çš„调用边"
#: cfgrtl.c:2551
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "call edges for non-call insn in bb %i"
msgid "sibcall edges for non-call insn in bb %i"
msgstr "åœ¨åŸºæœ¬å— %i 中éžè°ƒç”¨æŒ‡ä»¤çš„调用边"
@@ -15801,7 +15326,6 @@ msgstr ""
#: cgraph.c:2651
#, fuzzy, gcc-internal-format
-#| msgid "Assume symbols might be invalid"
msgid "local symbols must be defined"
msgstr "å‡å®šç¬¦å·å¯èƒ½æ— æ•ˆ"
@@ -15817,7 +15341,6 @@ msgstr "内è”已被å–地å€çš„克隆"
#: cgraph.c:2666
#, fuzzy, gcc-internal-format
-#| msgid "inline clone is needed"
msgid "inline clone is forced to output"
msgstr "需è¦å†…è”克隆"
@@ -15943,7 +15466,6 @@ msgstr "调用语å¥ç¼ºå°‘ callgraph 边:"
#: cgraph.c:2895
#, fuzzy, gcc-internal-format
-#| msgid "expected statement"
msgid "reference to dead statement"
msgstr "需è¦è¯­å¥"
@@ -15984,7 +15506,6 @@ msgstr "%qE属性被忽略,因为%qT已被定义"
#: cgraphunit.c:774
#, fuzzy, gcc-internal-format
-#| msgid "Warn when an inlined function cannot be inlined"
msgid "always_inline function might not be inlinable"
msgstr "当内è”函数无法被内è”时给出警告"
@@ -16010,7 +15531,6 @@ msgstr ""
#: cgraphunit.c:1200
#, fuzzy, gcc-internal-format
-#| msgid "%q+D used prior to declaration"
msgid "%q+D aliased declaration"
msgstr "%q+D在声明å‰ä½¿ç”¨"
@@ -16021,7 +15541,6 @@ msgstr "无法收回ä¸éœ€è¦çš„函数"
#: cgraphunit.c:1303
#, fuzzy, gcc-internal-format
-#| msgid "failed to reclaim unneeded function"
msgid "failed to reclaim unneeded function in same comdat group"
msgstr "无法收回ä¸éœ€è¦çš„函数"
@@ -16072,19 +15591,16 @@ msgstr "未知的解修饰风格‘%s’"
#: collect2.c:1567 collect2.c:1750 collect2.c:1790
#, fuzzy, gcc-internal-format
-#| msgid "fopen %s"
msgid "fopen %s: %m"
msgstr "fopen %s"
#: collect2.c:1570 collect2.c:1755 collect2.c:1793
#, fuzzy, gcc-internal-format
-#| msgid "fclose %s"
msgid "fclose %s: %m"
msgstr "fclose %s"
#: collect2.c:1857
#, fuzzy, gcc-internal-format
-#| msgid "can't get program status: %s"
msgid "can't get program status: %m"
msgstr "无法获å–程åºçŠ¶æ€ï¼š%s"
@@ -16130,7 +15646,6 @@ msgstr "找ä¸åˆ° ‘nm’"
#: collect2.c:2546
#, fuzzy, gcc-internal-format
-#| msgid "can't open nm output"
msgid "can't open nm output: %m"
msgstr "无法打开 nm 的输出"
@@ -16151,7 +15666,6 @@ msgstr "找ä¸åˆ°â€˜ldd’"
#: collect2.c:2742
#, fuzzy, gcc-internal-format
-#| msgid "can't open ldd output"
msgid "can't open ldd output: %m"
msgstr "无法打开 ldd 输出"
@@ -16247,7 +15761,6 @@ msgstr "%s 的存储信æ¯å¾ˆè¯¡å¼‚"
#: coverage.c:291
#, fuzzy, gcc-internal-format
-#| msgid "checksum is %x instead of %x"
msgid "checksum is (%x,%x) instead of (%x,%x)"
msgstr "检验和是 %x 而ä¸æ˜¯ %x"
@@ -16273,7 +15786,6 @@ msgstr ""
#: coverage.c:393
#, fuzzy, gcc-internal-format
-#| msgid "execution counts estimated"
msgid "execution counts estimated\n"
msgstr "预计执行次数"
@@ -16374,7 +15886,6 @@ msgstr "忽略未知的选项%q.*s,在%<-fdump-%s%>中"
#: dumpfile.c:862
#, fuzzy, gcc-internal-format
-#| msgid "ignoring unknown option %q.*s in %<-fdump-%s%>"
msgid "unknown option %q.*s in %<-fopt-info-%s%>"
msgstr "忽略未知的选项%q.*s,在%<-fdump-%s%>中"
@@ -16390,7 +15901,6 @@ msgstr "多个 EH 个性需è¦æ±‡ç¼–å™¨æ”¯æŒ .cfi.personality 指示。"
#: dwarf2out.c:11303
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "non-delegitimized UNSPEC %d found in variable location"
msgid "non-delegitimized UNSPEC %s (%d) found in variable location"
msgstr "å˜é‡ä½ç½®å¤„å‘现未被éžæ³•åŒ–çš„ UNSPEC %d"
@@ -16481,7 +15991,6 @@ msgstr "堆栈é™åˆ¶åœ¨æ­¤ç›®æ ‡æœºä¸Šä¸å—支æŒ"
#: expr.c:7657
#, fuzzy, gcc-internal-format
-#| msgid "global register variable %qD used in nested function"
msgid "local frame unavailable (naked function?)"
msgstr "嵌套函数中使用了全局寄存器å˜é‡%qD"
@@ -16853,7 +16362,6 @@ msgstr "比较最终指令转储"
#: gcc.c:7131
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "-fuse-linker-plugin, but "
msgid "-fuse-linker-plugin, but %s not found"
msgstr "使用了 -fuse-linker-plugin,但"
@@ -16944,7 +16452,6 @@ msgstr "%%:compare-debug-auxbase-opt çš„å‚数未以 .gk 结尾"
#: gcc.c:8636
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "too few arguments to function"
msgid "too few arguments to %%:replace-extension"
msgstr "给予函数的实å‚太少"
@@ -17042,13 +16549,11 @@ msgstr ""
#: gimplify.c:5647
#, fuzzy, gcc-internal-format
-#| msgid "%qE not specified in enclosing parallel"
msgid "%qE not specified in enclosing task"
msgstr "%qE未为在括入的并行中指定"
#: gimplify.c:5653
#, fuzzy, gcc-internal-format
-#| msgid "%qE not specified in enclosing parallel"
msgid "%qE not specified in enclosing teams construct"
msgstr "%qE未为在括入的并行中指定"
@@ -17069,7 +16574,6 @@ msgstr "括入并行"
#: gimplify.c:5770 gimplify.c:5799
#, fuzzy, gcc-internal-format
-#| msgid "iteration variable %qE should not be reduction"
msgid "iteration variable %qE is predetermined linear"
msgstr "迭代å˜é‡%qEä¸åº”当是 reduction"
@@ -17090,19 +16594,16 @@ msgstr "迭代å˜é‡%qEä¸åº”当是 reduction"
#: gimplify.c:5793
#, fuzzy, gcc-internal-format
-#| msgid "iteration variable %qE should not be firstprivate"
msgid "iteration variable %qE should not be lastprivate"
msgstr "迭代å˜é‡%qEä¸åº”当是 firstprivate"
#: gimplify.c:5796
#, fuzzy, gcc-internal-format
-#| msgid "iteration variable %qE should be private"
msgid "iteration variable %qE should not be private"
msgstr "迭代å˜é‡%qE应当是ç§æœ‰çš„"
#: gimplify.c:6064
#, fuzzy, gcc-internal-format
-#| msgid "%s variable %qE is private in outer context"
msgid "copyprivate variable %qE is not threadprivate or private in outer context"
msgstr "%s å˜é‡%qE在外层上下文中是ç§æœ‰çš„"
@@ -17113,7 +16614,6 @@ msgstr "%s å˜é‡%qE在外层上下文中是ç§æœ‰çš„"
#: gimplify.c:8063
#, fuzzy, gcc-internal-format
-#| msgid "expected %<}%> before %<else%>"
msgid "expected %<_Cilk_spawn%> before %<_Cilk_sync%>"
msgstr "%<else%>å‰éœ€è¦%<}%>"
@@ -17170,7 +16670,6 @@ msgstr "ä¸èƒ½ä½¿ç”¨ Graphite 循环优化"
#: ipa-devirt.c:302 ipa-devirt.c:337
#, fuzzy, gcc-internal-format
-#| msgid "previous definition here"
msgid "type %qD violates one definition rule "
msgstr "å…ˆå‰çš„定义在这里"
@@ -17212,7 +16711,6 @@ msgstr ""
#: ira.c:5544
#, fuzzy, gcc-internal-format
-#| msgid "as %qD"
msgid "for %qD"
msgstr "作为%qD"
@@ -17238,7 +16736,6 @@ msgstr ""
#: lto-cgraph.c:1083
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "bytecode stream: found multiple instances of cgraph node %d"
msgid "bytecode stream: found multiple instances of cgraph node with uid %d"
msgstr "字节ç æµï¼šæ‰¾åˆ° cgraph 节点 %d 的多个实例"
@@ -17312,19 +16809,16 @@ msgstr ""
#: lto-streamer-in.c:824
#, fuzzy, gcc-internal-format
-#| msgid "operand number out of range"
msgid "Reference statement index out of range"
msgstr "æ“作数å·è¶…出范围"
#: lto-streamer-in.c:827
#, fuzzy, gcc-internal-format
-#| msgid "Warn if deprecated empty statements are found"
msgid "Reference statement index not found"
msgstr "å‘现ä¸å»ºè®®ä½¿ç”¨çš„空语å¥æ—¶ç»™å‡ºè­¦å‘Š"
#: lto-streamer-out.c:393 lto-streamer-out.c:1307
#, fuzzy, gcc-internal-format
-#| msgid "tree code %qs is not supported in gimple streams"
msgid "tree code %qs is not supported in LTO streams"
msgstr "树代ç %qs在 gimple æµä¸­ä¸è¢«æ”¯æŒ"
@@ -17370,13 +16864,11 @@ msgstr ""
#: omp-low.c:2351 omp-low.c:2364
#, fuzzy, gcc-internal-format
-#| msgid "%<#pragma omp section%> may only be used in %<#pragma omp sections%> construct"
msgid "%<#pragma omp cancel sections%> inside %<nowait%> sections construct"
msgstr "%<#pragma omp section%>åªèƒ½ç”¨åœ¨%<#pragma omp sections%>结构中"
#: omp-low.c:2378
#, fuzzy, gcc-internal-format
-#| msgid "invalid PHI argument"
msgid "invalid arguments"
msgstr "无效的 PHI 实å‚"
@@ -17417,7 +16909,6 @@ msgstr "临界区域ä¸å¯ä»¥è¢«åµŒå¥—在åŒå的临界区域内"
#: omp-low.c:2492
#, fuzzy, gcc-internal-format
-#| msgid "master region may not be closely nested inside of work-sharing or explicit task region"
msgid "teams construct not closely nested inside of target region"
msgstr "主è¦åŒºåŸŸä¸å¯ä»¥ç´§å¯†åµŒå¥—在工作共享或显å¼çš„任务区域内"
@@ -17438,13 +16929,11 @@ msgstr "OpenMP 结构å—å…¥å£æ— æ•ˆ"
#: omp-low.c:10275
#, fuzzy, gcc-internal-format
-#| msgid "invalid entry to OpenMP structured block"
msgid "invalid entry to Cilk Plus structured block"
msgstr "OpenMP 结构å—å…¥å£æ— æ•ˆ"
#: omp-low.c:10283
#, fuzzy, gcc-internal-format
-#| msgid "invalid branch to/from an OpenMP structured block"
msgid "invalid branch to/from a Cilk Plus structured block"
msgstr "进出 OpenMP 结构å—的分支无效"
@@ -17455,7 +16944,6 @@ msgstr "进出 OpenMP 结构å—的分支无效"
#: omp-low.c:10761
#, fuzzy, gcc-internal-format
-#| msgid "ignoring duplicate directory \"%s\"\n"
msgid "ignoring large linear step"
msgstr "忽略é‡å¤çš„目录“%sâ€\n"
@@ -17558,7 +17046,6 @@ msgstr "当unit-at-a-time 被ç¦æ­¢æ—¶é¡¶å±‚é‡æ–°æŽ’åºå¿…é¡»ç¦æ­¢ã€‚"
#: opts.c:695
#, fuzzy, gcc-internal-format
-#| msgid "-static-libgfortran is not supported in this configuration"
msgid "transactional memory is not supported with non-call exceptions"
msgstr "-static-libgfortran 在此é…置下ä¸å—支æŒ"
@@ -17705,7 +17192,6 @@ msgstr "无效的å‚æ•°%qs"
#: passes.c:107
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%s does not support split_edge"
msgid "pass %s does not support cloning"
msgstr "%s ä¸æ”¯æŒ split_edge"
@@ -17721,13 +17207,11 @@ msgstr "无法识别的选项‘-%s’"
#: passes.c:999
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "unknown field %qE specified in initializer"
msgid "unknown pass %s specified in -fenable"
msgstr "åˆå§‹å€¼è®¾å®šé¡¹é‡Œæœ‰æœªçŸ¥çš„字段%qE"
#: passes.c:1001
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "unknown field %qE specified in initializer"
msgid "unknown pass %s specified in -fdisable"
msgstr "åˆå§‹å€¼è®¾å®šé¡¹é‡Œæœ‰æœªçŸ¥çš„字段%qE"
@@ -17743,19 +17227,16 @@ msgstr ""
#: passes.c:1065 passes.c:1093
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "invalid floating point option: -mfpu=%s"
msgid "Invalid range %s in option %s"
msgstr "无效的浮点选项:-mfpu=%s"
#: passes.c:1111
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "invalid storage class for function %qE"
msgid "enable pass %s for function %s"
msgstr "函数%qE存储类无效"
#: passes.c:1122
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "invalid storage class for function %qE"
msgid "disable pass %s for function %s"
msgstr "函数%qE存储类无效"
@@ -17859,7 +17340,6 @@ msgstr "-iplugindir <目录>选项未被传递给 gcc 驱动程åº"
#: predict.c:2805
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Missing argument list in function '%s' at %C"
msgid "Missing counts for called function %s/%i"
msgstr "函数‘%s’在%C处缺少å‚数列表"
@@ -17967,13 +17447,11 @@ msgstr "全局寄存器å˜é‡å‡ºçŽ°åœ¨å‡½æ•°å®šä¹‰åŽ"
#: reginfo.c:770
#, fuzzy, gcc-internal-format
-#| msgid "register used for two global register variables"
msgid "register of %qD used for multiple global register variables"
msgstr "寄存器用作两个全局寄存器å˜é‡"
#: reginfo.c:773
#, fuzzy, gcc-internal-format
-#| msgid " conflict with %q+D"
msgid "conflicts with %qD"
msgstr " 与%q+D冲çª"
@@ -18199,25 +17677,21 @@ msgstr "%D 在汇编中被引用åŽåˆè¢«é‡å‘½å"
#: symtab.c:736
#, fuzzy, gcc-internal-format
-#| msgid "function returning a function"
msgid "function symbol is not function"
msgstr "函数返回了一个函数"
#: symtab.c:744
#, fuzzy, gcc-internal-format
-#| msgid "array is not addressable"
msgid "variable symbol is not variable"
msgstr "数组ä¸èƒ½è¢«å–指"
#: symtab.c:750
#, fuzzy, gcc-internal-format
-#| msgid "node has wrong clone list"
msgid "node has unknown type"
msgstr "节点的克隆列表ä¸æ­£ç¡®"
#: symtab.c:759
#, fuzzy, gcc-internal-format
-#| msgid "node not found in cgraph_hash"
msgid "node not found in symtab decl hashtable"
msgstr "cgraph_hash 中找ä¸åˆ°èŠ‚点"
@@ -18233,19 +17707,16 @@ msgstr ""
#: symtab.c:790
#, fuzzy, gcc-internal-format
-#| msgid "node not found in cgraph_hash"
msgid "node not found in symtab assembler name hash"
msgstr "cgraph_hash 中找ä¸åˆ°èŠ‚点"
#: symtab.c:797
#, fuzzy, gcc-internal-format
-#| msgid "double linked list of clones corrupted"
msgid "double linked list of assembler names corrupted"
msgstr "åŒå‘克隆链接列表已æŸå"
#: symtab.c:802
#, fuzzy, gcc-internal-format
-#| msgid "node is in clone list but it is not clone"
msgid "node is analyzed byt it is not a definition"
msgstr "节点在克隆列表中,但并ä¸æ˜¯å…‹éš†"
@@ -18256,7 +17727,6 @@ msgstr ""
#: symtab.c:813
#, fuzzy, gcc-internal-format
-#| msgid "node is in clone list but it is not clone"
msgid "node is alias but not definition"
msgstr "节点在克隆列表中,但并ä¸æ˜¯å…‹éš†"
@@ -18272,7 +17742,6 @@ msgstr ""
#: symtab.c:832
#, fuzzy, gcc-internal-format
-#| msgid "Combining units with different profiles is not supported."
msgid "mixing different types of symbol in same comdat groups is not supported"
msgstr "ä¸æ”¯æŒç»„åˆæœ‰ä¸åŒå–æ ·ä¿¡æ¯çš„å•å…ƒã€‚"
@@ -18293,13 +17762,11 @@ msgstr ""
#: symtab.c:885
#, fuzzy, gcc-internal-format
-#| msgid "verify_cgraph_node failed"
msgid "verify_symtab_node failed"
msgstr "verify_cgraph_node 失败"
#: symtab.c:1110
#, fuzzy, gcc-internal-format
-#| msgid "function %q+D redeclared as inline"
msgid "function %q+D part of alias cycle"
msgstr "函数%q+Dé‡å£°æ˜Žä¸ºå†…è”çš„"
@@ -18335,13 +17802,11 @@ msgstr "#pragma GCC target 在此目标机上ä¸å—支æŒ"
#: tlink.c:489
#, fuzzy, gcc-internal-format
-#| msgid "removing .rpo file"
msgid "removing .rpo file: %m"
msgstr "删除 .rpo 文件"
#: tlink.c:491
#, fuzzy, gcc-internal-format
-#| msgid "renaming .rpo file"
msgid "renaming .rpo file: %m"
msgstr "é‡å‘½å .rpo 文件"
@@ -18382,7 +17847,6 @@ msgstr "-frecord-gcc-switches 在此目标机上ä¸å—支æŒ"
#: toplev.c:989
#, fuzzy, gcc-internal-format
-#| msgid "-fstack-usage not supported for this target"
msgid "stack usage computation not supported for this target"
msgstr "-fstack-usage 在此目标机上ä¸å—支æŒ"
@@ -18393,13 +17857,11 @@ msgstr ""
#: toplev.c:1060
#, fuzzy, gcc-internal-format
-#| msgid "stackframe too big: %d bytes"
msgid "stack usage might be %wd bytes"
msgstr "栈帧太大:%d 字节"
#: toplev.c:1063
#, fuzzy, gcc-internal-format
-#| msgid "stackframe too big: %d bytes"
msgid "stack usage is %wd bytes"
msgstr "栈帧太大:%d 字节"
@@ -18495,7 +17957,6 @@ msgstr "-fstack-protector 在此目标机上ä¸å—支æŒ"
#: toplev.c:1559
#, fuzzy, gcc-internal-format
-#| msgid "-fdata-sections not supported for this target"
msgid "-fsanitize=address not supported for this target"
msgstr "-fdata-sections 在此目标机上ä¸å—支æŒ"
@@ -18511,7 +17972,6 @@ msgstr "关闭 %s 时出错:%m"
#: trans-mem.c:614
#, fuzzy, gcc-internal-format
-#| msgid "invalid use of %qD in linkage specification"
msgid "invalid volatile use of %qD inside transaction"
msgstr "指定链接时使用%qD无效"
@@ -18532,7 +17992,6 @@ msgstr ""
#: trans-mem.c:725
#, fuzzy, gcc-internal-format
-#| msgid "indirect function call with a yet undetermined callee"
msgid "unsafe indirect function call within atomic transaction"
msgstr "间接函数调用目标未定义"
@@ -18548,25 +18007,21 @@ msgstr ""
#: trans-mem.c:743
#, fuzzy, gcc-internal-format
-#| msgid "indirect function call with a yet undetermined callee"
msgid "unsafe indirect function call within %<transaction_safe%> function"
msgstr "间接函数调用目标未定义"
#: trans-mem.c:758 trans-mem.c:4721
#, fuzzy, gcc-internal-format
-#| msgid "namespace %qD not allowed in using-declaration"
msgid "asm not allowed in atomic transaction"
msgstr "ä¸å…许在 using 声明中使用命å空间%qD"
#: trans-mem.c:761
#, fuzzy, gcc-internal-format
-#| msgid "attributes are not allowed on a function-definition"
msgid "asm not allowed in %<transaction_safe%> function"
msgstr "函数定义中ä¸å…许有属性"
#: trans-mem.c:772
#, fuzzy, gcc-internal-format
-#| msgid "Place each function into its own section"
msgid "relaxed transaction in atomic transaction"
msgstr "å°†æ¯ä¸ªå‡½æ•°åˆ†åˆ«æ”¾åœ¨å®ƒä»¬å„自的节中"
@@ -18577,7 +18032,6 @@ msgstr ""
#: trans-mem.c:782
#, fuzzy, gcc-internal-format
-#| msgid "pointer to a function used in subtraction"
msgid "outer transaction in transaction"
msgstr "函数指针ä¸èƒ½ç›¸å‡"
@@ -18593,7 +18047,6 @@ msgstr ""
#: trans-mem.c:4348
#, fuzzy, gcc-internal-format
-#| msgid "attributes are not allowed on a function-definition"
msgid "%Kasm not allowed in %<transaction_safe%> function"
msgstr "函数定义中ä¸å…许有属性"
@@ -18684,7 +18137,6 @@ msgstr "éžæ•´ä½“结果的模å¼ç²¾åº¦ä¸åŒ¹é… BIT_FIELD_REF 的字段尺寸"
#: tree-cfg.c:2836
#, fuzzy, gcc-internal-format
-#| msgid "invalid position or size operand to BIT_FIELD_REF"
msgid "position plus size exceeds size of referenced object in BIT_FIELD_REF"
msgstr "BIT_FIELD_REF ä½ç½®æˆ–大å°æ“作数无效"
@@ -18850,31 +18302,26 @@ msgstr "gimple 比较中æ“作数无效"
#: tree-cfg.c:3333
#, fuzzy, gcc-internal-format
-#| msgid "type mismatch in comparison expression"
msgid "mismatching comparison operand types"
msgstr "比较表达å¼ç±»åž‹ä¸åŒ¹é…"
#: tree-cfg.c:3347
#, fuzzy, gcc-internal-format
-#| msgid "function returning a function"
msgid "vector comparison returning a boolean"
msgstr "函数返回了一个函数"
#: tree-cfg.c:3361
#, fuzzy, gcc-internal-format
-#| msgid "invalid operands in gimple comparison"
msgid "non-vector operands in vector comparison"
msgstr "gimple 比较中æ“作数无效"
#: tree-cfg.c:3374
#, fuzzy, gcc-internal-format
-#| msgid "invalid vector permutation constant"
msgid "invalid vector comparison resulting type"
msgstr "无效的å‘é‡ç½®æ¢å¸¸é‡"
#: tree-cfg.c:3381
#, fuzzy, gcc-internal-format
-#| msgid "Warn about comparison of different enum types"
msgid "bogus comparison result type"
msgstr "对ä¸åŒæžšä¸¾ç±»åž‹ä¹‹é—´çš„比较给出警告"
@@ -18950,7 +18397,6 @@ msgstr "对浮点å‘é‡çš„éžå…ƒç´ å¤§å°çš„å‘é‡ç§»ä½"
#: tree-cfg.c:3660 tree-cfg.c:3681
#, fuzzy, gcc-internal-format
-#| msgid "type mismatch in vector shift expression"
msgid "type mismatch in widening vector shift expression"
msgstr "å‘é‡ç§»ä½è¡¨è¾¾å¼ç±»åž‹ä¸åŒ¹é…"
@@ -19001,13 +18447,11 @@ msgstr "æ¡ä»¶è¡¨è¾¾å¼ä¸­ç±»åž‹ä¸åŒ¹é…"
#: tree-cfg.c:3900
#, fuzzy, gcc-internal-format
-#| msgid "type mismatch in vector shift expression"
msgid "type mismatch in vector permute expression"
msgstr "å‘é‡ç§»ä½è¡¨è¾¾å¼ç±»åž‹ä¸åŒ¹é…"
#: tree-cfg.c:3912
#, fuzzy, gcc-internal-format
-#| msgid "expected integer expression"
msgid "vector types expected in vector permute expression"
msgstr "需è¦æ•´æ•°è¡¨è¾¾å¼"
@@ -19018,7 +18462,6 @@ msgstr ""
#: tree-cfg.c:3939
#, fuzzy, gcc-internal-format
-#| msgid "invalid increment expression"
msgid "invalid mask type in vector permute expression"
msgstr "无效的自增语å¥"
@@ -19084,43 +18527,36 @@ msgstr "开关语å¥æ“作数无效"
#: tree-cfg.c:4268
#, fuzzy, gcc-internal-format
-#| msgid "invalid operand to switch statement"
msgid "non-integral type switch statement"
msgstr "开关语å¥æ“作数无效"
#: tree-cfg.c:4276
#, fuzzy, gcc-internal-format
-#| msgid "%<default%> label not within a switch statement"
msgid "invalid default case label in switch statement"
msgstr "%<default%>æ ‡å·æœªå‡ºçŽ°åœ¨ switch 语å¥å†…"
#: tree-cfg.c:4288
#, fuzzy, gcc-internal-format
-#| msgid "case label not within a switch statement"
msgid "invalid case label in switch statement"
msgstr "case æ ‡å·å‡ºçŽ°åœ¨å¼€å…³è¯­å¥å¤–"
#: tree-cfg.c:4295
#, fuzzy, gcc-internal-format
-#| msgid "invalid operand to switch statement"
msgid "invalid case range in switch statement"
msgstr "开关语å¥æ“作数无效"
#: tree-cfg.c:4305
#, fuzzy, gcc-internal-format
-#| msgid "case label not within a switch statement"
msgid "type mismatch for case label in switch statement"
msgstr "case æ ‡å·å‡ºçŽ°åœ¨å¼€å…³è¯­å¥å¤–"
#: tree-cfg.c:4315
#, fuzzy, gcc-internal-format
-#| msgid "case label not within a switch statement"
msgid "type precision mismatch in switch statement"
msgstr "case æ ‡å·å‡ºçŽ°åœ¨å¼€å…³è¯­å¥å¤–"
#: tree-cfg.c:4324
#, fuzzy, gcc-internal-format
-#| msgid "case label not within a switch statement"
msgid "case labels not sorted in switch statement"
msgstr "case æ ‡å·å‡ºçŽ°åœ¨å¼€å…³è¯­å¥å¤–"
@@ -19191,7 +18627,6 @@ msgstr "gimple_bb (phi) 设置为一个错误的基本å—"
#: tree-cfg.c:4816
#, fuzzy, gcc-internal-format
-#| msgid "from this location"
msgid "PHI node with location"
msgstr "从这个地方"
@@ -19327,13 +18762,11 @@ msgstr "忽略声明有 warn_unused_result 属性的函数的返回值"
#: tree-diagnostic.c:203
#, fuzzy, gcc-internal-format
-#| msgid "redefinition of %q+D"
msgid "in definition of macro %qs"
msgstr "%q+Dé‡å®šä¹‰"
#: tree-diagnostic.c:220
#, fuzzy, gcc-internal-format
-#| msgid "%s:%d: in constexpr expansion of %qs"
msgid "in expansion of macro %qs"
msgstr "%s:%d:在%qs的广义常表达å¼æ‰©å±•ä¸­"
@@ -19439,7 +18872,6 @@ msgstr "函数%q+F无法被内è”,因为它使用了与内è”冲çªçš„属性"
#: tree-inline.c:4147
#, fuzzy, gcc-internal-format
-#| msgid "inlining failed in call to %q+F: %s"
msgid "inlining failed in call to always_inline %q+F: %s"
msgstr "调用%q+F时内è”失败:%s"
@@ -19466,7 +18898,6 @@ msgstr "未实现的功能"
#: tree-ssa-loop-niter.c:2632
#, fuzzy, gcc-internal-format
-#| msgid "operation on %qE may be undefined"
msgid "iteration %E invokes undefined behavior"
msgstr "%qE上的è¿ç®—结果å¯èƒ½æ˜¯æœªå®šä¹‰çš„"
@@ -19482,7 +18913,6 @@ msgstr ""
#: tree-ssa-operands.c:1001
#, fuzzy, gcc-internal-format
-#| msgid "invalid operand in return statement"
msgid "virtual def operand missing for stmt"
msgstr "返回语å¥æ“作数无效"
@@ -19503,7 +18933,6 @@ msgstr ""
#: tree-ssa-operands.c:1042
#, fuzzy, gcc-internal-format
-#| msgid "operand number missing after %%-letter"
msgid "use operand missing for stmt"
msgstr "%% å­—æ¯åŽç¼ºå°‘æ“作数å·"
@@ -19529,13 +18958,11 @@ msgstr "此函数中的%qD在使用å‰å¯èƒ½æœªåˆå§‹åŒ–"
#: tree-ssa-uninit.c:238
#, fuzzy, gcc-internal-format
-#| msgid "%qD is used uninitialized in this function"
msgid "%qE is used uninitialized in this function"
msgstr "此函数中的%qD在使用å‰æœªåˆå§‹åŒ–"
#: tree-ssa-uninit.c:243
#, fuzzy, gcc-internal-format
-#| msgid "%qD may be used uninitialized in this function"
msgid "%qE may be used uninitialized in this function"
msgstr "此函数中的%qD在使用å‰å¯èƒ½æœªåˆå§‹åŒ–"
@@ -19676,7 +19103,6 @@ msgstr ""
#: tree-streamer-out.c:510
#, fuzzy, gcc-internal-format
-#| msgid "gimple bytecode streams do not support machine specific builtin functions on this target"
msgid "tree bytecode streams do not support machine specific builtin functions on this target"
msgstr "GIMPLE 字节ç æµåœ¨æ­¤ç›®æ ‡æœºä¸Šä¸æ”¯æŒæœºå™¨ç›¸å…³çš„内建函数"
@@ -19882,37 +19308,31 @@ msgstr "树检查:在 %4$s 中访问有 %3$d 个æ“作数的 omp_clause %2$s ç
#: tree.c:12081
#, fuzzy
-#| msgid "%qD is deprecated (declared at %s:%d): %s"
msgid "%qD is deprecated (declared at %r%s:%d%R): %s"
msgstr "ä¸å»ºè®®ä½¿ç”¨%qD(声明于 %s:%d):%s"
#: tree.c:12085
#, fuzzy
-#| msgid "%qD is deprecated (declared at %s:%d)"
msgid "%qD is deprecated (declared at %r%s:%d%R)"
msgstr "ä¸å»ºè®®ä½¿ç”¨%qD(声明于 %s:%d)"
#: tree.c:12110
#, fuzzy
-#| msgid "%qE is deprecated (declared at %s:%d): %s"
msgid "%qE is deprecated (declared at %r%s:%d%R): %s"
msgstr "ä¸å»ºè®®ä½¿ç”¨%qE(声明于 %s:%d):%s"
#: tree.c:12114
#, fuzzy
-#| msgid "%qE is deprecated (declared at %s:%d)"
msgid "%qE is deprecated (declared at %r%s:%d%R)"
msgstr "ä¸å»ºè®®ä½¿ç”¨%qE(声明于 %s:%d)"
#: tree.c:12121
#, fuzzy
-#| msgid "type is deprecated (declared at %s:%d): %s"
msgid "type is deprecated (declared at %r%s:%d%R): %s"
msgstr "ä¸å»ºè®®ä½¿ç”¨ç±»åž‹(声明于 %s:%d):%s"
#: tree.c:12125
#, fuzzy
-#| msgid "type is deprecated (declared at %s:%d)"
msgid "type is deprecated (declared at %r%s:%d%R)"
msgstr "ä¸å»ºè®®ä½¿ç”¨ç±»åž‹(声明于 %s:%d)"
@@ -19968,13 +19388,11 @@ msgstr "å˜é‡è·Ÿè¸ªå¤§å°è¶Šé™"
#: varasm.c:319
#, fuzzy, gcc-internal-format
-#| msgid "%+D causes a section type conflict"
msgid "%+D causes a section type conflict with %D"
msgstr "%+D 导致一个节类型冲çª"
#: varasm.c:322
#, fuzzy, gcc-internal-format
-#| msgid " conflict with %q+D"
msgid "section type conflict with %D"
msgstr " 与%q+D冲çª"
@@ -19985,13 +19403,11 @@ msgstr "%+D 导致一个节类型冲çª"
#: varasm.c:329
#, fuzzy, gcc-internal-format
-#| msgid "%+D causes a section type conflict"
msgid "section type conflict"
msgstr "%+D 导致一个节类型冲çª"
#: varasm.c:977
#, fuzzy, gcc-internal-format
-#| msgid "alignment of %q+D is greater than maximum object file alignment. Using %d"
msgid "alignment of %q+D is greater than maximum object file alignment %d"
msgstr "%q+D的对é½è¦æ±‚大于目标文件的最大对é½è¾¹ç•Œã€‚使用 %d"
@@ -20012,13 +19428,11 @@ msgstr "为%q+D指定的寄存器ä¸é€‚åˆæ­¤æ•°æ®ç±»åž‹"
#: varasm.c:1295
#, fuzzy, gcc-internal-format
-#| msgid "register specified for %q+D isn%'t suitable for data type"
msgid "the register specified for %q+D cannot be accessed by the current target"
msgstr "为%q+D指定的寄存器ä¸é€‚åˆæ­¤æ•°æ®ç±»åž‹"
#: varasm.c:1298
#, fuzzy, gcc-internal-format
-#| msgid "register used for two global register variables"
msgid "the register specified for %q+D is not general enough to be used as a register variable"
msgstr "寄存器用作两个全局寄存器å˜é‡"
@@ -20094,7 +19508,6 @@ msgstr "弱引用在此é…置下ä¸å—支æŒ"
#: varasm.c:5600
#, fuzzy, gcc-internal-format
-#| msgid "nested functions not supported on this target"
msgid "ifunc is not supported on this target"
msgstr "嵌套函数在此目标机上ä¸å—支æŒ"
@@ -20141,20 +19554,17 @@ msgstr "字节ç æµï¼šæ ‡è®° %s ä¸åœ¨é¢„期的范围[%s,%s]内"
#: c-family/array-notation-common.c:70
#, fuzzy, gcc-internal-format
-#| msgid "case label is not an integer constant expression"
msgid "__sec_implicit_index parameter must be an integer constant expression"
msgstr "case æ ‡å·ä¸æ˜¯ä¸€ä¸ªæ•´æ•°å¸¸é‡è¡¨è¾¾å¼"
#: c-family/array-notation-common.c:106
#, fuzzy, gcc-internal-format
-#| msgid "type mismatch in shift expression"
msgid "length mismatch in expression"
msgstr "移ä½è¡¨è¾¾å¼ç±»åž‹ä¸åŒ¹é…"
#: c-family/array-notation-common.c:278 c-family/array-notation-common.c:306
#: c/c-array-notation.c:721 cp/cp-array-notation.c:610
#, fuzzy, gcc-internal-format
-#| msgid "comparison between %qT and %qT"
msgid "rank mismatch between %qE and %qE"
msgstr "在%qT和%qT间比较"
@@ -20166,7 +19576,6 @@ msgstr "在%qT和%qT间比较"
#. may lie in the original expression.
#: c-family/array-notation-common.c:287
#, fuzzy, gcc-internal-format
-#| msgid "type mismatch in shift expression"
msgid "rank mismatch in expression %qE"
msgstr "移ä½è¡¨è¾¾å¼ç±»åž‹ä¸åŒ¹é…"
@@ -20177,19 +19586,16 @@ msgstr ""
#: c-family/c-cilkplus.c:39
#, fuzzy, gcc-internal-format
-#| msgid "iteration variable %qE should be private"
msgid "iteration variable cannot be volatile"
msgstr "迭代å˜é‡%qE应当是ç§æœ‰çš„"
#: c-family/c-cilkplus.c:82
#, fuzzy, gcc-internal-format
-#| msgid "%qE appears more than once in data clauses"
msgid "variable appears in more than one clause"
msgstr "%qE在数æ®å­å¥ä¸­å¤šæ¬¡å‡ºçŽ°"
#: c-family/c-cilkplus.c:84
#, fuzzy, gcc-internal-format
-#| msgid "struct defined here"
msgid "other clause defined here"
msgstr "结构在此定义"
@@ -20400,13 +19806,11 @@ msgstr "使用 -flax-vector-conversions 以å…许元素类型或数é‡ä¸åŒçš„å
#: c-family/c-common.c:2333
#, fuzzy, gcc-internal-format
-#| msgid "the last argument must be an 8-bit immediate"
msgid "__builtin_shuffle last argument must be an integer vector"
msgstr "最åŽä¸€ä¸ªå®žå‚必须是一个 8 ä½ç«‹å³æ•°"
#: c-family/c-common.c:2342
#, fuzzy, gcc-internal-format
-#| msgid "%<__builtin_longjmp%> second argument must be 1"
msgid "__builtin_shuffle arguments must be vectors"
msgstr "%<__builtin_longjmp%>的第二个实å‚必须是 1"
@@ -20557,13 +19961,11 @@ msgstr "%<sizeof%>ä¸èƒ½ç”¨äºŽå‡½æ•°ç±»åž‹"
#: c-family/c-common.c:4958
#, fuzzy, gcc-internal-format
-#| msgid "ISO C++ does not allow %<alignof%> with a non-type"
msgid "ISO C++ does not permit %<alignof%> applied to a function type"
msgstr "ISO C++ ä¸å…许对éžç±»åž‹ä½¿ç”¨%<alignof%>"
#: c-family/c-common.c:4961
#, fuzzy, gcc-internal-format
-#| msgid "ISO C++ does not allow %<alignof%> with a non-type"
msgid "ISO C does not permit %<_Alignof%> applied to a function type"
msgstr "ISO C++ ä¸å…许对éžç±»åž‹ä½¿ç”¨%<alignof%>"
@@ -20574,13 +19976,11 @@ msgstr "%qsä¸èƒ½ç”¨äºŽ void 类型"
#: c-family/c-common.c:4981
#, fuzzy, gcc-internal-format
-#| msgid "invalid application of %qs to incomplete type %qT "
msgid "invalid application of %qs to incomplete type %qT"
msgstr "%qsä¸èƒ½ç”¨äºŽä¸å®Œå…¨çš„类型%qT"
#: c-family/c-common.c:4989
#, fuzzy, gcc-internal-format
-#| msgid "invalid application of %qs to incomplete type %qT "
msgid "invalid application of %qs to array type %qT of incomplete element type"
msgstr "%qsä¸èƒ½ç”¨äºŽä¸å®Œå…¨çš„类型%qT"
@@ -20787,13 +20187,11 @@ msgstr "此目标机ä¸æ”¯æŒèŠ‚属性"
#: c-family/c-common.c:7417
#, fuzzy, gcc-internal-format
-#| msgid "requested alignment is not a constant"
msgid "requested alignment is not an integer constant"
msgstr "è¦æ±‚的对é½è¾¹ç•Œä¸æ˜¯å¸¸é‡"
#: c-family/c-common.c:7425
#, fuzzy, gcc-internal-format
-#| msgid "requested alignment is not a power of 2"
msgid "requested alignment is not a positive power of 2"
msgstr "è¦æ±‚的对é½è¾¹ç•Œä¸æ˜¯ 2 çš„æŸæ¬¡æ–¹"
@@ -20804,7 +20202,6 @@ msgstr "è¦æ±‚的对é½è¾¹ç•Œå¤ªå¤§"
#: c-family/c-common.c:7513
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "requested alignment is too large"
msgid "requested alignment %d is larger than %d"
msgstr "è¦æ±‚的对é½è¾¹ç•Œå¤ªå¤§"
@@ -20921,37 +20318,31 @@ msgstr "定义之åŽä¸èƒ½è®¾å®š%qE属性"
#: c-family/c-common.c:8190
#, fuzzy, gcc-internal-format
-#| msgid "%qE attribute ignored"
msgid "%qE attribute duplicated"
msgstr "%qE属性被忽略"
#: c-family/c-common.c:8192
#, fuzzy, gcc-internal-format
-#| msgid "%qE attribute ignored for %qE"
msgid "%qE attribute follows %qE"
msgstr "%qE属性为%qE所忽略"
#: c-family/c-common.c:8291
#, fuzzy, gcc-internal-format
-#| msgid "previously declared here"
msgid "type was previously declared %qE"
msgstr "以å‰åœ¨æ­¤å£°æ˜Žè¿‡"
#: c-family/c-common.c:8344
#, fuzzy, gcc-internal-format
-#| msgid "cleanup argument not an identifier"
msgid "%qE argument not an identifier"
msgstr "cleanup 实å‚ä¸æ˜¯ä¸€ä¸ªæ ‡è¯†ç¬¦"
#: c-family/c-common.c:8355
#, fuzzy, gcc-internal-format
-#| msgid "%qD is not declared in %qD"
msgid "%qD is not compatible with %qD"
msgstr "%qD未在%qD中声明"
#: c-family/c-common.c:8358
#, fuzzy, gcc-internal-format
-#| msgid "cleanup argument not a function"
msgid "transaction_wrap argument is not a function"
msgstr "cleanup 实å‚ä¸æ˜¯ä¸€ä¸ªå‡½æ•°"
@@ -21095,7 +20486,6 @@ msgstr "给予函数%2$qEçš„å‚æ•°%1$uä¸æ˜¯æ•´åž‹å¸¸é‡"
#: c-family/c-common.c:9343
#, fuzzy, gcc-internal-format
-#| msgid "non-const integer argument %u in call to function %qE"
msgid "non-integer argument 3 in call to function %qE"
msgstr "给予函数%2$qEçš„å‚æ•°%1$uä¸æ˜¯æ•´åž‹å¸¸é‡"
@@ -21316,7 +20706,6 @@ msgstr "%<->%>å‚数类型无效(有%qT)"
#: c-family/c-common.c:9932
#, fuzzy, gcc-internal-format
-#| msgid "invalid type argument of %<->%> (have %qT)"
msgid "invalid type argument of %<->*%> (have %qT)"
msgstr "%<->%>å‚数类型无效(有%qT)"
@@ -21342,49 +20731,41 @@ msgstr "%2$qE的第 %1$d 个实å‚类型ä¸å…¼å®¹"
#: c-family/c-common.c:10277
#, fuzzy, gcc-internal-format
-#| msgid "not enough arguments to function %qE"
msgid "incorrect number of arguments to function %qE"
msgstr "æ供给函数%qE的实å‚太少"
#: c-family/c-common.c:10285
#, fuzzy, gcc-internal-format
-#| msgid "argument %d of %qE must be an address"
msgid "argument 1 of %qE must be a non-void pointer type"
msgstr "%2$qEçš„å®žå‚ %1$d 必须是地å€"
#: c-family/c-common.c:10294
#, fuzzy, gcc-internal-format
-#| msgid "%Kfirst argument of %D must be a pointer, second integer constant"
msgid "argument 1 of %qE must be a pointer to a constant size type"
msgstr "%K%D 的第一个实å‚必须是一个指针,第二个必须是整常é‡"
#: c-family/c-common.c:10305
#, fuzzy, gcc-internal-format
-#| msgid "%Kfirst argument of %D must be a pointer, second integer constant"
msgid "argument 1 of %qE must be a pointer to a nonzero size object"
msgstr "%K%D 的第一个实å‚必须是一个指针,第二个必须是整常é‡"
#: c-family/c-common.c:10320
#, fuzzy, gcc-internal-format
-#| msgid "argument %d of %qE must be an address"
msgid "argument %d of %qE must be a pointer type"
msgstr "%2$qEçš„å®žå‚ %1$d 必须是地å€"
#: c-family/c-common.c:10327
#, fuzzy, gcc-internal-format
-#| msgid "Type/rank mismatch in argument '%s' at %L"
msgid "size mismatch in argument %d of %qE"
msgstr "%2$L处实å‚‘%1$s’类型/秩ä¸åŒ¹é…"
#: c-family/c-common.c:10343
#, fuzzy, gcc-internal-format
-#| msgid "incompatible type for argument %d of %qE"
msgid "invalid memory model argument %d of %qE"
msgstr "%2$qE的第 %1$d 个实å‚类型ä¸å…¼å®¹"
#: c-family/c-common.c:10350
#, fuzzy, gcc-internal-format
-#| msgid "incompatible type for argument %d of %qE"
msgid "non-integer memory model argument %d of %qE"
msgstr "%2$qE的第 %1$d 个实å‚类型ä¸å…¼å®¹"
@@ -21520,7 +20901,6 @@ msgstr "比较无符å·æ•°å’Œå–ååŽåˆç»æå‡çš„无符å·æ•°"
#: c-family/c-common.c:11454
#, fuzzy, gcc-internal-format
-#| msgid "%q+D defined but not used"
msgid "typedef %qD locally defined but not used"
msgstr "%q+D定义åŽæœªä½¿ç”¨"
@@ -21532,7 +20912,6 @@ msgstr "索引值越界"
#: c-family/c-common.c:11733 c-family/c-common.c:11783
#: c-family/c-common.c:11798 cp/call.c:4493 cp/call.c:4500
#, fuzzy, gcc-internal-format
-#| msgid "conversion from %qT to %qT is ambiguous"
msgid "conversion of scalar %qT to vector %qT involves truncation"
msgstr "从%qT到%qT的转æ¢æœ‰æ­§ä¹‰"
@@ -22020,7 +21399,6 @@ msgstr "无效的自增语å¥"
#: c-family/c-omp.c:976
#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a function name"
msgid "%qD is not an function argument"
msgstr "%qEä¸æ˜¯ä¸€ä¸ªå‡½æ•°å"
@@ -22091,7 +21469,6 @@ msgstr "-Wformat-security 未与 -Wformat 一起使用,已忽略"
#: c-family/c-opts.c:924
#, fuzzy, gcc-internal-format
-#| msgid "nested functions not supported on this target"
msgid "external TLS initialization functions not supported on this target"
msgstr "嵌套函数在此目标机上ä¸å—支æŒ"
@@ -22502,19 +21879,16 @@ msgstr "ä¸èƒ½å¯¹è¯¥ç±»åž‹çš„实å‚求ç»å¯¹å€¼"
#: c-family/cilk.c:93 cp/parser.c:5784
#, fuzzy, gcc-internal-format
-#| msgid "%<friend%> can only be specified inside a class"
msgid "%<_Cilk_spawn%> may only be used inside a function"
msgstr "%<friend%>åªèƒ½åœ¨ç±»ä¸­æŒ‡å®š"
#: c-family/cilk.c:107
#, fuzzy, gcc-internal-format
-#| msgid "virtual functions cannot be friends"
msgid "only function calls can be spawned"
msgstr "虚函数ä¸èƒ½æ˜¯å‹å…ƒ"
#: c-family/cilk.c:356
#, fuzzy, gcc-internal-format
-#| msgid "address of explicit register variable %qD requested"
msgid "explicit register variable %qD may not be modified in spawn"
msgstr "è¦æ±‚显å¼å¯„存器å˜é‡%qD的地å€ã€‚"
@@ -22525,7 +21899,6 @@ msgstr ""
#: c-family/cilk.c:436
#, fuzzy, gcc-internal-format
-#| msgid "invalid use of %qD in linkage specification"
msgid "invalid use of label %q+D in %<_Cilk_spawn%>"
msgstr "指定链接时使用%qD无效"
@@ -22551,7 +21924,6 @@ msgstr "-mtls-size 开关的值%qsä¸æ­£ç¡®"
#: common/config/arc/arc-common.c:80
#, fuzzy, gcc-internal-format
-#| msgid "multiple function type attributes specified"
msgid "multiple -mcpu= options specified."
msgstr "指定了多个函数类型属性"
@@ -22572,43 +21944,36 @@ msgstr "-mcpu=%s 芯片版本ä¸æ­£ç¡®"
#: common/config/i386/i386-common.c:764
#, fuzzy, gcc-internal-format
-#| msgid "%salign-loops%s is obsolete, use -falign-loops%s"
msgid "-malign-loops is obsolete, use -falign-loops"
msgstr "%salign-loops%s å·²ç»è¿‡æ—¶ï¼Œè¯·ä½¿ç”¨ -falign-loops%s"
#: common/config/i386/i386-common.c:766
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%salign-loops=%d%s is not between 0 and %d"
msgid "-malign-loops=%d is not between 0 and %d"
msgstr "%salign-loops=%d%s ä¸åœ¨ 0 å’Œ %d 之间"
#: common/config/i386/i386-common.c:773
#, fuzzy, gcc-internal-format
-#| msgid "%salign-jumps%s is obsolete, use -falign-jumps%s"
msgid "-malign-jumps is obsolete, use -falign-jumps"
msgstr "%salign-jumps%s å·²ç»è¿‡æ—¶ï¼Œè¯·ä½¿ç”¨ -falign-jumps%s"
#: common/config/i386/i386-common.c:775
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%salign-loops=%d%s is not between 0 and %d"
msgid "-malign-jumps=%d is not between 0 and %d"
msgstr "%salign-loops=%d%s ä¸åœ¨ 0 å’Œ %d 之间"
#: common/config/i386/i386-common.c:783
#, fuzzy, gcc-internal-format
-#| msgid "%salign-functions%s is obsolete, use -falign-functions%s"
msgid "-malign-functions is obsolete, use -falign-functions"
msgstr "%salign-functions%s 已过时,请使用 -falign-functions%s"
#: common/config/i386/i386-common.c:785
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%salign-loops=%d%s is not between 0 and %d"
msgid "-malign-functions=%d is not between 0 and %d"
msgstr "%salign-loops=%d%s ä¸åœ¨ 0 å’Œ %d 之间"
#: common/config/i386/i386-common.c:794
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%sbranch-cost=%d%s is not between 0 and 5"
msgid "-mbranch-cost=%d is not between 0 and 5"
msgstr "%sbranch-cost=%d%sä¸åœ¨ 0 å’Œ 5 之间"
@@ -22664,7 +22029,6 @@ msgstr "RX200 CPU 没有 FPU 硬件"
#: common/config/rx/rx-common.c:63
#, fuzzy, gcc-internal-format
-#| msgid "the RX200 cpu does not have FPU hardware"
msgid "the RX100 cpu does not have FPU hardware"
msgstr "RX200 CPU 没有 FPU 硬件"
@@ -22680,7 +22044,6 @@ msgstr "栈大å°å¿…须刚好是 2 çš„æŸæ¬¡æ–¹"
#: common/config/v850/v850-common.c:47
#, fuzzy, gcc-internal-format
-#| msgid "value passed to %<-m%s%> is too large"
msgid "value passed in %qs is too large"
msgstr "传递给%<-m%s%>的值太大"
@@ -22777,7 +22140,6 @@ msgstr "%qE 2.95 虚表兼容属性åªå¯¹ C++ 类有效"
#: config/darwin.c:2738
#, fuzzy, gcc-internal-format
-#| msgid "visibility attribute not supported in this configuration; ignored"
msgid "protected visibility attribute not supported in this configuration; ignored"
msgstr "å¯è§æ€§å±žæ€§åœ¨æ­¤é…置下ä¸å—支æŒï¼›å·²å¿½ç•¥"
@@ -22788,19 +22150,16 @@ msgstr "无法打开临时å“应文件 %s"
#: config/darwin.c:3096
#, fuzzy, gcc-internal-format
-#| msgid "%<-fobjc-abi-version%> >= 2 is only supported on %<-m64%> targets for %<-fnext-runtime%>"
msgid "%<-fobjc-abi-version%> >= 2 must be used for %<-m64%> targets with %<-fnext-runtime%>"
msgstr "%<-fobjc-abi-version%> >= 2 åªåœ¨%<-m64%>目标下支æŒ%<-fnext-runtime%>"
#: config/darwin.c:3100
#, fuzzy, gcc-internal-format
-#| msgid "%<-fobjc-abi-version%> >= 2 is only supported on %<-m64%> targets for %<-fnext-runtime%>"
msgid "%<-fobjc-abi-version%> >= 2 is not supported on %<-m32%> targets with %<-fnext-runtime%>"
msgstr "%<-fobjc-abi-version%> >= 2 åªåœ¨%<-m64%>目标下支æŒ%<-fnext-runtime%>"
#: config/darwin.c:3185
#, fuzzy, gcc-internal-format
-#| msgid "-mdynamic-no-pic overrides -fpic or -fPIC"
msgid "%<-mdynamic-no-pic%> overrides %<-fpic%>, %<-fPIC%>, %<-fpie%> or %<-fPIE%>"
msgstr "-mdynamic-no-pic 覆盖了 -fpic 或 -fPIC"
@@ -22917,26 +22276,22 @@ msgstr "对 VxWorks çš„å–样支æŒ"
#: config/aarch64/aarch64-builtins.c:817
#, fuzzy, gcc-internal-format
-#| msgid "incompatible type for argument %d of %qE"
msgid "incompatible type for argument %d, expected %<const int%>"
msgstr "%2$qE的第 %1$d 个实å‚类型ä¸å…¼å®¹"
#: config/aarch64/aarch64.c:5041
#, fuzzy, gcc-internal-format
-#| msgid "missing filename after %qs"
msgid "missing feature modifier after %qs"
msgstr "%qsåŽç¼ºå°‘文件å"
#. Extension not found in list.
#: config/aarch64/aarch64.c:5062
#, fuzzy, gcc-internal-format
-#| msgid "unknown TLS model %qs"
msgid "unknown feature modifier %qs"
msgstr "未知的 TLS 模型%qs"
#: config/aarch64/aarch64.c:5093
#, fuzzy, gcc-internal-format
-#| msgid "missing path after %qs"
msgid "missing arch name in -march=%qs"
msgstr "%qsåŽç¼ºå°‘路径"
@@ -22948,33 +22303,28 @@ msgstr "开关 -mcpu=%s 与 -march=%s 冲çª"
#. ARCH name not found in list.
#: config/aarch64/aarch64.c:5125
#, fuzzy, gcc-internal-format
-#| msgid "unknown value %s for -mfpu"
msgid "unknown value %qs for -march"
msgstr "-mfpu 的值 %s 未知"
#: config/aarch64/aarch64.c:5150
#, fuzzy, gcc-internal-format
-#| msgid "missing path after %qs"
msgid "missing cpu name in -mcpu=%qs"
msgstr "%qsåŽç¼ºå°‘路径"
#. CPU name not found in list.
#: config/aarch64/aarch64.c:5174
#, fuzzy, gcc-internal-format
-#| msgid "unknown value %s for -mfpu"
msgid "unknown value %qs for -mcpu"
msgstr "-mfpu 的值 %s 未知"
#. CPU name not found in list.
#: config/aarch64/aarch64.c:5198
#, fuzzy, gcc-internal-format
-#| msgid "unknown value %s for -mfpu"
msgid "unknown value %qs for -mtune"
msgstr "-mfpu 的值 %s 未知"
#: config/aarch64/aarch64.c:5234
#, fuzzy, gcc-internal-format
-#| msgid "does not support multilib"
msgid "Assembler does not support -mabi=ilp32"
msgstr "ä¸æ”¯æŒ multilib"
@@ -22986,19 +22336,16 @@ msgstr ""
#: config/aarch64/aarch64.c:5611 config/aarch64/aarch64.c:5719
#: config/aarch64/aarch64.c:5958
#, fuzzy, gcc-internal-format
-#| msgid "Use hardware floating point instructions"
msgid "%qs and floating point or vector arguments"
msgstr "使用硬件浮点指令"
#: config/aarch64/aarch64.c:6830
#, fuzzy, gcc-internal-format
-#| msgid "operand number out of range"
msgid "lane out of range"
msgstr "æ“作数å·è¶…出范围"
#: config/aarch64/aarch64.c:6840
#, fuzzy, gcc-internal-format
-#| msgid "constant argument out of range for %qs"
msgid "constant out of range"
msgstr "常é‡å®žå‚超过%qs的范围"
@@ -23066,7 +22413,6 @@ msgstr "错误的内建 fcode"
#: config/arc/arc.c:738
#, fuzzy, gcc-internal-format
-#| msgid "-mrelax is only supported for RTP PIC"
msgid "-mmul64 not supported for ARC700"
msgstr "-mrelax åªåœ¨ RTP PIC 上å—支æŒ"
@@ -23107,7 +22453,6 @@ msgstr ""
#: config/arc/arc.c:1230
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "multiple function type attributes specified"
msgid "multiply option implies r%d is fixed"
msgstr "指定了多个函数类型属性"
@@ -23131,13 +22476,11 @@ msgstr ""
#: config/arc/arc.c:5373
#, fuzzy, gcc-internal-format
-#| msgid "%<__builtin_next_arg%> called without an argument"
msgid "__builtin_arc_aligned with non-constant alignment"
msgstr "调用%<__builtin_next_arg%>时没有给定实å‚"
#: config/arc/arc.c:5381
#, fuzzy, gcc-internal-format
-#| msgid "invalid argument to %<__builtin_frame_address%>"
msgid "invalid alignment value for __builtin_arc_aligned"
msgstr "%<__builtin_frame_address%>的实å‚无效"
@@ -23158,7 +22501,6 @@ msgstr ""
#: config/arc/arc.c:6206
#, fuzzy, gcc-internal-format
-#| msgid "Bad address, not register:"
msgid "insn addresses not freed"
msgstr "错误的地å€ï¼Œä¸æ˜¯å¯„存器:"
@@ -23294,7 +22636,6 @@ msgstr "AAPCS ä¸æ”¯æŒ -mcallee-super-interworking"
#: config/arm/arm.c:2571
#, fuzzy, gcc-internal-format
-#| msgid "-fPIC and -G are incompatible"
msgid "iWMMXt and NEON are incompatible"
msgstr "-fPIC 与 -G 互ä¸å…¼å®¹"
@@ -23320,13 +22661,11 @@ msgstr "-mtp=cp15 å’Œ 16 ä½ Thumb ä¸èƒ½å¹¶ç”¨"
#: config/arm/arm.c:2638
#, fuzzy, gcc-internal-format
-#| msgid "structure size boundary can only be set to %s"
msgid "structure size boundary can only be set to 8, 32 or 64"
msgstr "结构大å°è¾¹ç•Œåªèƒ½è¢«è®¾å®šä¸º %s"
#: config/arm/arm.c:2640
#, fuzzy, gcc-internal-format
-#| msgid "structure size boundary can only be set to %s"
msgid "structure size boundary can only be set to 8 or 32"
msgstr "结构大å°è¾¹ç•Œåªèƒ½è¢«è®¾å®šä¸º %s"
@@ -23352,7 +22691,6 @@ msgstr "‘%s’ä¸èƒ½è¢«ç”¨ä½œ PIC 寄存器"
#: config/arm/arm.c:2715
#, fuzzy, gcc-internal-format
-#| msgid "target CPU does not support ARM mode"
msgid "target CPU does not support unaligned accesses"
msgstr "目标 CPU ä¸æ”¯æŒ ARM 模å¼"
@@ -23440,7 +22778,6 @@ msgstr "掩ç å¿…须是一个立å³æ•°"
#: config/arm/arm.c:25441
#, fuzzy, gcc-internal-format
-#| msgid "%qE attribute argument should be between 0 to 255"
msgid "the range of mask should be in 0 to 255"
msgstr "%qE属性的å‚数应当在 0 å’Œ 255 之间"
@@ -23566,7 +22903,6 @@ msgstr ""
#: config/arm/arm.c:26165
#, fuzzy, gcc-internal-format
-#| msgid "Unexpected end of module"
msgid "Unexpected thumb1 far jump"
msgstr "éžé¢„期的模å—结æŸ"
@@ -23582,13 +22918,11 @@ msgstr "Thumb 模å¼ä¸­ä¸èƒ½ç¼–ç ä¸­æ–­æœåŠ¡è¿›ç¨‹"
#: config/avr/avr-c.c:66 config/avr/avr-c.c:191
#, fuzzy, gcc-internal-format
-#| msgid "%qs expects a constant argument"
msgid "%qs expects 1 argument but %d given"
msgstr "%qs需è¦ä¸€ä¸ªå¸¸é‡å®žå‚"
#: config/avr/avr-c.c:77
#, fuzzy, gcc-internal-format
-#| msgid "%qs expects a constant argument"
msgid "%qs expects a fixed-point value as argument"
msgstr "%qs需è¦ä¸€ä¸ªå¸¸é‡å®žå‚"
@@ -23599,25 +22933,21 @@ msgstr "ä¸å»ºè®®ä½¿ç”¨ã€‚此开关ä¸èµ·ä½œç”¨ã€‚"
#: config/avr/avr-c.c:108 config/avr/avr-c.c:174 config/avr/avr-c.c:231
#, fuzzy, gcc-internal-format
-#| msgid "no matching template for %qD found"
msgid "no matching fixed-point overload found for %qs"
msgstr "没有找到与%qD匹é…的模æ¿"
#: config/avr/avr-c.c:125
#, fuzzy, gcc-internal-format
-#| msgid "%qs expects a constant argument"
msgid "%qs expects 2 arguments but %d given"
msgstr "%qs需è¦ä¸€ä¸ªå¸¸é‡å®žå‚"
#: config/avr/avr-c.c:137 config/avr/avr-c.c:202
#, fuzzy, gcc-internal-format
-#| msgid "%qs expects a constant argument"
msgid "%qs expects a fixed-point value as first argument"
msgstr "%qs需è¦ä¸€ä¸ªå¸¸é‡å®žå‚"
#: config/avr/avr-c.c:145
#, fuzzy, gcc-internal-format
-#| msgid "%qs expects a constant argument"
msgid "%qs expects an integer value as second argument"
msgstr "%qs需è¦ä¸€ä¸ªå¸¸é‡å®žå‚"
@@ -23633,19 +22963,16 @@ msgstr "ä¸æ”¯æŒ -fPIC"
#: config/avr/avr.c:322
#, fuzzy, gcc-internal-format
-#| msgid "-fpic is not supported"
msgid "-fpie is not supported"
msgstr "ä¸æ”¯æŒ -fpic"
#: config/avr/avr.c:324
#, fuzzy, gcc-internal-format
-#| msgid "-fPIC is not supported"
msgid "-fPIE is not supported"
msgstr "ä¸æ”¯æŒ -fPIC"
#: config/avr/avr.c:586
#, fuzzy, gcc-internal-format
-#| msgid "-flto and -fwhopr are mutually exclusive"
msgid "function attributes %qs, %qs and %qs are mutually exclusive"
msgstr "-flto and -fwhopr 互斥"
@@ -23656,25 +22983,21 @@ msgstr "%qE属性åªèƒ½ç”¨äºŽå‡½æ•°"
#: config/avr/avr.c:616
#, fuzzy, gcc-internal-format
-#| msgid "%qD cannot have default arguments"
msgid "%qs function cannot have arguments"
msgstr "%qDä¸èƒ½æœ‰é»˜è®¤å‚æ•°"
#: config/avr/avr.c:619
#, fuzzy, gcc-internal-format
-#| msgid "functions cannot return __fp16 type"
msgid "%qs function cannot return a value"
msgstr "函数ä¸èƒ½è¿”回 __fp16 类型"
#: config/avr/avr.c:626
#, fuzzy, gcc-internal-format
-#| msgid "%qs appears to be a misspelled signal handler"
msgid "%qs appears to be a misspelled %s handler"
msgstr "%qs似乎是一个拼写错的信å·å¤„ç†è€…"
#: config/avr/avr.c:856
#, fuzzy, gcc-internal-format
-#| msgid "'builtin_return_address' contains only 2 bytes of address"
msgid "%<builtin_return_address%> contains only 2 bytes of address"
msgstr "‘builtin_return_address’åªåŒ…å«ä¸¤å­—节地å€"
@@ -23690,19 +23013,16 @@ msgstr "用程åºå†…存地å€è®¿é—®æ•°æ®å†…å­˜"
#: config/avr/avr.c:2241
#, fuzzy, gcc-internal-format
-#| msgid "accessing program memory with data memory address"
msgid "accessing program memory with data memory address"
msgstr "用数æ®å†…存地å€è®¿é—®ç¨‹åºå†…å­˜"
#: config/avr/avr.c:2660
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Number of registers used to pass integer arguments"
msgid "fixed register %s used to pass parameter to function"
msgstr "用以传递整数å‚数的寄存器个数"
#: config/avr/avr.c:2931
#, fuzzy, gcc-internal-format
-#| msgid "conflicting named address spaces (%s vs %s)"
msgid "writing to address space %qs not supported"
msgstr "冲çªçš„有å地å€ç©ºé—´(%så’Œ%s)"
@@ -23718,13 +23038,11 @@ msgstr ""
#: config/avr/avr.c:8292
#, fuzzy, gcc-internal-format
-#| msgid "pointers to disjoint address spaces used in conditional expression"
msgid "pointer targeting address space %qs must be const in %qT"
msgstr "æ¡ä»¶è¡¨è¾¾å¼ä¸­ä½¿ç”¨äº†æŒ‡å‘ä¸ç›¸äº¤åœ°å€ç©ºé—´çš„指针"
#: config/avr/avr.c:8295
#, fuzzy, gcc-internal-format
-#| msgid "pointers to disjoint address spaces used in conditional expression"
msgid "pointer targeting address space %qs must be const in %s %q+D"
msgstr "æ¡ä»¶è¡¨è¾¾å¼ä¸­ä½¿ç”¨äº†æŒ‡å‘ä¸ç›¸äº¤åœ°å€ç©ºé—´çš„指针"
@@ -23745,7 +23063,6 @@ msgstr "åªæœ‰æœªåˆå§‹åŒ–çš„å˜é‡æ‰èƒ½æ”¾åœ¨ .noinit 节中"
#: config/avr/avr.c:8597
#, fuzzy, gcc-internal-format
-#| msgid "only initialized variables can be placed into program memory area"
msgid "uninitialized variable %q+D put into program memory area"
msgstr "åªæœ‰åˆå§‹åŒ–çš„å˜é‡æ‰èƒ½æ”¾å…¥ç¨‹åºå†…存区"
@@ -23756,19 +23073,16 @@ msgstr "MCU%qsåªæ”¯æŒæ±‡ç¼–器"
#: config/avr/avr.c:11101
#, fuzzy, gcc-internal-format
-#| msgid "Conversion from %s to %s at %L"
msgid "conversion from address space %qs to address space %qs"
msgstr "从 %s 转æ¢åˆ° %s,ä½äºŽ %L"
#: config/avr/avr.c:12048
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Unexpected end of module in string constant"
msgid "%s expects a compile time integer constant"
msgstr "字符串常é‡ä¸­å‡ºçŽ°éžé¢„期的模å—结æŸ"
#: config/avr/avr.c:12062
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%qs expects a constant argument"
msgid "%s expects a compile time long integer constant as first argument"
msgstr "%qs需è¦ä¸€ä¸ªå¸¸é‡å®žå‚"
@@ -23855,7 +23169,6 @@ msgstr "ä¸èƒ½ä¸ºå±€éƒ¨å˜é‡æŒ‡å®š%qE属性"
#: config/c6x/c6x.c:238
#, fuzzy, gcc-internal-format
-#| msgid "-fPIC and -fpic are not supported for this target"
msgid "-fpic and -fPIC not supported without -mdsbt on this target"
msgstr "-fPIC å’Œ -fpic ä¸è¢«æ­¤ç›®æ ‡æ‰€æ”¯æŒ"
@@ -23871,7 +23184,6 @@ msgstr ""
#: config/cr16/cr16.c:299
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "invalid thread pointer option: -mtp=%s"
msgid "invalid data model option -mdata-model=%s"
msgstr "无效的线程指钟选项:-mtp=%s"
@@ -24020,13 +23332,11 @@ msgstr ""
#: config/epiphany/epiphany.c:1468
#, fuzzy, gcc-internal-format
-#| msgid "stack size must be an exact power of 2"
msgid "stack_offset must be at least 4"
msgstr "栈大å°å¿…须刚好是 2 çš„æŸæ¬¡æ–¹"
#: config/epiphany/epiphany.c:1470
#, fuzzy, gcc-internal-format
-#| msgid "stack size must be an exact power of 2"
msgid "stack_offset must be a multiple of 4"
msgstr "栈大å°å¿…须刚好是 2 çš„æŸæ¬¡æ–¹"
@@ -24092,7 +23402,6 @@ msgstr "此内建函数åªåœ¨ fr450 上å¯ç”¨"
#: config/h8300/h8300.c:324
#, fuzzy, gcc-internal-format
-#| msgid "-f%s not supported: ignored"
msgid "-msx is not supported in coff"
msgstr "-f%s ä¸å—支æŒï¼šå·²å¿½ç•¥"
@@ -24103,25 +23412,21 @@ msgstr "-ms2600 未与 -ms 一起使用"
#: config/h8300/h8300.c:352
#, fuzzy, gcc-internal-format
-#| msgid "-mn is used without -mh or -ms"
msgid "-mn is used without -mh or -ms or -msx"
msgstr "-mn 未与 -mh 或 -ms 一起使用"
#: config/h8300/h8300.c:358
#, fuzzy, gcc-internal-format
-#| msgid "-ms2600 is used without -ms"
msgid "-mexr is used without -ms"
msgstr "-ms2600 未与 -ms 一起使用"
#: config/h8300/h8300.c:364
#, fuzzy, gcc-internal-format
-#| msgid "%<__int128%> is not supported for this target"
msgid "-mint32 is not supported for H8300 and H8300L targets"
msgstr "%<__int128%>在此目标机上ä¸å—支æŒ"
#: config/h8300/h8300.c:370
#, fuzzy, gcc-internal-format
-#| msgid "-mn is used without -mh or -ms"
msgid "-mexr is used without -ms or -msx"
msgstr "-mn 未与 -mh 或 -ms 一起使用"
@@ -24142,7 +23447,6 @@ msgstr "ä¸èƒ½åœ¨ PCH 文件中设定ä½ç½®ï¼š%m"
#: config/i386/i386.c:2911
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "-Werror=%s: no option -%s"
msgid "wrong arg %s to option %s"
msgstr "-Werror=%s:没有选项 -%s"
@@ -24153,13 +23457,11 @@ msgstr ""
#: config/i386/i386.c:2929
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "register name not specified for %q+D"
msgid "wrong stringop strategy name %s specified for option %s"
msgstr "%q+D的寄存器å无效"
#: config/i386/i386.c:2943
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "alignment may not be specified for %q+D"
msgid "unknown alignment %s specified for option %s"
msgstr "ä¸èƒ½ä¸º%q+D指定对é½"
@@ -24170,13 +23472,11 @@ msgstr ""
#: config/i386/i386.c:2962
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "no class name specified with %qs"
msgid "too many size ranges specified in option %s"
msgstr "%qs没有指定类å"
#: config/i386/i386.c:3016
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Unknown argument list function at %L"
msgid "Unknown parameter to option -mtune-ctrl: %s"
msgstr "%L处å‚数列表函数未知"
@@ -24193,7 +23493,6 @@ msgstr ""
#: config/i386/i386.c:3424
#, fuzzy, gcc-internal-format
-#| msgid "code model %qs not supported in the %s bit mode"
msgid "address mode %qs not supported in the %s bit mode"
msgstr "代ç æ¨¡å¼%qs在 %s ä½æ¨¡å¼ä¸‹ä¸å—支æŒ"
@@ -24205,7 +23504,6 @@ msgstr "代ç æ¨¡å¼%qs在 %s ä½æ¨¡å¼ä¸‹ä¸å—支æŒ"
#: config/i386/i386.c:3462 config/i386/i386.c:3474
#, fuzzy, gcc-internal-format
-#| msgid "code model %qs not supported in the %s bit mode"
msgid "code model %qs not supported in x32 mode"
msgstr "代ç æ¨¡å¼%qs在 %s ä½æ¨¡å¼ä¸‹ä¸å—支æŒ"
@@ -24216,7 +23514,6 @@ msgstr "代ç æ¨¡å¼ %s 在 PIC 模å¼ä¸‹ä¸å—支æŒ"
#: config/i386/i386.c:3517
#, fuzzy, gcc-internal-format
-#| msgid "-m%s not supported in this configuration"
msgid "-masm=intel not supported in this configuration"
msgstr "-m%s 在此é…置下ä¸å—支æŒ"
@@ -24237,7 +23534,6 @@ msgstr "generic åªèƒ½ç”¨åœ¨%stune%s %s中"
#: config/i386/i386.c:3678
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "generic CPU can be used only for %stune=%s %s"
msgid "intel CPU can be used only for %stune=%s %s"
msgstr "generic åªèƒ½ç”¨åœ¨%stune%s %s中"
@@ -24253,13 +23549,11 @@ msgstr "%2$stune=%3$s%4$s所带å‚æ•°(%1$s)ä¸æ­£ç¡®"
#: config/i386/i386.c:3777
#, fuzzy, gcc-internal-format
-#| msgid "%sregparm%s is ignored in 64-bit mode"
msgid "-mregparm is ignored in 64-bit mode"
msgstr "%sregparm%s 在 64 ä½æ¨¡å¼ä¸‹è¢«å¿½ç•¥"
#: config/i386/i386.c:3780
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%sregparm=%d%s is not between 0 and %d"
msgid "-mregparm=%d is not between 0 and %d"
msgstr "%sregparm=%d%s ä¸åœ¨ 0 å’Œ %d 之间"
@@ -24270,13 +23564,11 @@ msgstr "%srtd%s 在 64 ä½æ¨¡å¼ä¸‹è¢«å¿½ç•¥"
#: config/i386/i386.c:3900
#, fuzzy, gcc-internal-format
-#| msgid "%spreferred-stack-boundary%s is not supported for this target"
msgid "-mpreferred-stack-boundary is not supported for this target"
msgstr "%spreferred-stack-boundary%s 在此目标机上ä¸è¢«æ”¯æŒ"
#: config/i386/i386.c:3903
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%spreferred-stack-boundary=%d%s is not between %d and %d"
msgid "-mpreferred-stack-boundary=%d is not between %d and %d"
msgstr "%spreferred-stack-boundary=%d%s ä¸åœ¨ %d å’Œ %d 之间"
@@ -24308,7 +23600,7 @@ msgstr "堆栈探针目å‰éœ€è¦æ¡†æž¶æŒ‡é’ˆæˆ– %saccumulate-outgoing-args%s æ¥
#: config/i386/i386.c:4108
#, gcc-internal-format
msgid "-mfentry isn%'t supported for 32-bit in combination with -fpic"
-msgstr "-mfentry 在 32 ä½ä¸‹ä¸èƒ½å’Œ -pic åŒæ—¶ä½¿ç”¨"
+msgstr "-mfentry 在 32 ä½ä¸‹ä¸èƒ½å’Œ -fpic åŒæ—¶ä½¿ç”¨"
#: config/i386/i386.c:4115
#, gcc-internal-format
@@ -24422,7 +23714,6 @@ msgstr "没有å¯ç”¨ AVX,å´å‡ºçŽ°äº† AVX å‘é‡å®žå‚,这改å˜äº† ABI"
#: config/i386/i386.c:6236
#, fuzzy, gcc-internal-format
-#| msgid "AVX vector argument without AVX enabled changes the ABI"
msgid "AVX vector return without AVX enabled changes the ABI"
msgstr "没有å¯ç”¨ AVX,å´å‡ºçŽ°äº† AVX å‘é‡å®žå‚,这改å˜äº† ABI"
@@ -24515,7 +23806,6 @@ msgstr "扩展的寄存器ä¸æ”¯æŒçš„æ“作数大å°"
#: config/i386/i386.c:14881
#, fuzzy, gcc-internal-format
-#| msgid "non-integer operand used with operand code '%c'"
msgid "non-integer operand used with operand code 'z'"
msgstr "éžæ•´æ•°æ“作数使用了æ“作数代ç â€˜%c’"
@@ -24541,7 +23831,6 @@ msgstr ""
#: config/i386/i386.c:31750 config/i386/i386.c:32198
#, fuzzy, gcc-internal-format
-#| msgid "static linking is not supported"
msgid "Virtual function multiversioning not supported"
msgstr "ä¸æ”¯æŒé™æ€é“¾æŽ¥"
@@ -24552,25 +23841,21 @@ msgstr ""
#: config/i386/i386.c:31818
#, fuzzy, gcc-internal-format
-#| msgid "previous declaration of %q+D"
msgid "previous declaration of %D"
msgstr "%q+Dçš„å‰ä¸€ä¸ªå£°æ˜Ž"
#: config/i386/i386.c:32037
#, fuzzy, gcc-internal-format
-#| msgid "nested functions not supported on this target"
msgid "multiversioning needs ifunc which is not supported on this target"
msgstr "嵌套函数在此目标机上ä¸å—支æŒ"
#: config/i386/i386.c:32405
#, fuzzy, gcc-internal-format
-#| msgid "argument to %qs must be a 2-bit unsigned literal"
msgid "Parameter to builtin must be a string constant or literal"
msgstr "%qs的实å‚必须是一个 2 ä½æ— ç¬¦å·å­—é¢å¸¸é‡"
#: config/i386/i386.c:32430 config/i386/i386.c:32480
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Argument to -ffpe-trap is not valid: %s"
msgid "Parameter to builtin not valid: %s"
msgstr "-ffpe-trap çš„å‚数无效:%s"
@@ -24581,25 +23866,21 @@ msgstr "最åŽä¸€ä¸ªå®žå‚必须是一个 2 ä½ç«‹å³æ•°"
#: config/i386/i386.c:33287
#, fuzzy, gcc-internal-format
-#| msgid "the fifth argument must be a 8-bit immediate"
msgid "the fifth argument must be an 8-bit immediate"
msgstr "第五个实å‚必须是一个 8 ä½ç«‹å³æ•°"
#: config/i386/i386.c:33382
#, fuzzy, gcc-internal-format
-#| msgid "the third argument must be a 8-bit immediate"
msgid "the third argument must be an 8-bit immediate"
msgstr "第三个实å‚必须是一个 8 ä½ç«‹å³æ•°"
#: config/i386/i386.c:33967
#, fuzzy, gcc-internal-format
-#| msgid "the last argument must be a 1-bit immediate"
msgid "the last argument must be an 1-bit immediate"
msgstr "最åŽä¸€ä¸ªå®žå‚必须是一个 1 ä½ç«‹å³æ•°"
#: config/i386/i386.c:33974
#, fuzzy, gcc-internal-format
-#| msgid "the last argument must be a 32-bit immediate"
msgid "the last argument must be a 3-bit immediate"
msgstr "最åŽä¸€ä¸ªå‚数必须是一个 32 ä½ç«‹å³æ•°"
@@ -24630,37 +23911,31 @@ msgstr "最åŽä¸€ä¸ªå®žå‚必须是一个 8 ä½ç«‹å³æ•°"
#: config/i386/i386.c:34214
#, fuzzy, gcc-internal-format
-#| msgid "argument must be a constant"
msgid "the third argument must be comparison constant"
msgstr "实å‚必须是常数"
#: config/i386/i386.c:34219
#, fuzzy, gcc-internal-format
-#| msgid "incorrect sharing of tree nodes"
msgid "incorect comparison mode"
msgstr "对树结节的共享ä¸æ­£ç¡®"
#: config/i386/i386.c:34225 config/i386/i386.c:34421
#, fuzzy, gcc-internal-format
-#| msgid "incorrect sharing of tree nodes"
msgid "incorrect rounding operand"
msgstr "对树结节的共享ä¸æ­£ç¡®"
#: config/i386/i386.c:34403
#, fuzzy, gcc-internal-format
-#| msgid "the last argument must be a 4-bit immediate"
msgid "the immediate argument must be a 4-bit immediate"
msgstr "最åŽä¸€ä¸ªå®žå‚必须是一个 4 ä½ç«‹å³æ•°"
#: config/i386/i386.c:34409
#, fuzzy, gcc-internal-format
-#| msgid "the last argument must be a 5-bit immediate"
msgid "the immediate argument must be a 5-bit immediate"
msgstr "最åŽä¸€ä¸ªå®žå‚必须是一个 5 ä½ç«‹å³æ•°"
#: config/i386/i386.c:34412
#, fuzzy, gcc-internal-format
-#| msgid "the last argument must be an 8-bit immediate"
msgid "the immediate argument must be an 8-bit immediate"
msgstr "最åŽä¸€ä¸ªå®žå‚必须是一个 8 ä½ç«‹å³æ•°"
@@ -24691,25 +23966,21 @@ msgstr "最åŽä¸€ä¸ªå®žå‚必须是一个立å³æ•°"
#: config/i386/i386.c:35816 config/i386/i386.c:35964
#, fuzzy, gcc-internal-format
-#| msgid "the last argument must be a 4-bit immediate"
msgid "the last argument must be scale 1, 2, 4, 8"
msgstr "最åŽä¸€ä¸ªå®žå‚必须是一个 4 ä½ç«‹å³æ•°"
#: config/i386/i386.c:36016
#, fuzzy, gcc-internal-format
-#| msgid "left argument must be a slice"
msgid "the forth argument must be scale 1, 2, 4, 8"
msgstr "左实å‚必须是一个切片"
#: config/i386/i386.c:36022
#, fuzzy, gcc-internal-format
-#| msgid "the last argument must be a 4-bit immediate"
msgid "the last argument must be hint 0 or 1"
msgstr "最åŽä¸€ä¸ªå®žå‚必须是一个 4 ä½ç«‹å³æ•°"
#: config/i386/i386.c:36041
#, fuzzy, gcc-internal-format
-#| msgid "the last argument must be an 8-bit immediate"
msgid "the xabort's argument must be an 8-bit immediate"
msgstr "最åŽä¸€ä¸ªå®žå‚必须是一个 8 ä½ç«‹å³æ•°"
@@ -24735,7 +24006,6 @@ msgstr "%qEä¸å…¼å®¹çš„属性已被忽略"
#: config/i386/i386.c:46439
#, fuzzy, gcc-internal-format
-#| msgid "Unknown architecture '%s'"
msgid "Unknown architecture specific memory model"
msgstr "未知的架构‘%s’"
@@ -24751,7 +24021,6 @@ msgstr ""
#: config/i386/i386.c:46476
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "unsupported ELF file class"
msgid "unsupported simdlen %d"
msgstr "ä¸æ”¯æŒçš„ ELF 文件类"
@@ -24955,7 +24224,6 @@ msgstr "ä¸æ”¯æŒ -falign-loops=%d"
#: config/m68k/m68k.c:624
#, fuzzy, gcc-internal-format
-#| msgid "stack limits not supported on this target"
msgid "-fstack-limit- options are not supported on this cpu"
msgstr "堆栈é™åˆ¶åœ¨æ­¤ç›®æ ‡æœºä¸Šä¸å—支æŒ"
@@ -25240,7 +24508,6 @@ msgstr "éžé¢„期的 %d 字节 cop 指令"
#: config/microblaze/microblaze.c:1679
#, fuzzy, gcc-internal-format
-#| msgid "-fPIC and -fpic are not supported for this target"
msgid "-fPIC/-fpic not supported for this target"
msgstr "-fPIC å’Œ -fpic ä¸è¢«æ­¤ç›®æ ‡æ‰€æ”¯æŒ"
@@ -25276,7 +24543,6 @@ msgstr "%qs属性åªèƒ½åº”用于函数"
#: config/mips/mips.c:1427 config/mips/mips.c:1433
#, fuzzy, gcc-internal-format
-#| msgid "%qE cannot have both %<mips16%> and %<nomips16%> attributes"
msgid "%qE cannot have both %qs and %qs attributes"
msgstr "%qEä¸èƒ½åŒæ—¶æœ‰%<mips16%>å’Œ%<nomips16%>属性"
@@ -25385,7 +24651,6 @@ msgstr "%<-mgp32%>å’Œ%<-mfp64%>åªæœ‰å½“使用 o32 ABI æ—¶æ‰èƒ½ä¸€èµ·ä½¿ç”¨"
#: config/mips/mips.c:17050 config/mips/mips.c:17052 config/mips/mips.c:17065
#, fuzzy, gcc-internal-format
-#| msgid "assert: %s is assign compatible with %s"
msgid "%qs is incompatible with %qs"
msgstr "assert:%s 与 %s 赋值兼容"
@@ -25396,7 +24661,6 @@ msgstr "assert:%s 与 %s 赋值兼容"
#. an error.
#: config/mips/mips.c:17059
#, fuzzy, gcc-internal-format
-#| msgid "assert: %s is assign compatible with %s"
msgid "the combination of %qs and %qs is incompatible with %qs"
msgstr "assert:%s 与 %s 赋值兼容"
@@ -25407,13 +24671,11 @@ msgstr "%qs架构ä¸æ”¯æŒ Branch-Likely 指令"
#: config/mips/mips.c:17120
#, fuzzy, gcc-internal-format
-#| msgid "the %qs architecture does not support the synci instruction"
msgid "the %qs architecture does not support madd or msub instructions"
msgstr "%qs架构ä¸æ”¯æŒ synci 指令"
#: config/mips/mips.c:17134
#, fuzzy, gcc-internal-format
-#| msgid "Generate position-independent code if possible (large mode)"
msgid "cannot generate position-independent code for %qs"
msgstr "å°½å¯èƒ½ç”Ÿæˆä¸Žä½ç½®æ— å…³çš„代ç (大模å¼)"
@@ -25530,19 +24792,16 @@ msgstr ""
#: config/msp430/msp430.c:1102
#, fuzzy, gcc-internal-format
-#| msgid "invalid argument of %qE attribute"
msgid "unrecognised interrupt vector argument of %qE attribute"
msgstr "属性%qEçš„å‚数无效"
#: config/msp430/msp430.c:1111
#, fuzzy, gcc-internal-format
-#| msgid "argument %d of %qE must be in the range %d...%d"
msgid "numeric argument of %qE attribute must be in range 0..63"
msgstr "%2$qE的第 %1$d 个å‚数必须是在 %3$d å’Œ %4$d 之间"
#: config/msp430/msp430.c:1117
#, fuzzy, gcc-internal-format
-#| msgid "argument of %qE attribute is not a string constant"
msgid "argument of %qE attribute is not a string constant or number"
msgstr "%qE属性的实å‚ä¸æ˜¯ä¸€ä¸ªå­—符串常é‡"
@@ -25564,13 +24823,11 @@ msgstr "给予函数的实å‚太少"
#: config/nds32/nds32.c:1213
#, fuzzy, gcc-internal-format
-#| msgid "multiple function type attributes specified"
msgid "multiple nested types attributes to function %qD"
msgstr "指定了多个函数类型属性"
#: config/nds32/nds32.c:1225
#, fuzzy, gcc-internal-format
-#| msgid "multiple interrupt attributes not allowed"
msgid "multiple interrupt attributes to function %qD"
msgstr "ä¸å…许多个中断属性"
@@ -25581,44 +24838,37 @@ msgstr "ä¸å…许多个中断属性"
#: config/nds32/nds32.c:3007 config/nds32/nds32.c:3013
#: config/nds32/nds32.c:3045
#, fuzzy, gcc-internal-format
-#| msgid "nested functions not supported on this target"
msgid "a nested function is not supported for reduced registers"
msgstr "嵌套函数在此目标机上ä¸å—支æŒ"
#. The enum index value for array size is out of range.
#: config/nds32/nds32.c:2848
#, fuzzy, gcc-internal-format
-#| msgid "invalid register in the instruction"
msgid "intrinsic register index is out of range"
msgstr "此指令中寄存器无效"
#: config/nds32/nds32.c:3153
#, fuzzy, gcc-internal-format
-#| msgid "invalid type for iteration variable %qE"
msgid "invalid id value for interrupt/exception attribute"
msgstr "迭代å˜é‡%qE类型无效"
#: config/nds32/nds32.c:3181
#, fuzzy, gcc-internal-format
-#| msgid "invalid argument of %qs attribute"
msgid "invalid id value for reset attribute"
msgstr "属性%qsçš„å‚数无效"
#: config/nds32/nds32.c:3197
#, fuzzy, gcc-internal-format
-#| msgid "invalid argument of %qs attribute"
msgid "invalid nmi function for reset attribute"
msgstr "属性%qsçš„å‚数无效"
#: config/nds32/nds32.c:3210
#, fuzzy, gcc-internal-format
-#| msgid "invalid argument of %qs attribute"
msgid "invalid warm function for reset attribute"
msgstr "属性%qsçš„å‚数无效"
#: config/nds32/nds32.c:3284
#, fuzzy, gcc-internal-format
-#| msgid "%s does not support split_block"
msgid "not support -fpic"
msgstr "%s ä¸æ”¯æŒ split_block"
@@ -25629,7 +24879,6 @@ msgstr ""
#: config/nios2/nios2.c:794
#, fuzzy, gcc-internal-format
-#| msgid "target attribute or pragma changes double precision floating point"
msgid "switch %<-mcustom-%s%> is required for double precision floating point"
msgstr "目标属性或 pragma 改å˜äº†åŒç²¾åº¦æµ®ç‚¹æ•°"
@@ -25675,7 +24924,6 @@ msgstr ""
#: config/nios2/nios2.c:2598
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "invalid argument to built-in function"
msgid "invalid argument to built-in function %s"
msgstr "内建函数实å‚无效"
@@ -25686,7 +24934,6 @@ msgstr ""
#: config/nios2/nios2.c:2743
#, fuzzy, gcc-internal-format
-#| msgid "switch -mcpu=%s conflicts with -march=%s switch"
msgid "switch %<-mcustom-%s%> conflicts with switch %<-mcustom-%s%>"
msgstr "开关 -mcpu=%s 与 -march=%s 冲çª"
@@ -25707,7 +24954,6 @@ msgstr ""
#: config/nios2/nios2.c:2899
#, fuzzy, gcc-internal-format
-#| msgid "%s only accepts 2 arguments"
msgid "%<no-custom-%s%> does not accept arguments"
msgstr "%s åªæŽ¥å— 2 个å‚æ•°"
@@ -25728,7 +24974,6 @@ msgstr ""
#: config/nios2/nios2.c:2943
#, fuzzy, gcc-internal-format
-#| msgid "type of %qE is unknown"
msgid "%<%s%> is unknown"
msgstr "%qE的类型未知"
@@ -25979,13 +25224,11 @@ msgstr "-malign-power 在 64 ä½ Darwin 下ä¸å—支æŒï¼›å®ƒä¸Žå·²å®‰è£…çš„ C å
#: config/rs6000/rs6000.c:3173
#, fuzzy, gcc-internal-format
-#| msgid "not configured for ABI: '%s'"
msgid "not configured for SPE ABI"
msgstr "没有为此 ABI é…置:‘%s’"
#: config/rs6000/rs6000.c:3178
#, fuzzy, gcc-internal-format
-#| msgid "Do not use PowerPC instruction set"
msgid "not configured for SPE instruction set"
msgstr "ä¸ä½¿ç”¨ PowerPC 指令集"
@@ -26021,7 +25264,6 @@ msgstr ""
#: config/rs6000/rs6000.c:3333
#, fuzzy, gcc-internal-format
-#| msgid "--resource requires -o"
msgid "-mdirect-move requires -mvsx"
msgstr "--resource éœ€è¦ -o"
@@ -26032,13 +25274,11 @@ msgstr ""
#: config/rs6000/rs6000.c:3347
#, fuzzy, gcc-internal-format
-#| msgid "--resource requires -o"
msgid "-mpower8-vector requires -mvsx"
msgstr "--resource éœ€è¦ -o"
#: config/rs6000/rs6000.c:3354
#, fuzzy, gcc-internal-format
-#| msgid "--resource requires -o"
msgid "-mvsx-timode requires -mvsx"
msgstr "--resource éœ€è¦ -o"
@@ -26099,7 +25339,6 @@ msgstr "内部错误:对 %s 的内建函数已ç»å¤„ç†è¿‡ã€‚"
#: config/rs6000/rs6000.c:11517
#, fuzzy, gcc-internal-format
-#| msgid "argument 1 must be a 5-bit signed literal"
msgid "argument 1 must be an 8-bit field value"
msgstr "å®žå‚ 1 必须是一个 5 ä½æœ‰ç¬¦å·å­—é¢å€¼"
@@ -26125,13 +25364,11 @@ msgstr "__builtin_altivec_predicate 的第 1 个实å‚越界"
#: config/rs6000/rs6000.c:12074
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "argument 2 must be a 5-bit unsigned literal"
msgid "argument %d must be an unsigned literal"
msgstr "å®žå‚ 2 必须是一个 5 ä½æ— ç¬¦å·å­—é¢å€¼"
#: config/rs6000/rs6000.c:12076
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "argument 1 of __builtin_spe_predicate is out of range"
msgid "argument %d is an unsigned literal that is out of range"
msgstr "__builtin_spe_predicate 的第 1 个实å‚越界"
@@ -26152,13 +25389,11 @@ msgstr "å®žå‚ 2 必须是一个 1 ä½æ— ç¬¦å·å­—é¢å€¼"
#: config/rs6000/rs6000.c:12246
#, fuzzy, gcc-internal-format
-#| msgid "number must be 0 or 1"
msgid "argument 2 must be 0 or 1"
msgstr "数字必须是 0 或 1"
#: config/rs6000/rs6000.c:12254
#, fuzzy, gcc-internal-format
-#| msgid "argument %d of %qE must be in the range %d...%d"
msgid "argument 3 must be in the range 0..15"
msgstr "%2$qE的第 %1$d 个å‚数必须是在 %3$d å’Œ %4$d 之间"
@@ -26199,7 +25434,6 @@ msgstr "__builtin_spe_predicate 的第 1 个实å‚越界"
#: config/rs6000/rs6000.c:13239
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "this builtin function is only available on the fr450"
msgid "Builtin function %s is only valid for the cell processor"
msgstr "此内建函数åªåœ¨ fr450 上å¯ç”¨"
@@ -26464,19 +25698,16 @@ msgstr "-fdirectives-only 与 -traditional ä¸å…¼å®¹"
#: config/rs6000/e500.h:37
#, fuzzy, gcc-internal-format
-#| msgid "AltiVec and E500 instructions cannot coexist"
msgid "AltiVec and SPE instructions cannot coexist"
msgstr "AltiVec å’Œ E500 指令ä¸èƒ½å…±å­˜"
#: config/rs6000/e500.h:39
#, fuzzy, gcc-internal-format
-#| msgid "VSX and E500 instructions cannot coexist"
msgid "VSX and SPE instructions cannot coexist"
msgstr "VSX å’Œ E500 指令ä¸èƒ½å…±å­˜"
#: config/rs6000/e500.h:41
#, fuzzy, gcc-internal-format
-#| msgid "64-bit E500 not supported"
msgid "64-bit SPE not supported"
msgstr "ä¸æ”¯æŒ 64 ä½ E500"
@@ -26492,7 +25723,6 @@ msgstr "-m64 éœ€è¦ PowerPC64 CPU"
#: config/rs6000/linux64.h:116
#, fuzzy, gcc-internal-format
-#| msgid "-mas100-syntax is incompatible with -gdwarf"
msgid "-mcall-aixdesc incompatible with -mabi=elfv2"
msgstr "-mas100-syntax 与 -gdwarf ä¸å…¼å®¹"
@@ -26550,13 +25780,11 @@ msgstr "-m%s 在此é…置下ä¸å—支æŒ"
#: config/rx/rx.c:644
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "unreocgnized control register number: %d - using 'psw'"
msgid "unrecognized control register number: %d - using 'psw'"
msgstr "无法识别的控制寄存器å·ï¼š%d - 使用‘psw’"
#: config/rx/rx.c:1380
#, fuzzy, gcc-internal-format
-#| msgid "multiple interrupt attributes not allowed"
msgid "multiple fast interrupt routines seen: %qE and %qE"
msgstr "ä¸å…许多个中断属性"
@@ -26577,13 +25805,11 @@ msgstr "RX FPU 指令ä¸æ”¯æŒ NaN 和无é™"
#: config/s390/s390.c:479
#, fuzzy, gcc-internal-format
-#| msgid "argument of %qE attribute is not a string constant"
msgid "requested %qE attribute is not a non-negative integer constant or too large (max. %d)"
msgstr "%qE属性的实å‚ä¸æ˜¯ä¸€ä¸ªå­—符串常é‡"
#: config/s390/s390.c:1712
#, fuzzy, gcc-internal-format
-#| msgid "argument to %qE attribute larger than %d"
msgid "argument to %qs is too large (max. %d)"
msgstr "%qE属性的实å‚大于 %d"
@@ -26634,13 +25860,11 @@ msgstr "-mstack-guard æ„味ç€ä½¿ç”¨ -mstack-size"
#: config/s390/s390.c:5480
#, fuzzy, gcc-internal-format
-#| msgid "function %q+D redeclared with attribute noinline"
msgid "function %qE with the %qs attribute is not hotpatchable"
msgstr "函数%q+Dé‡å£°æ˜Žä¸ºå¸¦æœ‰ä¸å¯å†…è”属性"
#: config/s390/s390.c:5521
#, fuzzy, gcc-internal-format
-#| msgid "ms_hook_prologue is not compatible with nested function"
msgid "hotpatch_prologue is not compatible with nested function"
msgstr "ms_hook_prologue 与嵌套函数ä¸å…¼å®¹"
@@ -26661,7 +25885,6 @@ msgstr ""
#: config/s390/s390.c:9019
#, fuzzy, gcc-internal-format
-#| msgid "frame size of %qs is "
msgid "frame size of %qs is %wd bytes"
msgstr "%qs的框架大å°æ˜¯"
@@ -26770,7 +25993,6 @@ msgstr "32 ä½ç³»ç»Ÿä¸æ”¯æŒ -mcmodel="
#: config/sparc/sparc.c:1298
#, fuzzy, gcc-internal-format
-#| msgid "-fdata-sections not supported for this target"
msgid "-fcall-saved-REG is not supported for out registers"
msgstr "-fdata-sections 在此目标机上ä¸å—支æŒ"
@@ -26856,13 +26078,11 @@ msgstr "__BELOW100__ 属性ä¸å…许用于自动存储类"
#: config/tilegx/tilegx.c:3512 config/tilepro/tilepro.c:3118
#, fuzzy, gcc-internal-format
-#| msgid "bad builtin code"
msgid "bad builtin icode"
msgstr "错误的内建代ç "
#: config/tilegx/tilegx.c:3553 config/tilepro/tilepro.c:3144
#, fuzzy, gcc-internal-format
-#| msgid "mask must be an immediate"
msgid "operand must be an immediate of the right size"
msgstr "掩ç å¿…须是一个立å³æ•°"
@@ -26983,19 +26203,16 @@ msgstr "è¦å‡†å¤‡å¤ªå¤šçš„堆栈空间:%d"
#: config/vms/vms-c.c:44
#, fuzzy, gcc-internal-format
-#| msgid "junk at end of #pragma ghs starttda"
msgid "junk at end of #pragma __nostandard"
msgstr "#pragma ghs starttda 末尾有垃圾字符"
#: config/vms/vms-c.c:55
#, fuzzy, gcc-internal-format
-#| msgid "junk at end of #pragma %s"
msgid "junk at end of #pragma __standard"
msgstr "#pragma %s 末尾有垃圾字符"
#: config/vms/vms-c.c:80
#, fuzzy, gcc-internal-format
-#| msgid "malformed %<#pragma align%>, ignoring"
msgid "malformed '#pragma member_alignment', ignoring"
msgstr "%<#pragma align%>æ ¼å¼é”™è¯¯ - 已忽略"
@@ -27006,25 +26223,21 @@ msgstr ""
#: config/vms/vms-c.c:100
#, fuzzy, gcc-internal-format
-#| msgid "malformed %<#pragma align%>"
msgid "malformed '#pragma member_alignment'"
msgstr "%<#pragma align%>æ ¼å¼é”™è¯¯"
#: config/vms/vms-c.c:134
#, fuzzy, gcc-internal-format
-#| msgid "invalid alignment for %<#pragma align%>, ignoring"
msgid "unhandled alignment for '#pragma nomember_alignment'"
msgstr "%<#pragma align%>指定的对é½è¾¹ç•Œæ— æ•ˆï¼Œå¿½ç•¥"
#: config/vms/vms-c.c:147
#, fuzzy, gcc-internal-format
-#| msgid "junk at end of '#pragma options'"
msgid "garbage at end of '#pragma nomember_alignment'"
msgstr "‘#pragma options’末尾有垃圾字符"
#: config/vms/vms-c.c:202
#, fuzzy, gcc-internal-format
-#| msgid "malformed '#pragma options', ignoring"
msgid "malformed '#pragma extern_model', ignoring"
msgstr "‘#pragma options’格å¼é”™è¯¯ - 已忽略"
@@ -27040,31 +26253,26 @@ msgstr ""
#: config/vms/vms-c.c:234
#, fuzzy, gcc-internal-format
-#| msgid "junk at end of %<#pragma extern_prefix%>"
msgid "junk at end of '#pragma extern_model'"
msgstr "%<#pragma extern_prefix%>末尾有垃圾字符"
#: config/vms/vms-c.c:248
#, fuzzy, gcc-internal-format
-#| msgid "malformed %<#pragma message%>, ignored"
msgid "vms '#pragma __message' is ignored"
msgstr "%<#pragma message%>æ ¼å¼é”™è¯¯ï¼Œå·²å¿½ç•¥"
#: config/vms/vms-c.c:273 config/vms/vms-c.c:279
#, fuzzy, gcc-internal-format
-#| msgid "malformed #pragma extern_prefix, ignored"
msgid "malformed '#pragma __extern_prefix', ignoring"
msgstr "#pragma extern_prefix æ ¼å¼é”™è¯¯ï¼Œå·²å¿½ç•¥"
#: config/vms/vms-c.c:312 config/vms/vms-c.c:332
#, fuzzy, gcc-internal-format
-#| msgid "malformed %<#pragma %s%>, ignored"
msgid "malformed %<#pragma %s%>, ignoring"
msgstr "%<#pragma %s%>æ ¼å¼é”™è¯¯ï¼Œå·²å¿½ç•¥"
#: config/vms/vms-c.c:328
#, fuzzy, gcc-internal-format
-#| msgid "invalid constant in %<#pragma pack%> - ignored"
msgid "invalid constant in %<#pragma %s%>"
msgstr "%<#pragma pack%>ä¸­æœ‰æ— æ•ˆå¸¸é‡ - 已忽略"
@@ -27146,31 +26354,26 @@ msgstr ""
#: c/c-array-notation.c:708 c/c-array-notation.c:714
#, fuzzy, gcc-internal-format
-#| msgid "%qD cannot be declared as constexpr"
msgid "%qE cannot be scalar when %qE is not"
msgstr "%qDä¸èƒ½è¢«å£°æ˜Žä¸ºå¹¿ä¹‰å¸¸è¡¨è¾¾å¼"
#: c/c-array-notation.c:776 cp/cp-array-notation.c:658
#, fuzzy, gcc-internal-format
-#| msgid "type mismatch between an SSA_NAME and its symbol"
msgid "length mismatch between LHS and RHS"
msgstr "SSA_NAME 和其符å·é—´ç±»åž‹ä¸åŒ¹é…"
#: c/c-array-notation.c:1323 cp/cp-array-notation.c:1407
#, fuzzy, gcc-internal-format
-#| msgid "array subscript is not an integer"
msgid "start-index of array notation triplet is not an integer"
msgstr "数组下标ä¸æ˜¯ä¸€ä¸ªæ•´æ•°"
#: c/c-array-notation.c:1328 cp/cp-array-notation.c:1412
#, fuzzy, gcc-internal-format
-#| msgid "array subscript is not an integer"
msgid "length of array notation triplet is not an integer"
msgstr "数组下标ä¸æ˜¯ä¸€ä¸ªæ•´æ•°"
#: c/c-array-notation.c:1335 cp/cp-array-notation.c:1417
#, fuzzy, gcc-internal-format
-#| msgid "array subscript is not an integer"
msgid "stride of array notation triplet is not an integer"
msgstr "数组下标ä¸æ˜¯ä¸€ä¸ªæ•´æ•°"
@@ -27593,7 +26796,6 @@ msgstr "带有类型é™å®šçš„空声明没有é‡å£°æ˜Žæ ‡è®°"
#: c/c-decl.c:3755
#, fuzzy, gcc-internal-format
-#| msgid "empty declaration with type qualifier does not redeclare tag"
msgid "empty declaration with %<_Alignas%> does not redeclare tag"
msgstr "带有类型é™å®šçš„空声明没有é‡å£°æ˜Žæ ‡è®°"
@@ -27609,7 +26811,6 @@ msgstr "%<inline%>用于空声明中"
#: c/c-decl.c:3799
#, fuzzy, gcc-internal-format
-#| msgid "%<inline%> in empty declaration"
msgid "%<_Noreturn%> in empty declaration"
msgstr "%<inline%>用于空声明中"
@@ -27630,7 +26831,6 @@ msgstr "空声明中指定存储类无用"
#: c/c-decl.c:3824
#, fuzzy, gcc-internal-format
-#| msgid "useless type name in empty declaration"
msgid "useless %qs in empty declaration"
msgstr "空声明中类型å无用"
@@ -27641,7 +26841,6 @@ msgstr "空声明中类型é™å®šæ— ç”¨"
#: c/c-decl.c:3844
#, fuzzy, gcc-internal-format
-#| msgid "useless %<__thread%> in empty declaration"
msgid "useless %<_Alignas%> in empty declaration"
msgstr "空声明中%<__thread%>无用"
@@ -27890,7 +27089,6 @@ msgstr "é‡å¤çš„%<volatile%>"
#: c/c-decl.c:5147
#, fuzzy, gcc-internal-format
-#| msgid "duplicate %<restrict%>"
msgid "duplicate %<_Atomic%>"
msgstr "é‡å¤çš„%<restrict%>"
@@ -27921,7 +27119,6 @@ msgstr "函数声明定义为%<typedef%>"
#: c/c-decl.c:5190
#, fuzzy, gcc-internal-format
-#| msgid "function definition declared %<auto%>"
msgid "function definition declared %qs"
msgstr "函数声明定义为%<auto%>"
@@ -27977,7 +27174,6 @@ msgstr "嵌套函数%qE被声明为%<extern%>"
#: c/c-decl.c:5259
#, fuzzy, gcc-internal-format
-#| msgid "function-scope %qE implicitly auto and declared %<__thread%>"
msgid "function-scope %qE implicitly auto and declared %qs"
msgstr "函数作用域的%qEéšå¼ä¸º auto,å´è¢«å£°æ˜Žä¸º%<__thread%>"
@@ -28103,7 +27299,6 @@ msgstr "忽略函数返回类型的类型é™å®š"
#: c/c-decl.c:5754 c/c-decl.c:5952 c/c-decl.c:6005 c/c-decl.c:6078
#: c/c-decl.c:6179 c/c-parser.c:2401
#, fuzzy, gcc-internal-format
-#| msgid "ISO C forbids qualified function types"
msgid "%<_Atomic%>-qualified function type"
msgstr "ISO C ä¸å…许使用 const 或 volatile é™å®šå‡½æ•°ç±»åž‹"
@@ -28149,55 +27344,46 @@ msgstr "为结构字段指定了%qs"
#: c/c-decl.c:5880
#, fuzzy, gcc-internal-format
-#| msgid "bit-field %qs has invalid type"
msgid "bit-field %qE has atomic type"
msgstr "ä½æ®µ%qs类型无效"
#: c/c-decl.c:5882
#, fuzzy, gcc-internal-format
-#| msgid "bit-field %qs has invalid type"
msgid "bit-field has atomic type"
msgstr "ä½æ®µ%qs类型无效"
#: c/c-decl.c:5891
#, fuzzy, gcc-internal-format
-#| msgid "alignment may not be specified for %q+D"
msgid "alignment specified for typedef %qE"
msgstr "ä¸èƒ½ä¸º%q+D指定对é½"
#: c/c-decl.c:5893
#, fuzzy, gcc-internal-format
-#| msgid "%qs specified for parameter %qE"
msgid "alignment specified for %<register%> object %qE"
msgstr "为形å‚%2$qE指定了%1$qs"
#: c/c-decl.c:5898
#, fuzzy, gcc-internal-format
-#| msgid "%qs specified for parameter %qE"
msgid "alignment specified for parameter %qE"
msgstr "为形å‚%2$qE指定了%1$qs"
#: c/c-decl.c:5900
#, fuzzy, gcc-internal-format
-#| msgid "%qs specified for unnamed parameter"
msgid "alignment specified for unnamed parameter"
msgstr "为无åå½¢å‚指定了%qs"
#: c/c-decl.c:5905
#, fuzzy, gcc-internal-format
-#| msgid "alignment may not be specified for %q+D"
msgid "alignment specified for bit-field %qE"
msgstr "ä¸èƒ½ä¸º%q+D指定对é½"
#: c/c-decl.c:5907
#, fuzzy, gcc-internal-format
-#| msgid "%qs specified for unnamed parameter"
msgid "alignment specified for unnamed bit-field"
msgstr "为无åå½¢å‚指定了%qs"
#: c/c-decl.c:5910
#, fuzzy, gcc-internal-format
-#| msgid "assignment of function %qD"
msgid "alignment specified for function %qE"
msgstr "å‘函数%qD赋值"
@@ -28218,7 +27404,6 @@ msgstr "typedef%q+D声明为%<inline%>"
#: c/c-decl.c:5968
#, fuzzy, gcc-internal-format
-#| msgid "typedef %q+D declared %<inline%>"
msgid "typedef %q+D declared %<_Noreturn%>"
msgstr "typedef%q+D声明为%<inline%>"
@@ -28250,7 +27435,6 @@ msgstr "å½¢å‚%q+D声明为%<inline%>"
#: c/c-decl.c:6111
#, fuzzy, gcc-internal-format
-#| msgid "parameter %q+D declared %<inline%>"
msgid "parameter %q+D declared %<_Noreturn%>"
msgstr "å½¢å‚%q+D声明为%<inline%>"
@@ -28281,19 +27465,16 @@ msgstr "ä¸èƒ½å†…è”%<main%>函数"
#: c/c-decl.c:6223
#, fuzzy, gcc-internal-format
-#| msgid "%qE initialized and declared %<extern%>"
msgid "%<main%> declared %<_Noreturn%>"
msgstr "%qEå·²åˆå§‹åŒ–,å´åˆè¢«å£°æ˜Žä¸º%<extern%>"
#: c/c-decl.c:6236
#, fuzzy, gcc-internal-format
-#| msgid "ISO C99 does not support %<_Static_assert%>"
msgid "ISO C99 does not support %<_Noreturn%>"
msgstr "ISO C90 ä¸æ”¯æŒ%<_Static_assert%>"
#: c/c-decl.c:6239
#, fuzzy, gcc-internal-format
-#| msgid "ISO C90 does not support %<long long%>"
msgid "ISO C90 does not support %<_Noreturn%>"
msgstr "ISO C90 ä¸æ”¯æŒ%<long long%>"
@@ -28309,7 +27490,6 @@ msgstr "å˜é‡%q+D声明为%<inline%>"
#: c/c-decl.c:6280
#, fuzzy, gcc-internal-format
-#| msgid "variable %q+D declared %<inline%>"
msgid "variable %q+D declared %<_Noreturn%>"
msgstr "å˜é‡%q+D声明为%<inline%>"
@@ -28482,7 +27662,6 @@ msgstr "å¯å˜æ•°ç»„是结构中的唯一æˆå‘˜"
#: c/c-decl.c:7352 cp/class.c:6386
#, fuzzy, gcc-internal-format
-#| msgid "size of array %qE is too large"
msgid "type %qT is too large"
msgstr "数组%qE太大"
@@ -28682,13 +27861,11 @@ msgstr "å½¢å‚%qD被设定但未被使用"
#. allow it.
#: c/c-decl.c:8697
#, fuzzy, gcc-internal-format
-#| msgid "%<for%> loop initial declarations are only allowed in C99 mode"
msgid "%<for%> loop initial declarations are only allowed in C99 or C11 mode"
msgstr "åªå…许在 C99 模å¼ä¸‹ä½¿ç”¨%<for%>循环åˆå§‹åŒ–声明"
#: c/c-decl.c:8702
#, fuzzy, gcc-internal-format
-#| msgid "use option -std=c99 or -std=gnu99 to compile your code"
msgid "use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile your code"
msgstr "使用 -std=c99 或 -std=gnu99 æ¥ç¼–译您的代ç "
@@ -28799,31 +27976,26 @@ msgstr "%qE没有出现在声明的开头"
#: c/c-decl.c:9862
#, fuzzy, gcc-internal-format
-#| msgid "%<__thread%> used with %<auto%>"
msgid "%qE used with %<auto%>"
msgstr "%<__thread%>与%<auto%>一起使用"
#: c/c-decl.c:9864
#, fuzzy, gcc-internal-format
-#| msgid "%<__thread%> used with %<register%>"
msgid "%qE used with %<register%>"
msgstr "%<__thread%>与%<register%>一起使用"
#: c/c-decl.c:9866
#, fuzzy, gcc-internal-format
-#| msgid "%<__thread%> used with %<typedef%>"
msgid "%qE used with %<typedef%>"
msgstr "%<__thread%>与%<typedef%>一起使用"
#: c/c-decl.c:9880 c/c-parser.c:6560
#, fuzzy, gcc-internal-format
-#| msgid "%s does not support %s"
msgid "ISO C99 does not support %qE"
msgstr "%s ä¸æ”¯æŒ %s"
#: c/c-decl.c:9883 c/c-parser.c:6563
#, fuzzy, gcc-internal-format
-#| msgid "ISO C90 does not support %<long long%>"
msgid "ISO C90 does not support %qE"
msgstr "ISO C90 ä¸æ”¯æŒ%<long long%>"
@@ -28849,7 +28021,6 @@ msgstr "声明指定了多个存储类"
#: c/c-decl.c:9933
#, fuzzy, gcc-internal-format
-#| msgid "%qs must be used with %qs"
msgid "%qs used with %qE"
msgstr "%qs必须与%qs一起使用"
@@ -28906,7 +28077,6 @@ msgstr "需è¦æŒ‡å®šå£°æ˜Ž"
#: c/c-parser.c:1535
#, fuzzy, gcc-internal-format
-#| msgid "%<inline%> in empty declaration"
msgid "%<__auto_type%> in empty declaration"
msgstr "%<inline%>用于空声明中"
@@ -28942,13 +28112,11 @@ msgstr "æ•°æ®å®šä¹‰æ—¶æ²¡æœ‰ç±»åž‹æˆ–存储类"
#: c/c-parser.c:1706
#, fuzzy, gcc-internal-format
-#| msgid "%<typeof%> applied to a bit-field"
msgid "%<__auto_type%> used with a bit-field initializer"
msgstr "为ä½æ®µä½¿ç”¨%<typeof%>"
#: c/c-parser.c:1778 c/c-parser.c:1863
#, fuzzy, gcc-internal-format
-#| msgid "%<auto%> in file-scope empty declaration"
msgid "%<__auto_type%> requires an initialized data declaration"
msgstr "文件作用域中出现%<auto%>空声明"
@@ -29022,19 +28190,16 @@ msgstr ""
#: c/c-parser.c:2372
#, fuzzy, gcc-internal-format
-#| msgid "ISO C99 does not support %<_Static_assert%>"
msgid "ISO C99 does not support the %<_Atomic%> qualifier"
msgstr "ISO C90 ä¸æ”¯æŒ%<_Static_assert%>"
#: c/c-parser.c:2375
#, fuzzy, gcc-internal-format
-#| msgid "ISO C90 does not support %<_Static_assert%>"
msgid "ISO C90 does not support the %<_Atomic%> qualifier"
msgstr "ISO C90 ä¸æ”¯æŒ%<_Static_assert%>"
#: c/c-parser.c:2403
#, fuzzy, gcc-internal-format
-#| msgid "%<typeof%> applied to a bit-field"
msgid "%<_Atomic%> applied to a qualified type"
msgstr "为ä½æ®µä½¿ç”¨%<typeof%>"
@@ -29109,13 +28274,11 @@ msgstr "为ä½æ®µä½¿ç”¨%<typeof%>"
#: c/c-parser.c:3049
#, fuzzy, gcc-internal-format
-#| msgid "ISO C90 does not support %<long long%>"
msgid "ISO C99 does not support %<_Alignas%>"
msgstr "ISO C90 ä¸æ”¯æŒ%<long long%>"
#: c/c-parser.c:3052
#, fuzzy, gcc-internal-format
-#| msgid "ISO C90 does not support %<long long%>"
msgid "ISO C90 does not support %<_Alignas%>"
msgstr "ISO C90 ä¸æ”¯æŒ%<long long%>"
@@ -29126,7 +28289,6 @@ msgstr "需è¦æ ‡è¯†ç¬¦æˆ–%<(%>"
#: c/c-parser.c:3349 c/c-parser.c:3378
#, fuzzy, gcc-internal-format
-#| msgid "Warn for obsolescent usage in a declaration"
msgid "array notations cannot be used in declaration"
msgstr "对声明中的过时用法给出警告"
@@ -29306,37 +28468,31 @@ msgstr "对ä½æ®µä½¿ç”¨%<sizeof%>"
#: c/c-parser.c:6616
#, fuzzy, gcc-internal-format
-#| msgid "ISO C++ does not allow %<alignof%> with a non-type"
msgid "ISO C does not allow %<%E (expression)%>"
msgstr "ISO C++ ä¸å…许对éžç±»åž‹ä½¿ç”¨%<alignof%>"
#: c/c-parser.c:6643
#, fuzzy, gcc-internal-format
-#| msgid "cannot take address of bit-field %qD"
msgid "cannot take address of %qs"
msgstr "无法å–å¾—ä½æ®µ%qD的地å€"
#: c/c-parser.c:6727
#, fuzzy, gcc-internal-format
-#| msgid "ISO C99 does not support %<_Static_assert%>"
msgid "ISO C99 does not support %<_Generic%>"
msgstr "ISO C90 ä¸æ”¯æŒ%<_Static_assert%>"
#: c/c-parser.c:6730
#, fuzzy, gcc-internal-format
-#| msgid "ISO C90 does not support %<_Static_assert%>"
msgid "ISO C90 does not support %<_Generic%>"
msgstr "ISO C90 ä¸æ”¯æŒ%<_Static_assert%>"
#: c/c-parser.c:6797
#, fuzzy, gcc-internal-format
-#| msgid "cast specifies function type"
msgid "%<_Generic%> association has function type"
msgstr "类型转æ¢æŒ‡å®šäº†å‡½æ•°ç±»åž‹"
#: c/c-parser.c:6800
#, fuzzy, gcc-internal-format
-#| msgid "expression statement has incomplete type"
msgid "%<_Generic%> association has incomplete type"
msgstr "表达å¼è¯­å¥ç±»åž‹ä¸å®Œå…¨"
@@ -29352,7 +28508,6 @@ msgstr ""
#: c/c-parser.c:6829
#, fuzzy, gcc-internal-format
-#| msgid "originally defined here"
msgid "original %<default%> is here"
msgstr "原先在这里定义"
@@ -29368,7 +28523,6 @@ msgstr "指针目标类型在 C++ 中ä¸å…¼å®¹"
#: c/c-parser.c:6861
#, fuzzy, gcc-internal-format
-#| msgid "Generate load/store multiple instructions"
msgid "%<_Generic> selector matches multiple associations"
msgstr "生æˆåŠ è½½/存储乘法指令"
@@ -29399,7 +28553,6 @@ msgstr "ISO C ä¸å…许在表达å¼ä¸­ä½¿ç”¨èŠ±æ‹¬å·ç»„"
#: c/c-parser.c:7265
#, fuzzy, gcc-internal-format
-#| msgid "wrong number of arguments to function %<__builtin_next_arg%>"
msgid "wrong number of arguments to %<__builtin_choose_expr%>"
msgstr "给函数%<__builtin_next_arg%>çš„å‚æ•°æ•°ç›®ä¸å¯¹"
@@ -29410,7 +28563,6 @@ msgstr "%<__builtin_choose_expr%>的第一个实å‚ä¸æ˜¯ä¸€ä¸ªå¸¸é‡"
#: c/c-parser.c:7347
#, fuzzy, gcc-internal-format
-#| msgid "wrong number of arguments to function %<__builtin_next_arg%>"
msgid "wrong number of arguments to %<__builtin_complex%>"
msgstr "给函数%<__builtin_next_arg%>çš„å‚æ•°æ•°ç›®ä¸å¯¹"
@@ -29421,13 +28573,11 @@ msgstr ""
#: c/c-parser.c:7378
#, fuzzy, gcc-internal-format
-#| msgid "%<__builtin_longjmp%> second argument must be 1"
msgid "%<__builtin_complex%> operands of different types"
msgstr "%<__builtin_longjmp%>的第二个实å‚必须是 1"
#: c/c-parser.c:7424 cp/parser.c:5861
#, fuzzy, gcc-internal-format
-#| msgid "wrong number of arguments to function %<__builtin_next_arg%>"
msgid "wrong number of arguments to %<__builtin_shuffle%>"
msgstr "给函数%<__builtin_next_arg%>çš„å‚æ•°æ•°ç›®ä¸å¯¹"
@@ -29538,19 +28688,16 @@ msgstr "%<#pragma omp taskwait%>åªèƒ½ç”¨åœ¨å¤åˆè¯­å¥ä¸­"
#: c/c-parser.c:9422 cp/parser.c:31380
#, fuzzy, gcc-internal-format
-#| msgid "%<#pragma omp taskwait%> may only be used in compound statements"
msgid "%<#pragma omp taskyield%> may only be used in compound statements"
msgstr "%<#pragma omp taskwait%>åªèƒ½ç”¨åœ¨å¤åˆè¯­å¥ä¸­"
#: c/c-parser.c:9433 cp/parser.c:31396
#, fuzzy, gcc-internal-format
-#| msgid "%<#pragma omp barrier%> may only be used in compound statements"
msgid "%<#pragma omp cancel%> may only be used in compound statements"
msgstr "%<#pragma omp barrier%>åªèƒ½ç”¨åœ¨å¤åˆè¯­å¥ä¸­"
#: c/c-parser.c:9444 cp/parser.c:31412
#, fuzzy, gcc-internal-format
-#| msgid "%<#pragma omp taskwait%> may only be used in compound statements"
msgid "%<#pragma omp cancellation point%> may only be used in compound statements"
msgstr "%<#pragma omp taskwait%>åªèƒ½ç”¨åœ¨å¤åˆè¯­å¥ä¸­"
@@ -29561,7 +28708,6 @@ msgstr "%<#pragma omp section%>åªèƒ½ç”¨åœ¨%<#pragma omp sections%>结构中"
#: c/c-parser.c:9479 cp/parser.c:31468
#, fuzzy, gcc-internal-format
-#| msgid "for statement expected"
msgid "for, while or do statement expected"
msgstr "éœ€è¦ for 语å¥"
@@ -29598,7 +28744,6 @@ msgstr "%<num_threads%>值必须为正"
#: c/c-parser.c:10195
#, fuzzy, gcc-internal-format
-#| msgid "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, %<|%>, %<&&%>, or %<||%>"
msgid "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or %<max%>"
msgstr "需è¦%<+%>ã€%<*%>ã€%<-%>ã€%<&%>ã€%<^%>ã€%<|%>ã€%<&&%>或%<||%>"
@@ -29619,19 +28764,16 @@ msgstr "无效的调度类型"
#: c/c-parser.c:10410
#, fuzzy, gcc-internal-format
-#| msgid "%<num_threads%> value must be positive"
msgid "%<num_teams%> value must be positive"
msgstr "%<num_threads%>值必须为正"
#: c/c-parser.c:10454
#, fuzzy, gcc-internal-format
-#| msgid "%<num_threads%> value must be positive"
msgid "%<thread_limit%> value must be positive"
msgstr "%<num_threads%>值必须为正"
#: c/c-parser.c:10496 cp/semantics.c:5589
#, fuzzy, gcc-internal-format
-#| msgid "%Hcollapse argument needs positive constant integer expression"
msgid "%<aligned%> clause alignment expression must be positive constant integer expression"
msgstr "%H折å å˜é‡éœ€è¦æ­£æ•´å¸¸æ•°è¡¨è¾¾å¼"
@@ -29642,49 +28784,41 @@ msgstr ""
#: c/c-parser.c:10538
#, fuzzy, gcc-internal-format
-#| msgid "schedule chunk size expression must be integral"
msgid "%<linear%> clause step expression must be integral"
msgstr "调度å—大å°è¡¨è¾¾å¼å¿…须为整型"
#: c/c-parser.c:10575
#, fuzzy, gcc-internal-format
-#| msgid "%Hcollapse argument needs positive constant integer expression"
msgid "%<safelen%> clause expression must be positive constant integer expression"
msgstr "%H折å å˜é‡éœ€è¦æ­£æ•´å¸¸æ•°è¡¨è¾¾å¼"
#: c/c-parser.c:10611
#, fuzzy, gcc-internal-format
-#| msgid "%Hcollapse argument needs positive constant integer expression"
msgid "%<simdlen%> clause expression must be positive constant integer expression"
msgstr "%H折å å˜é‡éœ€è¦æ­£æ•´å¸¸æ•°è¡¨è¾¾å¼"
#: c/c-parser.c:10673 cp/parser.c:27875 cp/parser.c:28058
#, fuzzy, gcc-internal-format
-#| msgid "invalid schedule kind"
msgid "invalid depend kind"
msgstr "无效的调度类型"
#: c/c-parser.c:10710 cp/parser.c:27915
#, fuzzy, gcc-internal-format
-#| msgid "invalid mask"
msgid "invalid map kind"
msgstr "无效掩ç "
#: c/c-parser.c:10775 cp/parser.c:28005
#, fuzzy, gcc-internal-format
-#| msgid "invalid schedule kind"
msgid "invalid dist_schedule kind"
msgstr "无效的调度类型"
#: c/c-parser.c:10844
#, fuzzy, gcc-internal-format
-#| msgid "invalid schedule kind"
msgid "invalid proc_bind kind"
msgstr "无效的调度类型"
#: c/c-parser.c:10999 cp/parser.c:28194
#, fuzzy, gcc-internal-format
-#| msgid "%qs must be used with %qs"
msgid "%qs must be the first clause of %qs"
msgstr "%qs必须与%qs一起使用"
@@ -29700,7 +28834,6 @@ msgstr "%qs对%qs而言无效"
#: c/c-parser.c:11459 cp/parser.c:28653 cp/parser.c:28679
#, fuzzy, gcc-internal-format
-#| msgid "invalid operator for %<#pragma omp atomic%>"
msgid "invalid form of %<#pragma omp atomic%>"
msgstr "%<#pragma omp atomic%>è¿ç®—符无效"
@@ -29746,19 +28879,16 @@ msgstr "迭代å˜é‡%qDä¸åº”当是 firstprivate"
#: c/c-parser.c:12219 cp/parser.c:29731
#, fuzzy, gcc-internal-format
-#| msgid "expected %<operator%>"
msgid "expected %<for%> after %qs"
msgstr "需è¦%<operator%>"
#: c/c-parser.c:12411 cp/parser.c:29918
#, fuzzy, gcc-internal-format
-#| msgid "expected %<using%>"
msgid "expected %<point%>"
msgstr "需è¦%<using%>"
#: c/c-parser.c:12615 cp/parser.c:30140
#, fuzzy, gcc-internal-format
-#| msgid "%<#pragma omp taskwait%> may only be used in compound statements"
msgid "%<#pragma omp target update%> may only be used in compound statements"
msgstr "%<#pragma omp taskwait%>åªèƒ½ç”¨åœ¨å¤åˆè¯­å¥ä¸­"
@@ -29774,7 +28904,6 @@ msgstr ""
#: c/c-parser.c:12817 c/c-parser.c:12845
#, fuzzy, gcc-internal-format
-#| msgid "%<#pragma align%> must appear before the declaration of %D, ignoring"
msgid "%<#pragma omp declare simd%> must be followed by function declaration or definition"
msgstr "%<#pragma align%>必须出现在 %D 的声明之å‰ï¼Œå¿½ç•¥"
@@ -29795,19 +28924,16 @@ msgstr ""
#: c/c-parser.c:12983 cp/parser.c:30450
#, fuzzy, gcc-internal-format
-#| msgid "expected %<try%>"
msgid "expected %<target%>"
msgstr "需è¦%<try%>"
#: c/c-parser.c:12990 cp/parser.c:30457
#, fuzzy, gcc-internal-format
-#| msgid "expected %<decltype%>"
msgid "expected %<declare%>"
msgstr "需è¦%<decltype%>"
#: c/c-parser.c:12996 cp/parser.c:30464
#, fuzzy, gcc-internal-format
-#| msgid "%<#pragma GCC pop_options%> without a corresponding %<#pragma GCC push_options%>"
msgid "%<#pragma omp end declare target%> without corresponding %<#pragma omp declare target%>"
msgstr "%<#pragma GCC pop_options%>缺少相应的%<#pragma GCC push_options%>"
@@ -29818,7 +28944,6 @@ msgstr "Objective-C 声明åªèƒ½å‡ºçŽ°åœ¨å…¨å±€ä½œç”¨åŸŸä¸­"
#: c/c-parser.c:13074
#, fuzzy, gcc-internal-format
-#| msgid "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, %<|%>, %<&&%>, or %<||%>"
msgid "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or identifier"
msgstr "需è¦%<+%>ã€%<*%>ã€%<-%>ã€%<&%>ã€%<^%>ã€%<|%>ã€%<&&%>或%<||%>"
@@ -29844,19 +28969,16 @@ msgstr ""
#: c/c-parser.c:13125
#, fuzzy, gcc-internal-format
-#| msgid "previous declaration"
msgid "previous %<#pragma omp declare reduction%>"
msgstr "上一个声明"
#: c/c-parser.c:13242
#, fuzzy, gcc-internal-format
-#| msgid "expected %<(%> or end of line"
msgid "expected %<omp_priv%> or function-name"
msgstr "需è¦%<(%>或行尾"
#: c/c-parser.c:13253
#, fuzzy, gcc-internal-format
-#| msgid "expected function"
msgid "expected function-name %<(%>"
msgstr "需è¦å‡½æ•°"
@@ -29867,7 +28989,6 @@ msgstr ""
#: c/c-parser.c:13388 cp/parser.c:30900
#, fuzzy, gcc-internal-format
-#| msgid "expected %<#pragma omp section%> or %<}%>"
msgid "expected %<simd%> or %<reduction%> or %<target%>"
msgstr "需è¦%<#pragma omp section%>或%<}%>"
@@ -29898,31 +29019,26 @@ msgstr ""
#: c/c-parser.c:13536
#, fuzzy, gcc-internal-format
-#| msgid "#pragma GCC optimize is not allowed inside functions"
msgid "pragma simd must be inside a function"
msgstr "#pragma GCC optimize ä¸å…许用在函数中"
#: c/c-parser.c:13580 cp/parser.c:31586
#, fuzzy, gcc-internal-format
-#| msgid "selector must be an integer constant in the range 0..%wi"
msgid "vectorlength must be an integer constant"
msgstr "选择å­å¿…须是 0 到 %wi 间的整常é‡"
#: c/c-parser.c:13582 cp/parser.c:31589
#, fuzzy, gcc-internal-format
-#| msgid "stack size must be an exact power of 2"
msgid "vectorlength must be a power of 2"
msgstr "栈大å°å¿…须刚好是 2 çš„æŸæ¬¡æ–¹"
#: c/c-parser.c:13665 cp/parser.c:31696
#, fuzzy, gcc-internal-format
-#| msgid "selector must be an integer constant in the range 0..%wi"
msgid "step size must be an integer constant expression or an integer variable"
msgstr "选择å­å¿…须是 0 到 %wi 间的整常é‡"
#: c/c-parser.c:13764 cp/parser.c:31789
#, fuzzy, gcc-internal-format
-#| msgid "expected %<#pragma omp%> clause"
msgid "expected %<#pragma simd%> clause"
msgstr "需è¦%<#pragma omp%>å­å¥"
@@ -29953,7 +29069,6 @@ msgstr ""
#: c/c-parser.c:14059 cp/parser.c:6263
#, fuzzy, gcc-internal-format
-#| msgid "expected %<:%> or %<::%>"
msgid "expected %<:%> or numeral"
msgstr "需è¦%<:%>或%<::%>"
@@ -29964,7 +29079,6 @@ msgstr ""
#: c/c-parser.c:14077 c/c-parser.c:14120
#, fuzzy, gcc-internal-format
-#| msgid "new cannot be applied to a function type"
msgid "array notations cannot be used with function type"
msgstr "new ä¸èƒ½ç”¨äºŽå‡½æ•°ç±»åž‹"
@@ -29980,7 +29094,6 @@ msgstr ""
#: c/c-parser.c:14148 c/c-parser.c:14151
#, fuzzy, gcc-internal-format
-#| msgid "expected boolean expression"
msgid "expected array notation expression"
msgstr "需è¦å¸ƒå°”表达å¼"
@@ -30062,7 +29175,6 @@ msgstr "在指å‘ä¸å®Œå…¨ç±»åž‹çš„指针上执行算术è¿ç®—"
#: c/c-typeck.c:1832
#, fuzzy, gcc-internal-format
-#| msgid "defining a type in a compound literal is invalid in C++"
msgid "converting an array compound literal to a pointer is ill-formed in C++"
msgstr "C++ ä¸å…许在组åˆå­—é¢å¸¸é‡ä¸­å®šä¹‰ç±»åž‹"
@@ -30088,7 +29200,6 @@ msgstr "æ领%<void *%>指针"
#: c/c-typeck.c:2434
#, fuzzy, gcc-internal-format
-#| msgid "alignment of array elements is greater than element size"
msgid "rank of the array's index is greater than 1"
msgstr "数组元素的对é½è¾¹ç•Œæ¯”元素大å°è¿˜è¦å¤§"
@@ -30129,19 +29240,16 @@ msgstr "在此声明"
#: c/c-typeck.c:2881
#, fuzzy, gcc-internal-format
-#| msgid "called object %qE is not a function"
msgid "called object %qE is not a function or function pointer"
msgstr "被调用的对象%qEä¸æ˜¯ä¸€ä¸ªå‡½æ•°"
#: c/c-typeck.c:2886
#, fuzzy, gcc-internal-format
-#| msgid "called object %qE is not a function"
msgid "called object %qD is not a function or function pointer"
msgstr "被调用的对象%qEä¸æ˜¯ä¸€ä¸ªå‡½æ•°"
#: c/c-typeck.c:2892
#, fuzzy, gcc-internal-format
-#| msgid "called object %qE is not a function"
msgid "called object is not a function or function pointer"
msgstr "被调用的对象%qEä¸æ˜¯ä¸€ä¸ªå‡½æ•°"
@@ -30250,7 +29358,6 @@ msgstr "函数指针ä¸èƒ½ç›¸å‡"
#: c/c-typeck.c:3515 cp/typeck.c:5054
#, fuzzy, gcc-internal-format
-#| msgid "arithmetic on pointer to an incomplete type"
msgid "arithmetic on pointer to an empty aggregate"
msgstr "在指å‘ä¸å®Œå…¨ç±»åž‹çš„指针上执行算术è¿ç®—"
@@ -30366,7 +29473,6 @@ msgstr "æ¡ä»¶è¡¨è¾¾å¼ä¸­æŒ‡é’ˆ/整数类型ä¸åŒ¹é…"
#: c/c-typeck.c:4725 cp/typeck.c:6204
#, fuzzy, gcc-internal-format
-#| msgid "a function call cannot appear in a constant-expression"
msgid "spawned function call cannot be part of a comma expression"
msgstr "函数调用ä¸èƒ½å‡ºçŽ°åœ¨å¸¸é‡è¡¨è¾¾å¼ä¸­"
@@ -30377,7 +29483,6 @@ msgstr "逗å·è¡¨è¾¾å¼çš„å·¦æ“作数ä¸èµ·ä½œç”¨"
#: c/c-typeck.c:4777 c/c-typeck.c:9666
#, fuzzy, gcc-internal-format
-#| msgid "left-hand operand of comma expression has no effect"
msgid "right-hand operand of comma expression has no effect"
msgstr "逗å·è¡¨è¾¾å¼çš„å·¦æ“作数ä¸èµ·ä½œç”¨"
@@ -30473,7 +29578,6 @@ msgstr "C++ ç¦æ­¢åœ¨ç±»åž‹è½¬æ¢ä¸­å®šä¹‰ç±»åž‹"
#: c/c-typeck.c:5214
#, fuzzy, gcc-internal-format
-#| msgid "assignment suppression"
msgid "assignment to expression with array type"
msgstr "å–消赋值"
@@ -30819,7 +29923,6 @@ msgstr "在嵌套的上下文中åˆå§‹åŒ–å¯å˜æ•°ç»„æˆå‘˜"
#: c/c-typeck.c:7436
#, fuzzy, gcc-internal-format
-#| msgid "missing initializer for member %qD"
msgid "missing initializer for field %qD of %qT"
msgstr "æˆå‘˜%qD缺少åˆå§‹å€¼è®¾å®š"
@@ -30945,7 +30048,6 @@ msgstr ""
#: c/c-typeck.c:9139 cp/typeck.c:8333
#, fuzzy, gcc-internal-format
-#| msgid "Logical range in CASE statement at %L is not allowed"
msgid "use of %<_Cilk_spawn%> in a return statement is not allowed"
msgstr "%L处 CASE 语å¥ä¸­çš„逻辑范围是ä¸è¢«å…许的"
@@ -31031,13 +30133,11 @@ msgstr "OpenMP for 循环中使用了 break 语å¥"
#: c/c-typeck.c:9621
#, fuzzy, gcc-internal-format
-#| msgid "break statement not within loop or switch"
msgid "break statement within %<#pragma simd%> loop body"
msgstr "break 语å¥ä¸åœ¨å¾ªçŽ¯æˆ–开关语å¥å†…"
#: c/c-typeck.c:9623 cp/parser.c:10656
#, fuzzy, gcc-internal-format
-#| msgid "continue statement not within a loop"
msgid "continue statement within %<#pragma simd%> loop body"
msgstr "continue 语å¥å‡ºçŽ°åœ¨å¾ªçŽ¯ä»¥å¤–"
@@ -31053,7 +30153,6 @@ msgstr "表达å¼è¯­å¥ç±»åž‹ä¸å®Œå…¨"
#: c/c-typeck.c:10464 c/c-typeck.c:10601 cp/typeck.c:4570
#, fuzzy, gcc-internal-format
-#| msgid "Warn about comparison of different enum types"
msgid "comparing vectors with different element types"
msgstr "对ä¸åŒæžšä¸¾ç±»åž‹ä¹‹é—´çš„比较给出警告"
@@ -31140,7 +30239,6 @@ msgstr "需è¦æ ‡é‡æ—¶ä½¿ç”¨äº†è”åˆç±»åž‹"
#: c/c-typeck.c:11053
#, fuzzy, gcc-internal-format
-#| msgid "used struct type value where scalar is required"
msgid "used vector type where scalar is required"
msgstr "需è¦æ ‡é‡æ—¶ä½¿ç”¨äº†ç»“构类型"
@@ -31156,33 +30254,28 @@ msgstr ""
#: c/c-typeck.c:11269 cp/semantics.c:4222 cp/semantics.c:5655
#, fuzzy, gcc-internal-format
-#| msgid "%qD is not a variable in clause %qs"
msgid "%qD is not a variable in %qs clause"
msgstr "%qD在å­å¥%qs中ä¸æ˜¯ä¸€ä¸ªå˜é‡"
#: c/c-typeck.c:11273 c/c-typeck.c:12044 cp/semantics.c:4226
#: cp/semantics.c:5658
#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a variable in clause %qs"
msgid "%qE is not a variable in %qs clause"
msgstr "%qE在å­å¥%qs中ä¸æ˜¯ä¸€ä¸ªå˜é‡"
#: c/c-typeck.c:11281 c/c-typeck.c:12051 cp/semantics.c:4234
#: cp/semantics.c:5664
#, fuzzy, gcc-internal-format
-#| msgid "%qD is not a variable in clause %qs"
msgid "%qD is threadprivate variable in %qs clause"
msgstr "%qD在å­å¥%qs中ä¸æ˜¯ä¸€ä¸ªå˜é‡"
#: c/c-typeck.c:11303 cp/semantics.c:4260
#, fuzzy, gcc-internal-format
-#| msgid "size in array new must have integral type"
msgid "low bound %qE of array section does not have integral type"
msgstr "数组 new 的大å°å¿…须有整数类型"
#: c/c-typeck.c:11310 cp/semantics.c:4267
#, fuzzy, gcc-internal-format
-#| msgid "size in array new must have integral type"
msgid "length %qE of array section does not have integral type"
msgstr "数组 new 的大å°å¿…须有整数类型"
@@ -31198,7 +30291,6 @@ msgstr ""
#: c/c-typeck.c:11359 cp/semantics.c:4316
#, fuzzy, gcc-internal-format
-#| msgid "variable length array is used"
msgid "negative length in array section in %qs clause"
msgstr "使用了å˜é•¿æ•°ç»„"
@@ -31219,14 +30311,12 @@ msgstr ""
#: c/c-typeck.c:11447 cp/semantics.c:4404
#, fuzzy, gcc-internal-format
-#| msgid "for increment expression has no effect"
msgid "for pointer type length expression must be specified"
msgstr "for 循环増é‡è¡¨è¾¾å¼ä¸èµ·ä½œç”¨"
#: c/c-typeck.c:11456 c/c-typeck.c:11571 cp/semantics.c:4413
#: cp/semantics.c:4524
#, fuzzy, gcc-internal-format
-#| msgid "Copy array sections into a contiguous block on procedure entry"
msgid "array section is not contiguous in %qs clause"
msgstr "在过程入å£å¤„将数组段å¤åˆ¶åˆ°ä¸€ä¸ªè¿žç»­çš„å—中"
@@ -31282,25 +30372,21 @@ msgstr "%qE在å­å¥%<lastprivate%>中ä¸æ˜¯ä¸€ä¸ªå˜é‡"
#: c/c-typeck.c:11975 cp/semantics.c:5545
#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a variable in clause %qs"
msgid "%qE is not a variable in %<aligned%> clause"
msgstr "%qE在å­å¥%qs中ä¸æ˜¯ä¸€ä¸ªå˜é‡"
#: c/c-typeck.c:11982
#, fuzzy, gcc-internal-format
-#| msgid "type to vector delete is neither pointer or array type"
msgid "%qE in %<aligned%> clause is neither a pointer nor an array"
msgstr "å‘é‡ delete 的实å‚类型既éžæŒ‡é’ˆä¹Ÿéžæ•°ç»„"
#: c/c-typeck.c:11989
#, fuzzy, gcc-internal-format
-#| msgid "%qE appears more than once in data clauses"
msgid "%qE appears more than once in %<aligned%> clauses"
msgstr "%qE在数æ®å­å¥ä¸­å¤šæ¬¡å‡ºçŽ°"
#: c/c-typeck.c:12010 cp/semantics.c:5615
#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a variable in clause %qs"
msgid "%qE is not a variable in %<depend%> clause"
msgstr "%qE在å­å¥%qs中ä¸æ˜¯ä¸€ä¸ªå˜é‡"
@@ -31311,31 +30397,26 @@ msgstr "在 %L 处的推迟数组“%1$sâ€åœ¨åˆå§‹åŒ–表达å¼ä¸­ä¸è¢«å…许"
#: c/c-typeck.c:12062 cp/semantics.c:5680
#, fuzzy, gcc-internal-format
-#| msgid "%qD is not a variable in clause %qs"
msgid "%qD does not have a mappable type in %qs clause"
msgstr "%qD在å­å¥%qs中ä¸æ˜¯ä¸€ä¸ªå˜é‡"
#: c/c-typeck.c:12069 cp/semantics.c:5687
#, fuzzy, gcc-internal-format
-#| msgid "%qD appears more than once in data clauses"
msgid "%qD appears more than once in motion clauses"
msgstr "%qD在数æ®å­å¥ä¸­å¤šæ¬¡å‡ºçŽ°"
#: c/c-typeck.c:12071 cp/semantics.c:5689
#, fuzzy, gcc-internal-format
-#| msgid "%qD appears more than once in data clauses"
msgid "%qD appears more than once in map clauses"
msgstr "%qD在数æ®å­å¥ä¸­å¤šæ¬¡å‡ºçŽ°"
#: c/c-typeck.c:12084 cp/semantics.c:5703
#, fuzzy, gcc-internal-format
-#| msgid "%qD is not a variable in clause %qs"
msgid "%qD is not an argument in %<uniform%> clause"
msgstr "%qD在å­å¥%qs中ä¸æ˜¯ä¸€ä¸ªå˜é‡"
#: c/c-typeck.c:12087 cp/semantics.c:5705
#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a variable in clause %qs"
msgid "%qE is not an argument in %<uniform%> clause"
msgstr "%qE在å­å¥%qs中ä¸æ˜¯ä¸€ä¸ªå˜é‡"
@@ -31424,7 +30505,6 @@ msgstr ""
#. Re-run template unification with diagnostics.
#: cp/call.c:3279
#, fuzzy, gcc-internal-format
-#| msgid "template argument %d is invalid"
msgid " template argument deduction/substitution failed:"
msgstr "模æ¿ç¬¬ %d 个å‚数无效"
@@ -31472,25 +30552,21 @@ msgstr "对%<(%T) (%A)%>的调用有歧义"
#: cp/call.c:4245
#, fuzzy, gcc-internal-format
-#| msgid "ambiguous overload for %qs in %<%s %E%>"
msgid "ambiguous overload for "
msgstr "%qs在%<%s %E%>中的é‡è½½æœ‰æ­§ä¹‰"
#: cp/call.c:4246
#, fuzzy, gcc-internal-format
-#| msgid "no match for %qs in %<%s %E%>"
msgid "no match for "
msgstr "%qs在%<%s %E%>中没有匹é…"
#: cp/call.c:4249
#, fuzzy, gcc-internal-format
-#| msgid "invalid operands to binary %s (have %qT and %qT)"
msgid " (operand types are %qT, %qT, and %qT)"
msgstr "åŒç›®è¿ç®—符 %s æ“作数(%qTå’Œ%qT)无效"
#: cp/call.c:4251
#, fuzzy, gcc-internal-format
-#| msgid "invalid operands to binary %s (have %qT and %qT)"
msgid " (operand types are %qT and %qT)"
msgstr "åŒç›®è¿ç®—符 %s æ“作数(%qTå’Œ%qT)无效"
@@ -31501,61 +30577,51 @@ msgstr ""
#: cp/call.c:4273
#, fuzzy, gcc-internal-format
-#| msgid "expected %<operator%>"
msgid "ternary %<operator?:%>"
msgstr "需è¦%<operator%>"
#: cp/call.c:4277
#, fuzzy, gcc-internal-format
-#| msgid "no match for ternary %<operator?:%> in %<%E ? %E : %E%>"
msgid "ternary %<operator?:%> in %<%E ? %E : %E%>"
msgstr "三元%<operator?:%>在%<%E ? %E : %E%>中没有匹é…"
#: cp/call.c:4286 cp/call.c:4317 cp/call.c:4326
#, fuzzy, gcc-internal-format
-#| msgid "expected %<operator%>"
msgid "%<operator%s%>"
msgstr "需è¦%<operator%>"
#: cp/call.c:4289
#, fuzzy, gcc-internal-format
-#| msgid "no match for %<operator%s%> in %<%E%s%>"
msgid "%<operator%s%> in %<%E%s%>"
msgstr "%<operator%s%>在%<%E%s%>中没有匹é…"
#: cp/call.c:4296
#, fuzzy, gcc-internal-format
-#| msgid "expected %<operator%>"
msgid "%<operator[]%>"
msgstr "需è¦%<operator%>"
#: cp/call.c:4299
#, fuzzy, gcc-internal-format
-#| msgid "no match for %<operator[]%> in %<%E[%E]%>"
msgid "%<operator[]%> in %<%E[%E]%>"
msgstr "%<operator[]%>在%<%E[%E]%>中没有匹é…"
#: cp/call.c:4307
#, fuzzy, gcc-internal-format
-#| msgid "%s"
msgid "%qs"
msgstr "%s"
#: cp/call.c:4310
#, fuzzy, gcc-internal-format
-#| msgid "no match for %qs in %<%s %E%>"
msgid "%qs in %<%s %E%>"
msgstr "%qs在%<%s %E%>中没有匹é…"
#: cp/call.c:4320
#, fuzzy, gcc-internal-format
-#| msgid "no match for %<operator%s%> in %<%E %s %E%>"
msgid "%<operator%s%> in %<%E %s %E%>"
msgstr "%<operator%s%>在%<%E %s %E%>中没有匹é…"
#: cp/call.c:4329
#, fuzzy, gcc-internal-format
-#| msgid "no match for %<operator%s%> in %<%s%E%>"
msgid "%<operator%s%> in %<%s%E%>"
msgstr "%<operator%s%>在%<%s%E%>中没有匹é…"
@@ -31571,7 +30637,6 @@ msgstr ""
#: cp/call.c:4554
#, fuzzy, gcc-internal-format
-#| msgid "enumeral mismatch in conditional expression: %qT vs %qT"
msgid "incompatible vector types in conditional expression: %qT, %qT and %qT"
msgstr "æ¡ä»¶è¡¨è¾¾å¼ä¸­æžšä¸¾ä¸åŒ¹é…:%qT对%qT"
@@ -31672,7 +30737,6 @@ msgstr "å°†%<false%>转æ¢ä¸ºæŒ‡å‘%2$qDçš„å®žå‚ %1$P 的指针类型"
#: cp/call.c:5883
#, fuzzy, gcc-internal-format
-#| msgid "converting %<false%> to pointer type for argument %P of %qD"
msgid "converting %<false%> to pointer type %qT"
msgstr "å°†%<false%>转æ¢ä¸ºæŒ‡å‘%2$qDçš„å®žå‚ %1$P 的指针类型"
@@ -31683,7 +30747,6 @@ msgstr "%qTçš„åˆå§‹å€¼è®¾å®šå‘¨å›´èŠ±æ‹¬å·å¤ªå¤š"
#: cp/call.c:5940
#, fuzzy, gcc-internal-format
-#| msgid "invalid conversion from %qT to %qT"
msgid "invalid user-defined conversion from %qT to %qT"
msgstr "从类型%qT到类型%qT的转æ¢æ— æ•ˆ"
@@ -31694,7 +30757,6 @@ msgstr "从类型%qT到类型%qT的转æ¢æ— æ•ˆ"
#: cp/call.c:5975
#, fuzzy, gcc-internal-format
-#| msgid " initializing argument %P of %qD"
msgid "initializing argument %P of %qD"
msgstr " åˆå§‹åŒ–%2$qDçš„å®žå‚ %1$P"
@@ -31705,7 +30767,6 @@ msgstr "从åˆå§‹åŒ–列表转æ¢ä¸º%qT将使用显å¼æž„造函数%qD"
#: cp/call.c:6080 cp/call.c:6219
#, fuzzy, gcc-internal-format
-#| msgid " initializing argument %P of %q+D"
msgid "initializing argument %P of %q+D"
msgstr "以åˆå§‹åŒ–%2$q+Dçš„å®žå‚ %1$P"
@@ -31736,7 +30797,6 @@ msgstr "无法将å³å€¼%qE绑定到%qT"
#: cp/call.c:6370 cp/cvt.c:1720
#, fuzzy, gcc-internal-format
-#| msgid "class %qT will be considered nearly empty in a future version of GCC"
msgid "scoped enum %qT will not promote to an integral type in a future version of GCC"
msgstr "在 GCC 的未æ¥ç‰ˆæœ¬ä¸­ç±»%qT将被看作几乎为空"
@@ -31758,7 +30818,6 @@ msgstr "递归计算%q#D的默认å‚æ•°"
#: cp/call.c:6507
#, fuzzy, gcc-internal-format
-#| msgid "the default argument for parameter %d of %qD has not yet been parsed"
msgid "call to %qD uses the default argument for parameter %P, which is not yet defined"
msgstr "%2$qD的第 %1$d 个形å‚的默认实å‚尚未被解æžåˆ°"
@@ -31769,7 +30828,6 @@ msgstr "函数的实å‚å¯èƒ½æ˜¯ format 属性的备选"
#: cp/call.c:6668
#, fuzzy, gcc-internal-format
-#| msgid "defaulted function %q+D with default argument"
msgid "use of multiversioned function without a default"
msgstr "默认化函数%q+D有默认å‚æ•°"
@@ -31820,7 +30878,6 @@ msgstr "ä¸èƒ½ç›´æŽ¥è°ƒç”¨æž„造函数%<%T::%D%>"
#: cp/call.c:7662
#, fuzzy, gcc-internal-format
-#| msgid " for a function-style cast, remove the redundant %<::%D%>"
msgid "for a function-style cast, remove the redundant %<::%D%>"
msgstr "对于函数类型的类型转æ¢ï¼Œç§»é™¤å†—余的%<::%D%>"
@@ -31891,7 +30948,6 @@ msgstr "ISO C++ 认为有歧义,尽管第一个备选的最差类型转æ¢è¦å
#: cp/call.c:9075
#, fuzzy, gcc-internal-format
-#| msgid "could not convert %qE to %qT"
msgid "could not convert %qE from %qT to %qT"
msgstr "ä¸èƒ½å°†%qE转æ¢ä¸º%qT"
@@ -31912,25 +30968,21 @@ msgstr "将类型为%qT的引用åˆå§‹åŒ–为类型为%qT的表达å¼æ— æ•ˆ"
#: cp/class.c:302
#, fuzzy, gcc-internal-format
-#| msgid "cannot convert from base %qT to derived type %qT via virtual base %qT"
msgid "cannot convert from pointer to base class %qT to pointer to derived class %qT because the base is virtual"
msgstr "无法从基类%qT转æ¢åˆ°æ´¾ç”Ÿç±»%qT,通过虚基类%qT"
#: cp/class.c:306
#, fuzzy, gcc-internal-format
-#| msgid "cannot convert from base %qT to derived type %qT via virtual base %qT"
msgid "cannot convert from base class %qT to derived class %qT because the base is virtual"
msgstr "无法从基类%qT转æ¢åˆ°æ´¾ç”Ÿç±»%qT,通过虚基类%qT"
#: cp/class.c:313
#, fuzzy, gcc-internal-format
-#| msgid "cannot convert from base %qT to derived type %qT via virtual base %qT"
msgid "cannot convert from pointer to base class %qT to pointer to derived class %qT via virtual base %qT"
msgstr "无法从基类%qT转æ¢åˆ°æ´¾ç”Ÿç±»%qT,通过虚基类%qT"
#: cp/class.c:318
#, fuzzy, gcc-internal-format
-#| msgid "cannot convert from base %qT to derived type %qT via virtual base %qT"
msgid "cannot convert from base class %qT to derived class %qT via virtual base %qT"
msgstr "无法从基类%qT转æ¢åˆ°æ´¾ç”Ÿç±»%qT,通过虚基类%qT"
@@ -31946,13 +30998,11 @@ msgstr "Java ç±»%qTä¸èƒ½æœ‰éšå¼çš„ä¸å¹³å‡¡çš„æžæž„函数"
#: cp/class.c:1159
#, fuzzy, gcc-internal-format
-#| msgid " inlined from %qs"
msgid "%q#D inherited from %qT"
msgstr " 内è”自%qs"
#: cp/class.c:1162
#, fuzzy, gcc-internal-format
-#| msgid "conflicts with previous declaration here"
msgid "conflicts with version inherited from %qT"
msgstr "与先å‰æ­¤å¤„的声明冲çª"
@@ -31998,7 +31048,6 @@ msgstr ""
#: cp/class.c:1389 cp/class.c:1399
#, fuzzy, gcc-internal-format
-#| msgid "%qD declared here"
msgid "%qT declared here"
msgstr "%qD在此声明"
@@ -32009,7 +31058,6 @@ msgstr ""
#: cp/class.c:1508
#, fuzzy, gcc-internal-format
-#| msgid "cannot convert from base %qT to derived type %qT via virtual base %qT"
msgid "cannot derive from %<final%> base %qT in derived type %qT"
msgstr "无法从基类%qT转æ¢åˆ°æ´¾ç”Ÿç±»%qT,通过虚基类%qT"
@@ -32040,7 +31088,6 @@ msgstr "%qD的最终é‡è½½åœ¨%qT中ä¸å”¯ä¸€"
#: cp/class.c:2753
#, fuzzy, gcc-internal-format
-#| msgid "%q+D defined but not used"
msgid "%q+#D marked final, but is not virtual"
msgstr "%q+D定义åŽæœªä½¿ç”¨"
@@ -32177,13 +31224,11 @@ msgstr "为éžç´§å®žçš„éžç®€å•æ—§æ•°æ®å­—段%q+#D忽略 packed 属性"
#: cp/class.c:3594
#, fuzzy, gcc-internal-format
-#| msgid "non-member %qs cannot be declared %<mutable%>"
msgid "member %q+D cannot be declared both %<const%> and %<mutable%>"
msgstr "éžæˆå‘˜%qsä¸èƒ½è¢«å£°æ˜Žä¸º%<mutable%>"
#: cp/class.c:3600
#, fuzzy, gcc-internal-format
-#| msgid "non-member %qs cannot be declared %<mutable%>"
msgid "member %q+D cannot be declared as a %<mutable%> reference"
msgstr "éžæˆå‘˜%qsä¸èƒ½è¢«å£°æ˜Žä¸º%<mutable%>"
@@ -32244,13 +31289,11 @@ msgstr "%3$L处 CLASS å˜é‡â€˜%2$s’的类型‘%1$s’ä¸èƒ½è¢«æ‰©å±•"
#: cp/class.c:5393
#, fuzzy, gcc-internal-format
-#| msgid "%q#T is not a class"
msgid "%q+T is not literal because:"
msgstr "%q#Tä¸æ˜¯ä¸€ä¸ªç±»"
#: cp/class.c:5395
#, fuzzy, gcc-internal-format
-#| msgid "base class %q#T has a non-virtual destructor"
msgid " %q+T has a non-trivial destructor"
msgstr "基类%q#T有一个éžè™šæžæž„函数"
@@ -32266,7 +31309,6 @@ msgstr "%3$L处 CLASS å˜é‡â€˜%2$s’的类型‘%1$s’ä¸èƒ½è¢«æ‰©å±•"
#: cp/class.c:5450
#, fuzzy, gcc-internal-format
-#| msgid "non-static data member %qD has Java class type"
msgid " non-static data member %q+D has non-literal type"
msgstr "éžé™æ€æ•°æ®æˆå‘˜%qD具有 Java 类类型"
@@ -32339,7 +31381,6 @@ msgstr "%q#T有虚函数和å¯è®¿é—®çš„éžè™šæ‹Ÿæžæž„函数"
#: cp/class.c:6643
#, fuzzy, gcc-internal-format
-#| msgid "type %qT does not have a known size"
msgid "type transparent %q#T does not have any fields"
msgstr "类型%qT大å°æœªçŸ¥"
@@ -32350,7 +31391,6 @@ msgstr ""
#: cp/class.c:6653
#, fuzzy, gcc-internal-format
-#| msgid "type %qE has virtual member functions"
msgid "type transparent class %qT has virtual functions"
msgstr "类型%qE有虚æˆå‘˜å‡½æ•°"
@@ -32421,7 +31461,6 @@ msgstr "改å˜äº†%qD的原æ„%q+#D"
#: cp/cp-array-notation.c:605
#, fuzzy, gcc-internal-format
-#| msgid "%qD cannot be declared as constexpr"
msgid "%qD cannot be scalar when %qD is not"
msgstr "%qDä¸èƒ½è¢«å£°æ˜Žä¸ºå¹¿ä¹‰å¸¸è¡¨è¾¾å¼"
@@ -32463,7 +31502,6 @@ msgstr ""
#: cp/cp-array-notation.c:1422
#, fuzzy, gcc-internal-format
-#| msgid "new cannot be applied to a function type"
msgid "array notation cannot be used with function type"
msgstr "new ä¸èƒ½ç”¨äºŽå‡½æ•°ç±»åž‹"
@@ -32484,13 +31522,11 @@ msgstr ""
#: cp/cp-cilkplus.c:53
#, fuzzy, gcc-internal-format
-#| msgid "statement-expressions are not allowed outside functions nor in template-argument lists"
msgid "throw expressions are not allowed inside loops marked with pragma simd"
msgstr "语å¥è¡¨è¾¾å¼åªèƒ½ç”¨äºŽå‡½æ•°æˆ–模æ¿å®žå‚列表内"
#: cp/cp-cilkplus.c:60
#, fuzzy, gcc-internal-format
-#| msgid "%s statement is not allowed inside of BLOCK at %C"
msgid "try statements are not allowed inside loops marked with #pragma simd"
msgstr "%s 语å¥ä¸èƒ½ç”¨åœ¨%C处 BLOCK 内"
@@ -32561,7 +31597,6 @@ msgstr "ä¸åº”使用%q#T而应使用%qT"
#: cp/cvt.c:780
#, fuzzy, gcc-internal-format
-#| msgid "could not convert %qE to %qT"
msgid "could not convert %qE from %<void%> to %<bool%>"
msgstr "ä¸èƒ½å°†%qE转æ¢ä¸º%qT"
@@ -32822,7 +31857,6 @@ msgstr "å°† NULL 转æ¢ä¸ºéžæŒ‡é’ˆç±»åž‹"
#: cp/cvt.c:1644
#, fuzzy, gcc-internal-format
-#| msgid "could not convert template argument %qE to %qT"
msgid "default type conversion can't deduce template argument for %qD"
msgstr "ä¸èƒ½å°†æ¨¡æ¿å‚数从%qE转æ¢åˆ°%qT"
@@ -32894,7 +31928,6 @@ msgstr "函数%q+Dé‡å£°æ˜Žä¸ºå†…è”çš„"
#: cp/decl.c:1304
#, fuzzy, gcc-internal-format
-#| msgid "previous declaration of %q+D with attribute noinline"
msgid "previous declaration of %qD with attribute noinline"
msgstr "å…ˆå‰%q+D的声明带有 noinline 属性"
@@ -32905,7 +31938,6 @@ msgstr "函数%q+Dé‡å£°æ˜Žä¸ºå¸¦æœ‰ä¸å¯å†…è”属性"
#: cp/decl.c:1314
#, fuzzy, gcc-internal-format
-#| msgid "previous declaration of %q+D was inline"
msgid "previous declaration of %qD was inline"
msgstr "%q+Då…ˆå‰è¢«å£°æ˜Žä¸ºå†…è”çš„"
@@ -32926,25 +31958,21 @@ msgstr "库函数%q#Dé‡å£°æ˜Žä¸ºéžå‡½æ•°%q#D"
#: cp/decl.c:1349
#, fuzzy, gcc-internal-format
-#| msgid "conflicts with built-in declaration %q#D"
msgid "declaration of %q#D conflicts with built-in declaration %q#D"
msgstr "与内建声明%q#D冲çª"
#: cp/decl.c:1357
#, fuzzy, gcc-internal-format
-#| msgid "declaration of %qD shadows a global declaration"
msgid "redeclaration of %<pragma omp declare reduction%>"
msgstr "%qD的声明éšè—了一个全局声明"
#: cp/decl.c:1359
#, fuzzy, gcc-internal-format
-#| msgid "previous non-function declaration %q+#D"
msgid "previous %<pragma omp declare reduction%> declaration"
msgstr "å…ˆå‰å¯¹äºŽ%q+#Dçš„éžå‡½æ•°å£°æ˜Ž"
#: cp/decl.c:1410
#, fuzzy, gcc-internal-format
-#| msgid "ambiguates built-in declaration %q#D"
msgid "new declaration %q#D ambiguates built-in declaration %q#D"
msgstr "使内建声明%q#D出现歧义"
@@ -32955,37 +31983,31 @@ msgstr "%q#D被é‡æ–°å£°æ˜Žä¸ºä¸åŒæ„义的符å·"
#: cp/decl.c:1505 cp/decl.c:1526 cp/decl.c:1553
#, fuzzy, gcc-internal-format
-#| msgid "previous declaration %q+D"
msgid "previous declaration %q#D"
msgstr "å…ˆå‰çš„声明%q+D"
#: cp/decl.c:1524
#, fuzzy, gcc-internal-format
-#| msgid "declaration of template %q#D"
msgid "conflicting declaration of template %q#D"
msgstr "模æ¿å£°æ˜Ž%q#D"
#: cp/decl.c:1540
#, fuzzy, gcc-internal-format
-#| msgid "ambiguates old declaration %q+#D"
msgid "ambiguating new declaration %q#D"
msgstr "使旧的声明%q+#D出现歧义"
#: cp/decl.c:1542 cp/decl.c:1565
#, fuzzy, gcc-internal-format
-#| msgid "global declaration %q+#D"
msgid "old declaration %q#D"
msgstr "全局声明%q+#D"
#: cp/decl.c:1550
#, fuzzy, gcc-internal-format
-#| msgid "conflicting declaration %q#D"
msgid "conflicting declaration of C function %q#D"
msgstr "相互冲çªçš„声明%q#D"
#: cp/decl.c:1563
#, fuzzy, gcc-internal-format
-#| msgid "ambiguates old declaration %q+#D"
msgid "ambiguating new declaration of %q#D"
msgstr "使旧的声明%q+#D出现歧义"
@@ -32996,7 +32018,6 @@ msgstr "相互冲çªçš„声明%q#D"
#: cp/decl.c:1575
#, fuzzy, gcc-internal-format
-#| msgid "previous declaration of %q+#D"
msgid "previous declaration as %q#D"
msgstr "%q+#Dçš„å‰ä¸€ä¸ªå£°æ˜Ž"
@@ -33009,13 +32030,11 @@ msgstr "%q+#Dçš„å‰ä¸€ä¸ªå£°æ˜Ž"
#. of the program.
#: cp/decl.c:1627
#, fuzzy, gcc-internal-format
-#| msgid "conflicting declaration %q#D"
msgid "conflicting declaration of namespace %qD"
msgstr "相互冲çªçš„声明%q#D"
#: cp/decl.c:1629
#, fuzzy, gcc-internal-format
-#| msgid "previous declaration of namespace %q+D here"
msgid "previous declaration of namespace %qD here"
msgstr "命å空间%q+D早先的声明在这里"
@@ -33026,37 +32045,31 @@ msgstr "%q+#D已在此定义过"
#: cp/decl.c:1642 cp/name-lookup.c:1152 cp/name-lookup.c:1175
#, fuzzy, gcc-internal-format
-#| msgid "previously declared here"
msgid "%q+#D previously declared here"
msgstr "以å‰åœ¨æ­¤å£°æ˜Žè¿‡"
#: cp/decl.c:1652
#, fuzzy, gcc-internal-format
-#| msgid "prototype for %q+#D"
msgid "prototype specified for %q#D"
msgstr "%q+#D的原型"
#: cp/decl.c:1654
#, fuzzy, gcc-internal-format
-#| msgid "follows non-prototype definition here"
msgid "previous non-prototype definition here"
msgstr "出现在此处的éžåŽŸåž‹å®šä¹‰ä¹‹åŽ"
#: cp/decl.c:1693
#, fuzzy, gcc-internal-format
-#| msgid "conflicts with new declaration with %qL linkage"
msgid "conflicting declaration of %q#D with %qL linkage"
msgstr "与带有%qL链接的新声明冲çª"
#: cp/decl.c:1696
#, fuzzy, gcc-internal-format
-#| msgid "previous declaration of %q+#D with %qL linkage"
msgid "previous declaration with %qL linkage"
msgstr "%q+#D的早先声明有%qL链接"
#: cp/decl.c:1723
#, fuzzy, gcc-internal-format
-#| msgid "redeclaration of friend %q#D may not have default template arguments"
msgid "redeclaration of %q#D may not have default arguments"
msgstr "å‹å…ƒ%q#Dçš„é‡å£°æ˜Žä¸èƒ½æœ‰é»˜è®¤æ¨¡æ¿å‚æ•°"
@@ -33067,7 +32080,6 @@ msgstr "为%2$q#D的第 %1$d 个形å‚指定了默认实å‚"
#: cp/decl.c:1741 cp/decl.c:1749
#, fuzzy, gcc-internal-format
-#| msgid "after previous specification in %q+#D"
msgid "previous specification in %q#D here"
msgstr "但先å‰åœ¨%q+#D中已有指定"
@@ -33078,7 +32090,6 @@ msgstr "åŒä¸€ä½œç”¨åŸŸä¸­%qD冗余的é‡å£°æ˜Ž"
#: cp/decl.c:1815 cp/decl.c:1825
#, fuzzy, gcc-internal-format
-#| msgid "previous declaration of %q+D"
msgid "previous declaration of %qD"
msgstr "%q+Dçš„å‰ä¸€ä¸ªå£°æ˜Ž"
@@ -33243,7 +32254,6 @@ msgstr "没有å为%q#T的类模æ¿ï¼Œåœ¨%q#T中 "
#: cp/decl.c:3395
#, fuzzy, gcc-internal-format
-#| msgid "no class template named %q#T in %q#T"
msgid "no type named %q#T in %q#T"
msgstr "没有å为%q#T的类模æ¿ï¼Œåœ¨%q#T中 "
@@ -33299,13 +32309,11 @@ msgstr "有拷è´èµ‹å€¼è¿ç®—符的æˆå‘˜%q+#Dä¸èƒ½ç”¨åœ¨è”åˆä¸­"
#: cp/decl.c:4246
#, fuzzy, gcc-internal-format
-#| msgid "attribute ignored in declaration of %q+#T"
msgid "attribute ignored in declaration of %q#T"
msgstr "属性于%q+#T的声明中被忽略"
#: cp/decl.c:4249
#, fuzzy, gcc-internal-format
-#| msgid "attribute for %q+#T must follow the %qs keyword"
msgid "attribute for %q#T must follow the %qs keyword"
msgstr "%q+#T的属性必须跟在%qs关键字åŽé¢"
@@ -33321,7 +32329,6 @@ msgstr "对 C++ 内建类型%qTçš„é‡å£°æ˜Ž"
#: cp/decl.c:4294
#, fuzzy, gcc-internal-format
-#| msgid "%qs can only be specified for functions"
msgid "%<auto%> can only be specified for variables or function declarations"
msgstr "åªèƒ½ä¸ºå‡½æ•°æŒ‡å®š%qs"
@@ -33372,13 +32379,11 @@ msgstr "%<constexpr%>ä¸èƒ½è¢«ç”¨ä½œç±»åž‹å£°æ˜Ž"
#: cp/decl.c:4378
#, fuzzy, gcc-internal-format
-#| msgid "attributes ignored on template instantiation"
msgid "attribute ignored in explicit instantiation %q#T"
msgstr "属性在模æ¿å®žä¾‹åŒ–上被忽略"
#: cp/decl.c:4381
#, fuzzy, gcc-internal-format
-#| msgid "%qE attribute can only be applied to class definitions"
msgid "no attribute can be applied to an explicit instantiation"
msgstr "åªèƒ½ä¸ºç±»å®šä¹‰åº”用%qE属性"
@@ -33543,7 +32548,6 @@ msgstr "%qTçš„åˆå§‹å€¼è®¾å®šå¿…须在花括å·å†…"
#: cp/decl.c:5260
#, fuzzy, gcc-internal-format
-#| msgid "name %qD used in a GNU-style designated initializer for an array"
msgid "%<[%E] =%> used in a GNU-style designated initializer for class %qT"
msgstr "åå­—%qD用在 GNU 风格的数组指定元素åˆå§‹å€¼è®¾å®šä¸­"
@@ -33590,7 +32594,6 @@ msgstr "å˜é•¿å¤åˆå­—é¢å€¼"
#: cp/decl.c:5632
#, fuzzy, gcc-internal-format
-#| msgid "%qD has incomplete type"
msgid "%q#D has incomplete type"
msgstr "%qD类型ä¸å®Œå…¨"
@@ -33666,19 +32669,16 @@ msgstr ""
#: cp/decl.c:7176
#, fuzzy, gcc-internal-format
-#| msgid "initializer fails to determine size of %qD"
msgid "initializer fails to determine size of %qT"
msgstr "åˆå§‹å€¼è®¾å®šæ— æ³•å†³å®š%qD的大å°"
#: cp/decl.c:7180
#, fuzzy, gcc-internal-format
-#| msgid "array size missing in %qD"
msgid "array size missing in %qT"
msgstr "%qD缺少数组大å°"
#: cp/decl.c:7183
#, fuzzy, gcc-internal-format
-#| msgid "zero-size array %qD"
msgid "zero-size array %qT"
msgstr "大å°ä¸º 0 的数组%qD"
@@ -33795,7 +32795,6 @@ msgstr "%<inline%>ä¸å…许用于å‹å…ƒæ¨¡æ¿ç‰¹ä¾‹åŒ–%qD的声明"
#: cp/decl.c:7499
#, fuzzy, gcc-internal-format
-#| msgid "%<inline%> is not allowed in declaration of friend template specialization %qD"
msgid "%<constexpr%> is not allowed in declaration of friend template specialization %qD"
msgstr "%<inline%>ä¸å…许用于å‹å…ƒæ¨¡æ¿ç‰¹ä¾‹åŒ–%qD的声明"
@@ -33811,7 +32810,6 @@ msgstr "ä¸èƒ½å°†%<::main%>声明为 inline"
#: cp/decl.c:7547
#, fuzzy, gcc-internal-format
-#| msgid "cannot declare %<::main%> to be inline"
msgid "cannot declare %<::main%> to be constexpr"
msgstr "ä¸èƒ½å°†%<::main%>声明为 inline"
@@ -33847,19 +32845,16 @@ msgstr "éžæˆå‘˜å‡½æ•°%qDä¸èƒ½æ‹¥æœ‰ cv é™å®šç¬¦"
#: cp/decl.c:7620
#, fuzzy, gcc-internal-format
-#| msgid "static member function %qD cannot have cv-qualifier"
msgid "static member function %qD cannot have ref-qualifier"
msgstr "æˆå‘˜å‡½æ•°%qDä¸èƒ½æ‹¥æœ‰ cv é™å®šç¬¦"
#: cp/decl.c:7621
#, fuzzy, gcc-internal-format
-#| msgid "non-member function %qD cannot have cv-qualifier"
msgid "non-member function %qD cannot have ref-qualifier"
msgstr "éžæˆå‘˜å‡½æ•°%qDä¸èƒ½æ‹¥æœ‰ cv é™å®šç¬¦"
#: cp/decl.c:7638
#, fuzzy, gcc-internal-format
-#| msgid "template with C linkage"
msgid "literal operator with C linkage"
msgstr "模æ¿æœ‰ C 链接"
@@ -33880,7 +32875,6 @@ msgstr ""
#: cp/decl.c:7667
#, fuzzy, gcc-internal-format
-#| msgid "%qD must be a nonstatic member function"
msgid "%qD must be a non-member function"
msgstr "%qD必须是一个éžé™æ€çš„æˆå‘˜å‡½æ•°"
@@ -33896,13 +32890,11 @@ msgstr "éšå¼å£°æ˜Žçš„%qD的定义"
#: cp/decl.c:7792
#, fuzzy, gcc-internal-format
-#| msgid "definition of implicitly-declared %qD"
msgid "definition of explicitly-defaulted %q+D"
msgstr "éšå¼å£°æ˜Žçš„%qD的定义"
#: cp/decl.c:7793
#, fuzzy, gcc-internal-format
-#| msgid "%q+#D previously defined here"
msgid "%q+#D explicitly defaulted here"
msgstr "%q+#D已在此定义过"
@@ -34017,7 +33009,6 @@ msgstr "数组维数溢出"
#: cp/decl.c:8522
#, fuzzy, gcc-internal-format
-#| msgid "declaration of %qD as array of void"
msgid "declaration of %qD as array of %<auto%>"
msgstr "%qD声明为 void 的数组"
@@ -34073,7 +33064,6 @@ msgstr "声明多维数组必须至少指定除第一维以外所有维的大å°
#: cp/decl.c:8578
#, fuzzy, gcc-internal-format
-#| msgid "creating array of functions"
msgid "array of array of runtime bound"
msgstr "创建函数的数组"
@@ -34144,13 +33134,11 @@ msgstr "函数定义未声明形å‚"
#: cp/decl.c:9014
#, fuzzy, gcc-internal-format
-#| msgid "template declaration of %<typedef%>"
msgid "declaration of %qD as %<typedef%>"
msgstr "%<typedef%>的模æ¿å£°æ˜Ž"
#: cp/decl.c:9019
#, fuzzy, gcc-internal-format
-#| msgid "declaration of %q+D shadows a parameter"
msgid "declaration of %qD as parameter"
msgstr "%q+D的声明éšè—了一个形å‚"
@@ -34326,25 +33314,21 @@ msgstr "%qs声明为返回一个数组的函数"
#: cp/decl.c:9608
#, fuzzy, gcc-internal-format
-#| msgid "%qs function uses %<auto%> type specifier without late return type"
msgid "%qs function uses %<auto%> type specifier without trailing return type"
msgstr "%qs函数使用了%<auto%>类型é™å®šå´æ²¡æœ‰è¿Ÿè¿”回类型"
#: cp/decl.c:9611
#, fuzzy, gcc-internal-format
-#| msgid "scoped enums only available with -std=c++0x or -std=gnu++0x"
msgid "deduced return type only available with -std=c++1y or -std=gnu++1y"
msgstr "带作用域的枚举åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/decl.c:9616
#, fuzzy, gcc-internal-format
-#| msgid "virtual functions cannot be friends"
msgid "virtual function cannot have deduced return type"
msgstr "虚函数ä¸èƒ½æ˜¯å‹å…ƒ"
#: cp/decl.c:9621
#, fuzzy, gcc-internal-format
-#| msgid "%qs function with late return type has %qT as its type rather than plain %<auto%>"
msgid "%qs function with trailing return type has %qT as its type rather than plain %<auto%>"
msgstr "%qs函数使用迟返回类型%qT作为它的类型,而ä¸æ˜¯%<auto%>"
@@ -34357,7 +33341,6 @@ msgstr "å¯å˜å‚数模æ¿åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/decl.c:9635
#, fuzzy, gcc-internal-format
-#| msgid "%qs function with late return type not declared with %<auto%> type specifier"
msgid "%qs function with trailing return type not declared with %<auto%> type specifier"
msgstr "%qs函数使用了迟返回类型å´æœªç”¨%<auto%>类型é™å®šå£°æ˜Ž"
@@ -34368,7 +33351,6 @@ msgstr "æžæž„函数ä¸èƒ½æ˜¯é™æ€æˆå‘˜å‡½æ•°"
#: cp/decl.c:9670
#, fuzzy, gcc-internal-format
-#| msgid "destructor cannot be static member function"
msgid "constructor cannot be static member function"
msgstr "æžæž„函数ä¸èƒ½æ˜¯é™æ€æˆå‘˜å‡½æ•°"
@@ -34379,13 +33361,11 @@ msgstr "æžæž„函数ä¸èƒ½è¢« cv é™å®š"
#: cp/decl.c:9675
#, fuzzy, gcc-internal-format
-#| msgid "destructors may not be cv-qualified"
msgid "constructors may not be cv-qualified"
msgstr "æžæž„函数ä¸èƒ½è¢« cv é™å®š"
#: cp/decl.c:9683
#, fuzzy, gcc-internal-format
-#| msgid "destructors may not be cv-qualified"
msgid "destructors may not be ref-qualified"
msgstr "æžæž„函数ä¸èƒ½è¢« cv é™å®š"
@@ -34447,13 +33427,11 @@ msgstr "ä¸èƒ½å£°æ˜ŽæŒ‡å‘é™å®šå‡½æ•°ç±»åž‹%qT的指针"
#: cp/decl.c:9829
#, fuzzy, gcc-internal-format
-#| msgid "Array reference out of bounds"
msgid "reference to array of runtime bound"
msgstr "对数组的引用超出范围"
#: cp/decl.c:9830
#, fuzzy, gcc-internal-format
-#| msgid "pointer to a function used in subtraction"
msgid "pointer to array of runtime bound"
msgstr "函数指针ä¸èƒ½ç›¸å‡"
@@ -34489,7 +33467,6 @@ msgstr "无法定义æˆå‘˜å‡½æ•°%<%T::%s%>,在%<%T%>中"
#: cp/decl.c:10028
#, fuzzy, gcc-internal-format
-#| msgid "cannot define member function %<%T::%s%> within %<%T%>"
msgid "cannot declare member function %<%T::%s%> within %<%T%>"
msgstr "无法定义æˆå‘˜å‡½æ•°%<%T::%s%>,在%<%T%>中"
@@ -34557,13 +33534,11 @@ msgstr "函数%qsä¸èƒ½è¢«å£°æ˜Žä¸º%<mutable%>"
#: cp/decl.c:10170
#, fuzzy, gcc-internal-format
-#| msgid "parameter declared %<auto%>"
msgid "typedef declared %<auto%>"
msgstr "å½¢å‚声明为%<auto%>"
#: cp/decl.c:10176
#, fuzzy, gcc-internal-format
-#| msgid "creating array of functions"
msgid "typedef naming array of runtime bound"
msgstr "创建函数的数组"
@@ -34624,7 +33599,6 @@ msgstr "ä¸èƒ½åœ¨å‚数声明中使用%<::%>"
#: cp/decl.c:10420
#, fuzzy, gcc-internal-format
-#| msgid "%<this%> may not be used in this context"
msgid "%<auto%> parameter not permitted in this context"
msgstr "%<this%>ä¸èƒ½ç”¨åœ¨æ­¤ä¸Šä¸‹æ–‡ä¸­"
@@ -34635,7 +33609,6 @@ msgstr "å½¢å‚声明为%<auto%>"
#: cp/decl.c:10465
#, fuzzy, gcc-internal-format
-#| msgid "non-static data member %qE declared %<constexpr%>"
msgid "non-static data member declared %<auto%>"
msgstr "éžé™æ€æ•°æ®æˆå‘˜%qE被声明为%<constexpr%>"
@@ -34682,7 +33655,6 @@ msgstr "在构造函数%qD中的å‹å…ƒå£°æ˜Žéœ€è¦é™å®šå"
#: cp/decl.c:10608
#, fuzzy, gcc-internal-format
-#| msgid "field %qD has incomplete type"
msgid "field %qD has incomplete type %qT"
msgstr "字段%qD类型ä¸å®Œå…¨"
@@ -34723,13 +33695,11 @@ msgstr "函数%qs的存储类%<__thread%>无效"
#: cp/decl.c:10747
#, fuzzy, gcc-internal-format
-#| msgid "storage class %<__thread%> invalid for function %qs"
msgid "storage class %<thread_local%> invalid for function %qs"
msgstr "函数%qs的存储类%<__thread%>无效"
#: cp/decl.c:10752
#, fuzzy, gcc-internal-format
-#| msgid "an asm-specification is not allowed on a function-definition"
msgid "virt-specifiers in %qs not allowed outside a class definition"
msgstr "函数定义中ä¸å…许出现 asm 指定"
@@ -34755,7 +33725,6 @@ msgstr "%qs定义在在éžç±»ä½œç”¨åŸŸä¸­"
#: cp/decl.c:10783
#, fuzzy, gcc-internal-format
-#| msgid "%qs defined in a non-class scope"
msgid "%qs declared in a non-class scope"
msgstr "%qs定义在在éžç±»ä½œç”¨åŸŸä¸­"
@@ -34802,7 +33771,6 @@ msgstr "%qs既有%<extern%>åˆæœ‰åˆå§‹å€¼è®¾å®š"
#: cp/decl.c:11032
#, fuzzy, gcc-internal-format
-#| msgid "default argument %qE uses local variable %qD"
msgid "default argument %qE uses %qD"
msgstr "默认实å‚%qE使用了局部å˜é‡%qD"
@@ -34984,7 +33952,6 @@ msgstr "使用模æ¿ç±»åž‹å½¢å‚%qT,在%qsåŽ"
#: cp/decl.c:11915
#, fuzzy, gcc-internal-format
-#| msgid "ambiguous template specialization %qD for %q+D"
msgid "using alias template specialization %qT after %qs"
msgstr "有歧义的模æ¿ç‰¹ä¾‹åŒ–%qD(为%q+D)"
@@ -34995,7 +33962,6 @@ msgstr "使用 typedef å%qD,在%qsåŽ"
#: cp/decl.c:11920
#, fuzzy, gcc-internal-format
-#| msgid "%q+D has a previous declaration here"
msgid "%qD has a previous declaration here"
msgstr "%q+Då…ˆå‰åœ¨æ­¤å¤„有过声明"
@@ -35123,7 +34089,6 @@ msgstr "%qD的枚举值ä¸æ˜¯ä¸€ä¸ªæ•´æ•°å¸¸é‡"
#: cp/decl.c:12928
#, fuzzy, gcc-internal-format
-#| msgid "integer constant is too large for %<unsigned long%> type"
msgid "incremented enumerator value is too large for %<unsigned long%>"
msgstr "对%<unsigned long%>类型而言整数常é‡å¤ªå¤§"
@@ -35134,7 +34099,6 @@ msgstr "%qD处枚举值溢出"
#: cp/decl.c:12960
#, fuzzy, gcc-internal-format
-#| msgid "enumerator value %E is too large for underlying type %<%T%>"
msgid "enumerator value %E is outside the range of underlying type %<%T%>"
msgstr "枚举值 %E 对其类型%<%T%>而言太大了"
@@ -35170,13 +34134,11 @@ msgstr "å½¢å‚%qD被声明为 void"
#: cp/decl.c:13960
#, fuzzy, gcc-internal-format
-#| msgid "no return statement in function returning non-void"
msgid "no return statements in function returning %qT"
msgstr "在有返回值的函数中未å‘现 return 语å¥"
#: cp/decl.c:13962 cp/typeck.c:8384
#, fuzzy, gcc-internal-format
-#| msgid "function return types not compatible due to %<volatile%>"
msgid "only plain %<auto%> return type can be deduced to %<void%>"
msgstr "由于%<volatile%>,函数返回类型ä¸å…¼å®¹"
@@ -35197,7 +34159,6 @@ msgstr "%qD已在类%qT中定义过"
#: cp/decl.c:14531 cp/decl2.c:4673
#, fuzzy, gcc-internal-format
-#| msgid "type of %qD defaults to %<int%>"
msgid "use of %qD before deduction of %<auto%>"
msgstr "%qD的类型默认为%<int%>"
@@ -35218,7 +34179,6 @@ msgstr "%<%T[%T]%>用作数组下标类型无效"
#: cp/decl2.c:449
#, fuzzy, gcc-internal-format
-#| msgid "deleting array %q#D"
msgid "deleting array %q#E"
msgstr "删除数组%q#D"
@@ -35337,7 +34297,6 @@ msgstr "ä½æ®µ%qDéžæ•´åž‹"
#: cp/decl2.c:1388
#, fuzzy, gcc-internal-format
-#| msgid "%qD is not a static data member of a class template"
msgid "%q+D static data member inside of declare target directive"
msgstr "%qDä¸æ˜¯ç±»æ¨¡æ¿çš„éžé™æ€æ•°æ®æˆå‘˜"
@@ -35444,43 +34403,36 @@ msgstr "with"
#: cp/error.c:3474
#, fuzzy, gcc-internal-format
-#| msgid "extended initializer lists only available with -std=c++0x or -std=gnu++0x"
msgid "extended initializer lists only available with -std=c++11 or -std=gnu++11"
msgstr "扩展åˆå§‹å€¼è®¾å®šåˆ—表åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/error.c:3479
#, fuzzy, gcc-internal-format
-#| msgid "explicit conversion operators only available with -std=c++0x or -std=gnu++0x"
msgid "explicit conversion operators only available with -std=c++11 or -std=gnu++11"
msgstr "显å¼è½¬æ¢è¿ç®—符åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/error.c:3484
#, fuzzy, gcc-internal-format
-#| msgid "variadic templates only available with -std=c++0x or -std=gnu++0x"
msgid "variadic templates only available with -std=c++11 or -std=gnu++11"
msgstr "å¯å˜å‚数模æ¿åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/error.c:3489
#, fuzzy, gcc-internal-format
-#| msgid "lambda expressions only available with -std=c++0x or -std=gnu++0x"
msgid "lambda expressions only available with -std=c++11 or -std=gnu++11"
msgstr "Lambda 表达å¼åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/error.c:3494
#, fuzzy, gcc-internal-format
-#| msgid "C++0x auto only available with -std=c++0x or -std=gnu++0x"
msgid "C++11 auto only available with -std=c++11 or -std=gnu++11"
msgstr "C++0x auto åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/error.c:3498
#, fuzzy, gcc-internal-format
-#| msgid "scoped enums only available with -std=c++0x or -std=gnu++0x"
msgid "scoped enums only available with -std=c++11 or -std=gnu++11"
msgstr "带作用域的枚举åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/error.c:3502
#, fuzzy, gcc-internal-format
-#| msgid "defaulted and deleted functions only available with -std=c++0x or -std=gnu++0x"
msgid "defaulted and deleted functions only available with -std=c++11 or -std=gnu++11"
msgstr "默认化和被删除的函数åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
@@ -35491,25 +34443,21 @@ msgstr "å¯å˜å‚数模æ¿åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/error.c:3512
#, fuzzy, gcc-internal-format
-#| msgid "explicit conversion operators only available with -std=c++0x or -std=gnu++0x"
msgid "override controls (override/final) only available with -std=c++11 or -std=gnu++11"
msgstr "显å¼è½¬æ¢è¿ç®—符åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/error.c:3517
#, fuzzy, gcc-internal-format
-#| msgid "extended initializer lists only available with -std=c++0x or -std=gnu++0x"
msgid "non-static data member initializers only available with -std=c++11 or -std=gnu++11"
msgstr "扩展åˆå§‹å€¼è®¾å®šåˆ—表åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/error.c:3522
#, fuzzy, gcc-internal-format
-#| msgid "extended initializer lists only available with -std=c++0x or -std=gnu++0x"
msgid "user-defined literals only available with -std=c++11 or -std=gnu++11"
msgstr "扩展åˆå§‹å€¼è®¾å®šåˆ—表åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/error.c:3527
#, fuzzy, gcc-internal-format
-#| msgid "explicit conversion operators only available with -std=c++0x or -std=gnu++0x"
msgid "delegating constructors only available with -std=c++11 or -std=gnu++11"
msgstr "显å¼è½¬æ¢è¿ç®—符åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
@@ -35520,13 +34468,11 @@ msgstr "å¯å˜å‚数模æ¿åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/error.c:3537
#, fuzzy, gcc-internal-format
-#| msgid "C++0x auto only available with -std=c++0x or -std=gnu++0x"
msgid "c++11 attributes only available with -std=c++11 or -std=gnu++11"
msgstr "C++0x auto åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/error.c:3542
#, fuzzy, gcc-internal-format
-#| msgid "scoped enums only available with -std=c++0x or -std=gnu++0x"
msgid "ref-qualifiers only available with -std=c++11 or -std=gnu++11"
msgstr "带作用域的枚举åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
@@ -35599,19 +34545,16 @@ msgstr " 在抛出的表达å¼ä¸­"
#: cp/except.c:987
#, fuzzy, gcc-internal-format
-#| msgid "cannot declare parameter %q+D to be of abstract type %qT"
msgid "cannot declare catch parameter to be of rvalue reference type %qT"
msgstr "ä¸èƒ½å°†å½¢å‚%q+D声明为具有抽象类型%qT"
#: cp/except.c:994
#, fuzzy, gcc-internal-format
-#| msgid "cannot create type information for type %qT because it involves types of variable size"
msgid "cannot throw expression of type %qT because it involves types of variable size"
msgstr "无法为类型%qT创建类型信æ¯ï¼Œå› ä¸ºå®ƒçš„大å°æ˜¯å¯å˜çš„"
#: cp/except.c:997
#, fuzzy, gcc-internal-format
-#| msgid "cannot create type information for type %qT because it involves types of variable size"
msgid "cannot catch type %qT because it involves types of variable size"
msgstr "无法为类型%qT创建类型信æ¯ï¼Œå› ä¸ºå®ƒçš„大å°æ˜¯å¯å˜çš„"
@@ -35726,7 +34669,6 @@ msgstr "(如果这ä¸æ˜¯æ‚¨åŽŸæ¥çš„想法,请确定此函数模æ¿å·²ç»å£°æ˜
#: cp/init.c:378
#, fuzzy, gcc-internal-format
-#| msgid "invalid application of %qs to incomplete type %qT "
msgid "value-initialization of incomplete type %qT"
msgstr "%qsä¸èƒ½ç”¨äºŽä¸å®Œå…¨çš„类型%qT"
@@ -35737,13 +34679,11 @@ msgstr "å½¢å‚%qD包å«äº†æŒ‡å‘具有未知边界数组%qT的指针"
#: cp/init.c:482
#, fuzzy, gcc-internal-format
-#| msgid "value-initialization of reference"
msgid "value-initialization of function type %qT"
msgstr "引用被值所åˆå§‹åŒ–"
#: cp/init.c:488
#, fuzzy, gcc-internal-format
-#| msgid "value-initialization of reference"
msgid "value-initialization of reference type %qT"
msgstr "引用被值所åˆå§‹åŒ–"
@@ -35759,7 +34699,6 @@ msgstr "%qD应该在æˆå‘˜åˆå§‹åŒ–列表中被åˆå§‹åŒ–"
#: cp/init.c:585
#, fuzzy, gcc-internal-format
-#| msgid "%qD is used uninitialized in this function"
msgid "%qD is initialized with itself"
msgstr "此函数中的%qD在使用å‰æœªåˆå§‹åŒ–"
@@ -35910,7 +34849,6 @@ msgstr "未åˆå§‹åŒ–的引用æˆå‘˜%qD"
#: cp/init.c:2147
#, fuzzy, gcc-internal-format
-#| msgid "uninitialized reference member in %q#T"
msgid "uninitialized reference member in base %q#T of %q#T"
msgstr "%q#T中有未åˆå§‹åŒ–的引用æˆå‘˜"
@@ -35936,25 +34874,21 @@ msgstr "%q#T中有未åˆå§‹åŒ–的引用æˆå‘˜"
#: cp/init.c:2317
#, fuzzy, gcc-internal-format
-#| msgid "integer overflow in expression"
msgid "integer overflow in array size"
msgstr "整数溢出"
#: cp/init.c:2327
#, fuzzy, gcc-internal-format
-#| msgid "Variable '%s' at %L in this context must be constant"
msgid "array size in operator new must be constant"
msgstr "å˜é‡â€˜%s’在%L处上下文中必须是常é‡"
#: cp/init.c:2341
#, fuzzy, gcc-internal-format
-#| msgid "variably modified field at file scope"
msgid "variably modified type not allowed in operator new"
msgstr "文件域中的动æ€å¯å˜å­—段"
#: cp/init.c:2355
#, fuzzy, gcc-internal-format
-#| msgid "ISO C does not support saturating types"
msgid "ISO C++ does not support variable-length array types"
msgstr "ISO C ä¸æ”¯æŒé¥±å’Œç±»åž‹"
@@ -35970,7 +34904,6 @@ msgstr "%<new%>%q#T时常é‡æœªåˆå§‹åŒ–"
#: cp/init.c:2477
#, fuzzy, gcc-internal-format
-#| msgid "not a valid Java .class file"
msgid "%qT isn%'t a valid Java class type"
msgstr "ä¸æ˜¯ä¸€ä¸ªæœ‰æ•ˆçš„ Java .class 文件。"
@@ -35996,7 +34929,6 @@ msgstr "对æˆå‘˜%qD的请求有歧义"
#: cp/init.c:2775
#, fuzzy, gcc-internal-format
-#| msgid "attributes after parenthesized initializer ignored"
msgid "parenthesized initializer in array new"
msgstr "括起的åˆå§‹å€¼è®¾å®šåŽå‡ºçŽ°çš„属性被忽略"
@@ -36027,7 +34959,6 @@ msgstr "%qT中找ä¸åˆ°%<class$%>"
#: cp/init.c:3158
#, fuzzy, gcc-internal-format
-#| msgid "possible problem detected in invocation of delete operator:"
msgid "possible problem detected in invocation of delete [] operator:"
msgstr "检测到调用 delete è¿ç®—符时å¯èƒ½å‡ºçŽ°çš„问题:"
@@ -36088,7 +35019,6 @@ msgstr ""
#: cp/lambda.c:477
#, fuzzy, gcc-internal-format
-#| msgid "compound literal has variable size"
msgid "because the array element type %qT has variable size"
msgstr "å¤åˆå­—é¢å€¼æœ‰å¯å˜çš„大å°"
@@ -36099,7 +35029,6 @@ msgstr "无法通过引用æ•èŽ·%qE"
#: cp/lambda.c:514
#, fuzzy, gcc-internal-format
-#| msgid "already captured %<this%> in lambda expression"
msgid "already captured %qD in lambda expression"
msgstr "å·²ç»åœ¨ Lambda 表达å¼ä¸­æ•èŽ·äº†%<this%>"
@@ -36170,7 +35099,6 @@ msgstr "修饰 typeof,请改用 decltype"
#: cp/mangle.c:2116
#, fuzzy, gcc-internal-format
-#| msgid "mangling unknown fixed point type"
msgid "mangling __underlying_type"
msgstr "修饰未知的定点类型"
@@ -36206,7 +35134,6 @@ msgstr "%qD修饰åŽçš„å字将在 GCC 的未æ¥ç‰ˆæœ¬ä¸­æœ‰å˜åŒ–"
#: cp/mangle.c:3500
#, fuzzy, gcc-internal-format
-#| msgid "-fabi-version=4 (or =0) avoids this error with a change in vector mangling"
msgid "-fabi-version=6 (or =0) avoids this error with a change in mangling"
msgstr "-fabi-version=4 (or =0) å¯ä»¥æ”¹å˜å‘é‡ä¿®é¥°æ¥é¿å…这个错误"
@@ -36237,13 +35164,11 @@ msgstr "未åˆå§‹åŒ–çš„æˆå‘˜%qD具有%<const%>类型%qT"
#: cp/method.c:1010
#, fuzzy, gcc-internal-format
-#| msgid "a destructor cannot be %<constexpr%>"
msgid "defaulted constructor calls non-constexpr %q+D"
msgstr "æžæž„函数ä¸èƒ½æ˜¯%<constexpr%>"
#: cp/method.c:1071
#, fuzzy, gcc-internal-format
-#| msgid "uninitialized const %qD is invalid in C++"
msgid "initializer for %q+#D is invalid"
msgstr "未åˆå§‹åŒ–的常é‡%qD在C++中是无效的"
@@ -36264,7 +35189,6 @@ msgstr ""
#: cp/method.c:1128
#, fuzzy, gcc-internal-format
-#| msgid "non-static data member %qD has Java class type"
msgid "copying non-static data member %q#D of rvalue reference type"
msgstr "éžé™æ€æ•°æ®æˆå‘˜%qD具有 Java 类类型"
@@ -36315,7 +35239,6 @@ msgstr "ä¸åŒ¹é…%qD预期的签å"
#: cp/method.c:1814
#, fuzzy, gcc-internal-format
-#| msgid "function %q+D defaulted on its first declaration must not have an exception-specification"
msgid "function %q+D defaulted on its redeclaration with an exception-specification that differs from the implicit declaration %q#D"
msgstr "首次声明时被默认化的函数%q+Dä¸å¯ä»¥æŒ‡å®šå¼‚常"
@@ -36326,7 +35249,6 @@ msgstr ""
#: cp/method.c:1860
#, fuzzy, gcc-internal-format
-#| msgid "%qD cannot be defaulted"
msgid "a template cannot be defaulted"
msgstr "%qDä¸èƒ½è¢«é»˜è®¤åŒ–"
@@ -36347,13 +35269,11 @@ msgstr "由于éšå¼çš„虚æžæž„函数,类%qTçš„ vtable 布局å¯èƒ½ä¸Ž ABI ä¸
#: cp/name-lookup.c:567
#, fuzzy, gcc-internal-format
-#| msgid "%q#D conflicts with previous using declaration %q#D"
msgid "%q#D conflicts with a previous declaration"
msgstr "%q#D与先å‰çš„ using 声明%q#D冲çª"
#: cp/name-lookup.c:569
#, fuzzy, gcc-internal-format
-#| msgid "previous declaration %q+D"
msgid "previous declaration %q+#D"
msgstr "å…ˆå‰çš„声明%q+D"
@@ -36420,7 +35340,6 @@ msgstr "%q#D的声明éšè—了一个形å‚"
#: cp/name-lookup.c:1189
#, fuzzy, gcc-internal-format
-#| msgid "declaration of %q+D shadows a parameter"
msgid "declaration of %qD shadows a lambda capture"
msgstr "%q+D的声明éšè—了一个形å‚"
@@ -36629,7 +35548,6 @@ msgstr "%qDåšäº†å¤šæ¬¡å¤æœ¬"
#: cp/parser.c:792
#, fuzzy, gcc-internal-format
-#| msgid "identifier %qE will become a keyword in C++0x"
msgid "identifier %qE is a keyword in C++11"
msgstr "标志符%qE将会æˆä¸º C++0x 的一个关键字"
@@ -36730,7 +35648,6 @@ msgstr "%qTä¸æ˜¯ä¸€ä¸ªæ¨¡æ¿"
#: cp/parser.c:2719
#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a template"
msgid "%qE is not a class template"
msgstr "%qEä¸æ˜¯ä¸€ä¸ªæ¨¡æ¿"
@@ -36811,7 +35728,6 @@ msgstr "%qDä¸èƒ½å‡ºçŽ°åœ¨å¸¸é‡è¡¨è¾¾å¼ä¸­"
#: cp/parser.c:2809
#, fuzzy, gcc-internal-format
-#| msgid "a function call cannot appear in a constant-expression"
msgid "a transaction expression cannot appear in a constant-expression"
msgstr "函数调用ä¸èƒ½å‡ºçŽ°åœ¨å¸¸é‡è¡¨è¾¾å¼ä¸­"
@@ -36844,7 +35760,6 @@ msgstr "%qEä¸æ˜¯ä¸€ä¸ªç±»åž‹å"
#: cp/parser.c:2903
#, fuzzy, gcc-internal-format
-#| msgid "C++0x %<constexpr%> only available with -std=c++0x or -std=gnu++0x"
msgid "C++11 %<constexpr%> only available with -std=c++11 or -std=gnu++11"
msgstr "C++0x %<constexpr%>åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
@@ -36855,7 +35770,6 @@ msgstr "(也许您本æ„是想用%<typename %T::%E%>)"
#: cp/parser.c:2948
#, fuzzy, gcc-internal-format
-#| msgid "%qE in namespace %qE does not name a type"
msgid "%qE in namespace %qE does not name a template type"
msgstr "%qEä¸æ˜¯å‘½å空间%qE中的一个类型å"
@@ -36882,13 +35796,11 @@ msgstr "%<%T::%E%>之å‰éœ€è¦%<typename%>,因为%qT是一个有ä¾èµ–的作ç”
#: cp/parser.c:2974
#, fuzzy, gcc-internal-format
-#| msgid "%qE in class %qT does not name a type"
msgid "%qE in %q#T does not name a template type"
msgstr "%qEä¸æ˜¯ç±»%qT中的一个类型å"
#: cp/parser.c:2978
#, fuzzy, gcc-internal-format
-#| msgid "%qE in class %qT does not name a type"
msgid "%qE in %q#T does not name a type"
msgstr "%qEä¸æ˜¯ç±»%qT中的一个类型å"
@@ -36914,25 +35826,21 @@ msgstr ""
#: cp/parser.c:3867
#, fuzzy, gcc-internal-format
-#| msgid "floating constant exceeds range of %qT"
msgid "integer literal exceeds range of %qT type"
msgstr "浮点常é‡è¶…出%qT的范围"
#: cp/parser.c:3873
#, fuzzy, gcc-internal-format
-#| msgid "floating constant exceeds range of %qT"
msgid "floating literal exceeds range of %qT type"
msgstr "浮点常é‡è¶…出%qT的范围"
#: cp/parser.c:3877
#, fuzzy, gcc-internal-format
-#| msgid "floating constant truncated to zero"
msgid "floating literal truncated to zero"
msgstr "浮点常é‡å‘零截断"
#: cp/parser.c:3920
#, fuzzy, gcc-internal-format
-#| msgid "unable to find a register to spill in class %qs"
msgid "unable to find numeric literal operator %qD"
msgstr "在类%qs中找ä¸åˆ°å¯æº¢å‡ºçš„寄存器"
@@ -36943,7 +35851,6 @@ msgstr ""
#: cp/parser.c:3969
#, fuzzy, gcc-internal-format
-#| msgid "unable to find a register to spill in class %qs"
msgid "unable to find string literal operator %qD"
msgstr "在类%qs中找ä¸åˆ°å¯æº¢å‡ºçš„寄存器"
@@ -37004,7 +35911,6 @@ msgstr "%<~%>å‰çš„作用域%qTä¸æ˜¯ä¸€ä¸ªç±»å"
#: cp/parser.c:4935 cp/parser.c:6785
#, fuzzy, gcc-internal-format
-#| msgid "C++0x auto only available with -std=c++0x or -std=gnu++0x"
msgid "%<~auto%> only available with -std=c++1y or -std=gnu++1y"
msgstr "C++0x auto åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
@@ -37035,7 +35941,6 @@ msgstr "嵌套å指定中使用了ä¸å®Œå…¨çš„类型%qT"
#: cp/parser.c:5276
#, fuzzy, gcc-internal-format
-#| msgid "%qT resolves to %qT, which is not an enumeration type"
msgid "decltype evaluates to %qT, which is not a class or enumeration type"
msgstr "%qT被解æžåˆ°éžæžšä¸¾ç±»åž‹%qT"
@@ -37076,7 +35981,6 @@ msgstr ""
#: cp/parser.c:6368
#, fuzzy, gcc-internal-format
-#| msgid "-client_name not allowed with -dynamiclib"
msgid "braced list index is not allowed with array notation"
msgstr "-client_name ä¸èƒ½å’Œ -dynamiclib 一起使用"
@@ -37092,7 +35996,6 @@ msgstr "错误地使用了%qD"
#: cp/parser.c:6558
#, fuzzy, gcc-internal-format
-#| msgid "%<%D::%D%> is not a member of %qT"
msgid "%<%D::%D%> is not a class member"
msgstr "%<%D::%D%>ä¸æ˜¯%qTçš„æˆå‘˜"
@@ -37113,7 +36016,6 @@ msgstr "类型ä¸èƒ½å®šä¹‰åœ¨%<decltype%>中"
#: cp/parser.c:7262
#, fuzzy, gcc-internal-format
-#| msgid "types may not be defined in a new-type-id"
msgid "types may not be defined in a new-expression"
msgstr "类型ä¸èƒ½å®šä¹‰åœ¨ new-type-id 中"
@@ -37144,7 +36046,6 @@ msgstr "使用旧å¼çš„类型转æ¢"
#: cp/parser.c:7891
#, fuzzy, gcc-internal-format
-#| msgid "%<>>%> operator will be treated as two right angle brackets in C++0x"
msgid "%<>>%> operator is treated as two right angle brackets in C++11"
msgstr "%<>>%>è¿ç®—符在 C++0x 中将被认为是两个å³å°–括å·"
@@ -37175,7 +36076,6 @@ msgstr ""
#: cp/parser.c:8901
#, fuzzy, gcc-internal-format
-#| msgid "lambda expressions only available with -std=c++0x or -std=gnu++0x"
msgid "lambda capture initializers only available with -std=c++1y or -std=gnu++1y"
msgstr "Lambda 表达å¼åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
@@ -37186,13 +36086,11 @@ msgstr ""
#: cp/parser.c:8931
#, fuzzy, gcc-internal-format
-#| msgid "increment of read-only variable %qD"
msgid "capture of non-variable %qD "
msgstr "令åªè¯»å˜é‡%qD自增"
#: cp/parser.c:8933 cp/parser.c:8942 cp/semantics.c:3237
#, fuzzy, gcc-internal-format
-#| msgid "%q+D declared here"
msgid "%q+#D declared here"
msgstr "%q+D已在此声明过"
@@ -37213,7 +36111,6 @@ msgstr ""
#: cp/parser.c:9027
#, fuzzy, gcc-internal-format
-#| msgid "variadic templates only available with -std=c++0x or -std=gnu++0x"
msgid "lambda templates are only available with -std=c++1y or -std=gnu++1y"
msgstr "å¯å˜å‚数模æ¿åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
@@ -37224,7 +36121,6 @@ msgstr "为 lambda å½¢å‚指定了默认å‚æ•°"
#: cp/parser.c:9485
#, fuzzy, gcc-internal-format
-#| msgid "attributes after parenthesized initializer ignored"
msgid "attributes at the beginning of statement are ignored"
msgstr "括起的åˆå§‹å€¼è®¾å®šåŽå‡ºçŽ°çš„属性被忽略"
@@ -37250,7 +36146,6 @@ msgstr "%<%T::%D%>命å了一个构造函数而éžç±»åž‹"
#: cp/parser.c:9692
#, fuzzy, gcc-internal-format
-#| msgid "%qD is not a constexpr function"
msgid "compound-statement in constexpr function"
msgstr "%qDä¸æ˜¯ä¸€ä¸ªå¹¿ä¹‰å¸¸å‡½æ•°"
@@ -37266,7 +36161,6 @@ msgstr "类型ä¸èƒ½å®šä¹‰åœ¨æ¡ä»¶è¡¨è¾¾å¼ä¸­"
#: cp/parser.c:10305
#, fuzzy, gcc-internal-format
-#| msgid "expression statement has incomplete type"
msgid "range-based %<for%> expression of type %qT has incomplete type"
msgstr "表达å¼è¯­å¥ç±»åž‹ä¸å®Œå…¨"
@@ -37292,13 +36186,11 @@ msgstr "需è¦å¾ªçŽ¯è¯­å¥"
#: cp/parser.c:10568
#, fuzzy, gcc-internal-format
-#| msgid "range-based-for loops are not allowed in C++98 mode"
msgid "range-based %<for%> loops are not allowed in C++98 mode"
msgstr "C++98 模å¼ä¸‹ä¸å…许使用基于范围的 for 循环"
#: cp/parser.c:10642
#, fuzzy, gcc-internal-format
-#| msgid "break statement used with OpenMP for loop"
msgid "break statement used with Cilk Plus for loop"
msgstr "OpenMP for 循环中使用了 break 语å¥"
@@ -37337,7 +36229,6 @@ msgstr "%<friend%>用在类外"
#. we're complaining about C++0x compatibility.
#: cp/parser.c:11485
#, fuzzy, gcc-internal-format
-#| msgid "%<auto%> will change meaning in C++0x; please remove it"
msgid "%<auto%> changes meaning in C++11; please remove it"
msgstr "%<auto%>的语义在 C++0x 中将被改å˜ï¼›è¯·è€ƒè™‘删除它"
@@ -37368,7 +36259,6 @@ msgstr "类型ä¸èƒ½å®šä¹‰åœ¨%<decltype%>中"
#: cp/parser.c:12122
#, fuzzy, gcc-internal-format
-#| msgid "types may not be defined in a new-type-id"
msgid "types may not be defined in a conversion-type-id"
msgstr "类型ä¸èƒ½å®šä¹‰åœ¨ new-type-id 中"
@@ -37379,7 +36269,6 @@ msgstr "在转æ¢è¿ç®—符中使用%<auto%>无效"
#: cp/parser.c:12153
#, fuzzy, gcc-internal-format
-#| msgid "invalid use of %<auto%> in conversion operator"
msgid "use of %<auto%> in member template conversion operator can never be deduced"
msgstr "在转æ¢è¿ç®—符中使用%<auto%>无效"
@@ -37395,7 +36284,6 @@ msgstr "无法从æˆå‘˜%<%D%>中扩展åˆå§‹å€¼"
#: cp/parser.c:12276
#, fuzzy, gcc-internal-format
-#| msgid "static declaration of %q+D follows non-static declaration"
msgid "mem-initializer for %qD follows constructor delegation"
msgstr "对%qDçš„é™æ€å£°æ˜Žå‡ºçŽ°åœ¨éžé™æ€å£°æ˜Žä¹‹åŽ"
@@ -37421,7 +36309,6 @@ msgstr "二元æ“作中中æ“作数无效"
#: cp/parser.c:12737 cp/parser.c:12784
#, fuzzy, gcc-internal-format
-#| msgid "expected a string after %<#pragma message%>"
msgid "expected empty string after %<operator%> keyword"
msgstr "%<#pragma message%>åŽéœ€è¦ä¸€ä¸ªå­—符串"
@@ -37432,7 +36319,6 @@ msgstr ""
#: cp/parser.c:12761
#, fuzzy, gcc-internal-format
-#| msgid "expected identifier"
msgid "expected suffix identifier"
msgstr "需è¦æ ‡è¯†ç¬¦"
@@ -37484,7 +36370,6 @@ msgstr "%<<:%>是%<[%>çš„å¦ä¸€ç§æ‹¼æ³•ã€‚请在%<<%>å’Œ%<::%>间加上空格"
#: cp/parser.c:13403
#, fuzzy, gcc-internal-format
-#| msgid "(if you use %<-fpermissive%> G++ will accept your code)"
msgid "(if you use %<-fpermissive%> or %<-std=c++11%>, or %<-std=gnu++11%> G++ will accept your code)"
msgstr "(如果您使用%<-fpermissive%>G++ 会接å—您的代ç )"
@@ -37547,19 +36432,16 @@ msgstr "需è¦ç±»åž‹é™å®š"
#: cp/parser.c:14510
#, fuzzy, gcc-internal-format
-#| msgid "defaulted and deleted functions only available with -std=c++0x or -std=gnu++0x"
msgid "use of %<auto%> in lambda parameter declaration only available with -std=c++1y or -std=gnu++1y"
msgstr "默认化和被删除的函数åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/parser.c:14516
#, fuzzy, gcc-internal-format
-#| msgid "defaulted and deleted functions only available with -std=c++0x or -std=gnu++0x"
msgid "use of %<auto%> in parameter declaration only available with -std=c++1y or -std=gnu++1y"
msgstr "默认化和被删除的函数åªåœ¨ -std=c++0x 或 -std=gnu++0x 下å¯ç”¨"
#: cp/parser.c:14521
#, fuzzy, gcc-internal-format
-#| msgid "ISO C forbids forward parameter declarations"
msgid "ISO C++ forbids use of %<auto%> in parameter declaration"
msgstr "ISO C ä¸å…许å‰å‘å‚数声明"
@@ -37640,7 +36522,6 @@ msgstr "%q#T多次定义"
#: cp/parser.c:15524
#, fuzzy, gcc-internal-format
-#| msgid "ISO C++ forbids incrementing an enum"
msgid "ISO C++ forbids empty anonymous enum"
msgstr "ISO C++ ä¸å…许枚举自增"
@@ -37681,7 +36562,6 @@ msgstr ""
#: cp/parser.c:16101
#, fuzzy, gcc-internal-format
-#| msgid "types may not be defined in exception-declarations"
msgid "types may not be defined in alias template declarations"
msgstr "类型ä¸èƒ½å®šä¹‰åœ¨å¼‚常声明中"
@@ -37764,7 +36644,6 @@ msgstr "无效的声明"
#. function.
#: cp/parser.c:17476
#, fuzzy, gcc-internal-format
-#| msgid "invalid type in declaration"
msgid "qualified-id in declaration"
msgstr "声明中有无效类型"
@@ -37780,7 +36659,6 @@ msgstr "%qD是一个命å空间"
#: cp/parser.c:17605
#, fuzzy, gcc-internal-format
-#| msgid "creating pointer to member of non-class type %qT"
msgid "cannot form pointer to member of non-class %q#T"
msgstr "生æˆéžç±»ç±»åž‹%qTçš„æˆå‘˜æŒ‡é’ˆ"
@@ -37796,13 +36674,11 @@ msgstr "é‡å¤çš„ cv é™å®š"
#: cp/parser.c:17739
#, fuzzy, gcc-internal-format
-#| msgid "duplicate cv-qualifier"
msgid "multiple ref-qualifiers"
msgstr "é‡å¤çš„ cv é™å®š"
#: cp/parser.c:17797
#, fuzzy, gcc-internal-format
-#| msgid "duplicate cv-qualifier"
msgid "duplicate virt-specifier"
msgstr "é‡å¤çš„ cv é™å®š"
@@ -37843,13 +36719,11 @@ msgstr "默认å‚æ•°åªå…许出现在函数å‚数中"
#: cp/parser.c:18594
#, fuzzy, gcc-internal-format
-#| msgid "%H%sparameter pack %qD cannot have a default argument"
msgid "parameter pack %qD cannot have a default argument"
msgstr "%H%s模æ¿å‚数包%qDä¸èƒ½æœ‰é»˜è®¤å‚æ•°"
#: cp/parser.c:18602
#, fuzzy, gcc-internal-format
-#| msgid "%H%sparameter pack cannot have a default argument"
msgid "parameter pack cannot have a default argument"
msgstr "%H%s模æ¿å‚数包ä¸èƒ½æœ‰é»˜è®¤å‚æ•°"
@@ -37860,7 +36734,6 @@ msgstr "ISO C++ ä¸å…许指定元素åˆå§‹å€¼è®¾å®š"
#: cp/parser.c:18907
#, fuzzy, gcc-internal-format
-#| msgid "ISO C++ does not allow designated initializers"
msgid "ISO C++ does not allow C99 designated initializers"
msgstr "ISO C++ ä¸å…许指定元素åˆå§‹å€¼è®¾å®š"
@@ -37891,7 +36764,6 @@ msgstr "需è¦%<{%>或%<:%>"
#: cp/parser.c:19667
#, fuzzy, gcc-internal-format
-#| msgid "cannot find file for class %s"
msgid "cannot specify %<override%> for a class"
msgstr "无法为类 %s 找到文件"
@@ -37942,7 +36814,6 @@ msgstr "需è¦ç±»å"
#: cp/parser.c:20181
#, fuzzy, gcc-internal-format
-#| msgid "a class-key must be used when declaring a friend"
msgid "in C++03 a class-key must be used when declaring a friend"
msgstr "声明å‹å…ƒæ—¶å¿…须使用 class 关键字"
@@ -38018,7 +36889,6 @@ msgstr "类型ä¸èƒ½å®šä¹‰åœ¨å¼‚常声明中"
#: cp/parser.c:21749
#, fuzzy, gcc-internal-format
-#| msgid "expected identifier or %<(%>"
msgid "expected an identifier for the attribute name"
msgstr "需è¦æ ‡è¯†ç¬¦æˆ–%<(%>"
@@ -38113,13 +36983,11 @@ msgstr "ISO C++ 1998 ä¸æ”¯æŒ%<long long%>"
#: cp/parser.c:24031
#, fuzzy, gcc-internal-format
-#| msgid "both %<_Sat%> and %<char%> in declaration specifiers"
msgid "both %<__thread%> and %<thread_local%> specified"
msgstr "声明中åŒæ—¶ä½¿ç”¨äº†%<_Sat%>å’Œ%<char%>"
#: cp/parser.c:24033
#, fuzzy, gcc-internal-format
-#| msgid "duplicate %qE"
msgid "duplicate %qD"
msgstr "é‡å¤çš„%qE"
@@ -38225,13 +37093,11 @@ msgstr "需è¦%<@throw%>"
#: cp/parser.c:24157
#, fuzzy, gcc-internal-format
-#| msgid "expected %<static_assert%>"
msgid "expected %<__transaction_atomic%>"
msgstr "需è¦%<static_assert%>"
#: cp/parser.c:24160
#, fuzzy, gcc-internal-format
-#| msgid "expected %<static_assert%>"
msgid "expected %<__transaction_relaxed%>"
msgstr "需è¦%<static_assert%>"
@@ -38272,7 +37138,6 @@ msgstr "使用了%qs标记,在命å%q#Tæ—¶"
#: cp/parser.c:24488
#, fuzzy, gcc-internal-format
-#| msgid "previously declared here"
msgid "%q#T was previously declared here"
msgstr "以å‰åœ¨æ­¤å£°æ˜Žè¿‡"
@@ -38283,7 +37148,6 @@ msgstr "%qDé‡å£°æ˜Žæ—¶æœ‰ä¸åŒçš„å¯è®¿é—®æ€§"
#: cp/parser.c:24528
#, fuzzy, gcc-internal-format
-#| msgid "%<template%> (as a disambiguator) is only allowed within templates"
msgid "in C++98 %<template%> (as a disambiguator) is only allowed within templates"
msgstr "用作消歧义的%<template%>åªèƒ½ç”¨äºŽæ¨¡æ¿å†…"
@@ -38354,7 +37218,6 @@ msgstr "%q+D的抽象类型无效"
#: cp/parser.c:27475
#, fuzzy, gcc-internal-format
-#| msgid "invalid initializer"
msgid "invalid reduction-identifier"
msgstr "无效的åˆå§‹å€¼è®¾å®š"
@@ -38365,7 +37228,6 @@ msgstr "括起的åˆå§‹åŒ–ä¸å…许使用在 OpenMP %<for%>循环中"
#: cp/parser.c:29045
#, fuzzy, gcc-internal-format
-#| msgid "parenthesized initialization is not allowed in OpenMP %<for%> loop"
msgid "parenthesized initialization is not allowed in for-loop"
msgstr "括起的åˆå§‹åŒ–ä¸å…许使用在 OpenMP %<for%>循环中"
@@ -38381,13 +37243,11 @@ msgstr "循环折å å¾—ä¸å¤Ÿ"
#: cp/parser.c:30334
#, fuzzy, gcc-internal-format
-#| msgid "attributes are not allowed on a function-definition"
msgid "vector attribute not immediately followed by a single function declaration or definition"
msgstr "函数定义中ä¸å…许有属性"
#: cp/parser.c:30561
#, fuzzy, gcc-internal-format
-#| msgid "invalid initializer"
msgid "invalid initializer clause"
msgstr "无效的åˆå§‹å€¼è®¾å®š"
@@ -38403,13 +37263,11 @@ msgstr ""
#: cp/parser.c:30678
#, fuzzy, gcc-internal-format
-#| msgid "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, %<|%>, %<&&%>, or %<||%>"
msgid "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, %<|%>, %<&&%>, %<||%> or identifier"
msgstr "需è¦%<+%>ã€%<*%>ã€%<-%>ã€%<&%>ã€%<^%>ã€%<|%>ã€%<&&%>或%<||%>"
#: cp/parser.c:30697
#, fuzzy, gcc-internal-format
-#| msgid "new types may not be defined in a return type"
msgid "types may not be defined in declare reduction type list"
msgstr "ä¸èƒ½åœ¨è¿”回类型中定义新类型"
@@ -38450,7 +37308,6 @@ msgstr "%<#pragma GCC pch_preprocess%>末尾有垃圾字符"
#: cp/parser.c:31479
#, fuzzy, gcc-internal-format
-#| msgid "#pragma GCC optimize is not allowed inside functions"
msgid "%<#pragma simd%> must be inside a function"
msgstr "#pragma GCC optimize ä¸å…许用在函数中"
@@ -38461,19 +37318,16 @@ msgstr "模å—间优化未为 C++ 实现"
#: cp/parser.c:31650
#, fuzzy, gcc-internal-format
-#| msgid "Expected variable name at %C"
msgid "expected variable-name"
msgstr "在%C处需è¦å˜é‡å"
#: cp/parser.c:31714
#, fuzzy, gcc-internal-format
-#| msgid "expected %<,%> or %<)%>"
msgid "expected %<,%> or %<)%> after %qE"
msgstr "éœ€è¦ %<,%> 或 %<)%>"
#: cp/parser.c:31996
#, fuzzy, gcc-internal-format
-#| msgid "templates may not be %<virtual%>"
msgid "implicit templates may not be %<virtual%>"
msgstr "模æ¿ä¸èƒ½æ˜¯%<virtual%>çš„"
@@ -38524,7 +37378,6 @@ msgstr "ç±»åéšè—了模æ¿çš„模æ¿å½¢å‚%qD"
#: cp/pt.c:831
#, fuzzy, gcc-internal-format
-#| msgid "declaration of template %q#D"
msgid "specialization of alias template %qD"
msgstr "模æ¿å£°æ˜Ž%q#D"
@@ -38562,13 +37415,11 @@ msgstr "%qD的特例化在实例化之åŽ"
#: cp/pt.c:1769
#, fuzzy, gcc-internal-format
-#| msgid "candidate is: %+#D"
msgid "candidate is: %#D"
msgstr "备选为:%+#D"
#: cp/pt.c:1776 cp/semantics.c:4775
#, fuzzy, gcc-internal-format
-#| msgid "%s %+#D"
msgid "%s %#D"
msgstr "%s %+#D"
@@ -38599,7 +37450,6 @@ msgstr "%qDä¸æ˜¯ç±»æ¨¡æ¿çš„éžé™æ€æ•°æ®æˆå‘˜"
#: cp/pt.c:2299
#, fuzzy, gcc-internal-format
-#| msgid "wrong number of template arguments (%d, should be %d)"
msgid "too many template headers for %D (should be %d)"
msgstr "模æ¿å‚æ•°æ•°ç›®ä¸å¯¹(ä¸åº”是 %d 个而应是 %d 个)"
@@ -38735,7 +37585,6 @@ msgstr ""
#: cp/pt.c:4159
#, fuzzy, gcc-internal-format
-#| msgid "previously declared here"
msgid "primary template here"
msgstr "以å‰åœ¨æ­¤å£°æ˜Žè¿‡"
@@ -38792,7 +37641,6 @@ msgstr "默认å‚æ•°ä¸èƒ½ç”¨åœ¨å‡½æ•°æ¨¡æ¿å‹å…ƒé‡å£°æ˜Žä¸­"
#: cp/pt.c:4478
#, fuzzy, gcc-internal-format
-#| msgid "default template arguments may not be used in function templates without -std=c++0x or -std=gnu++0x"
msgid "default template arguments may not be used in function templates without -std=c++11 or -std=gnu++11"
msgstr "åªæœ‰æŒ‡å®šäº† -std=c++0x 或 -std=gnu++0x æ—¶æ‰èƒ½åœ¨å‡½æ•°æ¨¡æ¿ä¸­ä½¿ç”¨é»˜è®¤å‚æ•°"
@@ -38914,19 +37762,16 @@ msgstr "它必须是一个具有外部链接函数的地å€"
#: cp/pt.c:5229
#, fuzzy, gcc-internal-format
-#| msgid "it must be the address of a function with external linkage"
msgid "it must be the name of a function with external linkage"
msgstr "它必须是一个具有外部链接函数的地å€"
#: cp/pt.c:5237
#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a valid template argument for type %qT because object %qD has not external linkage"
msgid "%qE is not a valid template argument for type %qT because %qD has no linkage"
msgstr "%qEä¸æ˜¯ç±»åž‹%qT的有效模æ¿å®žå‚,因为对象%qD没有外部链接"
#: cp/pt.c:5241
#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a valid template argument of type %qT because %qD does not have external linkage"
msgid "%qE is not a valid template argument for type %qT because %qD does not have external linkage"
msgstr "%qEä¸æ˜¯ç±»åž‹%qT的有效模æ¿å®žå‚,因为函数%qD没有外部链接"
@@ -38937,7 +37782,6 @@ msgstr "它必须是格å¼ä¸ºâ€˜&X::Y’的æˆå‘˜æŒ‡é’ˆ"
#: cp/pt.c:5318
#, fuzzy, gcc-internal-format
-#| msgid "got %d template parameters for %q#D"
msgid " couldn't deduce template parameter %qD"
msgstr "得到 %d 个模æ¿å‚数,为%q#D"
@@ -38948,31 +37792,26 @@ msgstr ""
#: cp/pt.c:5342
#, fuzzy, gcc-internal-format
-#| msgid "comparison between types %qT and %qT"
msgid " mismatched types %qT and %qT"
msgstr "在类型%qT和%qT间比较"
#: cp/pt.c:5351
#, fuzzy, gcc-internal-format
-#| msgid "template parameter pack %qD cannot have a default argument"
msgid " template parameter %qD is not a parameter pack, but argument %qD is"
msgstr "模æ¿å‚数包%qDä¸èƒ½æœ‰é»˜è®¤å‚æ•°"
#: cp/pt.c:5362
#, fuzzy, gcc-internal-format
-#| msgid "template arguments to %qD do not match original template %qD"
msgid " template argument %qE does not match pointer-to-member constant %qE"
msgstr "ç»™%qD的模æ¿å®žå‚ä¸åŒ¹é…原先的模æ¿%qD"
#: cp/pt.c:5372
#, fuzzy, gcc-internal-format
-#| msgid "%qs is not valid for %qs"
msgid " %qE is not equivalent to %qE"
msgstr "%qs对%qs而言无效"
#: cp/pt.c:5381
#, fuzzy, gcc-internal-format
-#| msgid "inconsistent deduction for %qT: %qT and then %qT"
msgid " inconsistent parameter pack deduction with %qT and %qT"
msgstr "对%qTä¸ä¸€è‡´çš„演绎:先是%qT然åŽæ˜¯%qT"
@@ -38988,31 +37827,26 @@ msgstr ""
#: cp/pt.c:5408
#, fuzzy, gcc-internal-format
-#| msgid "partial specialization %qT does not specialize any template arguments"
msgid " variable-sized array type %qT is not a valid template argument"
msgstr "部分特例化%qT并未特例化任何模æ¿å‚æ•°"
#: cp/pt.c:5419
#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a valid template argument for type %qT"
msgid " member function type %qT is not a valid template argument"
msgstr "%qEä¸æ˜¯ç±»åž‹%qT的有效模æ¿å‚æ•°"
#: cp/pt.c:5453
#, fuzzy, gcc-internal-format
-#| msgid "cannot convert type %qT to type %qT"
msgid " cannot convert %qE (type %qT) to type %qT"
msgstr "ä¸èƒ½å°†ç±»åž‹%qT转æ¢ä¸ºç±»åž‹%qT"
#: cp/pt.c:5466
#, fuzzy, gcc-internal-format
-#| msgid "%qT is an ambiguous base of %qT"
msgid " %qT is an ambiguous base class of %qT"
msgstr "%qT是%qT的有歧义的基类"
#: cp/pt.c:5470
#, fuzzy, gcc-internal-format
-#| msgid "type %qT is not derived from type %qT"
msgid " %qT is not derived from %qT"
msgstr "类型%qTä¸æ˜¯ç”±ç±»åž‹%qT派生的"
@@ -39023,13 +37857,11 @@ msgstr ""
#: cp/pt.c:5491
#, fuzzy, gcc-internal-format
-#| msgid "cannot decrement a pointer to incomplete type %qT"
msgid " can't deduce a template for %qT from non-template type %qT"
msgstr "指å‘ä¸å®Œå…¨ç±»åž‹%qT的指针ä¸èƒ½è‡ªå‡"
#: cp/pt.c:5501
#, fuzzy, gcc-internal-format
-#| msgid "template arguments to %qD do not match original template %qD"
msgid " template argument %qE does not match %qD"
msgstr "ç»™%qD的模æ¿å®žå‚ä¸åŒ¹é…原先的模æ¿%qD"
@@ -39055,7 +37887,6 @@ msgstr "%qDä¸æ˜¯ä¸€ä¸ªæœ‰æ•ˆæ¨¡æ¿å®žå‚,因为%qD是一个å˜é‡ï¼Œè€Œéžå˜
#: cp/pt.c:5747
#, fuzzy, gcc-internal-format
-#| msgid "%qD is not a valid template argument because %qD is a variable, not the address of a variable"
msgid "%qE is not a valid template argument for %qT because it is not the address of a variable"
msgstr "%qDä¸æ˜¯ä¸€ä¸ªæœ‰æ•ˆæ¨¡æ¿å®žå‚,因为%qD是一个å˜é‡ï¼Œè€Œéžå˜é‡çš„地å€"
@@ -39071,7 +37902,6 @@ msgstr "%qEä¸æ˜¯ç±»åž‹%qT的有效模æ¿å®žå‚,因为函数%qD没有外部链
#: cp/pt.c:5778
#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a valid template argument of type %qT because %qE is not a variable"
msgid "%qE is not a valid template argument of type %qT because %qD has no linkage"
msgstr "%qEä¸æ˜¯ç±»åž‹%qT的有效模æ¿å®žå‚,因为%qEä¸æ˜¯ä¸€ä¸ªå˜é‡"
@@ -39132,7 +37962,6 @@ msgstr "注入的类å%qD被用作模æ¿çš„模æ¿å‚æ•°"
#: cp/pt.c:6336
#, fuzzy, gcc-internal-format
-#| msgid "invalid use of destructor %qD as a type"
msgid "invalid use of destructor %qE as a type"
msgstr "å°†æžæž„函数%qD用作类型无效"
@@ -39210,13 +38039,11 @@ msgstr "æ供给%q+D"
#: cp/pt.c:6754
#, fuzzy, gcc-internal-format
-#| msgid "default argument for template parameter for class enclosing %qD"
msgid "pack expansion argument for non-pack parameter %qD of alias template %qD"
msgstr "包å«%qD的类的模æ¿å‚数有默认å‚æ•°"
#: cp/pt.c:7085
#, fuzzy, gcc-internal-format
-#| msgid "%qD is not a function template"
msgid "%q#D is not a function template"
msgstr "%qDä¸æ˜¯ä¸€ä¸ªå‡½æ•°æ¨¡æ¿"
@@ -39232,7 +38059,6 @@ msgstr "对于模æ¿å£°æ˜Ž%q+D"
#: cp/pt.c:8088
#, fuzzy
-#| msgid "template instantiation depth exceeds maximum of %d (use -ftemplate-depth= to increase the maximum) instantiating %qD"
msgid "template instantiation depth exceeds maximum of %d (use -ftemplate-depth= to increase the maximum) substituting %qS"
msgstr "在实例化%2$qD时模æ¿å®žä¾‹åŒ–深度超过最大值 %1$d(使用 use -ftemplate-depth= æ¥å¢žå¤§æœ€å¤§å€¼)"
@@ -39253,7 +38079,6 @@ msgstr "展开%<%E%>æ—¶å‚数包长度ä¸åŒ¹é…"
#: cp/pt.c:10108
#, fuzzy, gcc-internal-format
-#| msgid "redefinition of default argument for %q#D"
msgid " when instantiating default argument for call to %D"
msgstr "é‡å®šä¹‰%q#D的默认å‚æ•°"
@@ -39317,25 +38142,21 @@ msgstr "生æˆæŒ‡å‘引用类型%qT的引用"
#: cp/pt.c:11791
#, fuzzy, gcc-internal-format
-#| msgid "cannot declare pointer to qualified function type %qT"
msgid "forming pointer to qualified function type %qT"
msgstr "ä¸èƒ½å£°æ˜ŽæŒ‡å‘é™å®šå‡½æ•°ç±»åž‹%qT的指针"
#: cp/pt.c:11794
#, fuzzy, gcc-internal-format
-#| msgid "cannot declare reference to qualified function type %qT"
msgid "forming reference to qualified function type %qT"
msgstr "ä¸èƒ½å£°æ˜ŽæŒ‡å‘é™å®šå‡½æ•°ç±»åž‹%qT的引用"
#: cp/pt.c:11831
#, fuzzy, gcc-internal-format
-#| msgid "cannot declare reference to qualified function type %qT"
msgid "cannot declare reference to array of runtime bound"
msgstr "ä¸èƒ½å£°æ˜ŽæŒ‡å‘é™å®šå‡½æ•°ç±»åž‹%qT的引用"
#: cp/pt.c:11832
#, fuzzy, gcc-internal-format
-#| msgid "cannot declare pointer to %q#T member"
msgid "cannot declare pointer to array of runtime bound"
msgstr "无法声明指å‘%q#Tæˆå‘˜çš„指针"
@@ -39426,13 +38247,11 @@ msgstr ""
#: cp/pt.c:14567
#, fuzzy, gcc-internal-format
-#| msgid "%<%T::%E%> is not a type"
msgid "use %<%T::%D%> instead"
msgstr "%<%T::%E%>ä¸æ˜¯ä¸€ä¸ªç±»åž‹"
#: cp/pt.c:14571
#, fuzzy, gcc-internal-format
-#| msgid "%qE undeclared here (not in a function)"
msgid "%q+D declared here, later in the translation unit"
msgstr "%qE未声明(ä¸åœ¨å‡½æ•°å†…)"
@@ -39518,7 +38337,6 @@ msgstr "为模æ¿å®žä¾‹åŒ–化应用了存储类型%qD"
#: cp/pt.c:18935
#, fuzzy, gcc-internal-format
-#| msgid "explicit instantiation of non-template %q#D"
msgid "explicit instantiation of non-class template %qD"
msgstr "对éžæ¨¡æ¿%q#D的显å¼å®žä¾‹åŒ–"
@@ -39561,13 +38379,11 @@ msgstr "在实例化%2$q+D时模æ¿å®žä¾‹åŒ–深度超过了最大值 %1$d,å¯è
#: cp/pt.c:20137
#, fuzzy, gcc-internal-format
-#| msgid "invalid use of template type parameter %qT"
msgid "invalid template non-type parameter"
msgstr "对模æ¿ç±»åž‹å‚æ•°%qT的使用无效"
#: cp/pt.c:20139
#, fuzzy, gcc-internal-format
-#| msgid "%q#T is not a valid type for a template constant parameter"
msgid "%q#T is not a valid type for a template non-type parameter"
msgstr "%q#Tä¸æ˜¯ä¸€ä¸ªæœ‰æ•ˆçš„模æ¿å¸¸é‡å‚数类型"
@@ -39583,7 +38399,6 @@ msgstr ""
#: cp/pt.c:21484
#, fuzzy, gcc-internal-format
-#| msgid "unable to deduce %qT from %qE"
msgid "unable to deduce lambda return type from %qE"
msgstr "无法从%2$qE推导出%1$qT"
@@ -39629,7 +38444,6 @@ msgstr "在使用 typeid 之å‰å¿…须先 #include <typeinfo>"
#: cp/rtti.c:399
#, fuzzy, gcc-internal-format
-#| msgid "creating array of functions"
msgid "typeid of array of runtime bound"
msgstr "创建函数的数组"
@@ -39640,7 +38454,6 @@ msgstr "无法为类型%qT创建类型信æ¯ï¼Œå› ä¸ºå®ƒçš„大å°æ˜¯å¯å˜çš„"
#: cp/rtti.c:491
#, fuzzy, gcc-internal-format
-#| msgid "cannot declare pointer to qualified function type %qT"
msgid "typeid of qualified function type %qT"
msgstr "ä¸èƒ½å£°æ˜ŽæŒ‡å‘é™å®šå‡½æ•°ç±»åž‹%qT的指针"
@@ -39671,7 +38484,6 @@ msgstr "%qT是%qTä¸å¯è®¿é—®çš„基类"
#: cp/search.c:1899
#, fuzzy, gcc-internal-format
-#| msgid "invalid covariant return type for %q+#D"
msgid "invalid covariant return type for %q#D"
msgstr "%q+#Dçš„åå˜è¿”回类型无效"
@@ -39727,13 +38539,11 @@ msgstr "éšè—了被删除的函数%q+D"
#: cp/search.c:1966
#, fuzzy, gcc-internal-format
-#| msgid "virtual non-class function %qs"
msgid "virtual function %q+D"
msgstr "虚函数%qsä¸æ˜¯ç±»æˆå‘˜"
#: cp/search.c:1967
#, fuzzy, gcc-internal-format
-#| msgid "overriding deleted function %q+D"
msgid "overriding final function %q+D"
msgstr "éšè—了被删除的函数%q+D"
@@ -39851,7 +38661,6 @@ msgstr "无效的基类"
#: cp/semantics.c:3218
#, fuzzy, gcc-internal-format
-#| msgid "protected member %q+#D in anonymous union"
msgid "cannot capture member %qD of anonymous union"
msgstr "匿åè”åˆä¸­å‡ºçŽ°ä¿æŠ¤æˆå‘˜%q+#D"
@@ -39862,13 +38671,11 @@ msgstr "%qD未被æ•èŽ·"
#: cp/semantics.c:3235
#, fuzzy, gcc-internal-format
-#| msgid "use of %<auto%> variable from containing function"
msgid "use of local variable with automatic storage from containing function"
msgstr "在包å«å‡½æ•°ä¸­ä½¿ç”¨%<auto%>å˜é‡"
#: cp/semantics.c:3236
#, fuzzy, gcc-internal-format
-#| msgid "use of %<auto%> variable from containing function"
msgid "use of parameter from containing function"
msgstr "在包å«å‡½æ•°ä¸­ä½¿ç”¨%<auto%>å˜é‡"
@@ -39910,14 +38717,12 @@ msgstr "%qE的类型未知"
#: cp/semantics.c:3622
#, fuzzy, gcc-internal-format
-#| msgid "%qD is not an enumerator-name"
msgid "%qT is not an enumeration type"
msgstr "%qDä¸æ˜¯ä¸€ä¸ªæžšä¸¾å"
#. Parameter packs can only be used in templates
#: cp/semantics.c:3771
#, fuzzy, gcc-internal-format
-#| msgid "storage class specifiers invalid in parameter declarations"
msgid "Parameter pack __bases only valid in template declaration"
msgstr "为形å‚声明指定了无效的存储类"
@@ -39938,7 +38743,6 @@ msgstr "ä¸èƒ½ä¸ºæˆå‘˜å‡½æ•°%qD应用%<offsetof%>"
#: cp/semantics.c:4772
#, fuzzy, gcc-internal-format
-#| msgid "reference to %qD is ambiguous"
msgid "user defined reduction lookup is ambiguous"
msgstr "对%qD的引用有歧义"
@@ -39959,7 +38763,6 @@ msgstr ""
#: cp/semantics.c:5267
#, fuzzy, gcc-internal-format
-#| msgid "num_threads expression must be integral"
msgid "linear step expression must be integral"
msgstr "num_threads 表达å¼å¿…须是整型的"
@@ -39995,43 +38798,36 @@ msgstr "调度å—大å°è¡¨è¾¾å¼å¿…须为整型"
#: cp/semantics.c:5434
#, fuzzy, gcc-internal-format
-#| msgid "num_threads expression must be integral"
msgid "%qs length expression must be integral"
msgstr "num_threads 表达å¼å¿…须是整型的"
#: cp/semantics.c:5447
#, fuzzy, gcc-internal-format
-#| msgid "%Hcollapse argument needs positive constant integer expression"
msgid "%qs length expression must be positive constant integer expression"
msgstr "%H折å å˜é‡éœ€è¦æ­£æ•´å¸¸æ•°è¡¨è¾¾å¼"
#: cp/semantics.c:5464
#, fuzzy, gcc-internal-format
-#| msgid "num_threads expression must be integral"
msgid "%<num_teams%> expression must be integral"
msgstr "num_threads 表达å¼å¿…须是整型的"
#: cp/semantics.c:5483
#, fuzzy, gcc-internal-format
-#| msgid "num_threads expression must be integral"
msgid "%<thread_limit%> expression must be integral"
msgstr "num_threads 表达å¼å¿…须是整型的"
#: cp/semantics.c:5502
#, fuzzy, gcc-internal-format
-#| msgid "slice end must be integer"
msgid "%<device%> id must be integral"
msgstr "切片结尾必须是整数"
#: cp/semantics.c:5523
#, fuzzy, gcc-internal-format
-#| msgid "schedule chunk size expression must be integral"
msgid "%<dist_schedule%> chunk size expression must be integral"
msgstr "调度å—大å°è¡¨è¾¾å¼å¿…须为整型"
#: cp/semantics.c:5543
#, fuzzy, gcc-internal-format
-#| msgid "%qD is not a variable in clause %qs"
msgid "%qD is not a variable in %<aligned%> clause"
msgstr "%qD在å­å¥%qs中ä¸æ˜¯ä¸€ä¸ªå˜é‡"
@@ -40042,19 +38838,16 @@ msgstr ""
#: cp/semantics.c:5563
#, fuzzy, gcc-internal-format
-#| msgid "%qD appears more than once in data clauses"
msgid "%qD appears more than once in %<aligned%> clauses"
msgstr "%qD在数æ®å­å¥ä¸­å¤šæ¬¡å‡ºçŽ°"
#: cp/semantics.c:5576
#, fuzzy, gcc-internal-format
-#| msgid "schedule chunk size expression must be integral"
msgid "%<aligned%> clause alignment expression must be integral"
msgstr "调度å—大å°è¡¨è¾¾å¼å¿…须为整型"
#: cp/semantics.c:5613
#, fuzzy, gcc-internal-format
-#| msgid "%qD is not a variable in clause %qs"
msgid "%qD is not a variable in %<depend%> clause"
msgstr "%qD在å­å¥%qs中ä¸æ˜¯ä¸€ä¸ªå˜é‡"
@@ -40091,7 +38884,6 @@ msgstr ""
#. Report the error.
#: cp/semantics.c:6870
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "static assertion failed: %E"
msgid "static assertion failed: %s"
msgstr "é™æ€æ–­è¨€é”™è¯¯ï¼š%E"
@@ -40137,7 +38929,6 @@ msgstr "函数%2$qD的返回值类型%1$qTä¸æ˜¯ä¸€ä¸ªå­—é¢ç±»åž‹"
#: cp/semantics.c:7494
#, fuzzy, gcc-internal-format
-#| msgid "%q#T is not a class"
msgid "%q#T has virtual base classes"
msgstr "%q#Tä¸æ˜¯ä¸€ä¸ªç±»"
@@ -40168,7 +38959,6 @@ msgstr "返回语å¥è½¬æ¢æ— æ•ˆ"
#: cp/semantics.c:8033
#, fuzzy, gcc-internal-format
-#| msgid "%qD is not a constexpr function"
msgid "%q+D is not usable as a constexpr function because:"
msgstr "%qDä¸æ˜¯ä¸€ä¸ªå¹¿ä¹‰å¸¸å‡½æ•°"
@@ -40179,14 +38969,12 @@ msgstr "å‹å…ƒå£°æ˜Žæ²¡æœ‰æŒ‡å®šç±»æˆ–函数å"
#: cp/semantics.c:8382 cp/semantics.c:10054
#, fuzzy, gcc-internal-format
-#| msgid "call to non-function %qD"
msgid "call to non-constexpr function %qD"
msgstr "调用éžå‡½æ•°çš„%qD"
#. The definition of fun was somehow unsuitable.
#: cp/semantics.c:8416
#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a constant expression"
msgid "%qD called in a constant expression"
msgstr "%qEä¸æ˜¯ä¸€ä¸ªå¸¸é‡è¡¨è¾¾å¼"
@@ -40202,7 +38990,6 @@ msgstr "调用存在循环ä¾èµ–"
#: cp/semantics.c:8462
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "template instantiation depth exceeds maximum of %d (use -ftemplate-depth= to increase the maximum) instantiating %qD"
msgid "constexpr evaluation depth exceeds maximum of %d (use -fconstexpr-depth= to increase the maximum)"
msgstr "在实例化%2$qD时模æ¿å®žä¾‹åŒ–深度超过最大值 %1$d(使用 use -ftemplate-depth= æ¥å¢žå¤§æœ€å¤§å€¼)"
@@ -40218,7 +39005,6 @@ msgstr "数组下标越界"
#: cp/semantics.c:8682
#, fuzzy, gcc-internal-format
-#| msgid "Expected array subscript at %C"
msgid "negative array subscript"
msgstr "%C处需è¦æ•°ç»„下标"
@@ -40284,13 +39070,11 @@ msgstr "%qE的枚举值ä¸æ˜¯ä¸€ä¸ªæ•´æ•°å¸¸é‡"
#: cp/semantics.c:9492 cp/semantics.c:10361
#, fuzzy, gcc-internal-format
-#| msgid "enumeral and non-enumeral type in conditional expression"
msgid "temporary of non-literal type %qT in a constant expression"
msgstr "枚举和éžæžšä¸¾ç±»åž‹ä¸€èµ·å‡ºçŽ°åœ¨æ¡ä»¶è¡¨è¾¾å¼ä¸­"
#: cp/semantics.c:9735 cp/semantics.c:10146
#, fuzzy, gcc-internal-format
-#| msgid "reinterpret_cast from type %qT to type %qT casts away qualifiers"
msgid "reinterpret_cast from integer to pointer"
msgstr "从类型%qT到类型%qTçš„ reinterpret_cast 丢失了é™å®šç¬¦"
@@ -40331,7 +39115,6 @@ msgstr ""
#: cp/semantics.c:10200
#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a constant expression"
msgid "use of %<this%> in a constant expression"
msgstr "%qEä¸æ˜¯ä¸€ä¸ªå¸¸é‡è¡¨è¾¾å¼"
@@ -40352,7 +39135,6 @@ msgstr "整型表达å¼%qEä¸æ˜¯å¸¸é‡"
#: cp/semantics.c:10336
#, fuzzy, gcc-internal-format
-#| msgid "Bad type in constant expression"
msgid "cast to non-integral type %qT in a constant expression"
msgstr "常é‡è¡¨è¾¾å¼ä¸­ç±»åž‹é”™è¯¯"
@@ -40423,43 +39205,36 @@ msgstr "%qE属性在此平å°ä¸Šä¸å—支æŒ"
#: cp/tree.c:3333
#, fuzzy, gcc-internal-format
-#| msgid "declaration of %qD as member of %qT"
msgid "redeclaration of %qD adds abi tag %E"
msgstr "%qD声明为%qT的一个æˆå‘˜"
#: cp/tree.c:3339
#, fuzzy, gcc-internal-format
-#| msgid "previous declaration %q+#D here"
msgid "previous declaration here"
msgstr "与此处早先的声明%q+#D冲çª"
#: cp/tree.c:3356
#, fuzzy, gcc-internal-format
-#| msgid "%qE attribute ignored on non-class types"
msgid "%qE attribute applied to non-class, non-enum type %qT"
msgstr "%qE属性在ä¸æ˜¯ç±»çš„类型上被忽略"
#: cp/tree.c:3362
#, fuzzy, gcc-internal-format
-#| msgid "ignoring attributes applied to %qT after definition"
msgid "%qE attribute applied to %qT after its definition"
msgstr "忽略在其定义之åŽä¸º%qT应用的属性"
#: cp/tree.c:3384
#, fuzzy, gcc-internal-format
-#| msgid "%qE attribute applies only to functions"
msgid "%qE attribute applied to non-function %qD"
msgstr "%qE属性åªèƒ½ç”¨äºŽå‡½æ•°"
#: cp/tree.c:3389
#, fuzzy, gcc-internal-format
-#| msgid "%qE attribute applies only to functions"
msgid "%qE attribute applied to extern \"C\" function %qD"
msgstr "%qE属性åªèƒ½ç”¨äºŽå‡½æ•°"
#: cp/tree.c:4093
#, fuzzy, gcc-internal-format
-#| msgid "array bound is not an integer constant"
msgid "zero as null pointer constant"
msgstr "数组边界ä¸æ˜¯ä¸€ä¸ªæ•´æ•°å¸¸é‡"
@@ -40530,7 +39305,6 @@ msgstr "%qs用于æˆå‘˜å‡½æ•°æ— æ•ˆ"
#: cp/typeck.c:1559
#, fuzzy, gcc-internal-format
-#| msgid "creating array of functions"
msgid "taking sizeof array of runtime bound"
msgstr "创建函数的数组"
@@ -40561,7 +39335,6 @@ msgstr "对éžé™æ€æˆå‘˜å‡½æ•°çš„使用无效"
#: cp/typeck.c:1961
#, fuzzy, gcc-internal-format
-#| msgid "taking address of temporary"
msgid "taking address of temporary array"
msgstr "å–临时å˜é‡çš„地å€"
@@ -40572,7 +39345,6 @@ msgstr "ä¸å»ºè®®ä½¿ç”¨ä»Žå­—符串常é‡åˆ°%qT的转æ¢"
#: cp/typeck.c:2248 cp/typeck.c:2658
#, fuzzy, gcc-internal-format
-#| msgid "request for member %qD in %qE, which is of non-class type %qT"
msgid "request for member %qD in %qE, which is of pointer type %qT (maybe you meant to use %<->%> ?)"
msgstr "对æˆå‘˜%qD的请求出现在%qE中,而åŽè€…具有éžç±»ç±»åž‹%qT"
@@ -40663,7 +39435,6 @@ msgstr "数组引用缺少下标"
#: cp/typeck.c:3029
#, fuzzy, gcc-internal-format
-#| msgid "alignment of array elements is greater than element size"
msgid "rank of the array%'s index is greater than 1"
msgstr "数组元素的对é½è¾¹ç•Œæ¯”元素大å°è¿˜è¦å¤§"
@@ -40704,13 +39475,11 @@ msgstr "%qEä¸èƒ½ç”¨ä½œå‡½æ•°"
#: cp/typeck.c:3486
#, fuzzy, gcc-internal-format
-#| msgid "%qE cannot be used as a function"
msgid "%qD cannot be used as a function"
msgstr "%qEä¸èƒ½ç”¨ä½œå‡½æ•°"
#: cp/typeck.c:3489
#, fuzzy, gcc-internal-format
-#| msgid "%qE cannot be used as a function"
msgid "expression cannot be used as a function"
msgstr "%qEä¸èƒ½ç”¨ä½œå‡½æ•°"
@@ -40821,13 +39590,11 @@ msgstr "ISO C++ ä¸å…许比较指针和整数的值"
#: cp/typeck.c:4572 cp/typeck.c:4584
#, fuzzy, gcc-internal-format
-#| msgid "comparison between %qT and %qT"
msgid "operand types are %qT and %qT"
msgstr "在%qT和%qT间比较"
#: cp/typeck.c:4596
#, fuzzy, gcc-internal-format
-#| msgid "could not find interface for class %qE"
msgid "could not find an integer type of the same size as %qT"
msgstr "找ä¸åˆ°ç±»%qE的接å£"
@@ -40925,7 +39692,6 @@ msgstr "ä¸èƒ½åˆ›å»ºæŒ‡å‘引用æˆå‘˜%qD的指针"
#: cp/typeck.c:5473
#, fuzzy, gcc-internal-format
-#| msgid "taking address of expression of type %<void%>"
msgid "taking address of array of runtime bound"
msgstr "å–一个类型为%<void%>的表达å¼çš„地å€"
@@ -40981,7 +39747,6 @@ msgstr "请求声明为%<register%>çš„%qD的地å€"
#: cp/typeck.c:6077
#, fuzzy, gcc-internal-format
-#| msgid "initializer for %qT must be brace-enclosed"
msgid "list-initializer for non-class type must not be parenthesized"
msgstr "%qTçš„åˆå§‹å€¼è®¾å®šå¿…须在花括å·å†…"
@@ -41027,7 +39792,6 @@ msgstr "从类型%qT到类型%qTçš„ reinterpret_cast 丢失了é™å®šç¬¦"
#: cp/typeck.c:6296
#, fuzzy, gcc-internal-format
-#| msgid "invalid cast to function type %qT"
msgid "useless cast to type %qT"
msgstr "å‘函数类型%qT的转æ¢æ— æ•ˆ"
@@ -41058,7 +39822,6 @@ msgstr "从%qT到%qT的转æ¢å¢žå¤§äº†ç›®æ ‡ç±»åž‹çš„对é½éœ€æ±‚"
#: cp/typeck.c:6850
#, fuzzy, gcc-internal-format
-#| msgid "ISO C++ forbids casting between pointer-to-function and pointer-to-object"
msgid "casting between pointer-to-function and pointer-to-object is conditionally-supported"
msgstr "ISO C++ ä¸å…许在函数指针和对象指针间进行转æ¢"
@@ -41253,7 +40016,6 @@ msgstr "在返回%qT的函数中,返回语å¥ä¸å¸¦è¿”回值"
#: cp/typeck.c:8390
#, fuzzy, gcc-internal-format
-#| msgid "<brace-enclosed initializer list>"
msgid "returning initializer list"
msgstr "<花括å·å†…çš„åˆå§‹å€¼åˆ—表>"
@@ -41335,7 +40097,6 @@ msgstr "ä¸èƒ½å°†å½¢å‚%q+D声明为具有抽象类型%qT"
#: cp/typeck2.c:333
#, fuzzy, gcc-internal-format
-#| msgid "cannot declare parameter %q+D to be of abstract type %qT"
msgid "cannot declare parameter to be of abstract type %qT"
msgstr "ä¸èƒ½å°†å½¢å‚%q+D声明为具有抽象类型%qT"
@@ -41372,37 +40133,31 @@ msgstr "生æˆæŠ½è±¡ç±»åž‹%qT的数组"
#: cp/typeck2.c:356
#, fuzzy, gcc-internal-format
-#| msgid "invalid cast to function type %qT"
msgid "invalid cast to abstract class type %qT"
msgstr "å‘函数类型%qT的转æ¢æ— æ•ˆ"
#: cp/typeck2.c:359
#, fuzzy, gcc-internal-format
-#| msgid "invalid cast of an rvalue expression of type %qT to type %qT"
msgid "invalid new-expression of abstract class type %qT"
msgstr "从具有类型%qTçš„å³å€¼è¡¨è¾¾å¼åˆ°ç±»åž‹%qT中的转æ¢æ— æ•ˆ"
#: cp/typeck2.c:362
#, fuzzy, gcc-internal-format
-#| msgid "invalid parameter type %qT"
msgid "invalid abstract return type %qT"
msgstr "无效的å‚数类型%qT"
#: cp/typeck2.c:365
#, fuzzy, gcc-internal-format
-#| msgid "invalid parameter type %qT"
msgid "invalid abstract parameter type %qT"
msgstr "无效的å‚数类型%qT"
#: cp/typeck2.c:368
#, fuzzy, gcc-internal-format
-#| msgid "expression %qE of abstract class type %qT cannot be used in throw-expression"
msgid "expression of abstract class type %qT cannot be used in throw-expression"
msgstr "表达å¼%qE具有抽象类类型%qT,ä¸èƒ½ç”¨äºŽ throw 表达å¼ä¸­"
#: cp/typeck2.c:372
#, fuzzy, gcc-internal-format
-#| msgid "cannot declare parameter %q+D to be of abstract type %qT"
msgid "cannot declare catch parameter to be of abstract class type %qT"
msgstr "ä¸èƒ½å°†å½¢å‚%q+D声明为具有抽象类型%qT"
@@ -41448,7 +40203,6 @@ msgstr "对%qT的使用éžæ³•"
#: cp/typeck2.c:501
#, fuzzy, gcc-internal-format
-#| msgid "invalid use of member (did you forget the %<&%> ?)"
msgid "invalid use of member function (did you forget the %<()%> ?)"
msgstr "对æˆå‘˜çš„使用无效(您是å¦é—忘了%<&%>?)"
@@ -41474,7 +40228,6 @@ msgstr "对ä¾èµ–类型%qT的使用无效"
#: cp/typeck2.c:534
#, fuzzy, gcc-internal-format
-#| msgid "<brace-enclosed initializer list>"
msgid "invalid use of brace-enclosed initializer list"
msgstr "<花括å·å†…çš„åˆå§‹å€¼åˆ—表>"
@@ -41510,7 +40263,6 @@ msgstr "在 {} 内将%qE从%qT转æ¢ä¸ºè¾ƒçª„的类型%qT"
#: cp/typeck2.c:922
#, fuzzy, gcc-internal-format
-#| msgid "narrowing conversion of %qE from %qT to %qT inside { }"
msgid "narrowing conversion of %qE from %qT to %qT inside { } is ill-formed in C++11"
msgstr "在 {} 内将%qE从%qT转æ¢ä¸ºè¾ƒçª„的类型%qT"
@@ -41606,19 +40358,16 @@ msgstr "æˆå‘˜æŒ‡é’ˆç±»åž‹%qT与对象类型%qTä¸å…¼å®¹"
#: cp/typeck2.c:1759
#, fuzzy, gcc-internal-format
-#| msgid "pointer to member function used in arithmetic"
msgid "pointer-to-member-function type %qT requires an rvalue"
msgstr "在算术表达å¼ä¸­ä½¿ç”¨äº†æˆå‘˜æŒ‡é’ˆ"
#: cp/typeck2.c:1766
#, fuzzy, gcc-internal-format
-#| msgid "pointer to member function used in arithmetic"
msgid "pointer-to-member-function type %qT requires an lvalue"
msgstr "在算术表达å¼ä¸­ä½¿ç”¨äº†æˆå‘˜æŒ‡é’ˆ"
#: cp/typeck2.c:1807
#, fuzzy, gcc-internal-format
-#| msgid "invalid cast to function type %qT"
msgid "functional cast to array type %qT"
msgstr "å‘函数类型%qT的转æ¢æ— æ•ˆ"
@@ -41659,7 +40408,6 @@ msgstr "在%L处把一个无穷大或éžæ•°è½¬æ¢ä¸º INTEGER"
#: fortran/arith.c:904 fortran/arith.c:929
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Noninteger exponent in an initialization expression at %L"
msgid "Noninteger exponent in an initialization expression at %L"
msgstr "Fortran 2003:%L处åˆå§‹åŒ–表达å¼ä¸­éžæ•´æ•°æŒ‡æ•°"
@@ -41833,7 +40581,6 @@ msgstr "%C处数组规格中有多于 %d 的维数"
#: fortran/array.c:578
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Array specification at %C has more than %d dimensions"
msgid "Array specification at %C with more than 7 dimensions"
msgstr "%C处数组规格中有多于 %d 的维数"
@@ -41864,13 +40611,11 @@ msgstr "%C处数组构造语法错误"
#: fortran/array.c:1060
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: [...] style array constructors at %C"
msgid "[...] style array constructors at %C"
msgstr "Fortran 2003:%C处 [...] 风格的数组构造"
#: fortran/array.c:1082
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Array constructor including type specification at %C"
msgid "Array constructor including type specification at %C"
msgstr "Fortran 2003:%C处包å«ç±»åž‹è§„格的数组构造"
@@ -42074,7 +40819,6 @@ msgstr "%4$L处‘%3$s’内建函数的‘%1$s’和‘%2$s’实å‚类型必é¡
#: fortran/check.c:868 fortran/check.c:1807 fortran/check.c:1933
#: fortran/check.c:2007 fortran/check.c:2427
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: Different type kinds at %L"
msgid "Different type kinds at %L"
msgstr "扩展:%L处类型ç§åˆ«ä¸åŒ"
@@ -42085,7 +40829,6 @@ msgstr "%3$L处内建函数‘%2$s’的实å‚‘%1$s’必须是一个 POINTER"
#: fortran/check.c:913 fortran/check.c:949 fortran/check.c:2945
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "'%s' argument of '%s' intrinsic at %L must be of kind %d"
msgid "'%s' argument of '%s' intrinsic at %L shall not be coindexed"
msgstr "%3$L处内建函数‘%2$s’的实å‚‘%1$s’必须具有ç§åˆ« %4$d"
@@ -42121,19 +40864,16 @@ msgstr "‘%s’的实å‚在%L处必须是一个指针"
#: fortran/check.c:1030
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "'%s' and '%s' arguments of '%s' intrinsic at %L must have the same type"
msgid "ATOM and VALUE argument of the %s intrinsic function shall have the same type at %L"
msgstr "%4$L处‘%3$s’内建函数的‘%1$s’和‘%2$s’实å‚类型必须相åŒ"
#: fortran/check.c:1048
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "'%s' argument of '%s' intrinsic at %L must be default real"
msgid "ATOM argument of the %s intrinsic function at %L shall be definable"
msgstr "%3$L处内建函数‘%2$s’的‘%1$s’实å‚类型必须为默认实型"
#: fortran/check.c:1065
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "'%s' argument of '%s' intrinsic at %L must be default real"
msgid "VALUE argument of the %s intrinsic function at %L shall be definable"
msgstr "%3$L处内建函数‘%2$s’的‘%1$s’实å‚类型必须为默认实型"
@@ -42162,7 +40902,6 @@ msgstr ""
#: fortran/check.c:3609 fortran/check.c:3664 fortran/check.c:4620
#: fortran/check.c:4749
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: '%s' intrinsic with KIND argument at %L"
msgid "'%s' intrinsic with KIND argument at %L"
msgstr "Fortran 2003:%2$L处的‘%1$s’内建函数有 KIND 实å‚"
@@ -42203,7 +40942,6 @@ msgstr "%2$L处 %1$s 内建函数缺少实å‚"
#: fortran/check.c:1739
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2008: COMPLEX argument '%s' argument of '%s' intrinsic at %L"
msgid "COMPLEX argument '%s' argument of '%s' intrinsic at %L"
msgstr "Fortran 2008:%3$L处的‘%2$s’内建函数有 COMPLEX å‚数‘%1$s’"
@@ -42239,19 +40977,16 @@ msgstr "%2$L处的内建函数‘%1$s’必须至少有两个实å‚"
#: fortran/check.c:2384
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "'%s' argument of '%s' intrinsic at %L is empty"
msgid "Missing '%s' argument to the %s intrinsic at %L"
msgstr "%3$L处内建‘%2$s’内建函数的‘%1$s’实å‚为空"
#: fortran/check.c:2399
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "arguments '%s' and '%s' for intrinsic %s"
msgid "Duplicate argument '%s' at %L to intrinsic %s"
msgstr "‘%s’和‘%s’用作内建函数‘%s’的å‚æ•°"
#: fortran/check.c:2404
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "arguments '%s' and '%s' for intrinsic %s"
msgid "Unknown argument '%s' at %L to intrinsic %s"
msgstr "‘%s’和‘%s’用作内建函数‘%s’的å‚æ•°"
@@ -42262,7 +40997,6 @@ msgstr "%3$L处内建函数‘%2$s’的实å‚‘a%1$d’必须是 %4$s(%5$d)"
#: fortran/check.c:2464
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: '%s' intrinsic with CHARACTER argument at %L"
msgid "'%s' intrinsic with CHARACTER argument at %L"
msgstr "Fortran 2003:%2$L处的‘%1$s’内建函数有 CHARACTER 实å‚"
@@ -42298,13 +41032,11 @@ msgstr "%3$L处内建函数‘%2$s’的实å‚‘%1$s’必须为整数型或实
#: fortran/check.c:2815
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Second argument of NEAREST at %L shall not be zero"
msgid "The FROM argument to MOVE_ALLOC at %L shall not be coindexed"
msgstr "%L处 NEAREST 的第二个å‚æ•°ä¸èƒ½ä¸º 0"
#: fortran/check.c:2826
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Second argument of NEAREST at %L shall not be zero"
msgid "The TO argument to MOVE_ALLOC at %L shall not be coindexed"
msgstr "%L处 NEAREST 的第二个å‚æ•°ä¸èƒ½ä¸º 0"
@@ -42315,25 +41047,21 @@ msgstr ""
#: fortran/check.c:2844
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "the '%s' and '%s' arguments of '%s' intrinsic at %L must have the same rank %d/%d"
msgid "The FROM and TO arguments of the MOVE_ALLOC intrinsic at %L must have the same rank %d/%d"
msgstr "%4$L处‘%3$s’内建函数的‘%1$s’和‘%2$s’实å‚必须有相åŒçš„秩 %5$d/%6$d"
#: fortran/check.c:2853
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "the '%s' and '%s' arguments of '%s' intrinsic at %L must have the same rank %d/%d"
msgid "The FROM and TO arguments of the MOVE_ALLOC intrinsic at %L must have the same corank %d/%d"
msgstr "%4$L处‘%3$s’内建函数的‘%1$s’和‘%2$s’实å‚必须有相åŒçš„秩 %5$d/%6$d"
#: fortran/check.c:2880
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Second argument of NEAREST at %L shall not be zero"
msgid "Argument 'S' of NEAREST at %L shall not be zero"
msgstr "%L处 NEAREST 的第二个å‚æ•°ä¸èƒ½ä¸º 0"
#: fortran/check.c:2930
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "'%s' argument of '%s' intrinsic at %L must be ALLOCATABLE"
msgid "'%s' argument of '%s' intrinsic at %L must be a POINTER, ALLOCATABLE or procedure pointer"
msgstr "%3$L处内建函数‘%2$s’的实å‚‘%1$s’必须为 ALLOCATABLE"
@@ -42364,7 +41092,6 @@ msgstr "%3$L处内建函数‘%2$s’的实å‚‘%1$s’必须是‘%4$s’的å­
#: fortran/check.c:3150
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "'%s' argument of '%s' intrinsic at %L must be a variable"
msgid "The argument of the RANK intrinsic at %L must be a data object"
msgstr "%3$L处内建函数‘%2$s’的实å‚‘%1$s’必须是一个å˜é‡"
@@ -42410,7 +41137,6 @@ msgstr "若没有填充,%L处内建 ESHAPE æºä¸­æ²¡æœ‰è¶³å¤Ÿçš„元素去与å¤
#: fortran/check.c:3408 fortran/check.c:3427
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "'%s' argument of '%s' intrinsic at %L must be %s"
msgid "'%s' argument of '%s' intrinsic at %L cannot be of type %s"
msgstr "%3$L处内建函数‘%2$s’的实å‚‘%1$s’必须是 %4$s"
@@ -42436,19 +41162,16 @@ msgstr "‘shape’内建函数的‘source’实å‚在%L处ä¸èƒ½æ˜¯å‡å®šå¤§å°
#: fortran/check.c:3679 fortran/check.c:5705
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "'%s' argument of '%s' intrinsic at %L must be a scalar"
msgid "'%s' argument of '%s' intrinsic at %L shall not be a procedure"
msgstr "%3$L处内建函数‘%2$s’的实å‚‘%1$s’必须是一个标é‡"
#: fortran/check.c:3687 fortran/check.c:3826 fortran/check.c:5697
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "'%s' argument of '%s' intrinsic at %L cannot be INTENT(IN)"
msgid "'%s' argument of '%s' intrinsic at %L shall not be TYPE(*)"
msgstr "%3$L处内建函数‘%2$s’的实å‚‘%1$s’ä¸èƒ½æ˜¯ INTENT(IN)"
#: fortran/check.c:3698 fortran/check.c:3838
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "'source' argument of 'shape' intrinsic at %L must not be an assumed size array"
msgid "'%s' argument of '%s' intrinsic at %L shall not be an assumed-size array"
msgstr "‘shape’内建函数的‘source’实å‚在%L处ä¸èƒ½æ˜¯å‡å®šå¤§å°çš„数组"
@@ -42474,7 +41197,6 @@ msgstr ""
#: fortran/check.c:3906
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Argument dim at %L must be scalar"
msgid "Argument FPTR at %L to C_F_POINTER must be a pointer"
msgstr "%L 实å‚维数必须是标é‡"
@@ -42540,7 +41262,6 @@ msgstr "%L处数æ®ä¼ è¾“元素ä¸èƒ½æœ‰ POINTER 组件"
#: fortran/check.c:4036
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Function result '%s' at %L has no IMPLICIT type"
msgid "Function result '%s' at %L is invalid as X argument to C_FUNLOC"
msgstr "%2$L处的函数返回值‘%1$s’处没有éšå¼ç±»åž‹"
@@ -42551,7 +41272,6 @@ msgstr ""
#: fortran/check.c:4050
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "User operator procedure '%s' at %L must be a FUNCTION"
msgid "Noninteroperable procedure at %L to C_FUNLOC"
msgstr "%2$L处的用户è¿ç®—符‘%1$s’必须是一个 FUNCTION"
@@ -42567,7 +41287,6 @@ msgstr "‘%s’的实å‚在%L处必须是一个指针"
#: fortran/check.c:4081
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Component at %C must have the POINTER attribute"
msgid "Argument X at %L to C_LOC shall have either the POINTER or the TARGET attribute"
msgstr "%C处的组件必须有 POINTER 属性"
@@ -42730,7 +41449,6 @@ msgstr "%L处数æ®å…ƒç´ é«˜äºŽæ•°ç»„上é™"
#: fortran/data.c:327 fortran/data.c:493
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: re-initialization of '%s' at %L"
msgid "re-initialization of '%s' at %L"
msgstr "扩展:‘%s’é‡åˆå§‹åŒ–于 %L"
@@ -42741,7 +41459,6 @@ msgstr "%2$C处主机相关的å˜é‡â€˜%1$s’ä¸èƒ½å‡ºçŽ°åœ¨ DATA 语å¥ä¸­"
#: fortran/decl.c:271
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: initialization of common block variable '%s' in DATA statement at %C"
msgid "initialization of common block variable '%s' in DATA statement at %C"
msgstr "扩展:DATA 语å¥ä¸­å¯¹å…¬å…±å—å˜é‡â€˜%s’在%C处åˆå§‹åŒ–"
@@ -42787,7 +41504,6 @@ msgstr "%C处函数å‚数属性中有冲çª"
#: fortran/decl.c:752
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Obsolescent feature: Old-style character length at %C"
msgid "Old-style character length at %C"
msgstr "已过时:%C处的旧å¼å­—符长度"
@@ -42823,13 +41539,11 @@ msgstr "%2$L 处类型“%1$sâ€æ˜¯åŽ»åˆ° BIND(C) 过程“%3$sâ€çš„å‚数,ä½
#: fortran/decl.c:1032
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %L is a parameter to the BIND(C) procedure '%s' but may not be C interoperable"
msgid "Variable '%s' at %L is a dummy argument to the BIND(C) procedure '%s' but is not C interoperable because it is polymorphic"
msgstr "%2$L处å˜é‡â€˜%1$s’是 BIND(C) 过程‘%3$s’的å‚数,但它ä¸èƒ½ä¸Ž C 互æ“作"
#: fortran/decl.c:1038
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %L is a parameter to the BIND(C) procedure '%s' but may not be C interoperable"
msgid "Variable '%s' at %L is a dummy argument of the BIND(C) procedure '%s' but may not be C interoperable"
msgstr "%2$L处å˜é‡â€˜%1$s’是 BIND(C) 过程‘%3$s’的å‚数,但它ä¸èƒ½ä¸Ž C 互æ“作"
@@ -42840,37 +41554,31 @@ msgstr "%2$L处字符å‚数‘%1$s’长度必须为 1,因为过程‘%3$s’æ
#: fortran/decl.c:1066
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %L cannot have the ALLOCATABLE attribute because procedure '%s' is BIND(C)"
msgid "Variable '%s' at %L with ALLOCATABLE attribute in procedure '%s' with BIND(C)"
msgstr "%2$L处å˜é‡â€˜%1$s’ä¸èƒ½æœ‰ ALLOCATABLE 属性,因为过程‘%3$s’是 BIND(C)"
#: fortran/decl.c:1074
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %L cannot have the POINTER attribute because procedure '%s' is BIND(C)"
msgid "Variable '%s' at %L with POINTER attribute in procedure '%s' with BIND(C)"
msgstr "%2$L处å˜é‡â€˜%1$s’ä¸èƒ½æœ‰ POINTER 属性,因为过程‘%3$s’是 BIND(C)"
#: fortran/decl.c:1083
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %L cannot have the ALLOCATABLE attribute because procedure '%s' is BIND(C)"
msgid "Scalar variable '%s' at %L with POINTER or ALLOCATABLE in procedure '%s' with BIND(C) is not yet supported"
msgstr "%2$L处å˜é‡â€˜%1$s’ä¸èƒ½æœ‰ ALLOCATABLE 属性,因为过程‘%3$s’是 BIND(C)"
#: fortran/decl.c:1092
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %L cannot have the OPTIONAL attribute because procedure '%s' is BIND(C)"
msgid "Variable '%s' at %L cannot have both the OPTIONAL and the VALUE attribute because procedure '%s' is BIND(C)"
msgstr "%2$L处å˜é‡â€˜%1$s’ä¸èƒ½æœ‰ OPTIONAL 属性,因为过程‘%3$s’是 BIND(C)"
#: fortran/decl.c:1099
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %L cannot have the OPTIONAL attribute because procedure '%s' is BIND(C)"
msgid "Variable '%s' at %L with OPTIONAL attribute in procedure '%s' which is BIND(C)"
msgstr "%2$L处å˜é‡â€˜%1$s’ä¸èƒ½æœ‰ OPTIONAL 属性,因为过程‘%3$s’是 BIND(C)"
#: fortran/decl.c:1110
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Assumed-shape array '%s' at %L cannot be an argument to the procedure '%s' at %L because the procedure is BIND(C)"
msgid "Assumed-shape array '%s' at %L as dummy argument to the BIND(C) procedure '%s' at %L"
msgstr "%2$L处å‡å®šå¤–形数组‘%1$s’ä¸èƒ½æ˜¯%4$L处过程‘%3$s’的å‚数,因为该过程是 BIND(C)"
@@ -42946,7 +41654,6 @@ msgstr "%C处的 NULL() åˆå§‹åŒ–有歧义"
#: fortran/decl.c:1724
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "NULL() initialization at %C is ambiguous"
msgid "NULL() initialization at %C may not have MOLD"
msgstr "%C处的 NULL() åˆå§‹åŒ–有歧义"
@@ -42987,7 +41694,6 @@ msgstr "%C处 Cray 指针é‡å¤æŒ‡å®šäº†æ•°ç»„"
#: fortran/decl.c:2003
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: Old-style initialization at %C"
msgid "Old-style initialization at %C"
msgstr "扩展:%C处旧å¼çš„åˆå§‹åŒ–"
@@ -43068,7 +41774,6 @@ msgstr "%C处 CHARACTER 声明语法错误"
#: fortran/decl.c:2597
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: BYTE type at %C"
msgid "BYTE type at %C"
msgstr "扩展:%C处的 BYTE 类型"
@@ -43079,7 +41784,6 @@ msgstr "%C处使用到的 BYTE 类型在目标机上ä¸å¯ç”¨"
#: fortran/decl.c:2624
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "By-value argument at %L is not allowed in this context"
msgid "Assumed type at %C is not allowed for components"
msgstr "%L处上下文中ä¸å…许使用按值传递的实å‚"
@@ -43101,7 +41805,6 @@ msgstr "扩展:‘%s’é‡åˆå§‹åŒ–于 %L"
#: fortran/decl.c:2780
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: CLASS statement at %C"
msgid "CLASS statement at %C"
msgstr "Fortran 2003:%C处的 CLASS 语å¥"
@@ -43138,7 +41841,6 @@ msgstr "%C处 IMPORT 语å¥åªå…许出现在接å£ä½“中"
#: fortran/decl.c:3171
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Empty IMPLICIT statement at %C"
msgid "IMPORT statement at %C"
msgstr "%C处 IMPLICIT 语å¥ä¸ºç©º"
@@ -43179,7 +41881,6 @@ msgstr "é‡å¤çš„ %s 属性,ä½äºŽ %L"
#: fortran/decl.c:3667
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: ALLOCATABLE attribute at %C in a TYPE definition"
msgid "ALLOCATABLE attribute at %C in a TYPE definition"
msgstr "Fortran 2003:%C处的 ALLOCATABLE 属性出现在 TYPE 定义中"
@@ -43190,7 +41891,6 @@ msgstr "%L处的属性ä¸å…许出现在 TYPE 定义中"
#: fortran/decl.c:3694
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Attribute %s at %L in a TYPE definition"
msgid "Attribute %s at %L in a TYPE definition"
msgstr "Fortran 2003:属性 %s 在%L处出现在 TYPE 定义中"
@@ -43201,7 +41901,6 @@ msgstr "%2$L处的 %1$s 属性ä¸å…许出现在模å—规格说明以外"
#: fortran/decl.c:3718
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: ASYNCHRONOUS attribute at %C"
msgid "ASYNCHRONOUS attribute at %C"
msgstr "Fortran 2003:%C处的 ASYNCHRONOUS 属性"
@@ -43217,19 +41916,16 @@ msgstr "%C处的 PROTECTED ä»…å…许出现在模å—规格说明部分内"
#: fortran/decl.c:3780
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: PROTECTED attribute at %C"
msgid "PROTECTED attribute at %C"
msgstr "Fortran 2003:%C处的 PROTECT 属性"
#: fortran/decl.c:3809
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: VALUE attribute at %C"
msgid "VALUE attribute at %C"
msgstr "Fortran 2003:%C处的 VALUE 属性"
#: fortran/decl.c:3816
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: VOLATILE attribute at %C"
msgid "VOLATILE attribute at %C"
msgstr "Fortran 2003:%C处的 VOLATILE 属性"
@@ -43302,7 +41998,6 @@ msgstr "%C处的属性规格说明语å¥ç¼ºå°‘实体或公共å—å"
#: fortran/decl.c:4212
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Empty IMPLICIT statement at %C"
msgid "BIND(C) statement at %C"
msgstr "%C处 IMPLICIT 语å¥ä¸ºç©º"
@@ -43328,7 +42023,6 @@ msgstr ""
#: fortran/decl.c:4475 fortran/primary.c:1717
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Expected alternate return label at %C"
msgid "Alternate-return argument at %C"
msgstr "%C处需è¦æ›¿ä»£çš„返回标å·"
@@ -43359,7 +42053,6 @@ msgstr "%C处的函数声明åŽæœ‰éžé¢„期的垃圾字符"
#: fortran/decl.c:4687 fortran/decl.c:5753
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2008: BIND(C) attribute at %L may not be specified for an internal procedure"
msgid "BIND(C) attribute at %L may not be specified for an internal procedure"
msgstr "Fortran 2008:%L处的 BIND(C)属性对于内部过程ä¸å¯ä»¥æŒ‡å®š"
@@ -43400,7 +42093,6 @@ msgstr "%Cå¤„éœ€è¦ NOPASS 或显å¼æŽ¥å£"
#: fortran/decl.c:5031
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Procedure pointer component at %C"
msgid "Procedure pointer component at %C"
msgstr "Fortran 2003:%C处的过程指针组件"
@@ -43416,13 +42108,11 @@ msgstr "%C处的 PROCEDURE 必须在一个泛型接å£å†…"
#: fortran/decl.c:5130 fortran/decl.c:7325
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Syntax error in PROCEDURE statement at %C"
msgid "double colon in MODULE PROCEDURE statement at %L"
msgstr "%C处 PROCEDURE 语å¥è¯­æ³•é”™è¯¯"
#: fortran/decl.c:5199
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: PROCEDURE statement at %C"
msgid "PROCEDURE statement at %C"
msgstr "Fortran 2003:%C处的 PROCEDURE 语å¥"
@@ -43440,7 +42130,6 @@ msgstr "%L处的 BIND(C) 属性åªèƒ½ç”¨äºŽå˜é‡æˆ–公共å—"
#: fortran/decl.c:5440
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Empty IMPLICIT statement at %C"
msgid "ENTRY statement at %C"
msgstr "%C处 IMPLICIT 语å¥ä¸ºç©º"
@@ -43562,13 +42251,11 @@ msgstr "éœ€è¦ %s 语å¥åœ¨%L处"
#: fortran/decl.c:6144
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Expecting %s statement at %C"
msgid "Expecting %s statement at %L"
msgstr "éœ€è¦ %s 语å¥ï¼ŒäºŽ %C"
#: fortran/decl.c:6162
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Expected block name of '%s' in %s statement at %C"
msgid "Expected block name of '%s' in %s statement at %L"
msgstr "需è¦å—å‘%s’在‘%s’表达å¼ä¸­ï¼ŒäºŽ %C"
@@ -43674,7 +42361,6 @@ msgstr "%2$C处的 .%1$s. è¿ç®—符的访问规格说明已ç»è¢«æŒ‡å®š"
#: fortran/decl.c:6834
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: PROTECTED statement at %C"
msgid "PROTECTED statement at %C"
msgstr "Fortran 2003:%C处的 PROTECTED 语å¥"
@@ -43740,7 +42426,6 @@ msgstr "VALUE ä¸èƒ½ç”¨åœ¨%C处 BLOCK 内"
#: fortran/decl.c:7128
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: VALUE statement at %C"
msgid "VALUE statement at %C"
msgstr "Fortran 2003:%C处的 VALUE 语å¥"
@@ -43751,7 +42436,6 @@ msgstr "%C处 VALUE 语å¥è¯­æ³•é”™è¯¯"
#: fortran/decl.c:7177
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: VOLATILE statement at %C"
msgid "VOLATILE statement at %C"
msgstr "Fortran 2003:%C处的 VOLATILE 语å¥"
@@ -43767,7 +42451,6 @@ msgstr "%C处的 VOLATILE 语å¥è¯­æ³•é”™è¯¯"
#: fortran/decl.c:7236
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: ASYNCHRONOUS statement at %C"
msgid "ASYNCHRONOUS statement at %C"
msgstr "Fortran 2003:%C处的 ASYNCHRONOUS 语å¥"
@@ -43793,7 +42476,6 @@ msgstr "%C处 TYPE 定义中的歧义符å·"
#: fortran/decl.c:7416
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Symbol '%s' at %C has already been host associated"
msgid "Symbol '%s' at %C has not been previously defined"
msgstr "%2$C处符å·â€˜%1$s’已ç»ä¸Žä¸»æœºç›¸å…³è”"
@@ -43824,7 +42506,6 @@ msgstr "%C处的派生类型在模å—规格说明部分内åªèƒ½æ˜¯ PUBLIC"
#: fortran/decl.c:7492
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "ABSTRACT type '%s' used at %L"
msgid "ABSTRACT type at %C"
msgstr "%2$L处使用了 ABSTRACT 类型‘%1$s’"
@@ -43855,7 +42536,6 @@ msgstr "%C处 Cray 指针ä¸èƒ½æŒ‡å‘å‡å®šå¤–形数组"
#: fortran/decl.c:7722
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: ENUM and ENUMERATOR at %C"
msgid "ENUM and ENUMERATOR at %C"
msgstr "Fortran 2003:%C处的 ENUM 和 ENUMERATOR"
@@ -44171,7 +42851,6 @@ msgstr "%2$L处的转æ¢å†…建函数‘%1$s’ä¸å…许用在åˆå§‹åŒ–表达å¼ä
#: fortran/expr.c:2414
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: Evaluation of nonstandard initialization expression at %L"
msgid "Evaluation of nonstandard initialization expression at %L"
msgstr "扩展:%L处求éžæ ‡é‡åˆå§‹åŒ–表达å¼çš„值"
@@ -44302,19 +42981,16 @@ msgstr "%L处赋值å³æ‰‹è¾¹å‡ºçŽ° NULL"
#: fortran/expr.c:3161
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "POINTER valued function appears on right-hand side of assignment at %L"
msgid "POINTER-valued function appears on right-hand side of assignment at %L"
msgstr "%L处赋值å³æ‰‹è¾¹å‡ºçŽ°å€¼ä¸º POINTER 的函数"
#: fortran/expr.c:3171
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: BOZ literal at %L used to initialize non-integer variable '%s'"
msgid "BOZ literal at %L used to initialize non-integer variable '%s'"
msgstr "扩展:%L处 BOZ å­—é¢å€¼è¢«ç”¨æ¥åˆå§‹åŒ–éžæ•´æ•°å˜é‡â€˜%s’"
#: fortran/expr.c:3176 fortran/resolve.c:9062
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: BOZ literal at %L outside a DATA statement and outside INT/REAL/DBLE/CMPLX"
msgid "BOZ literal at %L outside a DATA statement and outside INT/REAL/DBLE/CMPLX"
msgstr "扩展:在 %L处的 BOZ å­—é¢å€¼åœ¨ä¸€ä¸ª DATA 语å¥ä¹‹å¤–并且也在 INT/REAL/DBLE/CMPLX 之外"
@@ -44375,7 +43051,6 @@ msgstr "%2$L处‘%1$s’需è¦è¾¹ç•Œè§„æ ¼"
#: fortran/expr.c:3343
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Bounds specification for '%s' in pointer assignment at %L"
msgid "Bounds specification for '%s' in pointer assignment at %L"
msgstr "Fortran 2003:%2$L处指针赋值语å¥ä¸­â€˜%1$s’的边界规格"
@@ -44406,7 +43081,6 @@ msgstr "%L处过程指针赋值éžæ³•"
#: fortran/expr.c:3445
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Statement function '%s' is invalid in procedure pointer assignment at %L"
msgid "Function result '%s' is invalid as proc-target in procedure pointer assignment at %L"
msgstr "语å¥å‡½æ•°â€˜%s’在%L处的过程指针赋值中是éžæ³•çš„"
@@ -44427,13 +43101,11 @@ msgstr "内部过程‘%s’在%L处的过程指针赋值中是éžæ³•çš„"
#: fortran/expr.c:3477
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Internal procedure '%s' is invalid in procedure pointer assignment at %L"
msgid "Intrinsic '%s' at %L is invalid in procedure pointer assignment"
msgstr "内部过程‘%s’在%L处的过程指针赋值中是éžæ³•çš„"
#: fortran/expr.c:3485
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Internal procedure '%s' is invalid in procedure pointer assignment at %L"
msgid "Nonintrinsic elemental procedure '%s' is invalid in procedure pointer assignment at %L"
msgstr "内部过程‘%s’在%L处的过程指针赋值中是éžæ³•çš„"
@@ -44444,7 +43116,6 @@ msgstr "%L处过程指针赋值ä¸åŒ¹é…:调用约定ä¸åŒ¹é…"
#: fortran/expr.c:3564 fortran/expr.c:3571 fortran/resolve.c:2430
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "NOPASS or explicit interface required at %C"
msgid "Explicit interface required for '%s' at %L: %s"
msgstr "%Cå¤„éœ€è¦ NOPASS 或显å¼æŽ¥å£"
@@ -44632,31 +43303,26 @@ msgstr "在%L处建立临时数组"
#: fortran/frontend-passes.c:562 fortran/frontend-passes.c:565
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Return value of function '%s' at %L not set"
msgid "Removing call to function '%s' at %L"
msgstr "%2$L处函数‘%1$s’的返回值没有设置"
#: fortran/frontend-passes.c:1668
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %C cannot be redefined inside loop beginning at %L"
msgid "Variable '%s' at %L set to undefined value inside loop beginning at %L as INTENT(OUT) argument to subroutine '%s'"
msgstr "å˜é‡â€˜%s’(ä½äºŽ %C)ä¸èƒ½åœ¨ä»Ž %L 开始的循环的内部é‡å®šä¹‰"
#: fortran/frontend-passes.c:1674
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %C cannot be redefined inside loop beginning at %L"
msgid "Variable '%s' at %L not definable inside loop beginning at %L as INTENT(INOUT) argument to subroutine '%s'"
msgstr "å˜é‡â€˜%s’(ä½äºŽ %C)ä¸èƒ½åœ¨ä»Ž %L 开始的循环的内部é‡å®šä¹‰"
#: fortran/frontend-passes.c:1738
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %C cannot be redefined inside loop beginning at %L"
msgid "Variable '%s' at %L set to undefined value inside loop beginning at %L as INTENT(OUT) argument to function '%s'"
msgstr "å˜é‡â€˜%s’(ä½äºŽ %C)ä¸èƒ½åœ¨ä»Ž %L 开始的循环的内部é‡å®šä¹‰"
#: fortran/frontend-passes.c:1744
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %C cannot be redefined inside loop beginning at %L"
msgid "Variable '%s' at %L not definable inside loop beginning at %L as INTENT(INOUT) argument to function '%s'"
msgstr "å˜é‡â€˜%s’(ä½äºŽ %C)ä¸èƒ½åœ¨ä»Ž %L 开始的循环的内部é‡å®šä¹‰"
@@ -44687,7 +43353,6 @@ msgstr "哑过程‘%s’在%C处ä¸èƒ½æœ‰æ³›åž‹æŽ¥å£"
#: fortran/interface.c:254
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: ABSTRACT INTERFACE at %C"
msgid "ABSTRACT INTERFACE at %C"
msgstr "Fortran 2003:%C处的 ABSTRACT INTERFACE"
@@ -44803,7 +43468,6 @@ msgstr ""
#: fortran/interface.c:1590
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Cray pointee '%s' in %s clause at %L"
msgid "Internal procedure '%s' in %s at %L"
msgstr "%3$L处 %2$s 分å¥ä¸­ çš„Cray 指针目标‘%1$s’"
@@ -44824,7 +43488,6 @@ msgstr "%2$L处的‘%1$s’并éžä¸€ä¸ªæ¨¡å—过程"
#: fortran/interface.c:1893
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Assumed shape array at %L must be a dummy argument"
msgid "The assumed-rank array at %L requires that the dummy argument '%s' has assumed-rank"
msgstr "%L处å‡å®šå¤–形的数组必须是一个虚å‚"
@@ -44865,7 +43528,6 @@ msgstr "%2$L处实å‚‘%1$s’类型ä¸åŒ¹é…;将 %3$s 传递给 %4$s"
#: fortran/interface.c:2007
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Assumed-shape actual argument at %L is incompatible with the non-assumed-shape dummy argument '%s' due to VOLATILE attribute"
msgid "Assumed-type actual argument at %L requires that dummy argument '%s' is of assumed type"
msgstr "%L处å‡å®šå¤–形的实å‚由于 VOLATILE 属性而与éžå‡å®šå¤–形虚å‚‘%s’ä¸å…¼å®¹"
@@ -45051,7 +43713,6 @@ msgstr ""
#: fortran/interface.c:2843
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Actual argument for '%s' must be a pointer at %L"
msgid "Actual CLASS array argument for '%s' must be a full array at %L"
msgstr "‘%s’的实å‚在%L处必须是一个指针"
@@ -45142,7 +43803,6 @@ msgstr "%2$L处过程‘%1$s’的关键字å‚æ•°è¦æ±‚显å¼çš„接å£"
#: fortran/interface.c:3298
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Symbol '%s' at %L already has an explicit interface"
msgid "Assumed-type argument %s at %L requires an explicit interface"
msgstr "符å·â€˜%s’在%L处已ç»æœ‰äº†æ˜¾å¼æŽ¥å£"
@@ -45158,7 +43818,6 @@ msgstr ""
#: fortran/interface.c:3328
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Keyword argument requires explicit interface for procedure '%s' at %L"
msgid "Assumed-rank argument requires an explicit interface at %L"
msgstr "%2$L处过程‘%1$s’的关键字å‚æ•°è¦æ±‚显å¼çš„接å£"
@@ -45179,7 +43838,6 @@ msgstr ""
#: fortran/interface.c:3902
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Entity '%s' at %C is already present in the interface"
msgid "Entity '%s' at %L is already present in the interface"
msgstr "%2$C处实体‘%1$s’已ç»å‡ºçŽ°åœ¨æŽ¥å£ä¸­"
@@ -45225,7 +43883,6 @@ msgstr "%2$L处的‘%1$s’覆盖了一个 FUNCTION 因此也必须是 FUNCTION
#: fortran/interface.c:4184
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Interface mismatch in dummy procedure '%s' at %L: %s"
msgid "Result mismatch for the overriding procedure '%s' at %L: %s"
msgstr "哑过程‘%s’接å£åœ¨%L处ä¸åŒ¹é…:%s"
@@ -45241,7 +43898,6 @@ msgstr "%3$L处‘%2$s’的虚å‚‘%1$s’应该命å为‘%4$s’以匹é…è¢
#: fortran/interface.c:4236
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Interface mismatch in dummy procedure '%s' at %L: %s"
msgid "Argument mismatch for the overriding procedure '%s' at %L: %s"
msgstr "哑过程‘%s’接å£åœ¨%L处ä¸åŒ¹é…:%s"
@@ -45267,31 +43923,26 @@ msgstr "%2$L处的‘%1$s’的传递对象虚å‚必须与被覆盖的过程传é
#: fortran/intrinsic.c:196
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "NULL pointer at %L is not permitted as actual argument of '%s' intrinsic function"
msgid "Variable with NO_ARG_CHECK attribute at %L is only permitted as argument to the intrinsic functions C_LOC and PRESENT"
msgstr "%L çš„ NULL 指针ä¸èƒ½ç”¨ä½œå†…建函数‘%s’的实å‚"
#: fortran/intrinsic.c:210
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "NULL pointer at %L is not permitted as actual argument of '%s' intrinsic function"
msgid "Assumed-type argument at %L is not permitted as actual argument to the intrinsic %s"
msgstr "%L çš„ NULL 指针ä¸èƒ½ç”¨ä½œå†…建函数‘%s’的实å‚"
#: fortran/intrinsic.c:217
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "NULL pointer at %L is not permitted as actual argument of '%s' intrinsic function"
msgid "Assumed-type argument at %L is only permitted as first actual argument to the intrinsic %s"
msgstr "%L çš„ NULL 指针ä¸èƒ½ç”¨ä½œå†…建函数‘%s’的实å‚"
#: fortran/intrinsic.c:224
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "NULL pointer at %L is not permitted as actual argument of '%s' intrinsic function"
msgid "Assumed-rank argument at %L is only permitted as actual argument to intrinsic inquiry functions"
msgstr "%L çš„ NULL 指针ä¸èƒ½ç”¨ä½œå†…建函数‘%s’的实å‚"
#: fortran/intrinsic.c:231
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "NULL pointer at %L is not permitted as actual argument of '%s' intrinsic function"
msgid "Assumed-rank argument at %L is only permitted as first actual argument to the intrinsic inquiry function %s"
msgstr "%L çš„ NULL 指针ä¸èƒ½ç”¨ä½œå†…建函数‘%s’的实å‚"
@@ -45342,19 +43993,16 @@ msgstr "%3$L处使用了内建的‘%1$s’(是 %2$s)"
#: fortran/intrinsic.c:4255
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Function '%s' as initialization expression at %L"
msgid "Function '%s' as initialization expression at %L"
msgstr "Fortran 2003:函数‘%s’在%L处用作åˆå§‹åŒ–表达å¼"
#: fortran/intrinsic.c:4331
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Elemental function as initialization expression with non-integer/non-character arguments at %L"
msgid "Elemental function as initialization expression with non-integer/non-character arguments at %L"
msgstr "Fortran 2003:作为åˆå§‹è¡¨è¾¾å¼çš„基本函数在%L处使用了éžæ•´æ•°æˆ–éžå­—符的å‚æ•°"
#: fortran/intrinsic.c:4402
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Subroutine call to intrinsic '%s' at %L is not PURE"
msgid "Subroutine call to intrinsic '%s' in DO CONCURRENT block at %L is not PURE"
msgstr "在%2$L处调用内建‘%1$s’的å­ä¾‹ç¨‹ä¸æ˜¯ PURE"
@@ -45395,25 +44043,21 @@ msgstr "扩展:%C处格å¼ä¸­çš„制表符"
#: fortran/io.c:455
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: DP format specifier not allowed at %C"
msgid "DP format specifier not allowed at %C"
msgstr "Fortran 2003:ä¸å…许在%C处使用 DP æ ¼å¼é™å®šç¬¦"
#: fortran/io.c:462
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: DC format specifier not allowed at %C"
msgid "DC format specifier not allowed at %C"
msgstr "Fortran 2003:ä¸å…许在%C处使用 DC æ ¼å¼é™å®šç¬¦"
#: fortran/io.c:651
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: X descriptor requires leading space count at %L"
msgid "X descriptor requires leading space count at %L"
msgstr "扩展:X æ述符在%L需è¦å‰å¯¼ç©ºæ ¼æ•°é‡"
#: fortran/io.c:680
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: $ descriptor at %L"
msgid "$ descriptor at %L"
msgstr "扩展:%L处的 $ æ述符"
@@ -45429,7 +44073,6 @@ msgstr "扩展:%L处的 L æ述符åŽç¼ºå°‘正的宽度"
#: fortran/io.c:826
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2008: 'G0' in format at %L"
msgid "'G0' in format at %L"
msgstr "Fortran 2008:%L处格å¼ä¸­çš„‘G0’"
@@ -45455,7 +44098,6 @@ msgstr "%L处的 H æ ¼å¼é™å®šç¬¦å·²åœ¨ Fortran 95 中被删除"
#: fortran/io.c:1059 fortran/io.c:1121
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: Missing comma at %L"
msgid "Missing comma at %L"
msgstr "扩展:%L处缺少逗å·"
@@ -45511,13 +44153,11 @@ msgstr "%L处 FORMAT 标记中的常é‡è¡¨è¾¾å¼é»˜è®¤ç±»åž‹å¿…须为 CHARACTER"
#: fortran/io.c:1399
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "FORMAT tag at %L must be of type CHARACTER or INTEGER"
msgid "FORMAT tag at %L must be of type default-kind CHARACTER or of INTEGER"
msgstr "%L处 FORMAT 标记必须具有类型 CHARACTER 或 INTEGER"
#: fortran/io.c:1405
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Deleted feature: ASSIGNED variable in FORMAT tag at %L"
msgid "ASSIGNED variable in FORMAT tag at %L"
msgstr "已删除的特性:%L处 FORMAT 标记中有 ASSIGNED å˜é‡"
@@ -45533,7 +44173,6 @@ msgstr "%2$L处的 FORMAT 标记中的标é‡â€˜%1$s’ä¸æ˜¯ä¸€ä¸ª ASSIGNED å˜é
#: fortran/io.c:1429
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: Non-character in FORMAT tag at %L"
msgid "Non-character in FORMAT tag at %L"
msgstr "扩展:%L处的 FORMAT 标记中有éžå­—符"
@@ -45559,7 +44198,6 @@ msgstr "%s 标记在%L处必须具有类型 %s"
#: fortran/io.c:1482
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Concat operator at %L must concatenate strings of the same kind"
msgid "%s tag at %L must be a character string of default kind"
msgstr "%L处的毗连è¿ç®—符必须毗连åŒä¸€ç§åˆ«çš„字符串"
@@ -45570,7 +44208,6 @@ msgstr "%s 标记在%L处必须是标é‡"
#: fortran/io.c:1495
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: IOMSG tag at %L"
msgid "IOMSG tag at %L"
msgstr "Fortran 2003:%L处的 IOMSG 标记"
@@ -45586,13 +44223,11 @@ msgstr "Fortran 95 在%2$L处的 %1$s 标记中需è¦é»˜è®¤çš„ INTEGER"
#: fortran/io.c:1516
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "UNIT not specified at %L"
msgid "NEWUNIT specifier at %L"
msgstr "%L没有指定 UNIT"
#: fortran/io.c:1534
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: CONVERT tag at %L"
msgid "CONVERT tag at %L"
msgstr "扩展:%L处的 CONVERT 标记"
@@ -45603,7 +44238,6 @@ msgstr "Fortran 2003:%3$C 处 %2$s 语å¥ä¸­çš„ %1$s é™å®šç¬¦å€¼ä¸ºâ€˜%4$s’
#: fortran/io.c:1727 fortran/io.c:1754
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%s specifier in %s statement at %C has invalid value '%s'"
msgid "%s specifier in %s statement at %C has value '%s'"
msgstr "为%3$C处 %2$s 语å¥ä¸­ %1$s 指定了éžæ³•çš„值‘%4$s’"
@@ -45639,37 +44273,31 @@ msgstr "%L处的 INQUIRE 语å¥éœ€è¦ FILE 或 UNIT é™å®šç¬¦"
#: fortran/io.c:1889
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: ASYNCHRONOUS= at %C not allowed in Fortran 95"
msgid "ASYNCHRONOUS= at %C not allowed in Fortran 95"
msgstr "Fortran 2003:%C处的 ASYNCHRONOUS= ä¸å…许用在 Fortran 95 中"
#: fortran/io.c:1907 fortran/io.c:3350
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: BLANK= at %C not allowed in Fortran 95"
msgid "BLANK= at %C not allowed in Fortran 95"
msgstr "Fortran 2003:%C处的 BLANK= ä¸å…许用在 Fortran 95 中"
#: fortran/io.c:1925 fortran/io.c:3329
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: DECIMAL= at %C not allowed in Fortran 95"
msgid "DECIMAL= at %C not allowed in Fortran 95"
msgstr "Fortran 2003:%C处的 DECIMAL= ä¸å…许用在 Fortran 95 中"
#: fortran/io.c:1957
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: ENCODING= at %C not allowed in Fortran 95"
msgid "ENCODING= at %C not allowed in Fortran 95"
msgstr "Fortran 2003:%C处的 ENCODING= ä¸å…许用在 Fortran 95 中"
#: fortran/io.c:2008 fortran/io.c:3392
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: ROUND= at %C not allowed in Fortran 95"
msgid "ROUND= at %C not allowed in Fortran 95"
msgstr "Fortran 2003:%C处的 ROUND= ä¸å…许用在 Fortran 95 中"
#: fortran/io.c:2028
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: SIGN= at %C not allowed in Fortran 95"
msgid "SIGN= at %C not allowed in Fortran 95"
msgstr "Fortran 2003:%C处的 SIGN= ä¸å…许用在 Fortran 95 中"
@@ -45680,7 +44308,6 @@ msgstr "CLOSE 语å¥ä¸å…许出现在%C处的 PURE 过程中"
#: fortran/io.c:2301
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "ASSIGNED GOTO statement at %L requires an INTEGER variable"
msgid "CLOSE statement at %L requires a UNIT number"
msgstr "ASSIGNED GOTO 语å¥åœ¨%L处需è¦ä¸€ä¸ª INTEGER å˜é‡"
@@ -45701,7 +44328,6 @@ msgstr "%L处的语å¥ä¸­ UNIT 数必须为éžè´Ÿçš„æ•°"
#: fortran/io.c:2474
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: FLUSH statement at %C"
msgid "FLUSH statement at %C"
msgstr "Fortran 2003:%C处的 FLUSH 语å¥"
@@ -45767,7 +44393,6 @@ msgstr ""
#: fortran/io.c:2904
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: Comma before i/o item list at %L"
msgid "Comma before i/o item list at %L"
msgstr "扩展:%L处 i/o 项目列表å‰çš„逗å·"
@@ -45814,7 +44439,6 @@ msgstr "%s 语å¥åœ¨%C处语法错误"
#: fortran/io.c:3246
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Internal file at %L with namelist"
msgid "Internal file at %L with namelist"
msgstr "Fortran 2003:%L处内部文件有å字列表"
@@ -45825,13 +44449,11 @@ msgstr "必须为%L处的 ASYNCHRONOUS= 指定一个åˆå§‹åŒ–表达å¼"
#: fortran/io.c:3371
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: PAD= at %C not allowed in Fortran 95"
msgid "PAD= at %C not allowed in Fortran 95"
msgstr "Fortran 2003:%C处的 PAD= ä¸å…许用在 Fortran 95 中"
#: fortran/io.c:3437
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: DELIM= at %C not allowed in Fortran 95"
msgid "DELIM= at %C not allowed in Fortran 95"
msgstr "Fortran 2003:%C处的 DELIM= ä¸å…许用在 Fortran 95 中"
@@ -45877,7 +44499,6 @@ msgstr "%L处的 INQUIRE 语å¥éœ€è¦å¸¦æœ‰ ID= 指定的 PENDING="
#: fortran/io.c:4188
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: WAIT at %C not allowed in Fortran 95"
msgid "WAIT at %C not allowed in Fortran 95"
msgstr "Fortran 2003:%C处的 WAIT ä¸å…许用在 Fortran 95 中"
@@ -45933,7 +44554,6 @@ msgstr "%C çš„å字太长"
#: fortran/match.c:560
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Invalid character '$' at %C. Use -fdollar-ok to allow it as an extension"
msgid "Invalid character '$' at %L. Use -fdollar-ok to allow it as an extension"
msgstr "%C处无效的字符‘$’。使用 -fdollar-ok 以å…许它作为一个扩展"
@@ -45974,7 +44594,6 @@ msgstr "%C处 PROGRAM 语å¥æ ¼å¼æ— æ•ˆ"
#: fortran/match.c:1395 fortran/match.c:1475
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Obsolescent feature: Arithmetic IF statement at %C"
msgid "Arithmetic IF statement at %C"
msgstr "已过时的特性:%C处的算术 IF 语å¥"
@@ -46186,7 +44805,6 @@ msgstr "%C处 Cray 指针必须是一个整数"
#: fortran/match.c:2766
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Unexpected CASE statement at %C"
msgid "PAUSE statement at %C"
msgstr "%C处éžé¢„期的 CASE 语å¥"
@@ -46224,19 +44842,16 @@ msgstr "%L有多余的 ERRMSG 标记"
#: fortran/match.c:2907
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Redundant SOURCE tag found at %L "
msgid "Redundant ACQUIRED_LOCK tag found at %L "
msgstr "%L有多余的 SOURCE 标记"
#: fortran/match.c:2972
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Empty IMPLICIT statement at %C"
msgid "LOCK statement at %C"
msgstr "%C处 IMPLICIT 语å¥ä¸ºç©º"
#: fortran/match.c:2982
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Empty IMPLICIT statement at %C"
msgid "UNLOCK statement at %C"
msgstr "%C处 IMPLICIT 语å¥ä¸ºç©º"
@@ -46262,13 +44877,11 @@ msgstr "PRINT 语å¥ä¸å…许出现在%C处的 PURE 过程中"
#: fortran/match.c:3211
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Deleted feature: ASSIGN statement at %C"
msgid "ASSIGN statement at %C"
msgstr "已删除的特性:%C处的 ASSIGN 语å¥"
#: fortran/match.c:3255
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Deleted feature: Assigned GOTO statement at %C"
msgid "Assigned GOTO statement at %C"
msgstr "已删除的特性:%C处赋值 GOTO 语å¥"
@@ -46279,7 +44892,6 @@ msgstr "%C处 GOTO 中的语å¥æ ‡å·åˆ—表ä¸èƒ½ä¸ºç©º"
#: fortran/match.c:3360
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Obsolescent feature: Computed GOTO at %C"
msgid "Computed GOTO at %C"
msgstr "已过时的特性:%C处的计算转移 GOTO 语å¥"
@@ -46290,7 +44902,6 @@ msgstr "%C处指定 TYPE IS 语法错误"
#: fortran/match.c:3442
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: typespec in ALLOCATE at %L"
msgid "typespec in ALLOCATE at %L"
msgstr "Fortran 2003:%L处 ALLOCATE 中有 typespec"
@@ -46331,13 +44942,11 @@ msgstr "%C处å¯åˆ†é…æ ‡é‡çš„外形规格说明"
#: fortran/match.c:3607
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: ERRMSG tag at %L"
msgid "ERRMSG tag at %L"
msgstr "Fortran 2003:%L处的 ERRMSG 标记"
#: fortran/match.c:3630
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: SOURCE tag at %L"
msgid "SOURCE tag at %L"
msgstr "Fortran 2003:%L处的 SOURCE 标记"
@@ -46353,7 +44962,6 @@ msgstr "%L处的 SOURCE 标记与%L处的类型指定冲çª"
#: fortran/match.c:3649
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "SOURCE tag at %L requires only a single entity in the allocation-list"
msgid "SOURCE tag at %L with more than a single allocate object"
msgstr "%L处的 SOURCE 标记在分é…列表中åªéœ€è¦ä¸€ä¸ªå•ç‹¬çš„实体"
@@ -46409,13 +45017,11 @@ msgstr ""
#: fortran/match.c:3906
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Allocate-object at %C is not a nonprocedure pointer or an allocatable variable"
msgid "Allocate-object at %C is not a nonprocedure pointer nor an allocatable variable"
msgstr "%C处的分é…对象ä¸æ˜¯ä¸€ä¸ªéžè¿‡ç¨‹æŒ‡é’ˆæˆ–å¯åˆ†é…çš„å˜é‡"
#: fortran/match.c:3943
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: ERRMSG at %L"
msgid "ERRMSG at %L"
msgstr "Fortran 2003:%L处的 ERRMSG"
@@ -46436,7 +45042,6 @@ msgstr "%C处的替代 RETURN 语å¥åªå…许出现在 SUBROUTINE 中"
#: fortran/match.c:4046
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: RETURN statement in main program at %C"
msgid "RETURN statement in main program at %C"
msgstr "扩展:%C处 RETURN 语å¥å‡ºçŽ°åœ¨ä¸»ç¨‹åºä¸­"
@@ -46545,7 +45150,6 @@ msgstr "%L处的语å¥å‡½æ•°æ˜¯é€’å½’çš„"
#: fortran/match.c:4941
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Statement function at %L is recursive"
msgid "Statement function at %C"
msgstr "%L处的语å¥å‡½æ•°æ˜¯é€’å½’çš„"
@@ -46561,7 +45165,6 @@ msgstr "%2$Cå¤„éœ€è¦ SELECT 构造的å—å‘%1$s’"
#: fortran/match.c:5339
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Syntax error in PROTECTED statement at %C"
msgid "parse error in SELECT TYPE statement at %C"
msgstr "%C处 PROTECTED 语å¥è¯­æ³•é”™è¯¯"
@@ -46638,7 +45241,6 @@ msgstr "扩展:%C处å•ç›®è¿ç®—符出现在算术è¿ç®—符之åŽ"
#: fortran/module.c:527
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: module nature in USE statement at %C"
msgid "module nature in USE statement at %C"
msgstr "Fortran 2003:%C处的 USE 语å¥ä¸­æ¨¡å—本性"
@@ -46654,7 +45256,6 @@ msgstr "%C处在模å—本性åŽéœ€è¦â€œ::â€"
#: fortran/module.c:562
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: \"USE :: module\" at %C"
msgid "\"USE :: module\" at %C"
msgstr "Fortran 2003:%C处的“USE :: moduleâ€"
@@ -46665,7 +45266,6 @@ msgstr "%C处的 USE 语å¥ç¼ºå°‘泛型规格"
#: fortran/module.c:629
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Renaming operators in USE statements at %C"
msgid "Renaming operators in USE statements at %C"
msgstr "Fortran 2003:%C处的 USE 语å¥ä¸­æ›´åè¿ç®—符"
@@ -46701,7 +45301,6 @@ msgstr "å字列表 %s ä¸èƒ½ä¸ºå¯¹ %s çš„ USE å…³è”æ¥æ›´å"
#: fortran/module.c:4494
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Name '%s' at %C is an ambiguous reference to '%s' from current program unit"
msgid "'%s' of module '%s', imported at %C, is also the name of the current program unit"
msgstr "%2$C处的å字‘%1$s’是从当å‰ç¨‹åºå•å…ƒå¯¹â€˜%3$s’有歧义的引用"
@@ -46778,13 +45377,11 @@ msgstr "%2$L处引用的符å·â€˜%1$sâ€™åœ¨å†…å»ºæ¨¡å— ISO_FORTRAN_ENV 中找ä¸
#: fortran/module.c:6307
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: ISO_FORTRAN_ENV intrinsic module at %C"
msgid "ISO_FORTRAN_ENV intrinsic module at %C"
msgstr "Fortran 2003:%C 处的 ISO_FORTRAN_ENV 内建模å—"
#: fortran/module.c:6319
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: ISO_C_BINDING module at %C"
msgid "ISO_C_BINDING module at %C"
msgstr "Fortran 2003:%C处的 ISO_C_BINDING 模å—"
@@ -46805,7 +45402,6 @@ msgstr "%2$C处对éžå†…建模å—‘%1$s’的使用与之å‰å¯¹å†…建模å—åå
#: fortran/module.c:6368
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "File '%s' opened at %C is not a GFORTRAN module file"
msgid "File '%s' opened at %C is not a GNU Fortran module file"
msgstr "%2$C处打开的文件的‘%1$s’并éžä¸€ä¸ª GFORTRAN 模å—文件"
@@ -46906,7 +45502,6 @@ msgstr "%L处的 IF 分å¥éœ€è¦ä¸€ä¸ªæ ‡é‡ LOGICAL 表达å¼"
#: fortran/openmp.c:824
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "IF clause at %L requires a scalar LOGICAL expression"
msgid "FINAL clause at %L requires a scalar LOGICAL expression"
msgstr "%L处的 IF 分å¥éœ€è¦ä¸€ä¸ªæ ‡é‡ LOGICAL 表达å¼"
@@ -47023,25 +45618,21 @@ msgstr "%L处 !$OMP ATOMIC 语å¥å¿…须设定一个内建类型的标é‡å€¼"
#: fortran/openmp.c:1189
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "!$OMP ATOMIC statement must set a scalar variable of intrinsic type at %L"
msgid "!$OMP ATOMIC READ statement must read from a scalar variable of intrinsic type at %L"
msgstr "%L处 !$OMP ATOMIC 语å¥å¿…须设定一个内建类型的标é‡å€¼"
#: fortran/openmp.c:1194
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "expr in !$OMP ATOMIC assignment var = var op expr must be scalar and cannot reference var at %L"
msgid "expr in !$OMP ATOMIC WRITE assignment var = expr must be scalar and cannot reference var at %L"
msgstr "%L处 !$OMP ATOMIC 赋值“å˜é‡ = å˜é‡ è¿ç®—符 表达å¼â€ä¸­çš„“表达å¼â€å¿…须是标é‡å¹¶ä¸”ä¸èƒ½å¼•ç”¨â€œå˜é‡â€"
#: fortran/openmp.c:1216 fortran/openmp.c:1486
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "!$OMP ATOMIC statement must set a scalar variable of intrinsic type at %L"
msgid "!$OMP ATOMIC CAPTURE capture statement must read from a scalar variable of intrinsic type at %L"
msgstr "%L处 !$OMP ATOMIC 语å¥å¿…须设定一个内建类型的标é‡å€¼"
#: fortran/openmp.c:1231
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "!$OMP ATOMIC statement must set a scalar variable of intrinsic type at %L"
msgid "!$OMP ATOMIC CAPTURE update statement must set a scalar variable of intrinsic type at %L"
msgstr "%L处 !$OMP ATOMIC 语å¥å¿…须设定一个内建类型的标é‡å€¼"
@@ -47052,7 +45643,6 @@ msgstr ""
#: fortran/openmp.c:1282
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "!$OMP ATOMIC assignment operator must be +, *, -, /, .AND., .OR., .EQV. or .NEQV. at %L"
msgid "!$OMP ATOMIC assignment operator must be binary +, *, -, /, .AND., .OR., .EQV. or .NEQV. at %L"
msgstr "%L处 !$OMP ATOMIC 赋值è¿ç®—符必须是 +ã€*ã€-ã€/ã€.AND.ã€.OR.ã€.EQV. 或 .NEQV."
@@ -47103,7 +45693,6 @@ msgstr "%L处 !$OMP ATOMIC 赋值的å³æ‰‹è¾¹å¿…须有一个è¿ç®—符或内建å‡
#: fortran/openmp.c:1464
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "!$OMP ATOMIC statement must set a scalar variable of intrinsic type at %L"
msgid "!$OMP ATOMIC CAPTURE capture statement must set a scalar variable of intrinsic type at %L"
msgstr "%L处 !$OMP ATOMIC 语å¥å¿…须设定一个内建类型的标é‡å€¼"
@@ -47199,7 +45788,6 @@ msgstr "-ffpe-trap çš„å‚数无效:%s"
#: fortran/options.c:564
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Argument to -ffpe-trap is not valid: %s"
msgid "Argument to -ffpe-summary is not valid: %s"
msgstr "-ffpe-trap çš„å‚数无效:%s"
@@ -47340,25 +45928,21 @@ msgstr "%C处 TYPE 中的组件必须先于 CONTAINS"
#: fortran/parse.c:1987
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Type-bound procedure at %C"
msgid "Type-bound procedure at %C"
msgstr "Fortran 2003:%C处的类型é™å®šè¿‡ç¨‹"
#: fortran/parse.c:1995
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Junk after GENERIC binding at %C"
msgid "GENERIC binding at %C"
msgstr "%C 处的泛型绑定åŽæœ‰åžƒåœ¾å­—符"
#: fortran/parse.c:2003
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: FINAL procedure declaration at %C"
msgid "FINAL procedure declaration at %C"
msgstr "Fortran 2003:%C处的的 FINAL 过程声明"
#: fortran/parse.c:2015
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2008: Derived type definition at %C with empty CONTAINS section"
msgid "Derived type definition at %C with empty CONTAINS section"
msgstr "Fortran 2008:%C的派生类型定义有空的 CONTAINS 节"
@@ -47394,7 +45978,6 @@ msgstr "%C处的 FINAL 声明必须在 CONTAINS 内"
#: fortran/parse.c:2119
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Derived type definition at %C without components"
msgid "Derived type definition at %C without components"
msgstr "Fortran 2003:%C处的派生类型定义没有组件"
@@ -47420,7 +46003,6 @@ msgstr "%C处é‡å¤çš„ SEQUENCE 语å¥"
#: fortran/parse.c:2173
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: CONTAINS block in derived type definition at %C"
msgid "CONTAINS block in derived type definition at %C"
msgstr "Fortran 2003:%C处的派生类型定义中的 CONTAINS å—"
@@ -47436,7 +46018,6 @@ msgstr ""
#: fortran/parse.c:2272
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Allocatable component of structure at %C must have a deferred shape"
msgid "Allocatable component %s at %L of type LOCK_TYPE must have a codimension"
msgstr "%C处å¯åˆ†é…的组件必须有延迟的外形"
@@ -47487,7 +46068,6 @@ msgstr "%s 语å¥ä¸èƒ½ç”¨åœ¨%C处 BLOCK 内"
#: fortran/parse.c:2653
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%s statement is not allowed inside of BLOCK at %C"
msgid "%s statement is not allowed inside of BLOCK DATA at %C"
msgstr "%s 语å¥ä¸èƒ½ç”¨åœ¨%C处 BLOCK 内"
@@ -47568,7 +46148,6 @@ msgstr "%C处 ENDDO 中的语å¥æ ‡å·ä¸Ž DO æ ‡å·ä¸åŒ¹é…"
#: fortran/parse.c:3372
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2008: BLOCK construct at %C"
msgid "BLOCK construct at %C"
msgstr "Fortran 2008:%C处的 BLOCK 结构"
@@ -47604,7 +46183,6 @@ msgstr "%2$C处的 %1$s 语å¥ä¸èƒ½ç»ˆæ­¢ä¸€ä¸ªä¸æˆå—çš„ DO 循环"
#: fortran/parse.c:3863
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "FORMAT statement at %L does not have a statement label"
msgid "DATA statement at %C after the first executable statement"
msgstr "%L处 FORMAT 语å¥æ²¡æœ‰è¯­å¥æ ‡å·"
@@ -47620,7 +46198,6 @@ msgstr "éžé¢„期的 %s 语å¥å‡ºçŽ°åœ¨%C处的 CONTAINS 段中"
#: fortran/parse.c:4135
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2008: CONTAINS statement without FUNCTION or SUBROUTINE statement at %C"
msgid "CONTAINS statement without FUNCTION or SUBROUTINE statement at %C"
msgstr "Fortran 2008:%C处 CONTAINS 语å¥æ²¡æœ‰ FUNCTION 或 SUBROUTINE 语å¥"
@@ -47631,7 +46208,6 @@ msgstr "%C处的 CONTAINS 语å¥å·²ç»åœ¨åŒ…å«çš„程åºå•å…ƒä¸­"
#: fortran/parse.c:4263
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Global name '%s' at %L is already being used as a %s at %L"
msgid "Global binding name '%s' at %L is already being used as a %s at %L"
msgstr "%2$L处的å字‘%1$s’已ç»åœ¨%4$L处被用作 %3$s"
@@ -47680,7 +46256,6 @@ msgstr "%C整数相对其ç§åˆ«è€Œè¨€å¤ªå¤§ã€‚这一检查å¯ç”¨ -fno-range-chec
#: fortran/primary.c:270
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: Hollerith constant at %C"
msgid "Hollerith constant at %C"
msgstr "扩展:%C处的è·å‹’瑞斯常é‡"
@@ -47701,7 +46276,6 @@ msgstr "%L处无效的è·å‹’瑞斯常é‡åŒ…å«ä¸€ä¸ªå®½å­—符"
#: fortran/primary.c:393
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: Hexadecimal constant at %C uses non-standard syntax"
msgid "Hexadecimal constant at %C uses non-standard syntax"
msgstr "扩展:%C处的å六进制常é‡ä½¿ç”¨äº†éžæ ‡å‡†è¯­æ³•"
@@ -47717,7 +46291,6 @@ msgstr "%C处的 BOZ 常é‡ä¸­æœ‰éžæ³•å­—符"
#: fortran/primary.c:431
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: BOZ constant at %C uses non-standard postfix syntax"
msgid "BOZ constant at %C uses non-standard postfix syntax"
msgstr "扩展:%C处的 BOZ 常é‡ä½¿ç”¨äº†éžæ ‡å‡†çš„åŽåºè¯­æ³•ã€‚"
@@ -47728,7 +46301,6 @@ msgstr "%2$C处的整数对其ç§åˆ« %1$i æ¥è¯´å¤ªå¤§"
#: fortran/primary.c:467
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: BOZ used outside a DATA statement at %C"
msgid "BOZ used outside a DATA statement at %C"
msgstr "Fortran 2003:%C处的 BOZ 用在了 DATA 语å¥ä¹‹å¤–"
@@ -47739,7 +46311,6 @@ msgstr ""
#: fortran/primary.c:561
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: Hollerith constant at %C"
msgid "Extension: exponent-letter 'q' in real-literal-constant at %C"
msgstr "扩展:%C处的è·å‹’瑞斯常é‡"
@@ -47755,13 +46326,11 @@ msgstr "%C处的实数有一个‘d’指数和一个显å¼çš„ç§åˆ«"
#: fortran/primary.c:663
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Real number at %C has a 'd' exponent and an explicit kind"
msgid "Real number at %C has a 'q' exponent and an explicit kind"
msgstr "%C处的实数有一个‘d’指数和一个显å¼çš„ç§åˆ«"
#: fortran/primary.c:677
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Invalid initializer %s in Data statement at %C"
msgid "Invalid exponent-letter 'q' in real-literal-constant at %C"
msgstr "%2$C处 DATA 语å¥åˆå§‹å€¼è®¾å®š %1$s 无效"
@@ -47822,7 +46391,6 @@ msgstr "%Cå¤„æ ‡é‡ PARAMETER è¦æ±‚å¤æ•°å¸¸é‡"
#: fortran/primary.c:1216
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Expected PARAMETER symbol in complex constant at %C"
msgid "PARAMETER symbol in complex constant at %C"
msgstr "%C处å¤æ•°å¸¸é‡ä¸­éœ€è¦ PARAMETER 符å·"
@@ -47843,7 +46411,6 @@ msgstr "关键字‘%s’在%C处已ç»å‡ºçŽ°åœ¨å½“å‰å®žå‚列表中"
#: fortran/primary.c:1645
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Unknown argument list function at %L"
msgid "argument list function at %C"
msgstr "%L处å‚数列表函数未知"
@@ -47874,13 +46441,11 @@ msgstr "在 %2$L 处的函数“%1$sâ€æ˜¯ INTRINSIC,但ä¸æ˜¯ä¸Žä¸€ä¸ªå†…建å
#: fortran/primary.c:1915
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Symbol '%s' at %L has no IMPLICIT type"
msgid "Symbol '%s' at %C has no IMPLICIT type"
msgstr "%2$L处的符å·â€˜%1$s’没有éšå¼ç±»åž‹"
#: fortran/primary.c:1921
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Unexpected character in variable list at %C"
msgid "Unexpected '%%' for nonderived-type variable '%s' at %C"
msgstr "%C处å˜é‡åˆ—表中有éžé¢„期的垃圾字符"
@@ -47906,7 +46471,6 @@ msgstr "Fortran 2003:%C处的过程指针组件"
#: fortran/primary.c:2363
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Structure constructor with missing optional arguments at %C"
msgid "Structure constructor with missing optional arguments at %C"
msgstr "Fortran 2003:%C处的结构构造函数丢失å¯é€‰çš„å‚æ•°"
@@ -47917,31 +46481,26 @@ msgstr "%2$C处结构构造函数中没有组件‘%1$s’的åˆå§‹å€¼è®¾å®šï¼"
#: fortran/primary.c:2418
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Can't construct ABSTRACT type '%s' at %C"
msgid "Can't construct ABSTRACT type '%s' at %L"
msgstr "%2$C处无法构建 ABSTRACT 类型‘%1$s’"
#: fortran/primary.c:2438
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Structure constructor with named arguments at %C"
msgid "Structure constructor with named arguments at %C"
msgstr "Fortran 2003:%C处的结构构造函数有有åçš„å‚æ•°"
#: fortran/primary.c:2453
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Component initializer without name after component named %s at %C!"
msgid "Component initializer without name after component named %s at %L!"
msgstr "%2$C处å为 %1$s 的组件之åŽçš„组件åˆå§‹å€¼è®¾å®šæ²¡æœ‰åå­—ï¼"
#: fortran/primary.c:2458
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Too many components in structure constructor at %C!"
msgid "Too many components in structure constructor at %L!"
msgstr "%C处结构构造函数中组件太多ï¼"
#: fortran/primary.c:2495
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Component '%s' is initialized twice in the structure constructor at %C!"
msgid "Component '%s' is initialized twice in the structure constructor at %L!"
msgstr "%2$C处结构构造函数中组件‘%1$s’被åˆå§‹åŒ–两次ï¼"
@@ -48012,31 +46571,26 @@ msgstr "%2$L处使用了 ABSTRACT 类型‘%1$s’"
#: fortran/resolve.c:145
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Interface '%s', used by procedure '%s' at %L, is declared in a later PROCEDURE statement"
msgid "Interface '%s' at %L is declared in a later PROCEDURE statement"
msgstr "为过程‘%2$s’在%3$L处使用的接å£â€˜%1$s’是在之åŽçš„ PROCEDURE 语å¥ä¸­å£°æ˜Žçš„"
#: fortran/resolve.c:158
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Interface '%s' at %C may not be generic"
msgid "Interface '%s' at %L may not be generic"
msgstr "%2$C处的接å£â€˜%1$s’ä¸èƒ½æ˜¯æ³›åž‹"
#: fortran/resolve.c:165
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Interface '%s' at %C may not be a statement function"
msgid "Interface '%s' at %L may not be a statement function"
msgstr "%2$C处的接å£â€˜%1$s’ä¸èƒ½æ˜¯ä¸ªè¯­å¥å‡½æ•°"
#: fortran/resolve.c:174
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Intrinsic procedure '%s' not allowed in PROCEDURE statement at %C"
msgid "Intrinsic procedure '%s' not allowed in PROCEDURE statement at %L"
msgstr "内建过程‘%s’ä¸å…许在 %C çš„ PROCEDURE 语å¥ä¸­"
#: fortran/resolve.c:180
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Interface '%s' of procedure '%s' at %L must be explicit"
msgid "Interface '%s' at %L must be explicit"
msgstr "%3$L处过程‘%2$s’的接å£â€˜%1$s’必须是显å¼çš„"
@@ -48057,7 +46611,6 @@ msgstr "函数‘%s’中的替代返回é™å®šç¬¦åœ¨%L处ä¸è¢«å…许"
#: fortran/resolve.c:311
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Keyword argument '%s' at %L is not in the procedure"
msgid "Self-referential argument '%s' at %L is not allowed"
msgstr "%2$L处关键字实å‚‘%1$s’ä¸åœ¨è¿‡ç¨‹é‡Œ"
@@ -48148,7 +46701,6 @@ msgstr "%2$L处函数‘%1$s’有ä¸åŒ¹é…的数组规格说明"
#: fortran/resolve.c:788
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: Function %s at %L with entries returning variables of different string lengths"
msgid "Function %s at %L with entries returning variables of different string lengths"
msgstr "扩展:%2$L处函数 %1$s 有返回ä¸åŒå­—符串长度的å˜é‡çš„表项"
@@ -48219,7 +46771,6 @@ msgstr ""
#: fortran/resolve.c:1001
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "COMMON block '%s' at %L is used as PARAMETER at %L"
msgid "COMMON block '%s' at %L uses the same global identifier as entity at %L"
msgstr "%2$L处的 COMMON å—‘%1$s’在%3$L处被用作 PARAMETER"
@@ -48240,7 +46791,6 @@ msgstr "%2$L处的 COMMON å—‘%1$s’在%3$L处被用作 PARAMETER"
#: fortran/resolve.c:1056
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %L cannot have both the POINTER and BIND(C) attributes"
msgid "COMMON block '%s' at %L can not have the EXTERNAL attribute"
msgstr "%2$L处å˜é‡â€˜%1$s’ä¸èƒ½æ—¢æœ‰ POINTER åˆæœ‰ BIND(C) 属性"
@@ -48251,31 +46801,26 @@ msgstr "%2$L处的 COMMON å—‘%1$s’也是一个内建过程"
#: fortran/resolve.c:1064
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: COMMON block '%s' at %L that is also a function result"
msgid "COMMON block '%s' at %L that is also a function result"
msgstr "Fortran 2003:%2$L处的 COMMON å—‘%1$s’也是一个函数返回值"
#: fortran/resolve.c:1069
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: COMMON block '%s' at %L that is also a global procedure"
msgid "COMMON block '%s' at %L that is also a global procedure"
msgstr "Fortran 2003:%2$L处的 COMMON å—‘%1$s’也是一个全局过程"
#: fortran/resolve.c:1152
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "The rank of the element in the derived type constructor at %L does not match that of the component (%d/%d)"
msgid "The rank of the element in the structure constructor at %L does not match that of the component (%d/%d)"
msgstr "%L处的派生类型构造函数中元素的秩与该组件(%d/%d)çš„ä¸åŒ¹é…"
#: fortran/resolve.c:1173
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "The element in the derived type constructor at %L, for pointer component '%s', is %s but should be %s"
msgid "The element in the structure constructor at %L, for pointer component '%s', is %s but should be %s"
msgstr "%L处指针组件‘%s’的派生类型构造函数中的元素是 %s 但应该是 %s"
#: fortran/resolve.c:1258
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "The NULL in the derived type constructor at %L is being applied to component '%s', which is neither a POINTER nor ALLOCATABLE"
msgid "The NULL in the structure constructor at %L is being applied to component '%s', which is neither a POINTER nor ALLOCATABLE"
msgstr "%L处派生类型构造函数中的 NULL 被用在既ä¸æ˜¯ä¸€ä¸ªæŒ‡é’ˆä¹Ÿä¸æ˜¯ ALLOCATABLE 的组件‘%s’上"
@@ -48286,7 +46831,6 @@ msgstr "%C处结构构造函数中组件太多ï¼"
#: fortran/resolve.c:1308
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "The element in the derived type constructor at %L, for pointer component '%s' should be a POINTER or a TARGET"
msgid "The element in the structure constructor at %L, for pointer component '%s' should be a POINTER or a TARGET"
msgstr "%L处指针组件‘%s’的派生类型构造函数中的元素应该是 POINTER 或 TARGET"
@@ -48297,7 +46841,6 @@ msgstr "%2$L处‘%1$s’的传递对象虚å‚ä¸èƒ½æ˜¯ ALLOCATABLE"
#: fortran/resolve.c:1336
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Invalid expression in the derived type constructor for pointer component '%s' at %L in PURE procedure"
msgid "Invalid expression in the structure constructor for pointer component '%s' at %L in PURE procedure"
msgstr "%2$L处指针组件‘%1$s’的派生类型构造函数中表达å¼æ— æ•ˆ"
@@ -48418,7 +46961,6 @@ msgstr "函数ä¸èƒ½è¿”回函数"
#: fortran/resolve.c:2442
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Interface mismatch in dummy procedure '%s' at %L: %s"
msgid "Interface mismatch in global procedure '%s' at %L: %s "
msgstr "哑过程‘%s’接å£åœ¨%L处ä¸åŒ¹é…:%s"
@@ -48470,13 +47012,11 @@ msgstr "%2$Lå¤„ç”¨æˆ·å®šä¹‰çš„éž ELEMENTAL 函数‘%1$s’ä¸å®¹è®¸å‡ºçŽ°åœ¨ W
#: fortran/resolve.c:2990
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "reference to non-PURE function '%s' at %L inside a FORALL %s"
msgid "Reference to non-PURE function '%s' at %L inside a FORALL %s"
msgstr "%2$Lå¤„å¯¹éž PURE 函数‘%1$s’的引用出现在 FORALL %3$s 中"
#: fortran/resolve.c:2997
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "reference to non-PURE function '%s' at %L inside a FORALL %s"
msgid "Reference to non-PURE function '%s' at %L inside a DO CONCURRENT %s"
msgstr "%2$Lå¤„å¯¹éž PURE 函数‘%1$s’的引用出现在 FORALL %3$s 中"
@@ -48502,7 +47042,6 @@ msgstr "%2$L处 FORALL å—内对‘%1$s’å­ä¾‹ç¨‹çš„调用ä¸æ˜¯ PURE"
#: fortran/resolve.c:3069
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Subroutine call to '%s' in FORALL block at %L is not PURE"
msgid "Subroutine call to '%s' in DO CONCURRENT block at %L is not PURE"
msgstr "%2$L处 FORALL å—内对‘%1$s’å­ä¾‹ç¨‹çš„调用ä¸æ˜¯ PURE"
@@ -48628,7 +47167,6 @@ msgstr "%L处数组索引必须具有 INTEGER 类型而ä¸æ˜¯ %s"
#: fortran/resolve.c:4129
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Extension: REAL array index at %L"
msgid "REAL array index at %L"
msgstr "扩展:%L处的 REAL 数组索引"
@@ -48704,7 +47242,6 @@ msgstr ""
#: fortran/resolve.c:4766
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Assumed shape array at %L must be a dummy argument"
msgid "Assumed-type variable %s at %L may only be used as actual argument"
msgstr "%L处å‡å®šå¤–形的数组必须是一个虚å‚"
@@ -48719,7 +47256,6 @@ msgstr ""
#: fortran/resolve.c:4791
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Assumed shape array at %L must be a dummy argument"
msgid "Assumed-rank variable %s at %L may only be used as actual argument"
msgstr "%L处å‡å®šå¤–形的数组必须是一个虚å‚"
@@ -48825,7 +47361,6 @@ msgstr "%L处的 DO 循环中的步进表达å¼ä¸èƒ½ä¸ºé›¶"
#: fortran/resolve.c:6292
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "DO loop at %L will be executed zero times"
msgid "DO loop at %L will be executed zero times (use -Wno-zerotrip to suppress)"
msgstr "%L处的 DO 循环会被执行零次"
@@ -49070,7 +47605,6 @@ msgstr "%2$L处派生类型‘%1$s’必须是‘%3$s’的一个扩展"
#: fortran/resolve.c:7966
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Unexpected use of subroutine name '%s' at %C"
msgid "Unexpected intrinsic type '%s' at %L"
msgstr "对å­è¿›ç¨‹å‘%s’éžé¢„期的使用,在%C处"
@@ -49086,7 +47620,6 @@ msgstr "%L处 SELECT TYPE 语å¥ä¸­æœ‰åŒé‡çš„ CLASS IS å—"
#: fortran/resolve.c:8256
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Invalid context for NULL() pointer at %%L"
msgid "Invalid context for NULL () intrinsic at %L"
msgstr "%%L处 NULL() 指针上下文无效"
@@ -49098,7 +47631,6 @@ msgstr ""
#: fortran/resolve.c:8296
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Data transfer element at %L cannot have POINTER components"
msgid "Data transfer element at %L cannot have POINTER components unless it is processed by a defined input/output procedure"
msgstr "%L处数æ®ä¼ è¾“元素ä¸èƒ½æœ‰ POINTER 组件"
@@ -49109,7 +47641,6 @@ msgstr "%L处数æ®ä¼ è¾“元素ä¸èƒ½æœ‰ POINTER 组件"
#: fortran/resolve.c:8312
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Data transfer element at %L cannot have ALLOCATABLE components"
msgid "Data transfer element at %L cannot have ALLOCATABLE components unless it is processed by a defined input/output procedure"
msgstr "%L处数æ®ä¼ è¾“元素ä¸èƒ½æœ‰ ALLOCATABLE 组件"
@@ -49125,7 +47656,6 @@ msgstr "%L处数æ®ä¼ è¾“元素ä¸èƒ½æ˜¯å¯¹ä¸€ä¸ªå‡å®šå¤§å°æ•°ç»„的全引用"
#: fortran/resolve.c:8388
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Stat-variable at %L must be a scalar INTEGER variable"
msgid "Lock variable at %L must be a scalar of type LOCK_TYPE"
msgstr "%L处 stat å˜é‡å¿…é¡»æ˜¯ä¸€ä¸ªæ ‡é‡ INTEGER å˜é‡"
@@ -49251,7 +47781,6 @@ msgstr ""
#: fortran/resolve.c:9196
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Assignment to a FORALL index variable at %L"
msgid "Assignment to an allocatable polymorphic variable at %L"
msgstr "%Lå¤„å‘ FORALL 索引å˜é‡èµ‹å€¼"
@@ -49318,7 +47847,6 @@ msgstr "%L处的 FORMALL 掩ç å­å¥éœ€è¦ä¸€ä¸ª LOGICAL 表达å¼"
#: fortran/resolve.c:10180
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Binding label '%s' at %L collides with the global entity '%s' at %L"
msgid "Variable %s with binding label %s at %L uses the same global identifier as entity at %L"
msgstr "%2$L处的绑定标å·â€˜%1$s’与 %4$L 处的全局实体‘%3$s’冲çª"
@@ -49334,7 +47862,6 @@ msgstr ""
#. multiple checks for the same procedure.
#: fortran/resolve.c:10210
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Binding label '%s' at %L collides with the global entity '%s' at %L"
msgid "Procedure %s with binding label %s at %L uses the same global identifier as entity at %L"
msgstr "%2$L处的绑定标å·â€˜%1$s’与 %4$L 处的全局实体‘%3$s’冲çª"
@@ -49350,7 +47877,6 @@ msgstr "%L处字符串太长"
#: fortran/resolve.c:10628
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Allocatable array '%s' at %L must have a deferred shape"
msgid "Allocatable array '%s' at %L must have a deferred shape or assumed rank"
msgstr "å¯åˆ†é…的数组‘%s’在%L处必须有延迟的外形"
@@ -49361,7 +47887,6 @@ msgstr "%2$L处标é‡å¯¹è±¡â€˜%1$s’ä¸èƒ½ä¸º ALLOCATABLE"
#: fortran/resolve.c:10640
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Array pointer '%s' at %L must have a deferred shape"
msgid "Array pointer '%s' at %L must have a deferred shape or assumed rank"
msgstr "数组指针‘%s’在%L处必须有延迟的外形"
@@ -49387,7 +47912,6 @@ msgstr "‘%s’在%L处ä¸èƒ½æ˜¯ä¸»æœºç›¸å…³çš„,因为它被在%L处声明的
#: fortran/resolve.c:10730
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2008: Implied SAVE for module variable '%s' at %L, needed due to the default initialization"
msgid "Implied SAVE for module variable '%s' at %L, needed due to the default initialization"
msgstr "Fortran 2008:%2$L处模å—å˜é‡â€˜%1$s’éšå«ä½¿ç”¨äº† SAVE,因为默认åˆå§‹åŒ–有此需求"
@@ -49415,7 +47939,6 @@ msgstr "å˜é‡â€˜%s’在%L处上下文中字符长度必须为常é‡"
#: fortran/resolve.c:10830
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "'%s' at %L must have constant character length in this context"
msgid "COMMON variable '%s' at %L must have constant character length"
msgstr "å˜é‡â€˜%s’在%L处上下文中字符长度必须为常é‡"
@@ -49456,13 +47979,11 @@ msgstr "%2$L处有字符值的语å¥å‡½æ•°â€˜%1$s’必须有常é‡é•¿åº¦"
#: fortran/resolve.c:10958
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: '%s' is of a PRIVATE type and cannot be a dummy argument of '%s', which is PUBLIC at %L"
msgid "'%s' is of a PRIVATE type and cannot be a dummy argument of '%s', which is PUBLIC at %L"
msgstr "Fortran 2003:%3$L处‘%1$s’是 PRIVATE 类型因而ä¸èƒ½æ˜¯ PUBLIC 类型‘%2$s’的虚å‚"
#: fortran/resolve.c:10980 fortran/resolve.c:11004
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Procedure '%s' in PUBLIC interface '%s' at %L takes dummy arguments of '%s' which is PRIVATE"
msgid "Procedure '%s' in PUBLIC interface '%s' at %L takes dummy arguments of '%s' which is PRIVATE"
msgstr "Fortran 2003: %3$L处 PUBLIC 接å£â€˜%2$s’中的过程‘%1$s’有 PRIVATE 的虚å‚‘%4$s’"
@@ -49508,19 +48029,16 @@ msgstr "CHARACTER(*) 函数‘%s’在%L处ä¸èƒ½æ˜¯é€’å½’çš„"
#: fortran/resolve.c:11093
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "CHARACTER(*) function '%s' at %L cannot be pure"
msgid "CHARACTER(*) function '%s' at %L"
msgstr "CHARACTER(*) 函数‘%s’在%L处ä¸èƒ½ä¸ºçº¯å‡½æ•°"
#: fortran/resolve.c:11102
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Procedure pointer component '%s' with PASS at %L must have at least one argument"
msgid "Procedure pointer '%s' at %L shall not be elemental"
msgstr "%2$L处的具有 PASS 的过程指针组件‘%1$s’必须至少有一个实å‚"
#: fortran/resolve.c:11108
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Dummy procedure '%s' at %C cannot have a generic interface"
msgid "Dummy procedure '%s' at %L shall not be elemental"
msgstr "哑过程‘%s’在%C处ä¸èƒ½æœ‰æ³›åž‹æŽ¥å£"
@@ -49766,7 +48284,6 @@ msgstr ""
#: fortran/resolve.c:12356
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: the component '%s' is a PRIVATE type and cannot be a component of '%s', which is PUBLIC at %L"
msgid "the component '%s' is a PRIVATE type and cannot be a component of '%s', which is PUBLIC at %L"
msgstr "Fortran 2003:%3$L处组åˆâ€˜%1$s’是一个 PRIVATE 类型,因此ä¸èƒ½æ˜¯ PUBLIC‘%2$s’的组åˆ"
@@ -49792,7 +48309,6 @@ msgstr "%2$L处具有 CLASS 的组件‘%1$s’必须是å¯åˆ†é…的或指针"
#: fortran/resolve.c:12484
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Component '%s' of '%s' at %L has the same name as an inherited type-bound procedure"
msgid "Generic name '%s' of function '%s' at %L being the same name as derived type at %L"
msgstr "%3$L处‘%2$s’的组件‘%1$s’与一个继承的类型é™å®šè¿‡ç¨‹åŒå"
@@ -49895,7 +48411,6 @@ msgstr "%L处å‡å®šå¤–形的数组必须是一个虚å‚"
#: fortran/resolve.c:12900
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Assumed shape array at %L must be a dummy argument"
msgid "Assumed-rank array at %L must be a dummy argument"
msgstr "%L处å‡å®šå¤–形的数组必须是一个虚å‚"
@@ -49941,13 +48456,11 @@ msgstr ""
#: fortran/resolve.c:12990
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %L cannot have both the ALLOCATABLE and BIND(C) attributes"
msgid "Variable %s at %L with NO_ARG_CHECK attribute may not have the ALLOCATABLE, CODIMENSION, POINTER or VALUE attribute"
msgstr "%2$L处å˜é‡â€˜%1$s’ä¸èƒ½æ—¢æœ‰ ALLOCATABLE åˆæœ‰ BIND(C) 属性"
#: fortran/resolve.c:12998
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %L cannot have both the POINTER and BIND(C) attributes"
msgid "Variable %s at %L with NO_ARG_CHECK attribute may not have the INTENT(OUT) attribute"
msgstr "%2$L处å˜é‡â€˜%1$s’ä¸èƒ½æ—¢æœ‰ POINTER åˆæœ‰ BIND(C) 属性"
@@ -49958,19 +48471,16 @@ msgstr ""
#: fortran/resolve.c:13025
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Assumed shape array '%s' at %L is not permitted in an initialization expression"
msgid "Assumed type of variable %s at %L is only permitted for dummy variables"
msgstr "%2$L处å‡å®šå¤–形数组‘%1$s’ä¸èƒ½ç”¨åœ¨åˆå§‹åŒ–表达å¼ä¸­"
#: fortran/resolve.c:13032
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %L cannot have both the ALLOCATABLE and BIND(C) attributes"
msgid "Assumed-type variable %s at %L may not have the ALLOCATABLE, CODIMENSION, POINTER or VALUE attribute"
msgstr "%2$L处å˜é‡â€˜%1$s’ä¸èƒ½æ—¢æœ‰ ALLOCATABLE åˆæœ‰ BIND(C) 属性"
#: fortran/resolve.c:13039
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Variable '%s' at %L cannot have both the POINTER and BIND(C) attributes"
msgid "Assumed-type variable %s at %L may not have the INTENT(OUT) attribute"
msgstr "%2$L处å˜é‡â€˜%1$s’ä¸èƒ½æ—¢æœ‰ POINTER åˆæœ‰ BIND(C) 属性"
@@ -49986,7 +48496,6 @@ msgstr "%2$L处å˜é‡â€˜%1$s’ä¸èƒ½æ˜¯ BIND(C) 因为它既ä¸æ˜¯ä¸€ä¸ª COMMON
#: fortran/resolve.c:13151
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: PUBLIC %s '%s' at %L of PRIVATE derived type '%s'"
msgid "PUBLIC %s '%s' at %L of PRIVATE derived type '%s'"
msgstr "Fortran 2003:%3$L处 PUBLIC %1$s‘%2$s’具有 PRIVATE 派生类型‘%4$s’"
@@ -50002,7 +48511,6 @@ msgstr "%2$L处INTENT(OUT) 虚å‚‘%1$s’是 ASSUMED SIZE,所以ä¸èƒ½æœ‰ä¸€
#: fortran/resolve.c:13196
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Dummy argument '%s' at %L cannot be INTENT(OUT)"
msgid "Dummy argument '%s' at %L of LOCK_TYPE shall not be INTENT(OUT)"
msgstr "%2$L处的‘%1$s’虚å‚ä¸èƒ½æ˜¯ INTENT(OUT)"
@@ -50178,7 +48686,6 @@ msgstr "%L çš„å­å­—符串长度为零"
#: fortran/resolve.c:14338
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: PUBLIC function '%s' at %L of PRIVATE type '%s'"
msgid "PUBLIC function '%s' at %L of PRIVATE type '%s'"
msgstr "Fortran 2003:%2$L处 PRIVATE 类型‘%3$s’的 PUBLIC 函数‘%1$s’"
@@ -50224,19 +48731,16 @@ msgstr "%2$L处 PURE 过程中包å«çš„过程‘%1$s’必须也是 PURE"
#: fortran/scanner.c:327
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "ignoring duplicate directory \"%s\"\n"
msgid "Include directory \"%s\": %s"
msgstr "忽略é‡å¤çš„目录“%sâ€\n"
#: fortran/scanner.c:333
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "ignoring nonexistent directory \"%s\"\n"
msgid "Nonexistent include directory \"%s\""
msgstr "忽略ä¸å­˜åœ¨çš„目录“%sâ€\n"
#: fortran/scanner.c:339
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%qD is not a type"
msgid "\"%s\" is not a directory"
msgstr "%qDä¸æ˜¯ä¸€ä¸ªç±»åž‹"
@@ -50536,7 +49040,6 @@ msgstr "%2$L 处的对象“%1$sâ€å¯¹äºŽæˆåˆ†çš„默认åˆå§‹åŒ–必须有 SAVE
#: fortran/symbol.c:474
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: Procedure pointer at %C"
msgid "Procedure pointer at %C"
msgstr "Fortran 2003:%C处的过程指针"
@@ -50562,13 +49065,11 @@ msgstr "%s 属性与 %s 属性冲çªï¼Œåœ¨â€˜%s’中,ä½äºŽ %L"
#: fortran/symbol.c:767
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%s attribute conflicts with %s attribute at %L"
msgid "%s attribute with %s attribute at %L"
msgstr "%s 属性与 %s 属性在%L处冲çª"
#: fortran/symbol.c:773
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%s attribute conflicts with %s attribute in '%s' at %L"
msgid "%s attribute with %s attribute in '%s' at %L"
msgstr "%s 属性与 %s 属性冲çªï¼Œåœ¨â€˜%s’中,ä½äºŽ %L"
@@ -50664,7 +49165,6 @@ msgstr "%L处指定了é‡å¤çš„ BIND 属性"
#: fortran/symbol.c:1590
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: BIND(C) at %L"
msgid "BIND(C) at %L"
msgstr "Fortran 2003:%L处的 BIND(C)"
@@ -50675,7 +49175,6 @@ msgstr "%L处指定了é‡å¤çš„ EXTENDS 属性"
#: fortran/symbol.c:1610
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Fortran 2003: EXTENDS at %L"
msgid "EXTENDS at %L"
msgstr "Fortran 2003:%L处的 EXTENDS"
@@ -50771,7 +49270,6 @@ msgstr "%2$Cå¤„çš„æ ‡å· %1$d å…ˆå‰ç”¨ä½œåˆ†æ”¯ç›®æ ‡"
#: fortran/symbol.c:2270
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Expected terminating name at %C"
msgid "Shared DO termination label %d at %C"
msgstr "%C处需è¦ç»“æŸå"
@@ -50868,7 +49366,6 @@ msgstr "走过错误的表达å¼ç±»åž‹(%d)"
#: fortran/trans-common.c:400
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Named COMMON block '%s' at %L shall be of the same size"
msgid "Named COMMON block '%s' at %L shall be of the same size as elsewhere (%lu vs %lu bytes)"
msgstr "%2$L处的 COMMON å—‘%1$s’应该有åŒæ ·çš„大å°"
@@ -50920,13 +49417,11 @@ msgstr "%2$L处的 COMMON‘%1$s’并ä¸å­˜åœ¨"
#: fortran/trans-common.c:1167
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "COMMON '%s' at %L requires %d bytes of padding at start; reorder elements or use -fno-align-commons"
msgid "COMMON '%s' at %L requires %d bytes of padding; reorder elements or use -fno-align-commons"
msgstr "%2$L处的 COMMON‘%1$sâ€™éœ€è¦ %3$d 字节填充在开始处;é‡æŽ’åºå…ƒç´ æˆ–使用 -fno-align-commons"
#: fortran/trans-common.c:1171
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "COMMON at %L requires %d bytes of padding at start; reorder elements or use -fno-align-commons"
msgid "COMMON at %L requires %d bytes of padding; reorder elements or use -fno-align-commons"
msgstr "%L处的 COMMON éœ€è¦ %d 字节填充在开始处;é‡æŽ’åºå…ƒç´ æˆ–使用 -fno-align-commons"
@@ -50967,7 +49462,6 @@ msgstr "模å—å˜é‡ %s çš„åŽç«¯å£°æ˜Žå·²å­˜åœ¨"
#: fortran/trans-decl.c:4257
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Unused variable '%s' declared at %L"
msgid "Unused PRIVATE module variable '%s' declared at %L"
msgstr "%2$L处声明了未使用的å˜é‡â€˜%1$s’"
@@ -50988,7 +49482,6 @@ msgstr "%2$L处声明了未使用的虚å‚‘%1$s’"
#: fortran/trans-decl.c:4837
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Unused variable '%s' declared at %L"
msgid "Unused module variable '%s' which has been explicitly imported at %L"
msgstr "%2$L处声明了未使用的å˜é‡â€˜%1$s’"
@@ -51004,7 +49497,6 @@ msgstr "%2$L处声明了未使用的å‚数‘%1$s’"
#: fortran/trans-decl.c:4896
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Unused parameter '%s' declared at %L"
msgid "Unused parameter '%s' which has been explicitly imported at %L"
msgstr "%2$L处声明了未使用的å‚数‘%1$s’"
@@ -51066,37 +49558,31 @@ msgstr ""
#: fortran/trans-types.c:496
#, fuzzy, gcc-internal-format
-#| msgid "integer kind=8 not available for -fdefault-integer-8 option"
msgid "INTEGER(KIND=8) is not available for -fdefault-integer-8 option"
msgstr "integer kind=8 在指定了 -fdefault-integer-8 选项时ä¸å¯ç”¨"
#: fortran/trans-types.c:504
#, fuzzy, gcc-internal-format
-#| msgid "integer kind=8 not available for -fdefault-integer-8 option"
msgid "INTEGER(KIND=8) is not available for -finteger-4-integer-8 option"
msgstr "integer kind=8 在指定了 -fdefault-integer-8 选项时ä¸å¯ç”¨"
#: fortran/trans-types.c:522
#, fuzzy, gcc-internal-format
-#| msgid "real kind=8 not available for -fdefault-real-8 option"
msgid "REAL(KIND=8) is not available for -fdefault-real-8 option"
msgstr "real kind=8 在指定了 -fdefault-real-8 选项时ä¸å¯ç”¨"
#: fortran/trans-types.c:529
#, fuzzy, gcc-internal-format
-#| msgid "real kind=8 not available for -fdefault-real-8 option"
msgid "REAL(KIND=8) is not available for -freal-4-real-8 option"
msgstr "real kind=8 在指定了 -fdefault-real-8 选项时ä¸å¯ç”¨"
#: fortran/trans-types.c:536
#, fuzzy, gcc-internal-format
-#| msgid "real kind=8 not available for -fdefault-real-8 option"
msgid "REAL(KIND=10) is not available for -freal-4-real-10 option"
msgstr "real kind=8 在指定了 -fdefault-real-8 选项时ä¸å¯ç”¨"
#: fortran/trans-types.c:543
#, fuzzy, gcc-internal-format
-#| msgid "real kind=8 not available for -fdefault-real-8 option"
msgid "REAL(KIND=16) is not available for -freal-4-real-16 option"
msgstr "real kind=8 在指定了 -fdefault-real-8 选项时ä¸å¯ç”¨"
@@ -51107,25 +49593,21 @@ msgstr "使用 -fdefault-double-8 æ—¶éœ€è¦ -fdefault-real-8"
#: fortran/trans-types.c:566
#, fuzzy, gcc-internal-format
-#| msgid "real kind=8 not available for -fdefault-real-8 option"
msgid "REAL(KIND=4) is not available for -freal-8-real-4 option"
msgstr "real kind=8 在指定了 -fdefault-real-8 选项时ä¸å¯ç”¨"
#: fortran/trans-types.c:573
#, fuzzy, gcc-internal-format
-#| msgid "real kind=8 not available for -fdefault-real-8 option"
msgid "REAL(KIND=10) is not available for -freal-8-real-10 option"
msgstr "real kind=8 在指定了 -fdefault-real-8 选项时ä¸å¯ç”¨"
#: fortran/trans-types.c:580
#, fuzzy, gcc-internal-format
-#| msgid "real kind=8 not available for -fdefault-real-8 option"
msgid "REAL(KIND=10) is not available for -freal-8-real-16 option"
msgstr "real kind=8 在指定了 -fdefault-real-8 选项时ä¸å¯ç”¨"
#: fortran/trans-types.c:1458
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Array element size too big"
msgid "Array element size too big at %C"
msgstr "数组元素太大"
@@ -51272,7 +49754,6 @@ msgstr "ä¸ä¼šæ‰§è¡Œåˆ°çš„字节ç ï¼Œä»Ž %d 直到方法末尾"
#. duplicate code from LOAD macro
#: java/expr.c:3549
#, fuzzy, gcc-internal-format
-#| msgid "unrecogized wide sub-instruction"
msgid "unrecognized wide sub-instruction"
msgstr "无法识别的宽å­æŒ‡ä»¤"
@@ -51570,19 +50051,16 @@ msgstr "ä¸èƒ½è¯»å– ELF 头:%s"
#: lto/lto.c:2302
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "cannot open %s"
msgid "Cannot open %s"
msgstr "ä¸èƒ½æ‰“å¼€ %s"
#: lto/lto.c:2323
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "cannot open %s"
msgid "Cannot map %s"
msgstr "ä¸èƒ½æ‰“å¼€ %s"
#: lto/lto.c:2334
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "cannot open %s"
msgid "Cannot read %s"
msgstr "ä¸èƒ½æ‰“å¼€ %s"
@@ -52006,7 +50484,6 @@ msgstr "全局/é™æ€å˜é‡èµ‹å€¼å·²è¢«æ‰“æ–­"
#: objc/objc-act.c:3964 objc/objc-act.c:3992 objc/objc-act.c:4048
#, fuzzy, gcc-internal-format
-#| msgid "unused variable %q+D"
msgid "duplicate instance variable %q+D"
msgstr "未使用的å˜é‡%q+D"
@@ -52125,7 +50602,6 @@ msgstr "也找到了%<%c%s%>"
#. rtype is an IDENTIFIER_NODE at this point.
#: objc/objc-act.c:5398 objc/objc-act.c:5532
#, fuzzy, gcc-internal-format
-#| msgid "definition of protocol %qE not found"
msgid "@interface of class %qE not found"
msgstr "找ä¸åˆ°åè®®%qE的方法定义"
diff --git a/gcc/postreload.c b/gcc/postreload.c
index 47687203d66..29ba81b41d5 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -584,7 +584,7 @@ reload_cse_simplify_operands (rtx insn, rtx testreg)
alternative yet and the operand being replaced is not
a cheap CONST_INT. */
if (op_alt_regno[i][j] == -1
- && recog_data.alternative_enabled_p[j]
+ && TEST_BIT (recog_data.enabled_alternatives, j)
&& reg_fits_class_p (testreg, rclass, 0, mode)
&& (!CONST_INT_P (recog_data.operand[i])
|| (set_src_cost (recog_data.operand[i],
diff --git a/gcc/predict.c b/gcc/predict.c
index 165cc4e2ec6..55a645d893f 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -739,12 +739,10 @@ dump_prediction (FILE *file, enum br_predictor predictor, int probability,
if (bb->count)
{
- fprintf (file, " exec ");
- fprintf (file, HOST_WIDEST_INT_PRINT_DEC, bb->count);
+ fprintf (file, " exec %"PRId64, bb->count);
if (e)
{
- fprintf (file, " hit ");
- fprintf (file, HOST_WIDEST_INT_PRINT_DEC, e->count);
+ fprintf (file, " hit %"PRId64, e->count);
fprintf (file, " (%.1f%%)", e->count * 100.0 / bb->count);
}
}
diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h
index 1deaa667290..e315c41642e 100644
--- a/gcc/pretty-print.h
+++ b/gcc/pretty-print.h
@@ -271,8 +271,6 @@ pp_get_prefix (const pretty_printer *pp) { return pp->prefix; }
while (0)
#define pp_wide_integer(PP, I) \
pp_scalar (PP, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) I)
-#define pp_widest_integer(PP, I) \
- pp_scalar (PP, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT) I)
#define pp_pointer(PP, P) pp_scalar (PP, "%p", P)
#define pp_identifier(PP, ID) pp_string (PP, (pp_translate_identifiers (PP) \
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index 3b0efa3938a..2f9f54738c0 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -187,6 +187,14 @@ print_rtx (const_rtx in_rtx)
i = 5;
#endif
+ if (INSN_CHAIN_CODE_P (GET_CODE (in_rtx)))
+ {
+ if (flag_dump_unnumbered)
+ fprintf (outfile, " #");
+ else
+ fprintf (outfile, " %d", INSN_UID (in_rtx));
+ }
+
/* Get the format string and skip the first elements if we have handled
them already. */
format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i;
@@ -215,26 +223,17 @@ print_rtx (const_rtx in_rtx)
An exception is the third field of a NOTE, where it indicates
that the field has several different valid contents. */
case '0':
- if (i == 1 && REG_P (in_rtx))
- {
- if (REGNO (in_rtx) != ORIGINAL_REGNO (in_rtx))
- fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx));
- }
#ifndef GENERATOR_FILE
- else if (i == 1 && GET_CODE (in_rtx) == SYMBOL_REF)
+ if (i == 1 && GET_CODE (in_rtx) == SYMBOL_REF)
{
int flags = SYMBOL_REF_FLAGS (in_rtx);
if (flags)
fprintf (outfile, " [flags %#x]", flags);
- }
- else if (i == 2 && GET_CODE (in_rtx) == SYMBOL_REF)
- {
tree decl = SYMBOL_REF_DECL (in_rtx);
if (decl)
print_node_brief (outfile, "", decl, dump_flags);
}
-#endif
- else if (i == 4 && NOTE_P (in_rtx))
+ else if (i == 3 && NOTE_P (in_rtx))
{
switch (NOTE_KIND (in_rtx))
{
@@ -249,19 +248,15 @@ print_rtx (const_rtx in_rtx)
case NOTE_INSN_BLOCK_BEG:
case NOTE_INSN_BLOCK_END:
-#ifndef GENERATOR_FILE
dump_addr (outfile, " ", NOTE_BLOCK (in_rtx));
-#endif
sawclose = 1;
break;
case NOTE_INSN_BASIC_BLOCK:
{
-#ifndef GENERATOR_FILE
basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
if (bb != 0)
fprintf (outfile, " [bb %d]", bb->index);
-#endif
break;
}
@@ -278,35 +273,29 @@ print_rtx (const_rtx in_rtx)
case NOTE_INSN_SWITCH_TEXT_SECTIONS:
{
-#ifndef GENERATOR_FILE
basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
if (bb != 0)
fprintf (outfile, " [bb %d]", bb->index);
-#endif
break;
}
case NOTE_INSN_VAR_LOCATION:
case NOTE_INSN_CALL_ARG_LOCATION:
-#ifndef GENERATOR_FILE
fputc (' ', outfile);
print_rtx (NOTE_VAR_LOCATION (in_rtx));
-#endif
break;
case NOTE_INSN_CFI:
-#ifndef GENERATOR_FILE
fputc ('\n', outfile);
output_cfi_directive (outfile, NOTE_CFI (in_rtx));
fputc ('\t', outfile);
-#endif
break;
default:
break;
}
}
- else if (i == 8 && JUMP_P (in_rtx) && JUMP_LABEL (in_rtx) != NULL)
+ else if (i == 7 && JUMP_P (in_rtx) && JUMP_LABEL (in_rtx) != NULL)
{
/* Output the JUMP_LABEL reference. */
fprintf (outfile, "\n%s%*s -> ", print_rtx_head, indent * 2, "");
@@ -319,20 +308,16 @@ print_rtx (const_rtx in_rtx)
}
else if (i == 0 && GET_CODE (in_rtx) == VALUE)
{
-#ifndef GENERATOR_FILE
cselib_val *val = CSELIB_VAL_PTR (in_rtx);
fprintf (outfile, " %u:%u", val->uid, val->hash);
dump_addr (outfile, " @", in_rtx);
dump_addr (outfile, "/", (void*)val);
-#endif
}
else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
{
-#ifndef GENERATOR_FILE
fprintf (outfile, " D#%i",
DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (in_rtx)));
-#endif
}
else if (i == 0 && GET_CODE (in_rtx) == ENTRY_VALUE)
{
@@ -342,18 +327,19 @@ print_rtx (const_rtx in_rtx)
print_rtx (ENTRY_VALUE_EXP (in_rtx));
indent -= 2;
}
+#endif
break;
case 'e':
do_e:
indent += 2;
- if (i == 7 && INSN_P (in_rtx))
+ if (i == 6 && INSN_P (in_rtx))
/* Put REG_NOTES on their own line. */
fprintf (outfile, "\n%s%*s",
print_rtx_head, indent * 2, "");
if (!sawclose)
fprintf (outfile, " ");
- if (i == 8 && CALL_P (in_rtx))
+ if (i == 7 && CALL_P (in_rtx))
{
in_call_function_usage = true;
print_rtx (XEXP (in_rtx, i));
@@ -403,7 +389,7 @@ print_rtx (const_rtx in_rtx)
break;
case 'i':
- if (i == 5 && INSN_P (in_rtx))
+ if (i == 4 && INSN_P (in_rtx))
{
#ifndef GENERATOR_FILE
/* Pretty-print insn locations. Ignore scoping as it is mostly
@@ -432,7 +418,7 @@ print_rtx (const_rtx in_rtx)
LOCATION_LINE (ASM_INPUT_SOURCE_LOCATION (in_rtx)));
#endif
}
- else if (i == 6 && NOTE_P (in_rtx))
+ else if (i == 5 && NOTE_P (in_rtx))
{
/* This field is only used for NOTE_INSN_DELETED_LABEL, and
other times often contains garbage from INSN->NOTE death. */
@@ -505,6 +491,8 @@ print_rtx (const_rtx in_rtx)
REG_OFFSET (in_rtx));
fputs (" ]", outfile);
}
+ if (REG_P (in_rtx) && REGNO (in_rtx) != ORIGINAL_REGNO (in_rtx))
+ fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx));
#endif
if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i)
diff --git a/gcc/profile.c b/gcc/profile.c
index 83cbc07967b..3282ee7a3c4 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -237,10 +237,10 @@ get_working_sets (void)
ws_info = &gcov_working_sets[ws_ix];
/* Print out the percentage using int arithmatic to avoid float. */
fprintf (dump_file, "\t\t%u.%02u%%: num counts=%u, min counter="
- HOST_WIDEST_INT_PRINT_DEC "\n",
+ "%"PRId64 "\n",
pct / 100, pct - (pct / 100 * 100),
ws_info->num_counters,
- (HOST_WIDEST_INT)ws_info->min_counter);
+ (int64_t)ws_info->min_counter);
}
}
}
@@ -318,7 +318,7 @@ is_edge_inconsistent (vec<edge, va_gc> *edges)
if (dump_file)
{
fprintf (dump_file,
- "Edge %i->%i is inconsistent, count"HOST_WIDEST_INT_PRINT_DEC,
+ "Edge %i->%i is inconsistent, count%"PRId64,
e->src->index, e->dest->index, e->count);
dump_bb (dump_file, e->src, 0, TDF_DETAILS);
dump_bb (dump_file, e->dest, 0, TDF_DETAILS);
@@ -367,7 +367,7 @@ is_inconsistent (void)
if (dump_file)
{
fprintf (dump_file, "BB %i count is negative "
- HOST_WIDEST_INT_PRINT_DEC,
+ "%"PRId64,
bb->index,
bb->count);
dump_bb (dump_file, bb, 0, TDF_DETAILS);
@@ -379,7 +379,7 @@ is_inconsistent (void)
if (dump_file)
{
fprintf (dump_file, "BB %i count does not match sum of incoming edges "
- HOST_WIDEST_INT_PRINT_DEC" should be " HOST_WIDEST_INT_PRINT_DEC,
+ "%"PRId64" should be %"PRId64,
bb->index,
bb->count,
sum_edge_counts (bb->preds));
@@ -394,7 +394,7 @@ is_inconsistent (void)
if (dump_file)
{
fprintf (dump_file, "BB %i count does not match sum of outgoing edges "
- HOST_WIDEST_INT_PRINT_DEC" should be " HOST_WIDEST_INT_PRINT_DEC,
+ "%"PRId64" should be %"PRId64,
bb->index,
bb->count,
sum_edge_counts (bb->succs));
@@ -471,8 +471,8 @@ read_profile_edge_counts (gcov_type *exec_counts)
{
fprintf (dump_file, "\nRead edge from %i to %i, count:",
bb->index, e->dest->index);
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) e->count);
+ fprintf (dump_file, "%"PRId64,
+ (int64_t) e->count);
}
}
}
diff --git a/gcc/realmpfr.h b/gcc/realmpfr.h
index 0595f39b997..d909dba2d03 100644
--- a/gcc/realmpfr.h
+++ b/gcc/realmpfr.h
@@ -25,9 +25,6 @@
#include <mpc.h>
#include "real.h"
-/* In builtins.c. */
-extern tree do_mpc_arg2 (tree, tree, tree, int, int (*)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t));
-
/* Convert between MPFR and REAL_VALUE_TYPE. The caller is
responsible for initializing and clearing the MPFR parameter. */
diff --git a/gcc/recog.c b/gcc/recog.c
index 2f5cf8eb577..c4706940bec 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -61,6 +61,11 @@ static void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx, bool);
static void validate_replace_src_1 (rtx *, void *);
static rtx split_insn (rtx);
+struct target_recog default_target_recog;
+#if SWITCHABLE_TARGET
+struct target_recog *this_target_recog = &default_target_recog;
+#endif
+
/* Nonzero means allow operands to be volatile.
This should be 0 if you are generating rtl, such as if you are calling
the functions in optabs.c and expmed.c (most of the time).
@@ -2137,6 +2142,48 @@ mode_dependent_address_p (rtx addr, addr_space_t addrspace)
return targetm.mode_dependent_address_p (addr, addrspace);
}
+/* Return the mask of operand alternatives that are allowed for INSN.
+ This mask depends only on INSN and on the current target; it does not
+ depend on things like the values of operands. */
+
+alternative_mask
+get_enabled_alternatives (rtx insn)
+{
+ /* Quick exit for asms and for targets that don't use the "enabled"
+ attribute. */
+ int code = INSN_CODE (insn);
+ if (code < 0 || !HAVE_ATTR_enabled)
+ return ALL_ALTERNATIVES;
+
+ /* Calling get_attr_enabled can be expensive, so cache the mask
+ for speed. */
+ if (this_target_recog->x_enabled_alternatives[code])
+ return this_target_recog->x_enabled_alternatives[code];
+
+ /* Temporarily install enough information for get_attr_enabled to assume
+ that the insn operands are already cached. As above, the attribute
+ mustn't depend on the values of operands, so we don't provide their
+ real values here. */
+ rtx old_insn = recog_data.insn;
+ int old_alternative = which_alternative;
+
+ recog_data.insn = insn;
+ alternative_mask enabled = ALL_ALTERNATIVES;
+ int n_alternatives = insn_data[code].n_alternatives;
+ for (int i = 0; i < n_alternatives; i++)
+ {
+ which_alternative = i;
+ if (!get_attr_enabled (insn))
+ enabled &= ~ALTERNATIVE_BIT (i);
+ }
+
+ recog_data.insn = old_insn;
+ which_alternative = old_alternative;
+
+ this_target_recog->x_enabled_alternatives[code] = enabled;
+ return enabled;
+}
+
/* Like extract_insn, but save insn extracted and don't extract again, when
called again for the same insn expecting that recog_data still contain the
valid information. This is used primary by gen_attr infrastructure that
@@ -2269,19 +2316,7 @@ extract_insn (rtx insn)
gcc_assert (recog_data.n_alternatives <= MAX_RECOG_ALTERNATIVES);
- if (INSN_CODE (insn) < 0)
- for (i = 0; i < recog_data.n_alternatives; i++)
- recog_data.alternative_enabled_p[i] = true;
- else
- {
- recog_data.insn = insn;
- for (i = 0; i < recog_data.n_alternatives; i++)
- {
- which_alternative = i;
- recog_data.alternative_enabled_p[i]
- = HAVE_ATTR_enabled ? get_attr_enabled (insn) : 1;
- }
- }
+ recog_data.enabled_alternatives = get_enabled_alternatives (insn);
recog_data.insn = NULL;
which_alternative = -1;
@@ -2314,7 +2349,7 @@ preprocess_constraints (void)
op_alt[j].matches = -1;
op_alt[j].matched = -1;
- if (!recog_data.alternative_enabled_p[j])
+ if (!TEST_BIT (recog_data.enabled_alternatives, j))
{
p = skip_alternative (p);
continue;
@@ -2490,7 +2525,7 @@ constrain_operands (int strict)
int lose = 0;
funny_match_index = 0;
- if (!recog_data.alternative_enabled_p[which_alternative])
+ if (!TEST_BIT (recog_data.enabled_alternatives, which_alternative))
{
int i;
@@ -4164,3 +4199,19 @@ make_pass_split_for_shorten_branches (gcc::context *ctxt)
{
return new pass_split_for_shorten_branches (ctxt);
}
+
+/* (Re)initialize the target information after a change in target. */
+
+void
+recog_init ()
+{
+ /* The information is zero-initialized, so we don't need to do anything
+ first time round. */
+ if (!this_target_recog->x_initialized)
+ {
+ this_target_recog->x_initialized = true;
+ return;
+ }
+ memset (this_target_recog->x_enabled_alternatives, 0,
+ sizeof (this_target_recog->x_enabled_alternatives));
+}
diff --git a/gcc/recog.h b/gcc/recog.h
index 89e87a94971..8c8d55f3e9f 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -20,8 +20,17 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_RECOG_H
#define GCC_RECOG_H
-/* Random number that should be large enough for all purposes. */
+/* Random number that should be large enough for all purposes. Also define
+ a type that has at least MAX_RECOG_ALTERNATIVES + 1 bits, with the extra
+ bit giving an invalid value that can be used to mean "uninitialized". */
#define MAX_RECOG_ALTERNATIVES 30
+typedef unsigned int alternative_mask;
+
+/* A mask of all alternatives. */
+#define ALL_ALTERNATIVES ((alternative_mask) -1)
+
+/* A mask containing just alternative X. */
+#define ALTERNATIVE_BIT(X) ((alternative_mask) 1 << (X))
/* Types of operands. */
enum op_type {
@@ -235,11 +244,11 @@ struct recog_data_d
/* True if insn is ASM_OPERANDS. */
bool is_asm;
- /* Specifies whether an insn alternative is enabled using the
- `enabled' attribute in the insn pattern definition. For back
- ends not using the `enabled' attribute the array fields are
- always set to `true' in expand_insn. */
- bool alternative_enabled_p [MAX_RECOG_ALTERNATIVES];
+ /* Specifies whether an insn alternative is enabled using the `enabled'
+ attribute in the insn pattern definition. For back ends not using
+ the `enabled' attribute the bits are always set to 1 in expand_insn.
+ Bits beyond the last alternative are also set to 1. */
+ alternative_mask enabled_alternatives;
/* In case we are caching, hold insn data was generated for. */
rtx insn;
@@ -361,4 +370,25 @@ struct insn_data_d
extern const struct insn_data_d insn_data[];
extern int peep2_current_count;
+#ifndef GENERATOR_FILE
+#include "insn-codes.h"
+
+/* Target-dependent globals. */
+struct target_recog {
+ bool x_initialized;
+ alternative_mask x_enabled_alternatives[LAST_INSN_CODE];
+};
+
+extern struct target_recog default_target_recog;
+#if SWITCHABLE_TARGET
+extern struct target_recog *this_target_recog;
+#else
+#define this_target_recog (&default_target_recog)
+#endif
+
+alternative_mask get_enabled_alternatives (rtx);
+
+void recog_init ();
+#endif
+
#endif /* GCC_RECOG_H */
diff --git a/gcc/ree.c b/gcc/ree.c
index 77f13842a52..ade413e8bed 100644
--- a/gcc/ree.c
+++ b/gcc/ree.c
@@ -507,6 +507,8 @@ struct ATTRIBUTE_PACKED ext_modified
/* Kind of modification of the insn. */
ENUM_BITFIELD(ext_modified_kind) kind : 2;
+ unsigned int do_not_reextend : 1;
+
/* True if the insn is scheduled to be deleted. */
unsigned int deleted : 1;
};
@@ -712,8 +714,10 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
register than the source operand, then additional restrictions
are needed. Note we have to handle cases where we have nested
extensions in the source operand. */
- if (REGNO (SET_DEST (PATTERN (cand->insn)))
- != REGNO (get_extended_src_reg (SET_SRC (PATTERN (cand->insn)))))
+ bool copy_needed
+ = (REGNO (SET_DEST (PATTERN (cand->insn)))
+ != REGNO (get_extended_src_reg (SET_SRC (PATTERN (cand->insn)))));
+ if (copy_needed)
{
/* In theory we could handle more than one reaching def, it
just makes the code to update the insn stream more complex. */
@@ -722,7 +726,7 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
/* We require the candidate not already be modified. It may,
for example have been changed from a (sign_extend (reg))
- into (zero_extend (sign_extend (reg)).
+ into (zero_extend (sign_extend (reg))).
Handling that case shouldn't be terribly difficult, but the code
here and the code to emit copies would need auditing. Until
@@ -777,6 +781,31 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
|| reg_set_between_p (SET_DEST (PATTERN (cand->insn)),
def_insn, cand->insn))
return false;
+
+ /* We must be able to copy between the two registers. Generate,
+ recognize and verify constraints of the copy. Also fail if this
+ generated more than one insn.
+
+ This generates garbage since we throw away the insn when we're
+ done, only to recreate it later if this test was successful. */
+ start_sequence ();
+ rtx sub_rtx = *get_sub_rtx (def_insn);
+ rtx pat = PATTERN (cand->insn);
+ rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
+ REGNO (XEXP (SET_SRC (pat), 0)));
+ rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
+ REGNO (SET_DEST (pat)));
+ emit_move_insn (new_dst, new_src);
+
+ rtx insn = get_insns();
+ end_sequence ();
+ if (NEXT_INSN (insn))
+ return false;
+ if (recog_memoized (insn) == -1)
+ return false;
+ extract_insn (insn);
+ if (!constrain_operands (1))
+ return false;
}
@@ -843,11 +872,15 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
fprintf (dump_file, "All merges were successful.\n");
FOR_EACH_VEC_ELT (state->modified_list, i, def_insn)
- if (state->modified[INSN_UID (def_insn)].kind == EXT_MODIFIED_NONE)
- state->modified[INSN_UID (def_insn)].kind
- = (cand->code == ZERO_EXTEND
- ? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT);
+ {
+ ext_modified *modified = &state->modified[INSN_UID (def_insn)];
+ if (modified->kind == EXT_MODIFIED_NONE)
+ modified->kind = (cand->code == ZERO_EXTEND ? EXT_MODIFIED_ZEXT
+ : EXT_MODIFIED_SEXT);
+ if (copy_needed)
+ modified->do_not_reextend = 1;
+ }
return true;
}
else
diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
index 831fe82272a..3146ba001bd 100644
--- a/gcc/reg-notes.def
+++ b/gcc/reg-notes.def
@@ -188,11 +188,6 @@ REG_NOTE (NORETURN)
computed goto. */
REG_NOTE (NON_LOCAL_GOTO)
-/* Indicates that a jump crosses between hot and cold sections in a
- (partitioned) assembly or .o file, and therefore should not be
- reduced to a simpler jump by optimizations. */
-REG_NOTE (CROSSING_JUMP)
-
/* This kind of note is generated at each to `setjmp', and similar
functions that can return twice. */
REG_NOTE (SETJMP)
diff --git a/gcc/regcprop.c b/gcc/regcprop.c
index a710cc38bf5..7a5a4f6c686 100644
--- a/gcc/regcprop.c
+++ b/gcc/regcprop.c
@@ -77,6 +77,7 @@ struct value_data
};
static alloc_pool debug_insn_changes_pool;
+static bool skip_debug_insn_p;
static void kill_value_one_regno (unsigned, struct value_data *);
static void kill_value_regno (unsigned, unsigned, struct value_data *);
@@ -485,7 +486,7 @@ replace_oldest_value_reg (rtx *loc, enum reg_class cl, rtx insn,
struct value_data *vd)
{
rtx new_rtx = find_oldest_value_reg (cl, *loc, vd);
- if (new_rtx)
+ if (new_rtx && (!DEBUG_INSN_P (insn) || !skip_debug_insn_p))
{
if (DEBUG_INSN_P (insn))
{
@@ -1112,6 +1113,26 @@ debug_value_data (struct value_data *vd)
vd->e[i].next_regno);
}
+/* Do copyprop_hardreg_forward_1 for a single basic block BB.
+ DEBUG_INSN is skipped since we do not want to involve DF related
+ staff as how it is handled in function pass_cprop_hardreg::execute.
+
+ NOTE: Currently it is only used for shrink-wrap. Maybe extend it
+ to handle DEBUG_INSN for other uses. */
+
+void
+copyprop_hardreg_forward_bb_without_debug_insn (basic_block bb)
+{
+ struct value_data *vd;
+ vd = XNEWVEC (struct value_data, 1);
+ init_value_data (vd);
+
+ skip_debug_insn_p = true;
+ copyprop_hardreg_forward_1 (bb, vd);
+ free (vd);
+ skip_debug_insn_p = false;
+}
+
#ifdef ENABLE_CHECKING
static void
validate_value_data (struct value_data *vd)
diff --git a/gcc/regcprop.h b/gcc/regcprop.h
new file mode 100644
index 00000000000..ab54eafcaf8
--- /dev/null
+++ b/gcc/regcprop.h
@@ -0,0 +1,27 @@
+/* Copy propagation on hard registers.
+ Copyright (C) 1989-2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_REGCPROP_H
+#define GCC_REGCPROP_H
+
+#include "basic-block.h"
+
+extern void copyprop_hardreg_forward_bb_without_debug_insn (basic_block bb);
+
+#endif /* GCC_REGCPROP_H */
diff --git a/gcc/reginfo.c b/gcc/reginfo.c
index 42668a158eb..edb865ef3f6 100644
--- a/gcc/reginfo.c
+++ b/gcc/reginfo.c
@@ -534,6 +534,7 @@ reinit_regs (void)
/* caller_save needs to be re-initialized. */
caller_save_initialized_p = false;
ira_init ();
+ recog_init ();
}
/* Initialize some fake stack-frame MEM references for use in
diff --git a/gcc/regs.h b/gcc/regs.h
index 006caca5611..be81db46a7e 100644
--- a/gcc/regs.h
+++ b/gcc/regs.h
@@ -135,9 +135,7 @@ extern size_t reg_info_p_size;
or profile driven feedback is available and the function is never executed,
frequency is always equivalent. Otherwise rescale the basic block
frequency. */
-#define REG_FREQ_FROM_BB(bb) (optimize_size \
- || (flag_branch_probabilities \
- && !ENTRY_BLOCK_PTR_FOR_FN (cfun)->count) \
+#define REG_FREQ_FROM_BB(bb) (optimize_function_for_size_p (cfun) \
? REG_FREQ_MAX \
: ((bb)->frequency * REG_FREQ_MAX / BB_FREQ_MAX)\
? ((bb)->frequency * REG_FREQ_MAX / BB_FREQ_MAX)\
@@ -421,4 +419,8 @@ range_in_hard_reg_set_p (const HARD_REG_SET set, unsigned regno, int nregs)
return true;
}
+/* Get registers used by given function call instruction. */
+extern bool get_call_reg_set_usage (rtx insn, HARD_REG_SET *reg_set,
+ HARD_REG_SET default_set);
+
#endif /* GCC_REGS_H */
diff --git a/gcc/reload.c b/gcc/reload.c
index 851daf30f29..87c453c85b8 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -3010,7 +3010,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
{
int swapped;
- if (!recog_data.alternative_enabled_p[this_alternative_number])
+ if (!TEST_BIT (recog_data.enabled_alternatives, this_alternative_number))
{
int i;
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 3d735eeeec9..9daafa45097 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -686,6 +686,65 @@ static int failure;
/* Temporary array of pseudo-register number. */
static int *temp_pseudo_reg_arr;
+/* If a pseudo has no hard reg, delete the insns that made the equivalence.
+ If that insn didn't set the register (i.e., it copied the register to
+ memory), just delete that insn instead of the equivalencing insn plus
+ anything now dead. If we call delete_dead_insn on that insn, we may
+ delete the insn that actually sets the register if the register dies
+ there and that is incorrect. */
+static void
+remove_init_insns ()
+{
+ for (int i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+ {
+ if (reg_renumber[i] < 0 && reg_equiv_init (i) != 0)
+ {
+ rtx list;
+ for (list = reg_equiv_init (i); list; list = XEXP (list, 1))
+ {
+ rtx equiv_insn = XEXP (list, 0);
+
+ /* If we already deleted the insn or if it may trap, we can't
+ delete it. The latter case shouldn't happen, but can
+ if an insn has a variable address, gets a REG_EH_REGION
+ note added to it, and then gets converted into a load
+ from a constant address. */
+ if (NOTE_P (equiv_insn)
+ || can_throw_internal (equiv_insn))
+ ;
+ else if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn)))
+ delete_dead_insn (equiv_insn);
+ else
+ SET_INSN_DELETED (equiv_insn);
+ }
+ }
+ }
+}
+
+/* Return true if remove_init_insns will delete INSN. */
+static bool
+will_delete_init_insn_p (rtx insn)
+{
+ rtx set = single_set (insn);
+ if (!set || !REG_P (SET_DEST (set)))
+ return false;
+ unsigned regno = REGNO (SET_DEST (set));
+
+ if (can_throw_internal (insn))
+ return false;
+
+ if (regno < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
+ return false;
+
+ for (rtx list = reg_equiv_init (regno); list; list = XEXP (list, 1))
+ {
+ rtx equiv_insn = XEXP (list, 0);
+ if (equiv_insn == insn)
+ return true;
+ }
+ return false;
+}
+
/* Main entry point for the reload pass.
FIRST is the first insn of the function being compiled.
@@ -993,37 +1052,7 @@ reload (rtx first, int global)
if (ep->can_eliminate)
mark_elimination (ep->from, ep->to);
- /* If a pseudo has no hard reg, delete the insns that made the equivalence.
- If that insn didn't set the register (i.e., it copied the register to
- memory), just delete that insn instead of the equivalencing insn plus
- anything now dead. If we call delete_dead_insn on that insn, we may
- delete the insn that actually sets the register if the register dies
- there and that is incorrect. */
-
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- {
- if (reg_renumber[i] < 0 && reg_equiv_init (i) != 0)
- {
- rtx list;
- for (list = reg_equiv_init (i); list; list = XEXP (list, 1))
- {
- rtx equiv_insn = XEXP (list, 0);
-
- /* If we already deleted the insn or if it may trap, we can't
- delete it. The latter case shouldn't happen, but can
- if an insn has a variable address, gets a REG_EH_REGION
- note added to it, and then gets converted into a load
- from a constant address. */
- if (NOTE_P (equiv_insn)
- || can_throw_internal (equiv_insn))
- ;
- else if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn)))
- delete_dead_insn (equiv_insn);
- else
- SET_INSN_DELETED (equiv_insn);
- }
- }
- }
+ remove_init_insns ();
/* Use the reload registers where necessary
by generating move instructions to move the must-be-register
@@ -1484,14 +1513,9 @@ calculate_needs_all_insns (int global)
rtx old_notes = REG_NOTES (insn);
int did_elimination = 0;
int operands_changed = 0;
- rtx set = single_set (insn);
/* Skip insns that only set an equivalence. */
- if (set && REG_P (SET_DEST (set))
- && reg_renumber[REGNO (SET_DEST (set))] < 0
- && (reg_equiv_constant (REGNO (SET_DEST (set)))
- || (reg_equiv_invariant (REGNO (SET_DEST (set)))))
- && reg_equiv_init (REGNO (SET_DEST (set))))
+ if (will_delete_init_insn_p (insn))
continue;
/* If needed, eliminate any eliminable registers. */
@@ -4586,6 +4610,9 @@ reload_as_needed (int live_known)
rtx old_prev = PREV_INSN (insn);
#endif
+ if (will_delete_init_insn_p (insn))
+ continue;
+
/* If we pass a label, copy the offsets from the label information
into the current offsets of each elimination. */
if (LABEL_P (insn))
diff --git a/gcc/reorg.c b/gcc/reorg.c
index 95e942f3eaf..e4b6d45176c 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -2289,8 +2289,8 @@ fill_simple_delay_slots (int non_jumps_p)
If LABEL is not followed by a jump, return LABEL.
If the chain loops or we can't find end, return LABEL,
since that tells caller to avoid changing the insn.
- If the returned label is obtained by following a REG_CROSSING_JUMP
- jump, set *CROSSING to true, otherwise set it to false. */
+ If the returned label is obtained by following a crossing jump,
+ set *CROSSING to true, otherwise set it to false. */
static rtx
follow_jumps (rtx label, rtx jump, bool *crossing)
@@ -2330,8 +2330,7 @@ follow_jumps (rtx label, rtx jump, bool *crossing)
if (!targetm.can_follow_jump (jump, insn))
break;
if (!*crossing)
- *crossing
- = find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX) != NULL_RTX;
+ *crossing = CROSSING_JUMP_P (jump);
value = this_label;
}
if (depth == 10)
@@ -2800,7 +2799,7 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
{
reorg_redirect_jump (insn, label);
if (crossing)
- set_unique_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX);
+ CROSSING_JUMP_P (insn) = 1;
}
}
@@ -3175,7 +3174,7 @@ relax_delay_slots (rtx first)
{
reorg_redirect_jump (insn, target_label);
if (crossing)
- set_unique_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX);
+ CROSSING_JUMP_P (insn) = 1;
}
/* See if this jump conditionally branches around an unconditional
@@ -3320,7 +3319,7 @@ relax_delay_slots (rtx first)
reorg_redirect_jump (delay_insn, trial);
target_label = trial;
if (crossing)
- set_unique_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX);
+ CROSSING_JUMP_P (insn) = 1;
}
/* If the first insn at TARGET_LABEL is redundant with a previous
diff --git a/gcc/resource.c b/gcc/resource.c
index aed00edc6f4..b55568256c3 100644
--- a/gcc/resource.c
+++ b/gcc/resource.c
@@ -655,10 +655,12 @@ mark_set_resources (rtx x, struct resources *res, int in_dest,
if (mark_type == MARK_SRC_DEST_CALL)
{
rtx link;
+ HARD_REG_SET regs;
res->cc = res->memory = 1;
- IOR_HARD_REG_SET (res->regs, regs_invalidated_by_call);
+ get_call_reg_set_usage (x, &regs, regs_invalidated_by_call);
+ IOR_HARD_REG_SET (res->regs, regs);
for (link = CALL_INSN_FUNCTION_USAGE (x);
link; link = XEXP (link, 1))
@@ -1011,11 +1013,15 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
predicated instruction, or if the CALL is NORETURN. */
if (GET_CODE (PATTERN (real_insn)) != COND_EXEC)
{
+ HARD_REG_SET regs_invalidated_by_this_call;
+ get_call_reg_set_usage (real_insn,
+ &regs_invalidated_by_this_call,
+ regs_invalidated_by_call);
/* CALL clobbers all call-used regs that aren't fixed except
sp, ap, and fp. Do this before setting the result of the
call live. */
AND_COMPL_HARD_REG_SET (current_live_regs,
- regs_invalidated_by_call);
+ regs_invalidated_by_this_call);
}
/* A CALL_INSN sets any global register live, since it may
diff --git a/gcc/rtl.c b/gcc/rtl.c
index d241c83885b..520f9a8eb7f 100644
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -28,8 +28,8 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "rtl.h"
#include "ggc.h"
+#include "rtl.h"
#ifdef GENERATOR_FILE
# include "errors.h"
#else
diff --git a/gcc/rtl.def b/gcc/rtl.def
index 2d7847d4157..d157b177391 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -139,46 +139,46 @@ DEF_RTL_EXPR(ADDRESS, "address", "i", RTX_EXTRA)
---------------------------------------------------------------------- */
/* An annotation for variable assignment tracking. */
-DEF_RTL_EXPR(DEBUG_INSN, "debug_insn", "iuuBeiie", RTX_INSN)
+DEF_RTL_EXPR(DEBUG_INSN, "debug_insn", "uuBeiie", RTX_INSN)
/* An instruction that cannot jump. */
-DEF_RTL_EXPR(INSN, "insn", "iuuBeiie", RTX_INSN)
+DEF_RTL_EXPR(INSN, "insn", "uuBeiie", RTX_INSN)
/* An instruction that can possibly jump.
Fields ( rtx->u.fld[] ) have exact same meaning as INSN's. */
-DEF_RTL_EXPR(JUMP_INSN, "jump_insn", "iuuBeiie0", RTX_INSN)
+DEF_RTL_EXPR(JUMP_INSN, "jump_insn", "uuBeiie0", RTX_INSN)
/* An instruction that can possibly call a subroutine
but which will not change which instruction comes next
in the current function.
Field ( rtx->u.fld[8] ) is CALL_INSN_FUNCTION_USAGE.
All other fields ( rtx->u.fld[] ) have exact same meaning as INSN's. */
-DEF_RTL_EXPR(CALL_INSN, "call_insn", "iuuBeiiee", RTX_INSN)
+DEF_RTL_EXPR(CALL_INSN, "call_insn", "uuBeiiee", RTX_INSN)
/* Placeholder for tablejump JUMP_INSNs. The pattern of this kind
of rtx is always either an ADDR_VEC or an ADDR_DIFF_VEC. These
placeholders do not appear as real instructions inside a basic
block, but are considered active_insn_p instructions for historical
reasons, when jump table data was represented with JUMP_INSNs. */
-DEF_RTL_EXPR(JUMP_TABLE_DATA, "jump_table_data", "iuuBe0000", RTX_INSN)
+DEF_RTL_EXPR(JUMP_TABLE_DATA, "jump_table_data", "uuBe0000", RTX_INSN)
/* A marker that indicates that control will not flow through. */
-DEF_RTL_EXPR(BARRIER, "barrier", "iuu00000", RTX_EXTRA)
+DEF_RTL_EXPR(BARRIER, "barrier", "uu00000", RTX_EXTRA)
/* Holds a label that is followed by instructions.
Operand:
- 4: is used in jump.c for the use-count of the label.
- 5: is used in the sh backend.
- 6: is a number that is unique in the entire compilation.
- 7: is the user-given name of the label, if any. */
-DEF_RTL_EXPR(CODE_LABEL, "code_label", "iuuB00is", RTX_EXTRA)
+ 3: is used in jump.c for the use-count of the label.
+ 4: is used in the sh backend.
+ 5: is a number that is unique in the entire compilation.
+ 6: is the user-given name of the label, if any. */
+DEF_RTL_EXPR(CODE_LABEL, "code_label", "uuB00is", RTX_EXTRA)
/* Say where in the code a source line starts, for symbol table's sake.
Operand:
- 4: note-specific data
- 5: enum insn_note
- 6: unique number if insn_note == note_insn_deleted_label. */
-DEF_RTL_EXPR(NOTE, "note", "iuuB0ni", RTX_EXTRA)
+ 3: note-specific data
+ 4: enum insn_note
+ 5: unique number if insn_note == note_insn_deleted_label. */
+DEF_RTL_EXPR(NOTE, "note", "uuB0ni", RTX_EXTRA)
/* ----------------------------------------------------------------------
Top level constituents of INSN, JUMP_INSN and CALL_INSN.
@@ -378,19 +378,16 @@ DEF_RTL_EXPR(PC, "pc", "", RTX_OBJ)
/* A register. The "operand" is the register number, accessed with
the REGNO macro. If this number is less than FIRST_PSEUDO_REGISTER
than a hardware register is being referred to. The second operand
- holds the original register number - this will be different for a
- pseudo register that got turned into a hard register. The third
- operand points to a reg_attrs structure.
+ points to a reg_attrs structure.
This rtx needs to have as many (or more) fields as a MEM, since we
can change REG rtx's into MEMs during reload. */
-DEF_RTL_EXPR(REG, "reg", "i00", RTX_OBJ)
+DEF_RTL_EXPR(REG, "reg", "i0", RTX_OBJ)
/* A scratch register. This represents a register used only within a
- single insn. It will be turned into a REG during register allocation
+ single insn. It will be replaced by a REG during register allocation
or reload unless the constraint indicates that the register won't be
- needed, in which case it can remain a SCRATCH. This code is
- marked as having one operand so it can be turned into a REG. */
-DEF_RTL_EXPR(SCRATCH, "scratch", "0", RTX_OBJ)
+ needed, in which case it can remain a SCRATCH. */
+DEF_RTL_EXPR(SCRATCH, "scratch", "", RTX_OBJ)
/* A reference to a part of another value. The first operand is the
complete value and the second is the byte offset of the selected part. */
@@ -432,10 +429,9 @@ DEF_RTL_EXPR(LABEL_REF, "label_ref", "u", RTX_CONST_OBJ)
/* Reference to a named label:
Operand 0: label name
- Operand 1: flags (see SYMBOL_FLAG_* in rtl.h)
- Operand 2: tree from which this symbol is derived, or null.
+ Operand 1: tree from which this symbol is derived, or null.
This is either a DECL node, or some kind of constant. */
-DEF_RTL_EXPR(SYMBOL_REF, "symbol_ref", "s00", RTX_CONST_OBJ)
+DEF_RTL_EXPR(SYMBOL_REF, "symbol_ref", "s0", RTX_CONST_OBJ)
/* The condition code register is represented, in our imagination,
as a register holding a value that can be compared to zero.
@@ -750,9 +746,7 @@ DEF_RTL_EXPR(US_TRUNCATE, "us_truncate", "e", RTX_UNARY)
DEF_RTL_EXPR(FMA, "fma", "eee", RTX_TERNARY)
/* Information about the variable and its location. */
-/* Changed 'te' to 'tei'; the 'i' field is for recording
- initialization status of variables. */
-DEF_RTL_EXPR(VAR_LOCATION, "var_location", "tei", RTX_EXTRA)
+DEF_RTL_EXPR(VAR_LOCATION, "var_location", "te", RTX_EXTRA)
/* Used in VAR_LOCATION for a pointer to a decl that is no longer
addressable. */
diff --git a/gcc/rtl.h b/gcc/rtl.h
index dbf24f328b3..51cfae5ffa6 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -109,6 +109,10 @@ extern const char * const rtx_format[NUM_RTX_CODE];
extern const enum rtx_class rtx_class[NUM_RTX_CODE];
#define GET_RTX_CLASS(CODE) (rtx_class[(int) (CODE)])
+/* True if CODE is part of the insn chain (i.e. has INSN_UID, PREV_INSN
+ and NEXT_INSN fields). */
+#define INSN_CHAIN_CODE_P(CODE) IN_RANGE (CODE, DEBUG_INSN, NOTE)
+
extern const unsigned char rtx_code_size[NUM_RTX_CODE];
extern const unsigned char rtx_next[NUM_RTX_CODE];
@@ -207,7 +211,7 @@ union rtunion
if SYMBOL_REF_HAS_BLOCK_INFO_P is true. */
struct GTY(()) block_symbol {
/* The usual SYMBOL_REF fields. */
- rtunion GTY ((skip)) fld[3];
+ rtunion GTY ((skip)) fld[2];
/* The block that contains this object. */
struct object_block *block;
@@ -263,7 +267,7 @@ struct GTY((variable_size)) hwivec_def {
/* RTL expression ("rtx"). */
struct GTY((chain_next ("RTX_NEXT (&%h)"),
- chain_prev ("RTX_PREV (&%h)"), variable_size)) rtx_def {
+ chain_prev ("RTX_PREV (&%h)"))) rtx_def {
/* The kind of expression this is. */
ENUM_BITFIELD(rtx_code) code: 16;
@@ -272,6 +276,7 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
/* 1 in a MEM if we should keep the alias set for this mem unchanged
when we access a component.
+ 1 in a JUMP_INSN if it is a crossing jump.
1 in a CALL_INSN if it is a sibling call.
1 in a SET that is for a return.
In a CODE_LABEL, part of the two-bit alternate entry field.
@@ -352,10 +357,22 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
layout for that case and use the gap for extra code-specific
information. */
+ /* The ORIGINAL_REGNO of a REG. */
+ unsigned int original_regno;
+
+ /* The INSN_UID of an RTX_INSN-class code. */
+ int insn_uid;
+
+ /* The SYMBOL_REF_FLAGS of a SYMBOL_REF. */
+ unsigned int symbol_ref_flags;
+
+ /* The PAT_VAR_LOCATION_STATUS of a VAR_LOCATION. */
+ enum var_init_status var_location_status;
+
/* In a CONST_WIDE_INT (aka hwivec_def), this is the number of
HOST_WIDE_INTs in the hwivec_def. */
- unsigned GTY ((tag ("CONST_WIDE_INT"))) num_elem:32;
- } GTY ((desc ("GET_CODE (&%0)"))) u2;
+ unsigned int num_elem;
+ } GTY ((skip)) u2;
/* The first element of the operands of this rtx.
The number of operands and their types are controlled
@@ -406,7 +423,7 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
for a variable number of things. The principle use is inside
PARALLEL expressions. */
-struct GTY((variable_size)) rtvec_def {
+struct GTY(()) rtvec_def {
int num_elem; /* number of elements */
rtx GTY ((length ("%h.num_elem"))) elem[1];
};
@@ -691,7 +708,7 @@ struct GTY((variable_size)) rtvec_def {
#define BLOCK_SYMBOL_CHECK(RTX) __extension__ \
({ __typeof (RTX) const _symbol = (RTX); \
- const unsigned int flags = RTL_CHECKC1 (_symbol, 1, SYMBOL_REF).rt_int; \
+ const unsigned int flags = SYMBOL_REF_FLAGS (_symbol); \
if ((flags & SYMBOL_FLAG_HAS_BLOCK_INFO) == 0) \
rtl_check_failed_block_symbol (__FILE__, __LINE__, \
__FUNCTION__); \
@@ -814,15 +831,12 @@ extern void rtvec_check_failed_bounds (const_rtvec, int, const char *, int,
__FUNCTION__); \
_rtx; })
-#define RTL_FLAG_CHECK8(NAME, RTX, C1, C2, C3, C4, C5, C6, C7, C8) \
+#define RTL_INSN_CHAIN_FLAG_CHECK(NAME, RTX) \
__extension__ \
({ __typeof (RTX) const _rtx = (RTX); \
- if (GET_CODE (_rtx) != C1 && GET_CODE (_rtx) != C2 \
- && GET_CODE (_rtx) != C3 && GET_CODE (_rtx) != C4 \
- && GET_CODE (_rtx) != C5 && GET_CODE (_rtx) != C6 \
- && GET_CODE (_rtx) != C7 && GET_CODE (_rtx) != C8) \
- rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
- __FUNCTION__); \
+ if (!INSN_CHAIN_CODE_P (GET_CODE (_rtx))) \
+ rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
_rtx; })
extern void rtl_check_failed_flag (const char *, const_rtx, const char *,
@@ -836,10 +850,10 @@ extern void rtl_check_failed_flag (const char *, const_rtx, const char *,
#define RTL_FLAG_CHECK2(NAME, RTX, C1, C2) (RTX)
#define RTL_FLAG_CHECK3(NAME, RTX, C1, C2, C3) (RTX)
#define RTL_FLAG_CHECK4(NAME, RTX, C1, C2, C3, C4) (RTX)
-#define RTL_FLAG_CHECK5(NAME, RTX, C1, C2, C3, C4, C5) (RTX)
+#define RTL_FLAG_CHECK5(NAME, RTX, C1, C2, C3, C4, C5) (RTX)
#define RTL_FLAG_CHECK6(NAME, RTX, C1, C2, C3, C4, C5, C6) (RTX)
#define RTL_FLAG_CHECK7(NAME, RTX, C1, C2, C3, C4, C5, C6, C7) (RTX)
-#define RTL_FLAG_CHECK8(NAME, RTX, C1, C2, C3, C4, C5, C6, C7, C8) (RTX)
+#define RTL_INSN_CHAIN_FLAG_CHECK(NAME, RTX) (RTX)
#endif
#define XINT(RTX, N) (RTL_CHECK2 (RTX, N, 'i', 'n').rt_int)
@@ -896,18 +910,19 @@ extern void rtl_check_failed_flag (const char *, const_rtx, const char *,
/* Holds a unique number for each insn.
These are not necessarily sequentially increasing. */
-#define INSN_UID(INSN) XINT (INSN, 0)
+#define INSN_UID(INSN) \
+ (RTL_INSN_CHAIN_FLAG_CHECK ("INSN_UID", (INSN))->u2.insn_uid)
/* Chain insns together in sequence. */
-#define PREV_INSN(INSN) XEXP (INSN, 1)
-#define NEXT_INSN(INSN) XEXP (INSN, 2)
+#define PREV_INSN(INSN) XEXP (INSN, 0)
+#define NEXT_INSN(INSN) XEXP (INSN, 1)
-#define BLOCK_FOR_INSN(INSN) XBBDEF (INSN, 3)
+#define BLOCK_FOR_INSN(INSN) XBBDEF (INSN, 2)
/* The body of an insn. */
-#define PATTERN(INSN) XEXP (INSN, 4)
+#define PATTERN(INSN) XEXP (INSN, 3)
-#define INSN_LOCATION(INSN) XUINT (INSN, 5)
+#define INSN_LOCATION(INSN) XUINT (INSN, 4)
#define INSN_HAS_LOCATION(INSN) ((LOCATION_LOCUS (INSN_LOCATION (INSN)))\
!= UNKNOWN_LOCATION)
@@ -918,7 +933,7 @@ extern void rtl_check_failed_flag (const char *, const_rtx, const char *,
/* Code number of instruction, from when it was recognized.
-1 means this instruction has not been recognized yet. */
-#define INSN_CODE(INSN) XINT (INSN, 6)
+#define INSN_CODE(INSN) XINT (INSN, 5)
#define RTX_FRAME_RELATED_P(RTX) \
(RTL_FLAG_CHECK6 ("RTX_FRAME_RELATED_P", (RTX), DEBUG_INSN, INSN, \
@@ -926,9 +941,11 @@ extern void rtl_check_failed_flag (const char *, const_rtx, const char *,
/* 1 if RTX is an insn that has been deleted. */
#define INSN_DELETED_P(RTX) \
- (RTL_FLAG_CHECK8 ("INSN_DELETED_P", (RTX), DEBUG_INSN, INSN, \
- CALL_INSN, JUMP_INSN, JUMP_TABLE_DATA, \
- CODE_LABEL, BARRIER, NOTE)->volatil)
+ (RTL_INSN_CHAIN_FLAG_CHECK ("INSN_DELETED_P", (RTX))->volatil)
+
+/* 1 if JUMP RTX is a crossing jump. */
+#define CROSSING_JUMP_P(RTX) \
+ (RTL_FLAG_CHECK1 ("CROSSING_JUMP_P", (RTX), JUMP_INSN)->jump)
/* 1 if RTX is a call to a const function. Built from ECF_CONST and
TREE_READONLY. */
@@ -978,7 +995,7 @@ extern void rtl_check_failed_flag (const char *, const_rtx, const char *,
chain pointer and the first operand is the REG being described.
The mode field of the EXPR_LIST contains not a real machine mode
but a value from enum reg_note. */
-#define REG_NOTES(INSN) XEXP(INSN, 7)
+#define REG_NOTES(INSN) XEXP(INSN, 6)
/* In an ENTRY_VALUE this is the DECL_INCOMING_RTL of the argument in
question. */
@@ -1009,12 +1026,12 @@ extern const char * const reg_note_name[];
CLOBBER expressions document the registers explicitly clobbered
by this CALL_INSN.
Pseudo registers can not be mentioned in this list. */
-#define CALL_INSN_FUNCTION_USAGE(INSN) XEXP(INSN, 8)
+#define CALL_INSN_FUNCTION_USAGE(INSN) XEXP(INSN, 7)
/* The label-number of a code-label. The assembler label
is made from `L' and the label-number printed in decimal.
Label numbers are unique in a compilation. */
-#define CODE_LABEL_NUMBER(INSN) XINT (INSN, 6)
+#define CODE_LABEL_NUMBER(INSN) XINT (INSN, 5)
/* In a NOTE that is a line number, this is a string for the file name that the
line is in. We use the same field to record block numbers temporarily in
@@ -1023,19 +1040,19 @@ extern const char * const reg_note_name[];
*/
/* Opaque data. */
-#define NOTE_DATA(INSN) RTL_CHECKC1 (INSN, 4, NOTE)
-#define NOTE_DELETED_LABEL_NAME(INSN) XCSTR (INSN, 4, NOTE)
+#define NOTE_DATA(INSN) RTL_CHECKC1 (INSN, 3, NOTE)
+#define NOTE_DELETED_LABEL_NAME(INSN) XCSTR (INSN, 3, NOTE)
#define SET_INSN_DELETED(INSN) set_insn_deleted (INSN);
-#define NOTE_BLOCK(INSN) XCTREE (INSN, 4, NOTE)
-#define NOTE_EH_HANDLER(INSN) XCINT (INSN, 4, NOTE)
-#define NOTE_BASIC_BLOCK(INSN) XCBBDEF (INSN, 4, NOTE)
-#define NOTE_VAR_LOCATION(INSN) XCEXP (INSN, 4, NOTE)
-#define NOTE_CFI(INSN) XCCFI (INSN, 4, NOTE)
-#define NOTE_LABEL_NUMBER(INSN) XCINT (INSN, 4, NOTE)
+#define NOTE_BLOCK(INSN) XCTREE (INSN, 3, NOTE)
+#define NOTE_EH_HANDLER(INSN) XCINT (INSN, 3, NOTE)
+#define NOTE_BASIC_BLOCK(INSN) XCBBDEF (INSN, 3, NOTE)
+#define NOTE_VAR_LOCATION(INSN) XCEXP (INSN, 3, NOTE)
+#define NOTE_CFI(INSN) XCCFI (INSN, 3, NOTE)
+#define NOTE_LABEL_NUMBER(INSN) XCINT (INSN, 3, NOTE)
/* In a NOTE that is a line number, this is the line number.
Other kinds of NOTEs are identified by negative numbers here. */
-#define NOTE_KIND(INSN) XCINT (INSN, 5, NOTE)
+#define NOTE_KIND(INSN) XCINT (INSN, 4, NOTE)
/* Nonzero if INSN is a note marking the beginning of a basic block. */
#define NOTE_INSN_BASIC_BLOCK_P(INSN) \
@@ -1049,7 +1066,8 @@ extern const char * const reg_note_name[];
can be unknown, uninitialized or initialized. See enumeration
type below. */
#define PAT_VAR_LOCATION_STATUS(PAT) \
- ((enum var_init_status) (XCINT ((PAT), 2, VAR_LOCATION)))
+ (RTL_FLAG_CHECK1 ("PAT_VAR_LOCATION_STATUS", PAT, VAR_LOCATION) \
+ ->u2.var_location_status)
/* Accessors for a NOTE_INSN_VAR_LOCATION. */
#define NOTE_VAR_LOCATION_DECL(NOTE) \
@@ -1118,11 +1136,11 @@ extern const char * const note_insn_name[NOTE_INSN_MAX];
/* The name of a label, in case it corresponds to an explicit label
in the input source code. */
-#define LABEL_NAME(RTX) XCSTR (RTX, 7, CODE_LABEL)
+#define LABEL_NAME(RTX) XCSTR (RTX, 6, CODE_LABEL)
/* In jump.c, each label contains a count of the number
of LABEL_REFs that point at it, so unused labels can be deleted. */
-#define LABEL_NUSES(RTX) XCINT (RTX, 5, CODE_LABEL)
+#define LABEL_NUSES(RTX) XCINT (RTX, 4, CODE_LABEL)
/* Labels carry a two-bit field composed of the ->jump and ->call
bits. This field indicates whether the label is an alternate
@@ -1177,12 +1195,12 @@ enum label_kind
/* In jump.c, each JUMP_INSN can point to a label that it can jump to,
so that if the JUMP_INSN is deleted, the label's LABEL_NUSES can
be decremented and possibly the label can be deleted. */
-#define JUMP_LABEL(INSN) XCEXP (INSN, 8, JUMP_INSN)
+#define JUMP_LABEL(INSN) XCEXP (INSN, 7, JUMP_INSN)
/* Once basic blocks are found, each CODE_LABEL starts a chain that
goes through all the LABEL_REFs that jump to that label. The chain
eventually winds up at the CODE_LABEL: it is circular. */
-#define LABEL_REFS(LABEL) XCEXP (LABEL, 4, CODE_LABEL)
+#define LABEL_REFS(LABEL) XCEXP (LABEL, 3, CODE_LABEL)
/* For a REG rtx, REGNO extracts the register number. REGNO can only
be used on RHS. Use SET_REGNO to change the value. */
@@ -1194,7 +1212,8 @@ enum label_kind
/* ORIGINAL_REGNO holds the number the register originally had; for a
pseudo register turned into a hard reg this will hold the old pseudo
register number. */
-#define ORIGINAL_REGNO(RTX) X0UINT (RTX, 1)
+#define ORIGINAL_REGNO(RTX) \
+ (RTL_FLAG_CHECK1 ("ORIGINAL_REGNO", (RTX), REG)->u2.original_regno)
/* Force the REGNO macro to only be used on the lhs. */
static inline unsigned int
@@ -1641,7 +1660,7 @@ do { \
/* The register attribute block. We provide access macros for each value
in the block and provide defaults if none specified. */
-#define REG_ATTRS(RTX) X0REGATTR (RTX, 2)
+#define REG_ATTRS(RTX) X0REGATTR (RTX, 1)
#ifndef GENERATOR_FILE
/* For a MEM rtx, the alias set. If 0, this MEM is not in any alias
@@ -1754,24 +1773,24 @@ do { \
/* A pointer attached to the SYMBOL_REF; either SYMBOL_REF_DECL or
SYMBOL_REF_CONSTANT. */
-#define SYMBOL_REF_DATA(RTX) X0ANY ((RTX), 2)
+#define SYMBOL_REF_DATA(RTX) X0ANY ((RTX), 1)
/* Set RTX's SYMBOL_REF_DECL to DECL. RTX must not be a constant
pool symbol. */
#define SET_SYMBOL_REF_DECL(RTX, DECL) \
- (gcc_assert (!CONSTANT_POOL_ADDRESS_P (RTX)), X0TREE ((RTX), 2) = (DECL))
+ (gcc_assert (!CONSTANT_POOL_ADDRESS_P (RTX)), X0TREE ((RTX), 1) = (DECL))
/* The tree (decl or constant) associated with the symbol, or null. */
#define SYMBOL_REF_DECL(RTX) \
- (CONSTANT_POOL_ADDRESS_P (RTX) ? NULL : X0TREE ((RTX), 2))
+ (CONSTANT_POOL_ADDRESS_P (RTX) ? NULL : X0TREE ((RTX), 1))
/* Set RTX's SYMBOL_REF_CONSTANT to C. RTX must be a constant pool symbol. */
#define SET_SYMBOL_REF_CONSTANT(RTX, C) \
- (gcc_assert (CONSTANT_POOL_ADDRESS_P (RTX)), X0CONSTANT ((RTX), 2) = (C))
+ (gcc_assert (CONSTANT_POOL_ADDRESS_P (RTX)), X0CONSTANT ((RTX), 1) = (C))
/* The rtx constant pool entry for a symbol, or null. */
#define SYMBOL_REF_CONSTANT(RTX) \
- (CONSTANT_POOL_ADDRESS_P (RTX) ? X0CONSTANT ((RTX), 2) : NULL)
+ (CONSTANT_POOL_ADDRESS_P (RTX) ? X0CONSTANT ((RTX), 1) : NULL)
/* A set of flags on a symbol_ref that are, in some respects, redundant with
information derivable from the tree decl associated with this symbol.
@@ -1780,7 +1799,9 @@ do { \
this information to avoid recomputing it. Finally, this allows space for
the target to store more than one bit of information, as with
SYMBOL_REF_FLAG. */
-#define SYMBOL_REF_FLAGS(RTX) X0INT ((RTX), 1)
+#define SYMBOL_REF_FLAGS(RTX) \
+ (RTL_FLAG_CHECK1 ("SYMBOL_REF_FLAGS", (RTX), SYMBOL_REF) \
+ ->u2.symbol_ref_flags)
/* These flags are common enough to be defined for all targets. They
are computed by the default version of targetm.encode_section_info. */
@@ -1936,7 +1957,7 @@ extern int currently_expanding_to_rtl;
/* In explow.c */
extern HOST_WIDE_INT trunc_int_for_mode (HOST_WIDE_INT, enum machine_mode);
-extern rtx plus_constant (enum machine_mode, rtx, HOST_WIDE_INT);
+extern rtx plus_constant (enum machine_mode, rtx, HOST_WIDE_INT, bool = false);
/* In rtl.c */
extern rtx rtx_alloc_stat (RTX_CODE MEM_STAT_DECL);
@@ -2176,6 +2197,7 @@ extern enum machine_mode choose_hard_reg_mode (unsigned int, unsigned int,
bool);
/* In emit-rtl.c */
+extern rtx set_for_reg_notes (rtx);
extern rtx set_unique_reg_note (rtx, enum reg_note, rtx);
extern rtx set_dst_reg_note (rtx, enum reg_note, rtx, rtx);
extern void set_insn_deleted (rtx);
@@ -2554,6 +2576,8 @@ extern rtx gen_raw_REG (enum machine_mode, int);
extern rtx gen_rtx_REG (enum machine_mode, unsigned);
extern rtx gen_rtx_SUBREG (enum machine_mode, rtx, int);
extern rtx gen_rtx_MEM (enum machine_mode, rtx);
+extern rtx gen_rtx_VAR_LOCATION (enum machine_mode, tree, rtx,
+ enum var_init_status);
#define GEN_INT(N) gen_rtx_CONST_INT (VOIDmode, (N))
diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def
index 6184b5ad58b..4016fc534cd 100644
--- a/gcc/sanitizer.def
+++ b/gcc/sanitizer.def
@@ -41,6 +41,9 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD8, "__asan_report_load8",
BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD16, "__asan_report_load16",
BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD_N, "__asan_report_load_n",
+ BT_FN_VOID_PTR_PTRMODE,
+ ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE1, "__asan_report_store1",
BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE2, "__asan_report_store2",
@@ -51,6 +54,9 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE8, "__asan_report_store8",
BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16, "__asan_report_store16",
BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE_N, "__asan_report_store_n",
+ BT_FN_VOID_PTR_PTRMODE,
+ ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REGISTER_GLOBALS,
"__asan_register_globals",
BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
@@ -371,3 +377,11 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT,
"__ubsan_handle_load_invalid_value_abort",
BT_FN_VOID_PTR_PTR,
ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW,
+ "__ubsan_handle_float_cast_overflow",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT,
+ "__ubsan_handle_float_cast_overflow_abort",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
diff --git a/gcc/sched-int.h b/gcc/sched-int.h
index d04bf0876b1..fe00496faa5 100644
--- a/gcc/sched-int.h
+++ b/gcc/sched-int.h
@@ -170,7 +170,7 @@ struct ready_list
int n_debug;
};
-extern char *ready_try;
+extern signed char *ready_try;
extern struct ready_list ready;
extern int max_issue (struct ready_list *, int, state_t, bool, int *);
@@ -1141,9 +1141,7 @@ enum SCHED_FLAGS {
enum SPEC_SCHED_FLAGS {
COUNT_SPEC_IN_CRITICAL_PATH = 1,
- PREFER_NON_DATA_SPEC = COUNT_SPEC_IN_CRITICAL_PATH << 1,
- PREFER_NON_CONTROL_SPEC = PREFER_NON_DATA_SPEC << 1,
- SEL_SCHED_SPEC_DONT_CHECK_CONTROL = PREFER_NON_CONTROL_SPEC << 1
+ SEL_SCHED_SPEC_DONT_CHECK_CONTROL = COUNT_SPEC_IN_CRITICAL_PATH << 1
};
#define NOTE_NOT_BB_P(NOTE) (NOTE_P (NOTE) && (NOTE_KIND (NOTE) \
@@ -1552,34 +1550,37 @@ sd_iterator_start (rtx insn, sd_list_types_def types)
static inline bool
sd_iterator_cond (sd_iterator_def *it_ptr, dep_t *dep_ptr)
{
- dep_link_t link = *it_ptr->linkp;
-
- if (link != NULL)
- {
- *dep_ptr = DEP_LINK_DEP (link);
- return true;
- }
- else
+ while (true)
{
- sd_list_types_def types = it_ptr->types;
+ dep_link_t link = *it_ptr->linkp;
- if (types != SD_LIST_NONE)
- /* Switch to next list. */
+ if (link != NULL)
+ {
+ *dep_ptr = DEP_LINK_DEP (link);
+ return true;
+ }
+ else
{
- deps_list_t list;
+ sd_list_types_def types = it_ptr->types;
- sd_next_list (it_ptr->insn,
- &it_ptr->types, &list, &it_ptr->resolved_p);
+ if (types != SD_LIST_NONE)
+ /* Switch to next list. */
+ {
+ deps_list_t list;
- it_ptr->linkp = &DEPS_LIST_FIRST (list);
+ sd_next_list (it_ptr->insn,
+ &it_ptr->types, &list, &it_ptr->resolved_p);
- if (list)
- return sd_iterator_cond (it_ptr, dep_ptr);
- }
+ it_ptr->linkp = &DEPS_LIST_FIRST (list);
+
+ if (list)
+ continue;
+ }
- *dep_ptr = NULL;
- return false;
- }
+ *dep_ptr = NULL;
+ return false;
+ }
+ }
}
/* Advance iterator. */
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index 868083b1a02..3cba326e897 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -162,7 +162,7 @@ static void create_initial_data_sets (basic_block);
static void free_av_set (basic_block);
static void invalidate_av_set (basic_block);
static void extend_insn_data (void);
-static void sel_init_new_insn (insn_t, int);
+static void sel_init_new_insn (insn_t, int, int = -1);
static void finish_insns (void);
/* Various list functions. */
@@ -4007,9 +4007,10 @@ get_seqno_by_succs (rtx insn)
return seqno;
}
-/* Compute seqno for INSN by its preds or succs. */
+/* Compute seqno for INSN by its preds or succs. Use OLD_SEQNO to compute
+ seqno in corner cases. */
static int
-get_seqno_for_a_jump (insn_t insn)
+get_seqno_for_a_jump (insn_t insn, int old_seqno)
{
int seqno;
@@ -4065,8 +4066,16 @@ get_seqno_for_a_jump (insn_t insn)
if (seqno < 0)
seqno = get_seqno_by_succs (insn);
- gcc_assert (seqno >= 0);
+ if (seqno < 0)
+ {
+ /* The only case where this could be here legally is that the only
+ unscheduled insn was a conditional jump that got removed and turned
+ into this unconditional one. Initialize from the old seqno
+ of that jump passed down to here. */
+ seqno = old_seqno;
+ }
+ gcc_assert (seqno >= 0);
return seqno;
}
@@ -4246,22 +4255,24 @@ init_insn_data (insn_t insn)
}
/* This is used to initialize spurious jumps generated by
- sel_redirect_edge (). */
+ sel_redirect_edge (). OLD_SEQNO is used for initializing seqnos
+ in corner cases within get_seqno_for_a_jump. */
static void
-init_simplejump_data (insn_t insn)
+init_simplejump_data (insn_t insn, int old_seqno)
{
init_expr (INSN_EXPR (insn), vinsn_create (insn, false), 0,
REG_BR_PROB_BASE, 0, 0, 0, 0, 0, 0,
vNULL, true, false, false,
false, true);
- INSN_SEQNO (insn) = get_seqno_for_a_jump (insn);
+ INSN_SEQNO (insn) = get_seqno_for_a_jump (insn, old_seqno);
init_first_time_insn_data (insn);
}
/* Perform deferred initialization of insns. This is used to process
- a new jump that may be created by redirect_edge. */
-void
-sel_init_new_insn (insn_t insn, int flags)
+ a new jump that may be created by redirect_edge. OLD_SEQNO is used
+ for initializing simplejumps in init_simplejump_data. */
+static void
+sel_init_new_insn (insn_t insn, int flags, int old_seqno)
{
/* We create data structures for bb when the first insn is emitted in it. */
if (INSN_P (insn)
@@ -4288,7 +4299,7 @@ sel_init_new_insn (insn_t insn, int flags)
if (flags & INSN_INIT_TODO_SIMPLEJUMP)
{
extend_insn_data ();
- init_simplejump_data (insn);
+ init_simplejump_data (insn, old_seqno);
}
gcc_assert (CONTAINING_RGN (BLOCK_NUM (insn))
@@ -5575,14 +5586,14 @@ sel_merge_blocks (basic_block a, basic_block b)
}
/* A wrapper for redirect_edge_and_branch_force, which also initializes
- data structures for possibly created bb and insns. Returns the newly
- added bb or NULL, when a bb was not needed. */
+ data structures for possibly created bb and insns. */
void
sel_redirect_edge_and_branch_force (edge e, basic_block to)
{
basic_block jump_bb, src, orig_dest = e->dest;
int prev_max_uid;
rtx jump;
+ int old_seqno = -1;
/* This function is now used only for bookkeeping code creation, where
we'll never get the single pred of orig_dest block and thus will not
@@ -5591,8 +5602,13 @@ sel_redirect_edge_and_branch_force (edge e, basic_block to)
&& !single_pred_p (orig_dest));
src = e->src;
prev_max_uid = get_max_uid ();
- jump_bb = redirect_edge_and_branch_force (e, to);
+ /* Compute and pass old_seqno down to sel_init_new_insn only for the case
+ when the conditional jump being redirected may become unconditional. */
+ if (any_condjump_p (BB_END (src))
+ && INSN_SEQNO (BB_END (src)) >= 0)
+ old_seqno = INSN_SEQNO (BB_END (src));
+ jump_bb = redirect_edge_and_branch_force (e, to);
if (jump_bb != NULL)
sel_add_bb (jump_bb);
@@ -5604,7 +5620,8 @@ sel_redirect_edge_and_branch_force (edge e, basic_block to)
jump = find_new_jump (src, jump_bb, prev_max_uid);
if (jump)
- sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP);
+ sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP,
+ old_seqno);
set_immediate_dominator (CDI_DOMINATORS, to,
recompute_dominator (CDI_DOMINATORS, to));
set_immediate_dominator (CDI_DOMINATORS, orig_dest,
@@ -5623,6 +5640,7 @@ sel_redirect_edge_and_branch (edge e, basic_block to)
edge redirected;
bool recompute_toporder_p = false;
bool maybe_unreachable = single_pred_p (orig_dest);
+ int old_seqno = -1;
latch_edge_p = (pipelining_p
&& current_loop_nest
@@ -5631,6 +5649,12 @@ sel_redirect_edge_and_branch (edge e, basic_block to)
src = e->src;
prev_max_uid = get_max_uid ();
+ /* Compute and pass old_seqno down to sel_init_new_insn only for the case
+ when the conditional jump being redirected may become unconditional. */
+ if (any_condjump_p (BB_END (src))
+ && INSN_SEQNO (BB_END (src)) >= 0)
+ old_seqno = INSN_SEQNO (BB_END (src));
+
redirected = redirect_edge_and_branch (e, to);
gcc_assert (redirected && !last_added_blocks.exists ());
@@ -5651,7 +5675,7 @@ sel_redirect_edge_and_branch (edge e, basic_block to)
jump = find_new_jump (src, NULL, prev_max_uid);
if (jump)
- sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP);
+ sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP, old_seqno);
/* Only update dominator info when we don't have unreachable blocks.
Otherwise we'll update in maybe_tidy_empty_bb. */
diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index 241bdad146a..0c864acd7f7 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -3502,8 +3502,6 @@ process_pipelined_exprs (av_set_t *av_ptr)
static void
process_spec_exprs (av_set_t *av_ptr)
{
- bool try_data_p = true;
- bool try_control_p = true;
expr_t expr;
av_set_iterator si;
@@ -3529,34 +3527,6 @@ process_spec_exprs (av_set_t *av_ptr)
av_set_iter_remove (&si);
continue;
}
-
- if ((spec_info->flags & PREFER_NON_DATA_SPEC)
- && !(ds & BEGIN_DATA))
- try_data_p = false;
-
- if ((spec_info->flags & PREFER_NON_CONTROL_SPEC)
- && !(ds & BEGIN_CONTROL))
- try_control_p = false;
- }
-
- FOR_EACH_EXPR_1 (expr, si, av_ptr)
- {
- ds_t ds;
-
- ds = EXPR_SPEC_DONE_DS (expr);
-
- if (ds & SPECULATIVE)
- {
- if ((ds & BEGIN_DATA) && !try_data_p)
- /* We don't want any data speculative instructions right
- now. */
- av_set_iter_remove (&si);
-
- if ((ds & BEGIN_CONTROL) && !try_control_p)
- /* We don't want any control speculative instructions right
- now. */
- av_set_iter_remove (&si);
- }
}
}
@@ -4255,7 +4225,7 @@ invoke_dfa_lookahead_guard (void)
if (! have_hook || i == 0)
r = 0;
else
- r = !targetm.sched.first_cycle_multipass_dfa_lookahead_guard (insn);
+ r = targetm.sched.first_cycle_multipass_dfa_lookahead_guard (insn, i);
gcc_assert (INSN_CODE (insn) >= 0);
diff --git a/gcc/sese.c b/gcc/sese.c
index 342c5e864d9..a0b08995513 100644
--- a/gcc/sese.c
+++ b/gcc/sese.c
@@ -698,7 +698,7 @@ if_region_set_false_region (ifsese if_region, sese region)
if (slot)
{
- struct loop_exit *loop_exit = ggc_alloc_cleared_loop_exit ();
+ struct loop_exit *loop_exit = ggc_cleared_alloc<struct loop_exit> ();
memcpy (loop_exit, *((struct loop_exit **) slot), sizeof (struct loop_exit));
htab_clear_slot (current_loops->exits, slot);
diff --git a/gcc/shrink-wrap.c b/gcc/shrink-wrap.c
new file mode 100644
index 00000000000..7d9c6e715db
--- /dev/null
+++ b/gcc/shrink-wrap.c
@@ -0,0 +1,935 @@
+/* Shrink-wrapping related optimizations.
+ Copyright (C) 1987-2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* This file handles shrink-wrapping related optimizations. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl-error.h"
+#include "tree.h"
+#include "stor-layout.h"
+#include "varasm.h"
+#include "stringpool.h"
+#include "flags.h"
+#include "except.h"
+#include "function.h"
+#include "expr.h"
+#include "optabs.h"
+#include "libfuncs.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h"
+#include "recog.h"
+#include "output.h"
+#include "hashtab.h"
+#include "tm_p.h"
+#include "langhooks.h"
+#include "target.h"
+#include "common/common-target.h"
+#include "gimple-expr.h"
+#include "gimplify.h"
+#include "tree-pass.h"
+#include "predict.h"
+#include "df.h"
+#include "params.h"
+#include "bb-reorder.h"
+#include "shrink-wrap.h"
+#include "regcprop.h"
+
+#ifdef HAVE_simple_return
+
+/* Return true if INSN requires the stack frame to be set up.
+ PROLOGUE_USED contains the hard registers used in the function
+ prologue. SET_UP_BY_PROLOGUE is the set of registers we expect the
+ prologue to set up for the function. */
+bool
+requires_stack_frame_p (rtx insn, HARD_REG_SET prologue_used,
+ HARD_REG_SET set_up_by_prologue)
+{
+ df_ref *df_rec;
+ HARD_REG_SET hardregs;
+ unsigned regno;
+
+ if (CALL_P (insn))
+ return !SIBLING_CALL_P (insn);
+
+ /* We need a frame to get the unique CFA expected by the unwinder. */
+ if (cfun->can_throw_non_call_exceptions && can_throw_internal (insn))
+ return true;
+
+ CLEAR_HARD_REG_SET (hardregs);
+ for (df_rec = DF_INSN_DEFS (insn); *df_rec; df_rec++)
+ {
+ rtx dreg = DF_REF_REG (*df_rec);
+
+ if (!REG_P (dreg))
+ continue;
+
+ add_to_hard_reg_set (&hardregs, GET_MODE (dreg),
+ REGNO (dreg));
+ }
+ if (hard_reg_set_intersect_p (hardregs, prologue_used))
+ return true;
+ AND_COMPL_HARD_REG_SET (hardregs, call_used_reg_set);
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (TEST_HARD_REG_BIT (hardregs, regno)
+ && df_regs_ever_live_p (regno))
+ return true;
+
+ for (df_rec = DF_INSN_USES (insn); *df_rec; df_rec++)
+ {
+ rtx reg = DF_REF_REG (*df_rec);
+
+ if (!REG_P (reg))
+ continue;
+
+ add_to_hard_reg_set (&hardregs, GET_MODE (reg),
+ REGNO (reg));
+ }
+ if (hard_reg_set_intersect_p (hardregs, set_up_by_prologue))
+ return true;
+
+ return false;
+}
+
+/* See whether there has a single live edge from BB, which dest uses
+ [REGNO, END_REGNO). Return the live edge if its dest bb has
+ one or two predecessors. Otherwise return NULL. */
+
+static edge
+live_edge_for_reg (basic_block bb, int regno, int end_regno)
+{
+ edge e, live_edge;
+ edge_iterator ei;
+ bitmap live;
+ int i;
+
+ live_edge = NULL;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ {
+ live = df_get_live_in (e->dest);
+ for (i = regno; i < end_regno; i++)
+ if (REGNO_REG_SET_P (live, i))
+ {
+ if (live_edge && live_edge != e)
+ return NULL;
+ live_edge = e;
+ }
+ }
+
+ /* We can sometimes encounter dead code. Don't try to move it
+ into the exit block. */
+ if (!live_edge || live_edge->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
+ return NULL;
+
+ /* Reject targets of abnormal edges. This is needed for correctness
+ on ports like Alpha and MIPS, whose pic_offset_table_rtx can die on
+ exception edges even though it is generally treated as call-saved
+ for the majority of the compilation. Moving across abnormal edges
+ isn't going to be interesting for shrink-wrap usage anyway. */
+ if (live_edge->flags & EDGE_ABNORMAL)
+ return NULL;
+
+ /* When live_edge->dest->preds == 2, we can create a new block on
+ the edge to make it meet the requirement. */
+ if (EDGE_COUNT (live_edge->dest->preds) > 2)
+ return NULL;
+
+ return live_edge;
+}
+
+/* Try to move INSN from BB to a successor. Return true on success.
+ USES and DEFS are the set of registers that are used and defined
+ after INSN in BB. SPLIT_P indicates whether a live edge from BB
+ is splitted or not. */
+
+static bool
+move_insn_for_shrink_wrap (basic_block bb, rtx insn,
+ const HARD_REG_SET uses,
+ const HARD_REG_SET defs,
+ bool *split_p)
+{
+ rtx set, src, dest;
+ bitmap live_out, live_in, bb_uses, bb_defs;
+ unsigned int i, dregno, end_dregno, sregno, end_sregno;
+ basic_block next_block;
+ edge live_edge;
+
+ /* Look for a simple register copy. */
+ set = single_set (insn);
+ if (!set)
+ return false;
+ src = SET_SRC (set);
+ dest = SET_DEST (set);
+ if (!REG_P (dest) || !REG_P (src)
+ /* STACK or FRAME related adjustment might be part of prologue.
+ So keep them in the entry block. */
+ || dest == stack_pointer_rtx
+ || dest == frame_pointer_rtx
+ || dest == hard_frame_pointer_rtx)
+ return false;
+
+ /* Make sure that the source register isn't defined later in BB. */
+ sregno = REGNO (src);
+ end_sregno = END_REGNO (src);
+ if (overlaps_hard_reg_set_p (defs, GET_MODE (src), sregno))
+ return false;
+
+ /* Make sure that the destination register isn't referenced later in BB. */
+ dregno = REGNO (dest);
+ end_dregno = END_REGNO (dest);
+ if (overlaps_hard_reg_set_p (uses, GET_MODE (dest), dregno)
+ || overlaps_hard_reg_set_p (defs, GET_MODE (dest), dregno))
+ return false;
+
+ /* See whether there is a successor block to which we could move INSN. */
+ live_edge = live_edge_for_reg (bb, dregno, end_dregno);
+ if (!live_edge)
+ return false;
+
+ next_block = live_edge->dest;
+ /* Create a new basic block on the edge. */
+ if (EDGE_COUNT (next_block->preds) == 2)
+ {
+ /* split_edge for a block with only one successor is meaningless. */
+ if (EDGE_COUNT (bb->succs) == 1)
+ return false;
+
+ /* If DF_LIVE doesn't exist, i.e. at -O1, just give up. */
+ if (!df_live)
+ return false;
+
+ next_block = split_edge (live_edge);
+
+ /* We create a new basic block. Call df_grow_bb_info to make sure
+ all data structures are allocated. */
+ df_grow_bb_info (df_live);
+ bitmap_copy (df_get_live_in (next_block), df_get_live_out (bb));
+ df_set_bb_dirty (next_block);
+
+ /* We should not split more than once for a function. */
+ gcc_assert (!(*split_p));
+ *split_p = true;
+ }
+
+ /* At this point we are committed to moving INSN, but let's try to
+ move it as far as we can. */
+ do
+ {
+ live_out = df_get_live_out (bb);
+ live_in = df_get_live_in (next_block);
+ bb = next_block;
+
+ /* Check whether BB uses DEST or clobbers DEST. We need to add
+ INSN to BB if so. Either way, DEST is no longer live on entry,
+ except for any part that overlaps SRC (next loop). */
+ bb_uses = &DF_LR_BB_INFO (bb)->use;
+ bb_defs = &DF_LR_BB_INFO (bb)->def;
+ if (df_live)
+ {
+ for (i = dregno; i < end_dregno; i++)
+ {
+ if (*split_p
+ || REGNO_REG_SET_P (bb_uses, i)
+ || REGNO_REG_SET_P (bb_defs, i)
+ || REGNO_REG_SET_P (&DF_LIVE_BB_INFO (bb)->gen, i))
+ next_block = NULL;
+ CLEAR_REGNO_REG_SET (live_out, i);
+ CLEAR_REGNO_REG_SET (live_in, i);
+ }
+
+ /* Check whether BB clobbers SRC. We need to add INSN to BB if so.
+ Either way, SRC is now live on entry. */
+ for (i = sregno; i < end_sregno; i++)
+ {
+ if (*split_p
+ || REGNO_REG_SET_P (bb_defs, i)
+ || REGNO_REG_SET_P (&DF_LIVE_BB_INFO (bb)->gen, i))
+ next_block = NULL;
+ SET_REGNO_REG_SET (live_out, i);
+ SET_REGNO_REG_SET (live_in, i);
+ }
+ }
+ else
+ {
+ /* DF_LR_BB_INFO (bb)->def does not comprise the DF_REF_PARTIAL and
+ DF_REF_CONDITIONAL defs. So if DF_LIVE doesn't exist, i.e.
+ at -O1, just give up searching NEXT_BLOCK. */
+ next_block = NULL;
+ for (i = dregno; i < end_dregno; i++)
+ {
+ CLEAR_REGNO_REG_SET (live_out, i);
+ CLEAR_REGNO_REG_SET (live_in, i);
+ }
+
+ for (i = sregno; i < end_sregno; i++)
+ {
+ SET_REGNO_REG_SET (live_out, i);
+ SET_REGNO_REG_SET (live_in, i);
+ }
+ }
+
+ /* If we don't need to add the move to BB, look for a single
+ successor block. */
+ if (next_block)
+ {
+ live_edge = live_edge_for_reg (next_block, dregno, end_dregno);
+ if (!live_edge || EDGE_COUNT (live_edge->dest->preds) > 1)
+ break;
+ next_block = live_edge->dest;
+ }
+ }
+ while (next_block);
+
+ /* For the new created basic block, there is no dataflow info at all.
+ So skip the following dataflow update and check. */
+ if (!(*split_p))
+ {
+ /* BB now defines DEST. It only uses the parts of DEST that overlap SRC
+ (next loop). */
+ for (i = dregno; i < end_dregno; i++)
+ {
+ CLEAR_REGNO_REG_SET (bb_uses, i);
+ SET_REGNO_REG_SET (bb_defs, i);
+ }
+
+ /* BB now uses SRC. */
+ for (i = sregno; i < end_sregno; i++)
+ SET_REGNO_REG_SET (bb_uses, i);
+ }
+
+ emit_insn_after (PATTERN (insn), bb_note (bb));
+ delete_insn (insn);
+ return true;
+}
+
+/* Look for register copies in the first block of the function, and move
+ them down into successor blocks if the register is used only on one
+ path. This exposes more opportunities for shrink-wrapping. These
+ kinds of sets often occur when incoming argument registers are moved
+ to call-saved registers because their values are live across one or
+ more calls during the function. */
+
+void
+prepare_shrink_wrap (basic_block entry_block)
+{
+ rtx insn, curr, x;
+ HARD_REG_SET uses, defs;
+ df_ref *ref;
+ bool split_p = false;
+
+ if (JUMP_P (BB_END (entry_block)))
+ {
+ /* To have more shrink-wrapping opportunities, prepare_shrink_wrap tries
+ to sink the copies from parameter to callee saved register out of
+ entry block. copyprop_hardreg_forward_bb_without_debug_insn is called
+ to release some dependences. */
+ copyprop_hardreg_forward_bb_without_debug_insn (entry_block);
+ }
+
+ CLEAR_HARD_REG_SET (uses);
+ CLEAR_HARD_REG_SET (defs);
+ FOR_BB_INSNS_REVERSE_SAFE (entry_block, insn, curr)
+ if (NONDEBUG_INSN_P (insn)
+ && !move_insn_for_shrink_wrap (entry_block, insn, uses, defs,
+ &split_p))
+ {
+ /* Add all defined registers to DEFs. */
+ for (ref = DF_INSN_DEFS (insn); *ref; ref++)
+ {
+ x = DF_REF_REG (*ref);
+ if (REG_P (x) && HARD_REGISTER_P (x))
+ SET_HARD_REG_BIT (defs, REGNO (x));
+ }
+
+ /* Add all used registers to USESs. */
+ for (ref = DF_INSN_USES (insn); *ref; ref++)
+ {
+ x = DF_REF_REG (*ref);
+ if (REG_P (x) && HARD_REGISTER_P (x))
+ SET_HARD_REG_BIT (uses, REGNO (x));
+ }
+ }
+}
+
+/* Create a copy of BB instructions and insert at BEFORE. Redirect
+ preds of BB to COPY_BB if they don't appear in NEED_PROLOGUE. */
+void
+dup_block_and_redirect (basic_block bb, basic_block copy_bb, rtx before,
+ bitmap_head *need_prologue)
+{
+ edge_iterator ei;
+ edge e;
+ rtx insn = BB_END (bb);
+
+ /* We know BB has a single successor, so there is no need to copy a
+ simple jump at the end of BB. */
+ if (simplejump_p (insn))
+ insn = PREV_INSN (insn);
+
+ start_sequence ();
+ duplicate_insn_chain (BB_HEAD (bb), insn);
+ if (dump_file)
+ {
+ unsigned count = 0;
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (active_insn_p (insn))
+ ++count;
+ fprintf (dump_file, "Duplicating bb %d to bb %d, %u active insns.\n",
+ bb->index, copy_bb->index, count);
+ }
+ insn = get_insns ();
+ end_sequence ();
+ emit_insn_before (insn, before);
+
+ /* Redirect all the paths that need no prologue into copy_bb. */
+ for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei));)
+ if (!bitmap_bit_p (need_prologue, e->src->index))
+ {
+ int freq = EDGE_FREQUENCY (e);
+ copy_bb->count += e->count;
+ copy_bb->frequency += EDGE_FREQUENCY (e);
+ e->dest->count -= e->count;
+ if (e->dest->count < 0)
+ e->dest->count = 0;
+ e->dest->frequency -= freq;
+ if (e->dest->frequency < 0)
+ e->dest->frequency = 0;
+ redirect_edge_and_branch_force (e, copy_bb);
+ continue;
+ }
+ else
+ ei_next (&ei);
+}
+
+
+/* Try to perform a kind of shrink-wrapping, making sure the
+ prologue/epilogue is emitted only around those parts of the
+ function that require it. */
+
+void
+try_shrink_wrapping (edge *entry_edge, edge orig_entry_edge,
+ bitmap_head *bb_flags, rtx prologue_seq)
+{
+ edge e;
+ edge_iterator ei;
+ bool nonempty_prologue = false;
+ unsigned max_grow_size;
+ rtx seq;
+
+ for (seq = prologue_seq; seq; seq = NEXT_INSN (seq))
+ if (!NOTE_P (seq) || NOTE_KIND (seq) != NOTE_INSN_PROLOGUE_END)
+ {
+ nonempty_prologue = true;
+ break;
+ }
+
+ if (flag_shrink_wrap && HAVE_simple_return
+ && (targetm.profile_before_prologue () || !crtl->profile)
+ && nonempty_prologue && !crtl->calls_eh_return)
+ {
+ HARD_REG_SET prologue_clobbered, prologue_used, live_on_edge;
+ struct hard_reg_set_container set_up_by_prologue;
+ rtx p_insn;
+ vec<basic_block> vec;
+ basic_block bb;
+ bitmap_head bb_antic_flags;
+ bitmap_head bb_on_list;
+ bitmap_head bb_tail;
+
+ if (dump_file)
+ fprintf (dump_file, "Attempting shrink-wrapping optimization.\n");
+
+ /* Compute the registers set and used in the prologue. */
+ CLEAR_HARD_REG_SET (prologue_clobbered);
+ CLEAR_HARD_REG_SET (prologue_used);
+ for (p_insn = prologue_seq; p_insn; p_insn = NEXT_INSN (p_insn))
+ {
+ HARD_REG_SET this_used;
+ if (!NONDEBUG_INSN_P (p_insn))
+ continue;
+
+ CLEAR_HARD_REG_SET (this_used);
+ note_uses (&PATTERN (p_insn), record_hard_reg_uses,
+ &this_used);
+ AND_COMPL_HARD_REG_SET (this_used, prologue_clobbered);
+ IOR_HARD_REG_SET (prologue_used, this_used);
+ note_stores (PATTERN (p_insn), record_hard_reg_sets,
+ &prologue_clobbered);
+ }
+
+ prepare_shrink_wrap ((*entry_edge)->dest);
+
+ bitmap_initialize (&bb_antic_flags, &bitmap_default_obstack);
+ bitmap_initialize (&bb_on_list, &bitmap_default_obstack);
+ bitmap_initialize (&bb_tail, &bitmap_default_obstack);
+
+ /* Find the set of basic blocks that require a stack frame,
+ and blocks that are too big to be duplicated. */
+
+ vec.create (n_basic_blocks_for_fn (cfun));
+
+ CLEAR_HARD_REG_SET (set_up_by_prologue.set);
+ add_to_hard_reg_set (&set_up_by_prologue.set, Pmode,
+ STACK_POINTER_REGNUM);
+ add_to_hard_reg_set (&set_up_by_prologue.set, Pmode, ARG_POINTER_REGNUM);
+ if (frame_pointer_needed)
+ add_to_hard_reg_set (&set_up_by_prologue.set, Pmode,
+ HARD_FRAME_POINTER_REGNUM);
+ if (pic_offset_table_rtx)
+ add_to_hard_reg_set (&set_up_by_prologue.set, Pmode,
+ PIC_OFFSET_TABLE_REGNUM);
+ if (crtl->drap_reg)
+ add_to_hard_reg_set (&set_up_by_prologue.set,
+ GET_MODE (crtl->drap_reg),
+ REGNO (crtl->drap_reg));
+ if (targetm.set_up_by_prologue)
+ targetm.set_up_by_prologue (&set_up_by_prologue);
+
+ /* We don't use a different max size depending on
+ optimize_bb_for_speed_p because increasing shrink-wrapping
+ opportunities by duplicating tail blocks can actually result
+ in an overall decrease in code size. */
+ max_grow_size = get_uncond_jump_length ();
+ max_grow_size *= PARAM_VALUE (PARAM_MAX_GROW_COPY_BB_INSNS);
+
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ rtx insn;
+ unsigned size = 0;
+
+ FOR_BB_INSNS (bb, insn)
+ if (NONDEBUG_INSN_P (insn))
+ {
+ if (requires_stack_frame_p (insn, prologue_used,
+ set_up_by_prologue.set))
+ {
+ if (bb == (*entry_edge)->dest)
+ goto fail_shrinkwrap;
+ bitmap_set_bit (bb_flags, bb->index);
+ vec.quick_push (bb);
+ break;
+ }
+ else if (size <= max_grow_size)
+ {
+ size += get_attr_min_length (insn);
+ if (size > max_grow_size)
+ bitmap_set_bit (&bb_on_list, bb->index);
+ }
+ }
+ }
+
+ /* Blocks that really need a prologue, or are too big for tails. */
+ bitmap_ior_into (&bb_on_list, bb_flags);
+
+ /* For every basic block that needs a prologue, mark all blocks
+ reachable from it, so as to ensure they are also seen as
+ requiring a prologue. */
+ while (!vec.is_empty ())
+ {
+ basic_block tmp_bb = vec.pop ();
+
+ FOR_EACH_EDGE (e, ei, tmp_bb->succs)
+ if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
+ && bitmap_set_bit (bb_flags, e->dest->index))
+ vec.quick_push (e->dest);
+ }
+
+ /* Find the set of basic blocks that need no prologue, have a
+ single successor, can be duplicated, meet a max size
+ requirement, and go to the exit via like blocks. */
+ vec.quick_push (EXIT_BLOCK_PTR_FOR_FN (cfun));
+ while (!vec.is_empty ())
+ {
+ basic_block tmp_bb = vec.pop ();
+
+ FOR_EACH_EDGE (e, ei, tmp_bb->preds)
+ if (single_succ_p (e->src)
+ && !bitmap_bit_p (&bb_on_list, e->src->index)
+ && can_duplicate_block_p (e->src))
+ {
+ edge pe;
+ edge_iterator pei;
+
+ /* If there is predecessor of e->src which doesn't
+ need prologue and the edge is complex,
+ we might not be able to redirect the branch
+ to a copy of e->src. */
+ FOR_EACH_EDGE (pe, pei, e->src->preds)
+ if ((pe->flags & EDGE_COMPLEX) != 0
+ && !bitmap_bit_p (bb_flags, pe->src->index))
+ break;
+ if (pe == NULL && bitmap_set_bit (&bb_tail, e->src->index))
+ vec.quick_push (e->src);
+ }
+ }
+
+ /* Now walk backwards from every block that is marked as needing
+ a prologue to compute the bb_antic_flags bitmap. Exclude
+ tail blocks; They can be duplicated to be used on paths not
+ needing a prologue. */
+ bitmap_clear (&bb_on_list);
+ bitmap_and_compl (&bb_antic_flags, bb_flags, &bb_tail);
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ if (!bitmap_bit_p (&bb_antic_flags, bb->index))
+ continue;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index)
+ && bitmap_set_bit (&bb_on_list, e->src->index))
+ vec.quick_push (e->src);
+ }
+ while (!vec.is_empty ())
+ {
+ basic_block tmp_bb = vec.pop ();
+ bool all_set = true;
+
+ bitmap_clear_bit (&bb_on_list, tmp_bb->index);
+ FOR_EACH_EDGE (e, ei, tmp_bb->succs)
+ if (!bitmap_bit_p (&bb_antic_flags, e->dest->index))
+ {
+ all_set = false;
+ break;
+ }
+
+ if (all_set)
+ {
+ bitmap_set_bit (&bb_antic_flags, tmp_bb->index);
+ FOR_EACH_EDGE (e, ei, tmp_bb->preds)
+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index)
+ && bitmap_set_bit (&bb_on_list, e->src->index))
+ vec.quick_push (e->src);
+ }
+ }
+ /* Find exactly one edge that leads to a block in ANTIC from
+ a block that isn't. */
+ if (!bitmap_bit_p (&bb_antic_flags, (*entry_edge)->dest->index))
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ if (!bitmap_bit_p (&bb_antic_flags, bb->index))
+ continue;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index))
+ {
+ if (*entry_edge != orig_entry_edge)
+ {
+ *entry_edge = orig_entry_edge;
+ if (dump_file)
+ fprintf (dump_file, "More than one candidate edge.\n");
+ goto fail_shrinkwrap;
+ }
+ if (dump_file)
+ fprintf (dump_file, "Found candidate edge for "
+ "shrink-wrapping, %d->%d.\n", e->src->index,
+ e->dest->index);
+ *entry_edge = e;
+ }
+ }
+
+ if (*entry_edge != orig_entry_edge)
+ {
+ /* Test whether the prologue is known to clobber any register
+ (other than FP or SP) which are live on the edge. */
+ CLEAR_HARD_REG_BIT (prologue_clobbered, STACK_POINTER_REGNUM);
+ if (frame_pointer_needed)
+ CLEAR_HARD_REG_BIT (prologue_clobbered, HARD_FRAME_POINTER_REGNUM);
+ REG_SET_TO_HARD_REG_SET (live_on_edge,
+ df_get_live_in ((*entry_edge)->dest));
+ if (hard_reg_set_intersect_p (live_on_edge, prologue_clobbered))
+ {
+ *entry_edge = orig_entry_edge;
+ if (dump_file)
+ fprintf (dump_file,
+ "Shrink-wrapping aborted due to clobber.\n");
+ }
+ }
+ if (*entry_edge != orig_entry_edge)
+ {
+ crtl->shrink_wrapped = true;
+ if (dump_file)
+ fprintf (dump_file, "Performing shrink-wrapping.\n");
+
+ /* Find tail blocks reachable from both blocks needing a
+ prologue and blocks not needing a prologue. */
+ if (!bitmap_empty_p (&bb_tail))
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ bool some_pro, some_no_pro;
+ if (!bitmap_bit_p (&bb_tail, bb->index))
+ continue;
+ some_pro = some_no_pro = false;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ {
+ if (bitmap_bit_p (bb_flags, e->src->index))
+ some_pro = true;
+ else
+ some_no_pro = true;
+ }
+ if (some_pro && some_no_pro)
+ vec.quick_push (bb);
+ else
+ bitmap_clear_bit (&bb_tail, bb->index);
+ }
+ /* Find the head of each tail. */
+ while (!vec.is_empty ())
+ {
+ basic_block tbb = vec.pop ();
+
+ if (!bitmap_bit_p (&bb_tail, tbb->index))
+ continue;
+
+ while (single_succ_p (tbb))
+ {
+ tbb = single_succ (tbb);
+ bitmap_clear_bit (&bb_tail, tbb->index);
+ }
+ }
+ /* Now duplicate the tails. */
+ if (!bitmap_empty_p (&bb_tail))
+ FOR_EACH_BB_REVERSE_FN (bb, cfun)
+ {
+ basic_block copy_bb, tbb;
+ rtx insert_point;
+ int eflags;
+
+ if (!bitmap_clear_bit (&bb_tail, bb->index))
+ continue;
+
+ /* Create a copy of BB, instructions and all, for
+ use on paths that don't need a prologue.
+ Ideal placement of the copy is on a fall-thru edge
+ or after a block that would jump to the copy. */
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (!bitmap_bit_p (bb_flags, e->src->index)
+ && single_succ_p (e->src))
+ break;
+ if (e)
+ {
+ /* Make sure we insert after any barriers. */
+ rtx end = get_last_bb_insn (e->src);
+ copy_bb = create_basic_block (NEXT_INSN (end),
+ NULL_RTX, e->src);
+ BB_COPY_PARTITION (copy_bb, e->src);
+ }
+ else
+ {
+ /* Otherwise put the copy at the end of the function. */
+ copy_bb = create_basic_block (NULL_RTX, NULL_RTX,
+ EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
+ BB_COPY_PARTITION (copy_bb, bb);
+ }
+
+ insert_point = emit_note_after (NOTE_INSN_DELETED,
+ BB_END (copy_bb));
+ emit_barrier_after (BB_END (copy_bb));
+
+ tbb = bb;
+ while (1)
+ {
+ dup_block_and_redirect (tbb, copy_bb, insert_point,
+ bb_flags);
+ tbb = single_succ (tbb);
+ if (tbb == EXIT_BLOCK_PTR_FOR_FN (cfun))
+ break;
+ e = split_block (copy_bb, PREV_INSN (insert_point));
+ copy_bb = e->dest;
+ }
+
+ /* Quiet verify_flow_info by (ab)using EDGE_FAKE.
+ We have yet to add a simple_return to the tails,
+ as we'd like to first convert_jumps_to_returns in
+ case the block is no longer used after that. */
+ eflags = EDGE_FAKE;
+ if (CALL_P (PREV_INSN (insert_point))
+ && SIBLING_CALL_P (PREV_INSN (insert_point)))
+ eflags = EDGE_SIBCALL | EDGE_ABNORMAL;
+ make_single_succ_edge (copy_bb, EXIT_BLOCK_PTR_FOR_FN (cfun),
+ eflags);
+
+ /* verify_flow_info doesn't like a note after a
+ sibling call. */
+ delete_insn (insert_point);
+ if (bitmap_empty_p (&bb_tail))
+ break;
+ }
+ }
+
+ fail_shrinkwrap:
+ bitmap_clear (&bb_tail);
+ bitmap_clear (&bb_antic_flags);
+ bitmap_clear (&bb_on_list);
+ vec.release ();
+ }
+}
+
+/* If we're allowed to generate a simple return instruction, then by
+ definition we don't need a full epilogue. If the last basic
+ block before the exit block does not contain active instructions,
+ examine its predecessors and try to emit (conditional) return
+ instructions. */
+
+edge
+get_unconverted_simple_return (edge exit_fallthru_edge, bitmap_head bb_flags,
+ vec<edge> *unconverted_simple_returns,
+ rtx *returnjump)
+{
+ if (optimize)
+ {
+ unsigned i, last;
+
+ /* convert_jumps_to_returns may add to preds of the exit block
+ (but won't remove). Stop at end of current preds. */
+ last = EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds);
+ for (i = 0; i < last; i++)
+ {
+ edge e = EDGE_I (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds, i);
+ if (LABEL_P (BB_HEAD (e->src))
+ && !bitmap_bit_p (&bb_flags, e->src->index)
+ && !active_insn_between (BB_HEAD (e->src), BB_END (e->src)))
+ *unconverted_simple_returns
+ = convert_jumps_to_returns (e->src, true,
+ *unconverted_simple_returns);
+ }
+ }
+
+ if (exit_fallthru_edge != NULL
+ && EDGE_COUNT (exit_fallthru_edge->src->preds) != 0
+ && !bitmap_bit_p (&bb_flags, exit_fallthru_edge->src->index))
+ {
+ basic_block last_bb;
+
+ last_bb = emit_return_for_exit (exit_fallthru_edge, true);
+ *returnjump = BB_END (last_bb);
+ exit_fallthru_edge = NULL;
+ }
+ return exit_fallthru_edge;
+}
+
+/* If there were branches to an empty LAST_BB which we tried to
+ convert to conditional simple_returns, but couldn't for some
+ reason, create a block to hold a simple_return insn and redirect
+ those remaining edges. */
+
+void
+convert_to_simple_return (edge entry_edge, edge orig_entry_edge,
+ bitmap_head bb_flags, rtx returnjump,
+ vec<edge> unconverted_simple_returns)
+{
+ edge e;
+ edge_iterator ei;
+
+ if (!unconverted_simple_returns.is_empty ())
+ {
+ basic_block simple_return_block_hot = NULL;
+ basic_block simple_return_block_cold = NULL;
+ edge pending_edge_hot = NULL;
+ edge pending_edge_cold = NULL;
+ basic_block exit_pred;
+ int i;
+
+ gcc_assert (entry_edge != orig_entry_edge);
+
+ /* See if we can reuse the last insn that was emitted for the
+ epilogue. */
+ if (returnjump != NULL_RTX
+ && JUMP_LABEL (returnjump) == simple_return_rtx)
+ {
+ e = split_block (BLOCK_FOR_INSN (returnjump), PREV_INSN (returnjump));
+ if (BB_PARTITION (e->src) == BB_HOT_PARTITION)
+ simple_return_block_hot = e->dest;
+ else
+ simple_return_block_cold = e->dest;
+ }
+
+ /* Also check returns we might need to add to tail blocks. */
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
+ if (EDGE_COUNT (e->src->preds) != 0
+ && (e->flags & EDGE_FAKE) != 0
+ && !bitmap_bit_p (&bb_flags, e->src->index))
+ {
+ if (BB_PARTITION (e->src) == BB_HOT_PARTITION)
+ pending_edge_hot = e;
+ else
+ pending_edge_cold = e;
+ }
+
+ /* Save a pointer to the exit's predecessor BB for use in
+ inserting new BBs at the end of the function. Do this
+ after the call to split_block above which may split
+ the original exit pred. */
+ exit_pred = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb;
+
+ FOR_EACH_VEC_ELT (unconverted_simple_returns, i, e)
+ {
+ basic_block *pdest_bb;
+ edge pending;
+
+ if (BB_PARTITION (e->src) == BB_HOT_PARTITION)
+ {
+ pdest_bb = &simple_return_block_hot;
+ pending = pending_edge_hot;
+ }
+ else
+ {
+ pdest_bb = &simple_return_block_cold;
+ pending = pending_edge_cold;
+ }
+
+ if (*pdest_bb == NULL && pending != NULL)
+ {
+ emit_return_into_block (true, pending->src);
+ pending->flags &= ~(EDGE_FALLTHRU | EDGE_FAKE);
+ *pdest_bb = pending->src;
+ }
+ else if (*pdest_bb == NULL)
+ {
+ basic_block bb;
+ rtx start;
+
+ bb = create_basic_block (NULL, NULL, exit_pred);
+ BB_COPY_PARTITION (bb, e->src);
+ start = emit_jump_insn_after (gen_simple_return (),
+ BB_END (bb));
+ JUMP_LABEL (start) = simple_return_rtx;
+ emit_barrier_after (start);
+
+ *pdest_bb = bb;
+ make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
+ }
+ redirect_edge_and_branch_force (e, *pdest_bb);
+ }
+ unconverted_simple_returns.release ();
+ }
+
+ if (entry_edge != orig_entry_edge)
+ {
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
+ if (EDGE_COUNT (e->src->preds) != 0
+ && (e->flags & EDGE_FAKE) != 0
+ && !bitmap_bit_p (&bb_flags, e->src->index))
+ {
+ emit_return_into_block (true, e->src);
+ e->flags &= ~(EDGE_FALLTHRU | EDGE_FAKE);
+ }
+ }
+}
+
+#endif
diff --git a/gcc/shrink-wrap.h b/gcc/shrink-wrap.h
new file mode 100644
index 00000000000..bccfb31aad3
--- /dev/null
+++ b/gcc/shrink-wrap.h
@@ -0,0 +1,52 @@
+/* Shrink-wrapping related functions.
+ Copyright (C) 1989-2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_SHRINK_WRAP_H
+#define GCC_SHRINK_WRAP_H
+
+#include "hashtab.h"
+#include "vec.h"
+#include "machmode.h"
+
+#ifdef HAVE_simple_return
+/* In function.c. */
+extern void emit_return_into_block (bool simple_p, basic_block bb);
+extern bool active_insn_between (rtx head, rtx tail);
+extern vec<edge> convert_jumps_to_returns (basic_block last_bb, bool simple_p,
+ vec<edge> unconverted);
+extern basic_block emit_return_for_exit (edge exit_fallthru_edge,
+ bool simple_p);
+
+/* In shrink-wrap.c. */
+extern bool requires_stack_frame_p (rtx, HARD_REG_SET, HARD_REG_SET);
+extern void prepare_shrink_wrap (basic_block entry_block);
+extern void dup_block_and_redirect (basic_block bb, basic_block copy_bb,
+ rtx before, bitmap_head *need_prologue);
+extern void try_shrink_wrapping (edge *entry_edge, edge orig_entry_edge,
+ bitmap_head *bb_flags, rtx prologue_seq);
+extern edge get_unconverted_simple_return (edge, bitmap_head,
+ vec<edge> *, rtx *);
+extern void convert_to_simple_return (edge entry_edge, edge orig_entry_edge,
+ bitmap_head bb_flags, rtx returnjump,
+ vec<edge> unconverted_simple_returns);
+#endif
+
+#endif /* GCC_SHRINK_WRAP_H */
+
+
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 7fb1c6db63d..181b56fb8c0 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -884,7 +884,7 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
so we can perform the above simplification. */
if (STORE_FLAG_VALUE == -1
&& GET_CODE (op) == ASHIFTRT
- && GET_CODE (XEXP (op, 1))
+ && CONST_INT_P (XEXP (op, 1))
&& INTVAL (XEXP (op, 1)) == GET_MODE_PRECISION (mode) - 1)
return simplify_gen_relational (GE, mode, VOIDmode,
XEXP (op, 0), const0_rtx);
@@ -3419,6 +3419,31 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
}
}
+ /* If we have two nested selects that are inverses of each
+ other, replace them with the source operand. */
+ if (GET_CODE (trueop0) == VEC_SELECT
+ && GET_MODE (XEXP (trueop0, 0)) == mode)
+ {
+ rtx op0_subop1 = XEXP (trueop0, 1);
+ gcc_assert (GET_CODE (op0_subop1) == PARALLEL);
+ gcc_assert (XVECLEN (trueop1, 0) == GET_MODE_NUNITS (mode));
+
+ /* Apply the outer ordering vector to the inner one. (The inner
+ ordering vector is expressly permitted to be of a different
+ length than the outer one.) If the result is { 0, 1, ..., n-1 }
+ then the two VEC_SELECTs cancel. */
+ for (int i = 0; i < XVECLEN (trueop1, 0); ++i)
+ {
+ rtx x = XVECEXP (trueop1, 0, i);
+ if (!CONST_INT_P (x))
+ return 0;
+ rtx y = XVECEXP (op0_subop1, 0, INTVAL (x));
+ if (!CONST_INT_P (y) || i != INTVAL (y))
+ return 0;
+ }
+ return XEXP (trueop0, 0);
+ }
+
return 0;
case VEC_CONCAT:
{
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 163d495b2b0..7c1ea5d5cb9 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -59,6 +59,7 @@ along with GCC; see the file COPYING3. If not see
#include "pretty-print.h"
#include "params.h"
#include "dumpfile.h"
+#include "builtins.h"
/* Functions and data structures for expanding case statements. */
@@ -774,24 +775,20 @@ static void
dump_case_nodes (FILE *f, struct case_node *root,
int indent_step, int indent_level)
{
- HOST_WIDE_INT low, high;
-
if (root == 0)
return;
indent_level++;
dump_case_nodes (f, root->left, indent_step, indent_level);
- low = tree_to_shwi (root->low);
- high = tree_to_shwi (root->high);
-
fputs (";; ", f);
- if (high == low)
- fprintf (f, "%*s" HOST_WIDE_INT_PRINT_DEC,
- indent_step * indent_level, "", low);
- else
- fprintf (f, "%*s" HOST_WIDE_INT_PRINT_DEC " ... " HOST_WIDE_INT_PRINT_DEC,
- indent_step * indent_level, "", low, high);
+ fprintf (f, "%*s", indent_step * indent_level, "");
+ print_dec (root->low, f, TYPE_SIGN (TREE_TYPE (root->low)));
+ if (!tree_int_cst_equal (root->low, root->high))
+ {
+ fprintf (f, " ... ");
+ print_dec (root->high, f, TYPE_SIGN (TREE_TYPE (root->high)));
+ }
fputs ("\n", f);
dump_case_nodes (f, root->right, indent_step, indent_level);
diff --git a/gcc/stringpool.c b/gcc/stringpool.c
index 4b6900cd1b7..c880cb1e678 100644
--- a/gcc/stringpool.c
+++ b/gcc/stringpool.c
@@ -79,7 +79,7 @@ alloc_node (cpp_hash_table *table ATTRIBUTE_UNUSED)
nul-terminated string, and the length is calculated using strlen. */
const char *
-ggc_alloc_string_stat (const char *contents, int length MEM_STAT_DECL)
+ggc_alloc_string (const char *contents, int length MEM_STAT_DECL)
{
char *result;
@@ -91,7 +91,7 @@ ggc_alloc_string_stat (const char *contents, int length MEM_STAT_DECL)
if (length == 1 && ISDIGIT (contents[0]))
return digit_string (contents[0] - '0');
- result = (char *) ggc_alloc_atomic_stat (length + 1 PASS_MEM_STAT);
+ result = (char *) ggc_internal_cleared_alloc (length + 1 PASS_MEM_STAT);
memcpy (result, contents, length);
result[length] = '\0';
return (const char *) result;
@@ -258,10 +258,10 @@ static GTY(()) struct string_pool_data * spd;
void
gt_pch_save_stringpool (void)
{
- spd = ggc_alloc_string_pool_data ();
+ spd = ggc_alloc<string_pool_data> ();
spd->nslots = ident_hash->nslots;
spd->nelements = ident_hash->nelements;
- spd->entries = ggc_alloc_vec_ht_identifier_ptr (spd->nslots);
+ spd->entries = ggc_vec_alloc<ht_identifier_ptr> (spd->nslots);
memcpy (spd->entries, ident_hash->entries,
spd->nslots * sizeof (spd->entries[0]));
}
diff --git a/gcc/symtab.c b/gcc/symtab.c
index f948e774259..79fdbc28469 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -57,8 +57,6 @@ const char * const ld_plugin_symbol_resolution_names[]=
"prevailing_def_ironly_exp"
};
-/* Hash table used to convert declarations into nodes. */
-static GTY((param_is (symtab_node))) htab_t symtab_hash;
/* Hash table used to convert assembler names into nodes. */
static GTY((param_is (symtab_node))) htab_t assembler_name_hash;
@@ -70,26 +68,6 @@ symtab_node *symtab_nodes;
them, to support -fno-toplevel-reorder. */
int symtab_order;
-/* Returns a hash code for P. */
-
-static hashval_t
-hash_node (const void *p)
-{
- const symtab_node *n = (const symtab_node *) p;
- return (hashval_t) DECL_UID (n->decl);
-}
-
-
-/* Returns nonzero if P1 and P2 are equal. */
-
-static int
-eq_node (const void *p1, const void *p2)
-{
- const symtab_node *n1 = (const symtab_node *) p1;
- const symtab_node *n2 = (const symtab_node *) p2;
- return DECL_UID (n1->decl) == DECL_UID (n2->decl);
-}
-
/* Hash asmnames ignoring the user specified marks. */
static hashval_t
@@ -282,21 +260,14 @@ symtab_prevail_in_asm_name_hash (symtab_node *node)
void
symtab_register_node (symtab_node *node)
{
- struct symtab_node key;
- symtab_node **slot;
-
node->next = symtab_nodes;
node->previous = NULL;
if (symtab_nodes)
symtab_nodes->previous = node;
symtab_nodes = node;
- if (!symtab_hash)
- symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
- key.decl = node->decl;
- slot = (symtab_node **) htab_find_slot (symtab_hash, &key, INSERT);
- if (*slot == NULL)
- *slot = node;
+ if (!node->decl->decl_with_vis.symtab_node)
+ node->decl->decl_with_vis.symtab_node = node;
ipa_empty_ref_list (&node->ref_list);
@@ -307,32 +278,11 @@ symtab_register_node (symtab_node *node)
insert_to_assembler_name_hash (node, false);
}
-/* Make NODE to be the one symtab hash is pointing to. Used when reshaping tree
- of inline clones. */
+/* Remove NODE from same comdat group. */
void
-symtab_insert_node_to_hashtable (symtab_node *node)
+symtab_remove_from_same_comdat_group (symtab_node *node)
{
- struct symtab_node key;
- symtab_node **slot;
-
- if (!symtab_hash)
- symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
- key.decl = node->decl;
- slot = (symtab_node **) htab_find_slot (symtab_hash, &key, INSERT);
- *slot = node;
-}
-
-/* Remove node from symbol table. This function is not used directly, but via
- cgraph/varpool node removal routines. */
-
-void
-symtab_unregister_node (symtab_node *node)
-{
- void **slot;
- ipa_remove_all_references (&node->ref_list);
- ipa_remove_all_referring (&node->ref_list);
-
if (node->same_comdat_group)
{
symtab_node *prev;
@@ -346,6 +296,18 @@ symtab_unregister_node (symtab_node *node)
prev->same_comdat_group = node->same_comdat_group;
node->same_comdat_group = NULL;
}
+}
+
+/* Remove node from symbol table. This function is not used directly, but via
+ cgraph/varpool node removal routines. */
+
+void
+symtab_unregister_node (symtab_node *node)
+{
+ ipa_remove_all_references (&node->ref_list);
+ ipa_remove_all_referring (&node->ref_list);
+
+ symtab_remove_from_same_comdat_group (node);
if (node->previous)
node->previous->next = node->next;
@@ -356,55 +318,20 @@ symtab_unregister_node (symtab_node *node)
node->next = NULL;
node->previous = NULL;
- slot = htab_find_slot (symtab_hash, node, NO_INSERT);
-
/* During LTO symtab merging we temporarily corrupt decl to symtab node
hash. */
- gcc_assert ((slot && *slot) || in_lto_p);
- if (slot && *slot && *slot == node)
+ gcc_assert (node->decl->decl_with_vis.symtab_node || in_lto_p);
+ if (node->decl->decl_with_vis.symtab_node == node)
{
symtab_node *replacement_node = NULL;
if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
replacement_node = cgraph_find_replacement_node (cnode);
- if (!replacement_node)
- htab_clear_slot (symtab_hash, slot);
- else
- *slot = replacement_node;
+ node->decl->decl_with_vis.symtab_node = replacement_node;
}
if (!is_a <varpool_node *> (node) || !DECL_HARD_REGISTER (node->decl))
unlink_from_assembler_name_hash (node, false);
}
-/* Return symbol table node associated with DECL, if any,
- and NULL otherwise. */
-
-symtab_node *
-symtab_get_node (const_tree decl)
-{
- symtab_node **slot;
- struct symtab_node key;
-
-#ifdef ENABLE_CHECKING
- /* Check that we are called for sane type of object - functions
- and static or external variables. */
- gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL
- || (TREE_CODE (decl) == VAR_DECL
- && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
- || in_lto_p)));
-#endif
-
- if (!symtab_hash)
- return NULL;
-
- key.decl = CONST_CAST2 (tree, const_tree, decl);
-
- slot = (symtab_node **) htab_find_slot (symtab_hash, &key,
- NO_INSERT);
-
- if (slot)
- return *slot;
- return NULL;
-}
/* Remove symtab NODE from the symbol table. */
@@ -505,11 +432,11 @@ void
symtab_add_to_same_comdat_group (symtab_node *new_node,
symtab_node *old_node)
{
- gcc_assert (DECL_ONE_ONLY (old_node->decl));
+ gcc_assert (old_node->get_comdat_group ());
gcc_assert (!new_node->same_comdat_group);
gcc_assert (new_node != old_node);
- DECL_COMDAT_GROUP (new_node->decl) = DECL_COMDAT_GROUP (old_node->decl);
+ new_node->set_comdat_group (old_node->get_comdat_group ());
new_node->same_comdat_group = old_node;
if (!old_node->same_comdat_group)
old_node->same_comdat_group = new_node;
@@ -538,10 +465,10 @@ symtab_dissolve_same_comdat_group_list (symtab_node *node)
{
next = n->same_comdat_group;
n->same_comdat_group = NULL;
- /* Clear DECL_COMDAT_GROUP for comdat locals, since
+ /* Clear comdat_group for comdat locals, since
make_decl_local doesn't. */
if (!TREE_PUBLIC (n->decl))
- DECL_COMDAT_GROUP (n->decl) = NULL_TREE;
+ n->set_comdat_group (NULL);
n = next;
}
while (n != node);
@@ -631,9 +558,9 @@ dump_symtab_base (FILE *f, symtab_node *node)
fprintf (f, " dll_import");
if (DECL_COMDAT (node->decl))
fprintf (f, " comdat");
- if (DECL_COMDAT_GROUP (node->decl))
+ if (node->get_comdat_group ())
fprintf (f, " comdat_group:%s",
- IDENTIFIER_POINTER (DECL_COMDAT_GROUP (node->decl)));
+ IDENTIFIER_POINTER (node->get_comdat_group_id ()));
if (DECL_ONE_ONLY (node->decl))
fprintf (f, " one_only");
if (DECL_SECTION_NAME (node->decl))
@@ -758,7 +685,7 @@ verify_symtab_base (symtab_node *node)
hashed_node = symtab_get_node (node->decl);
if (!hashed_node)
{
- error ("node not found in symtab decl hashtable");
+ error ("node not found node->decl->decl_with_vis.symtab_node");
error_found = true;
}
if (hashed_node != node
@@ -767,7 +694,7 @@ verify_symtab_base (symtab_node *node)
|| dyn_cast <cgraph_node *> (node)->clone_of->decl
!= node->decl))
{
- error ("node differs from symtab decl hashtable");
+ error ("node differs from node->decl->decl_with_vis.symtab_node");
error_found = true;
}
}
@@ -824,9 +751,19 @@ verify_symtab_base (symtab_node *node)
{
symtab_node *n = node->same_comdat_group;
- if (!DECL_ONE_ONLY (n->decl))
+ if (!n->get_comdat_group ())
+ {
+ error ("node is in same_comdat_group list but has no comdat_group");
+ error_found = true;
+ }
+ if (n->get_comdat_group () != node->get_comdat_group ())
{
- error ("non-DECL_ONE_ONLY node in a same_comdat_group list");
+ error ("same_comdat_group list across different groups");
+ error_found = true;
+ }
+ if (!n->definition)
+ {
+ error ("Node has same_comdat_group but it is not a definition");
error_found = true;
}
if (n->type != node->type)
@@ -932,7 +869,7 @@ symtab_make_decl_local (tree decl)
{
rtx rtl, symbol;
- /* Avoid clearing DECL_COMDAT_GROUP on comdat-local decls. */
+ /* Avoid clearing comdat_groups on comdat-local decls. */
if (TREE_PUBLIC (decl) == 0)
return;
@@ -940,12 +877,11 @@ symtab_make_decl_local (tree decl)
DECL_COMMON (decl) = 0;
else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
- if (DECL_ONE_ONLY (decl) || DECL_COMDAT (decl))
+ if (DECL_COMDAT (decl))
{
DECL_SECTION_NAME (decl) = 0;
DECL_COMDAT (decl) = 0;
}
- DECL_COMDAT_GROUP (decl) = 0;
DECL_WEAK (decl) = 0;
DECL_EXTERNAL (decl) = 0;
DECL_VISIBILITY_SPECIFIED (decl) = 0;
@@ -1079,11 +1015,13 @@ fixup_same_cpp_alias_visibility (symtab_node *node, symtab_node *target)
DECL_VIRTUAL_P (node->decl) = DECL_VIRTUAL_P (target->decl);
if (TREE_PUBLIC (node->decl))
{
+ tree group;
+
DECL_EXTERNAL (node->decl) = DECL_EXTERNAL (target->decl);
DECL_COMDAT (node->decl) = DECL_COMDAT (target->decl);
- DECL_COMDAT_GROUP (node->decl)
- = DECL_COMDAT_GROUP (target->decl);
- if (DECL_ONE_ONLY (target->decl)
+ group = target->get_comdat_group ();
+ node->set_comdat_group (group);
+ if (group
&& !node->same_comdat_group)
symtab_add_to_same_comdat_group (node, target);
}
@@ -1124,7 +1062,7 @@ symtab_resolve_alias (symtab_node *node, symtab_node *target)
node->analyzed = true;
ipa_record_reference (node, target, IPA_REF_ALIAS, NULL);
- /* Alias targets become reudndant after alias is resolved into an reference.
+ /* Alias targets become redundant after alias is resolved into an reference.
We do not want to keep it around or we would have to mind updating them
when renaming symbols. */
node->alias_target = NULL;
@@ -1213,9 +1151,6 @@ symtab_nonoverwritable_alias (symtab_node *node)
/* Update the properties. */
DECL_EXTERNAL (new_decl) = 0;
- if (DECL_ONE_ONLY (node->decl))
- DECL_SECTION_NAME (new_decl) = NULL;
- DECL_COMDAT_GROUP (new_decl) = 0;
TREE_PUBLIC (new_decl) = 0;
DECL_COMDAT (new_decl) = 0;
DECL_WEAK (new_decl) = 0;
@@ -1228,10 +1163,13 @@ symtab_nonoverwritable_alias (symtab_node *node)
(new_decl, node->decl);
}
else
- new_node = varpool_create_variable_alias (new_decl,
- node->decl);
+ {
+ TREE_READONLY (new_decl) = TREE_READONLY (node->decl);
+ new_node = varpool_create_variable_alias (new_decl, node->decl);
+ }
symtab_resolve_alias (new_node, node);
- gcc_assert (decl_binds_to_current_def_p (new_decl));
+ gcc_assert (decl_binds_to_current_def_p (new_decl)
+ && targetm.binds_local_p (new_decl));
return new_node;
}
@@ -1310,8 +1248,7 @@ symtab_get_symbol_partitioning_class (symtab_node *node)
return SYMBOL_EXTERNAL;
/* Linker discardable symbols are duplicated to every use unless they are
- keyed.
- Keyed symbols or those. */
+ keyed. */
if (DECL_ONE_ONLY (node->decl)
&& !node->force_output
&& !node->forced_by_abi
diff --git a/gcc/system.h b/gcc/system.h
index b20b5cfde1d..6cb24b0913b 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -22,6 +22,12 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_SYSTEM_H
#define GCC_SYSTEM_H
+/* Define this so that inttypes.h defines the PRI?64 macros even
+ when compiling with a C++ compiler. Define it here so in the
+ event inttypes.h gets pulled in by another header it is already
+ defined. */
+#define __STDC_FORMAT_MACROS
+
/* We must include stdarg.h before stdio.h. */
#include <stdarg.h>
@@ -1070,7 +1076,10 @@ helper_const_non_const_cast (const char *p)
#define DEBUG_VARIABLE
#endif
-/* Get definitions of HOST_WIDE_INT and HOST_WIDEST_INT. */
+/* General macro to extract bit Y of X. */
+#define TEST_BIT(X, Y) (((X) >> (Y)) & 1)
+
+/* Get definitions of HOST_WIDE_INT. */
#include "hwint.h"
#endif /* ! GCC_SYSTEM_H */
diff --git a/gcc/target-globals.c b/gcc/target-globals.c
index 7cf95aeeddf..f1bfded3979 100644
--- a/gcc/target-globals.c
+++ b/gcc/target-globals.c
@@ -43,12 +43,14 @@ along with GCC; see the file COPYING3. If not see
#include "gcse.h"
#include "bb-reorder.h"
#include "lower-subreg.h"
+#include "recog.h"
#if SWITCHABLE_TARGET
struct target_globals default_target_globals = {
&default_target_flag_state,
&default_target_regs,
&default_target_rtl,
+ &default_target_recog,
&default_target_hard_regs,
&default_target_reload,
&default_target_expmed,
@@ -83,13 +85,14 @@ save_target_globals (void)
g = (struct target_globals *) p;
g->flag_state = &p->flag_state;
g->regs = ggc_internal_cleared_alloc (sizeof (struct target_regs));
- g->rtl = ggc_alloc_cleared_target_rtl ();
+ g->rtl = ggc_cleared_alloc<target_rtl> ();
+ g->recog = ggc_internal_cleared_alloc (sizeof (struct target_recog));
g->hard_regs
= ggc_internal_cleared_alloc (sizeof (struct target_hard_regs));
g->reload = ggc_internal_cleared_alloc (sizeof (struct target_reload));
g->expmed = ggc_internal_cleared_alloc (sizeof (struct target_expmed));
g->optabs = &p->optabs;
- g->libfuncs = ggc_alloc_cleared_target_libfuncs ();
+ g->libfuncs = ggc_cleared_alloc<target_libfuncs> ();
g->cfgloop = &p->cfgloop;
g->ira = ggc_internal_cleared_alloc (sizeof (struct target_ira));
g->ira_int = ggc_internal_cleared_alloc (sizeof (struct target_ira_int));
diff --git a/gcc/target-globals.h b/gcc/target-globals.h
index e848a01677c..f4ef91fd21c 100644
--- a/gcc/target-globals.h
+++ b/gcc/target-globals.h
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
extern struct target_flag_state *this_target_flag_state;
extern struct target_regs *this_target_regs;
extern struct target_rtl *this_target_rtl;
+extern struct target_recog *this_target_recog;
extern struct target_hard_regs *this_target_hard_regs;
extern struct target_reload *this_target_reload;
extern struct target_expmed *this_target_expmed;
@@ -43,6 +44,7 @@ struct GTY(()) target_globals {
struct target_flag_state *GTY((skip)) flag_state;
void *GTY((atomic)) regs;
struct target_rtl *rtl;
+ void *GTY((atomic)) recog;
void *GTY((atomic)) hard_regs;
void *GTY((atomic)) reload;
void *GTY((atomic)) expmed;
@@ -70,6 +72,7 @@ restore_target_globals (struct target_globals *g)
this_target_flag_state = g->flag_state;
this_target_regs = (struct target_regs *) g->regs;
this_target_rtl = g->rtl;
+ this_target_recog = (struct target_recog *) g->recog;
this_target_hard_regs = (struct target_hard_regs *) g->hard_regs;
this_target_reload = (struct target_reload *) g->reload;
this_target_expmed = (struct target_expmed *) g->expmed;
diff --git a/gcc/target.def b/gcc/target.def
index febd3207bed..5fe2e823e27 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -1174,11 +1174,17 @@ DEFHOOK
"\n\
This hook controls what insns from the ready insn queue will be\n\
considered for the multipass insn scheduling. If the hook returns\n\
-zero for @var{insn}, the insn will be not chosen to\n\
-be issued.\n\
+zero for @var{insn}, the insn will be considered in multipass scheduling.\n\
+Positive return values will remove @var{insn} from consideration on\n\
+the current round of multipass scheduling.\n\
+Negative return values will remove @var{insn} from consideration for given\n\
+number of cycles.\n\
+Backends should be careful about returning non-zero for highest priority\n\
+instruction at position 0 in the ready list. @var{ready_index} is passed\n\
+to allow backends make correct judgements.\n\
\n\
The default is that any ready insns can be chosen to be issued.",
- int, (rtx insn), NULL)
+ int, (rtx insn, int ready_index), NULL)
/* This hook prepares the target for a new round of multipass
scheduling.
@@ -1193,7 +1199,7 @@ DEFHOOK
(first_cycle_multipass_begin,
"This hook prepares the target backend for a new round of multipass\n\
scheduling.",
- void, (void *data, char *ready_try, int n_ready, bool first_cycle_insn_p),
+ void, (void *data, signed char *ready_try, int n_ready, bool first_cycle_insn_p),
NULL)
/* This hook is called when multipass scheduling evaluates instruction INSN.
@@ -1209,7 +1215,7 @@ scheduling.",
DEFHOOK
(first_cycle_multipass_issue,
"This hook is called when multipass scheduling evaluates instruction INSN.",
- void, (void *data, char *ready_try, int n_ready, rtx insn,
+ void, (void *data, signed char *ready_try, int n_ready, rtx insn,
const void *prev_data), NULL)
/* This hook is called when multipass scheduling backtracks from evaluation of
@@ -1225,7 +1231,7 @@ DEFHOOK
(first_cycle_multipass_backtrack,
"This is called when multipass scheduling backtracks from evaluation of\n\
an instruction.",
- void, (const void *data, char *ready_try, int n_ready), NULL)
+ void, (const void *data, signed char *ready_try, int n_ready), NULL)
/* This hook notifies the target about the result of the concluded current
round of multipass scheduling.
@@ -1421,26 +1427,6 @@ a pattern for a branchy check corresponding to a simple check denoted by\n\
@var{insn} should be generated. In this case @var{label} can't be null.",
rtx, (rtx insn, rtx label, unsigned int ds), NULL)
-/* The following member value is a pointer to a function controlling
- what insns from the ready insn queue will be considered for the
- multipass insn scheduling. If the hook returns zero for the insn
- passed as the parameter, the insn will not be chosen to be
- issued. This hook is used to discard speculative instructions,
- that stand at the first position of the ready list. */
-DEFHOOK
-(first_cycle_multipass_dfa_lookahead_guard_spec,
- "This hook is used as a workaround for\n\
-@samp{TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD} not being\n\
-called on the first instruction of the ready list. The hook is used to\n\
-discard speculative instructions that stand first in the ready list from\n\
-being scheduled on the current cycle. If the hook returns @code{false},\n\
-@var{insn} will not be chosen to be issued.\n\
-For non-speculative instructions,\n\
-the hook should always return @code{true}. For example, in the ia64 backend\n\
-the hook is used to cancel data speculative insns when the ALAT table\n\
-is nearly full.",
- bool, (const_rtx insn), NULL)
-
/* The following member value is a pointer to a function that provides
information about the speculation capabilities of the target.
The parameter is a pointer to spec_info variable. */
@@ -5373,5 +5359,43 @@ bool, false)
/* Leave the boolean fields at the end. */
+/* Functions related to mode switching. */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_MODE_"
+HOOK_VECTOR (TARGET_TOGGLE_, mode_switching)
+
+DEFHOOK
+(emit,
+ "Generate one or more insns to set @var{entity} to @var{mode}. @var{hard_reg_live} is the set of hard registers live at the point where the insn(s) are to be inserted. Sets of a lower numbered entity will be emitted before sets of a higher numbered entity to a mode of the same or lower priority.",
+ void, (int entity, int mode, HARD_REG_SET regs_live), NULL)
+
+DEFHOOK
+(needed,
+ "@var{entity} is an integer specifying a mode-switched entity. If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this macro to return an integer value not larger than the corresponding element in @code{NUM_MODES_FOR_MODE_SWITCHING}, to denote the mode that @var{entity} must be switched into prior to the execution of @var{insn}.",
+ int, (int entity, rtx insn), NULL)
+
+DEFHOOK
+(after,
+ "@var{entity} is an integer specifying a mode-switched entity. If this macro is defined, it is evaluated for every @var{insn} during mode switching. It determines the mode that an insn results in (if different from the incoming mode).",
+ int, (int entity, int mode, rtx insn), NULL)
+
+DEFHOOK
+(entry,
+ "If this macro is defined, it is evaluated for every @var{entity} that needs mode switching. It should evaluate to an integer, which is a mode that @var{entity} is assumed to be switched to at function entry. If @code{TARGET_MODE_ENTRY} is defined then @code{TARGET_MODE_EXIT} must be defined.",
+ int, (int entity), NULL)
+
+DEFHOOK
+(exit,
+ "If this macro is defined, it is evaluated for every @var{entity} that needs mode switching. It should evaluate to an integer, which is a mode that @var{entity} is assumed to be switched to at function exit. If @code{TARGET_MODE_EXIT} is defined then @code{TARGET_MODE_ENTRY} must be defined.",
+ int, (int entity), NULL)
+
+DEFHOOK
+(priority,
+ "This macro specifies the order in which modes for @var{entity} are processed. 0 is the highest priority, @code{NUM_MODES_FOR_MODE_SWITCHING[@var{entity}] - 1} the lowest. The value of the macro should be an integer designating a mode for @var{entity}. For any fixed @var{entity}, @code{mode_priority} (@var{entity}, @var{n}) shall be a bijection in 0 @dots{} @code{num_modes_for_mode_switching[@var{entity}] - 1}.",
+ int, (int entity, int n), NULL)
+
+HOOK_VECTOR_END (mode_switching)
+
/* Close the 'struct gcc_target' definition. */
HOOK_VECTOR_END (C90_EMPTY_HACK)
+
diff --git a/gcc/target.h b/gcc/target.h
index 31123d97b3e..7be94b82558 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -51,6 +51,8 @@
#include "insn-modes.h"
#include "insn-codes.h"
#include "wide-int.h"
+#include "tm.h"
+#include "hard-reg-set.h"
#ifdef ENABLE_CHECKING
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 3df93d39432..dfbd2543086 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -1322,6 +1322,31 @@ default_have_conditional_execution (void)
#endif
}
+/* By default we assume that c99 functions are present at the runtime,
+ but sincos is not. */
+bool
+default_libc_has_function (enum function_class fn_class)
+{
+ if (fn_class == function_c94
+ || fn_class == function_c99_misc
+ || fn_class == function_c99_math_complex)
+ return true;
+
+ return false;
+}
+
+bool
+gnu_libc_has_function (enum function_class fn_class ATTRIBUTE_UNUSED)
+{
+ return true;
+}
+
+bool
+no_c99_libc_has_function (enum function_class fn_class ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
tree
default_builtin_tm_load_store (tree ARG_UNUSED (type))
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 97ce690bff9..590969e82cc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,1002 @@
+2014-06-02 Jeff Law <law@redhat.com>
+
+ PR rtl-optimization/61094
+ * g++.dg/pr61094: New test.
+
+2014-06-02 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/xop-rotate1-vector.c (dg-options): Add -mno-avx2.
+ * gcc.target/i386/xop-rotate2-vector.c (dg-options): Ditto.
+ * gcc.target/i386/xop-rotate3-vector.c (dg-options): Ditto.
+ * gcc.target/i386/xop-imul32widen-vector.c (dg-options): Ditto.
+ * gcc.target/i386/xop-imul64-vector.c (dg-options): Ditto.
+ * gcc.target/i386/xop-shift1-vector.c (dg-options): Ditto.
+ * gcc.target/i386/xop-shift2-vector.c (dg-options): Ditto.
+ * gcc.target/i386/xop-shift3-vector.c (dg-options): Ditto.
+
+2014-06-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61346
+ * gcc.dg/torture/pr61346.c: New testcase.
+
+2014-06-01 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/sibcall-2.c: Xfail dg-final scan-assembler-not,
+ not compilation.
+ * gcc.target/i386/sibcall-4.c: Ditto.
+ * gcc.target/i386/fuse-caller-save.c: Add -mregparm=1 for ia32 target.
+
+2014-06-01 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/sibcall-2.c (dg-final): Properly escape '[' and ']'
+ in scan-assembler-not string.
+ * gcc.target/i386/sibcall-3.c (dg-final): Ditto.
+ * gcc.target/i386/sibcall-4.c (dg-final): Ditto.
+ * gcc.target/i386/sibcall-6.c (dg-final): Ditto.
+
+2014-06-01 Uros Bizjak <ubizjak@gmail.com>
+
+ * g++.dg/pr60969.C (dg-do compile): Change ilp32 target to ia32.
+
+2014-06-01 Kai Tietz <ktietz@redhat.com>
+
+ PR target/61377
+ * gcc.target/i386/sibcall-6.c: New test.
+
+2014-05-31 Paolo Carlini <paolo.carlini@oracle.com>
+
+ DR 1227
+ PR c++/57543
+ * g++.dg/cpp0x/pr57543-1.C: New.
+ * g++.dg/cpp0x/pr57543-2.C: Likewise.
+ * g++.dg/cpp0x/pr57543-3.C: Likewise.
+ * g++.dg/cpp0x/decltype59.C: Likewise.
+
+2014-05-31 Tom de Vries <tom@codesourcery.com>
+
+ * gcc.target/i386/sibcall-4.c: Add missing closing brace.
+
+2014-05-30 Jakub Jelinek <jakub@redhat.com>
+
+ * lib/target-libpath.exp (set_gcc_exec_prefix_env_var,
+ restore_gcc_exec_prefix_env_var): New procedures.
+ (set_ld_library_path_env_vars,
+ restore_ld_library_path_env_vars): Use them.
+ * lib/c-compat.exp: Load target-libpath.exp.
+ (compat-use-alt-compiler): Call restore_gcc_exec_prefix_env_var.
+ (compat-use-tst-compiler): Call set_gcc_exec_prefix_env_var.
+ * g++.dg/compat/compat.exp (compat-use-alt-compiler): Call
+ restore_gcc_exec_prefix_env_var.
+ * g++.dg/compat/struct-layout-1.exp (compat-use-alt-compiler):
+ Likewise.
+
+ * c-c++-common/asan/misalign-1.c: New test.
+ * c-c++-common/asan/misalign-2.c: New test.
+
+ * g++.dg/asan/asan_test.C: Add -std=c++11 and
+ -DSANITIZER_USE_DEJAGNU_GTEST=1 to dg-options, remove
+ -DASAN_USE_DEJAGNU_GTEST=1.
+ * g++.dg/asan/asan_mem_test.cc: Updated from upstream r209283.
+ * g++.dg/asan/asan_oob_test.cc: Likewise.
+ * g++.dg/asan/sanitizer_test_utils.h: Likewise.
+ * g++.dg/asan/asan_str_test.cc: Likewise.
+ * g++.dg/asan/asan_test_utils.h: Likewise.
+ * g++.dg/asan/sanitizer_test_config.h: Likewise.
+ * g++.dg/asan/asan_test.cc: Likewise. Allow size 12 for long double.
+ * g++.dg/asan/sanitizer_pthread_wrappers.h: New file.
+ Imported from upstream r209283.
+ * g++.dg/asan/asan_test_config.h: Likewise.
+
+2014-05-30 Kai Tietz <ktietz@redhat.com>
+
+ PR target/60104
+ * gcc.target/i386/sibcall-1.c: New test.
+ * gcc.target/i386/sibcall-2.c: New test.
+ * gcc.target/i386/sibcall-3.c: New test.
+ * gcc.target/i386/sibcall-4.c: New test.
+
+2014-05-30 Ian Lance Taylor <iant@google.com>
+
+ * gcc.target/i386/pause-2.c: New test.
+
+2014-05-30 Tom de Vries <tom@codesourcery.com>
+
+ * gcc.target/i386/fuse-caller-save.c: New test.
+ * gcc.dg/ira-shrinkwrap-prep-1.c: Run with -fno-use-caller-save.
+ * gcc.dg/ira-shrinkwrap-prep-2.c: Same.
+
+2014-04-30 Alan Lawrence <alan.lawrence@arm.com>
+
+ * gcc.target/arm/simd/vrev16p8_1.c: New file.
+ * gcc.target/arm/simd/vrev16qp8_1.c: New file.
+ * gcc.target/arm/simd/vrev16qs8_1.c: New file.
+ * gcc.target/arm/simd/vrev16qu8_1.c: New file.
+ * gcc.target/arm/simd/vrev16s8_1.c: New file.
+ * gcc.target/arm/simd/vrev16u8_1.c: New file.
+ * gcc.target/arm/simd/vrev32p16_1.c: New file.
+ * gcc.target/arm/simd/vrev32p8_1.c: New file.
+ * gcc.target/arm/simd/vrev32qp16_1.c: New file.
+ * gcc.target/arm/simd/vrev32qp8_1.c: New file.
+ * gcc.target/arm/simd/vrev32qs16_1.c: New file.
+ * gcc.target/arm/simd/vrev32qs8_1.c: New file.
+ * gcc.target/arm/simd/vrev32qu16_1.c: New file.
+ * gcc.target/arm/simd/vrev32qu8_1.c: New file.
+ * gcc.target/arm/simd/vrev32s16_1.c: New file.
+ * gcc.target/arm/simd/vrev32s8_1.c: New file.
+ * gcc.target/arm/simd/vrev32u16_1.c: New file.
+ * gcc.target/arm/simd/vrev32u8_1.c: New file.
+ * gcc.target/arm/simd/vrev64f32_1.c: New file.
+ * gcc.target/arm/simd/vrev64p16_1.c: New file.
+ * gcc.target/arm/simd/vrev64p8_1.c: New file.
+ * gcc.target/arm/simd/vrev64qf32_1.c: New file.
+ * gcc.target/arm/simd/vrev64qp16_1.c: New file.
+ * gcc.target/arm/simd/vrev64qp8_1.c: New file.
+ * gcc.target/arm/simd/vrev64qs16_1.c: New file.
+ * gcc.target/arm/simd/vrev64qs32_1.c: New file.
+ * gcc.target/arm/simd/vrev64qs8_1.c: New file.
+ * gcc.target/arm/simd/vrev64qu16_1.c: New file.
+ * gcc.target/arm/simd/vrev64qu32_1.c: New file.
+ * gcc.target/arm/simd/vrev64qu8_1.c: New file.
+ * gcc.target/arm/simd/vrev64s16_1.c: New file.
+ * gcc.target/arm/simd/vrev64s32_1.c: New file.
+ * gcc.target/arm/simd/vrev64s8_1.c: New file.
+ * gcc.target/arm/simd/vrev64u16_1.c: New file.
+ * gcc.target/arm/simd/vrev64u32_1.c: New file.
+ * gcc.target/arm/simd/vrev64u8_1.c: New file.
+
+2014-05-29 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/61325
+ * gcc.target/aarch64/pr61325.c: New.
+
+2014-05-29 Alan Lawrence <alan.lawrence@arm.com>
+
+ * gcc.target/arm/simd/vextQf32_1.c: New file.
+ * gcc.target/arm/simd/vextQp16_1.c: New file.
+ * gcc.target/arm/simd/vextQp8_1.c: New file.
+ * gcc.target/arm/simd/vextQs16_1.c: New file.
+ * gcc.target/arm/simd/vextQs32_1.c: New file.
+ * gcc.target/arm/simd/vextQs64_1.c: New file.
+ * gcc.target/arm/simd/vextQs8_1.c: New file.
+ * gcc.target/arm/simd/vextQu16_1.c: New file.
+ * gcc.target/arm/simd/vextQu32_1.c: New file.
+ * gcc.target/arm/simd/vextQu64_1.c: New file.
+ * gcc.target/arm/simd/vextQu8_1.c: New file.
+ * gcc.target/arm/simd/vextQp64_1.c: New file.
+ * gcc.target/arm/simd/vextf32_1.c: New file.
+ * gcc.target/arm/simd/vextp16_1.c: New file.
+ * gcc.target/arm/simd/vextp8_1.c: New file.
+ * gcc.target/arm/simd/vexts16_1.c: New file.
+ * gcc.target/arm/simd/vexts32_1.c: New file.
+ * gcc.target/arm/simd/vexts64_1.c: New file.
+ * gcc.target/arm/simd/vexts8_1.c: New file.
+ * gcc.target/arm/simd/vextu16_1.c: New file.
+ * gcc.target/arm/simd/vextu32_1.c: New file.
+ * gcc.target/arm/simd/vextu64_1.c: New file.
+ * gcc.target/arm/simd/vextu8_1.c: New file.
+ * gcc.target/arm/simd/vextp64_1.c: New file.
+
+2014-05-29 Radovan Obradovic <robradovic@mips.com>
+ Tom de Vries <tom@codesourcery.com>
+
+ * gcc.target/mips/mips.exp: Add use-caller-save to -ffoo/-fno-foo
+ options.
+ * gcc.target/mips/fuse-caller-save.h: New include file.
+ * gcc.target/mips/fuse-caller-save.c: New test.
+ * gcc.target/mips/fuse-caller-save-mips16.c: Same.
+ * gcc.target/mips/fuse-caller-save-micromips.c: Same.
+
+2014-05-29 Evgeny Stupachenko <evstupac@gmail.com>
+
+ * gcc.dg/vect/pr52252-ld.c: Fix target and options for the test.
+
+2014-05-28 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/61045
+ * gcc.dg/pr61045.c: New testcase.
+
+2014-05-28 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * lib/clearcap.exp: New file.
+ * gcc.dg/vect/vect.exp: Load clearcap.exp.
+ Remove clearcap_ldflags handling.
+ Call clearcap-init, clearcap-finish.
+ * gcc.target/i386/i386.exp: Likewise.
+ * gcc.target/i386/clearcap.map: Move to ../config/sol2-clearcap.map.
+ * gcc.target/i386/clearcapv2.map: Move to
+ ../config/sol2-clearcapv2.map.
+ * gcc.target/x86_64/abi/avx/abi-avx.exp: Likewise.
+ * gcc.target/x86_64/abi/avx512f/abi-avx512f.exp: Likewise.
+
+2014-05-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61335
+ * gfortran.dg/pr61335.f90: New testcase.
+
+2014-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/aliasing1.adb (dg-final): Robustify pattern matching.
+
+2014-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/overflow_fixed.adb: New test.
+
+2014-05-27 Marek Polacek <polacek@redhat.com>
+
+ PR c/56724
+ * gcc.dg/pr56724-1.c: New test.
+ * gcc.dg/pr56724-2.c: New test.
+ * gcc.dg/wtr-conversion-1.c: Use -Wtraditional-conversion instead of
+ -Wtraditional.
+ * gcc.dg/dfp/wtr-conversion-1.c: Likewise.
+
+2014-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/fold-compare-8.c: New test.
+ * gcc.dg/Wstrict-overflow-25.c: Likewise.
+
+2014-05-27 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/vrp92.c: New testcase.
+
+2014-05-27 Marek Polacek <polacek@redhat.com>
+
+ PR testsuite/61319
+ * c-c++-common/ubsan/float-cast.h: Conditionally define LLONG_MAX,
+ LLONG_MIN, and ULLONG_MAX.
+
+2014-05-27 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * lib/target-supports.exp (check_effective_target_vect_bswap):
+ Specify arm*-*-* support.
+
+2014-05-27 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ PR testsuite/61319
+ * c-c++-common/ubsan/float-cast-overflow-1.c: Make the sign of
+ -nan optional.
+ * c-c++-common/ubsan/float-cast-overflow-2.c: Likewise.
+ * c-c++-common/ubsan/float-cast-overflow-4.c: Likewise.
+
+2014-05-26 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.dg/tree-ssa/ssa-fre-40.c: Cleanup fre1 tree dump.
+
+2014-05-26 Richard Sandiford <r.sandiford@uk.ibm.com>
+
+ PR rtl-optimization/61222
+ * gcc.c-torture/compile/pr61222-1.c: New test.
+ * gcc.c-torture/compile/pr61222-2.c: Likewise.
+
+2014-05-26 Uros Bizjak <ubizjak@gmail.com>
+
+ * c-c++-common/cilk-plus/AN/pr61191.c: Fix dg-error directives.
+
+2014-05-26 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.dg/lto/pr61278_1.c: Remove dg directives.
+
+2014-05-26 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR libgfortran/55117
+ * gfortran.dg/namelist_85.f90: New test.
+
+2014-05-26 Igor Zamyatin <igor.zamyatin@intel.com>
+
+ PR c/61191
+ * c-c++-common/cilk-plus/AN/pr61191.c: Check for correct handling of
+ the case with syntax error.
+
+2014-05-26 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ * gcc.dg/lto/pr61278_0.c: New test.
+ * gcc.dg/lto/pr61278_1.c: New test.
+
+2014-05-26 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ * gcc.dg/pr61220.c: New test.
+ * gcc.dg/shrink-wrap-loop.c: Disable for x86_64 -m32 mode.
+
+2014-05-25 Tobias Burnus <burnus@net-b.de>
+
+ * gfortran.dg/coarray_10.f90: Update dg-warning.
+ * gfortran.dg/coarray_this_image_1.f90: New.
+ * gfortran.dg/coarray_this_image_2.f90: New.
+
+2014-05-24 Jerry DeLisle <jvdelisle@gcc.gnu>
+
+ PR libfortran/61173
+ * gfortran.dg/arrayio_14.f90: New test.
+
+2014-05-24 Andreas Schwab <schwab@suse.de>
+
+ * gcc.c-torture/execute/bswap-2.c (main): Handle more bitfield layouts.
+
+2014-05-24 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ * gfortran.dg/gfortran.dg/bind_c_array_params_2.f90:
+ Adjust regexp for -flto.
+ * gfortran.dg/gfortran.dg/pr48636-2.f90: Likewise.
+ * gfortran.dg/pr52835.f90: Likewise.
+
+2014-05-23 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/61215
+ * gcc.target/i386/pr61215.c: New.
+
+2014-05-23 Marek Polacek <polacek@redhat.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/ubsan/float-cast-overflow-1.c: New test.
+ * c-c++-common/ubsan/float-cast-overflow-10.c: New test.
+ * c-c++-common/ubsan/float-cast-overflow-2.c: New test.
+ * c-c++-common/ubsan/float-cast-overflow-3.c: New test.
+ * c-c++-common/ubsan/float-cast-overflow-4.c: New test.
+ * c-c++-common/ubsan/float-cast-overflow-5.c: New test.
+ * c-c++-common/ubsan/float-cast-overflow-6.c: New test.
+ * c-c++-common/ubsan/float-cast-overflow-7.c: New test.
+ * c-c++-common/ubsan/float-cast-overflow-7.h: New file.
+ * c-c++-common/ubsan/float-cast-overflow-8.c: New test.
+ * c-c++-common/ubsan/float-cast-overflow-9.c: New test.
+ * c-c++-common/ubsan/float-cast.h: New file.
+ * g++.dg/ubsan/float-cast-overflow-bf.C: New test.
+ * gcc.dg/ubsan/float-cast-overflow-bf.c: New test.
+
+2014-05-23 Jiong Wang <jiong.wang@arm.com>
+
+ * gcc.target/aarch64/tail_indirect_call_1.c: New.
+
+2014-05-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/cpp1y/lambda-init9.C: New.
+
+2014-05-23 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/61266
+ * gcc.dg/Wstrict-overflow-18.c: Revert un-XFAILing and
+ adjust testcase to reflect reality.
+
+2014-05-23 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ PR tree-optimization/54733
+ * gcc.dg/optimize-bswapdi-3.c: New test to check extension of bswap
+ optimization to support memory sources and bitwise operations
+ equivalent to load in host endianness.
+ * gcc.dg/optimize-bswaphi-1.c: Likewise.
+ * gcc.dg/optimize-bswapsi-2.c: Likewise.
+ * gcc.c-torture/execute/bswap-2.c: Likewise.
+
+2014-05-23 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * lib/target-supports.exp: New effective targets for architectures
+ capable of performing byte swap.
+ * gcc.dg/optimize-bswapdi-1.c: Convert to new bswap target.
+ * gcc.dg/optimize-bswapdi-2.c: Likewise.
+ * gcc.dg/optimize-bswapsi-1.c: Likewise.
+
+2014-05-22 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/61088
+ * g++.dg/cpp0x/lambda/lambda-ice13.C: New.
+ * g++.dg/cpp0x/lambda/lambda-ice7.C: Adjust.
+
+2014-05-22 Xinliang David Li <davidxl@google.com>
+
+ * g++.dg/ipa/devirt-15.C: Fix expected message.
+ * g++.dg/ipa/devirt-16.C: Ditto.
+ * g++.dg/ipa/devirt-17.C: Ditto.
+ * g++.dg/ipa/devirt-26.C: Ditto.
+ * g++.dg/ipa/imm-devirt-1.C: Ditto.
+ * g++.dg/ipa/imm-devirt-2.C: Ditto.
+ * g++.dg/tree-ssa/pr8781.C:Ditto.
+
+2014-05-22 Peter Bergner <bergner@vnet.ibm.com>
+
+ * gcc.target/powerpc/htm-ttest.c: New test.
+
+2014-05-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/opt37.ad[sb]: New test.
+
+2014-05-21 Jonathan Wakely <jwakely@redhat.com>
+
+ PR c/61271
+ * g++.dg/cilk-plus/AN/array_function.cc: New.
+
+2014-05-22 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/alias-33.c: New testcase.
+
+2014-05-22 Kostya Serebryany <kcc@google.com>
+
+ * c-c++-common/tsan/mutexset1.c: Update the test to match
+ upstream r209283.
+ * g++.dg/asan/symbolize-callback-1.C: Delete the deprecated test.
+
+2014-05-21 Marek Polacek <polacek@redhat.com>
+
+ PR sanitizer/61272
+ * g++.dg/ubsan/pr61272.C: New test.
+
+2014-05-21 Cesar Philippidis <cesar@codesourcery.com>
+ Sandra Loosemore <sandra@codesourcery.com>
+
+ PR lto/60179
+ * lib/scanasm.exp (scan-lto-assembler): New procedure.
+ * gcc.target/nios2/custom-fp-lto.c: New test.
+
+2014-05-21 Andreas Schwab <schwab@suse.de>
+
+ * g++.dg/cpp0x/pr61038.C (operator "" _s): Use size_t.
+
+2014-05-21 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/54236
+ * gcc.target/sh/pr54236-3.c: New.
+
+2014-05-21 Igor Zamyatin <igor.zamyatin@intel.com>
+
+ PR c++/60189
+ * c-c++-common/cilk-plus/CK/invalid_sync.c: New test.
+
+2014-05-20 Jan Hubicka <hubicka@ucw.cz>
+
+ PR tree-optimization/60899
+ * g++.dg/ipa/devirt-11.C: Update template.
+
+2014-05-20 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ PR C++/61038
+ * g++.dg/cpp0x/pr61038.C: New.
+
+2014-05-20 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58753
+ PR c++/58930
+ PR c++/58704
+ * g++.dg/cpp0x/nsdmi-template11.C: New.
+ * g++.dg/cpp0x/nsdmi-template12.C: Likewise.
+ * g++.dg/cpp0x/nsdmi-template13.C: Likewise.
+
+2014-05-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/opt35.adb: New test.
+ * gnat.dg/opt36.adb: Likewise.
+ * gnat.dg/opt35_pkg.ad[sb]: New helper.
+
+2014-05-20 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/60373
+ * g++.dg/cpp0x/Wattributes1.C: New.
+ * g++.dg/ext/visibility/redecl1.C: Adjust.
+ * g++.dg/ext/visibility/visibility-7.C: Likewise.
+
+2014-05-20 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/vsxcopy.c: New test.
+
+2014-05-20 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58664
+ * g++.dg/cpp0x/nsdmi-union6.C: New.
+ * g++.dg/parse/pr58664.C: Likewise.
+ * g++.dg/cpp0x/nsdmi6.C: Tweak.
+ * g++.dg/parse/crash31.C: Likewise.
+ * g++.dg/template/error2.C: Likewise.
+ * g++.dg/template/inherit8.C: Likewise.
+ * g++.dg/template/offsetof2.C: Likewise.
+
+2014-05-19 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * c-c++-common/gomp/simd4.c: Adjust for inform.
+ * g++.dg/cpp0x/decltype-call1.C: Likewise.
+ * g++.dg/cpp0x/forw_enum6.C: Likewise.
+ * g++.dg/cpp0x/lambda/lambda-ice7.C: Likewise.
+ * g++.dg/cpp0x/noexcept15.C: Likewise.
+ * g++.dg/cpp0x/variadic-ex2.C: Likewise.
+ * g++.dg/eh/spec6.C: Likewise.
+ * g++.dg/expr/cast1.C: Likewise.
+ * g++.dg/expr/dtor1.C: Likewise.
+ * g++.dg/ext/is_base_of_diagnostic.C: Likewise.
+ * g++.dg/ext/unary_trait_incomplete.C: Likewise.
+ * g++.dg/gomp/pr49223-2.C: Likewise.
+ * g++.dg/gomp/udr-4.C: Likewise.
+ * g++.dg/init/delete1.C: Likewise.
+ * g++.dg/other/crash-2.C: Likewise.
+ * g++.dg/parse/crash24.C: Likewise.
+ * g++.dg/parse/crash25.C: Likewise.
+ * g++.dg/parse/crash31.C: Likewise.
+ * g++.dg/parse/crash49.C: Likewise.
+ * g++.dg/parse/crash50.C: Likewise.
+ * g++.dg/parse/crash54.C: Likewise.
+ * g++.dg/parse/dtor7.C: Likewise.
+ * g++.dg/parse/error40.C: Likewise.
+ * g++.dg/parse/fused-params1.C: Likewise.
+ * g++.dg/parse/new1.C: Likewise.
+ * g++.dg/template/crash35.C: Likewise.
+ * g++.dg/template/crash59.C: Likewise.
+ * g++.dg/template/crash77.C: Likewise.
+ * g++.dg/template/error51.C: Likewise.
+ * g++.dg/template/incomplete1.C: Likewise.
+ * g++.dg/template/incomplete3.C: Likewise.
+ * g++.dg/template/incomplete4.C: Likewise.
+ * g++.dg/template/incomplete5.C: Likewise.
+ * g++.dg/template/inherit8.C: Likewise.
+ * g++.dg/template/instantiate1.C: Likewise.
+ * g++.dg/template/instantiate3.C: Likewis: Likewise.
+ * g++.dg/template/offsetof2.C: Likewise.
+ * g++.dg/tm/pr51928.C: Likewise.
+ * g++.dg/warn/Wdelete-incomplete-1.C: Likewise.
+ * g++.dg/warn/incomplete1.C: Likewise.
+ * g++.dg/warn/incomplete2.C: Likewise.
+ * g++.old-deja/g++.brendan/friend4.C: Likewise.
+ * g++.old-deja/g++.bugs/900121_01.C: Likewise.
+ * g++.old-deja/g++.bugs/900214_01.C: Likewise.
+ * g++.old-deja/g++.eh/catch1.C: Likewise.
+ * g++.old-deja/g++.eh/spec6.C: Likewise.
+ * g++.old-deja/g++.mike/p7868.C: Likewise.
+ * g++.old-deja/g++.other/crash38.C: Likewise.
+ * g++.old-deja/g++.other/enum2.C: Likewise.
+ * g++.old-deja/g++.other/incomplete.C: Likewise.
+ * g++.old-deja/g++.other/vaarg3.C: Likewise.
+ * g++.old-deja/g++.pt/crash9.C: Likewise.
+ * g++.old-deja/g++.pt/niklas01a.C: Likewise.
+ * g++.old-deja/g++.pt/typename8.C: Likewise.
+ * g++.old-deja/g++.robertl/ice990323-1.C: Likewise.
+
+2014-05-19 Joseph Myers <joseph@codesourcery.com>
+
+ * lib/target-supports.exp
+ (check_effective_target_vect_sizes_32B_16B): Return false if
+ 128-bit AVX vectors preferred.
+
+2014-05-19 Mike Stump <mikestump@comcast.net>
+
+ * lib/target-supports.exp (check_effective_target_avx): Early out
+ if not x86 to prevent x86 flags on non-x86 targets.
+
+2014-05-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61221
+ * gcc.dg/torture/pr61221.c: New testcase.
+
+2014-05-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61209
+ * gfortran.dg/pr61209.f90: New testcase.
+
+2014-05-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61184
+ * c-c++-common/torture/pr61184.c: New testcase.
+
+2014-05-19 Christian Bruel <christian.bruel@st.com>
+
+ PR target/61195
+ * gcc.target/sh/pr61195.c: New test.
+
+2014-05-18 Wei Mi <wmi@google.com>
+
+ PR target/58066
+ * gcc.target/i386/pr58066.c: Replace pattern matching of .cfi
+ directive with rtl insns. Add effective-target fpic and
+ tls_native.
+
+2014-05-17 Xinliang David Li <davidxl@google.com>
+
+ * g++.dg/ipa/devirt-33.C: New testcase.
+
+2014-05-17 Jan Hubicka <hubicka@ucw.cz>
+
+ * g++.dg/ipa/comdat.C: New file.
+
+2014-05-18 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/volatile12.ad[sb]: New test.
+
+2014-05-18 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/enum3.adb: New test.
+
+2014-05-18 Andreas Schwab <schwab@suse.de>
+
+ * gcc.target/ia64/visibility-1.c (variable_l): Add used attribute.
+
+2014-05-17 Jerry DeLisle <jvdelisle@gcc.gnu>
+
+ PR libfortran/52539
+ * gfortran.dg/namelist_utf8.f90: New test.
+
+2014-05-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/52875
+ * g++.dg/cpp0x/decltype58.C: New.
+
+2014-05-17 Ajit Agarwal <ajitkum@xilinx.com>
+
+ * gcc.target/microblaze/others/break_handler.c: New.
+
+2014-05-17 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/61140
+ PR tree-optimization/61150
+ PR tree-optimization/61197
+ * gcc.dg/tree-ssa/pr61140.c: New file.
+ * gcc.dg/tree-ssa/pr61150.c: New file.
+ * gcc.dg/tree-ssa/pr61197.c: New file.
+
+2014-05-17 Uros Bizjak <ubizjak@gmail.com>
+
+ * g++.dg/pr60969.C: Compile for all ilp32 x86 targets.
+ (dg-options): Add -mfpmath=387.
+ (dg-final): Check that no MMX registers are used.
+
+2014-05-17 Andreas Schwab <schwab@suse.de>
+
+ * gcc.target/ia64/visibility-1.c (variable_i): Add used attribute.
+
+2014-05-16 David Malcolm <dmalcolm@redhat.com>
+
+ Revert:
+ 2014-04-29 David Malcolm <dmalcolm@redhat.com>
+
+ * gcc.dg/tree-ssa/pr23401.c: Update the expected number of
+ occurrences of "int" in the gimple dump to reflect that the return
+ types of functions now show up in such dumps.
+ * gcc.dg/tree-ssa/pr27810.c: Likewise.
+
+2014-05-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * gcc.c-torture/execute/20101011-1.c: Update testcase.
+ * gcc.dg/ira-shrinkwrap-prep-1.c: Update testcase.
+ * gcc.dg/tree-ssa/writeonly.c: New testcase.
+ * gcc.dg/tree-ssa/ssa-dse-6.c: Update testcase.
+ * gcc.dg/tree-ssa/pr21559.c: Update testcase.
+ * gcc.dg/debug/pr35154.c: Update testcase.
+ * gcc.target/i386/vectorize1.c: Update testcase.
+
+2014-05-16 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51640
+ * g++.dg/parse/error54.C: New.
+
+2014-05-16 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/60969
+ * g++.dg/pr60969.C: New.
+
+2014-05-16 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61194
+ * gcc.dg/vect/pr61194.c: New testcase.
+
+2014-05-16 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/ssa-fre-39.c: New testcase.
+ * gcc.dg/tree-ssa/ssa-fre-40.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-pre-8.c: One more elimination.
+ * gcc.dg/tree-ssa/struct-aliasing-2.c: Scan cddce1 dump.
+
+2014-05-16 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/ssa-fre-41.c: New testcase.
+
+2014-05-15 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/61085
+ * g++.dg/ipa/pr61085.C: New test.
+
+2014-05-15 Martin Jambor <mjambor@suse.cz>
+
+ PR tree-optimization/61090
+ * gcc.dg/tree-ssa/pr61090.c: New test.
+
+2014-05-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/61158
+ * gcc.dg/pr61158.c: New test.
+
+2014-05-15 Andreas Schwab <schwab@suse.de>
+
+ * obj-c++.dg/exceptions-3.mm: Remove check for message no longer
+ emitted.
+ * obj-c++.dg/exceptions-5.mm: Likewise.
+
+2014-05-15 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ * shrink-wrap-loop.c: New test case.
+
+2014-05-14 Alan Lawrence <alan.lawrence@arm.com>
+
+ * gcc.target/arm/simd/vtrnqf32_1.c: New file.
+ * gcc.target/arm/simd/vtrnqp16_1.c: New file.
+ * gcc.target/arm/simd/vtrnqp8_1.c: New file.
+ * gcc.target/arm/simd/vtrnqs16_1.c: New file.
+ * gcc.target/arm/simd/vtrnqs32_1.c: New file.
+ * gcc.target/arm/simd/vtrnqs8_1.c: New file.
+ * gcc.target/arm/simd/vtrnqu16_1.c: New file.
+ * gcc.target/arm/simd/vtrnqu32_1.c: New file.
+ * gcc.target/arm/simd/vtrnqu8_1.c: New file.
+ * gcc.target/arm/simd/vtrnf32_1.c: New file.
+ * gcc.target/arm/simd/vtrnp16_1.c: New file.
+ * gcc.target/arm/simd/vtrnp8_1.c: New file.
+ * gcc.target/arm/simd/vtrns16_1.c: New file.
+ * gcc.target/arm/simd/vtrns32_1.c: New file.
+ * gcc.target/arm/simd/vtrns8_1.c: New file.
+ * gcc.target/arm/simd/vtrnu16_1.c: New file.
+ * gcc.target/arm/simd/vtrnu32_1.c: New file.
+ * gcc.target/arm/simd/vtrnu8_1.c: New file.
+
+2014-05-14 Ilya Tocar <ilya.tocar@intel.com>
+
+ * gcc.target/i386/clflushopt-1.c: New.
+ * gcc.target/i386/xsavec-1.c: Ditto.
+ * gcc.target/i386/xsavec64-1.c: Ditto.
+ * gcc.target/i386/xsaves-1.c: Ditto.
+ * gcc.target/i386/xsaves64-1.c: Ditto.
+ * gcc.target/i386/sse-12.c: Test new options.
+ * gcc.target/i386/sse-13.c: Ditto.
+ * gcc.target/i386/sse-14.c: Ditto.
+ * gcc.target/i386/sse-22.c: Ditto.
+ * gcc.target/i386/sse-23.c: Ditto.
+ * g++.dg/other/i386-2.C: Ditto.
+ * g++.dg/other/i386-3.C: Ditto.
+
+2014-05-14 Andrey Belevantsev <abel@ispras.ru>
+
+ PR rtl-optimization/60866
+ * gcc.dg/pr60866.c: New test.
+
+2014-05-14 Andrey Belevantsev <abel@ispras.ru>
+
+ PR rtl-optimization/60901
+ * gcc.target/i386/pr60901.c: New test.
+
+2014-05-14 Yury Gribov <y.gribov@samsung.com>
+
+ PR sanitizer/61100
+ * c-c++-common/asan/asan-interface-1.c: New test.
+ * lib/asan-dg.exp (asan_include_flags): New function.
+ (asan_init): Call asan_include_flags to obtain path
+ to sanitizer headers.
+
+2014-05-13 Peter Bergner <bergner@vnet.ibm.com>
+
+ * lib/target-support.exp (check_dfp_hw_available): New function.
+ (is-effective-target): Check $arg for dfp_hw.
+ (is-effective-target-keyword): Likewise.
+ * gcc.target/powerpc/pack03.c: (dg-require-effective-target):
+ Change target to dfp_hw.
+
+2014-05-13 Marek Polacek <polacek@redhat.com>
+
+ PR c/61162
+ * gcc.dg/pr61162.c: New test.
+
+2014-05-13 Marek Polacek <polacek@redhat.com>
+
+ * c-c++-common/pr50459.c: Move cdtor tests to a separate testcase.
+ * c-c++-common/pr50459-2.c: New test.
+
+2014-05-13 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/54310
+ * g++.dg/template/pr54310.C: New.
+
+2014-05-13 Nathan Sidwell <nathan@codesourcery.com>
+ Sandra Loosemore <sandra@codesourcery.com>
+
+ * gcc.target/mips/loongson-simd.c: Disable micromips too.
+
+2014-05-13 Catherine Moore <clm@cm00re.com>
+
+ * gcc.target/mips/near-far-1.c: Adjust expected output
+ to allow the JALS instruction.
+ * gcc.target/mips/near-far-2.c: Likewise.
+ * gcc.target/mips/near-far-4.c: Likewise.
+
+2014-05-13 Bin Cheng <bin.cheng@arm.com>
+
+ * gcc.dg/tree-ssa/ivopts-lower_base.c: New test.
+
+2014-05-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/61060
+ * gcc.dg/pr61060.c: New test.
+
+2014-05-12 DJ Delorie <dj@redhat.com>
+
+ * gcc.dg/sibcall-3.c: MSP430 doesn't have sibcall.
+ * gcc.dg/sibcall-4.c: Likewise.
+
+2014-05-12 Dimitris Papavasiliou <dpapavas@gmail.com>
+
+ * objc.dg/shadow-1.m: New test.
+ * objc.dg/shadow-2.m: New test.
+ * objc.dg/ivar-scope-1.m: New test.
+ * objc.dg/ivar-scope-2.m: New test.
+ * objc.dg/ivar-scope-3.m: New test.
+ * objc.dg/ivar-scope-4.m: New test.
+ * objc.dg/ivar-visibility-1.m: New test.
+ * objc.dg/ivar-visibility-2.m: New test.
+ * objc.dg/ivar-visibility-3.m: New test.
+ * objc.dg/ivar-visibility-4.m: New test.
+
+2014-05-12 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/60127
+ * gfortran.dg/gomp/omp_do_concurrent.f90: New.
+
+2014-05-12 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/60834
+ * gfortran.dg/associate_16.f90: New test.
+
+2014-05-12 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
+
+ PR target/60991
+ * gcc.target/avr/pr60991.c: New testcase.
+
+2014-05-12 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/60054
+ * g++.dg/cpp1y/pr60054.C: New.
+
+2014-05-12 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51199
+ * g++.dg/template/pr51199.C: New.
+
+2014-05-11 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * gcc.c-torture/execute/20101011-1.c [__MMIX__] (DO_TEST): Define as 0.
+
+2014-05-11 Jakub Jelinek <jakub@redhat.com>
+
+ * gfortran.dg/gomp/affinity-1.f90: New test.
+
+2014-05-11 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * gcc.dg/torture/pr61136.c: New test.
+
+2014-05-11 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/59705
+ * g++.dg/cpp0x/sfinae51.C: New.
+
+ PR c++/58353
+ * g++.dg/cpp0x/variadic157.C: New.
+
+2014-05-10 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/51244
+ * gcc.target/sh/pr51244-14.c: Relax criteria for passing the test.
+
+2014-05-10 Marek Polacek <polacek@redhat.com>
+
+ * gcc.dg/pedwarn-init.c: New test.
+ * gcc.dg/init-string-1.c: Adjust dg-error.
+
+2014-05-10 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * lib/target-supports.exp
+ (check_effective_target_logical_op_short_circuit): Add mmix-*-*
+ to the list.
+
+2014-05-09 Marek Polacek <polacek@redhat.com>
+
+ PR c/61096
+ * gcc.dg/pr61096-1.c: New test.
+ * gcc.dg/pr61096-2.c: New test.
+
+2014-05-09 Florian Weimer <fweimer@redhat.com>
+
+ * gcc.dg/fstack-protector-strong.c: Add coverage for return slots.
+ * g++.dg/fstack-protector-strong.C: Likewise.
+ * gcc.target/i386/ssp-strong-reg.c: New file.
+
+2014-05-09 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/61055
+ * gcc.target/avr/torture/pr61055.c: New test.
+
+2014-05-09 Marek Polacek <polacek@redhat.com>
+
+ PR c/50459
+ * c-c++-common/attributes-1.c: Move test line to a new test.
+ * c-c++-common/attributes-2.c: New test.
+ * c-c++-common/pr50459.c: New test.
+ * c-c++-common/pr59280.c: Add "undeclared" to dg-error.
+ * gcc.dg/nonnull-2.c: Likewise.
+ * gcc.dg/pr55570.c: Modify dg-error.
+ * gcc.dg/tm/wrap-2.c: Likewise.
+
+2014-05-08 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/61009
+ * g++.dg/tree-ssa/pr61009.C: New test.
+
+2014-05-08 Matthias Klose <doko@ubuntu.com>
+
+ PR driver/61106
+ * gcc-dg/unused-8a.c: New.
+ * gcc-dg/unused-8b.c: Likewise.
+
+2014-05-08 Marek Polacek <polacek@redhat.com>
+
+ PR c/61053
+ * gcc.dg/pr61053.c: New test.
+
+2014-05-08 Marek Polacek <polacek@redhat.com>
+
+ PR c/61077
+ * gcc.dg/pr61077.c: New test.
+
+2014-05-08 Tobias Burnus <burnus@net-b.de>
+
+ * gfortran.dg/coarray_collectives_1.f90: New.
+ * gfortran.dg/coarray_collectives_2.f90: New.
+ * gfortran.dg/coarray_collectives_3.f90: New.
+ * gfortran.dg/coarray_collectives_4.f90: New.
+ * gfortran.dg/coarray_collectives_5.f90: New.
+ * gfortran.dg/coarray_collectives_6.f90: New.
+ * gfortran.dg/coarray/collectives_1.f90: New.
+ * gfortran.dg/assumed_rank_5.f90: Update dg-error.
+ * gfortran.dg/assumed_type_4.f90: Update dg-error.
+ * gfortran.dg/bind_c_array_params.f03: Update dg-error.
+ * gfortran.dg/bind_c_usage_28.f90: Update dg-error.
+ * gfortran.dg/c_funloc_tests_5.f03: Update dg-error.
+ * gfortran.dg/c_funloc_tests_6.f90: Update dg-error.
+ * gfortran.dg/c_loc_tests_11.f03: Update dg-error.
+
+2014-05-08 Wei Mi <wmi@google.com>
+
+ PR target/58066
+ * gcc.target/i386/pr58066.c: New test.
+
+2014-05-08 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.target/i386/avx256-unaligned-load-2.c,
+ gcc.target/i386/pr49002-1.c, gcc.target/i386/pr53712.c,
+ gcc.target/i386/pr53907.c, gcc.target/i386/pr59539-1.c: Allow
+ packed-single instructions.
+
+2014-05-08 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/13981
+ * g++.dg/diagnostic/pr13981.C: New.
+
+2014-05-08 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/59100
+ * gcc.dg/tree-ssa/phi-opt-12.c: New file.
+ * gcc.dg/tree-ssa/phi-opt-13.c: Likewise.
+
+2014-05-08 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR tree-optimization/61095
+ * gcc.dg/torture/pr61095.c: New test.
+
+2014-05-04 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ PR middle-end/39246
+ * gcc.dg/uninit-13.c: Move warning on the actual source line where
+ the uninitialized complex is used.
+ * gcc.dg/uninit-17.c: New test to check partial initialization of
+ complex with branches.
+ * gcc.dg/uninit-17-O0.c: Likewise.
+
+2014-05-07 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/60884
+ * gcc.target/sh/pr53976-1.c (test_02): Remove inappropriate test case.
+ (test_03): Rename to test_02.
+
+2014-05-07 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/61083
+ * g++.dg/cpp0x/sfinae50.C: New.
+
2014-05-07 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/61080
@@ -516,7 +1515,7 @@
2014-04-28 Martin Jambor <mjambor@suse.cz>
- * gcc.dg/tree-ssa/sra-14.c: New test.
+ * gcc.dg/tree-ssa/sra-14.c: New test.
2014-04-28 Richard Biener <rguenther@suse.de>
@@ -565,10 +1564,10 @@
2014-04-25 Cary Coutant <ccoutant@google.com>
- PR debug/60929
- * g++.dg/debug/dwarf2/dwarf4-nested.C: New test case.
- * g++.dg/debug/dwarf2/dwarf4-typedef.C: Add
- -fdebug-types-section flag.
+ PR debug/60929
+ * g++.dg/debug/dwarf2/dwarf4-nested.C: New test case.
+ * g++.dg/debug/dwarf2/dwarf4-typedef.C: Add
+ -fdebug-types-section flag.
2014-04-25 Jiong Wang <jiong.wang@arm.com>
diff --git a/gcc/testsuite/c-c++-common/asan/asan-interface-1.c b/gcc/testsuite/c-c++-common/asan/asan-interface-1.c
new file mode 100644
index 00000000000..33ed1b0e845
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/asan-interface-1.c
@@ -0,0 +1,13 @@
+/* Check that interface headers work. */
+
+/* { dg-do run { target { *-*-linux* } } } */
+
+#include <sanitizer/asan_interface.h>
+
+int main() {
+ char tmp;
+ if (__asan_address_is_poisoned((volatile char *)&tmp + 1))
+ return 0;
+ return 1;
+}
+
diff --git a/gcc/testsuite/c-c++-common/asan/misalign-1.c b/gcc/testsuite/c-c++-common/asan/misalign-1.c
new file mode 100644
index 00000000000..0c5b6e0c754
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/misalign-1.c
@@ -0,0 +1,42 @@
+/* { dg-do run { target { ilp32 || lp64 } } } */
+/* { dg-options "-O2" } */
+/* { dg-shouldfail "asan" } */
+
+struct S { int i; } __attribute__ ((packed));
+
+__attribute__((noinline, noclone)) int
+foo (struct S *s)
+{
+ return s->i;
+}
+
+__attribute__((noinline, noclone)) int
+bar (int *s)
+{
+ return *s;
+}
+
+__attribute__((noinline, noclone)) struct S
+baz (struct S *s)
+{
+ return *s;
+}
+
+int
+main ()
+{
+ struct T { char a[3]; struct S b[3]; char c; } t;
+ int v = 5;
+ struct S *p = t.b;
+ asm volatile ("" : "+rm" (p));
+ p += 3;
+ if (bar (&v) != 5) __builtin_abort ();
+ volatile int w = foo (p);
+ return 0;
+}
+
+/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
+/* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in _*foo(\[^\n\r]*misalign-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*misalign-1.c:34|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/asan/misalign-2.c b/gcc/testsuite/c-c++-common/asan/misalign-2.c
new file mode 100644
index 00000000000..7fbe299cc54
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/misalign-2.c
@@ -0,0 +1,42 @@
+/* { dg-do run { target { ilp32 || lp64 } } } */
+/* { dg-options "-O2" } */
+/* { dg-shouldfail "asan" } */
+
+struct S { int i; } __attribute__ ((packed));
+
+__attribute__((noinline, noclone)) int
+foo (struct S *s)
+{
+ return s->i;
+}
+
+__attribute__((noinline, noclone)) int
+bar (int *s)
+{
+ return *s;
+}
+
+__attribute__((noinline, noclone)) struct S
+baz (struct S *s)
+{
+ return *s;
+}
+
+int
+main ()
+{
+ struct T { char a[3]; struct S b[3]; char c; } t;
+ int v = 5;
+ struct S *p = t.b;
+ asm volatile ("" : "+rm" (p));
+ p += 3;
+ if (bar (&v) != 5) __builtin_abort ();
+ volatile struct S w = baz (p);
+ return 0;
+}
+
+/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
+/* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in _*baz(\[^\n\r]*misalign-2.c:22|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*misalign-2.c:34|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/attributes-1.c b/gcc/testsuite/c-c++-common/attributes-1.c
index af4dd12275c..1657da10d5e 100644
--- a/gcc/testsuite/c-c++-common/attributes-1.c
+++ b/gcc/testsuite/c-c++-common/attributes-1.c
@@ -9,8 +9,6 @@ typedef char vec __attribute__((vector_size(bar))); /* { dg-warning "ignored" }
void f1(char*) __attribute__((nonnull(bar))); /* { dg-error "invalid operand" } */
void f2(char*) __attribute__((nonnull(1,bar))); /* { dg-error "invalid operand" } */
-void g() __attribute__((aligned(bar))); /* { dg-error "invalid value|not an integer" } */
-
void foo(void);
void* my_calloc(unsigned, unsigned) __attribute__((alloc_size(1,foo))); /* { dg-warning "outside range" } */
void* my_realloc(void*, unsigned) __attribute__((alloc_size(foo))); /* { dg-warning "outside range" } */
diff --git a/gcc/testsuite/c-c++-common/attributes-2.c b/gcc/testsuite/c-c++-common/attributes-2.c
new file mode 100644
index 00000000000..47b2c7b3ca8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/attributes-2.c
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+
+void g() __attribute__((aligned(bar))); /* { dg-error "undeclared here|not declared" } */
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr61191.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr61191.c
new file mode 100644
index 00000000000..deb83921833
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr61191.c
@@ -0,0 +1,10 @@
+/* PR c/61191 */
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+double f(double * A, double * B)
+{
+ return __sec_reduce_add((B[0:500])(; /* { dg-error "called object" "" { target c } } */
+/* { dg-error "expected expression before ';' token" "" { target c } 7 } */
+/* { dg-error "expected primary-expression before ';' token" "" { target c++ } 7 } */
+} /* { dg-error "expected" "" { target c } } */
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/invalid_sync.cc b/gcc/testsuite/c-c++-common/cilk-plus/CK/invalid_sync.cc
new file mode 100644
index 00000000000..cf1caf12b31
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/invalid_sync.cc
@@ -0,0 +1,9 @@
+/* PR c/60189 */
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+int main (void)
+{
+ _Cilk_sync return; /* { dg-error " expected ';' before 'return'" } */
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/simd4.c b/gcc/testsuite/c-c++-common/gomp/simd4.c
index 37901b6a07f..399003388ae 100644
--- a/gcc/testsuite/c-c++-common/gomp/simd4.c
+++ b/gcc/testsuite/c-c++-common/gomp/simd4.c
@@ -2,7 +2,7 @@
/* { dg-options "-fopenmp" } */
/* { dg-additional-options "-std=c99" { target c } } */
-struct S *p; /* { dg-error "forward declaration" "" { target c++ } } */
+struct S *p; /* { dg-message "forward declaration" "" { target c++ } } */
float f;
int j;
diff --git a/gcc/testsuite/c-c++-common/pr50459-2.c b/gcc/testsuite/c-c++-common/pr50459-2.c
new file mode 100644
index 00000000000..0e8fec3e2e5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr50459-2.c
@@ -0,0 +1,7 @@
+/* PR c/50459 */
+/* { dg-do compile { target init_priority } } */
+/* { dg-options "-Wall -Wextra" } */
+
+enum { A = 128, B = 1 };
+void fn3 (void) __attribute__((constructor (A)));
+void fn4 (void) __attribute__((destructor (A)));
diff --git a/gcc/testsuite/c-c++-common/pr50459.c b/gcc/testsuite/c-c++-common/pr50459.c
new file mode 100644
index 00000000000..8d75228bbcf
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr50459.c
@@ -0,0 +1,12 @@
+/* PR c/50459 */
+/* { dg-do compile } */
+/* { dg-options "-Wall -Wextra" } */
+
+enum { A = 128, B = 1 };
+void *fn1 (void) __attribute__((assume_aligned (A)));
+void *fn2 (void) __attribute__((assume_aligned (A, 4)));
+void *fn5 (int) __attribute__((alloc_size (B)));
+void *fn6 (int) __attribute__((alloc_align (B)));
+void fn7 (const char *, ...) __attribute__ ((sentinel (B)));
+int __attribute__((vector_size (A))) a;
+int __attribute__((aligned (A))) foo;
diff --git a/gcc/testsuite/c-c++-common/pr59280.c b/gcc/testsuite/c-c++-common/pr59280.c
index 779f0fb858f..581a1cf7b59 100644
--- a/gcc/testsuite/c-c++-common/pr59280.c
+++ b/gcc/testsuite/c-c++-common/pr59280.c
@@ -1,4 +1,4 @@
/* PR c/59280 */
/* { dg-do compile } */
-void bar (char *) __attribute__((constructor(foo))); /* { dg-error "constructor priorities must be integers|was not declared|constructor priorities are not supported" } */
+void bar (char *) __attribute__((constructor(foo))); /* { dg-error "constructor priorities must be integers|was not declared|undeclared|constructor priorities are not supported" } */
diff --git a/gcc/testsuite/c-c++-common/torture/pr61184.c b/gcc/testsuite/c-c++-common/torture/pr61184.c
new file mode 100644
index 00000000000..83117b9cfb0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/pr61184.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fno-strict-overflow" } */
+
+short a;
+
+void
+foo (void)
+{
+ for (a = 0; a >= 0; a++)
+ ;
+}
+
+int
+main ()
+{
+ foo ();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/tsan/mutexset1.c b/gcc/testsuite/c-c++-common/tsan/mutexset1.c
index 7c32a8524b4..d27f7c817cb 100644
--- a/gcc/testsuite/c-c++-common/tsan/mutexset1.c
+++ b/gcc/testsuite/c-c++-common/tsan/mutexset1.c
@@ -35,6 +35,6 @@ int main() {
/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */
/* { dg-output " Read of size 4 at 0x\[0-9a-f\]+ by thread T1 \\(mutexes: write M\[0-9\]\\):.*" } */
/* { dg-output " Previous write of size 4 at 0x\[0-9a-f\]+ by thread T2:.*" } */
-/* { dg-output " Mutex M\[0-9\] created at:.*" } */
+/* { dg-output " Mutex M\[0-9\] \\(0x.*\\) created at:.*" } */
/* { dg-output " #0 pthread_mutex_init.*" } */
/* { dg-output " #1 main (.*mutexset1.c|\\?{2}):\[0-9]+.*" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c
new file mode 100644
index 00000000000..f94588e4752
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c
@@ -0,0 +1,204 @@
+/* { dg-do run { target { lp64 || ilp32 } } } */
+/* { dg-options "-fsanitize=float-cast-overflow" } */
+/* { dg-additional-options "-msse2 -mfpmath=sse" { target { sse2_runtime && ia32 } } } */
+
+#include <limits.h>
+#include "float-cast.h"
+
+int
+main (void)
+{
+ const double inf = __builtin_inf ();
+ const double nan = __builtin_nan ("");
+ volatile double d;
+
+ volatile signed char sc;
+ d = SCHAR_MIN;
+ CHECK_BOUNDARY (sc, d);
+ d = 0.0;
+ CHECK_BOUNDARY (sc, d);
+ d = SCHAR_MAX;
+ CHECK_BOUNDARY (sc, d);
+ CHECK_NONNUMBERS (sc);
+
+ volatile unsigned char uc;
+ d = UCHAR_MAX;
+ CHECK_BOUNDARY (uc, d);
+ d = 0.0;
+ CHECK_BOUNDARY (uc, d);
+ CHECK_NONNUMBERS (uc);
+
+ volatile short int s;
+ d = SHRT_MIN;
+ CHECK_BOUNDARY (s, d);
+ d = 0.0;
+ CHECK_BOUNDARY (s, d);
+ d = SHRT_MAX;
+ CHECK_BOUNDARY (s, d);
+ CHECK_NONNUMBERS (s);
+
+ volatile unsigned short int us;
+ d = USHRT_MAX;
+ CHECK_BOUNDARY (us, d);
+ d = 0.0;
+ CHECK_BOUNDARY (us, d);
+ CHECK_NONNUMBERS (us);
+
+ volatile int i;
+ d = INT_MIN;
+ CHECK_BOUNDARY (i, d);
+ d = 0.0;
+ CHECK_BOUNDARY (i, d);
+ d = INT_MAX;
+ CHECK_BOUNDARY (i, d);
+ CHECK_NONNUMBERS (i);
+
+ volatile unsigned int u;
+ d = UINT_MAX;
+ CHECK_BOUNDARY (u, d);
+ d = 0.0;
+ CHECK_BOUNDARY (u, d);
+ CHECK_NONNUMBERS (u);
+
+ volatile long l;
+ /* 64-bit vs 32-bit longs matter causes too much of a headache. */
+ d = 0.0;
+ CHECK_BOUNDARY (l, d);
+ CHECK_NONNUMBERS (l);
+
+ volatile unsigned long ul;
+ d = 0.0;
+ CHECK_BOUNDARY (ul, d);
+ CHECK_NONNUMBERS (ul);
+
+ volatile long long ll;
+ d = LLONG_MIN;
+ CHECK_BOUNDARY (ll, d);
+ d = 0.0;
+ CHECK_BOUNDARY (ll, d);
+ d = LLONG_MAX;
+ CHECK_BOUNDARY (ll, d);
+ CHECK_NONNUMBERS (ll);
+
+ volatile unsigned long long ull;
+ d = ULLONG_MAX;
+ CHECK_BOUNDARY (ull, d);
+ d = 0.0;
+ CHECK_BOUNDARY (ull, d);
+ CHECK_NONNUMBERS (ull);
+
+ return 0;
+}
+
+/* { dg-output "value -133 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -129.5 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -129 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 128.5 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 132 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 256.5 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 260 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -32773 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -32769.5 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -32769 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 32768 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 32768.5 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 32772 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 65536 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 65536.5 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 65540 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c
new file mode 100644
index 00000000000..81ceb92afab
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c
@@ -0,0 +1,79 @@
+/* { dg-do run { target dfp } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover" } */
+/* { dg-additional-options "-DUSE_INT128" { target int128 } } */
+/* FIXME: When _DecimalXX <-> {signed, unsigned} __int128 conversions are
+ supported, -DBROKEN_DECIMAL_INT128 can be removed. */
+/* { dg-additional-options "-DUSE_DFP -DBROKEN_DECIMAL_INT128" } */
+
+#include "float-cast-overflow-8.c"
+
+/* _Decimal32 */
+/* { dg-output "value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* _Decimal64 */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* _Decimal128 */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-2.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-2.c
new file mode 100644
index 00000000000..6cbd3d4032f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-2.c
@@ -0,0 +1,73 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int128 } */
+/* { dg-options "-fsanitize=float-cast-overflow" } */
+
+#include "float-cast.h"
+
+int
+main (void)
+{
+ const double inf = __builtin_inf ();
+ const double nan = __builtin_nan ("");
+ volatile double d;
+
+ __int128 i;
+ d = INT128_MIN;
+ CHECK_BOUNDARY (i, d);
+ d = 0.0;
+ CHECK_BOUNDARY (i, d);
+ d = INT128_MAX;
+ CHECK_BOUNDARY (i, d);
+ CHECK_NONNUMBERS (i);
+
+ unsigned __int128 u;
+ d = UINT128_MAX;
+ CHECK_BOUNDARY (u, d);
+ d = 0.0;
+ CHECK_BOUNDARY (u, d);
+ CHECK_NONNUMBERS (u);
+
+ return 0;
+}
+
+/* { dg-output "runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value nan is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value -?nan is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value inf is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value -inf is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value -5 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value -1.5 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value -1 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value nan is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value -?nan is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value inf is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*runtime error: value -inf is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-3.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-3.c
new file mode 100644
index 00000000000..2200e669239
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-3.c
@@ -0,0 +1,40 @@
+/* { dg-do run { target { lp64 || ilp32 } } } */
+/* { dg-options "-fsanitize=float-cast-overflow" } */
+
+#include <limits.h>
+#include "float-cast.h"
+
+int
+main (void)
+{
+ volatile float f;
+
+ volatile signed char s;
+ f = SCHAR_MIN;
+ CHECK_BOUNDARY (s, f);
+ f = 0.0;
+ CHECK_BOUNDARY (s, f);
+ f = SCHAR_MAX;
+ CHECK_BOUNDARY (s, f);
+
+ volatile unsigned char u;
+ f = UCHAR_MAX;
+ CHECK_BOUNDARY (u, f);
+ f = 0.0;
+ CHECK_BOUNDARY (u, f);
+
+ return 0;
+}
+
+/* { dg-output "value -133* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -129.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -129 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 128.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 132 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 256.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 260 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-4.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-4.c
new file mode 100644
index 00000000000..5a1a65bfbe9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-4.c
@@ -0,0 +1,52 @@
+/* { dg-do run { target { lp64 } } } */
+/* { dg-options "-fsanitize=float-cast-overflow" } */
+
+#include <limits.h>
+#include "float-cast.h"
+
+int
+main (void)
+{
+ const long double inf = __builtin_infl ();
+ const long double nan = __builtin_nanl ("");
+ volatile long double ld;
+
+ volatile int i;
+ ld = INT_MIN;
+ CHECK_BOUNDARY (i, ld);
+ ld = 0.0l;
+ CHECK_BOUNDARY (i, ld);
+ ld = INT_MAX;
+ CHECK_BOUNDARY (i, ld);
+ CHECK_NONNUMBERS (i);
+
+ volatile unsigned int u;
+ ld = UINT_MAX;
+ CHECK_BOUNDARY (u, ld);
+ ld = 0.0l;
+ CHECK_BOUNDARY (u, ld);
+ CHECK_NONNUMBERS (u);
+
+ return 0;
+}
+
+/* { dg-output "value -2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -?nan is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-5.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-5.c
new file mode 100644
index 00000000000..44910eedba7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-5.c
@@ -0,0 +1,40 @@
+/* { dg-do run { target i?86-*-* x86_64-*-* ia64-*-* } } */
+/* { dg-options "-fsanitize=float-cast-overflow" } */
+
+#include <limits.h>
+#include "float-cast.h"
+
+int
+main (void)
+{
+ volatile __float128 f;
+
+ volatile signed char s;
+ f = SCHAR_MIN;
+ CHECK_BOUNDARY (s, f);
+ f = 0.0q;
+ CHECK_BOUNDARY (s, f);
+ f = SCHAR_MAX;
+ CHECK_BOUNDARY (s, f);
+
+ volatile unsigned char u;
+ f = UCHAR_MAX;
+ CHECK_BOUNDARY (u, f);
+ f = 0.0q;
+ CHECK_BOUNDARY (u, f);
+
+ return 0;
+}
+
+/* { dg-output "value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-6.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-6.c
new file mode 100644
index 00000000000..f51a2c838fd
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-6.c
@@ -0,0 +1,40 @@
+/* { dg-do run { target { { x86_64-*-* ia64-*-* } && { ! { ia32 } } } } } */
+/* { dg-options "-fsanitize=float-cast-overflow" } */
+
+#include <limits.h>
+#include "float-cast.h"
+
+int
+main (void)
+{
+ volatile __float80 f;
+
+ volatile signed char s;
+ f = SCHAR_MIN;
+ CHECK_BOUNDARY (s, f);
+ f = 0.0w;
+ CHECK_BOUNDARY (s, f);
+ f = SCHAR_MAX;
+ CHECK_BOUNDARY (s, f);
+
+ volatile unsigned char u;
+ f = UCHAR_MAX;
+ CHECK_BOUNDARY (u, f);
+ f = 0.0w;
+ CHECK_BOUNDARY (u, f);
+
+ return 0;
+}
+
+/* { dg-output "value -133 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -129.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -129 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 128.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 132 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 256.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 260 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c
new file mode 100644
index 00000000000..3223d5ec575
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c
@@ -0,0 +1,196 @@
+/* { dg-do run } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-options "-fsanitize=float-cast-overflow -fno-sanitize-recover" } */
+/* FIXME: When _DecimalXX <-> {signed, unsigned} __int128 conversions are
+ supported, -DBROKEN_DECIMAL_INT128 can be removed. */
+/* { dg-additional-options "-DUSE_DFP -DBROKEN_DECIMAL_INT128" { target dfp } } */
+
+#define USE_FLT_DBL_LDBL
+#ifdef __SIZEOF_INT128__
+#define USE_INT128
+#endif
+#ifdef __SIZEOF_FLOAT80__
+#define USE_FLOAT80
+#endif
+#ifdef __SIZEOF_FLOAT128__
+#define USE_FLOAT128
+#endif
+
+#include "float-cast-overflow-7.h"
+
+#define TEST(type1, type2) \
+ if (cvt_##type1##_##type2 (-0.5f) != 0) abort (); \
+ if (cvt_##type1##_##type2 (0.5f) != 0) abort (); \
+ if (cvt_##type1##_##type2 (-0.75f) != 0) abort (); \
+ if (cvt_##type1##_##type2 (0.75f) != 0) abort (); \
+ if (type1##_MIN) \
+ { \
+ /* For RADIX 2 type1##_MIN should be always */ \
+ /* exactly representable in type2. */ \
+ if (type2##_RADIX == 2 \
+ || type1##_MAX <= type2##_MAX) \
+ { \
+ if (cvt_##type1##_##type2 (type1##_MIN) \
+ != type1##_MIN) abort (); \
+ volatile type2 tem = ((type2) -0.75f) + type1##_MIN; \
+ volatile type2 tem2 = ((type2) -1.0f) + type1##_MIN; \
+ if (tem != tem2 \
+ && cvt_##type1##_##type2 ((type2) -0.75f \
+ + type1##_MIN) \
+ != type1##_MIN) abort (); \
+ } \
+ else \
+ { \
+ type2 min = type1##_MIN; \
+ /* tem could be below minimum here due to */ \
+ /* rounding. */ \
+ MAXT add = 1; \
+ while (add) \
+ { \
+ volatile type2 tem = type1##_MIN + (type1) add; \
+ if (tem != min) \
+ break; \
+ MAXT newadd = add * type2##_RADIX; \
+ if (newadd < add || newadd > type1##_MAX) \
+ add = 0; \
+ else \
+ add = newadd; \
+ } \
+ if (add) \
+ { \
+ MAXT newadd \
+ = (-(type1##_MIN + (type1) add)) % add; \
+ volatile type2 tem = type1##_MIN + (type1) newadd;\
+ volatile type2 tem2 = type1##_MIN + (type1) add; \
+ if (tem == tem2) \
+ add = newadd; \
+ else \
+ { \
+ newadd += add; \
+ if (newadd < add || newadd > type1##_MAX) \
+ add = 0; \
+ else \
+ { \
+ tem = type1##_MIN + (type1) newadd; \
+ if (tem == tem2) \
+ add = newadd; \
+ else \
+ add = 0; \
+ } \
+ } \
+ } \
+ if (add \
+ && cvt_##type1##_##type2 (type1##_MIN \
+ + (type1) add) \
+ != type1##_MIN + (type1) add) abort (); \
+ } \
+ } \
+ if (type1##_MAX <= type2##_MAX) \
+ { \
+ if (cvt_##type1##_##type2 (type1##_MAX) != type1##_MAX) \
+ abort (); \
+ volatile type2 tem = ((type2) 0.75f) + type1##_MAX; \
+ volatile type2 tem2 = ((type2) 1.0f) + type1##_MAX; \
+ if (tem < tem2 \
+ && cvt_##type1##_##type2 ((type2) 0.75f + type1##_MAX)\
+ != type1##_MAX) abort (); \
+ } \
+ else \
+ { \
+ type2 max = type1##_MAX; \
+ /* tem could be above maximum here due to rounding. */ \
+ MAXT sub = 1; \
+ while (sub) \
+ { \
+ volatile type2 tem = type1##_MAX - sub; \
+ if (tem != max) \
+ break; \
+ MAXT newsub = sub * type2##_RADIX; \
+ if (newsub < sub || newsub > type1##_MAX) \
+ sub = 0; \
+ else \
+ sub = newsub; \
+ } \
+ if (sub) \
+ { \
+ MAXT newsub = ((type1##_MAX - sub) % sub); \
+ volatile type2 tem = type1##_MAX - newsub; \
+ volatile type2 tem2 = type1##_MAX - sub; \
+ if (tem == tem2) \
+ sub = newsub; \
+ else \
+ { \
+ newsub += sub; \
+ if (newsub < sub || newsub > type1##_MAX) \
+ sub = 0; \
+ else \
+ { \
+ tem = type1##_MAX - newsub; \
+ if (tem == tem2) \
+ sub = newsub; \
+ else \
+ sub = 0; \
+ } \
+ } \
+ } \
+ if (sub \
+ && cvt_##type1##_##type2 (type1##_MAX - sub) \
+ != type1##_MAX - sub) abort (); \
+ }
+
+
+#ifdef si128_MAX
+# define TESTS128(type2) TEST (si128, type2) TEST (ui128, type2)
+#else
+# define TESTS128(type2)
+#endif
+
+#define TESTS(type2) \
+ TEST (sc, type2) TEST (c, type2) TEST (uc, type2) \
+ TEST (ss, type2) TEST (us, type2) \
+ TEST (si, type2) TEST (ui, type2) \
+ TEST (sl, type2) TEST (ul, type2) \
+ TEST (sll, type2) TEST (ull, type2) \
+ TESTS128 (type2)
+
+int
+main ()
+{
+#ifdef f_MAX
+ TESTS (f)
+#endif
+#ifdef d_MAX
+ TESTS (d)
+#endif
+#ifdef ld_MAX
+ TESTS (ld)
+#endif
+#ifdef f80_MAX
+ TESTS (f80)
+#endif
+#ifdef f128_MAX
+ TESTS (f128)
+#endif
+#ifdef BROKEN_DECIMAL_INT128
+# undef TESTS128
+# define TESTS128(type2)
+# undef TWO
+# undef M1U
+# undef MAXS
+# undef MAXT
+# define TWO 2ULL
+# define M1U -1ULL
+# define MAXS (__CHAR_BIT__ * __SIZEOF_LONG_LONG__)
+# define MAXT unsigned long long
+#endif
+#ifdef d32_MAX
+ TESTS (d32)
+#endif
+#ifdef d64_MAX
+ TESTS (d64)
+#endif
+#ifdef d128_MAX
+ TESTS (d128)
+#endif
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.h b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.h
new file mode 100644
index 00000000000..b839a6cb52f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.h
@@ -0,0 +1,156 @@
+#define CVTFN(type1, type2) \
+__attribute__((noinline)) type1 \
+cvt_##type1##_##type2 (type2 x) \
+{ \
+ return x; \
+}
+
+typedef signed char sc;
+#define sc_MIN (-__SCHAR_MAX__ - 1)
+#define sc_MAX __SCHAR_MAX__
+typedef unsigned char uc;
+#define uc_MIN 0
+#define uc_MAX (2U * __SCHAR_MAX__ + 1U)
+typedef char c;
+#define c_MIN ((((char) -1) > (char) 0) ? uc_MIN : sc_MIN)
+#define c_MAX ((((char) -1) > (char) 0) ? uc_MAX : sc_MAX)
+typedef signed short ss;
+#define ss_MIN (-__SHRT_MAX__ - 1)
+#define ss_MAX __SHRT_MAX__
+typedef unsigned short us;
+#define us_MIN 0
+#define us_MAX (2U * __SHRT_MAX__ + 1U)
+typedef signed int si;
+#define si_MIN (-__INT_MAX__ - 1)
+#define si_MAX __INT_MAX__
+typedef unsigned int ui;
+#define ui_MIN 0
+#define ui_MAX (2U * __INT_MAX__ + 1U)
+typedef signed long sl;
+#define sl_MIN (-__LONG_MAX__ - 1L)
+#define sl_MAX __LONG_MAX__
+typedef unsigned long ul;
+#define ul_MIN 0L
+#define ul_MAX (2UL * __LONG_MAX__ + 1UL)
+typedef signed long long sll;
+#define sll_MIN (-__LONG_LONG_MAX__ - 1LL)
+#define sll_MAX __LONG_LONG_MAX__
+typedef unsigned long long ull;
+#define ull_MIN 0LL
+#define ull_MAX (2ULL * __LONG_LONG_MAX__ + 1ULL)
+#ifdef USE_INT128
+typedef signed __int128 si128;
+# define si128_MAX \
+ ((signed __int128) ((((unsigned __int128) 1) \
+ << (__CHAR_BIT__ * __SIZEOF_INT128__ - 1)) - 1))
+# define si128_MIN (-si128_MAX - 1)
+typedef unsigned __int128 ui128;
+#define ui128_MIN ((unsigned __int128) 0)
+#define ui128_MAX (((unsigned __int128) 2) * si128_MAX + 1)
+#endif
+
+#ifdef si128_MAX
+# define CVTS128(type2) CVTFN (si128, type2) CVTFN (ui128, type2)
+#else
+# define CVTS128(type2)
+#endif
+
+#define CVTS(type2) \
+ CVTFN (sc, type2) CVTFN (c, type2) CVTFN (uc, type2) \
+ CVTFN (ss, type2) CVTFN (us, type2) \
+ CVTFN (si, type2) CVTFN (ui, type2) \
+ CVTFN (sl, type2) CVTFN (ul, type2) \
+ CVTFN (sll, type2) CVTFN (ull, type2) \
+ CVTS128 (type2)
+
+#ifdef __SIZEOF_INT128__
+# define TWO ((unsigned __int128) 2)
+# define M1U ((unsigned __int128) -1)
+# define MAXS (__CHAR_BIT__ * __SIZEOF_INT128__)
+# define MAXT unsigned __int128
+#else
+# define TWO 2ULL
+# define M1U -1ULL
+# define MAXS (__CHAR_BIT__ * __SIZEOF_LONG_LONG__)
+# define MAXT unsigned long long
+#endif
+
+#ifdef USE_FLT_DBL_LDBL
+typedef float f;
+#define f_RADIX 2
+#define f_MANT_DIG __FLT_MANT_DIG__
+#define f_MAX ((TWO << (f_MANT_DIG - 1)) - 1)
+typedef double d;
+#define d_RADIX 2
+#define d_MANT_DIG __DBL_MANT_DIG__
+#define d_MAX ((TWO << (d_MANT_DIG - 1)) - 1)
+typedef long double ld;
+#define ld_RADIX 2
+#define ld_MANT_DIG __LDBL_MANT_DIG__
+#define ld_MAX \
+ (ld_MANT_DIG > MAXS ? M1U : (TWO << (ld_MANT_DIG > MAXS \
+ ? 0 : ld_MANT_DIG - 1)) - 1)
+CVTS (f)
+CVTS (d)
+CVTS (ld)
+#endif
+#ifdef USE_FLOAT80
+typedef __float80 f80;
+# define f80_RADIX 2
+# define f80_MANT_DIG 64
+# define f80_MAX ((TWO << (f80_MANT_DIG - 1)) - 1)
+CVTS (f80)
+#endif
+#ifdef USE_FLOAT128
+typedef __float128 f128;
+# define f128_RADIX 2
+# define f128_MANT_DIG 113
+# define f128_MAX \
+ (f128_MANT_DIG > MAXS ? M1U : (TWO << (f128_MANT_DIG > MAXS \
+ ? 0 : f128_MANT_DIG - 1)) - 1)
+CVTS (f128)
+#endif
+#ifdef USE_DFP
+# ifdef __cplusplus
+typedef float _Decimal32 __attribute__((mode(SD)));
+typedef float _Decimal64 __attribute__((mode(DD)));
+typedef float _Decimal128 __attribute__((mode(TD)));
+# endif
+typedef _Decimal32 d32;
+# define d32_RADIX 10
+# define d32_MANT_DIG __DEC32_MANT_DIG__
+# if d32_MANT_DIG == 7
+# define d32_MAX 9999999ULL
+# endif
+typedef _Decimal64 d64;
+# define d64_RADIX 10
+# define d64_MANT_DIG __DEC64_MANT_DIG__
+# if d64_MANT_DIG == 16
+# define d64_MAX 9999999999999999ULL
+# endif
+typedef _Decimal128 d128;
+# define d128_RADIX 10
+# define d128_MANT_DIG __DEC128_MANT_DIG__
+# if d128_MANT_DIG == 34
+# ifdef __SIZEOF_INT128__
+/* #define d128_MAX 0x1ed09bead87c0378d8e63ffffffff */
+# define d128_MAX \
+ ((((unsigned __int128) 0x1ed09bead87c0) << 64) + 0x378d8e63ffffffffULL)
+# else
+# define d128_MAX M1U
+# endif
+# endif
+# ifdef BROKEN_DECIMAL_INT128
+# undef CVTS128
+# define CVTS128(type2)
+# endif
+CVTS (d32)
+CVTS (d64)
+CVTS (d128)
+#endif
+
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort ();
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c
new file mode 100644
index 00000000000..aa1c0da2768
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c
@@ -0,0 +1,205 @@
+/* { dg-do run } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover -DUSE_FLT_DBL_LDBL" } */
+/* { dg-additional-options "-DUSE_INT128" { target int128 } } */
+
+#include "float-cast-overflow-7.h"
+
+#define TEST(type1, type2) \
+ if (type1##_MIN) \
+ { \
+ type2 min = type1##_MIN; \
+ type2 add = -1.0; \
+ while (1) \
+ { \
+ volatile type2 tem = min + add; \
+ if (tem != min) \
+ { \
+ volatile type1 tem3 = cvt_##type1##_##type2 (tem);\
+ break; \
+ } \
+ add = add * type2##_RADIX; \
+ if (min == add) \
+ break; \
+ } \
+ } \
+ else \
+ { \
+ volatile type1 tem3 = cvt_##type1##_##type2 (-1.0f); \
+ } \
+ { \
+ type2 max = type1##_MAX; \
+ type2 add = 1.0; \
+ while (1) \
+ { \
+ volatile type2 tem = max + add; \
+ if (tem != max) \
+ { \
+ volatile type1 tem3 = cvt_##type1##_##type2 (tem); \
+ break; \
+ } \
+ add = add * type2##_RADIX; \
+ if (max == add) \
+ break; \
+ } \
+ }
+
+#ifdef si128_MAX
+# define TESTS128(type2) TEST (si128, type2) TEST (ui128, type2)
+#else
+# define TESTS128(type2)
+#endif
+
+#define TESTS(type2) \
+ TEST (sc, type2) TEST (c, type2) TEST (uc, type2) \
+ TEST (ss, type2) TEST (us, type2) \
+ TEST (si, type2) TEST (ui, type2) \
+ TEST (sl, type2) TEST (ul, type2) \
+ TEST (sll, type2) TEST (ull, type2) \
+ TESTS128 (type2)
+
+int
+main ()
+{
+#ifdef f_MAX
+ TESTS (f)
+#endif
+#ifdef d_MAX
+ TESTS (d)
+#endif
+#ifdef ld_MAX
+ TESTS (ld)
+#endif
+#ifdef f80_MAX
+ TESTS (f80)
+#endif
+#ifdef f128_MAX
+ TESTS (f128)
+#endif
+#ifdef BROKEN_DECIMAL_INT128
+# undef TESTS128
+# define TESTS128(type2)
+# undef TWO
+# undef M1U
+# undef MAXS
+# define TWO 2ULL
+# define M1U -1ULL
+# define MAXS (__CHAR_BIT__ * __SIZEOF_LONG_LONG__)
+#endif
+#ifdef d32_MAX
+ TESTS (d32)
+#endif
+#ifdef d64_MAX
+ TESTS (d64)
+#endif
+#ifdef d128_MAX
+ TESTS (d128)
+#endif
+ return 0;
+}
+
+/* float */
+/* { dg-output "value -129 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "value \[0-9.e+-]* is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value (-129|-1) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value (128|256) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value -32769 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value 32768 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 65536 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */
+/* No error for float and __int128 unsigned max value, as ui128_MAX is +Inf in float. */
+/* double */
+/* { dg-output "\[^\n\r]*value -129 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value (-129|-1) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value (128|256) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value -32769 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value 32768 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 65536 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */
+/* long double */
+/* { dg-output "\[^\n\r]*value -129 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value (-129|-1) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value (128|256) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value -32769 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value 32768 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 65536 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c
new file mode 100644
index 00000000000..cadef311121
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c
@@ -0,0 +1,61 @@
+/* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover -DUSE_FLOAT80 -DUSE_FLOAT128" } */
+/* { dg-additional-options "-DUSE_INT128" { target int128 } } */
+
+#include "float-cast-overflow-8.c"
+
+/* __float80 */
+/* { dg-output "value -129 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value (-129|-1) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value (128|256) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -32769 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 32768 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 65536 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */
+/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */
+/* __float128 */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */
+/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast.h b/gcc/testsuite/c-c++-common/ubsan/float-cast.h
new file mode 100644
index 00000000000..e76171a8f9d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/float-cast.h
@@ -0,0 +1,39 @@
+/* Various macros for -fsanitize=float-cast-overflow testing. */
+
+/* E.g. on CentOS 5 these aren't defined in limits.h. */
+#ifndef LLONG_MAX
+# define LLONG_MAX __LONG_LONG_MAX__
+#endif
+#ifndef LLONG_MIN
+# define LLONG_MIN (-__LONG_LONG_MAX__ - 1LL)
+#endif
+#ifndef ULLONG_MAX
+# define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1ULL)
+#endif
+
+#define INT128_MAX (__int128) (((unsigned __int128) 1 << ((__SIZEOF_INT128__ * __CHAR_BIT__) - 1)) - 1)
+#define INT128_MIN (-INT128_MAX - 1)
+#define UINT128_MAX ((2 * (unsigned __int128) INT128_MAX) + 1)
+
+#define CHECK_BOUNDARY(VAR, VAL) \
+ (VAR) = (VAL) - 5.0; \
+ (VAR) = (VAL) - 1.5; \
+ (VAR) = (VAL) - 1.0; \
+ (VAR) = (VAL) - 0.75; \
+ (VAR) = (VAL) - 0.5; \
+ (VAR) = (VAL) - 0.0000001; \
+ (VAR) = (VAL) - 0.0; \
+ (VAR) = (VAL); \
+ (VAR) = (VAL) + 0.0; \
+ (VAR) = (VAL) + 0.0000001; \
+ (VAR) = (VAL) + 0.5; \
+ (VAR) = (VAL) + 0.75; \
+ (VAR) = (VAL) + 1.0; \
+ (VAR) = (VAL) + 1.5; \
+ (VAR) = (VAL) + 5.0;
+
+#define CHECK_NONNUMBERS(VAR) \
+ (VAR) = nan; \
+ (VAR) = -nan; \
+ (VAR) = inf; \
+ (VAR) = -inf;
diff --git a/gcc/testsuite/g++.dg/asan/asan_mem_test.cc b/gcc/testsuite/g++.dg/asan/asan_mem_test.cc
index 5656aab0bac..5fc4af7e9e3 100644
--- a/gcc/testsuite/g++.dg/asan/asan_mem_test.cc
+++ b/gcc/testsuite/g++.dg/asan/asan_mem_test.cc
@@ -74,17 +74,17 @@ TEST(AddressSanitizer, MemSetOOBTest) {
// Strictly speaking we are not guaranteed to find such two pointers,
// but given the structure of asan's allocator we will.
static bool AllocateTwoAdjacentArrays(char **x1, char **x2, size_t size) {
- vector<char *> v;
+ vector<uintptr_t> v;
bool res = false;
for (size_t i = 0; i < 1000U && !res; i++) {
- v.push_back(new char[size]);
+ v.push_back(reinterpret_cast<uintptr_t>(new char[size]));
if (i == 0) continue;
sort(v.begin(), v.end());
for (size_t j = 1; j < v.size(); j++) {
assert(v[j] > v[j-1]);
if ((size_t)(v[j] - v[j-1]) < size * 2) {
- *x2 = v[j];
- *x1 = v[j-1];
+ *x2 = reinterpret_cast<char*>(v[j]);
+ *x1 = reinterpret_cast<char*>(v[j-1]);
res = true;
break;
}
@@ -92,9 +92,10 @@ static bool AllocateTwoAdjacentArrays(char **x1, char **x2, size_t size) {
}
for (size_t i = 0; i < v.size(); i++) {
- if (res && v[i] == *x1) continue;
- if (res && v[i] == *x2) continue;
- delete [] v[i];
+ char *p = reinterpret_cast<char *>(v[i]);
+ if (res && p == *x1) continue;
+ if (res && p == *x2) continue;
+ delete [] p;
}
return res;
}
@@ -223,6 +224,13 @@ TEST(AddressSanitizer, MemCmpOOBTest) {
s1[size - 1] = '\0';
s2[size - 1] = '\0';
EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0));
+
+ // Even if the buffers differ in the first byte, we still assume that
+ // memcmp may access the whole buffer and thus reporting the overflow here:
+ s1[0] = 1;
+ s2[0] = 123;
+ EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0));
+
free(s1);
free(s2);
}
diff --git a/gcc/testsuite/g++.dg/asan/asan_oob_test.cc b/gcc/testsuite/g++.dg/asan/asan_oob_test.cc
index 61d50553703..2361dc286d7 100644
--- a/gcc/testsuite/g++.dg/asan/asan_oob_test.cc
+++ b/gcc/testsuite/g++.dg/asan/asan_oob_test.cc
@@ -97,7 +97,6 @@ TEST(AddressSanitizer, OOBRightTest) {
}
}
-#if ASAN_ALLOCATOR_VERSION == 2 // Broken with the asan_allocator1
TEST(AddressSanitizer, LargeOOBRightTest) {
size_t large_power_of_two = 1 << 19;
for (size_t i = 16; i <= 256; i *= 2) {
@@ -107,7 +106,6 @@ TEST(AddressSanitizer, LargeOOBRightTest) {
delete [] p;
}
}
-#endif // ASAN_ALLOCATOR_VERSION == 2
TEST(AddressSanitizer, DISABLED_DemoOOBLeftLow) {
oob_test<U1>(10, -1);
diff --git a/gcc/testsuite/g++.dg/asan/asan_str_test.cc b/gcc/testsuite/g++.dg/asan/asan_str_test.cc
index 1b9805e8eb1..207de422316 100644
--- a/gcc/testsuite/g++.dg/asan/asan_str_test.cc
+++ b/gcc/testsuite/g++.dg/asan/asan_str_test.cc
@@ -10,6 +10,10 @@
//===----------------------------------------------------------------------===//
#include "asan_test_utils.h"
+#if defined(__APPLE__)
+#include <AvailabilityMacros.h> // For MAC_OS_X_VERSION_*
+#endif
+
// Used for string functions tests
static char global_string[] = "global";
static size_t global_string_length = 6;
@@ -59,7 +63,19 @@ TEST(AddressSanitizer, StrLenOOBTest) {
free(heap_string);
}
-#ifndef __APPLE__
+TEST(AddressSanitizer, WcsLenTest) {
+ EXPECT_EQ(0U, wcslen(Ident(L"")));
+ size_t hello_len = 13;
+ size_t hello_size = (hello_len + 1) * sizeof(wchar_t);
+ EXPECT_EQ(hello_len, wcslen(Ident(L"Hello, World!")));
+ wchar_t *heap_string = Ident((wchar_t*)malloc(hello_size));
+ memcpy(heap_string, L"Hello, World!", hello_size);
+ EXPECT_EQ(hello_len, Ident(wcslen(heap_string)));
+ EXPECT_DEATH(Ident(wcslen(heap_string + 14)), RightOOBReadMessage(0));
+ free(heap_string);
+}
+
+#if SANITIZER_TEST_HAS_STRNLEN
TEST(AddressSanitizer, StrNLenOOBTest) {
size_t size = Ident(123);
char *str = MallocAndMemsetString(size);
@@ -77,7 +93,7 @@ TEST(AddressSanitizer, StrNLenOOBTest) {
EXPECT_DEATH(Ident(strnlen(str, size + 1)), RightOOBReadMessage(0));
free(str);
}
-#endif
+#endif // SANITIZER_TEST_HAS_STRNLEN
TEST(AddressSanitizer, StrDupOOBTest) {
size_t size = Ident(42);
@@ -168,7 +184,7 @@ TEST(AddressSanitizer, StrNCpyOOBTest) {
typedef char*(*PointerToStrChr1)(const char*, int);
typedef char*(*PointerToStrChr2)(char*, int);
-USED static void RunStrChrTest(PointerToStrChr1 StrChr) {
+UNUSED static void RunStrChrTest(PointerToStrChr1 StrChr) {
size_t size = Ident(100);
char *str = MallocAndMemsetString(size);
str[10] = 'q';
@@ -184,7 +200,7 @@ USED static void RunStrChrTest(PointerToStrChr1 StrChr) {
EXPECT_DEATH(Ident(StrChr(str, 'a')), RightOOBReadMessage(0));
free(str);
}
-USED static void RunStrChrTest(PointerToStrChr2 StrChr) {
+UNUSED static void RunStrChrTest(PointerToStrChr2 StrChr) {
size_t size = Ident(100);
char *str = MallocAndMemsetString(size);
str[10] = 'q';
@@ -203,7 +219,9 @@ USED static void RunStrChrTest(PointerToStrChr2 StrChr) {
TEST(AddressSanitizer, StrChrAndIndexOOBTest) {
RunStrChrTest(&strchr);
+#if !defined(_WIN32) // no index() on Windows.
RunStrChrTest(&index);
+#endif
}
TEST(AddressSanitizer, StrCmpAndFriendsLogicTest) {
@@ -226,6 +244,7 @@ TEST(AddressSanitizer, StrCmpAndFriendsLogicTest) {
EXPECT_LT(0, strncmp("baa", "aaa", 1));
EXPECT_LT(0, strncmp("zyx", "", 2));
+#if !defined(_WIN32) // no str[n]casecmp on Windows.
// strcasecmp
EXPECT_EQ(0, strcasecmp("", ""));
EXPECT_EQ(0, strcasecmp("zzz", "zzz"));
@@ -245,6 +264,7 @@ TEST(AddressSanitizer, StrCmpAndFriendsLogicTest) {
EXPECT_LT(0, strncasecmp("xyz", "xyy", 10));
EXPECT_LT(0, strncasecmp("Baa", "aaa", 1));
EXPECT_LT(0, strncasecmp("zyx", "", 2));
+#endif
// memcmp
EXPECT_EQ(0, memcmp("a", "b", 0));
@@ -287,9 +307,11 @@ TEST(AddressSanitizer, StrCmpOOBTest) {
RunStrCmpTest(&strcmp);
}
+#if !defined(_WIN32) // no str[n]casecmp on Windows.
TEST(AddressSanitizer, StrCaseCmpOOBTest) {
RunStrCmpTest(&strcasecmp);
}
+#endif
typedef int(*PointerToStrNCmp)(const char*, const char*, size_t);
void RunStrNCmpTest(PointerToStrNCmp StrNCmp) {
@@ -322,9 +344,12 @@ TEST(AddressSanitizer, StrNCmpOOBTest) {
RunStrNCmpTest(&strncmp);
}
+#if !defined(_WIN32) // no str[n]casecmp on Windows.
TEST(AddressSanitizer, StrNCaseCmpOOBTest) {
RunStrNCmpTest(&strncasecmp);
}
+#endif
+
TEST(AddressSanitizer, StrCatOOBTest) {
// strcat() reads strlen(to) bytes from |to| before concatenating.
size_t to_size = Ident(100);
@@ -506,11 +531,13 @@ void RunAtoiOOBTest(PointerToCallAtoi Atoi) {
free(array);
}
+#if !defined(_WIN32) // FIXME: Fix and enable on Windows.
TEST(AddressSanitizer, AtoiAndFriendsOOBTest) {
RunAtoiOOBTest(&CallAtoi);
RunAtoiOOBTest(&CallAtol);
RunAtoiOOBTest(&CallAtoll);
}
+#endif
void CallStrtol(const char *nptr, char **endptr, int base) {
Ident(strtol(nptr, endptr, base));
@@ -560,11 +587,13 @@ void RunStrtolOOBTest(PointerToCallStrtol Strtol) {
free(array);
}
+#if !defined(_WIN32) // FIXME: Fix and enable on Windows.
TEST(AddressSanitizer, StrtollOOBTest) {
RunStrtolOOBTest(&CallStrtoll);
}
TEST(AddressSanitizer, StrtolOOBTest) {
RunStrtolOOBTest(&CallStrtol);
}
+#endif
diff --git a/gcc/testsuite/g++.dg/asan/asan_test.C b/gcc/testsuite/g++.dg/asan/asan_test.C
index e11531e07de..3cee7150f73 100644
--- a/gcc/testsuite/g++.dg/asan/asan_test.C
+++ b/gcc/testsuite/g++.dg/asan/asan_test.C
@@ -2,7 +2,7 @@
// { dg-skip-if "" { *-*-* } { "*" } { "-O2" } }
// { dg-skip-if "" { *-*-* } { "-flto" } { "" } }
// { dg-additional-sources "asan_globals_test-wrapper.cc" }
-// { dg-options "-fsanitize=address -fno-builtin -Wall -Wno-format -Werror -g -DASAN_UAR=0 -DASAN_HAS_EXCEPTIONS=1 -DASAN_HAS_BLACKLIST=0 -DASAN_USE_DEJAGNU_GTEST=1 -lasan -lpthread -ldl" }
+// { dg-options "-std=c++11 -fsanitize=address -fno-builtin -Wall -Wno-format -Werror -g -DASAN_UAR=0 -DASAN_HAS_EXCEPTIONS=1 -DASAN_HAS_BLACKLIST=0 -DSANITIZER_USE_DEJAGNU_GTEST=1 -lasan -lpthread -ldl" }
// { dg-additional-options "-DASAN_NEEDS_SEGV=1" { target { ! arm*-*-* } } }
// { dg-additional-options "-DASAN_LOW_MEMORY=1 -DASAN_NEEDS_SEGV=0" { target arm*-*-* } }
// { dg-additional-options "-DASAN_AVOID_EXPENSIVE_TESTS=1" { target { ! run_expensive_tests } } }
diff --git a/gcc/testsuite/g++.dg/asan/asan_test.cc b/gcc/testsuite/g++.dg/asan/asan_test.cc
index 2df8c62cbb1..5f2e2c244dd 100644
--- a/gcc/testsuite/g++.dg/asan/asan_test.cc
+++ b/gcc/testsuite/g++.dg/asan/asan_test.cc
@@ -23,27 +23,10 @@ NOINLINE void *malloc_bbb(size_t size) {
NOINLINE void *malloc_aaa(size_t size) {
void *res = malloc_bbb(size); break_optimization(0); return res;}
-#ifndef __APPLE__
-NOINLINE void *memalign_fff(size_t alignment, size_t size) {
- void *res = memalign/**/(alignment, size); break_optimization(0); return res;}
-NOINLINE void *memalign_eee(size_t alignment, size_t size) {
- void *res = memalign_fff(alignment, size); break_optimization(0); return res;}
-NOINLINE void *memalign_ddd(size_t alignment, size_t size) {
- void *res = memalign_eee(alignment, size); break_optimization(0); return res;}
-NOINLINE void *memalign_ccc(size_t alignment, size_t size) {
- void *res = memalign_ddd(alignment, size); break_optimization(0); return res;}
-NOINLINE void *memalign_bbb(size_t alignment, size_t size) {
- void *res = memalign_ccc(alignment, size); break_optimization(0); return res;}
-NOINLINE void *memalign_aaa(size_t alignment, size_t size) {
- void *res = memalign_bbb(alignment, size); break_optimization(0); return res;}
-#endif // __APPLE__
-
-
NOINLINE void free_ccc(void *p) { free(p); break_optimization(0);}
NOINLINE void free_bbb(void *p) { free_ccc(p); break_optimization(0);}
NOINLINE void free_aaa(void *p) { free_bbb(p); break_optimization(0);}
-
template<typename T>
NOINLINE void uaf_test(int size, int off) {
char *p = (char *)malloc_aaa(size);
@@ -88,19 +71,19 @@ TEST(AddressSanitizer, VariousMallocsTest) {
*c = 0;
delete c;
-#if !defined(__APPLE__) && !defined(ANDROID) && !defined(__ANDROID__)
+#if SANITIZER_TEST_HAS_POSIX_MEMALIGN
int *pm;
int pm_res = posix_memalign((void**)&pm, kPageSize, kPageSize);
EXPECT_EQ(0, pm_res);
free(pm);
-#endif
+#endif // SANITIZER_TEST_HAS_POSIX_MEMALIGN
-#if !defined(__APPLE__)
+#if SANITIZER_TEST_HAS_MEMALIGN
int *ma = (int*)memalign(kPageSize, kPageSize);
EXPECT_EQ(0U, (uintptr_t)ma % kPageSize);
ma[123] = 0;
free(ma);
-#endif // __APPLE__
+#endif // SANITIZER_TEST_HAS_MEMALIGN
}
TEST(AddressSanitizer, CallocTest) {
@@ -109,13 +92,37 @@ TEST(AddressSanitizer, CallocTest) {
free(a);
}
+TEST(AddressSanitizer, CallocReturnsZeroMem) {
+ size_t sizes[] = {16, 1000, 10000, 100000, 2100000};
+ for (size_t s = 0; s < sizeof(sizes)/sizeof(sizes[0]); s++) {
+ size_t size = sizes[s];
+ for (size_t iter = 0; iter < 5; iter++) {
+ char *x = Ident((char*)calloc(1, size));
+ EXPECT_EQ(x[0], 0);
+ EXPECT_EQ(x[size - 1], 0);
+ EXPECT_EQ(x[size / 2], 0);
+ EXPECT_EQ(x[size / 3], 0);
+ EXPECT_EQ(x[size / 4], 0);
+ memset(x, 0x42, size);
+ free(Ident(x));
+#if !defined(_WIN32)
+ // FIXME: OOM on Windows. We should just make this a lit test
+ // with quarantine size set to 1.
+ free(Ident(malloc(Ident(1 << 27)))); // Try to drain the quarantine.
+#endif
+ }
+ }
+}
+
+#if !defined(_WIN32) // No valloc on Windows.
TEST(AddressSanitizer, VallocTest) {
void *a = valloc(100);
EXPECT_EQ(0U, (uintptr_t)a % kPageSize);
free(a);
}
+#endif
-#ifndef __APPLE__
+#if SANITIZER_TEST_HAS_PVALLOC
TEST(AddressSanitizer, PvallocTest) {
char *a = (char*)pvalloc(kPageSize + 100);
EXPECT_EQ(0U, (uintptr_t)a % kPageSize);
@@ -127,8 +134,10 @@ TEST(AddressSanitizer, PvallocTest) {
a[101] = 1; // we should not report an error here.
free(a);
}
-#endif // __APPLE__
+#endif // SANITIZER_TEST_HAS_PVALLOC
+#if !defined(_WIN32)
+// FIXME: Use an equivalent of pthread_setspecific on Windows.
void *TSDWorker(void *test_key) {
if (test_key) {
pthread_setspecific(*(pthread_key_t*)test_key, (void*)0xfeedface);
@@ -158,6 +167,7 @@ TEST(AddressSanitizer, DISABLED_TSDTest) {
PTHREAD_JOIN(th, NULL);
pthread_key_delete(test_key);
}
+#endif
TEST(AddressSanitizer, UAF_char) {
const char *uaf_string = "AddressSanitizer:.*heap-use-after-free";
@@ -168,6 +178,36 @@ TEST(AddressSanitizer, UAF_char) {
EXPECT_DEATH(uaf_test<U1>(kLargeMalloc, kLargeMalloc / 2), uaf_string);
}
+TEST(AddressSanitizer, UAF_long_double) {
+ if (sizeof(long double) == sizeof(double)) return;
+ long double *p = Ident(new long double[10]);
+ EXPECT_DEATH(Ident(p)[12] = 0, "WRITE of size 1[026]");
+ EXPECT_DEATH(Ident(p)[0] = Ident(p)[12], "READ of size 1[026]");
+ delete [] Ident(p);
+}
+
+#if !defined(_WIN32)
+struct Packed5 {
+ int x;
+ char c;
+} __attribute__((packed));
+#else
+# pragma pack(push, 1)
+struct Packed5 {
+ int x;
+ char c;
+};
+# pragma pack(pop)
+#endif
+
+TEST(AddressSanitizer, UAF_Packed5) {
+ static_assert(sizeof(Packed5) == 5, "Please check the keywords used");
+ Packed5 *p = Ident(new Packed5[2]);
+ EXPECT_DEATH(p[0] = p[3], "READ of size 5");
+ EXPECT_DEATH(p[3] = p[0], "WRITE of size 5");
+ delete [] Ident(p);
+}
+
#if ASAN_HAS_BLACKLIST
TEST(AddressSanitizer, IgnoreTest) {
int *x = Ident(new int);
@@ -244,41 +284,6 @@ TEST(AddressSanitizer, SignalTest) {
} // namespace
#endif
-static void MallocStress(size_t n) {
- uint32_t seed = my_rand();
- for (size_t iter = 0; iter < 10; iter++) {
- vector<void *> vec;
- for (size_t i = 0; i < n; i++) {
- if ((i % 3) == 0) {
- if (vec.empty()) continue;
- size_t idx = my_rand_r(&seed) % vec.size();
- void *ptr = vec[idx];
- vec[idx] = vec.back();
- vec.pop_back();
- free_aaa(ptr);
- } else {
- size_t size = my_rand_r(&seed) % 1000 + 1;
-#ifndef __APPLE__
- size_t alignment = 1 << (my_rand_r(&seed) % 7 + 3);
- char *ptr = (char*)memalign_aaa(alignment, size);
-#else
- char *ptr = (char*) malloc_aaa(size);
-#endif
- vec.push_back(ptr);
- ptr[0] = 0;
- ptr[size-1] = 0;
- ptr[size/2] = 0;
- }
- }
- for (size_t i = 0; i < vec.size(); i++)
- free_aaa(vec[i]);
- }
-}
-
-TEST(AddressSanitizer, MallocStressTest) {
- MallocStress((ASAN_LOW_MEMORY) ? 20000 : 200000);
-}
-
static void TestLargeMalloc(size_t size) {
char buff[1024];
sprintf(buff, "is located 1 bytes to the left of %lu-byte", (long)size);
@@ -286,28 +291,21 @@ static void TestLargeMalloc(size_t size) {
}
TEST(AddressSanitizer, LargeMallocTest) {
- for (int i = 113; i < (1 << 28); i = i * 2 + 13) {
+ const int max_size = (SANITIZER_WORDSIZE == 32) ? 1 << 26 : 1 << 28;
+ for (int i = 113; i < max_size; i = i * 2 + 13) {
TestLargeMalloc(i);
}
}
-#if ASAN_LOW_MEMORY != 1
TEST(AddressSanitizer, HugeMallocTest) {
-#ifdef __APPLE__
- // It was empirically found out that 1215 megabytes is the maximum amount of
- // memory available to the process under AddressSanitizer on 32-bit Mac 10.6.
- // 32-bit Mac 10.7 gives even less (< 1G).
- // (the libSystem malloc() allows allocating up to 2300 megabytes without
- // ASan).
- size_t n_megs = SANITIZER_WORDSIZE == 32 ? 500 : 4100;
-#else
- size_t n_megs = SANITIZER_WORDSIZE == 32 ? 2600 : 4100;
-#endif
- TestLargeMalloc(n_megs << 20);
+ if (SANITIZER_WORDSIZE != 64 || ASAN_AVOID_EXPENSIVE_TESTS) return;
+ size_t n_megs = 4100;
+ EXPECT_DEATH(Ident((char*)malloc(n_megs << 20))[-1] = 0,
+ "is located 1 bytes to the left|"
+ "AddressSanitizer failed to allocate");
}
-#endif
-#ifndef __APPLE__
+#if SANITIZER_TEST_HAS_MEMALIGN
void MemalignRun(size_t align, size_t size, int idx) {
char *p = (char *)memalign(align, size);
Ident(p)[idx] = 0;
@@ -323,20 +321,7 @@ TEST(AddressSanitizer, memalign) {
"is located 1 bytes to the right");
}
}
-#endif
-
-TEST(AddressSanitizer, ThreadedMallocStressTest) {
- const int kNumThreads = 4;
- const int kNumIterations = (ASAN_LOW_MEMORY) ? 10000 : 100000;
- pthread_t t[kNumThreads];
- for (int i = 0; i < kNumThreads; i++) {
- PTHREAD_CREATE(&t[i], 0, (void* (*)(void *x))MallocStress,
- (void*)kNumIterations);
- }
- for (int i = 0; i < kNumThreads; i++) {
- PTHREAD_JOIN(t[i], 0);
- }
-}
+#endif // SANITIZER_TEST_HAS_MEMALIGN
void *ManyThreadsWorker(void *a) {
for (int iter = 0; iter < 100; iter++) {
@@ -377,17 +362,30 @@ TEST(AddressSanitizer, ReallocTest) {
free(ptr2);
}
+TEST(AddressSanitizer, ReallocFreedPointerTest) {
+ void *ptr = Ident(malloc(42));
+ ASSERT_TRUE(NULL != ptr);
+ free(ptr);
+ EXPECT_DEATH(ptr = realloc(ptr, 77), "attempting double-free");
+}
+
+TEST(AddressSanitizer, ReallocInvalidPointerTest) {
+ void *ptr = Ident(malloc(42));
+ EXPECT_DEATH(ptr = realloc((int*)ptr + 1, 77), "attempting free.*not malloc");
+ free(ptr);
+}
+
TEST(AddressSanitizer, ZeroSizeMallocTest) {
// Test that malloc(0) and similar functions don't return NULL.
void *ptr = Ident(malloc(0));
EXPECT_TRUE(NULL != ptr);
free(ptr);
-#if !defined(__APPLE__) && !defined(ANDROID) && !defined(__ANDROID__)
+#if SANITIZER_TEST_HAS_POSIX_MEMALIGN
int pm_res = posix_memalign(&ptr, 1<<20, 0);
EXPECT_EQ(0, pm_res);
EXPECT_TRUE(NULL != ptr);
free(ptr);
-#endif
+#endif // SANITIZER_TEST_HAS_POSIX_MEMALIGN
int *int_ptr = new int[0];
int *int_ptr2 = new int[0];
EXPECT_TRUE(NULL != int_ptr);
@@ -397,7 +395,7 @@ TEST(AddressSanitizer, ZeroSizeMallocTest) {
delete[] int_ptr2;
}
-#ifndef __APPLE__
+#if SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE
static const char *kMallocUsableSizeErrorMsg =
"AddressSanitizer: attempting to call malloc_usable_size()";
@@ -413,8 +411,9 @@ TEST(AddressSanitizer, MallocUsableSizeTest) {
kMallocUsableSizeErrorMsg);
free(array);
EXPECT_DEATH(malloc_usable_size(array), kMallocUsableSizeErrorMsg);
+ delete int_ptr;
}
-#endif
+#endif // SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE
void WrongFree() {
int *x = (int*)malloc(100 * sizeof(int));
@@ -423,10 +422,14 @@ void WrongFree() {
free(x + 1);
}
+#if !defined(_WIN32) // FIXME: This should be a lit test.
TEST(AddressSanitizer, WrongFreeTest) {
- EXPECT_DEATH(WrongFree(),
- "ERROR: AddressSanitizer: attempting free.*not malloc");
+ EXPECT_DEATH(WrongFree(), ASAN_PCRE_DOTALL
+ "ERROR: AddressSanitizer: attempting free.*not malloc"
+ ".*is located 4 bytes inside of 400-byte region"
+ ".*allocated by thread");
}
+#endif
void DoubleFree() {
int *x = (int*)malloc(100 * sizeof(int));
@@ -437,6 +440,7 @@ void DoubleFree() {
abort();
}
+#if !defined(_WIN32) // FIXME: This should be a lit test.
TEST(AddressSanitizer, DoubleFreeTest) {
EXPECT_DEATH(DoubleFree(), ASAN_PCRE_DOTALL
"ERROR: AddressSanitizer: attempting double-free"
@@ -444,20 +448,22 @@ TEST(AddressSanitizer, DoubleFreeTest) {
".*freed by thread T0 here"
".*previously allocated by thread T0 here");
}
+#endif
template<int kSize>
NOINLINE void SizedStackTest() {
char a[kSize];
char *A = Ident((char*)&a);
+ const char *expected_death = "AddressSanitizer: stack-buffer-";
for (size_t i = 0; i < kSize; i++)
A[i] = i;
- EXPECT_DEATH(A[-1] = 0, "");
- EXPECT_DEATH(A[-20] = 0, "");
- EXPECT_DEATH(A[-31] = 0, "");
- EXPECT_DEATH(A[kSize] = 0, "");
- EXPECT_DEATH(A[kSize + 1] = 0, "");
- EXPECT_DEATH(A[kSize + 10] = 0, "");
- EXPECT_DEATH(A[kSize + 31] = 0, "");
+ EXPECT_DEATH(A[-1] = 0, expected_death);
+ EXPECT_DEATH(A[-5] = 0, expected_death);
+ EXPECT_DEATH(A[kSize] = 0, expected_death);
+ EXPECT_DEATH(A[kSize + 1] = 0, expected_death);
+ EXPECT_DEATH(A[kSize + 5] = 0, expected_death);
+ if (kSize > 16)
+ EXPECT_DEATH(A[kSize + 31] = 0, expected_death);
}
TEST(AddressSanitizer, SimpleStackTest) {
@@ -478,6 +484,9 @@ TEST(AddressSanitizer, SimpleStackTest) {
SizedStackTest<128>();
}
+#if !defined(_WIN32)
+// FIXME: It's a bit hard to write multi-line death test expectations
+// in a portable way. Anyways, this should just be turned into a lit test.
TEST(AddressSanitizer, ManyStackObjectsTest) {
char XXX[10];
char YYY[20];
@@ -486,6 +495,47 @@ TEST(AddressSanitizer, ManyStackObjectsTest) {
Ident(YYY);
EXPECT_DEATH(Ident(ZZZ)[-1] = 0, ASAN_PCRE_DOTALL "XXX.*YYY.*ZZZ");
}
+#endif
+
+#if 0 // This test requires online symbolizer.
+// Moved to lit_tests/stack-oob-frames.cc.
+// Reenable here once we have online symbolizer by default.
+NOINLINE static void Frame0(int frame, char *a, char *b, char *c) {
+ char d[4] = {0};
+ char *D = Ident(d);
+ switch (frame) {
+ case 3: a[5]++; break;
+ case 2: b[5]++; break;
+ case 1: c[5]++; break;
+ case 0: D[5]++; break;
+ }
+}
+NOINLINE static void Frame1(int frame, char *a, char *b) {
+ char c[4] = {0}; Frame0(frame, a, b, c);
+ break_optimization(0);
+}
+NOINLINE static void Frame2(int frame, char *a) {
+ char b[4] = {0}; Frame1(frame, a, b);
+ break_optimization(0);
+}
+NOINLINE static void Frame3(int frame) {
+ char a[4] = {0}; Frame2(frame, a);
+ break_optimization(0);
+}
+
+TEST(AddressSanitizer, GuiltyStackFrame0Test) {
+ EXPECT_DEATH(Frame3(0), "located .*in frame <.*Frame0");
+}
+TEST(AddressSanitizer, GuiltyStackFrame1Test) {
+ EXPECT_DEATH(Frame3(1), "located .*in frame <.*Frame1");
+}
+TEST(AddressSanitizer, GuiltyStackFrame2Test) {
+ EXPECT_DEATH(Frame3(2), "located .*in frame <.*Frame2");
+}
+TEST(AddressSanitizer, GuiltyStackFrame3Test) {
+ EXPECT_DEATH(Frame3(3), "located .*in frame <.*Frame3");
+}
+#endif
NOINLINE void LongJmpFunc1(jmp_buf buf) {
// create three red zones for these two stack objects.
@@ -498,6 +548,24 @@ NOINLINE void LongJmpFunc1(jmp_buf buf) {
longjmp(buf, 1);
}
+NOINLINE void TouchStackFunc() {
+ int a[100]; // long array will intersect with redzones from LongJmpFunc1.
+ int *A = Ident(a);
+ for (int i = 0; i < 100; i++)
+ A[i] = i*i;
+}
+
+// Test that we handle longjmp and do not report false positives on stack.
+TEST(AddressSanitizer, LongJmpTest) {
+ static jmp_buf buf;
+ if (!setjmp(buf)) {
+ LongJmpFunc1(buf);
+ } else {
+ TouchStackFunc();
+ }
+}
+
+#if !defined(_WIN32) // Only basic longjmp is available on Windows.
NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) {
// create three red zones for these two stack objects.
int a;
@@ -531,25 +599,10 @@ NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) {
siglongjmp(buf, 1);
}
-
-NOINLINE void TouchStackFunc() {
- int a[100]; // long array will intersect with redzones from LongJmpFunc1.
- int *A = Ident(a);
- for (int i = 0; i < 100; i++)
- A[i] = i*i;
-}
-
-// Test that we handle longjmp and do not report fals positives on stack.
-TEST(AddressSanitizer, LongJmpTest) {
- static jmp_buf buf;
- if (!setjmp(buf)) {
- LongJmpFunc1(buf);
- } else {
- TouchStackFunc();
- }
-}
-
-#if not defined(__ANDROID__)
+#if !defined(__ANDROID__) && \
+ !defined(__powerpc64__) && !defined(__powerpc__)
+// Does not work on Power:
+// https://code.google.com/p/address-sanitizer/issues/detail?id=185
TEST(AddressSanitizer, BuiltinLongJmpTest) {
static jmp_buf buf;
if (!__builtin_setjmp((void**)buf)) {
@@ -558,7 +611,8 @@ TEST(AddressSanitizer, BuiltinLongJmpTest) {
TouchStackFunc();
}
}
-#endif // not defined(__ANDROID__)
+#endif // !defined(__ANDROID__) && !defined(__powerpc64__) &&
+ // !defined(__powerpc__)
TEST(AddressSanitizer, UnderscopeLongJmpTest) {
static jmp_buf buf;
@@ -577,8 +631,10 @@ TEST(AddressSanitizer, SigLongJmpTest) {
TouchStackFunc();
}
}
+#endif
-#ifdef __EXCEPTIONS
+// FIXME: Why does clang-cl define __EXCEPTIONS?
+#if defined(__EXCEPTIONS) && !defined(_WIN32)
NOINLINE void ThrowFunc() {
// create three red zones for these two stack objects.
int a;
@@ -626,7 +682,8 @@ TEST(AddressSanitizer, ThreadStackReuseTest) {
PTHREAD_JOIN(t, 0);
}
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i686__) || defined(__x86_64__)
+#include <emmintrin.h>
TEST(AddressSanitizer, Store128Test) {
char *a = Ident((char*)malloc(Ident(12)));
char *p = a;
@@ -644,11 +701,19 @@ TEST(AddressSanitizer, Store128Test) {
}
#endif
+// FIXME: All tests that use this function should be turned into lit tests.
string RightOOBErrorMessage(int oob_distance, bool is_write) {
assert(oob_distance >= 0);
char expected_str[100];
- sprintf(expected_str, ASAN_PCRE_DOTALL "%s.*located %d bytes to the right",
- is_write ? "WRITE" : "READ", oob_distance);
+ sprintf(expected_str, ASAN_PCRE_DOTALL
+#if !GTEST_USES_SIMPLE_RE
+ "buffer-overflow.*%s.*"
+#endif
+ "located %d bytes to the right",
+#if !GTEST_USES_SIMPLE_RE
+ is_write ? "WRITE" : "READ",
+#endif
+ oob_distance);
return string(expected_str);
}
@@ -660,11 +725,19 @@ string RightOOBReadMessage(int oob_distance) {
return RightOOBErrorMessage(oob_distance, /*is_write*/false);
}
+// FIXME: All tests that use this function should be turned into lit tests.
string LeftOOBErrorMessage(int oob_distance, bool is_write) {
assert(oob_distance > 0);
char expected_str[100];
- sprintf(expected_str, ASAN_PCRE_DOTALL "%s.*located %d bytes to the left",
- is_write ? "WRITE" : "READ", oob_distance);
+ sprintf(expected_str,
+#if !GTEST_USES_SIMPLE_RE
+ ASAN_PCRE_DOTALL "%s.*"
+#endif
+ "located %d bytes to the left",
+#if !GTEST_USES_SIMPLE_RE
+ is_write ? "WRITE" : "READ",
+#endif
+ oob_distance);
return string(expected_str);
}
@@ -818,6 +891,7 @@ void ThreadedTestSpawn() {
PTHREAD_JOIN(t, 0);
}
+#if !defined(_WIN32) // FIXME: This should be a lit test.
TEST(AddressSanitizer, ThreadedTest) {
EXPECT_DEATH(ThreadedTestSpawn(),
ASAN_PCRE_DOTALL
@@ -825,6 +899,7 @@ TEST(AddressSanitizer, ThreadedTest) {
".*Thread T.*created"
".*Thread T.*created");
}
+#endif
void *ThreadedTestFunc(void *unused) {
// Check if prctl(PR_SET_NAME) is supported. Return if not.
@@ -855,7 +930,11 @@ TEST(AddressSanitizer, ShadowGapTest) {
#if SANITIZER_WORDSIZE == 32
char *addr = (char*)0x22000000;
#else
+# if defined(__powerpc64__)
+ char *addr = (char*)0x024000800000;
+# else
char *addr = (char*)0x0000100000080000;
+# endif
#endif
EXPECT_DEATH(*addr = 1, "AddressSanitizer: SEGV on unknown");
}
@@ -1015,7 +1094,8 @@ TEST(AddressSanitizer, PthreadExitTest) {
}
}
-#ifdef __EXCEPTIONS
+// FIXME: Why does clang-cl define __EXCEPTIONS?
+#if defined(__EXCEPTIONS) && !defined(_WIN32)
NOINLINE static void StackReuseAndException() {
int large_stack[1000];
Ident(large_stack);
@@ -1033,12 +1113,14 @@ TEST(AddressSanitizer, DISABLED_StressStackReuseAndExceptionsTest) {
}
#endif
+#if !defined(_WIN32)
TEST(AddressSanitizer, MlockTest) {
EXPECT_EQ(0, mlockall(MCL_CURRENT));
EXPECT_EQ(0, mlock((void*)0x12345, 0x5678));
EXPECT_EQ(0, munlockall());
EXPECT_EQ(0, munlock((void*)0x987, 0x654));
}
+#endif
struct LargeStruct {
int foo[100];
@@ -1051,19 +1133,26 @@ TEST(AddressSanitizer, LargeStructCopyTest) {
*Ident(&a) = *Ident(&a);
}
-ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
-static void NoAddressSafety() {
+ATTRIBUTE_NO_SANITIZE_ADDRESS
+static void NoSanitizeAddress() {
char *foo = new char[10];
Ident(foo)[10] = 0;
delete [] foo;
}
-TEST(AddressSanitizer, AttributeNoAddressSafetyTest) {
- Ident(NoAddressSafety)();
+TEST(AddressSanitizer, AttributeNoSanitizeAddressTest) {
+ Ident(NoSanitizeAddress)();
}
-// It doesn't work on Android, as calls to new/delete go through malloc/free.
-#if !defined(ANDROID) && !defined(__ANDROID__)
+// The new/delete/etc mismatch checks don't work on Android,
+// as calls to new/delete go through malloc/free.
+// OS X support is tracked here:
+// https://code.google.com/p/address-sanitizer/issues/detail?id=131
+// Windows support is tracked here:
+// https://code.google.com/p/address-sanitizer/issues/detail?id=309
+#if !defined(ANDROID) && !defined(__ANDROID__) && \
+ !defined(__APPLE__) && \
+ !defined(_WIN32)
static string MismatchStr(const string &str) {
return string("AddressSanitizer: alloc-dealloc-mismatch \\(") + str;
}
@@ -1177,3 +1266,18 @@ TEST(AddressSanitizer, LongDoubleNegativeTest) {
memcpy(Ident(&a), Ident(&b), sizeof(long double));
memcpy(Ident(&c), Ident(&b), sizeof(long double));
}
+
+#if !defined(_WIN32)
+TEST(AddressSanitizer, pthread_getschedparam) {
+ int policy;
+ struct sched_param param;
+ EXPECT_DEATH(
+ pthread_getschedparam(pthread_self(), &policy, Ident(&param) + 2),
+ "AddressSanitizer: stack-buffer-.*flow");
+ EXPECT_DEATH(
+ pthread_getschedparam(pthread_self(), Ident(&policy) - 1, &param),
+ "AddressSanitizer: stack-buffer-.*flow");
+ int res = pthread_getschedparam(pthread_self(), &policy, &param);
+ ASSERT_EQ(0, res);
+}
+#endif
diff --git a/gcc/testsuite/g++.dg/asan/asan_test_config.h b/gcc/testsuite/g++.dg/asan/asan_test_config.h
index b039dc8beb2..97b7dd0873f 100644
--- a/gcc/testsuite/g++.dg/asan/asan_test_config.h
+++ b/gcc/testsuite/g++.dg/asan/asan_test_config.h
@@ -19,12 +19,6 @@
#include <string>
#include <map>
-#if ASAN_USE_DEJAGNU_GTEST
-# include "dejagnu-gtest.h"
-#else
-# include "gtest/gtest.h"
-#endif
-
using std::string;
using std::vector;
using std::map;
@@ -42,11 +36,11 @@ using std::map;
#endif
#ifndef ASAN_NEEDS_SEGV
-# error "please define ASAN_NEEDS_SEGV"
-#endif
-
-#ifndef ASAN_LOW_MEMORY
-# define ASAN_LOW_MEMORY 0
+# if defined(_WIN32)
+# define ASAN_NEEDS_SEGV 0
+# else
+# define ASAN_NEEDS_SEGV 1
+# endif
#endif
#ifndef ASAN_AVOID_EXPENSIVE_TESTS
diff --git a/gcc/testsuite/g++.dg/asan/asan_test_utils.h b/gcc/testsuite/g++.dg/asan/asan_test_utils.h
index 5ea7d4449f4..f5281a6a9e3 100644
--- a/gcc/testsuite/g++.dg/asan/asan_test_utils.h
+++ b/gcc/testsuite/g++.dg/asan/asan_test_utils.h
@@ -12,24 +12,28 @@
#ifndef ASAN_TEST_UTILS_H
#define ASAN_TEST_UTILS_H
-#if !defined(ASAN_EXTERNAL_TEST_CONFIG)
+#if !defined(SANITIZER_EXTERNAL_TEST_CONFIG)
# define INCLUDED_FROM_ASAN_TEST_UTILS_H
# include "asan_test_config.h"
# undef INCLUDED_FROM_ASAN_TEST_UTILS_H
#endif
#include "sanitizer_test_utils.h"
+#include "sanitizer_pthread_wrappers.h"
+
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
-#include <strings.h>
-#include <pthread.h>
#include <stdint.h>
-#include <setjmp.h>
#include <assert.h>
#include <algorithm>
-#include <sys/mman.h>
+
+#if !defined(_WIN32)
+# include <strings.h>
+# include <sys/mman.h>
+# include <setjmp.h>
+#endif
#ifdef __linux__
# include <sys/prctl.h>
@@ -39,18 +43,10 @@
#include <unistd.h>
#endif
-#if defined(__i386__) || defined(__x86_64__)
-#include <emmintrin.h>
-#endif
-
-#ifndef __APPLE__
+#if !defined(__APPLE__) && !defined(__FreeBSD__)
#include <malloc.h>
#endif
-// Check that pthread_create/pthread_join return success.
-#define PTHREAD_CREATE(a, b, c, d) ASSERT_EQ(0, pthread_create(a, b, c, d))
-#define PTHREAD_JOIN(a, b) ASSERT_EQ(0, pthread_join(a, b))
-
#if ASAN_HAS_EXCEPTIONS
# define ASAN_THROW(x) throw (x)
#else
diff --git a/gcc/testsuite/g++.dg/asan/sanitizer_pthread_wrappers.h b/gcc/testsuite/g++.dg/asan/sanitizer_pthread_wrappers.h
new file mode 100644
index 00000000000..2e71ecbb333
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/sanitizer_pthread_wrappers.h
@@ -0,0 +1,64 @@
+//===-- sanitizer_pthread_wrappers.h ----------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of *Sanitizer runtime.
+// It provides handy wrappers for thread manipulation, that:
+// a) assert on any failure rather than returning an error code
+// b) defines pthread-like interface on platforms where where <pthread.h>
+// is not supplied by default.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_PTHREAD_WRAPPERS_H
+#define SANITIZER_PTHREAD_WRAPPERS_H
+
+#include "sanitizer_test_utils.h"
+
+#if !defined(_WIN32)
+# include <pthread.h>
+// Simply forward the arguments and check that the pthread functions succeed.
+# define PTHREAD_CREATE(a, b, c, d) ASSERT_EQ(0, pthread_create(a, b, c, d))
+# define PTHREAD_JOIN(a, b) ASSERT_EQ(0, pthread_join(a, b))
+#else
+typedef HANDLE pthread_t;
+
+struct PthreadHelperCreateThreadInfo {
+ void *(*start_routine)(void *);
+ void *arg;
+};
+
+inline DWORD WINAPI PthreadHelperThreadProc(void *arg) {
+ PthreadHelperCreateThreadInfo *start_data =
+ reinterpret_cast<PthreadHelperCreateThreadInfo*>(arg);
+ void *ret = (start_data->start_routine)(start_data->arg);
+ delete start_data;
+ return (DWORD)ret;
+}
+
+inline void PTHREAD_CREATE(pthread_t *thread, void *attr,
+ void *(*start_routine)(void *), void *arg) {
+ ASSERT_EQ(0, attr) << "Thread attributes are not supported yet.";
+ PthreadHelperCreateThreadInfo *data = new PthreadHelperCreateThreadInfo;
+ data->start_routine = start_routine;
+ data->arg = arg;
+ *thread = CreateThread(0, 0, PthreadHelperThreadProc, data, 0, 0);
+ ASSERT_NE(nullptr, *thread) << "Failed to create a thread.";
+}
+
+inline void PTHREAD_JOIN(pthread_t thread, void **value_ptr) {
+ ASSERT_EQ(0, value_ptr) << "Nonzero value_ptr is not supported yet.";
+ ASSERT_EQ(WAIT_OBJECT_0, WaitForSingleObject(thread, INFINITE));
+ ASSERT_NE(0, CloseHandle(thread));
+}
+
+inline void pthread_exit(void *retval) {
+ ASSERT_EQ(0, retval) << "Nonzero retval is not supported yet.";
+ ExitThread((DWORD)retval);
+}
+#endif // _WIN32
+
+#endif // SANITIZER_PTHREAD_WRAPPERS_H
diff --git a/gcc/testsuite/g++.dg/asan/sanitizer_test_config.h b/gcc/testsuite/g++.dg/asan/sanitizer_test_config.h
new file mode 100644
index 00000000000..a819a4097a9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/sanitizer_test_config.h
@@ -0,0 +1,28 @@
+//===-- sanitizer_test_config.h ---------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of *Sanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+#if !defined(INCLUDED_FROM_SANITIZER_TEST_UTILS_H)
+# error "This file should be included into sanitizer_test_utils.h only"
+#endif
+
+#ifndef SANITIZER_TEST_CONFIG_H
+#define SANITIZER_TEST_CONFIG_H
+
+#include <vector>
+#include <string>
+#include <map>
+
+#if SANITIZER_USE_DEJAGNU_GTEST
+# include "dejagnu-gtest.h"
+#else
+# include "gtest/gtest.h"
+#endif
+
+#endif // SANITIZER_TEST_CONFIG_H
diff --git a/gcc/testsuite/g++.dg/asan/sanitizer_test_utils.h b/gcc/testsuite/g++.dg/asan/sanitizer_test_utils.h
index 99720c354fa..b118de1d346 100644
--- a/gcc/testsuite/g++.dg/asan/sanitizer_test_utils.h
+++ b/gcc/testsuite/g++.dg/asan/sanitizer_test_utils.h
@@ -14,32 +14,47 @@
#define SANITIZER_TEST_UTILS_H
#if defined(_WIN32)
-typedef unsigned __int8 uint8_t;
-typedef unsigned __int16 uint16_t;
-typedef unsigned __int32 uint32_t;
-typedef unsigned __int64 uint64_t;
-typedef __int8 int8_t;
-typedef __int16 int16_t;
-typedef __int32 int32_t;
-typedef __int64 int64_t;
+// <windows.h> should always be the first include on Windows.
+# include <windows.h>
+// MSVS headers define max/min as macros, so std::max/min gets crazy.
+# undef max
+# undef min
+#endif
+
+#if !defined(SANITIZER_EXTERNAL_TEST_CONFIG)
+# define INCLUDED_FROM_SANITIZER_TEST_UTILS_H
+# include "sanitizer_test_config.h"
+# undef INCLUDED_FROM_SANITIZER_TEST_UTILS_H
+#endif
+
+#include <stdint.h>
+
+#if defined(_MSC_VER)
# define NOINLINE __declspec(noinline)
-# define USED
-#else // defined(_WIN32)
+#else // defined(_MSC_VER)
# define NOINLINE __attribute__((noinline))
+#endif // defined(_MSC_VER)
+
+#if !defined(_MSC_VER) || defined(__clang__)
+# define UNUSED __attribute__((unused))
# define USED __attribute__((used))
-#include <stdint.h>
-#endif // defined(_WIN32)
+#else
+# define UNUSED
+# define USED
+#endif
#if !defined(__has_feature)
#define __has_feature(x) 0
#endif
-#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
-# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS \
+#ifndef ATTRIBUTE_NO_SANITIZE_ADDRESS
+# if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+# define ATTRIBUTE_NO_SANITIZE_ADDRESS \
__attribute__((no_sanitize_address))
-#else
-# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
-#endif
+# else
+# define ATTRIBUTE_NO_SANITIZE_ADDRESS
+# endif
+#endif // ATTRIBUTE_NO_SANITIZE_ADDRESS
#if __LP64__ || defined(_WIN64)
# define SANITIZER_WORDSIZE 64
@@ -49,7 +64,9 @@ typedef __int64 int64_t;
// Make the compiler thinks that something is going on there.
inline void break_optimization(void *arg) {
+#if !defined(_WIN32) || defined(__clang__)
__asm__ __volatile__("" : : "r" (arg) : "memory");
+#endif
}
// This function returns its parameter but in such a way that compiler
@@ -74,5 +91,28 @@ static inline uint32_t my_rand() {
return my_rand_r(&global_seed);
}
+// Set availability of platform-specific functions.
+
+#if !defined(__APPLE__) && !defined(ANDROID) && !defined(__ANDROID__) && !defined(_WIN32)
+# define SANITIZER_TEST_HAS_POSIX_MEMALIGN 1
+#else
+# define SANITIZER_TEST_HAS_POSIX_MEMALIGN 0
+#endif
+
+#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(_WIN32)
+# define SANITIZER_TEST_HAS_MEMALIGN 1
+# define SANITIZER_TEST_HAS_PVALLOC 1
+# define SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE 1
+#else
+# define SANITIZER_TEST_HAS_MEMALIGN 0
+# define SANITIZER_TEST_HAS_PVALLOC 0
+# define SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE 0
+#endif
+
+#if !defined(__APPLE__)
+# define SANITIZER_TEST_HAS_STRNLEN 1
+#else
+# define SANITIZER_TEST_HAS_STRNLEN 0
+#endif
#endif // SANITIZER_TEST_UTILS_H
diff --git a/gcc/testsuite/g++.dg/asan/symbolize-callback-1.C b/gcc/testsuite/g++.dg/asan/symbolize-callback-1.C
deleted file mode 100644
index 9978958f9e2..00000000000
--- a/gcc/testsuite/g++.dg/asan/symbolize-callback-1.C
+++ /dev/null
@@ -1,21 +0,0 @@
-// { dg-do run }
-// { dg-skip-if "" { *-*-* } { "*" } { "-O2" } }
-// { dg-options "-fno-builtin-malloc -fno-builtin-free" }
-// { dg-shouldfail "asan" }
-
-#include <stdio.h>
-#include <stdlib.h>
-
-extern "C"
-bool __asan_symbolize(const void *, char *out_buffer, int out_size) {
- snprintf(out_buffer, out_size, "MySymbolizer");
- return true;
-}
-
-int main() {
- char *x = (char*)malloc(10);
- free(x);
- return x[5];
-}
-
-// { dg-output "MySymbolizer" }
diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/array_function.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/array_function.cc
new file mode 100644
index 00000000000..b111e217cfc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_function.cc
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+void f() { }
+int main()
+{
+ f[0:1:1]; // { dg-error "function type" }
+}
diff --git a/gcc/testsuite/g++.dg/compat/compat.exp b/gcc/testsuite/g++.dg/compat/compat.exp
index 1a7cdb8396a..7fd77d7ed96 100644
--- a/gcc/testsuite/g++.dg/compat/compat.exp
+++ b/gcc/testsuite/g++.dg/compat/compat.exp
@@ -55,6 +55,7 @@ proc compat-use-alt-compiler { } {
set ALWAYS_CXXFLAGS ""
set ld_library_path $alt_ld_library_path
set_ld_library_path_env_vars
+ restore_gcc_exec_prefix_env_var
}
}
diff --git a/gcc/testsuite/g++.dg/compat/struct-layout-1.exp b/gcc/testsuite/g++.dg/compat/struct-layout-1.exp
index 13211c2fa17..0beb5953723 100644
--- a/gcc/testsuite/g++.dg/compat/struct-layout-1.exp
+++ b/gcc/testsuite/g++.dg/compat/struct-layout-1.exp
@@ -60,6 +60,7 @@ proc compat-use-alt-compiler { } {
set ALWAYS_CXXFLAGS ""
set ld_library_path $alt_ld_library_path
set_ld_library_path_env_vars
+ restore_gcc_exec_prefix_env_var
}
}
diff --git a/gcc/testsuite/g++.dg/conversion/ambig1.C b/gcc/testsuite/g++.dg/conversion/ambig1.C
index 85ea1d25f9e..1db1667073f 100644
--- a/gcc/testsuite/g++.dg/conversion/ambig1.C
+++ b/gcc/testsuite/g++.dg/conversion/ambig1.C
@@ -6,4 +6,3 @@ struct H {
};
int const& ref = H(); // { dg-error "ambiguous" }
-// { dg-message "candidate" "candidate note" { target *-*-* } 8 }
diff --git a/gcc/testsuite/g++.dg/conversion/op1.C b/gcc/testsuite/g++.dg/conversion/op1.C
index e0a3e5f46ed..dd7ac2f9cec 100644
--- a/gcc/testsuite/g++.dg/conversion/op1.C
+++ b/gcc/testsuite/g++.dg/conversion/op1.C
@@ -7,5 +7,4 @@ class C
int fn (C c)
{
return C::operator float(c); // { dg-error "operator float.C" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 9 }
}
diff --git a/gcc/testsuite/g++.dg/conversion/op4.C b/gcc/testsuite/g++.dg/conversion/op4.C
index 7ef4b6a0c6d..cb99a380b43 100644
--- a/gcc/testsuite/g++.dg/conversion/op4.C
+++ b/gcc/testsuite/g++.dg/conversion/op4.C
@@ -9,11 +9,11 @@ struct X {
}
};
-void add_one (X & ref) { /* { dg-message "in passing argument" } */
+void add_one (X & ref) { /* { dg-message "argument" } */
++ ref.x;
}
void foo() {
X const a (2);
- add_one(a); /* { dg-error "invalid initialization of reference of type" } */
+ add_one(a); /* { dg-error "discards qualifiers" } */
}
diff --git a/gcc/testsuite/g++.dg/conversion/op5.C b/gcc/testsuite/g++.dg/conversion/op5.C
index 69ef996d5c2..0aad9259bf9 100644
--- a/gcc/testsuite/g++.dg/conversion/op5.C
+++ b/gcc/testsuite/g++.dg/conversion/op5.C
@@ -15,6 +15,6 @@ struct B
void
foo (const B& b)
{
- const A a = b; // { dg-error "conversion from 'const B' to non-scalar type 'const A' requested" }
+ const A a = b; // { dg-error "const B" }
}
diff --git a/gcc/testsuite/g++.dg/conversion/simd1.C b/gcc/testsuite/g++.dg/conversion/simd1.C
index 522d8b5470a..7955f68c1a1 100644
--- a/gcc/testsuite/g++.dg/conversion/simd1.C
+++ b/gcc/testsuite/g++.dg/conversion/simd1.C
@@ -18,7 +18,6 @@ extern const vector signed short *cvssp;
void foo ()
{
vss = vld(i, vscp); /* { dg-error "no matching function for call" } */
- // { dg-message "candidate" "candidate note" { target *-*-* } 20 }
vss = vld(i, vssp);
vss = vld(i, cvssp);
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C b/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C
new file mode 100644
index 00000000000..4d3c29ce3f1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C
@@ -0,0 +1,8 @@
+// PR c++/60373
+// { dg-do compile { target c++11 } }
+// { dg-require-visibility "" }
+
+#include <new>
+__attribute__((visibility("hidden")))void*operator new(std::size_t); // { dg-warning "visibility attribute ignored" }
+
+// { dg-message "previous declaration" "" { target *-*-* } 128 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-call1.C b/gcc/testsuite/g++.dg/cpp0x/decltype-call1.C
index 2616bb09046..39069ba228f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype-call1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-call1.C
@@ -2,7 +2,7 @@
// N3276
// { dg-do compile { target c++11 } }
-struct A; // { dg-error "forward declaration" }
+struct A; // { dg-message "forward declaration" }
A f();
decltype(f()) g1(); // OK
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype58.C b/gcc/testsuite/g++.dg/cpp0x/decltype58.C
new file mode 100644
index 00000000000..c3918bf8474
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype58.C
@@ -0,0 +1,24 @@
+// PR c++/52875
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ friend void swap(A&,A&) {}
+};
+
+class B
+{
+ A a;
+
+ template <class T>
+ friend auto swap(T& x, T& y) -> decltype(swap(x.a,y.a))
+ {
+ swap(x.a,y.a);
+ }
+};
+
+int main()
+{
+ B x, y;
+ swap(x, y);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype59.C b/gcc/testsuite/g++.dg/cpp0x/decltype59.C
new file mode 100644
index 00000000000..93208df95cb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype59.C
@@ -0,0 +1,41 @@
+// PR c++/57543
+// { dg-do compile { target c++11 } }
+
+template< typename > struct X
+{
+ void foo();
+ auto bar() -> decltype( X::foo() );
+};
+
+template< typename > struct Y
+{
+ void foo();
+ template< typename >
+ auto bar() -> decltype( Y::foo() );
+};
+
+template< typename > struct Z
+{
+ void foo();
+ template< typename T >
+ auto bar() -> decltype( T::foo() );
+};
+
+template< typename > struct K
+{
+ void foo();
+ template< typename T >
+ auto bar() -> decltype( T::foo() );
+};
+
+template<>
+template<>
+auto K<int>::bar<K<int>>() -> decltype( K<int>::foo() );
+
+int main()
+{
+ X<int>().bar();
+ Y<int>().bar<double>();
+ Z<int>().bar<Z<int>>();
+ K<int>().bar<K<int>>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted14.C b/gcc/testsuite/g++.dg/cpp0x/defaulted14.C
index 0c07fa701b7..16df8bcc306 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted14.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted14.C
@@ -14,7 +14,5 @@ int main()
{
A a;
a = B(); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 16 }
a = 1.0; // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 18 }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted18.C b/gcc/testsuite/g++.dg/cpp0x/defaulted18.C
index 6d84a1e8813..83e1126dc08 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted18.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted18.C
@@ -6,5 +6,4 @@ void f(int i, ...); // { dg-message "void f" }
int main()
{
f(1,1); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 8 }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted20.C b/gcc/testsuite/g++.dg/cpp0x/defaulted20.C
index affda20fdd4..2bc4f7fbb5b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted20.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted20.C
@@ -10,7 +10,7 @@ struct B {
B(B&&) = default; // { dg-error "implicitly deleted|use of deleted" }
};
-void g(B); // { dg-error "argument 1" }
+void g(B); // { dg-message "argument 1" }
B&& f();
int main()
diff --git a/gcc/testsuite/g++.dg/cpp0x/diag2.C b/gcc/testsuite/g++.dg/cpp0x/diag2.C
new file mode 100644
index 00000000000..0d01b1de795
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/diag2.C
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++11 } }
+
+struct A {};
+
+// We shouldn't arbitarily choose which of these is better.
+void f (A&);
+void f (const A&&);
+
+// But do prefer the lvalue overload here.
+void g (A&);
+void g (A&&);
+int main()
+{
+ const A a;
+ f(a); // { dg-error "no match" }
+ // { dg-error "qualifiers" "" { target *-*-* } 15 }
+ // { dg-error "lvalue" "" { target *-*-* } 15 }
+ g(a); // { dg-error "qualifiers" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit3.C b/gcc/testsuite/g++.dg/cpp0x/explicit3.C
index 678076c8e41..6318ade2c0e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/explicit3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit3.C
@@ -45,6 +45,6 @@ int main()
f(a); // { dg-error "" }
B b2 = { a }; // { dg-error "" }
a + true; // { dg-error "5:no match" }
- b ? a : true; // { dg-error "5:no match" }
- a ? a : true; // { dg-error "5:no match" }
+ b ? a : true; // { dg-error "5:?:" }
+ a ? a : true; // { dg-error "5:?:" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit4.C b/gcc/testsuite/g++.dg/cpp0x/explicit4.C
index 663878e55a8..346a6e25908 100644
--- a/gcc/testsuite/g++.dg/cpp0x/explicit4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit4.C
@@ -14,5 +14,4 @@ int main()
B b;
(A(b)); // OK
(A(b,1)); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 16 }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C
index ccce13a79b8..7d2094df52b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C
@@ -25,10 +25,10 @@ enum class E3 e3; // { dg-error "scoped enum must not use" }
enum struct E3 e4; // { dg-error "scoped enum must not use" }
enum E5 : int e5; // { dg-error "expected|invalid type" }
-enum E6 : int { a, b, c }; // { dg-error "previous definition" }
+enum E6 : int { a, b, c }; // { dg-message "previous definition" }
enum E6 : int { a, b, c }; // { dg-error "multiple definition" }
-enum class E7 { }; // { dg-error "previous definition" }
+enum class E7 { }; // { dg-message "previous definition" }
enum class E7 { a, b, c }; // { dg-error "multiple definition" }
namespace N1
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist84.C b/gcc/testsuite/g++.dg/cpp0x/initlist84.C
new file mode 100644
index 00000000000..4d46746c52f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist84.C
@@ -0,0 +1,17 @@
+// PR c++/61242
+// { dg-do compile { target c++11 } }
+
+struct Foo
+{
+ struct A
+ {
+ const int &container;
+ const int &args;
+ };
+ static void Create (const A &);
+};
+
+int main ()
+{
+ Foo::Create ({{}, {}});
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-59483.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-59483.C
new file mode 100644
index 00000000000..b5b06d2c813
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-59483.C
@@ -0,0 +1,31 @@
+// PR c++/59483
+// { dg-do compile { target c++11 } }
+
+struct X
+{
+protected:
+ int i;
+};
+
+struct Y : X
+{
+ Y()
+ {
+ [&]{ X::i = 3; }();
+ }
+};
+
+template <class T>
+struct Y2 : T
+{
+ Y2()
+ {
+ [&]{ T::i = 3; }();
+ }
+};
+
+int main()
+{
+ Y y;
+ Y2<X> y2;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-61148.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-61148.C
new file mode 100644
index 00000000000..879030caa0d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-61148.C
@@ -0,0 +1,33 @@
+// PR c++/61148
+// { dg-do compile { target c++11 } }
+
+class DB
+{
+protected:
+ void foo() {};
+};
+
+class DC : public DB
+{
+public:
+ DC()
+ {
+ [this]() {DB::foo();}();
+ };
+};
+
+template <class T>
+class DC2 : public T
+{
+public:
+ DC2()
+ {
+ [this]() {T::foo();}();
+ };
+};
+
+int main(void)
+{
+ DC x;
+ DC2<DB> x2;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-this.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-this.C
new file mode 100644
index 00000000000..220ac911cdb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-this.C
@@ -0,0 +1,9 @@
+// PR c++/60463
+// PR c++/60755
+// { dg-do compile { target c++11 } }
+struct S {
+ void f();
+ void g() const {
+ [=] { f(); } (); // { dg-error "no match|qualifiers" }
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice13.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice13.C
new file mode 100644
index 00000000000..4c611ad8ee1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice13.C
@@ -0,0 +1,14 @@
+// PR c++/61088
+// { dg-do compile { target c++11 } }
+
+void f()
+{
+ typedef void (*X) ();
+ X x[] = { [x](){} }; // { dg-error "incomplete type" }
+}
+
+void g()
+{
+ typedef void (X) ();
+ X x[] = { [x](){} }; // { dg-error "array of functions|not declared" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C
index 6a31e0a36f3..702f18f6ac8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C
@@ -12,6 +12,5 @@ int main()
auto l = []() { return 5; }; // { dg-message "lambda closure type" }
run(l); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 14 }
// { dg-error "use of deleted function" "candidate explanation" { target *-*-* } 5 }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice7.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice7.C
index d0ee866110d..6f8272aeb60 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice7.C
@@ -1,9 +1,9 @@
// PR c++/52487
// { dg-do compile { target c++11 } }
-struct A; // { dg-error "forward declaration" }
+struct A; // { dg-message "forward declaration" }
void foo(A& a)
{
- [=](){a;}; // { dg-error "invalid use of incomplete type" }
+ [=](){a;}; // { dg-error "incomplete type" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi6.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi6.C
new file mode 100644
index 00000000000..98cdbce28b3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi6.C
@@ -0,0 +1,23 @@
+// PR c++/58761
+// { dg-do compile { target c++11 } }
+
+template <class T>
+struct X
+{
+ int x = 42;
+ int y = [this](){return this->x;}();
+};
+
+template <class T>
+struct Y
+{
+ int x = 42;
+ int y = [this](){return this->x;}();
+ Y(int) {}
+};
+
+int main()
+{
+ X<int> x;
+ Y<int> y(42);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this18.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this18.C
new file mode 100644
index 00000000000..fec2da615b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this18.C
@@ -0,0 +1,30 @@
+// PR c++/61151
+// { dg-do compile { target c++11 } }
+
+struct B
+{
+ void foo () {}
+};
+
+template <class>
+struct A
+{
+ template <class> void bar ();
+ B a;
+};
+
+template <class T>
+template <class U>
+void
+A<T>::bar ()
+{
+ auto f = [this] () { auto g = [=] () { a.foo (); }; g (); };
+ f ();
+}
+
+int
+main ()
+{
+ A<int> a;
+ a.bar <int> ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept15.C b/gcc/testsuite/g++.dg/cpp0x/noexcept15.C
index 909ee9748bc..5cbbea8a91a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept15.C
@@ -23,12 +23,10 @@ template<class Tp>
return single<typename std::decay<Tp>::type>(x);
}
-class Blob; // { dg-error "forward declaration" }
+class Blob; // { dg-message "forward declaration" }
void
foo(Blob *b)
{
make_single(*b);
}
-
-// { dg-prune-output "include" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template11.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template11.C
new file mode 100644
index 00000000000..60e53c4190a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template11.C
@@ -0,0 +1,15 @@
+// PR c++/58930
+// { dg-do compile { target c++11 } }
+
+struct SampleModule
+{
+ explicit SampleModule (int);
+};
+
+template < typename >
+struct BaseHandler
+{
+ SampleModule module_ { 0 };
+};
+
+BaseHandler<int> a;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C
new file mode 100644
index 00000000000..5b87f429e8a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template12.C
@@ -0,0 +1,17 @@
+// PR c++/58753
+// { dg-do compile { target c++11 } }
+
+#include <initializer_list>
+
+template <class T>
+struct X {X(std::initializer_list<int>) {}};
+
+template <class zomg>
+class T {
+ X<T> x{1};
+};
+
+int main()
+{
+ T<int> t;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C
new file mode 100644
index 00000000000..65ccd0aaa7f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template13.C
@@ -0,0 +1,11 @@
+// PR c++/58704
+// { dg-do compile { target c++11 } }
+
+struct A {};
+
+template<typename> struct B
+{
+ A a[1] = { };
+};
+
+B<int> b;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-union6.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-union6.C
new file mode 100644
index 00000000000..764fe21d610
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-union6.C
@@ -0,0 +1,56 @@
+// PR c++/58664
+// { dg-do compile { target c++11 } }
+
+struct F; // { dg-message "forward declaration" }
+
+union U // { dg-message "not complete" }
+{
+ U u[1] = { 0 }; // { dg-error "incomplete type" }
+};
+
+template<typename T>
+union UT // { dg-message "not complete" }
+{
+ UT u[1] = { 0 }; // { dg-error "incomplete type" }
+};
+
+template union UT<int>;
+
+union UF
+{
+ F u[1] = { 0 }; // { dg-error "incomplete type" }
+};
+
+template<typename T>
+union UFT
+{
+ F u[1] = { 0 }; // { dg-error "incomplete type" }
+};
+
+template union UFT<int>;
+
+struct S // { dg-message "not complete" }
+{
+ S s[1] = { 0 }; // { dg-error "incomplete type" }
+};
+
+template<typename T>
+struct ST // { dg-message "not complete" }
+{
+ ST s[1] = { 0 }; // { dg-error "incomplete type" }
+};
+
+template class ST<int>;
+
+struct SF
+{
+ F s[1] = { 0 }; // { dg-error "incomplete type" }
+};
+
+template<typename T>
+struct SFT
+{
+ F s[1] = { 0 }; // { dg-error "incomplete type" }
+};
+
+template class SFT<int>;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi6.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi6.C
index e78f50019a5..f88a347426a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi6.C
@@ -4,5 +4,5 @@
struct A
{
typedef int int T; // { dg-error "two or more data types in declaration" }
- struct T x[1] = { 0 }; // { dg-error "invalid|forward" }
+ struct T x[1] = { 0 }; // { dg-error "incomplete type|forward" }
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr19.C b/gcc/testsuite/g++.dg/cpp0x/nullptr19.C
index 8b6a0b4289d..17c4b7caa3b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr19.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr19.C
@@ -11,7 +11,5 @@ nullptr_t k( nullptr_t ); /* { dg-message "note" } */
void test_k()
{
k(0); /* { dg-error "is ambiguous" } */
- // { dg-message "candidate" "candidate note" { target *-*-* } 13 }
k(__null); /* { dg-error "is ambiguous" } */
- // { dg-message "candidate" "candidate note" { target *-*-* } 15 }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/overloadn.C b/gcc/testsuite/g++.dg/cpp0x/overloadn.C
index 16c39a9ed37..243f83be73e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/overloadn.C
+++ b/gcc/testsuite/g++.dg/cpp0x/overloadn.C
@@ -543,9 +543,9 @@ void ucr1111(const S&&) {}
int main()
{
- l0001(l); // { dg-error "lvalue" }
- l0010(l); // { dg-error "lvalue" }
- l0011(l); // { dg-error "lvalue" }
+ l0001(l); // { dg-error "" }
+ l0010(l); // { dg-error "" }
+ l0011(l); // { dg-error "" }
l0100(l);
l0101(l);
l0110(l);
@@ -564,8 +564,8 @@ int main()
cl0101(cl);
cl0110(cl);
cl0111(cl);
- cl1001(cl); // { dg-error "lvalue" }
- cl1011(cl); // { dg-error "lvalue" }
+ cl1001(cl); // { dg-error "" }
+ cl1011(cl); // { dg-error "" }
cl1100(cl);
cl1101(cl);
cl1110(cl);
@@ -617,8 +617,8 @@ int main()
ncl0101(ncl);
ncl0110(ncl);
ncl0111(ncl);
- ncl1001(ncl); // { dg-error "lvalue" }
- ncl1011(ncl); // { dg-error "lvalue" }
+ ncl1001(ncl); // { dg-error "" }
+ ncl1011(ncl); // { dg-error "" }
ncl1100(ncl);
ncl1101(ncl);
ncl1110(ncl);
@@ -644,8 +644,8 @@ int main()
ncr0101(ncr);
ncr0110(ncr);
ncr0111(ncr);
- ncr1001(ncr); // { dg-error "lvalue" }
- ncr1011(ncr); // { dg-error "lvalue" }
+ ncr1001(ncr); // { dg-error "" }
+ ncr1011(ncr); // { dg-error "" }
ncr1100(ncr);
ncr1101(ncr);
ncr1110(ncr);
@@ -671,8 +671,8 @@ int main()
ucl0101(ucl());
ucl0110(ucl());
ucl0111(ucl());
- ucl1001(ucl()); // { dg-error "lvalue" }
- ucl1011(ucl()); // { dg-error "lvalue" }
+ ucl1001(ucl()); // { dg-error "" }
+ ucl1011(ucl()); // { dg-error "" }
ucl1100(ucl());
ucl1101(ucl());
ucl1110(ucl());
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31434.C b/gcc/testsuite/g++.dg/cpp0x/pr31434.C
index e70bdd17e9a..afb719f17c8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31434.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31434.C
@@ -8,5 +8,4 @@ template<typename... T> int foo(const T&) // { dg-error "not expanded with|T" }
void bar()
{
foo(0); // { dg-error "no matching" }
- // { dg-message "(candidate|cannot convert)" "candidate note" { target *-*-* } 10 }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31437.C b/gcc/testsuite/g++.dg/cpp0x/pr31437.C
index 5f7010fe6a1..7e2ed7a1375 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31437.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31437.C
@@ -7,4 +7,3 @@ template <typename... T> struct A // { dg-message "candidates|A" }
};
A<int> a(0); // { dg-error "no matching" }
-// { dg-message "candidate" "candidate note" { target *-*-* } 9 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr57543-1.C b/gcc/testsuite/g++.dg/cpp0x/pr57543-1.C
new file mode 100644
index 00000000000..d77d71e8bdb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr57543-1.C
@@ -0,0 +1,13 @@
+// DR 1227, PR c++/57543
+// { dg-do compile { target c++11 } }
+
+template <class T> struct A { using X = typename T::X; }; // { dg-error "not a class" }
+template <class T> typename T::X f(typename A<T>::X);
+template <class T> void f(...) { }
+template <class T> auto g(typename A<T>::X) -> typename T::X; // { dg-message "required" }
+template <class T> void g(...) { }
+
+void h() {
+ f<int>(0); // OK
+ g<int>(0); // { dg-message "required" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr57543-2.C b/gcc/testsuite/g++.dg/cpp0x/pr57543-2.C
new file mode 100644
index 00000000000..7afa7fe491b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr57543-2.C
@@ -0,0 +1,17 @@
+// DR 1227, PR c++/57543
+// { dg-do compile { target c++11 } }
+
+struct S
+{
+ template <class T> struct A { using X = typename T::X; }; // { dg-error "not a class" }
+ template <class T> typename T::X f(typename A<T>::X);
+ template <class T> void f(...) { }
+ template <class T> auto g(typename A<T>::X) -> typename T::X; // { dg-message "required" }
+ template <class T> void g(...) { }
+
+ void h()
+ {
+ f<int>(0); // OK
+ g<int>(0); // { dg-message "required" }
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr57543-3.C b/gcc/testsuite/g++.dg/cpp0x/pr57543-3.C
new file mode 100644
index 00000000000..b77fefc8c11
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr57543-3.C
@@ -0,0 +1,20 @@
+// DR 1227, PR c++/57543
+// { dg-do compile { target c++11 } }
+
+template <class>
+class C
+{
+ template <class T> struct A { using X = typename T::X; }; // { dg-error "not a class" }
+ template <class T> typename T::X f(typename A<T>::X);
+ template <class T> void f(...) { }
+ template <class T> auto g(typename A<T>::X) -> typename T::X; // { dg-message "required" }
+ template <class T> void g(...) { }
+
+ void h()
+ {
+ f<int>(0); // OK
+ g<int>(0); // { dg-message "required" }
+ }
+};
+
+template class C<int>; // { dg-message "required" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr61038.C b/gcc/testsuite/g++.dg/cpp0x/pr61038.C
new file mode 100644
index 00000000000..6c7a47bae73
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr61038.C
@@ -0,0 +1,40 @@
+// PR c++/61038
+// { dg-do compile { target c++11 } }
+
+#include <cstring>
+#include <cstdlib>
+
+void
+operator "" _s(const char *, size_t)
+{ }
+
+void
+operator "" _t(const char)
+{ }
+
+#define QUOTE(s) #s
+#define QQUOTE(s) QUOTE(s)
+
+int
+main()
+{
+ const char *s = QQUOTE(QUOTE("hello"_s));
+ const char *t = QUOTE("\"hello\"_s");
+ if (strcmp(s, t) != 0)
+ abort();
+
+ const char *c = QQUOTE(QUOTE('"'_t));
+ const char *d = QUOTE("'\"'_t");
+ if (strcmp(c, d) != 0)
+ abort();
+
+ const char *e = QQUOTE(QUOTE('\''_t));
+ const char *f = QUOTE("'\\''_t");
+ if (strcmp(e, f) != 0)
+ abort();
+
+ const char *g = QQUOTE(QUOTE('\\'_t));
+ const char *h = QUOTE("'\\\\'_t");
+ if (strcmp(g, h) != 0)
+ abort();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cond1.C b/gcc/testsuite/g++.dg/cpp0x/rv-cond1.C
new file mode 100644
index 00000000000..a8f598f17d4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-cond1.C
@@ -0,0 +1,13 @@
+// PR c++/58714
+// { dg-do compile { target c++11 } }
+
+struct X {
+ X& operator=(const X&) = delete;
+ X& operator=(X&& ) = default;
+};
+
+void f(bool t) {
+ X a, b;
+ *(t ? &a : &b) = X();
+ (t ? a : b) = X();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cond2.C b/gcc/testsuite/g++.dg/cpp0x/rv-cond2.C
new file mode 100644
index 00000000000..e231b11e1a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-cond2.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++11 } }
+
+template <class T, class U> struct ST;
+template <class T> struct ST<T,T> {};
+
+int&& f();
+const int&& g();
+
+void h(bool b) {
+ ST<decltype(b ? f() : g()),const int&&>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv1n.C b/gcc/testsuite/g++.dg/cpp0x/rv1n.C
index 9aa534a653a..204ca31a00d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv1n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv1n.C
@@ -37,13 +37,13 @@ int test1_1()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_1_1(ca); // { dg-error "invalid initialization" }
- sink_1_1(va); // { dg-error "invalid initialization" }
- sink_1_1(cva); // { dg-error "invalid initialization" }
- sink_1_1(source()); // { dg-error "invalid initialization" }
- sink_1_1(c_source()); // { dg-error "invalid initialization" }
- sink_1_1(v_source()); // { dg-error "invalid initialization" }
- sink_1_1(cv_source()); // { dg-error "invalid initialization" }
+ sink_1_1(ca); // { dg-error "" }
+ sink_1_1(va); // { dg-error "" }
+ sink_1_1(cva); // { dg-error "" }
+ sink_1_1(source()); // { dg-error "" }
+ sink_1_1(c_source()); // { dg-error "" }
+ sink_1_1(v_source()); // { dg-error "" }
+ sink_1_1(cv_source()); // { dg-error "" }
return 0;
}
@@ -55,10 +55,10 @@ int test1_2()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_1_2(va); // { dg-error "invalid initialization" }
- sink_1_2(cva); // { dg-error "invalid initialization" }
- sink_1_2(v_source()); // { dg-error "invalid initialization" }
- sink_1_2(cv_source()); // { dg-error "invalid initialization" }
+ sink_1_2(va); // { dg-error "" }
+ sink_1_2(cva); // { dg-error "" }
+ sink_1_2(v_source()); // { dg-error "" }
+ sink_1_2(cv_source()); // { dg-error "" }
return 0;
}
@@ -70,12 +70,12 @@ int test1_3()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_1_3(ca); // { dg-error "invalid initialization" }
- sink_1_3(cva); // { dg-error "invalid initialization" }
- sink_1_3(source()); // { dg-error "invalid initialization" }
- sink_1_3(c_source()); // { dg-error "invalid initialization" }
- sink_1_3(v_source()); // { dg-error "invalid initialization" }
- sink_1_3(cv_source()); // { dg-error "invalid initialization" }
+ sink_1_3(ca); // { dg-error "" }
+ sink_1_3(cva); // { dg-error "" }
+ sink_1_3(source()); // { dg-error "" }
+ sink_1_3(c_source()); // { dg-error "" }
+ sink_1_3(v_source()); // { dg-error "" }
+ sink_1_3(cv_source()); // { dg-error "" }
return 0;
}
@@ -87,10 +87,10 @@ int test1_4()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_1_4(source()); // { dg-error "invalid initialization" }
- sink_1_4(c_source()); // { dg-error "invalid initialization" }
- sink_1_4(v_source()); // { dg-error "invalid initialization" }
- sink_1_4(cv_source()); // { dg-error "invalid initialization" }
+ sink_1_4(source()); // { dg-error "" }
+ sink_1_4(c_source()); // { dg-error "" }
+ sink_1_4(v_source()); // { dg-error "" }
+ sink_1_4(cv_source()); // { dg-error "" }
return 0;
}
@@ -103,12 +103,12 @@ int test1_5()
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
sink_1_5(a); // { dg-error "lvalue" }
- sink_1_5(ca); // { dg-error "invalid initialization" }
- sink_1_5(va); // { dg-error "invalid initialization" }
- sink_1_5(cva); // { dg-error "invalid initialization" }
- sink_1_5(c_source()); // { dg-error "invalid initialization" }
- sink_1_5(v_source()); // { dg-error "invalid initialization" }
- sink_1_5(cv_source()); // { dg-error "invalid initialization" }
+ sink_1_5(ca); // { dg-error "" }
+ sink_1_5(va); // { dg-error "" }
+ sink_1_5(cva); // { dg-error "" }
+ sink_1_5(c_source()); // { dg-error "" }
+ sink_1_5(v_source()); // { dg-error "" }
+ sink_1_5(cv_source()); // { dg-error "" }
return 0;
}
@@ -122,10 +122,10 @@ int test1_6()
const volatile A cva = a; // { dg-error "deleted" }
sink_1_6(a); // { dg-error "lvalue" }
sink_1_6(ca); // { dg-error "lvalue" }
- sink_1_6(va); // { dg-error "invalid initialization" }
- sink_1_6(cva); // { dg-error "invalid initialization" }
- sink_1_6(v_source()); // { dg-error "invalid initialization" }
- sink_1_6(cv_source()); // { dg-error "invalid initialization" }
+ sink_1_6(va); // { dg-error "" }
+ sink_1_6(cva); // { dg-error "" }
+ sink_1_6(v_source()); // { dg-error "" }
+ sink_1_6(cv_source()); // { dg-error "" }
return 0;
}
@@ -138,11 +138,11 @@ int test1_7()
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
sink_1_7(a); // { dg-error "lvalue" }
- sink_1_7(ca); // { dg-error "invalid initialization" }
+ sink_1_7(ca); // { dg-error "" }
sink_1_7(va); // { dg-error "lvalue" }
- sink_1_7(cva); // { dg-error "invalid initialization" }
- sink_1_7(c_source()); // { dg-error "invalid initialization" }
- sink_1_7(cv_source()); // { dg-error "invalid initialization" }
+ sink_1_7(cva); // { dg-error "" }
+ sink_1_7(c_source()); // { dg-error "" }
+ sink_1_7(cv_source()); // { dg-error "" }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv2n.C b/gcc/testsuite/g++.dg/cpp0x/rv2n.C
index 289cffb181c..9677f58982c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv2n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv2n.C
@@ -30,8 +30,8 @@ const volatile A cv_source();
// 2 at a time
-one sink_2_12( A&); // { dg-message "note|argument" }
-two sink_2_12(const A&); // { dg-message "note|argument" }
+one sink_2_12( A&);
+two sink_2_12(const A&);
int test2_12()
{
@@ -39,19 +39,15 @@ int test2_12()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_12(va); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 42 }
- sink_2_12(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 44 }
- sink_2_12(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 46 }
- sink_2_12(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 48 }
+ sink_2_12(va); // { dg-error "" }
+ sink_2_12(cva); // { dg-error "" }
+ sink_2_12(v_source()); // { dg-error "" }
+ sink_2_12(cv_source()); // { dg-error "" }
return 0;
}
-one sink_2_13( A&); // { dg-message "note|argument" }
-three sink_2_13(volatile A&); // { dg-message "note|argument" }
+one sink_2_13( A&);
+three sink_2_13(volatile A&);
int test2_13()
{
@@ -59,23 +55,17 @@ int test2_13()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_13(ca); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 62 }
- sink_2_13(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 64 }
- sink_2_13(source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 66 }
- sink_2_13(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 68 }
- sink_2_13(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 70 }
- sink_2_13(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 72 }
+ sink_2_13(ca); // { dg-error "" }
+ sink_2_13(cva); // { dg-error "" }
+ sink_2_13(source()); // { dg-error "" }
+ sink_2_13(c_source()); // { dg-error "" }
+ sink_2_13(v_source()); // { dg-error "" }
+ sink_2_13(cv_source()); // { dg-error "" }
return 0;
}
-one sink_2_14( A&); // { dg-message "note|argument" }
-four sink_2_14(const volatile A&); // { dg-message "note|argument" }
+one sink_2_14( A&);
+four sink_2_14(const volatile A&);
int test2_14()
{
@@ -83,19 +73,15 @@ int test2_14()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_14(source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 86 }
- sink_2_14(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 88 }
- sink_2_14(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 90 }
- sink_2_14(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 92 }
+ sink_2_14(source()); // { dg-error "" }
+ sink_2_14(c_source()); // { dg-error "" }
+ sink_2_14(v_source()); // { dg-error "" }
+ sink_2_14(cv_source()); // { dg-error "" }
return 0;
}
-one sink_2_15( A&); // { dg-message "note|argument" }
-five sink_2_15( A&&); // { dg-message "note|argument" }
+one sink_2_15( A&);
+five sink_2_15( A&&);
int test2_15()
{
@@ -103,23 +89,17 @@ int test2_15()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_15(ca); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 106 }
- sink_2_15(va); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 108 }
- sink_2_15(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 110 }
- sink_2_15(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 112 }
- sink_2_15(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 114 }
- sink_2_15(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 116 }
+ sink_2_15(ca); // { dg-error "" }
+ sink_2_15(va); // { dg-error "" }
+ sink_2_15(cva); // { dg-error "" }
+ sink_2_15(c_source()); // { dg-error "" }
+ sink_2_15(v_source()); // { dg-error "" }
+ sink_2_15(cv_source()); // { dg-error "" }
return 0;
}
-one sink_2_16( A&); // { dg-message "note|argument" }
-six sink_2_16(const A&&); // { dg-message "note|argument" }
+one sink_2_16( A&);
+six sink_2_16(const A&&);
int test2_16()
{
@@ -127,20 +107,16 @@ int test2_16()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_16(ca); // { dg-error "lvalue" }
- sink_2_16(va); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 131 }
- sink_2_16(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 133 }
- sink_2_16(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 135 }
- sink_2_16(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 137 }
+ sink_2_16(ca); // { dg-error "" }
+ sink_2_16(va); // { dg-error "" }
+ sink_2_16(cva); // { dg-error "" }
+ sink_2_16(v_source()); // { dg-error "" }
+ sink_2_16(cv_source()); // { dg-error "" }
return 0;
}
-one sink_2_17( A&); // { dg-message "note|argument" }
-seven sink_2_17(volatile A&&); // { dg-message "note|argument" }
+one sink_2_17( A&);
+seven sink_2_17(volatile A&&);
int test2_17()
{
@@ -148,20 +124,16 @@ int test2_17()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_17(ca); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 151 }
- sink_2_17(va); // { dg-error "lvalue" }
- sink_2_17(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 154 }
- sink_2_17(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 156 }
- sink_2_17(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 158 }
+ sink_2_17(ca); // { dg-error "" }
+ sink_2_17(va); // { dg-error "" }
+ sink_2_17(cva); // { dg-error "" }
+ sink_2_17(c_source()); // { dg-error "" }
+ sink_2_17(cv_source()); // { dg-error "" }
return 0;
}
one sink_2_18( A&);
-eight sink_2_18(const volatile A&&); // { dg-message "argument" }
+eight sink_2_18(const volatile A&&);
int test2_18()
{
@@ -169,13 +141,13 @@ int test2_18()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_18(ca); // { dg-error "lvalue" }
- sink_2_18(va); // { dg-error "lvalue" }
- sink_2_18(cva); // { dg-error "lvalue" }
+ sink_2_18(ca); // { dg-error "" }
+ sink_2_18(va); // { dg-error "" }
+ sink_2_18(cva); // { dg-error "" }
}
-two sink_2_23(const A&); // { dg-message "note|argument" }
-three sink_2_23(volatile A&); // { dg-message "note|argument" }
+two sink_2_23(const A&);
+three sink_2_23(volatile A&);
int test2_23()
{
@@ -184,18 +156,14 @@ int test2_23()
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
sink_2_23(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 186 }
- sink_2_23(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 188 }
- sink_2_23(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 190 }
- sink_2_23(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 192 }
+ sink_2_23(cva); // { dg-error "" }
+ sink_2_23(v_source()); // { dg-error "" }
+ sink_2_23(cv_source()); // { dg-error "" }
return 0;
}
-two sink_2_24(const A&); // { dg-message "note|argument" }
-four sink_2_24(const volatile A&); // { dg-message "note|argument" }
+two sink_2_24(const A&);
+four sink_2_24(const volatile A&);
int test2_24()
{
@@ -203,15 +171,13 @@ int test2_24()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_24(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 206 }
- sink_2_24(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 208 }
+ sink_2_24(v_source()); // { dg-error "" }
+ sink_2_24(cv_source()); // { dg-error "" }
return 0;
}
-three sink_2_34(volatile A&); // { dg-message "three sink_2_34|no known conversion" }
-four sink_2_34(const volatile A&); // { dg-message "note|argument" }
+three sink_2_34(volatile A&);
+four sink_2_34(const volatile A&);
int test2_34()
{
@@ -219,19 +185,15 @@ int test2_34()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_34(source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 222 }
- sink_2_34(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 224 }
- sink_2_34(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 226 }
- sink_2_34(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 228 }
+ sink_2_34(source()); // { dg-error "" }
+ sink_2_34(c_source()); // { dg-error "" }
+ sink_2_34(v_source()); // { dg-error "" }
+ sink_2_34(cv_source()); // { dg-error "" }
return 0;
}
-two sink_2_25(const A&); // { dg-message "two sink_2_25|no known conversion" }
-five sink_2_25( A&&); // { dg-message "note|argument" }
+two sink_2_25(const A&);
+five sink_2_25( A&&);
int test2_25()
{
@@ -239,19 +201,15 @@ int test2_25()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_25(va); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 242 }
- sink_2_25(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 244 }
- sink_2_25(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 246 }
- sink_2_25(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 248 }
+ sink_2_25(va); // { dg-error "" }
+ sink_2_25(cva); // { dg-error "" }
+ sink_2_25(v_source()); // { dg-error "" }
+ sink_2_25(cv_source()); // { dg-error "" }
return 0;
}
-two sink_2_26(const A&); // { dg-message "two sink_2_26|no known conversion" }
-six sink_2_26(const A&&); // { dg-message "note|argument" }
+two sink_2_26(const A&);
+six sink_2_26(const A&&);
int test2_26()
{
@@ -259,19 +217,15 @@ int test2_26()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_26(va); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 262 }
- sink_2_26(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 264 }
- sink_2_26(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 266 }
- sink_2_26(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 268 }
+ sink_2_26(va); // { dg-error "" }
+ sink_2_26(cva); // { dg-error "" }
+ sink_2_26(v_source()); // { dg-error "" }
+ sink_2_26(cv_source()); // { dg-error "" }
return 0;
}
-two sink_2_27(const A&); // { dg-message "two sink_2_27|no known conversion" }
-seven sink_2_27(volatile A&&); // { dg-message "note|argument" }
+two sink_2_27(const A&);
+seven sink_2_27(volatile A&&);
int test2_27()
{
@@ -279,16 +233,14 @@ int test2_27()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_27(va); // { dg-error "lvalue" }
- sink_2_27(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 283 }
- sink_2_27(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 285 }
+ sink_2_27(va); // { dg-error "" }
+ sink_2_27(cva); // { dg-error "" }
+ sink_2_27(cv_source()); // { dg-error "" }
return 0;
}
two sink_2_28(const A&);
-eight sink_2_28(const volatile A&&); // { dg-message "argument" }
+eight sink_2_28(const volatile A&&);
int test2_28()
{
@@ -296,12 +248,12 @@ int test2_28()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_28(va); // { dg-error "lvalue" }
- sink_2_28(cva); // { dg-error "lvalue" }
+ sink_2_28(va); // { dg-error "" }
+ sink_2_28(cva); // { dg-error "" }
}
-three sink_2_35(volatile A&); // { dg-message "three sink_2_35|no known conversion" }
-five sink_2_35( A&&); // { dg-message "note|argument" }
+three sink_2_35(volatile A&);
+five sink_2_35( A&&);
int test2_35()
{
@@ -309,21 +261,16 @@ int test2_35()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_35(ca); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 312 }
- sink_2_35(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 314 }
- sink_2_35(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 316 }
- sink_2_35(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 318 }
- sink_2_35(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 320 }
+ sink_2_35(ca); // { dg-error "" }
+ sink_2_35(cva); // { dg-error "" }
+ sink_2_35(c_source()); // { dg-error "" }
+ sink_2_35(v_source()); // { dg-error "" }
+ sink_2_35(cv_source()); // { dg-error "" }
return 0;
}
-three sink_2_36(volatile A&); // { dg-message "three sink_2_36|no known conversion" }
-six sink_2_36(const A&&); // { dg-message "note|argument" }
+three sink_2_36(volatile A&);
+six sink_2_36(const A&&);
int test2_36()
{
@@ -331,18 +278,15 @@ int test2_36()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_36(ca); // { dg-error "lvalue" }
- sink_2_36(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 335 }
- sink_2_36(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 337 }
- sink_2_36(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 339 }
+ sink_2_36(ca); // { dg-error "" }
+ sink_2_36(cva); // { dg-error "" }
+ sink_2_36(v_source()); // { dg-error "" }
+ sink_2_36(cv_source()); // { dg-error "" }
return 0;
}
-three sink_2_37(volatile A&); // { dg-message "three sink_2_37|no known conversion" }
-seven sink_2_37(volatile A&&); // { dg-message "note|argument" }
+three sink_2_37(volatile A&);
+seven sink_2_37(volatile A&&);
int test2_37()
{
@@ -350,19 +294,15 @@ int test2_37()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_37(ca); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 353 }
- sink_2_37(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 355 }
- sink_2_37(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 357 }
- sink_2_37(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 359 }
+ sink_2_37(ca); // { dg-error "" }
+ sink_2_37(cva); // { dg-error "" }
+ sink_2_37(c_source()); // { dg-error "" }
+ sink_2_37(cv_source()); // { dg-error "" }
return 0;
}
three sink_2_38(volatile A&);
-eight sink_2_38(const volatile A&&); // { dg-message "argument" }
+eight sink_2_38(const volatile A&&);
int test2_38()
{
@@ -370,12 +310,12 @@ int test2_38()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_38(ca); // { dg-error "lvalue" }
- sink_2_38(cva); // { dg-error "lvalue" }
+ sink_2_38(ca); // { dg-error "" }
+ sink_2_38(cva); // { dg-error "" }
}
-four sink_2_45(const volatile A&); // { dg-message "note" }
-five sink_2_45( A&&); // { dg-message "note|argument" }
+four sink_2_45(const volatile A&);
+five sink_2_45( A&&);
int test2_45()
{
@@ -383,17 +323,14 @@ int test2_45()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_45(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 386 }
- sink_2_45(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 388 }
- sink_2_45(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 390 }
+ sink_2_45(c_source()); // { dg-error "" }
+ sink_2_45(v_source()); // { dg-error "" }
+ sink_2_45(cv_source()); // { dg-error "" }
return 0;
}
-four sink_2_46(const volatile A&); // { dg-message "note" }
-six sink_2_46(const A&&); // { dg-message "note|argument" }
+four sink_2_46(const volatile A&);
+six sink_2_46(const A&&);
int test2_46()
{
@@ -401,15 +338,13 @@ int test2_46()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_46(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 404 }
- sink_2_46(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 406 }
+ sink_2_46(v_source()); // { dg-error "" }
+ sink_2_46(cv_source()); // { dg-error "" }
return 0;
}
-four sink_2_47(const volatile A&); // { dg-message "note" }
-seven sink_2_47(volatile A&&); // { dg-message "note|argument" }
+four sink_2_47(const volatile A&);
+seven sink_2_47(volatile A&&);
int test2_47()
{
@@ -417,15 +352,13 @@ int test2_47()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_47(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 420 }
- sink_2_47(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 422 }
+ sink_2_47(c_source()); // { dg-error "" }
+ sink_2_47(cv_source()); // { dg-error "" }
return 0;
}
-five sink_2_56( A&&); // { dg-message "note|argument" }
-six sink_2_56(const A&&); // { dg-message "note|argument" }
+five sink_2_56( A&&);
+six sink_2_56(const A&&);
int test2_56()
{
@@ -433,21 +366,17 @@ int test2_56()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_56(a); // { dg-error "lvalue" }
- sink_2_56(ca); // { dg-error "lvalue" }
- sink_2_56(va); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 438 }
- sink_2_56(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 440 }
- sink_2_56(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 442 }
- sink_2_56(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 444 }
+ sink_2_56(a); // { dg-error "" }
+ sink_2_56(ca); // { dg-error "" }
+ sink_2_56(va); // { dg-error "" }
+ sink_2_56(cva); // { dg-error "" }
+ sink_2_56(v_source()); // { dg-error "" }
+ sink_2_56(cv_source()); // { dg-error "" }
return 0;
}
-five sink_2_57( A&&); // { dg-message "note|argument" }
-seven sink_2_57(volatile A&&); // { dg-message "note|argument" }
+five sink_2_57( A&&);
+seven sink_2_57(volatile A&&);
int test2_57()
{
@@ -455,21 +384,17 @@ int test2_57()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_57(a); // { dg-error "lvalue" }
- sink_2_57(va); // { dg-error "lvalue" }
- sink_2_57(ca); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 460 }
- sink_2_57(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 462 }
- sink_2_57(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 464 }
- sink_2_57(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 466 }
+ sink_2_57(a); // { dg-error "" }
+ sink_2_57(va); // { dg-error "" }
+ sink_2_57(ca); // { dg-error "" }
+ sink_2_57(cva); // { dg-error "" }
+ sink_2_57(c_source()); // { dg-error "" }
+ sink_2_57(cv_source()); // { dg-error "" }
return 0;
}
-five sink_2_58( A&&); // { dg-message "argument" }
-eight sink_2_58(const volatile A&&); // { dg-message "argument" }
+five sink_2_58( A&&);
+eight sink_2_58(const volatile A&&);
int test2_58()
{
@@ -477,14 +402,14 @@ int test2_58()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_58(a); // { dg-error "lvalue" }
- sink_2_58(ca); // { dg-error "lvalue" }
- sink_2_58(va); // { dg-error "lvalue" }
- sink_2_58(cva); // { dg-error "lvalue" }
+ sink_2_58(a); // { dg-error "" }
+ sink_2_58(ca); // { dg-error "" }
+ sink_2_58(va); // { dg-error "" }
+ sink_2_58(cva); // { dg-error "" }
}
-six sink_2_67(const A&&); // { dg-message "note|argument" }
-seven sink_2_67(volatile A&&); // { dg-message "note|argument" }
+six sink_2_67(const A&&);
+seven sink_2_67(volatile A&&);
int test2_67()
{
@@ -492,21 +417,17 @@ int test2_67()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_67(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 495 }
- sink_2_67(ca); // { dg-error "lvalue" }
- sink_2_67(va); // { dg-error "lvalue" }
- sink_2_67(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 499 }
- sink_2_67(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 501 }
- sink_2_67(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 503 }
+ sink_2_67(a); // { dg-error "" }
+ sink_2_67(ca); // { dg-error "" }
+ sink_2_67(va); // { dg-error "" }
+ sink_2_67(cva); // { dg-error "" }
+ sink_2_67(source()); // { dg-error "" }
+ sink_2_67(cv_source()); // { dg-error "" }
return 0;
}
-six sink_2_68(const A&&); // { dg-message "argument" }
-eight sink_2_68(const volatile A&&); // { dg-message "argument" }
+six sink_2_68(const A&&);
+eight sink_2_68(const volatile A&&);
int test2_68()
{
@@ -514,14 +435,14 @@ int test2_68()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_68(a); // { dg-error "lvalue" }
- sink_2_68(ca); // { dg-error "lvalue" }
- sink_2_68(va); // { dg-error "lvalue" }
- sink_2_68(cva); // { dg-error "lvalue" }
+ sink_2_68(a); // { dg-error "" }
+ sink_2_68(ca); // { dg-error "" }
+ sink_2_68(va); // { dg-error "" }
+ sink_2_68(cva); // { dg-error "" }
}
-seven sink_2_78(volatile A&&); // { dg-message "argument" }
-eight sink_2_78(const volatile A&&); // { dg-message "argument" }
+seven sink_2_78(volatile A&&);
+eight sink_2_78(const volatile A&&);
int test2_78()
{
@@ -529,10 +450,10 @@ int test2_78()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_2_78(a); // { dg-error "lvalue" }
- sink_2_78(ca); // { dg-error "lvalue" }
- sink_2_78(va); // { dg-error "lvalue" }
- sink_2_78(cva); // { dg-error "lvalue" }
+ sink_2_78(a); // { dg-error "" }
+ sink_2_78(ca); // { dg-error "" }
+ sink_2_78(va); // { dg-error "" }
+ sink_2_78(cva); // { dg-error "" }
}
int main()
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv3n.C b/gcc/testsuite/g++.dg/cpp0x/rv3n.C
index 765dfbc7f22..8a1730b61ef 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv3n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv3n.C
@@ -30,9 +30,9 @@ const volatile A cv_source();
// 3 at a time
-one sink_3_123( A&); // { dg-message "one sink_3_123|no known conversion" }
-two sink_3_123(const A&); // { dg-message "two sink_3_123|no known conversion" }
-three sink_3_123(volatile A&); // { dg-message "three sink_3_123|no known conversion" }
+one sink_3_123( A&);
+two sink_3_123(const A&);
+three sink_3_123(volatile A&);
int test3_123()
{
@@ -40,22 +40,19 @@ int test3_123()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_123(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 43 }
- sink_3_123(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 45 }
- sink_3_123(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 47 }
+ sink_3_123(cva); // { dg-error "" }
+ sink_3_123(v_source()); // { dg-error "" }
+ sink_3_123(cv_source()); // { dg-error "" }
return 0;
}
-one sink_3_125( A&); // { dg-message "one sink_3_125|no known conversion" }
-two sink_3_125(const A&); // { dg-message "two sink_3_125|no known conversion" }
-five sink_3_125( A&&); // { dg-message "five sink_3_125|no known conversion" }
+one sink_3_125( A&);
+two sink_3_125(const A&);
+five sink_3_125( A&&);
-one sink_3_124( A&); // { dg-message "one sink_3_124|no known conversion" }
-two sink_3_124(const A&); // { dg-message "two sink_3_124|no known conversion" }
-four sink_3_124(const volatile A&); // { dg-message "four sink_3_124|no known conversion" }
+one sink_3_124( A&);
+two sink_3_124(const A&);
+four sink_3_124(const volatile A&);
int test3_124()
{
@@ -63,10 +60,8 @@ int test3_124()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_124(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 66 }
- sink_3_124(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 68 }
+ sink_3_124(v_source()); // { dg-error "" }
+ sink_3_124(cv_source()); // { dg-error "" }
return 0;
}
@@ -76,20 +71,16 @@ int test3_125()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_125(va); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 79 }
- sink_3_125(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 81 }
- sink_3_125(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 83 }
- sink_3_125(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 85 }
+ sink_3_125(va); // { dg-error "" }
+ sink_3_125(cva); // { dg-error "" }
+ sink_3_125(v_source()); // { dg-error "" }
+ sink_3_125(cv_source()); // { dg-error "" }
return 0;
}
-one sink_3_126( A&); // { dg-message "one sink_3_126|no known conversion" }
-two sink_3_126(const A&); // { dg-message "two sink_3_126|no known conversion" }
-six sink_3_126(const A&&); // { dg-message "six sink_3_126|no known conversion" }
+one sink_3_126( A&);
+two sink_3_126(const A&);
+six sink_3_126(const A&&);
int test3_126()
{
@@ -97,20 +88,16 @@ int test3_126()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_126(va); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 100 }
- sink_3_126(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 102 }
- sink_3_126(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 104 }
- sink_3_126(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 106 }
+ sink_3_126(va); // { dg-error "" }
+ sink_3_126(cva); // { dg-error "" }
+ sink_3_126(v_source()); // { dg-error "" }
+ sink_3_126(cv_source()); // { dg-error "" }
return 0;
}
-one sink_3_127( A&); // { dg-message "one sink_3_127|no known conversion" }
-two sink_3_127(const A&); // { dg-message "two sink_3_127|no known conversion" }
-seven sink_3_127(volatile A&&); // { dg-message "seven sink_3_127|no known conversion" }
+one sink_3_127( A&);
+two sink_3_127(const A&);
+seven sink_3_127(volatile A&&);
int test3_127()
{
@@ -118,17 +105,15 @@ int test3_127()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_127(va); // { dg-error "lvalue" }
- sink_3_127(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 122 }
- sink_3_127(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 124 }
+ sink_3_127(va); // { dg-error "" }
+ sink_3_127(cva); // { dg-error "" }
+ sink_3_127(cv_source()); // { dg-error "" }
return 0;
}
one sink_3_128( A&);
two sink_3_128(const A&);
-eight sink_3_128(const volatile A&&); // { dg-message "" }
+eight sink_3_128(const volatile A&&);
int test3_128()
{
@@ -137,13 +122,13 @@ int test3_128()
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_128(va); // { dg-error "lvalue" }
- sink_3_128(cva); // { dg-error "lvalue" }
+ sink_3_128(va); // { dg-error "" }
+ sink_3_128(cva); // { dg-error "" }
}
-one sink_3_134( A&); // { dg-message "one sink_3_134|no known conversion" }
-three sink_3_134(volatile A&); // { dg-message "three sink_3_134|no known conversion" }
-four sink_3_134(const volatile A&); // { dg-message "four sink_3_134|no known conversion" }
+one sink_3_134( A&);
+three sink_3_134(volatile A&);
+four sink_3_134(const volatile A&);
int test3_134()
{
@@ -151,20 +136,16 @@ int test3_134()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_134(source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 154 }
- sink_3_134(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 156 }
- sink_3_134(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 158 }
- sink_3_134(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 160 }
+ sink_3_134(source()); // { dg-error "" }
+ sink_3_134(c_source()); // { dg-error "" }
+ sink_3_134(v_source()); // { dg-error "" }
+ sink_3_134(cv_source()); // { dg-error "" }
return 0;
}
-one sink_3_135( A&); // { dg-message "one sink_3_135|no known conversion" }
-three sink_3_135(volatile A&); // { dg-message "three sink_3_135|no known conversion" }
-five sink_3_135( A&&); // { dg-message "five sink_3_135|no known conversion" }
+one sink_3_135( A&);
+three sink_3_135(volatile A&);
+five sink_3_135( A&&);
int test3_135()
{
@@ -172,22 +153,17 @@ int test3_135()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_135(ca); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 175 }
- sink_3_135(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 177 }
- sink_3_135(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 179 }
- sink_3_135(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 181 }
- sink_3_135(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 183 }
+ sink_3_135(ca); // { dg-error "" }
+ sink_3_135(cva); // { dg-error "" }
+ sink_3_135(c_source()); // { dg-error "" }
+ sink_3_135(v_source()); // { dg-error "" }
+ sink_3_135(cv_source()); // { dg-error "" }
return 0;
}
-one sink_3_136( A&); // { dg-message "one sink_3_136|no known conversion" }
-three sink_3_136(volatile A&); // { dg-message "note" }
-six sink_3_136(const A&&); // { dg-message "" }
+one sink_3_136( A&);
+three sink_3_136(volatile A&);
+six sink_3_136(const A&&);
int test3_136()
{
@@ -195,19 +171,16 @@ int test3_136()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_136(ca); // { dg-error "lvalue" }
- sink_3_136(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 199 }
- sink_3_136(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 201 }
- sink_3_136(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 203 }
+ sink_3_136(ca); // { dg-error "" }
+ sink_3_136(cva); // { dg-error "" }
+ sink_3_136(v_source()); // { dg-error "" }
+ sink_3_136(cv_source()); // { dg-error "" }
return 0;
}
-one sink_3_137( A&); // { dg-message "one sink_3_137|no known conversion" }
-three sink_3_137(volatile A&); // { dg-message "note" }
-seven sink_3_137(volatile A&&); // { dg-message "note" }
+one sink_3_137( A&);
+three sink_3_137(volatile A&);
+seven sink_3_137(volatile A&&);
int test3_137()
{
@@ -215,20 +188,16 @@ int test3_137()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_137(ca); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 218 }
- sink_3_137(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 220 }
- sink_3_137(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 222 }
- sink_3_137(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 224 }
+ sink_3_137(ca); // { dg-error "" }
+ sink_3_137(cva); // { dg-error "" }
+ sink_3_137(c_source()); // { dg-error "" }
+ sink_3_137(cv_source()); // { dg-error "" }
return 0;
}
one sink_3_138( A&);
three sink_3_138(volatile A&);
-eight sink_3_138(const volatile A&&); // { dg-message "" }
+eight sink_3_138(const volatile A&&);
int test3_138()
{
@@ -236,14 +205,14 @@ int test3_138()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_138(ca); // { dg-error "lvalue" }
- sink_3_138(cva); // { dg-error "lvalue" }
+ sink_3_138(ca); // { dg-error "" }
+ sink_3_138(cva); // { dg-error "" }
return 0;
}
-one sink_3_145( A&); // { dg-message "one sink_3_145|no known conversion" }
-four sink_3_145(const volatile A&); // { dg-message "note" }
-five sink_3_145( A&&); // { dg-message "note" }
+one sink_3_145( A&);
+four sink_3_145(const volatile A&);
+five sink_3_145( A&&);
int test3_145()
{
@@ -251,18 +220,15 @@ int test3_145()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_145(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 254 }
- sink_3_145(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 256 }
- sink_3_145(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 258 }
+ sink_3_145(c_source()); // { dg-error "" }
+ sink_3_145(v_source()); // { dg-error "" }
+ sink_3_145(cv_source()); // { dg-error "" }
return 0;
}
-one sink_3_146( A&); // { dg-message "one sink_3_146|no known conversion" }
-four sink_3_146(const volatile A&); // { dg-message "note" }
-six sink_3_146(const A&&); // { dg-message "note" }
+one sink_3_146( A&);
+four sink_3_146(const volatile A&);
+six sink_3_146(const A&&);
int test3_146()
{
@@ -270,16 +236,14 @@ int test3_146()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_146(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 273 }
- sink_3_146(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 275 }
+ sink_3_146(v_source()); // { dg-error "" }
+ sink_3_146(cv_source()); // { dg-error "" }
return 0;
}
-one sink_3_147( A&); // { dg-message "one sink_3_147|no known conversion" }
-four sink_3_147(const volatile A&); // { dg-message "note" }
-seven sink_3_147(volatile A&&); // { dg-message "note" }
+one sink_3_147( A&);
+four sink_3_147(const volatile A&);
+seven sink_3_147(volatile A&&);
int test3_147()
{
@@ -287,16 +251,14 @@ int test3_147()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_147(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 290 }
- sink_3_147(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 292 }
+ sink_3_147(c_source()); // { dg-error "" }
+ sink_3_147(cv_source()); // { dg-error "" }
return 0;
}
-one sink_3_156( A&); // { dg-message "one sink_3_156|no known conversion" }
-five sink_3_156( A&&); // { dg-message "note" }
-six sink_3_156(const A&&); // { dg-message "" }
+one sink_3_156( A&);
+five sink_3_156( A&&);
+six sink_3_156(const A&&);
int test3_156()
{
@@ -304,21 +266,17 @@ int test3_156()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_156(ca); // { dg-error "lvalue" }
- sink_3_156(va); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 308 }
- sink_3_156(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 310 }
- sink_3_156(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 312 }
- sink_3_156(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 314 }
+ sink_3_156(ca); // { dg-error "" }
+ sink_3_156(va); // { dg-error "" }
+ sink_3_156(cva); // { dg-error "" }
+ sink_3_156(v_source()); // { dg-error "" }
+ sink_3_156(cv_source()); // { dg-error "" }
return 0;
}
-one sink_3_157( A&); // { dg-message "one sink_3_157|no known conversion" }
-five sink_3_157( A&&); // { dg-message "note" }
-seven sink_3_157(volatile A&&); // { dg-message "" }
+one sink_3_157( A&);
+five sink_3_157( A&&);
+seven sink_3_157(volatile A&&);
int test3_157()
{
@@ -326,21 +284,17 @@ int test3_157()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_157(ca); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 329 }
- sink_3_157(va); // { dg-error "lvalue" }
- sink_3_157(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 332 }
- sink_3_157(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 334 }
- sink_3_157(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 336 }
+ sink_3_157(ca); // { dg-error "" }
+ sink_3_157(va); // { dg-error "" }
+ sink_3_157(cva); // { dg-error "" }
+ sink_3_157(c_source()); // { dg-error "" }
+ sink_3_157(cv_source()); // { dg-error "" }
return 0;
}
one sink_3_158( A&);
five sink_3_158( A&&);
-eight sink_3_158(const volatile A&&); // { dg-message "" }
+eight sink_3_158(const volatile A&&);
int test3_158()
{
@@ -348,15 +302,15 @@ int test3_158()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_158(ca); // { dg-error "lvalue" }
- sink_3_158(va); // { dg-error "lvalue" }
- sink_3_158(cva); // { dg-error "lvalue" }
+ sink_3_158(ca); // { dg-error "" }
+ sink_3_158(va); // { dg-error "" }
+ sink_3_158(cva); // { dg-error "" }
return 0;
}
-one sink_3_167( A&); // { dg-message "one sink_3_167|no known conversion" }
-six sink_3_167(const A&&); // { dg-message "" }
-seven sink_3_167(volatile A&&); // { dg-message "" }
+one sink_3_167( A&);
+six sink_3_167(const A&&);
+seven sink_3_167(volatile A&&);
int test3_167()
{
@@ -364,20 +318,17 @@ int test3_167()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_167(ca); // { dg-error "lvalue" }
- sink_3_167(va); // { dg-error "lvalue" }
- sink_3_167(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 369 }
- sink_3_167(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 371 }
- sink_3_167(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 373 }
+ sink_3_167(ca); // { dg-error "" }
+ sink_3_167(va); // { dg-error "" }
+ sink_3_167(cva); // { dg-error "" }
+ sink_3_167(source()); // { dg-error "" }
+ sink_3_167(cv_source()); // { dg-error "" }
return 0;
}
one sink_3_168( A&);
-six sink_3_168(const A&&); // { dg-message "" }
-eight sink_3_168(const volatile A&&); // { dg-message "" }
+six sink_3_168(const A&&);
+eight sink_3_168(const volatile A&&);
int test3_168()
{
@@ -385,15 +336,15 @@ int test3_168()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_168(ca); // { dg-error "lvalue" }
- sink_3_168(va); // { dg-error "lvalue" }
- sink_3_168(cva); // { dg-error "lvalue" }
+ sink_3_168(ca); // { dg-error "" }
+ sink_3_168(va); // { dg-error "" }
+ sink_3_168(cva); // { dg-error "" }
return 0;
}
one sink_3_178( A&);
-seven sink_3_178(volatile A&&); // { dg-message "" }
-eight sink_3_178(const volatile A&&); // { dg-message "" }
+seven sink_3_178(volatile A&&);
+eight sink_3_178(const volatile A&&);
int test3_178()
{
@@ -401,15 +352,15 @@ int test3_178()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_178(ca); // { dg-error "lvalue" }
- sink_3_178(va); // { dg-error "lvalue" }
- sink_3_178(cva); // { dg-error "lvalue" }
+ sink_3_178(ca); // { dg-error "" }
+ sink_3_178(va); // { dg-error "" }
+ sink_3_178(cva); // { dg-error "" }
return 0;
}
-two sink_3_234(const A&); // { dg-message "two sink_3_234|no known conversion" }
-three sink_3_234(volatile A&); // { dg-message "note" }
-four sink_3_234(const volatile A&); // { dg-message "note" }
+two sink_3_234(const A&);
+three sink_3_234(volatile A&);
+four sink_3_234(const volatile A&);
int test3_234()
{
@@ -417,18 +368,15 @@ int test3_234()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_234(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 420 }
- sink_3_234(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 422 }
- sink_3_234(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 424 }
+ sink_3_234(a); // { dg-error "" }
+ sink_3_234(v_source()); // { dg-error "" }
+ sink_3_234(cv_source()); // { dg-error "" }
return 0;
}
-two sink_3_235(const A&); // { dg-message "two sink_3_235|no known conversion" }
-three sink_3_235(volatile A&); // { dg-message "note" }
-five sink_3_235( A&&); // { dg-message "note" }
+two sink_3_235(const A&);
+three sink_3_235(volatile A&);
+five sink_3_235( A&&);
int test3_235()
{
@@ -436,20 +384,16 @@ int test3_235()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_235(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 439 }
- sink_3_235(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 441 }
- sink_3_235(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 443 }
- sink_3_235(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 445 }
+ sink_3_235(a); // { dg-error "" }
+ sink_3_235(cva); // { dg-error "" }
+ sink_3_235(v_source()); // { dg-error "" }
+ sink_3_235(cv_source()); // { dg-error "" }
return 0;
}
-two sink_3_236(const A&); // { dg-message "two sink_3_236|no known conversion" }
-three sink_3_236(volatile A&); // { dg-message "note" }
-six sink_3_236(const A&&); // { dg-message "note" }
+two sink_3_236(const A&);
+three sink_3_236(volatile A&);
+six sink_3_236(const A&&);
int test3_236()
{
@@ -457,20 +401,16 @@ int test3_236()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_236(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 460 }
- sink_3_236(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 462 }
- sink_3_236(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 464 }
- sink_3_236(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 466 }
+ sink_3_236(a); // { dg-error "" }
+ sink_3_236(cva); // { dg-error "" }
+ sink_3_236(v_source()); // { dg-error "" }
+ sink_3_236(cv_source()); // { dg-error "" }
return 0;
}
-two sink_3_237(const A&); // { dg-message "two sink_3_237|no known conversion" }
-three sink_3_237(volatile A&); // { dg-message "note" }
-seven sink_3_237(volatile A&&); // { dg-message "note" }
+two sink_3_237(const A&);
+three sink_3_237(volatile A&);
+seven sink_3_237(volatile A&&);
int test3_237()
{
@@ -478,18 +418,15 @@ int test3_237()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_237(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 481 }
- sink_3_237(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 483 }
- sink_3_237(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 485 }
+ sink_3_237(a); // { dg-error "" }
+ sink_3_237(cva); // { dg-error "" }
+ sink_3_237(cv_source()); // { dg-error "" }
return 0;
}
-two sink_3_238(const A&); // { dg-message "two sink_3_238|no known conversion" }
-three sink_3_238(volatile A&); // { dg-message "three sink_3_238|no known conversion" }
-eight sink_3_238(const volatile A&&); // { dg-message "eight sink_3_238|no known conversion" }
+two sink_3_238(const A&);
+three sink_3_238(volatile A&);
+eight sink_3_238(const volatile A&&);
int test3_238()
{
@@ -497,15 +434,14 @@ int test3_238()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_238(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 500 }
- sink_3_238(cva); // { dg-error "lvalue" }
+ sink_3_238(a); // { dg-error "" }
+ sink_3_238(cva); // { dg-error "" }
return 0;
}
-two sink_3_245(const A&); // { dg-message "two sink_3_245|no known conversion" }
-four sink_3_245(const volatile A&); // { dg-message "four sink_3_245|no known conversion" }
-five sink_3_245( A&&); // { dg-message "five sink_3_245|no known conversion" }
+two sink_3_245(const A&);
+four sink_3_245(const volatile A&);
+five sink_3_245( A&&);
int test3_245()
{
@@ -513,16 +449,14 @@ int test3_245()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_245(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 516 }
- sink_3_245(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 518 }
+ sink_3_245(v_source()); // { dg-error "" }
+ sink_3_245(cv_source()); // { dg-error "" }
return 0;
}
-two sink_3_246(const A&); // { dg-message "two sink_3_246|no known conversion" }
-four sink_3_246(const volatile A&); // { dg-message "four sink_3_246|no known conversion" }
-six sink_3_246(const A&&); // { dg-message "six sink_3_246|no known conversion" }
+two sink_3_246(const A&);
+four sink_3_246(const volatile A&);
+six sink_3_246(const A&&);
int test3_246()
{
@@ -530,16 +464,14 @@ int test3_246()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_246(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 533 }
- sink_3_246(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 535 }
+ sink_3_246(v_source()); // { dg-error "" }
+ sink_3_246(cv_source()); // { dg-error "" }
return 0;
}
-two sink_3_247(const A&); // { dg-message "two sink_3_247|no known conversion" }
-four sink_3_247(const volatile A&); // { dg-message "four sink_3_247|no known conversion" }
-seven sink_3_247(volatile A&&); // { dg-message "seven sink_3_247|no known conversion" }
+two sink_3_247(const A&);
+four sink_3_247(const volatile A&);
+seven sink_3_247(volatile A&&);
int test3_247()
{
@@ -547,14 +479,13 @@ int test3_247()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_247(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 550 }
+ sink_3_247(cv_source()); // { dg-error "" }
return 0;
}
-two sink_3_256(const A&); // { dg-message "two sink_3_256|no known conversion" }
-five sink_3_256( A&&); // { dg-message "five sink_3_256|no known conversion" }
-six sink_3_256(const A&&); // { dg-message "six sink_3_256|no known conversion" }
+two sink_3_256(const A&);
+five sink_3_256( A&&);
+six sink_3_256(const A&&);
int test3_256()
{
@@ -562,20 +493,16 @@ int test3_256()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_256(va); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 565 }
- sink_3_256(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 567 }
- sink_3_256(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 569 }
- sink_3_256(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 571 }
+ sink_3_256(va); // { dg-error "" }
+ sink_3_256(cva); // { dg-error "" }
+ sink_3_256(v_source()); // { dg-error "" }
+ sink_3_256(cv_source()); // { dg-error "" }
return 0;
}
-two sink_3_257(const A&); // { dg-message "two sink_3_257|no known conversion" }
-five sink_3_257( A&&); // { dg-message "five sink_3_257|no known conversion" }
-seven sink_3_257(volatile A&&); // { dg-message "seven sink_3_257|no known conversion" }
+two sink_3_257(const A&);
+five sink_3_257( A&&);
+seven sink_3_257(volatile A&&);
int test3_257()
{
@@ -583,17 +510,15 @@ int test3_257()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_257(va); // { dg-error "lvalue" }
- sink_3_257(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 587 }
- sink_3_257(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 589 }
+ sink_3_257(va); // { dg-error "" }
+ sink_3_257(cva); // { dg-error "" }
+ sink_3_257(cv_source()); // { dg-error "" }
return 0;
}
two sink_3_258(const A&);
five sink_3_258( A&&);
-eight sink_3_258(const volatile A&&); // { dg-message "" }
+eight sink_3_258(const volatile A&&);
int test3_258()
{
@@ -601,14 +526,14 @@ int test3_258()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_258(va); // { dg-error "lvalue" }
- sink_3_258(cva); // { dg-error "lvalue" }
+ sink_3_258(va); // { dg-error "" }
+ sink_3_258(cva); // { dg-error "" }
return 0;
}
-two sink_3_267(const A&); // { dg-message "two sink_3_267|no known conversion" }
-six sink_3_267(const A&&); // { dg-message "six sink_3_267|no known conversion" }
-seven sink_3_267(volatile A&&); // { dg-message "seven sink_3_267|no known conversion" }
+two sink_3_267(const A&);
+six sink_3_267(const A&&);
+seven sink_3_267(volatile A&&);
int test3_267()
{
@@ -616,19 +541,16 @@ int test3_267()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_267(va); // { dg-error "lvalue" }
- sink_3_267(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 620 }
- sink_3_267(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 622 }
- sink_3_267(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 624 }
+ sink_3_267(va); // { dg-error "" }
+ sink_3_267(cva); // { dg-error "" }
+ sink_3_267(source()); // { dg-error "" }
+ sink_3_267(cv_source()); // { dg-error "" }
return 0;
}
two sink_3_268(const A&);
six sink_3_268(const A&&);
-eight sink_3_268(const volatile A&&); // { dg-message "" }
+eight sink_3_268(const volatile A&&);
int test3_268()
{
@@ -636,14 +558,14 @@ int test3_268()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_268(va); // { dg-error "lvalue" }
- sink_3_268(cva); // { dg-error "lvalue" }
+ sink_3_268(va); // { dg-error "" }
+ sink_3_268(cva); // { dg-error "" }
return 0;
}
two sink_3_278(const A&);
-seven sink_3_278(volatile A&&); // { dg-message "" }
-eight sink_3_278(const volatile A&&); // { dg-message "" }
+seven sink_3_278(volatile A&&);
+eight sink_3_278(const volatile A&&);
int test3_278()
{
@@ -651,14 +573,14 @@ int test3_278()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_278(va); // { dg-error "lvalue" }
- sink_3_278(cva); // { dg-error "lvalue" }
+ sink_3_278(va); // { dg-error "" }
+ sink_3_278(cva); // { dg-error "" }
return 0;
}
-three sink_3_345(volatile A&); // { dg-message "three sink_3_345|no known conversion" }
-four sink_3_345(const volatile A&); // { dg-message "four sink_3_345|no known conversion" }
-five sink_3_345( A&&); // { dg-message "five sink_3_345|no known conversion" }
+three sink_3_345(volatile A&);
+four sink_3_345(const volatile A&);
+five sink_3_345( A&&);
int test3_345()
{
@@ -666,18 +588,15 @@ int test3_345()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_345(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 669 }
- sink_3_345(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 671 }
- sink_3_345(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 673 }
+ sink_3_345(c_source()); // { dg-error "" }
+ sink_3_345(v_source()); // { dg-error "" }
+ sink_3_345(cv_source()); // { dg-error "" }
return 0;
}
-three sink_3_346(volatile A&); // { dg-message "three sink_3_346|no known conversion" }
-four sink_3_346(const volatile A&); // { dg-message "four sink_3_346|no known conversion" }
-six sink_3_346(const A&&); // { dg-message "six sink_3_346|no known conversion" }
+three sink_3_346(volatile A&);
+four sink_3_346(const volatile A&);
+six sink_3_346(const A&&);
int test3_346()
{
@@ -685,16 +604,14 @@ int test3_346()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_346(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 688 }
- sink_3_346(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 690 }
+ sink_3_346(v_source()); // { dg-error "" }
+ sink_3_346(cv_source()); // { dg-error "" }
return 0;
}
-three sink_3_347(volatile A&); // { dg-message "three sink_3_347|no known conversion" }
-four sink_3_347(const volatile A&); // { dg-message "four sink_3_347|no known conversion" }
-seven sink_3_347(volatile A&&); // { dg-message "seven sink_3_347|no known conversion" }
+three sink_3_347(volatile A&);
+four sink_3_347(const volatile A&);
+seven sink_3_347(volatile A&&);
int test3_347()
{
@@ -702,16 +619,14 @@ int test3_347()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_347(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 705 }
- sink_3_347(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 707 }
+ sink_3_347(c_source()); // { dg-error "" }
+ sink_3_347(cv_source()); // { dg-error "" }
return 0;
}
-three sink_3_356(volatile A&); // { dg-message "three sink_3_356|no known conversion" }
-five sink_3_356( A&&); // { dg-message "five sink_3_356|no known conversion" }
-six sink_3_356(const A&&); // { dg-message "six sink_3_356|no known conversion" }
+three sink_3_356(volatile A&);
+five sink_3_356( A&&);
+six sink_3_356(const A&&);
int test3_356()
{
@@ -719,19 +634,16 @@ int test3_356()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_356(ca); // { dg-error "lvalue" }
- sink_3_356(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 723 }
- sink_3_356(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 725 }
- sink_3_356(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 727 }
+ sink_3_356(ca); // { dg-error "" }
+ sink_3_356(cva); // { dg-error "" }
+ sink_3_356(v_source()); // { dg-error "" }
+ sink_3_356(cv_source()); // { dg-error "" }
return 0;
}
-three sink_3_357(volatile A&); // { dg-message "three sink_3_357|no known conversion" }
-five sink_3_357( A&&); // { dg-message "five sink_3_357|no known conversion" }
-seven sink_3_357(volatile A&&); // { dg-message "seven sink_3_357|no known conversion" }
+three sink_3_357(volatile A&);
+five sink_3_357( A&&);
+seven sink_3_357(volatile A&&);
int test3_357()
{
@@ -739,20 +651,16 @@ int test3_357()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_357(ca); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 742 }
- sink_3_357(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 744 }
- sink_3_357(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 746 }
- sink_3_357(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 748 }
+ sink_3_357(ca); // { dg-error "" }
+ sink_3_357(cva); // { dg-error "" }
+ sink_3_357(c_source()); // { dg-error "" }
+ sink_3_357(cv_source()); // { dg-error "" }
return 0;
}
three sink_3_358(volatile A&);
five sink_3_358( A&&);
-eight sink_3_358(const volatile A&&); // { dg-message "" }
+eight sink_3_358(const volatile A&&);
int test3_358()
{
@@ -760,14 +668,14 @@ int test3_358()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_358(ca); // { dg-error "lvalue" }
- sink_3_358(cva); // { dg-error "lvalue" }
+ sink_3_358(ca); // { dg-error "" }
+ sink_3_358(cva); // { dg-error "" }
return 0;
}
-three sink_3_367(volatile A&); // { dg-message "three sink_3_367|no known conversion" }
-six sink_3_367(const A&&); // { dg-message "six sink_3_367|no known conversion" }
-seven sink_3_367(volatile A&&); // { dg-message "seven sink_3_367|no known conversion" }
+three sink_3_367(volatile A&);
+six sink_3_367(const A&&);
+seven sink_3_367(volatile A&&);
int test3_367()
{
@@ -775,19 +683,16 @@ int test3_367()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_367(ca); // { dg-error "lvalue" }
- sink_3_367(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 779 }
- sink_3_367(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 781 }
- sink_3_367(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 783 }
+ sink_3_367(ca); // { dg-error "" }
+ sink_3_367(cva); // { dg-error "" }
+ sink_3_367(source()); // { dg-error "" }
+ sink_3_367(cv_source()); // { dg-error "" }
return 0;
}
three sink_3_368(volatile A&);
-six sink_3_368(const A&&); // { dg-message "" }
-eight sink_3_368(const volatile A&&); // { dg-message "" }
+six sink_3_368(const A&&);
+eight sink_3_368(const volatile A&&);
int test3_368()
{
@@ -795,14 +700,14 @@ int test3_368()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_368(ca); // { dg-error "lvalue" }
- sink_3_368(cva); // { dg-error "lvalue" }
+ sink_3_368(ca); // { dg-error "" }
+ sink_3_368(cva); // { dg-error "" }
return 0;
}
three sink_3_378(volatile A&);
seven sink_3_378(volatile A&&);
-eight sink_3_378(const volatile A&&); // { dg-message "" }
+eight sink_3_378(const volatile A&&);
int test3_378()
{
@@ -810,14 +715,14 @@ int test3_378()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_378(ca); // { dg-error "lvalue" }
- sink_3_378(cva); // { dg-error "lvalue" }
+ sink_3_378(ca); // { dg-error "" }
+ sink_3_378(cva); // { dg-error "" }
return 0;
}
-four sink_3_456(const volatile A&); // { dg-message "note" }
-five sink_3_456( A&&); // { dg-message "note" }
-six sink_3_456(const A&&); // { dg-message "note" }
+four sink_3_456(const volatile A&);
+five sink_3_456( A&&);
+six sink_3_456(const A&&);
int test3_456()
{
@@ -825,16 +730,14 @@ int test3_456()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_456(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 828 }
- sink_3_456(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 830 }
+ sink_3_456(v_source()); // { dg-error "" }
+ sink_3_456(cv_source()); // { dg-error "" }
return 0;
}
-four sink_3_457(const volatile A&); // { dg-message "note" }
-five sink_3_457( A&&); // { dg-message "note" }
-seven sink_3_457(volatile A&&); // { dg-message "note" }
+four sink_3_457(const volatile A&);
+five sink_3_457( A&&);
+seven sink_3_457(volatile A&&);
int test3_457()
{
@@ -842,16 +745,14 @@ int test3_457()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_457(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 845 }
- sink_3_457(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 847 }
+ sink_3_457(c_source()); // { dg-error "" }
+ sink_3_457(cv_source()); // { dg-error "" }
return 0;
}
-four sink_3_467(const volatile A&); // { dg-message "note" }
-six sink_3_467(const A&&); // { dg-message "note" }
-seven sink_3_467(volatile A&&); // { dg-message "note" }
+four sink_3_467(const volatile A&);
+six sink_3_467(const A&&);
+seven sink_3_467(volatile A&&);
int test3_467()
{
@@ -859,16 +760,14 @@ int test3_467()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_467(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 862 }
- sink_3_467(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 864 }
+ sink_3_467(source()); // { dg-error "" }
+ sink_3_467(cv_source()); // { dg-error "" }
return 0;
}
-five sink_3_567( A&&); // { dg-message "five sink_3_567|no known conversion" }
-six sink_3_567(const A&&); // { dg-message "six sink_3_567|no known conversion" }
-seven sink_3_567(volatile A&&); // { dg-message "seven sink_3_567|no known conversion" }
+five sink_3_567( A&&);
+six sink_3_567(const A&&);
+seven sink_3_567(volatile A&&);
int test3_567()
{
@@ -876,19 +775,17 @@ int test3_567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_567(a); // { dg-error "lvalue" }
- sink_3_567(ca); // { dg-error "lvalue" }
- sink_3_567(va); // { dg-error "lvalue" }
- sink_3_567(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 882 }
- sink_3_567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 884 }
+ sink_3_567(a); // { dg-error "" }
+ sink_3_567(ca); // { dg-error "" }
+ sink_3_567(va); // { dg-error "" }
+ sink_3_567(cva); // { dg-error "" }
+ sink_3_567(cv_source()); // { dg-error "" }
return 0;
}
-five sink_3_568( A&&); // { dg-message "" }
-six sink_3_568(const A&&); // { dg-message "" }
-eight sink_3_568(const volatile A&&); // { dg-message "" }
+five sink_3_568( A&&);
+six sink_3_568(const A&&);
+eight sink_3_568(const volatile A&&);
int test3_568()
{
@@ -896,16 +793,16 @@ int test3_568()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_568(a); // { dg-error "lvalue" }
- sink_3_568(ca); // { dg-error "lvalue" }
- sink_3_568(va); // { dg-error "lvalue" }
- sink_3_568(cva); // { dg-error "lvalue" }
+ sink_3_568(a); // { dg-error "" }
+ sink_3_568(ca); // { dg-error "" }
+ sink_3_568(va); // { dg-error "" }
+ sink_3_568(cva); // { dg-error "" }
return 0;
}
-five sink_3_578( A&&); // { dg-message "" }
-seven sink_3_578(volatile A&&); // { dg-message "" }
-eight sink_3_578(const volatile A&&); // { dg-message "" }
+five sink_3_578( A&&);
+seven sink_3_578(volatile A&&);
+eight sink_3_578(const volatile A&&);
int test3_578()
{
@@ -913,16 +810,16 @@ int test3_578()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_578(a); // { dg-error "lvalue" }
- sink_3_578(ca); // { dg-error "lvalue" }
- sink_3_578(va); // { dg-error "lvalue" }
- sink_3_578(cva); // { dg-error "lvalue" }
+ sink_3_578(a); // { dg-error "" }
+ sink_3_578(ca); // { dg-error "" }
+ sink_3_578(va); // { dg-error "" }
+ sink_3_578(cva); // { dg-error "" }
return 0;
}
-six sink_3_678(const A&&); // { dg-message "six sink_3_678|no known conversion" }
-seven sink_3_678(volatile A&&); // { dg-message "seven sink_3_678|no known conversion" }
-eight sink_3_678(const volatile A&&); // { dg-message "eight sink_3_678|no known conversion" }
+six sink_3_678(const A&&);
+seven sink_3_678(volatile A&&);
+eight sink_3_678(const volatile A&&);
int test3_678()
{
@@ -930,13 +827,11 @@ int test3_678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_3_678(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 933 }
- sink_3_678(ca); // { dg-error "lvalue" }
- sink_3_678(va); // { dg-error "lvalue" }
- sink_3_678(cva); // { dg-error "lvalue" }
- sink_3_678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 938 }
+ sink_3_678(a); // { dg-error "" }
+ sink_3_678(ca); // { dg-error "" }
+ sink_3_678(va); // { dg-error "" }
+ sink_3_678(cva); // { dg-error "" }
+ sink_3_678(source()); // { dg-error "" }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv4n.C b/gcc/testsuite/g++.dg/cpp0x/rv4n.C
index dc56afeba43..e64856de701 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv4n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv4n.C
@@ -30,10 +30,10 @@ const volatile A cv_source();
// 4 at a time
-one sink_4_1234( A&); // { dg-message "one sink_4_1234|no known conversion" }
-two sink_4_1234(const A&); // { dg-message "note" }
-three sink_4_1234(volatile A&); // { dg-message "note" }
-four sink_4_1234(const volatile A&); // { dg-message "note" }
+one sink_4_1234( A&);
+two sink_4_1234(const A&);
+three sink_4_1234(volatile A&);
+four sink_4_1234(const volatile A&);
int test4_1234()
{
@@ -41,17 +41,15 @@ int test4_1234()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1234(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 44 }
- sink_4_1234(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 46 }
+ sink_4_1234(v_source()); // { dg-error "" }
+ sink_4_1234(cv_source()); // { dg-error "" }
return 0;
}
-one sink_4_1235( A&); // { dg-message "one sink_4_1235|no known conversion" }
-two sink_4_1235(const A&); // { dg-message "note" }
-three sink_4_1235(volatile A&); // { dg-message "note" }
-five sink_4_1235( A&&); // { dg-message "note" }
+one sink_4_1235( A&);
+two sink_4_1235(const A&);
+three sink_4_1235(volatile A&);
+five sink_4_1235( A&&);
int test4_1235()
{
@@ -59,19 +57,16 @@ int test4_1235()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1235(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 62 }
- sink_4_1235(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 64 }
- sink_4_1235(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 66 }
+ sink_4_1235(cva); // { dg-error "" }
+ sink_4_1235(v_source()); // { dg-error "" }
+ sink_4_1235(cv_source()); // { dg-error "" }
return 0;
}
-one sink_4_1236( A&); // { dg-message "one sink_4_1236|no known conversion" }
-two sink_4_1236(const A&); // { dg-message "note" }
-three sink_4_1236(volatile A&); // { dg-message "note" }
-six sink_4_1236(const A&&); // { dg-message "note" }
+one sink_4_1236( A&);
+two sink_4_1236(const A&);
+three sink_4_1236(volatile A&);
+six sink_4_1236(const A&&);
int test4_1236()
{
@@ -79,19 +74,16 @@ int test4_1236()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1236(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 82 }
- sink_4_1236(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 84 }
- sink_4_1236(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 86 }
+ sink_4_1236(cva); // { dg-error "" }
+ sink_4_1236(v_source()); // { dg-error "" }
+ sink_4_1236(cv_source()); // { dg-error "" }
return 0;
}
-one sink_4_1237( A&); // { dg-message "one sink_4_1237|no known conversion" }
-two sink_4_1237(const A&); // { dg-message "note" }
-three sink_4_1237(volatile A&); // { dg-message "note" }
-seven sink_4_1237(volatile A&&); // { dg-message "note" }
+one sink_4_1237( A&);
+two sink_4_1237(const A&);
+three sink_4_1237(volatile A&);
+seven sink_4_1237(volatile A&&);
int test4_1237()
{
@@ -99,10 +91,8 @@ int test4_1237()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1237(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 102 }
- sink_4_1237(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 104 }
+ sink_4_1237(cva); // { dg-error "" }
+ sink_4_1237(cv_source()); // { dg-error "" }
return 0;
}
@@ -117,14 +107,14 @@ int test4_1238()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1238(cva); // { dg-error "lvalue" }
+ sink_4_1238(cva); // { dg-error "" }
return 0;
}
-one sink_4_1245( A&); // { dg-message "one sink_4_1245|no known conversion" }
-two sink_4_1245(const A&); // { dg-message "note" }
-four sink_4_1245(const volatile A&); // { dg-message "note" }
-five sink_4_1245( A&&); // { dg-message "note" }
+one sink_4_1245( A&);
+two sink_4_1245(const A&);
+four sink_4_1245(const volatile A&);
+five sink_4_1245( A&&);
int test4_1245()
{
@@ -132,17 +122,15 @@ int test4_1245()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1245(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 135 }
- sink_4_1245(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 137 }
+ sink_4_1245(v_source()); // { dg-error "" }
+ sink_4_1245(cv_source()); // { dg-error "" }
return 0;
}
-one sink_4_1246( A&); // { dg-message "one sink_4_1246|no known conversion" }
-two sink_4_1246(const A&); // { dg-message "note" }
-four sink_4_1246(const volatile A&); // { dg-message "note" }
-six sink_4_1246(const A&&); // { dg-message "note" }
+one sink_4_1246( A&);
+two sink_4_1246(const A&);
+four sink_4_1246(const volatile A&);
+six sink_4_1246(const A&&);
int test4_1246()
{
@@ -150,17 +138,15 @@ int test4_1246()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1246(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 153 }
- sink_4_1246(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 155 }
+ sink_4_1246(v_source()); // { dg-error "" }
+ sink_4_1246(cv_source()); // { dg-error "" }
return 0;
}
-one sink_4_1247( A&); // { dg-message "one sink_4_1247|no known conversion" }
-two sink_4_1247(const A&); // { dg-message "note" }
-four sink_4_1247(const volatile A&); // { dg-message "note" }
-seven sink_4_1247(volatile A&&); // { dg-message "note" }
+one sink_4_1247( A&);
+two sink_4_1247(const A&);
+four sink_4_1247(const volatile A&);
+seven sink_4_1247(volatile A&&);
int test4_1247()
{
@@ -168,15 +154,14 @@ int test4_1247()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1247(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 171 }
+ sink_4_1247(cv_source()); // { dg-error "" }
return 0;
}
-one sink_4_1256( A&); // { dg-message "one sink_4_1256|no known conversion" }
-two sink_4_1256(const A&); // { dg-message "note" }
-five sink_4_1256( A&&); // { dg-message "note" }
-six sink_4_1256(const A&&); // { dg-message "note" }
+one sink_4_1256( A&);
+two sink_4_1256(const A&);
+five sink_4_1256( A&&);
+six sink_4_1256(const A&&);
int test4_1256()
{
@@ -184,21 +169,17 @@ int test4_1256()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1256(va); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 187 }
- sink_4_1256(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 189 }
- sink_4_1256(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 191 }
- sink_4_1256(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 193 }
+ sink_4_1256(va); // { dg-error "" }
+ sink_4_1256(cva); // { dg-error "" }
+ sink_4_1256(v_source()); // { dg-error "" }
+ sink_4_1256(cv_source()); // { dg-error "" }
return 0;
}
-one sink_4_1257( A&); // { dg-message "one sink_4_1257|no known conversion" }
-two sink_4_1257(const A&); // { dg-message "note" }
-five sink_4_1257( A&&); // { dg-message "note" }
-seven sink_4_1257(volatile A&&); // { dg-message "" }
+one sink_4_1257( A&);
+two sink_4_1257(const A&);
+five sink_4_1257( A&&);
+seven sink_4_1257(volatile A&&);
int test4_1257()
{
@@ -206,11 +187,9 @@ int test4_1257()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1257(va); // { dg-error "lvalue" }
- sink_4_1257(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 210 }
- sink_4_1257(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 212 }
+ sink_4_1257(va); // { dg-error "" }
+ sink_4_1257(cva); // { dg-error "" }
+ sink_4_1257(cv_source()); // { dg-error "" }
return 0;
}
@@ -225,15 +204,15 @@ int test4_1258()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1258(va); // { dg-error "lvalue" }
- sink_4_1258(cva); // { dg-error "lvalue" }
+ sink_4_1258(va); // { dg-error "" }
+ sink_4_1258(cva); // { dg-error "" }
return 0;
}
-one sink_4_1267( A&); // { dg-message "one sink_4_1267|no known conversion" }
-two sink_4_1267(const A&); // { dg-message "note" }
-six sink_4_1267(const A&&); // { dg-message "note" }
-seven sink_4_1267(volatile A&&); // { dg-message "" }
+one sink_4_1267( A&);
+two sink_4_1267(const A&);
+six sink_4_1267(const A&&);
+seven sink_4_1267(volatile A&&);
int test4_1267()
{
@@ -241,13 +220,10 @@ int test4_1267()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1267(va); // { dg-error "lvalue" }
- sink_4_1267(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 245 }
- sink_4_1267(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 247 }
- sink_4_1267(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 249 }
+ sink_4_1267(va); // { dg-error "" }
+ sink_4_1267(cva); // { dg-error "" }
+ sink_4_1267(source()); // { dg-error "" }
+ sink_4_1267(cv_source()); // { dg-error "" }
return 0;
}
@@ -262,8 +238,8 @@ int test4_1268()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1268(va); // { dg-error "lvalue" }
- sink_4_1268(cva); // { dg-error "lvalue" }
+ sink_4_1268(va); // { dg-error "" }
+ sink_4_1268(cva); // { dg-error "" }
return 0;
}
@@ -278,15 +254,15 @@ int test4_1278()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1278(va); // { dg-error "lvalue" }
- sink_4_1278(cva); // { dg-error "lvalue" }
+ sink_4_1278(va); // { dg-error "" }
+ sink_4_1278(cva); // { dg-error "" }
return 0;
}
-one sink_4_1345( A&); // { dg-message "one sink_4_1345|no known conversion" }
-three sink_4_1345(volatile A&); // { dg-message "note" }
-four sink_4_1345(const volatile A&); // { dg-message "note" }
-five sink_4_1345( A&&); // { dg-message "note" }
+one sink_4_1345( A&);
+three sink_4_1345(volatile A&);
+four sink_4_1345(const volatile A&);
+five sink_4_1345( A&&);
int test4_1345()
{
@@ -294,19 +270,16 @@ int test4_1345()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1345(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 297 }
- sink_4_1345(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 299 }
- sink_4_1345(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 301 }
+ sink_4_1345(c_source()); // { dg-error "" }
+ sink_4_1345(v_source()); // { dg-error "" }
+ sink_4_1345(cv_source()); // { dg-error "" }
return 0;
}
-one sink_4_1346( A&); // { dg-message "one sink_4_1346|no known conversion" }
-three sink_4_1346(volatile A&); // { dg-message "note" }
-four sink_4_1346(const volatile A&); // { dg-message "note" }
-six sink_4_1346(const A&&); // { dg-message "note" }
+one sink_4_1346( A&);
+three sink_4_1346(volatile A&);
+four sink_4_1346(const volatile A&);
+six sink_4_1346(const A&&);
int test4_1346()
{
@@ -314,17 +287,15 @@ int test4_1346()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1346(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 317 }
- sink_4_1346(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 319 }
+ sink_4_1346(v_source()); // { dg-error "" }
+ sink_4_1346(cv_source()); // { dg-error "" }
return 0;
}
-one sink_4_1347( A&); // { dg-message "one sink_4_1347|no known conversion" }
-three sink_4_1347(volatile A&); // { dg-message "note" }
-four sink_4_1347(const volatile A&); // { dg-message "note" }
-seven sink_4_1347(volatile A&&); // { dg-message "note" }
+one sink_4_1347( A&);
+three sink_4_1347(volatile A&);
+four sink_4_1347(const volatile A&);
+seven sink_4_1347(volatile A&&);
int test4_1347()
{
@@ -332,17 +303,15 @@ int test4_1347()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1347(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 335 }
- sink_4_1347(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 337 }
+ sink_4_1347(c_source()); // { dg-error "" }
+ sink_4_1347(cv_source()); // { dg-error "" }
return 0;
}
-one sink_4_1356( A&); // { dg-message "one sink_4_1356|no known conversion" }
-three sink_4_1356(volatile A&); // { dg-message "note" }
-five sink_4_1356( A&&); // { dg-message "note" }
-six sink_4_1356(const A&&); // { dg-message "" }
+one sink_4_1356( A&);
+three sink_4_1356(volatile A&);
+five sink_4_1356( A&&);
+six sink_4_1356(const A&&);
int test4_1356()
{
@@ -350,20 +319,17 @@ int test4_1356()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1356(ca); // { dg-error "lvalue" }
- sink_4_1356(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 354 }
- sink_4_1356(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 356 }
- sink_4_1356(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 358 }
+ sink_4_1356(ca); // { dg-error "" }
+ sink_4_1356(cva); // { dg-error "" }
+ sink_4_1356(v_source()); // { dg-error "" }
+ sink_4_1356(cv_source()); // { dg-error "" }
return 0;
}
-one sink_4_1357( A&); // { dg-message "one sink_4_1357|no known conversion" }
-three sink_4_1357(volatile A&); // { dg-message "note" }
-five sink_4_1357( A&&); // { dg-message "note" }
-seven sink_4_1357(volatile A&&); // { dg-message "note" }
+one sink_4_1357( A&);
+three sink_4_1357(volatile A&);
+five sink_4_1357( A&&);
+seven sink_4_1357(volatile A&&);
int test4_1357()
{
@@ -371,14 +337,10 @@ int test4_1357()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1357(ca); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 374 }
- sink_4_1357(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 376 }
- sink_4_1357(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 378 }
- sink_4_1357(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 380 }
+ sink_4_1357(ca); // { dg-error "" }
+ sink_4_1357(cva); // { dg-error "" }
+ sink_4_1357(c_source()); // { dg-error "" }
+ sink_4_1357(cv_source()); // { dg-error "" }
return 0;
}
@@ -393,15 +355,15 @@ int test4_1358()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1358(ca); // { dg-error "lvalue" }
- sink_4_1358(cva); // { dg-error "lvalue" }
+ sink_4_1358(ca); // { dg-error "" }
+ sink_4_1358(cva); // { dg-error "" }
return 0;
}
-one sink_4_1367( A&); // { dg-message "one sink_4_1367|no known conversion" }
-three sink_4_1367(volatile A&); // { dg-message "note" }
-six sink_4_1367(const A&&); // { dg-message "" }
-seven sink_4_1367(volatile A&&); // { dg-message "note" }
+one sink_4_1367( A&);
+three sink_4_1367(volatile A&);
+six sink_4_1367(const A&&);
+seven sink_4_1367(volatile A&&);
int test4_1367()
{
@@ -409,13 +371,10 @@ int test4_1367()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1367(ca); // { dg-error "lvalue" }
- sink_4_1367(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 413 }
- sink_4_1367(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 415 }
- sink_4_1367(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 417 }
+ sink_4_1367(ca); // { dg-error "" }
+ sink_4_1367(cva); // { dg-error "" }
+ sink_4_1367(source()); // { dg-error "" }
+ sink_4_1367(cv_source()); // { dg-error "" }
return 0;
}
@@ -430,8 +389,8 @@ int test4_1368()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1368(ca); // { dg-error "lvalue" }
- sink_4_1368(cva); // { dg-error "lvalue" }
+ sink_4_1368(ca); // { dg-error "" }
+ sink_4_1368(cva); // { dg-error "" }
return 0;
}
@@ -446,15 +405,15 @@ int test4_1378()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1378(ca); // { dg-error "lvalue" }
- sink_4_1378(cva); // { dg-error "lvalue" }
+ sink_4_1378(ca); // { dg-error "" }
+ sink_4_1378(cva); // { dg-error "" }
return 0;
}
-one sink_4_1456( A&); // { dg-message "one sink_4_1456|no known conversion" }
-four sink_4_1456(const volatile A&); // { dg-message "note" }
-five sink_4_1456( A&&); // { dg-message "note" }
-six sink_4_1456(const A&&); // { dg-message "note" }
+one sink_4_1456( A&);
+four sink_4_1456(const volatile A&);
+five sink_4_1456( A&&);
+six sink_4_1456(const A&&);
int test4_1456()
{
@@ -462,17 +421,15 @@ int test4_1456()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1456(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 465 }
- sink_4_1456(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 467 }
+ sink_4_1456(v_source()); // { dg-error "" }
+ sink_4_1456(cv_source()); // { dg-error "" }
return 0;
}
-one sink_4_1457( A&); // { dg-message "one sink_4_1457|no known conversion" }
-four sink_4_1457(const volatile A&); // { dg-message "note" }
-five sink_4_1457( A&&); // { dg-message "note" }
-seven sink_4_1457(volatile A&&); // { dg-message "note" }
+one sink_4_1457( A&);
+four sink_4_1457(const volatile A&);
+five sink_4_1457( A&&);
+seven sink_4_1457(volatile A&&);
int test4_1457()
{
@@ -480,17 +437,15 @@ int test4_1457()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1457(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 483 }
- sink_4_1457(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 485 }
+ sink_4_1457(c_source()); // { dg-error "" }
+ sink_4_1457(cv_source()); // { dg-error "" }
return 0;
}
-one sink_4_1467( A&); // { dg-message "one sink_4_1467|no known conversion" }
-four sink_4_1467(const volatile A&); // { dg-message "note" }
-six sink_4_1467(const A&&); // { dg-message "note" }
-seven sink_4_1467(volatile A&&); // { dg-message "note" }
+one sink_4_1467( A&);
+four sink_4_1467(const volatile A&);
+six sink_4_1467(const A&&);
+seven sink_4_1467(volatile A&&);
int test4_1467()
{
@@ -498,17 +453,15 @@ int test4_1467()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1467(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 501 }
- sink_4_1467(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 503 }
+ sink_4_1467(source()); // { dg-error "" }
+ sink_4_1467(cv_source()); // { dg-error "" }
return 0;
}
-one sink_4_1567( A&); // { dg-message "one sink_4_1567|no known conversion" }
-five sink_4_1567( A&&); // { dg-message "note" }
-six sink_4_1567(const A&&); // { dg-message "" }
-seven sink_4_1567(volatile A&&); // { dg-message "" }
+one sink_4_1567( A&);
+five sink_4_1567( A&&);
+six sink_4_1567(const A&&);
+seven sink_4_1567(volatile A&&);
int test4_1567()
{
@@ -516,12 +469,10 @@ int test4_1567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1567(ca); // { dg-error "lvalue" }
- sink_4_1567(va); // { dg-error "lvalue" }
- sink_4_1567(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 521 }
- sink_4_1567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 523 }
+ sink_4_1567(ca); // { dg-error "" }
+ sink_4_1567(va); // { dg-error "" }
+ sink_4_1567(cva); // { dg-error "" }
+ sink_4_1567(cv_source()); // { dg-error "" }
return 0;
}
@@ -536,9 +487,9 @@ int test4_1568()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1568(ca); // { dg-error "lvalue" }
- sink_4_1568(va); // { dg-error "lvalue" }
- sink_4_1568(cva); // { dg-error "lvalue" }
+ sink_4_1568(ca); // { dg-error "" }
+ sink_4_1568(va); // { dg-error "" }
+ sink_4_1568(cva); // { dg-error "" }
return 0;
}
@@ -553,16 +504,16 @@ int test4_1578()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1578(ca); // { dg-error "lvalue" }
- sink_4_1578(va); // { dg-error "lvalue" }
- sink_4_1578(cva); // { dg-error "lvalue" }
+ sink_4_1578(ca); // { dg-error "" }
+ sink_4_1578(va); // { dg-error "" }
+ sink_4_1578(cva); // { dg-error "" }
return 0;
}
one sink_4_1678( A&);
-six sink_4_1678(const A&&); // { dg-message "" }
-seven sink_4_1678(volatile A&&); // { dg-message "" }
-eight sink_4_1678(const volatile A&&); // { dg-message "" }
+six sink_4_1678(const A&&);
+seven sink_4_1678(volatile A&&);
+eight sink_4_1678(const volatile A&&);
int test4_1678()
{
@@ -570,18 +521,17 @@ int test4_1678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_1678(ca); // { dg-error "lvalue" }
- sink_4_1678(va); // { dg-error "lvalue" }
- sink_4_1678(cva); // { dg-error "lvalue" }
- sink_4_1678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 576 }
+ sink_4_1678(ca); // { dg-error "" }
+ sink_4_1678(va); // { dg-error "" }
+ sink_4_1678(cva); // { dg-error "" }
+ sink_4_1678(source()); // { dg-error "" }
return 0;
}
-two sink_4_2345(const A&); // { dg-message "two sink_4_2345|no known conversion" }
-three sink_4_2345(volatile A&); // { dg-message "note" }
-four sink_4_2345(const volatile A&); // { dg-message "note" }
-five sink_4_2345( A&&); // { dg-message "note" }
+two sink_4_2345(const A&);
+three sink_4_2345(volatile A&);
+four sink_4_2345(const volatile A&);
+five sink_4_2345( A&&);
int test4_2345()
{
@@ -589,19 +539,16 @@ int test4_2345()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2345(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 592 }
- sink_4_2345(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 594 }
- sink_4_2345(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 596 }
+ sink_4_2345(a); // { dg-error "" }
+ sink_4_2345(v_source()); // { dg-error "" }
+ sink_4_2345(cv_source()); // { dg-error "" }
return 0;
}
-two sink_4_2346(const A&); // { dg-message "two sink_4_2346|no known conversion" }
-three sink_4_2346(volatile A&); // { dg-message "note" }
-four sink_4_2346(const volatile A&); // { dg-message "note" }
-six sink_4_2346(const A&&); // { dg-message "note" }
+two sink_4_2346(const A&);
+three sink_4_2346(volatile A&);
+four sink_4_2346(const volatile A&);
+six sink_4_2346(const A&&);
int test4_2346()
{
@@ -609,19 +556,16 @@ int test4_2346()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2346(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 612 }
- sink_4_2346(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 614 }
- sink_4_2346(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 616 }
+ sink_4_2346(a); // { dg-error "" }
+ sink_4_2346(v_source()); // { dg-error "" }
+ sink_4_2346(cv_source()); // { dg-error "" }
return 0;
}
-two sink_4_2347(const A&); // { dg-message "two sink_4_2347|no known conversion" }
-three sink_4_2347(volatile A&); // { dg-message "note" }
-four sink_4_2347(const volatile A&); // { dg-message "note" }
-seven sink_4_2347(volatile A&&); // { dg-message "note" }
+two sink_4_2347(const A&);
+three sink_4_2347(volatile A&);
+four sink_4_2347(const volatile A&);
+seven sink_4_2347(volatile A&&);
int test4_2347()
{
@@ -629,17 +573,15 @@ int test4_2347()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2347(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 632 }
- sink_4_2347(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 634 }
+ sink_4_2347(a); // { dg-error "" }
+ sink_4_2347(cv_source()); // { dg-error "" }
return 0;
}
-two sink_4_2348(const A&); // { dg-message "note" }
-three sink_4_2348(volatile A&); // { dg-message "note" }
-four sink_4_2348(const volatile A&); // { dg-message "note" }
-eight sink_4_2348(const volatile A&&); // { dg-message "note" }
+two sink_4_2348(const A&);
+three sink_4_2348(volatile A&);
+four sink_4_2348(const volatile A&);
+eight sink_4_2348(const volatile A&&);
int test4_2348()
{
@@ -647,15 +589,14 @@ int test4_2348()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2348(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 650 }
+ sink_4_2348(a); // { dg-error "" }
return 0;
}
-two sink_4_2356(const A&); // { dg-message "two sink_4_2356|no known conversion" }
-three sink_4_2356(volatile A&); // { dg-message "note" }
-five sink_4_2356( A&&); // { dg-message "note" }
-six sink_4_2356(const A&&); // { dg-message "note" }
+two sink_4_2356(const A&);
+three sink_4_2356(volatile A&);
+five sink_4_2356( A&&);
+six sink_4_2356(const A&&);
int test4_2356()
{
@@ -663,21 +604,17 @@ int test4_2356()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2356(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 666 }
- sink_4_2356(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 668 }
- sink_4_2356(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 670 }
- sink_4_2356(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 672 }
+ sink_4_2356(a); // { dg-error "" }
+ sink_4_2356(cva); // { dg-error "" }
+ sink_4_2356(v_source()); // { dg-error "" }
+ sink_4_2356(cv_source()); // { dg-error "" }
return 0;
}
-two sink_4_2357(const A&); // { dg-message "two sink_4_2357|no known conversion" }
-three sink_4_2357(volatile A&); // { dg-message "note" }
-five sink_4_2357( A&&); // { dg-message "note" }
-seven sink_4_2357(volatile A&&); // { dg-message "note" }
+two sink_4_2357(const A&);
+three sink_4_2357(volatile A&);
+five sink_4_2357( A&&);
+seven sink_4_2357(volatile A&&);
int test4_2357()
{
@@ -685,19 +622,16 @@ int test4_2357()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2357(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 688 }
- sink_4_2357(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 690 }
- sink_4_2357(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 692 }
+ sink_4_2357(a); // { dg-error "" }
+ sink_4_2357(cva); // { dg-error "" }
+ sink_4_2357(cv_source()); // { dg-error "" }
return 0;
}
-two sink_4_2358(const A&); // { dg-message "note" }
-three sink_4_2358(volatile A&); // { dg-message "note" }
-five sink_4_2358( A&&); // { dg-message "note" }
-eight sink_4_2358(const volatile A&&); // { dg-message "" }
+two sink_4_2358(const A&);
+three sink_4_2358(volatile A&);
+five sink_4_2358( A&&);
+eight sink_4_2358(const volatile A&&);
int test4_2358()
{
@@ -705,16 +639,15 @@ int test4_2358()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2358(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 708 }
- sink_4_2358(cva); // { dg-error "lvalue" }
+ sink_4_2358(a); // { dg-error "" }
+ sink_4_2358(cva); // { dg-error "" }
return 0;
}
-two sink_4_2367(const A&); // { dg-message "two sink_4_2367|no known conversion" }
-three sink_4_2367(volatile A&); // { dg-message "note" }
-six sink_4_2367(const A&&); // { dg-message "note" }
-seven sink_4_2367(volatile A&&); // { dg-message "note" }
+two sink_4_2367(const A&);
+three sink_4_2367(volatile A&);
+six sink_4_2367(const A&&);
+seven sink_4_2367(volatile A&&);
int test4_2367()
{
@@ -722,21 +655,17 @@ int test4_2367()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2367(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 725 }
- sink_4_2367(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 727 }
- sink_4_2367(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 729 }
- sink_4_2367(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 731 }
+ sink_4_2367(a); // { dg-error "" }
+ sink_4_2367(cva); // { dg-error "" }
+ sink_4_2367(source()); // { dg-error "" }
+ sink_4_2367(cv_source()); // { dg-error "" }
return 0;
}
-two sink_4_2368(const A&); // { dg-message "note" }
-three sink_4_2368(volatile A&); // { dg-message "note" }
-six sink_4_2368(const A&&); // { dg-message "note" }
-eight sink_4_2368(const volatile A&&); // { dg-message "" }
+two sink_4_2368(const A&);
+three sink_4_2368(volatile A&);
+six sink_4_2368(const A&&);
+eight sink_4_2368(const volatile A&&);
int test4_2368()
{
@@ -744,16 +673,15 @@ int test4_2368()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2368(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 747 }
- sink_4_2368(cva); // { dg-error "lvalue" }
+ sink_4_2368(a); // { dg-error "" }
+ sink_4_2368(cva); // { dg-error "" }
return 0;
}
-two sink_4_2378(const A&); // { dg-message "note" }
-three sink_4_2378(volatile A&); // { dg-message "note" }
-seven sink_4_2378(volatile A&&); // { dg-message "note" }
-eight sink_4_2378(const volatile A&&); // { dg-message "" }
+two sink_4_2378(const A&);
+three sink_4_2378(volatile A&);
+seven sink_4_2378(volatile A&&);
+eight sink_4_2378(const volatile A&&);
int test4_2378()
{
@@ -761,16 +689,15 @@ int test4_2378()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2378(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 764 }
- sink_4_2378(cva); // { dg-error "lvalue" }
+ sink_4_2378(a); // { dg-error "" }
+ sink_4_2378(cva); // { dg-error "" }
return 0;
}
-two sink_4_2456(const A&); // { dg-message "two sink_4_2456|no known conversion" }
-four sink_4_2456(const volatile A&); // { dg-message "note" }
-five sink_4_2456( A&&); // { dg-message "note" }
-six sink_4_2456(const A&&); // { dg-message "note" }
+two sink_4_2456(const A&);
+four sink_4_2456(const volatile A&);
+five sink_4_2456( A&&);
+six sink_4_2456(const A&&);
int test4_2456()
{
@@ -778,17 +705,15 @@ int test4_2456()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2456(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 781 }
- sink_4_2456(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 783 }
+ sink_4_2456(v_source()); // { dg-error "" }
+ sink_4_2456(cv_source()); // { dg-error "" }
return 0;
}
-two sink_4_2457(const A&); // { dg-message "two sink_4_2457|no known conversion" }
-four sink_4_2457(const volatile A&); // { dg-message "note" }
-five sink_4_2457( A&&); // { dg-message "note" }
-seven sink_4_2457(volatile A&&); // { dg-message "note" }
+two sink_4_2457(const A&);
+four sink_4_2457(const volatile A&);
+five sink_4_2457( A&&);
+seven sink_4_2457(volatile A&&);
int test4_2457()
{
@@ -796,15 +721,14 @@ int test4_2457()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2457(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 799 }
+ sink_4_2457(cv_source()); // { dg-error "" }
return 0;
}
-two sink_4_2467(const A&); // { dg-message "two sink_4_2467|no known conversion" }
-four sink_4_2467(const volatile A&); // { dg-message "note" }
-six sink_4_2467(const A&&); // { dg-message "note" }
-seven sink_4_2467(volatile A&&); // { dg-message "note" }
+two sink_4_2467(const A&);
+four sink_4_2467(const volatile A&);
+six sink_4_2467(const A&&);
+seven sink_4_2467(volatile A&&);
int test4_2467()
{
@@ -812,17 +736,15 @@ int test4_2467()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2467(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 815 }
- sink_4_2467(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 817 }
+ sink_4_2467(source()); // { dg-error "" }
+ sink_4_2467(cv_source()); // { dg-error "" }
return 0;
}
-two sink_4_2567(const A&); // { dg-message "two sink_4_2567|no known conversion" }
-five sink_4_2567( A&&); // { dg-message "note" }
-six sink_4_2567(const A&&); // { dg-message "note" }
-seven sink_4_2567(volatile A&&); // { dg-message "" }
+two sink_4_2567(const A&);
+five sink_4_2567( A&&);
+six sink_4_2567(const A&&);
+seven sink_4_2567(volatile A&&);
int test4_2567()
{
@@ -830,11 +752,9 @@ int test4_2567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2567(va); // { dg-error "lvalue" }
- sink_4_2567(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 834 }
- sink_4_2567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 836 }
+ sink_4_2567(va); // { dg-error "" }
+ sink_4_2567(cva); // { dg-error "" }
+ sink_4_2567(cv_source()); // { dg-error "" }
return 0;
}
@@ -849,8 +769,8 @@ int test4_2568()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2568(va); // { dg-error "lvalue" }
- sink_4_2568(cva); // { dg-error "lvalue" }
+ sink_4_2568(va); // { dg-error "" }
+ sink_4_2568(cva); // { dg-error "" }
return 0;
}
@@ -865,15 +785,15 @@ int test4_2578()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2578(va); // { dg-error "lvalue" }
- sink_4_2578(cva); // { dg-error "lvalue" }
+ sink_4_2578(va); // { dg-error "" }
+ sink_4_2578(cva); // { dg-error "" }
return 0;
}
-two sink_4_2678(const A&); // { dg-message "note" }
-six sink_4_2678(const A&&); // { dg-message "note" }
-seven sink_4_2678(volatile A&&); // { dg-message "" }
-eight sink_4_2678(const volatile A&&); // { dg-message "" }
+two sink_4_2678(const A&);
+six sink_4_2678(const A&&);
+seven sink_4_2678(volatile A&&);
+eight sink_4_2678(const volatile A&&);
int test4_2678()
{
@@ -881,17 +801,16 @@ int test4_2678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_2678(va); // { dg-error "lvalue" }
- sink_4_2678(cva); // { dg-error "lvalue" }
- sink_4_2678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 886 }
+ sink_4_2678(va); // { dg-error "" }
+ sink_4_2678(cva); // { dg-error "" }
+ sink_4_2678(source()); // { dg-error "" }
return 0;
}
-three sink_4_3456(volatile A&); // { dg-message "three sink_4_3456|no known conversion" }
-four sink_4_3456(const volatile A&); // { dg-message "note" }
-five sink_4_3456( A&&); // { dg-message "note" }
-six sink_4_3456(const A&&); // { dg-message "note" }
+three sink_4_3456(volatile A&);
+four sink_4_3456(const volatile A&);
+five sink_4_3456( A&&);
+six sink_4_3456(const A&&);
int test4_3456()
{
@@ -899,17 +818,15 @@ int test4_3456()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_3456(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 902 }
- sink_4_3456(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 904 }
+ sink_4_3456(v_source()); // { dg-error "" }
+ sink_4_3456(cv_source()); // { dg-error "" }
return 0;
}
-three sink_4_3457(volatile A&); // { dg-message "three sink_4_3457|no known conversion" }
-four sink_4_3457(const volatile A&); // { dg-message "note" }
-five sink_4_3457( A&&); // { dg-message "note" }
-seven sink_4_3457(volatile A&&); // { dg-message "note" }
+three sink_4_3457(volatile A&);
+four sink_4_3457(const volatile A&);
+five sink_4_3457( A&&);
+seven sink_4_3457(volatile A&&);
int test4_3457()
{
@@ -917,17 +834,15 @@ int test4_3457()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_3457(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 920 }
- sink_4_3457(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 922 }
+ sink_4_3457(c_source()); // { dg-error "" }
+ sink_4_3457(cv_source()); // { dg-error "" }
return 0;
}
-three sink_4_3467(volatile A&); // { dg-message "three sink_4_3467|no known conversion" }
-four sink_4_3467(const volatile A&); // { dg-message "note" }
-six sink_4_3467(const A&&); // { dg-message "note" }
-seven sink_4_3467(volatile A&&); // { dg-message "note" }
+three sink_4_3467(volatile A&);
+four sink_4_3467(const volatile A&);
+six sink_4_3467(const A&&);
+seven sink_4_3467(volatile A&&);
int test4_3467()
{
@@ -935,17 +850,15 @@ int test4_3467()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_3467(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 938 }
- sink_4_3467(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 940 }
+ sink_4_3467(source()); // { dg-error "" }
+ sink_4_3467(cv_source()); // { dg-error "" }
return 0;
}
-three sink_4_3567(volatile A&); // { dg-message "three sink_4_3567|no known conversion" }
-five sink_4_3567( A&&); // { dg-message "note" }
-six sink_4_3567(const A&&); // { dg-message "" }
-seven sink_4_3567(volatile A&&); // { dg-message "note" }
+three sink_4_3567(volatile A&);
+five sink_4_3567( A&&);
+six sink_4_3567(const A&&);
+seven sink_4_3567(volatile A&&);
int test4_3567()
{
@@ -953,11 +866,9 @@ int test4_3567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_3567(ca); // { dg-error "lvalue" }
- sink_4_3567(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 957 }
- sink_4_3567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 959 }
+ sink_4_3567(ca); // { dg-error "" }
+ sink_4_3567(cva); // { dg-error "" }
+ sink_4_3567(cv_source()); // { dg-error "" }
return 0;
}
@@ -972,8 +883,8 @@ int test4_3568()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_3568(ca); // { dg-error "lvalue" }
- sink_4_3568(cva); // { dg-error "lvalue" }
+ sink_4_3568(ca); // { dg-error "" }
+ sink_4_3568(cva); // { dg-error "" }
return 0;
}
@@ -988,15 +899,15 @@ int test4_3578()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_3578(ca); // { dg-error "lvalue" }
- sink_4_3578(cva); // { dg-error "lvalue" }
+ sink_4_3578(ca); // { dg-error "" }
+ sink_4_3578(cva); // { dg-error "" }
return 0;
}
three sink_4_3678(volatile A&);
-six sink_4_3678(const A&&); // { dg-message "" }
-seven sink_4_3678(volatile A&&); // { dg-message "note" }
-eight sink_4_3678(const volatile A&&); // { dg-message "" }
+six sink_4_3678(const A&&);
+seven sink_4_3678(volatile A&&);
+eight sink_4_3678(const volatile A&&);
int test4_3678()
{
@@ -1004,17 +915,16 @@ int test4_3678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_3678(ca); // { dg-error "lvalue" }
- sink_4_3678(cva); // { dg-error "lvalue" }
- sink_4_3678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 1009 }
+ sink_4_3678(ca); // { dg-error "" }
+ sink_4_3678(cva); // { dg-error "" }
+ sink_4_3678(source()); // { dg-error "" }
return 0;
}
-four sink_4_4567(const volatile A&); // { dg-message "note" }
-five sink_4_4567( A&&); // { dg-message "note" }
-six sink_4_4567(const A&&); // { dg-message "note" }
-seven sink_4_4567(volatile A&&); // { dg-message "note" }
+four sink_4_4567(const volatile A&);
+five sink_4_4567( A&&);
+six sink_4_4567(const A&&);
+seven sink_4_4567(volatile A&&);
int test4_4567()
{
@@ -1022,15 +932,14 @@ int test4_4567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_4567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 1025 }
+ sink_4_4567(cv_source()); // { dg-error "" }
return 0;
}
four sink_4_4678(const volatile A&);
-six sink_4_4678(const A&&); // { dg-message "note" }
-seven sink_4_4678(volatile A&&); // { dg-message "note" }
-eight sink_4_4678(const volatile A&&); // { dg-message "note" }
+six sink_4_4678(const A&&);
+seven sink_4_4678(volatile A&&);
+eight sink_4_4678(const volatile A&&);
int test4_4678()
{
@@ -1038,8 +947,7 @@ int test4_4678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_4678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 1041 }
+ sink_4_4678(source()); // { dg-error "" }
return 0;
}
@@ -1054,10 +962,10 @@ int test4_5678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_4_5678(a); // { dg-error "lvalue" }
- sink_4_5678(ca); // { dg-error "lvalue" }
- sink_4_5678(va); // { dg-error "lvalue" }
- sink_4_5678(cva); // { dg-error "lvalue" }
+ sink_4_5678(a); // { dg-error "" }
+ sink_4_5678(ca); // { dg-error "" }
+ sink_4_5678(va); // { dg-error "" }
+ sink_4_5678(cva); // { dg-error "" }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv5n.C b/gcc/testsuite/g++.dg/cpp0x/rv5n.C
index ca179cd822c..90d54183063 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv5n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv5n.C
@@ -31,10 +31,10 @@ const volatile A cv_source();
// 5 at a time
one sink_5_12345( A&); // { dg-message "one sink_5_12345|no known conversion" }
-two sink_5_12345(const A&); // { dg-message "note" }
-three sink_5_12345(volatile A&); // { dg-message "note" }
-four sink_5_12345(const volatile A&); // { dg-message "note" }
-five sink_5_12345( A&&); // { dg-message "note" }
+two sink_5_12345(const A&);
+three sink_5_12345(volatile A&);
+four sink_5_12345(const volatile A&);
+five sink_5_12345( A&&);
int test5_12345()
{
@@ -42,18 +42,16 @@ int test5_12345()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12345(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 45 }
- sink_5_12345(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 47 }
+ sink_5_12345(v_source()); // { dg-error "" }
+ sink_5_12345(cv_source()); // { dg-error "" }
return 0;
}
one sink_5_12346( A&); // { dg-message "one sink_5_12346|no known conversion" }
-two sink_5_12346(const A&); // { dg-message "note" }
-three sink_5_12346(volatile A&); // { dg-message "note" }
-four sink_5_12346(const volatile A&); // { dg-message "note" }
-six sink_5_12346(const A&&); // { dg-message "note" }
+two sink_5_12346(const A&);
+three sink_5_12346(volatile A&);
+four sink_5_12346(const volatile A&);
+six sink_5_12346(const A&&);
int test5_12346()
{
@@ -61,18 +59,16 @@ int test5_12346()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12346(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 64 }
- sink_5_12346(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 66 }
+ sink_5_12346(v_source()); // { dg-error "" }
+ sink_5_12346(cv_source()); // { dg-error "" }
return 0;
}
one sink_5_12347( A&); // { dg-message "one sink_5_12347|no known conversion" }
-two sink_5_12347(const A&); // { dg-message "note" }
-three sink_5_12347(volatile A&); // { dg-message "note" }
-four sink_5_12347(const volatile A&); // { dg-message "note" }
-seven sink_5_12347(volatile A&&); // { dg-message "note" }
+two sink_5_12347(const A&);
+three sink_5_12347(volatile A&);
+four sink_5_12347(const volatile A&);
+seven sink_5_12347(volatile A&&);
int test5_12347()
{
@@ -80,16 +76,15 @@ int test5_12347()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12347(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 83 }
+ sink_5_12347(cv_source()); // { dg-error "" }
return 0;
}
one sink_5_12356( A&); // { dg-message "one sink_5_12356|no known conversion" }
-two sink_5_12356(const A&); // { dg-message "note" }
-three sink_5_12356(volatile A&); // { dg-message "note" }
-five sink_5_12356( A&&); // { dg-message "note" }
-six sink_5_12356(const A&&); // { dg-message "note" }
+two sink_5_12356(const A&);
+three sink_5_12356(volatile A&);
+five sink_5_12356( A&&);
+six sink_5_12356(const A&&);
int test5_12356()
{
@@ -97,20 +92,17 @@ int test5_12356()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12356(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 100 }
- sink_5_12356(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 102 }
- sink_5_12356(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 104 }
+ sink_5_12356(cva); // { dg-error "" }
+ sink_5_12356(v_source()); // { dg-error "" }
+ sink_5_12356(cv_source()); // { dg-error "" }
return 0;
}
one sink_5_12357( A&); // { dg-message "one sink_5_12357|no known conversion" }
-two sink_5_12357(const A&); // { dg-message "note" }
-three sink_5_12357(volatile A&); // { dg-message "note" }
-five sink_5_12357( A&&); // { dg-message "note" }
-seven sink_5_12357(volatile A&&); // { dg-message "note" }
+two sink_5_12357(const A&);
+three sink_5_12357(volatile A&);
+five sink_5_12357( A&&);
+seven sink_5_12357(volatile A&&);
int test5_12357()
{
@@ -118,10 +110,8 @@ int test5_12357()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12357(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 121 }
- sink_5_12357(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 123 }
+ sink_5_12357(cva); // { dg-error "" }
+ sink_5_12357(cv_source()); // { dg-error "" }
return 0;
}
@@ -137,15 +127,15 @@ int test5_12358()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12358(cva); // { dg-error "lvalue" }
+ sink_5_12358(cva); // { dg-error "" }
return 0;
}
one sink_5_12367( A&); // { dg-message "one sink_5_12367|no known conversion" }
-two sink_5_12367(const A&); // { dg-message "note" }
-three sink_5_12367(volatile A&); // { dg-message "note" }
-six sink_5_12367(const A&&); // { dg-message "note" }
-seven sink_5_12367(volatile A&&); // { dg-message "note" }
+two sink_5_12367(const A&);
+three sink_5_12367(volatile A&);
+six sink_5_12367(const A&&);
+seven sink_5_12367(volatile A&&);
int test5_12367()
{
@@ -153,12 +143,9 @@ int test5_12367()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12367(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 156 }
- sink_5_12367(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 158 }
- sink_5_12367(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 160 }
+ sink_5_12367(cva); // { dg-error "" }
+ sink_5_12367(source()); // { dg-error "" }
+ sink_5_12367(cv_source()); // { dg-error "" }
return 0;
}
@@ -174,7 +161,7 @@ int test5_12368()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12368(cva); // { dg-error "lvalue" }
+ sink_5_12368(cva); // { dg-error "" }
return 0;
}
@@ -190,15 +177,15 @@ int test5_12378()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12378(cva); // { dg-error "lvalue" }
+ sink_5_12378(cva); // { dg-error "" }
return 0;
}
one sink_5_12456( A&); // { dg-message "one sink_5_12456|no known conversion" }
-two sink_5_12456(const A&); // { dg-message "note" }
-four sink_5_12456(const volatile A&); // { dg-message "note" }
-five sink_5_12456( A&&); // { dg-message "note" }
-six sink_5_12456(const A&&); // { dg-message "note" }
+two sink_5_12456(const A&);
+four sink_5_12456(const volatile A&);
+five sink_5_12456( A&&);
+six sink_5_12456(const A&&);
int test5_12456()
{
@@ -206,18 +193,16 @@ int test5_12456()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12456(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 209 }
- sink_5_12456(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 211 }
+ sink_5_12456(v_source()); // { dg-error "" }
+ sink_5_12456(cv_source()); // { dg-error "" }
return 0;
}
one sink_5_12457( A&); // { dg-message "one sink_5_12457|no known conversion" }
-two sink_5_12457(const A&); // { dg-message "note" }
-four sink_5_12457(const volatile A&); // { dg-message "note" }
-five sink_5_12457( A&&); // { dg-message "note" }
-seven sink_5_12457(volatile A&&); // { dg-message "note" }
+two sink_5_12457(const A&);
+four sink_5_12457(const volatile A&);
+five sink_5_12457( A&&);
+seven sink_5_12457(volatile A&&);
int test5_12457()
{
@@ -225,16 +210,15 @@ int test5_12457()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12457(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 228 }
+ sink_5_12457(cv_source()); // { dg-error "" }
return 0;
}
one sink_5_12467( A&); // { dg-message "one sink_5_12467|no known conversion" }
-two sink_5_12467(const A&); // { dg-message "note" }
-four sink_5_12467(const volatile A&); // { dg-message "note" }
-six sink_5_12467(const A&&); // { dg-message "note" }
-seven sink_5_12467(volatile A&&); // { dg-message "note" }
+two sink_5_12467(const A&);
+four sink_5_12467(const volatile A&);
+six sink_5_12467(const A&&);
+seven sink_5_12467(volatile A&&);
int test5_12467()
{
@@ -242,17 +226,15 @@ int test5_12467()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12467(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 245 }
- sink_5_12467(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 247 }
+ sink_5_12467(source()); // { dg-error "" }
+ sink_5_12467(cv_source()); // { dg-error "" }
return 0;
}
one sink_5_12567( A&); // { dg-message "one sink_5_12567|no known conversion" }
-two sink_5_12567(const A&); // { dg-message "note" }
-five sink_5_12567( A&&); // { dg-message "note" }
-six sink_5_12567(const A&&); // { dg-message "note" }
+two sink_5_12567(const A&);
+five sink_5_12567( A&&);
+six sink_5_12567(const A&&);
seven sink_5_12567(volatile A&&); // { dg-message "" }
int test5_12567()
@@ -261,11 +243,9 @@ int test5_12567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12567(va); // { dg-error "lvalue" }
- sink_5_12567(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 265 }
- sink_5_12567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 267 }
+ sink_5_12567(va); // { dg-error "" }
+ sink_5_12567(cva); // { dg-error "" }
+ sink_5_12567(cv_source()); // { dg-error "" }
return 0;
}
@@ -281,8 +261,8 @@ int test5_12568()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12568(va); // { dg-error "lvalue" }
- sink_5_12568(cva); // { dg-error "lvalue" }
+ sink_5_12568(va); // { dg-error "" }
+ sink_5_12568(cva); // { dg-error "" }
return 0;
}
@@ -298,14 +278,14 @@ int test5_12578()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12578(va); // { dg-error "lvalue" }
- sink_5_12578(cva); // { dg-error "lvalue" }
+ sink_5_12578(va); // { dg-error "" }
+ sink_5_12578(cva); // { dg-error "" }
return 0;
}
one sink_5_12678( A&);
-two sink_5_12678(const A&); // { dg-message "note" }
-six sink_5_12678(const A&&); // { dg-message "note" }
+two sink_5_12678(const A&);
+six sink_5_12678(const A&&);
seven sink_5_12678(volatile A&&); // { dg-message "" }
eight sink_5_12678(const volatile A&&); // { dg-message "" }
@@ -315,18 +295,17 @@ int test5_12678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_12678(va); // { dg-error "lvalue" }
- sink_5_12678(cva); // { dg-error "lvalue" }
- sink_5_12678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 320 }
+ sink_5_12678(va); // { dg-error "" }
+ sink_5_12678(cva); // { dg-error "" }
+ sink_5_12678(source()); // { dg-error "" }
return 0;
}
one sink_5_13456( A&); // { dg-message "one sink_5_13456|no known conversion" }
-three sink_5_13456(volatile A&); // { dg-message "note" }
-four sink_5_13456(const volatile A&); // { dg-message "note" }
-five sink_5_13456( A&&); // { dg-message "note" }
-six sink_5_13456(const A&&); // { dg-message "note" }
+three sink_5_13456(volatile A&);
+four sink_5_13456(const volatile A&);
+five sink_5_13456( A&&);
+six sink_5_13456(const A&&);
int test5_13456()
{
@@ -334,18 +313,16 @@ int test5_13456()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_13456(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 337 }
- sink_5_13456(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 339 }
+ sink_5_13456(v_source()); // { dg-error "" }
+ sink_5_13456(cv_source()); // { dg-error "" }
return 0;
}
one sink_5_13457( A&); // { dg-message "one sink_5_13457|no known conversion" }
-three sink_5_13457(volatile A&); // { dg-message "note" }
-four sink_5_13457(const volatile A&); // { dg-message "note" }
-five sink_5_13457( A&&); // { dg-message "note" }
-seven sink_5_13457(volatile A&&); // { dg-message "note" }
+three sink_5_13457(volatile A&);
+four sink_5_13457(const volatile A&);
+five sink_5_13457( A&&);
+seven sink_5_13457(volatile A&&);
int test5_13457()
{
@@ -353,18 +330,16 @@ int test5_13457()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_13457(c_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 356 }
- sink_5_13457(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 358 }
+ sink_5_13457(c_source()); // { dg-error "" }
+ sink_5_13457(cv_source()); // { dg-error "" }
return 0;
}
one sink_5_13467( A&); // { dg-message "one sink_5_13467|no known conversion" }
-three sink_5_13467(volatile A&); // { dg-message "note" }
-four sink_5_13467(const volatile A&); // { dg-message "note" }
-six sink_5_13467(const A&&); // { dg-message "note" }
-seven sink_5_13467(volatile A&&); // { dg-message "note" }
+three sink_5_13467(volatile A&);
+four sink_5_13467(const volatile A&);
+six sink_5_13467(const A&&);
+seven sink_5_13467(volatile A&&);
int test5_13467()
{
@@ -372,18 +347,16 @@ int test5_13467()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_13467(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 375 }
- sink_5_13467(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 377 }
+ sink_5_13467(source()); // { dg-error "" }
+ sink_5_13467(cv_source()); // { dg-error "" }
return 0;
}
one sink_5_13567( A&); // { dg-message "one sink_5_13567|no known conversion" }
-three sink_5_13567(volatile A&); // { dg-message "note" }
-five sink_5_13567( A&&); // { dg-message "note" }
+three sink_5_13567(volatile A&);
+five sink_5_13567( A&&);
six sink_5_13567(const A&&); // { dg-message "" }
-seven sink_5_13567(volatile A&&); // { dg-message "note" }
+seven sink_5_13567(volatile A&&);
int test5_13567()
{
@@ -391,11 +364,9 @@ int test5_13567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_13567(ca); // { dg-error "lvalue" }
- sink_5_13567(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 395 }
- sink_5_13567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 397 }
+ sink_5_13567(ca); // { dg-error "" }
+ sink_5_13567(cva); // { dg-error "" }
+ sink_5_13567(cv_source()); // { dg-error "" }
return 0;
}
@@ -411,8 +382,8 @@ int test5_13568()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_13568(ca); // { dg-error "lvalue" }
- sink_5_13568(cva); // { dg-error "lvalue" }
+ sink_5_13568(ca); // { dg-error "" }
+ sink_5_13568(cva); // { dg-error "" }
return 0;
}
@@ -428,15 +399,15 @@ int test5_13578()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_13578(ca); // { dg-error "lvalue" }
- sink_5_13578(cva); // { dg-error "lvalue" }
+ sink_5_13578(ca); // { dg-error "" }
+ sink_5_13578(cva); // { dg-error "" }
return 0;
}
one sink_5_13678( A&);
three sink_5_13678(volatile A&);
six sink_5_13678(const A&&); // { dg-message "" }
-seven sink_5_13678(volatile A&&); // { dg-message "note" }
+seven sink_5_13678(volatile A&&);
eight sink_5_13678(const volatile A&&); // { dg-message "" }
int test5_13678()
@@ -445,18 +416,17 @@ int test5_13678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_13678(ca); // { dg-error "lvalue" }
- sink_5_13678(cva); // { dg-error "lvalue" }
- sink_5_13678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 450 }
+ sink_5_13678(ca); // { dg-error "" }
+ sink_5_13678(cva); // { dg-error "" }
+ sink_5_13678(source()); // { dg-error "" }
return 0;
}
one sink_5_14567( A&); // { dg-message "one sink_5_14567|no known conversion" }
-four sink_5_14567(const volatile A&); // { dg-message "note" }
-five sink_5_14567( A&&); // { dg-message "note" }
-six sink_5_14567(const A&&); // { dg-message "note" }
-seven sink_5_14567(volatile A&&); // { dg-message "note" }
+four sink_5_14567(const volatile A&);
+five sink_5_14567( A&&);
+six sink_5_14567(const A&&);
+seven sink_5_14567(volatile A&&);
int test5_14567()
{
@@ -464,16 +434,15 @@ int test5_14567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_14567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 467 }
+ sink_5_14567(cv_source()); // { dg-error "" }
return 0;
}
one sink_5_14678( A&);
four sink_5_14678(const volatile A&);
-six sink_5_14678(const A&&); // { dg-message "note" }
-seven sink_5_14678(volatile A&&); // { dg-message "note" }
-eight sink_5_14678(const volatile A&&); // { dg-message "note" }
+six sink_5_14678(const A&&);
+seven sink_5_14678(volatile A&&);
+eight sink_5_14678(const volatile A&&);
int test5_14678()
{
@@ -481,8 +450,7 @@ int test5_14678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_14678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 484 }
+ sink_5_14678(source()); // { dg-error "" }
return 0;
}
@@ -498,17 +466,17 @@ int test5_15678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_15678(ca); // { dg-error "lvalue" }
- sink_5_15678(va); // { dg-error "lvalue" }
- sink_5_15678(cva); // { dg-error "lvalue" }
+ sink_5_15678(ca); // { dg-error "" }
+ sink_5_15678(va); // { dg-error "" }
+ sink_5_15678(cva); // { dg-error "" }
return 0;
}
two sink_5_23456(const A&); // { dg-message "two sink_5_23456|no known conversion" }
-three sink_5_23456(volatile A&); // { dg-message "note" }
-four sink_5_23456(const volatile A&); // { dg-message "note" }
-five sink_5_23456( A&&); // { dg-message "note" }
-six sink_5_23456(const A&&); // { dg-message "note" }
+three sink_5_23456(volatile A&);
+four sink_5_23456(const volatile A&);
+five sink_5_23456( A&&);
+six sink_5_23456(const A&&);
int test5_23456()
{
@@ -516,20 +484,17 @@ int test5_23456()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_23456(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 519 }
- sink_5_23456(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 521 }
- sink_5_23456(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 523 }
+ sink_5_23456(a); // { dg-error "" }
+ sink_5_23456(v_source()); // { dg-error "" }
+ sink_5_23456(cv_source()); // { dg-error "" }
return 0;
}
two sink_5_23457(const A&); // { dg-message "two sink_5_23457|no known conversion" }
-three sink_5_23457(volatile A&); // { dg-message "note" }
-four sink_5_23457(const volatile A&); // { dg-message "note" }
-five sink_5_23457( A&&); // { dg-message "note" }
-seven sink_5_23457(volatile A&&); // { dg-message "note" }
+three sink_5_23457(volatile A&);
+four sink_5_23457(const volatile A&);
+five sink_5_23457( A&&);
+seven sink_5_23457(volatile A&&);
int test5_23457()
{
@@ -537,18 +502,16 @@ int test5_23457()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_23457(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 540 }
- sink_5_23457(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 542 }
+ sink_5_23457(a); // { dg-error "" }
+ sink_5_23457(cv_source()); // { dg-error "" }
return 0;
}
-two sink_5_23458(const A&); // { dg-message "note" }
-three sink_5_23458(volatile A&); // { dg-message "note" }
-four sink_5_23458(const volatile A&); // { dg-message "note" }
-five sink_5_23458( A&&); // { dg-message "note" }
-eight sink_5_23458(const volatile A&&); // { dg-message "note" }
+two sink_5_23458(const A&);
+three sink_5_23458(volatile A&);
+four sink_5_23458(const volatile A&);
+five sink_5_23458( A&&);
+eight sink_5_23458(const volatile A&&);
int test5_23458()
{
@@ -556,16 +519,15 @@ int test5_23458()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_23458(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 559 }
+ sink_5_23458(a); // { dg-error "" }
return 0;
}
two sink_5_23467(const A&); // { dg-message "two sink_5_23467|no known conversion" }
-three sink_5_23467(volatile A&); // { dg-message "note" }
-four sink_5_23467(const volatile A&); // { dg-message "note" }
-six sink_5_23467(const A&&); // { dg-message "note" }
-seven sink_5_23467(volatile A&&); // { dg-message "note" }
+three sink_5_23467(volatile A&);
+four sink_5_23467(const volatile A&);
+six sink_5_23467(const A&&);
+seven sink_5_23467(volatile A&&);
int test5_23467()
{
@@ -573,20 +535,17 @@ int test5_23467()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_23467(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 576 }
- sink_5_23467(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 578 }
- sink_5_23467(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 580 }
+ sink_5_23467(a); // { dg-error "" }
+ sink_5_23467(source()); // { dg-error "" }
+ sink_5_23467(cv_source()); // { dg-error "" }
return 0;
}
-two sink_5_23468(const A&); // { dg-message "note" }
-three sink_5_23468(volatile A&); // { dg-message "note" }
-four sink_5_23468(const volatile A&); // { dg-message "note" }
-six sink_5_23468(const A&&); // { dg-message "note" }
-eight sink_5_23468(const volatile A&&); // { dg-message "note" }
+two sink_5_23468(const A&);
+three sink_5_23468(volatile A&);
+four sink_5_23468(const volatile A&);
+six sink_5_23468(const A&&);
+eight sink_5_23468(const volatile A&&);
int test5_23468()
{
@@ -594,16 +553,15 @@ int test5_23468()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_23468(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 597 }
+ sink_5_23468(a); // { dg-error "" }
return 0;
}
-two sink_5_23478(const A&); // { dg-message "note" }
-three sink_5_23478(volatile A&); // { dg-message "note" }
-four sink_5_23478(const volatile A&); // { dg-message "note" }
-seven sink_5_23478(volatile A&&); // { dg-message "note" }
-eight sink_5_23478(const volatile A&&); // { dg-message "note" }
+two sink_5_23478(const A&);
+three sink_5_23478(volatile A&);
+four sink_5_23478(const volatile A&);
+seven sink_5_23478(volatile A&&);
+eight sink_5_23478(const volatile A&&);
int test5_23478()
{
@@ -611,16 +569,15 @@ int test5_23478()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_23478(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 614 }
+ sink_5_23478(a); // { dg-error "" }
return 0;
}
two sink_5_23567(const A&); // { dg-message "two sink_5_23567|no known conversion" }
-three sink_5_23567(volatile A&); // { dg-message "note" }
-five sink_5_23567( A&&); // { dg-message "note" }
-six sink_5_23567(const A&&); // { dg-message "note" }
-seven sink_5_23567(volatile A&&); // { dg-message "note" }
+three sink_5_23567(volatile A&);
+five sink_5_23567( A&&);
+six sink_5_23567(const A&&);
+seven sink_5_23567(volatile A&&);
int test5_23567()
{
@@ -628,20 +585,17 @@ int test5_23567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_23567(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 631 }
- sink_5_23567(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 633 }
- sink_5_23567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 635 }
+ sink_5_23567(a); // { dg-error "" }
+ sink_5_23567(cva); // { dg-error "" }
+ sink_5_23567(cv_source()); // { dg-error "" }
return 0;
}
-two sink_5_23568(const A&); // { dg-message "note" }
-three sink_5_23568(volatile A&); // { dg-message "note" }
-five sink_5_23568( A&&); // { dg-message "note" }
-six sink_5_23568(const A&&); // { dg-message "note" }
-eight sink_5_23568(const volatile A&&); // { dg-message "" }
+two sink_5_23568(const A&);
+three sink_5_23568(volatile A&);
+five sink_5_23568( A&&);
+six sink_5_23568(const A&&);
+eight sink_5_23568(const volatile A&&);
int test5_23568()
{
@@ -649,16 +603,15 @@ int test5_23568()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_23568(cva); // { dg-error "lvalue" }
- sink_5_23568(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 653 }
+ sink_5_23568(cva); // { dg-error "" }
+ sink_5_23568(a); // { dg-error "" }
return 0;
}
-two sink_5_23578(const A&); // { dg-message "note" }
-three sink_5_23578(volatile A&); // { dg-message "note" }
-five sink_5_23578( A&&); // { dg-message "note" }
-seven sink_5_23578(volatile A&&); // { dg-message "note" }
+two sink_5_23578(const A&);
+three sink_5_23578(volatile A&);
+five sink_5_23578( A&&);
+seven sink_5_23578(volatile A&&);
eight sink_5_23578(const volatile A&&); // { dg-message "" }
int test5_23578()
@@ -667,16 +620,15 @@ int test5_23578()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_23578(cva); // { dg-error "lvalue" }
- sink_5_23578(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 671 }
+ sink_5_23578(cva); // { dg-error "" }
+ sink_5_23578(a); // { dg-error "" }
return 0;
}
-two sink_5_23678(const A&); // { dg-message "note" }
-three sink_5_23678(volatile A&); // { dg-message "note" }
-six sink_5_23678(const A&&); // { dg-message "note" }
-seven sink_5_23678(volatile A&&); // { dg-message "note" }
+two sink_5_23678(const A&);
+three sink_5_23678(volatile A&);
+six sink_5_23678(const A&&);
+seven sink_5_23678(volatile A&&);
eight sink_5_23678(const volatile A&&); // { dg-message "" }
int test5_23678()
@@ -685,19 +637,17 @@ int test5_23678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_23678(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 688 }
- sink_5_23678(cva); // { dg-error "lvalue" }
- sink_5_23678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 691 }
+ sink_5_23678(a); // { dg-error "" }
+ sink_5_23678(cva); // { dg-error "" }
+ sink_5_23678(source()); // { dg-error "" }
return 0;
}
two sink_5_24567(const A&); // { dg-message "two sink_5_24567|no known conversion" }
-four sink_5_24567(const volatile A&); // { dg-message "note" }
-five sink_5_24567( A&&); // { dg-message "note" }
-six sink_5_24567(const A&&); // { dg-message "note" }
-seven sink_5_24567(volatile A&&); // { dg-message "note" }
+four sink_5_24567(const volatile A&);
+five sink_5_24567( A&&);
+six sink_5_24567(const A&&);
+seven sink_5_24567(volatile A&&);
int test5_24567()
{
@@ -705,16 +655,15 @@ int test5_24567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_24567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 708 }
+ sink_5_24567(cv_source()); // { dg-error "" }
return 0;
}
-two sink_5_24678(const A&); // { dg-message "note" }
+two sink_5_24678(const A&);
four sink_5_24678(const volatile A&);
-six sink_5_24678(const A&&); // { dg-message "note" }
-seven sink_5_24678(volatile A&&); // { dg-message "note" }
-eight sink_5_24678(const volatile A&&); // { dg-message "note" }
+six sink_5_24678(const A&&);
+seven sink_5_24678(volatile A&&);
+eight sink_5_24678(const volatile A&&);
int test5_24678()
{
@@ -722,8 +671,7 @@ int test5_24678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_24678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 725 }
+ sink_5_24678(source()); // { dg-error "" }
return 0;
}
@@ -739,16 +687,16 @@ int test5_25678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_25678(va); // { dg-error "lvalue" }
- sink_5_25678(cva); // { dg-error "lvalue" }
+ sink_5_25678(va); // { dg-error "" }
+ sink_5_25678(cva); // { dg-error "" }
return 0;
}
three sink_5_34567(volatile A&); // { dg-message "three sink_5_34567|no known conversion" }
-four sink_5_34567(const volatile A&); // { dg-message "note" }
-five sink_5_34567( A&&); // { dg-message "note" }
-six sink_5_34567(const A&&); // { dg-message "note" }
-seven sink_5_34567(volatile A&&); // { dg-message "note" }
+four sink_5_34567(const volatile A&);
+five sink_5_34567( A&&);
+six sink_5_34567(const A&&);
+seven sink_5_34567(volatile A&&);
int test5_34567()
{
@@ -756,16 +704,15 @@ int test5_34567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_34567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 759 }
+ sink_5_34567(cv_source()); // { dg-error "" }
return 0;
}
three sink_5_34678(volatile A&);
four sink_5_34678(const volatile A&);
-six sink_5_34678(const A&&); // { dg-message "note" }
-seven sink_5_34678(volatile A&&); // { dg-message "note" }
-eight sink_5_34678(const volatile A&&); // { dg-message "note" }
+six sink_5_34678(const A&&);
+seven sink_5_34678(volatile A&&);
+eight sink_5_34678(const volatile A&&);
int test5_34678()
{
@@ -773,8 +720,7 @@ int test5_34678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_34678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 776 }
+ sink_5_34678(source()); // { dg-error "" }
return 0;
}
@@ -790,8 +736,8 @@ int test5_35678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_5_35678(ca); // { dg-error "lvalue" }
- sink_5_35678(cva); // { dg-error "lvalue" }
+ sink_5_35678(ca); // { dg-error "" }
+ sink_5_35678(cva); // { dg-error "" }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv6n.C b/gcc/testsuite/g++.dg/cpp0x/rv6n.C
index d00c1e242b2..5bd9a230261 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv6n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv6n.C
@@ -31,11 +31,11 @@ const volatile A cv_source();
// 6 at a time
one sink_6_123456( A&); // { dg-message "one sink_6_123456|no known conversion" }
-two sink_6_123456(const A&); // { dg-message "note" }
-three sink_6_123456(volatile A&); // { dg-message "note" }
-four sink_6_123456(const volatile A&); // { dg-message "note" }
-five sink_6_123456( A&&); // { dg-message "note" }
-six sink_6_123456(const A&&); // { dg-message "note" }
+two sink_6_123456(const A&);
+three sink_6_123456(volatile A&);
+four sink_6_123456(const volatile A&);
+five sink_6_123456( A&&);
+six sink_6_123456(const A&&);
int test6_123456()
{
@@ -43,19 +43,17 @@ int test6_123456()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_123456(v_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 46 }
- sink_6_123456(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 48 }
+ sink_6_123456(v_source()); // { dg-error "" }
+ sink_6_123456(cv_source()); // { dg-error "" }
return 0;
}
one sink_6_123457( A&); // { dg-message "one sink_6_123457|no known conversion" }
-two sink_6_123457(const A&); // { dg-message "note" }
-three sink_6_123457(volatile A&); // { dg-message "note" }
-four sink_6_123457(const volatile A&); // { dg-message "note" }
-five sink_6_123457( A&&); // { dg-message "note" }
-seven sink_6_123457(volatile A&&); // { dg-message "note" }
+two sink_6_123457(const A&);
+three sink_6_123457(volatile A&);
+four sink_6_123457(const volatile A&);
+five sink_6_123457( A&&);
+seven sink_6_123457(volatile A&&);
int test6_123457()
{
@@ -63,16 +61,15 @@ int test6_123457()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_123457(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 66 }
+ sink_6_123457(cv_source()); // { dg-error "" }
return 0;
}
-two sink_6_235678(const A&); // { dg-message "note" }
-three sink_6_235678(volatile A&); // { dg-message "note" }
-five sink_6_235678( A&&); // { dg-message "note" }
-six sink_6_235678(const A&&); // { dg-message "note" }
-seven sink_6_235678(volatile A&&); // { dg-message "note" }
+two sink_6_235678(const A&);
+three sink_6_235678(volatile A&);
+five sink_6_235678( A&&);
+six sink_6_235678(const A&&);
+seven sink_6_235678(volatile A&&);
eight sink_6_235678(const volatile A&&); // { dg-message "" }
int test6_235678()
@@ -81,18 +78,17 @@ int test6_235678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_235678(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 84 }
- sink_6_235678(cva); // { dg-error "lvalue" }
+ sink_6_235678(a); // { dg-error "" }
+ sink_6_235678(cva); // { dg-error "" }
return 0;
}
-two sink_6_234678(const A&); // { dg-message "note" }
-three sink_6_234678(volatile A&); // { dg-message "note" }
-four sink_6_234678(const volatile A&); // { dg-message "note" }
-six sink_6_234678(const A&&); // { dg-message "note" }
-seven sink_6_234678(volatile A&&); // { dg-message "note" }
-eight sink_6_234678(const volatile A&&); // { dg-message "note" }
+two sink_6_234678(const A&);
+three sink_6_234678(volatile A&);
+four sink_6_234678(const volatile A&);
+six sink_6_234678(const A&&);
+seven sink_6_234678(volatile A&&);
+eight sink_6_234678(const volatile A&&);
int test6_234678()
{
@@ -100,19 +96,17 @@ int test6_234678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_234678(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 103 }
- sink_6_234678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 105 }
+ sink_6_234678(a); // { dg-error "" }
+ sink_6_234678(source()); // { dg-error "" }
return 0;
}
-two sink_6_234578(const A&); // { dg-message "note" }
-three sink_6_234578(volatile A&); // { dg-message "note" }
-four sink_6_234578(const volatile A&); // { dg-message "note" }
-five sink_6_234578( A&&); // { dg-message "note" }
-seven sink_6_234578(volatile A&&); // { dg-message "note" }
-eight sink_6_234578(const volatile A&&); // { dg-message "note" }
+two sink_6_234578(const A&);
+three sink_6_234578(volatile A&);
+four sink_6_234578(const volatile A&);
+five sink_6_234578( A&&);
+seven sink_6_234578(volatile A&&);
+eight sink_6_234578(const volatile A&&);
int test6_234578()
{
@@ -120,17 +114,16 @@ int test6_234578()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_234578(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 123 }
+ sink_6_234578(a); // { dg-error "" }
return 0;
}
-two sink_6_234568(const A&); // { dg-message "note" }
-three sink_6_234568(volatile A&); // { dg-message "note" }
-four sink_6_234568(const volatile A&); // { dg-message "note" }
-five sink_6_234568( A&&); // { dg-message "note" }
-six sink_6_234568(const A&&); // { dg-message "note" }
-eight sink_6_234568(const volatile A&&); // { dg-message "note" }
+two sink_6_234568(const A&);
+three sink_6_234568(volatile A&);
+four sink_6_234568(const volatile A&);
+five sink_6_234568( A&&);
+six sink_6_234568(const A&&);
+eight sink_6_234568(const volatile A&&);
int test6_234568()
{
@@ -138,17 +131,16 @@ int test6_234568()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_234568(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 141 }
+ sink_6_234568(a); // { dg-error "" }
return 0;
}
two sink_6_234567(const A&); // { dg-message "two sink_6_234567|no known conversion" }
-three sink_6_234567(volatile A&); // { dg-message "note" }
-four sink_6_234567(const volatile A&); // { dg-message "note" }
-five sink_6_234567( A&&); // { dg-message "note" }
-six sink_6_234567(const A&&); // { dg-message "note" }
-seven sink_6_234567(volatile A&&); // { dg-message "note" }
+three sink_6_234567(volatile A&);
+four sink_6_234567(const volatile A&);
+five sink_6_234567( A&&);
+six sink_6_234567(const A&&);
+seven sink_6_234567(volatile A&&);
int test6_234567()
{
@@ -156,19 +148,17 @@ int test6_234567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_234567(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 159 }
- sink_6_234567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 161 }
+ sink_6_234567(a); // { dg-error "" }
+ sink_6_234567(cv_source()); // { dg-error "" }
return 0;
}
one sink_6_134678( A&);
three sink_6_134678(volatile A&);
four sink_6_134678(const volatile A&);
-six sink_6_134678(const A&&); // { dg-message "note" }
-seven sink_6_134678(volatile A&&); // { dg-message "note" }
-eight sink_6_134678(const volatile A&&); // { dg-message "note" }
+six sink_6_134678(const A&&);
+seven sink_6_134678(volatile A&&);
+eight sink_6_134678(const volatile A&&);
int test6_134678()
{
@@ -176,17 +166,16 @@ int test6_134678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_134678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 179 }
+ sink_6_134678(source()); // { dg-error "" }
return 0;
}
one sink_6_124678( A&);
-two sink_6_124678(const A&); // { dg-message "note" }
+two sink_6_124678(const A&);
four sink_6_124678(const volatile A&);
-six sink_6_124678(const A&&); // { dg-message "note" }
-seven sink_6_124678(volatile A&&); // { dg-message "note" }
-eight sink_6_124678(const volatile A&&); // { dg-message "note" }
+six sink_6_124678(const A&&);
+seven sink_6_124678(volatile A&&);
+eight sink_6_124678(const volatile A&&);
int test6_124678()
{
@@ -194,16 +183,15 @@ int test6_124678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_124678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 197 }
+ sink_6_124678(source()); // { dg-error "" }
return 0;
}
one sink_6_123678( A&);
-two sink_6_123678(const A&); // { dg-message "note" }
+two sink_6_123678(const A&);
three sink_6_123678(volatile A&);
-six sink_6_123678(const A&&); // { dg-message "note" }
-seven sink_6_123678(volatile A&&); // { dg-message "note" }
+six sink_6_123678(const A&&);
+seven sink_6_123678(volatile A&&);
eight sink_6_123678(const volatile A&&); // { dg-message "" }
int test6_123678()
@@ -212,18 +200,17 @@ int test6_123678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_123678(cva); // { dg-error "lvalue" }
- sink_6_123678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 216 }
+ sink_6_123678(cva); // { dg-error "" }
+ sink_6_123678(source()); // { dg-error "" }
return 0;
}
one sink_6_123567( A&); // { dg-message "one sink_6_123567|no known conversion" }
-two sink_6_123567(const A&); // { dg-message "note" }
-three sink_6_123567(volatile A&); // { dg-message "note" }
-five sink_6_123567( A&&); // { dg-message "note" }
-six sink_6_123567(const A&&); // { dg-message "note" }
-seven sink_6_123567(volatile A&&); // { dg-message "note" }
+two sink_6_123567(const A&);
+three sink_6_123567(volatile A&);
+five sink_6_123567( A&&);
+six sink_6_123567(const A&&);
+seven sink_6_123567(volatile A&&);
int test6_123567()
{
@@ -231,10 +218,8 @@ int test6_123567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_123567(cva); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 234 }
- sink_6_123567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 236 }
+ sink_6_123567(cva); // { dg-error "" }
+ sink_6_123567(cv_source()); // { dg-error "" }
return 0;
}
@@ -251,7 +236,7 @@ int test6_123568()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_123568(cva); // { dg-error "lvalue" }
+ sink_6_123568(cva); // { dg-error "" }
return 0;
}
@@ -268,16 +253,16 @@ int test6_123578()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_123578(cva); // { dg-error "lvalue" }
+ sink_6_123578(cva); // { dg-error "" }
return 0;
}
one sink_6_123467( A&); // { dg-message "one sink_6_123467|no known conversion" }
-two sink_6_123467(const A&); // { dg-message "note" }
-three sink_6_123467(volatile A&); // { dg-message "note" }
-four sink_6_123467(const volatile A&); // { dg-message "note" }
-six sink_6_123467(const A&&); // { dg-message "note" }
-seven sink_6_123467(volatile A&&); // { dg-message "note" }
+two sink_6_123467(const A&);
+three sink_6_123467(volatile A&);
+four sink_6_123467(const volatile A&);
+six sink_6_123467(const A&&);
+seven sink_6_123467(volatile A&&);
int test6_123467()
{
@@ -285,19 +270,17 @@ int test6_123467()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_123467(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 288 }
- sink_6_123467(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 290 }
+ sink_6_123467(source()); // { dg-error "" }
+ sink_6_123467(cv_source()); // { dg-error "" }
return 0;
}
one sink_6_124567( A&); // { dg-message "one sink_6_124567|no known conversion" }
-two sink_6_124567(const A&); // { dg-message "note" }
-four sink_6_124567(const volatile A&); // { dg-message "note" }
-five sink_6_124567( A&&); // { dg-message "note" }
-six sink_6_124567(const A&&); // { dg-message "note" }
-seven sink_6_124567(volatile A&&); // { dg-message "note" }
+two sink_6_124567(const A&);
+four sink_6_124567(const volatile A&);
+five sink_6_124567( A&&);
+six sink_6_124567(const A&&);
+seven sink_6_124567(volatile A&&);
int test6_124567()
{
@@ -305,8 +288,7 @@ int test6_124567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_124567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 308 }
+ sink_6_124567(cv_source()); // { dg-error "" }
return 0;
}
@@ -323,17 +305,17 @@ int test6_125678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_125678(va); // { dg-error "lvalue" }
- sink_6_125678(cva); // { dg-error "lvalue" }
+ sink_6_125678(va); // { dg-error "" }
+ sink_6_125678(cva); // { dg-error "" }
return 0;
}
one sink_6_134567( A&); // { dg-message "one sink_6_134567|no known conversion" }
-three sink_6_134567(volatile A&); // { dg-message "note" }
-four sink_6_134567(const volatile A&); // { dg-message "note" }
-five sink_6_134567( A&&); // { dg-message "note" }
-six sink_6_134567(const A&&); // { dg-message "note" }
-seven sink_6_134567(volatile A&&); // { dg-message "note" }
+three sink_6_134567(volatile A&);
+four sink_6_134567(const volatile A&);
+five sink_6_134567( A&&);
+six sink_6_134567(const A&&);
+seven sink_6_134567(volatile A&&);
int test6_134567()
{
@@ -341,8 +323,7 @@ int test6_134567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_134567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 344 }
+ sink_6_134567(cv_source()); // { dg-error "" }
return 0;
}
@@ -359,8 +340,8 @@ int test6_135678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_6_135678(ca); // { dg-error "lvalue" }
- sink_6_135678(cva); // { dg-error "lvalue" }
+ sink_6_135678(ca); // { dg-error "" }
+ sink_6_135678(cva); // { dg-error "" }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv7n.C b/gcc/testsuite/g++.dg/cpp0x/rv7n.C
index 7e7a6648e23..38ca7b8aff2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv7n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv7n.C
@@ -31,12 +31,12 @@ const volatile A cv_source();
// 7 at a time
one sink_7_1234567( A&); // { dg-message "one sink_7_1234567|no known conversion" }
-two sink_7_1234567(const A&); // { dg-message "note" }
-three sink_7_1234567(volatile A&); // { dg-message "note" }
-four sink_7_1234567(const volatile A&); // { dg-message "note" }
-five sink_7_1234567( A&&); // { dg-message "note" }
-six sink_7_1234567(const A&&); // { dg-message "note" }
-seven sink_7_1234567(volatile A&&); // { dg-message "note" }
+two sink_7_1234567(const A&);
+three sink_7_1234567(volatile A&);
+four sink_7_1234567(const volatile A&);
+five sink_7_1234567( A&&);
+six sink_7_1234567(const A&&);
+seven sink_7_1234567(volatile A&&);
int test7_1234567()
{
@@ -44,8 +44,7 @@ int test7_1234567()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_7_1234567(cv_source()); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 47 }
+ sink_7_1234567(cv_source()); // { dg-error "" }
return 0;
}
@@ -63,17 +62,17 @@ int test7_1235678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_7_1235678(cva); // { dg-error "lvalue" }
+ sink_7_1235678(cva); // { dg-error "" }
return 0;
}
-two sink_7_2345678(const A&); // { dg-message "note" }
-three sink_7_2345678(volatile A&); // { dg-message "note" }
-four sink_7_2345678(const volatile A&); // { dg-message "note" }
-five sink_7_2345678( A&&); // { dg-message "note" }
-six sink_7_2345678(const A&&); // { dg-message "note" }
-seven sink_7_2345678(volatile A&&); // { dg-message "note" }
-eight sink_7_2345678(const volatile A&&); // { dg-message "note" }
+two sink_7_2345678(const A&);
+three sink_7_2345678(volatile A&);
+four sink_7_2345678(const volatile A&);
+five sink_7_2345678( A&&);
+six sink_7_2345678(const A&&);
+seven sink_7_2345678(volatile A&&);
+eight sink_7_2345678(const volatile A&&);
int test7_2345678()
{
@@ -81,18 +80,17 @@ int test7_2345678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_7_2345678(a); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 84 }
+ sink_7_2345678(a); // { dg-error "" }
return 0;
}
one sink_7_1234678( A&);
-two sink_7_1234678(const A&); // { dg-message "note" }
+two sink_7_1234678(const A&);
three sink_7_1234678(volatile A&);
four sink_7_1234678(const volatile A&);
-six sink_7_1234678(const A&&); // { dg-message "note" }
-seven sink_7_1234678(volatile A&&); // { dg-message "note" }
-eight sink_7_1234678(const volatile A&&); // { dg-message "note" }
+six sink_7_1234678(const A&&);
+seven sink_7_1234678(volatile A&&);
+eight sink_7_1234678(const volatile A&&);
int test7_1234678()
{
@@ -100,8 +98,7 @@ int test7_1234678()
const A ca = a; // { dg-error "deleted" }
volatile A va;
const volatile A cva = a; // { dg-error "deleted" }
- sink_7_1234678(source()); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 103 }
+ sink_7_1234678(source()); // { dg-error "" }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae50.C b/gcc/testsuite/g++.dg/cpp0x/sfinae50.C
new file mode 100644
index 00000000000..e8d90ca7681
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae50.C
@@ -0,0 +1,41 @@
+// PR c++/61083
+// { dg-do compile { target c++11 } }
+
+template<typename T> T declval();
+
+template<typename T, typename U>
+struct is_same {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> {
+ static const bool value = true;
+};
+
+struct true_type {};
+struct false_type {};
+
+template <typename T>
+struct is_foo {
+private:
+ template<typename U, U> struct helper {};
+
+ template <typename Z> static auto
+ test(Z z) -> decltype(helper<void (Z::*)() const, &Z::foo>(), true_type());
+
+ template <typename> static auto test(...) -> false_type;
+
+public:
+ enum { value = is_same<decltype(test<T>(declval<T>())), true_type>::value };
+};
+
+struct A {
+ int foo();
+ void foo() const;
+};
+
+struct A1 : public A {};
+
+static_assert (is_foo<A>::value == 1, "");
+static_assert (is_foo<A1>::value == 0, "");
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae51.C b/gcc/testsuite/g++.dg/cpp0x/sfinae51.C
new file mode 100644
index 00000000000..380811dce03
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae51.C
@@ -0,0 +1,28 @@
+// PR c++/59705
+// { dg-do compile { target c++11 } }
+
+struct HasIter {
+ typedef int * const_iterator;
+};
+
+struct NoIter {
+};
+
+template <typename T>
+constexpr bool foo(const T &, typename T::const_iterator *)
+{
+ return true;
+}
+
+template <typename T>
+constexpr bool foo(const T &, ...)
+{
+ return false;
+}
+
+HasIter has_iter;
+NoIter no_iter;
+
+static_assert (!foo(no_iter, 0), "");
+static_assert (foo(has_iter, 0), "");
+static_assert (foo<HasIter>(has_iter, 0), "");
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C
index 015d9d8403f..a887e339848 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C
@@ -1,5 +1,5 @@
// { dg-do compile { target c++11 } }
-template<class... Types> struct B { // { dg-error "declaration of" }
+template<class... Types> struct B { // { dg-message "declaration of" }
void f3();
void f4();
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic157.C b/gcc/testsuite/g++.dg/cpp0x/variadic157.C
new file mode 100644
index 00000000000..40aa3801d06
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic157.C
@@ -0,0 +1,28 @@
+// PR c++/58353
+// { dg-do compile { target c++11 } }
+
+template<class E, E V, int CNT>
+struct seq_t
+{
+ template<E... Es> struct seq{};
+
+ template<int N, E... Es>
+ struct gen : gen<N - 1, V, Es...>{};
+
+ template<E... Es>
+ struct gen<0, Es...> : seq<Es...>{};
+
+ struct bits_t{ E e[CNT]; };
+
+ template<E... Es>
+ static bits_t init(seq<Es...>) {return {{Es...}};}
+
+ static bits_t init() {return init(gen<CNT>{});}
+};
+
+typedef seq_t<int, 123, 5> wow;
+
+int main()
+{
+ wow::init();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35147.C b/gcc/testsuite/g++.dg/cpp0x/vt-35147.C
index 0827beee6ac..577b027b23d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-35147.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-35147.C
@@ -9,7 +9,6 @@ template<typename... Args>
void g(Args&&... args)
{
f(forward<Args...>(args...)); // { dg-error "no matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 11 }
}
void h()
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-init6.C b/gcc/testsuite/g++.dg/cpp1y/lambda-init6.C
index 2b82bca4578..e2530004f5c 100644
--- a/gcc/testsuite/g++.dg/cpp1y/lambda-init6.C
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-init6.C
@@ -1,12 +1,10 @@
-// Test that simple captures are not named in the closure type, but
-// initialized captures are named.
+// Test that captures are not named in the closure type.
// { dg-do compile { target c++1y } }
int main()
{
int i;
auto lam = [i,j=42]{};
- lam.j;
- lam.j.foo; // { dg-error "::j" }
+ lam.j; // { dg-error "no member" }
lam.i; // { dg-error "no member" }
}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-init8.C b/gcc/testsuite/g++.dg/cpp1y/lambda-init8.C
new file mode 100644
index 00000000000..3a61b74eaed
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-init8.C
@@ -0,0 +1,26 @@
+// DR1760: "no additional copy and destruction is performed"
+// { dg-do run { target c++1y } }
+
+#include <cassert>
+
+int copy_count = 0;
+int dtor_count = 0;
+
+struct X
+{
+ X() = default;
+ X(const X&) { ++copy_count; }
+ ~X() { ++dtor_count; }
+};
+
+int main()
+{
+ {
+ X x;
+ auto z = [y = x](){};
+ X x2;
+ auto z2 = [x2](){};
+ assert(copy_count == 2);
+ }
+ assert(dtor_count == 4);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-init9.C b/gcc/testsuite/g++.dg/cpp1y/lambda-init9.C
new file mode 100644
index 00000000000..c13a3d9e09e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-init9.C
@@ -0,0 +1,6 @@
+// { dg-do compile { target c++1y } }
+
+void f()
+{
+ [&x=1]{}; // { dg-error "cannot capture|invalid initialization" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60054.C b/gcc/testsuite/g++.dg/cpp1y/pr60054.C
new file mode 100644
index 00000000000..6b5179ac7dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr60054.C
@@ -0,0 +1,11 @@
+// PR c++/60054
+// { dg-do compile { target c++1y } }
+
+template<typename T> T fooA(T);
+template<typename T> decltype(T{}) fooB(T);
+
+void bar()
+{
+ fooA((auto*)0); // { dg-error "invalid use" }
+ fooB((auto*)0); // { dg-error "invalid use" }
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/pr13981.C b/gcc/testsuite/g++.dg/diagnostic/pr13981.C
new file mode 100644
index 00000000000..1b8a028d948
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/pr13981.C
@@ -0,0 +1,12 @@
+// PR c++/13981
+
+struct A {};
+struct B; // { dg-message "is incomplete" }
+
+void func( A *a );
+
+int main()
+{
+ B *b = 0;
+ func(b); // { dg-error "cannot convert" }
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/ref1.C b/gcc/testsuite/g++.dg/diagnostic/ref1.C
new file mode 100644
index 00000000000..36368ded018
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/ref1.C
@@ -0,0 +1,7 @@
+// PR c++/20332
+
+struct bar {};
+void foo1() {
+ bar& b = bar(); // { dg-error "rvalue" }
+}
+void foo(bar& b = bar()) {} // { dg-error "rvalue" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/ref2.C b/gcc/testsuite/g++.dg/diagnostic/ref2.C
new file mode 100644
index 00000000000..ded35e0d3af
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/ref2.C
@@ -0,0 +1,9 @@
+// PR c++/21631
+
+int f(int&);
+int f();
+
+int g(void)
+{
+ return f(1); // { dg-error "rvalue" }
+}
diff --git a/gcc/testsuite/g++.dg/eh/spec6.C b/gcc/testsuite/g++.dg/eh/spec6.C
index eb1177b07f5..d6d81762891 100644
--- a/gcc/testsuite/g++.dg/eh/spec6.C
+++ b/gcc/testsuite/g++.dg/eh/spec6.C
@@ -3,7 +3,7 @@
// { dg-options "-fpermissive -w" }
-struct A; // { dg-error "" }
+struct A; // { dg-message "" }
struct B
{
diff --git a/gcc/testsuite/g++.dg/expr/cast1.C b/gcc/testsuite/g++.dg/expr/cast1.C
index ee1adcc3d23..2f0e94fc698 100644
--- a/gcc/testsuite/g++.dg/expr/cast1.C
+++ b/gcc/testsuite/g++.dg/expr/cast1.C
@@ -1,3 +1,3 @@
-struct S; // { dg-error "forward" }
+struct S; // { dg-message "forward" }
void f(S* p) { ((S) (*p)); } // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/expr/cond10.C b/gcc/testsuite/g++.dg/expr/cond10.C
new file mode 100644
index 00000000000..892576fa8b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/cond10.C
@@ -0,0 +1,17 @@
+// PR c++/32019
+
+struct C
+{
+ C(const char *);
+ operator const char *();
+};
+
+extern C c;
+extern const char * s;
+
+void
+foo (bool b)
+{
+ b ? c : s; // { dg-error "?:" }
+ // { dg-message "convert" "" { target *-*-* } 15 }
+}
diff --git a/gcc/testsuite/g++.dg/expr/cond11.C b/gcc/testsuite/g++.dg/expr/cond11.C
new file mode 100644
index 00000000000..7bd122ddac5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/cond11.C
@@ -0,0 +1,20 @@
+struct A;
+struct C
+{
+ operator A();
+};
+
+struct A
+{
+ A(C);
+};
+
+extern A a;
+extern C c;
+
+void
+foo (bool b)
+{
+ b ? c : a; // { dg-error "?:" }
+ // { dg-message "ambiguous" "" { target *-*-* } 18 }
+}
diff --git a/gcc/testsuite/g++.dg/expr/cond12.C b/gcc/testsuite/g++.dg/expr/cond12.C
new file mode 100644
index 00000000000..9134f81668f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/cond12.C
@@ -0,0 +1,12 @@
+// PR c++/58714
+// { dg-do run }
+
+struct X {
+ X& operator=(const X&){}
+ X& operator=(X&){__builtin_abort();}
+};
+
+int main(int argv,char**) {
+ X a, b;
+ ((argv > 2) ? a : b) = X();
+}
diff --git a/gcc/testsuite/g++.dg/expr/cond13.C b/gcc/testsuite/g++.dg/expr/cond13.C
new file mode 100644
index 00000000000..90ae904a5d6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/cond13.C
@@ -0,0 +1,9 @@
+// PR c++/54348
+
+struct A {} a;
+struct B {} b;
+
+void f()
+{
+ false ? a : b; // { dg-error "different types" }
+}
diff --git a/gcc/testsuite/g++.dg/expr/cond14.C b/gcc/testsuite/g++.dg/expr/cond14.C
new file mode 100644
index 00000000000..52762879421
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/cond14.C
@@ -0,0 +1,6 @@
+// DR 587
+// PR c++/51317
+
+int x = 1;
+int const y = 2;
+int const *p = &(1 ? x : y); // error: lvalue required as unary '&' operand
diff --git a/gcc/testsuite/g++.dg/expr/cond8.C b/gcc/testsuite/g++.dg/expr/cond8.C
index 3e089537ff8..11b090dfc54 100644
--- a/gcc/testsuite/g++.dg/expr/cond8.C
+++ b/gcc/testsuite/g++.dg/expr/cond8.C
@@ -1,13 +1,12 @@
// PR c++/22434
-// { dg-options "" }
struct A
{
- A(void*); // { dg-message "initializing" }
+ A(void*);
~A();
};
void foo(const int i, bool b)
{
- b ? A(0) : i; // { dg-error "conversion" }
+ b ? A(0) : i; // { dg-error "" }
}
diff --git a/gcc/testsuite/g++.dg/expr/cond9.C b/gcc/testsuite/g++.dg/expr/cond9.C
index e8e1397c06e..b344c1f683a 100644
--- a/gcc/testsuite/g++.dg/expr/cond9.C
+++ b/gcc/testsuite/g++.dg/expr/cond9.C
@@ -1,12 +1,10 @@
// PR c++/27666
struct A { // { dg-message "A" }
- A(int); // { dg-message "A" }
+ A(int);
};
void foo(volatile A a) {
- 1 ? a : 0; // { dg-error "match|temporary" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 8 }
- 1 ? 0 : a; // { dg-error "match|temporary" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 10 }
+ 1 ? a : 0; // { dg-error "qualifiers|lvalue|no match" }
+ 1 ? 0 : a; // { dg-error "qualifiers|lvalue|no match" }
}
diff --git a/gcc/testsuite/g++.dg/expr/dtor1.C b/gcc/testsuite/g++.dg/expr/dtor1.C
index 0775a93c91b..5570f786a64 100644
--- a/gcc/testsuite/g++.dg/expr/dtor1.C
+++ b/gcc/testsuite/g++.dg/expr/dtor1.C
@@ -1,4 +1,4 @@
-class Foo; // { dg-error "" }
+class Foo; // { dg-message "" }
void
bar(void* p)
diff --git a/gcc/testsuite/g++.dg/expr/pmf-1.C b/gcc/testsuite/g++.dg/expr/pmf-1.C
index 3dd01c6b90f..90f34314100 100644
--- a/gcc/testsuite/g++.dg/expr/pmf-1.C
+++ b/gcc/testsuite/g++.dg/expr/pmf-1.C
@@ -15,6 +15,5 @@ struct A
void (A::*p)() = &A::f;
void (A::*q)() = &(A::f); // { dg-error "parenthesized" "" }
foo(&g<int>); // { dg-error "no matching" "" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 17 }
}
};
diff --git a/gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C b/gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C
index 4ccc72b9e94..aac6cfba480 100644
--- a/gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C
+++ b/gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C
@@ -1,7 +1,7 @@
class A
{ };
-class B; // { dg-error "forward declaration" }
+class B; // { dg-message "forward declaration" }
union C
{ };
diff --git a/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C b/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C
index ecc5ec224b3..b60ce84dcb2 100644
--- a/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C
+++ b/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C
@@ -1,6 +1,6 @@
// PR c++/39475
-struct I; // { dg-error "forward declaration" }
+struct I; // { dg-message "forward declaration" }
struct C { };
bool nas1 = __has_nothrow_assign(I); // { dg-error "incomplete type" }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/redecl1.C b/gcc/testsuite/g++.dg/ext/visibility/redecl1.C
index b53335ef583..a85e6c38e95 100644
--- a/gcc/testsuite/g++.dg/ext/visibility/redecl1.C
+++ b/gcc/testsuite/g++.dg/ext/visibility/redecl1.C
@@ -3,5 +3,5 @@
struct __attribute((visibility("hidden"))) B;
struct __attribute((visibility("default"))) B; // { dg-error "visibility" }
-__attribute ((visibility ("hidden"))) void f(); // { dg-warning "previous" }
+__attribute ((visibility ("hidden"))) void f(); // { dg-message "previous" }
__attribute ((visibility ("default"))) void f(); // { dg-warning "visibility" }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/visibility-7.C b/gcc/testsuite/g++.dg/ext/visibility/visibility-7.C
index ae4589397b6..0a6e4ba637b 100644
--- a/gcc/testsuite/g++.dg/ext/visibility/visibility-7.C
+++ b/gcc/testsuite/g++.dg/ext/visibility/visibility-7.C
@@ -4,7 +4,7 @@
extern int
__attribute__((visibility ("hidden")))
-xyzzy; /* { dg-warning "previous declaration here" "" } */
+xyzzy; /* { dg-message "previous declaration" "" } */
int
__attribute__((visibility ("protected")))
diff --git a/gcc/testsuite/g++.dg/fstack-protector-strong.C b/gcc/testsuite/g++.dg/fstack-protector-strong.C
index a4f0f816310..5a820ed69d8 100644
--- a/gcc/testsuite/g++.dg/fstack-protector-strong.C
+++ b/gcc/testsuite/g++.dg/fstack-protector-strong.C
@@ -32,4 +32,52 @@ int foo2 ()
return global_func (a);
}
-/* { dg-final { scan-assembler-times "stack_chk_fail" 2 } } */
+/* Frame addressed exposed through return slot. */
+
+struct B
+{
+ /* Discourage passing this struct in registers. */
+ int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
+ int method ();
+ B return_slot();
+};
+
+B global_func ();
+void noop ();
+
+int foo3 ()
+{
+ return global_func ().a1;
+}
+
+int foo4 ()
+{
+ try {
+ noop ();
+ return 0;
+ } catch (...) {
+ return global_func ().a1;
+ }
+}
+
+int foo5 ()
+{
+ try {
+ return global_func ().a1;
+ } catch (...) {
+ return 0;
+ }
+}
+
+int foo6 ()
+{
+ B b;
+ return b.method ();
+}
+
+int foo7 (B *p)
+{
+ return p->return_slot ().a1;
+}
+
+/* { dg-final { scan-assembler-times "stack_chk_fail" 7 } } */
diff --git a/gcc/testsuite/g++.dg/gomp/pr26690-1.C b/gcc/testsuite/g++.dg/gomp/pr26690-1.C
index 17e01b3d553..403ff52e83e 100644
--- a/gcc/testsuite/g++.dg/gomp/pr26690-1.C
+++ b/gcc/testsuite/g++.dg/gomp/pr26690-1.C
@@ -11,6 +11,5 @@ foo ()
{
A a(0);
#pragma omp parallel private (a) // { dg-error "no matching function" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 13 }
;
}
diff --git a/gcc/testsuite/g++.dg/gomp/pr26690-2.C b/gcc/testsuite/g++.dg/gomp/pr26690-2.C
index ca01a3a5954..ec93cd11a24 100644
--- a/gcc/testsuite/g++.dg/gomp/pr26690-2.C
+++ b/gcc/testsuite/g++.dg/gomp/pr26690-2.C
@@ -12,6 +12,5 @@ foo ()
{
A a(6);
#pragma omp parallel private (a) // { dg-error "call of overloaded" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 14 }
;
}
diff --git a/gcc/testsuite/g++.dg/gomp/pr49223-2.C b/gcc/testsuite/g++.dg/gomp/pr49223-2.C
index 95397733ebe..b367b0419b8 100644
--- a/gcc/testsuite/g++.dg/gomp/pr49223-2.C
+++ b/gcc/testsuite/g++.dg/gomp/pr49223-2.C
@@ -3,7 +3,7 @@
// { dg-require-effective-target tls }
// { dg-options "-fopenmp" }
-struct S; // { dg-error "forward declaration" }
+struct S; // { dg-message "forward declaration" }
extern __thread struct S s; // { dg-error "has incomplete type" }
struct T;
extern __thread struct T t;
diff --git a/gcc/testsuite/g++.dg/gomp/udr-4.C b/gcc/testsuite/g++.dg/gomp/udr-4.C
index f1b388bbd91..566d7d1321f 100644
--- a/gcc/testsuite/g++.dg/gomp/udr-4.C
+++ b/gcc/testsuite/g++.dg/gomp/udr-4.C
@@ -1,6 +1,6 @@
// { dg-do compile }
-struct S; // { dg-error "forward declaration" }
+struct S; // { dg-message "forward declaration" }
#pragma omp declare reduction (+:S:omp_out.s += omp_in.s) // { dg-error "invalid use of incomplete type" }
struct S { int s; S () : s (1) {} };
#pragma omp declare reduction (*:S:omp_out.s *= omp_in.s)
diff --git a/gcc/testsuite/g++.dg/init/copy7.C b/gcc/testsuite/g++.dg/init/copy7.C
new file mode 100644
index 00000000000..655fae21e66
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/copy7.C
@@ -0,0 +1,9 @@
+// CWG 5
+
+struct C { };
+C c;
+struct A {
+ A(const A&);
+ A(const C&);
+};
+const volatile A a = c; // Okay
diff --git a/gcc/testsuite/g++.dg/init/delete1.C b/gcc/testsuite/g++.dg/init/delete1.C
index 304dca1caf9..8236abcd6fe 100644
--- a/gcc/testsuite/g++.dg/init/delete1.C
+++ b/gcc/testsuite/g++.dg/init/delete1.C
@@ -1,6 +1,6 @@
// PR c++/19811
-class C; // { dg-warning "forward" }
+class C; // { dg-message "forward" }
void foo(void *p) {
delete [] ((C*)p) ; // { dg-warning "problem|incomplete" }
diff --git a/gcc/testsuite/g++.dg/init/synth2.C b/gcc/testsuite/g++.dg/init/synth2.C
index ed504671559..cc6cce0e4a1 100644
--- a/gcc/testsuite/g++.dg/init/synth2.C
+++ b/gcc/testsuite/g++.dg/init/synth2.C
@@ -1,12 +1,11 @@
// PR c++/34180
struct G {
- G(); // { dg-message "" "candidate" }
+ G();
G(G&); // { dg-message "" "candidate" }
};
class A // { dg-error "" }
-// { dg-message "candidate" "candidate note" { target *-*-* } 8 }
{
const G g;
};
diff --git a/gcc/testsuite/g++.dg/ipa/comdat.C b/gcc/testsuite/g++.dg/ipa/comdat.C
new file mode 100644
index 00000000000..40a607f9368
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/comdat.C
@@ -0,0 +1,15 @@
+/* { dg-do compile { target *-*-linux* *-*-gnu* } } */
+/* { dg-options "-O2 -fdump-ipa-comdats" } */
+#include <stdio.h>
+__attribute__ ((noinline))
+static int q(void)
+{
+ return printf ("test");
+}
+inline int t(void)
+{
+ return q();
+}
+int (*f)()=t;
+/* { dg-final { scan-ipa-dump-times "Localizing symbol" 1 "comdats" } } */
+/* { dg-final { cleanup-ipa-dump "comdats" } } */
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-11.C b/gcc/testsuite/g++.dg/ipa/devirt-11.C
index d30d56cff24..3246e214f14 100644
--- a/gcc/testsuite/g++.dg/ipa/devirt-11.C
+++ b/gcc/testsuite/g++.dg/ipa/devirt-11.C
@@ -42,8 +42,7 @@ bar ()
baz ();
c + d;
}
-/* While inlining function called once we should devirtualize a new call to fn2
- and two to fn3. While doing so the new symbol for fn2 needs to be
- introduced. */
-/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 3 "inline" } } */
+/* While inlining function called once we should devirtualize a new call to fn3.
+ Because fn2 is already removed, we should not devirtualize. */
+/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 1 "inline" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-15.C b/gcc/testsuite/g++.dg/ipa/devirt-15.C
index 2ea85f487f4..924564661b8 100644
--- a/gcc/testsuite/g++.dg/ipa/devirt-15.C
+++ b/gcc/testsuite/g++.dg/ipa/devirt-15.C
@@ -1,7 +1,7 @@
/* Check that we speculatively devirutalize call to FOO to B::foo becuase
A is noreturn. */
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-ipa-devirt -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fdump-ipa-devirt-details -fdump-tree-optimized" } */
class A {
public:
virtual int foo(void)
@@ -33,7 +33,7 @@ main()
m();
}
-/* { dg-final { scan-ipa-dump "Speculatively devirtualizing call" "devirt"} } */
+/* { dg-final { scan-ipa-dump "speculatively devirtualizing call" "devirt"} } */
/* { dg-final { cleanup-ipa-dump "devirt" } } */
/* Match if (PROF_6 == foo) to verify that the speculation survived. */
/* { dg-final { scan-tree-dump "== foo" "optimized"} } */
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-16.C b/gcc/testsuite/g++.dg/ipa/devirt-16.C
index 85567867ff1..dd7696e6f55 100644
--- a/gcc/testsuite/g++.dg/ipa/devirt-16.C
+++ b/gcc/testsuite/g++.dg/ipa/devirt-16.C
@@ -1,7 +1,7 @@
/* We shall devirtualize to unreachable. No anonymous type method should surivve
reachability. */
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-ipa-whole-program" } */
+/* { dg-options "-O2 -fdump-ipa-whole-program-details" } */
namespace {
class B {
public:
@@ -32,7 +32,7 @@ main()
return b->foo();
}
-/* { dg-final { scan-ipa-dump "Devirtualizing" "whole-program"} } */
+/* { dg-final { scan-ipa-dump "devirtualizing" "whole-program"} } */
/* { dg-final { scan-ipa-dump "builtin_unreachable" "whole-program"} } */
/* { dg-final { scan-ipa-dump-not "A::foo" "whole-program"} } */
/* { dg-final { scan-ipa-dump-not "A::foo" "whole-program"} } */
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-17.C b/gcc/testsuite/g++.dg/ipa/devirt-17.C
index 9edfd73af56..ce7943a8464 100644
--- a/gcc/testsuite/g++.dg/ipa/devirt-17.C
+++ b/gcc/testsuite/g++.dg/ipa/devirt-17.C
@@ -1,7 +1,7 @@
/* We shall devirtualize to B::foo since it is the only live candidate of an
anonymous type. */
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-ipa-whole-program" } */
+/* { dg-options "-O2 -fdump-ipa-whole-program-details" } */
namespace {
class B {
public:
@@ -37,7 +37,7 @@ main()
return b->foo();
}
-/* { dg-final { scan-ipa-dump "Devirtualizing" "whole-program"} } */
+/* { dg-final { scan-ipa-dump "devirtualizing" "whole-program"} } */
/* { dg-final { scan-ipa-dump-not "builtin_unreachable" "whole-program"} } */
/* { dg-final { scan-ipa-dump "B::foo" "whole-program"} } */
/* { dg-final { scan-ipa-dump-not "A::foo" "whole-program"} } */
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-26.C b/gcc/testsuite/g++.dg/ipa/devirt-26.C
index 2df429c3457..469a1402d25 100644
--- a/gcc/testsuite/g++.dg/ipa/devirt-26.C
+++ b/gcc/testsuite/g++.dg/ipa/devirt-26.C
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -fdump-ipa-devirt" } */
+/* { dg-options "-O3 -fdump-ipa-devirt-details" } */
struct A
{
int a;
@@ -25,5 +25,5 @@ int test(void)
/* The call to b->foo() is perfectly devirtualizable because C can not be in construction
when &c was used, but we can not analyze that so far. Test that we at least speculate
that type is in the construction. */
-/* { dg-final { scan-ipa-dump "Speculatively devirtualizing" "devirt" } } */
+/* { dg-final { scan-ipa-dump "speculatively devirtualizing" "devirt" } } */
/* { dg-final { cleanup-ipa-dump "devirt" } } */
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-33.C b/gcc/testsuite/g++.dg/ipa/devirt-33.C
new file mode 100644
index 00000000000..970a96b88d8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/devirt-33.C
@@ -0,0 +1,78 @@
+/* Verify we do not devirtualize wrongly to __cxa_pure_virtual */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -std=c++11" } */
+
+
+inline void* operator new(__SIZE_TYPE__ s, void* buf) throw() {
+ return buf;
+}
+
+class A {
+
+private:
+ struct Base {
+ virtual ~Base() {}
+ virtual Base *Clone(void *buf) const = 0;
+ virtual float *Allocate(__SIZE_TYPE__ count) = 0;
+ };
+
+ struct Value : Base {
+ virtual ~Value (){}
+ Base *Clone(void* buf) const override {
+ return new (buf) Value();
+ }
+
+ float *Allocate(__SIZE_TYPE__ count) override {
+ return new float[count];
+ }
+ };
+
+public:
+ A() {
+ new (buffer_) Value();
+ }
+ A(const A& other) {
+ other.ptr()->Clone(buffer_);
+ }
+
+ float *Allocate() {
+ return ptr()->Allocate(100);
+ }
+ const Base *ptr() const { return reinterpret_cast<const Base*>(buffer_);}
+ Base *ptr() { return reinterpret_cast< Base*>(buffer_);}
+
+private:
+ alignas(16) char buffer_[1024];
+};
+
+
+struct B {
+ B (const A& a) : a_(a) {
+ buff_ = a_.Allocate();
+ }
+
+ float *buff_;
+ A a_;
+};
+
+struct Dummy {
+ int i;
+};
+
+struct D : public Dummy {
+ __attribute__((noinline)) D( const A&a);
+
+ B b_;
+};
+
+D::D(const A&a) : b_(a) {}
+
+int main()
+{
+ A a;
+ D d(a);
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/ipa/imm-devirt-1.C b/gcc/testsuite/g++.dg/ipa/imm-devirt-1.C
index 32f7258a452..9307d96db09 100644
--- a/gcc/testsuite/g++.dg/ipa/imm-devirt-1.C
+++ b/gcc/testsuite/g++.dg/ipa/imm-devirt-1.C
@@ -58,5 +58,5 @@ int main (int argc, char *argv[])
return 0;
}
-/* { dg-final { scan-tree-dump "Replacing call target with foo" "fre1" } } */
+/* { dg-final { scan-tree-dump "converting indirect call to function virtual int B::foo" "fre1" } } */
/* { dg-final { cleanup-tree-dump "fre1" } } */
diff --git a/gcc/testsuite/g++.dg/ipa/imm-devirt-2.C b/gcc/testsuite/g++.dg/ipa/imm-devirt-2.C
index 5bddc2fcb26..079aa4b6f15 100644
--- a/gcc/testsuite/g++.dg/ipa/imm-devirt-2.C
+++ b/gcc/testsuite/g++.dg/ipa/imm-devirt-2.C
@@ -91,5 +91,5 @@ int main (int argc, char *argv[])
return 0;
}
-/* { dg-final { scan-tree-dump "Replacing call target" "fre1" } } */
+/* { dg-final { scan-tree-dump "converting indirect call to function" "fre1" } } */
/* { dg-final { cleanup-tree-dump "fre1" } } */
diff --git a/gcc/testsuite/g++.dg/ipa/pr61085.C b/gcc/testsuite/g++.dg/ipa/pr61085.C
new file mode 100644
index 00000000000..531f59d5302
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr61085.C
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-early-inlining" } */
+
+struct A {};
+struct B : virtual A {
+ unsigned m_i;
+ B() : m_i () {}
+ virtual A *m_virt ()
+ {
+ return 0;
+ }
+ ~B ()
+ {
+ m_foo ();
+ while (m_i)
+ ;
+ }
+ void m_foo ()
+ {
+ m_virt ();
+ }
+};
+
+class C : B {
+ A *m_virt () {
+ __builtin_abort ();
+ }
+};
+
+int main ()
+{
+ C c;
+}
diff --git a/gcc/testsuite/g++.dg/lookup/conv-1.C b/gcc/testsuite/g++.dg/lookup/conv-1.C
index 0c4393e8a40..b861c6036df 100644
--- a/gcc/testsuite/g++.dg/lookup/conv-1.C
+++ b/gcc/testsuite/g++.dg/lookup/conv-1.C
@@ -22,6 +22,5 @@ struct B : A1, A2
int Foo (B const &b)
{
return b; // { dg-error "ambiguous" "" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 24 }
}
diff --git a/gcc/testsuite/g++.dg/lookup/new1.C b/gcc/testsuite/g++.dg/lookup/new1.C
index 11a6d97ddf7..3c3b02b3d81 100644
--- a/gcc/testsuite/g++.dg/lookup/new1.C
+++ b/gcc/testsuite/g++.dg/lookup/new1.C
@@ -6,7 +6,6 @@ int main() {
int i;
void* operator new(__SIZE_TYPE__ s, int* p);
int* e = new(&i) int; // { dg-error "no matching function" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 8 }
int* f = new int;
return 0;
}
diff --git a/gcc/testsuite/g++.dg/lookup/two-stage4.C b/gcc/testsuite/g++.dg/lookup/two-stage4.C
index bbb44afa0d0..7d971094d1a 100644
--- a/gcc/testsuite/g++.dg/lookup/two-stage4.C
+++ b/gcc/testsuite/g++.dg/lookup/two-stage4.C
@@ -3,15 +3,15 @@
template<class T> struct wrap {};
-template<typename T> bool& operator==(wrap<T>, wrap<T>);
+template<typename T> bool operator==(wrap<T>, wrap<T>);
template<typename T>
void g(T, wrap<wrap<int> > x)
{
- bool& b = x == x; // { dg-bogus "invalid initialization of reference" "" { xfail *-*-*} }
+ bool b = x == x; // { dg-bogus "" "" { xfail *-*-* } }
}
-template<typename T> int& operator==(wrap<wrap<T> >, wrap<wrap<T> >);
+template<typename T> void operator==(wrap<wrap<T> >, wrap<wrap<T> >);
void h()
{
diff --git a/gcc/testsuite/g++.dg/lookup/using9.C b/gcc/testsuite/g++.dg/lookup/using9.C
index fd3e788638e..7b0ccd1f604 100644
--- a/gcc/testsuite/g++.dg/lookup/using9.C
+++ b/gcc/testsuite/g++.dg/lookup/using9.C
@@ -20,7 +20,6 @@ void h()
using C::f;
f('h');
f(1); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 22 }
void f(int); // { dg-error "previous declaration" }
}
diff --git a/gcc/testsuite/g++.dg/other/crash-2.C b/gcc/testsuite/g++.dg/other/crash-2.C
index 961a18a2384..b8645b09309 100644
--- a/gcc/testsuite/g++.dg/other/crash-2.C
+++ b/gcc/testsuite/g++.dg/other/crash-2.C
@@ -3,7 +3,7 @@
// Contributed by Hans Buchmann <hans dot buchmann at fhso dot ch>
// PR c++/14033: ICE while inlining a function with incomplete parameter
-struct A; // { dg-error "forward declaration" }
+struct A; // { dg-message "forward declaration" }
void foo(A a) {} // { dg-error "incomplete" }
struct A {};
diff --git a/gcc/testsuite/g++.dg/other/error13.C b/gcc/testsuite/g++.dg/other/error13.C
index 4ee935ad609..efda0863298 100644
--- a/gcc/testsuite/g++.dg/other/error13.C
+++ b/gcc/testsuite/g++.dg/other/error13.C
@@ -7,6 +7,5 @@ struct A // { dg-message "note" }
};
struct B : A {}; // { dg-error "no matching function for call|deleted" }
-// { dg-message "candidate" "candidate note" { target *-*-* } 9 }
B b; // { dg-message "synthesized method|deleted" }
diff --git a/gcc/testsuite/g++.dg/other/error20.C b/gcc/testsuite/g++.dg/other/error20.C
index bb7d7b3b078..dab6de40e4f 100644
--- a/gcc/testsuite/g++.dg/other/error20.C
+++ b/gcc/testsuite/g++.dg/other/error20.C
@@ -9,5 +9,4 @@ struct A // { dg-message "operator=|no known conversion" }
void bar (A& a)
{
a.foo () = 0; // { dg-error "operand types are 'A' and 'int'" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 11 }
}
diff --git a/gcc/testsuite/g++.dg/other/error31.C b/gcc/testsuite/g++.dg/other/error31.C
index 95c9d737413..fd428bf46d6 100644
--- a/gcc/testsuite/g++.dg/other/error31.C
+++ b/gcc/testsuite/g++.dg/other/error31.C
@@ -10,5 +10,4 @@ foo ()
{
A a;
a = ({ { 1; } }); // { dg-error "no match for" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 12 }
}
diff --git a/gcc/testsuite/g++.dg/other/i386-2.C b/gcc/testsuite/g++.dg/other/i386-2.C
index 2f8650a66b0..b205c3d466d 100644
--- a/gcc/testsuite/g++.dg/other/i386-2.C
+++ b/gcc/testsuite/g++.dg/other/i386-2.C
@@ -1,5 +1,5 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1" } */
+/* { dg-options "-O -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt" } */
/* Test that {,x,e,p,t,s,w,a,b,i}mmintrin.h, mm3dnow.h, fma4intrin.h,
xopintrin.h, abmintrin.h, bmiintrin.h, tbmintrin.h, lwpintrin.h,
diff --git a/gcc/testsuite/g++.dg/other/i386-3.C b/gcc/testsuite/g++.dg/other/i386-3.C
index df0bd279790..aa94a481327 100644
--- a/gcc/testsuite/g++.dg/other/i386-3.C
+++ b/gcc/testsuite/g++.dg/other/i386-3.C
@@ -1,5 +1,5 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O -fkeep-inline-functions -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1" } */
+/* { dg-options "-O -fkeep-inline-functions -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt" } */
/* Test that {,x,e,p,t,s,w,a,b,i}mmintrin.h, mm3dnow.h, fma4intrin.h,
xopintrin.h, abmintrin.h, bmiintrin.h, tbmintrin.h, lwpintrin.h,
diff --git a/gcc/testsuite/g++.dg/other/pr28114.C b/gcc/testsuite/g++.dg/other/pr28114.C
index 63ecbf51f4f..d54fec96085 100644
--- a/gcc/testsuite/g++.dg/other/pr28114.C
+++ b/gcc/testsuite/g++.dg/other/pr28114.C
@@ -6,5 +6,4 @@ template<int> void foo(struct {}*); // { dg-message "" }
void bar()
{
foo<0>(0); // { dg-error "" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 8 }
}
diff --git a/gcc/testsuite/g++.dg/overload/ambig1.C b/gcc/testsuite/g++.dg/overload/ambig1.C
index d11e00a187b..21948bf3146 100644
--- a/gcc/testsuite/g++.dg/overload/ambig1.C
+++ b/gcc/testsuite/g++.dg/overload/ambig1.C
@@ -20,5 +20,4 @@ void f(B); // { dg-message "note" "candidate" }
int main()
{
f (42); // { dg-error "ambiguous" "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 22 }
}
diff --git a/gcc/testsuite/g++.dg/overload/arg3.C b/gcc/testsuite/g++.dg/overload/arg3.C
index 34624cd22e4..1684fccf5c7 100644
--- a/gcc/testsuite/g++.dg/overload/arg3.C
+++ b/gcc/testsuite/g++.dg/overload/arg3.C
@@ -10,14 +10,13 @@ struct A {};
struct B : A
{
- B(int); // { dg-message "B::B|no known conversion" "" }
+ B(int);
B(B&); // { dg-message "note" "" }
};
-void foo(B); // { dg-error "initializing" }
+void foo(B); // { dg-message "initializing" }
void bar()
{
- foo(0); // { dg-error "no matching function" "no matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 21 }
+ foo(0); // { dg-error "" }
}
diff --git a/gcc/testsuite/g++.dg/overload/builtin1.C b/gcc/testsuite/g++.dg/overload/builtin1.C
index fdd208135c7..72080ea444a 100644
--- a/gcc/testsuite/g++.dg/overload/builtin1.C
+++ b/gcc/testsuite/g++.dg/overload/builtin1.C
@@ -14,5 +14,4 @@ int main ()
A a;
a + a; // { dg-error "ambiguous" "ambiguous" }
// { dg-message "operator" "match candidate text" { target *-*-* } 15 }
- // { dg-message "candidates" "candidates" { target *-*-* } 15 }
}
diff --git a/gcc/testsuite/g++.dg/overload/conv-op1.C b/gcc/testsuite/g++.dg/overload/conv-op1.C
index 6a63cbaeb87..cd8d9f481ec 100644
--- a/gcc/testsuite/g++.dg/overload/conv-op1.C
+++ b/gcc/testsuite/g++.dg/overload/conv-op1.C
@@ -11,7 +11,7 @@ void f()
{
const int i = 42;
A()(i); // { dg-message "<conversion>" }
+ // { dg-error "qualifiers" "" { target *-*-* } 13 }
}
// { dg-prune-output "no match" }
-// { dg-prune-output "candidate" }
diff --git a/gcc/testsuite/g++.dg/overload/copy1.C b/gcc/testsuite/g++.dg/overload/copy1.C
index f0ec385fc9c..5c7922f8330 100644
--- a/gcc/testsuite/g++.dg/overload/copy1.C
+++ b/gcc/testsuite/g++.dg/overload/copy1.C
@@ -4,18 +4,17 @@ struct A;
struct B
{
- B (A const &); // { dg-message "note" }
+ B (A const &);
B (B &); // { dg-message "note" }
};
struct A
{
- A (B); // { dg-error "initializing" }
+ A (B); // { dg-message "initializing" }
};
B
f (B const& b)
{
- return b; // { dg-error "matching" "matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 19 }
+ return b; // { dg-error "" }
}
diff --git a/gcc/testsuite/g++.dg/overload/new1.C b/gcc/testsuite/g++.dg/overload/new1.C
index bf2190b8e05..0cfbfc4bf15 100644
--- a/gcc/testsuite/g++.dg/overload/new1.C
+++ b/gcc/testsuite/g++.dg/overload/new1.C
@@ -16,6 +16,5 @@ void f(X *x = new X[4]); // { dg-error "" }
void f(X *x = new (3) X(6)); // { dg-error "" }
void f(X *x = new (2) X[10]); // { dg-error "" }
-// { dg-message "candidate" "candidate note" { target *-*-* } 18 }
void f(X *x = new X[10][5]); // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/overload/template4.C b/gcc/testsuite/g++.dg/overload/template4.C
index 8f00d4171d4..7c49c6d3641 100644
--- a/gcc/testsuite/g++.dg/overload/template4.C
+++ b/gcc/testsuite/g++.dg/overload/template4.C
@@ -16,9 +16,6 @@ void
test ()
{
foo <0> (0); // { dg-error "is ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 18 }
bar <1> (0, 1); // { dg-error "is ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 20 }
baz (0); // { dg-error "is ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 22 }
}
diff --git a/gcc/testsuite/g++.dg/overload/using2.C b/gcc/testsuite/g++.dg/overload/using2.C
index d1824548ad5..579e4e6a4d6 100644
--- a/gcc/testsuite/g++.dg/overload/using2.C
+++ b/gcc/testsuite/g++.dg/overload/using2.C
@@ -73,12 +73,10 @@ int main () {
exit (0);
_exit (0); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 75 }
abort ();
c1 ();
C1 (); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 80 }
c2 ();
C2 (); // one might expect an ambiguous call error here as well, but
@@ -86,7 +84,6 @@ int main () {
c3 ();
C3 (); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 88 }
C3 (0);
C3 (0l);
}
diff --git a/gcc/testsuite/g++.dg/overload/volatile1.C b/gcc/testsuite/g++.dg/overload/volatile1.C
index baf467d8182..0426b8f361d 100644
--- a/gcc/testsuite/g++.dg/overload/volatile1.C
+++ b/gcc/testsuite/g++.dg/overload/volatile1.C
@@ -1,14 +1,13 @@
// PR c++/48118
-// { dg-prune-output "note" }
struct A { };
-void f (A); // { dg-error "argument 1" }
+void f (A); // { dg-message "" }
void (*g)(A);
int main()
{
volatile A a;
- f(a); // { dg-error "no match" }
- g(a); // { dg-error "no match" }
+ f(a); // { dg-error "" }
+ g(a); // { dg-error "" }
}
diff --git a/gcc/testsuite/g++.dg/parse/crash24.C b/gcc/testsuite/g++.dg/parse/crash24.C
index fdc4f1e7c9d..d0804b13381 100644
--- a/gcc/testsuite/g++.dg/parse/crash24.C
+++ b/gcc/testsuite/g++.dg/parse/crash24.C
@@ -1,6 +1,6 @@
// PR c++/20461
// { dg-do compile }
-class C; // { dg-error "forward declaration" }
+class C; // { dg-message "forward declaration" }
C::C() : f() {} // { dg-error "invalid use|does not have" }
diff --git a/gcc/testsuite/g++.dg/parse/crash25.C b/gcc/testsuite/g++.dg/parse/crash25.C
index d7f20c62f26..f0d8ffd7218 100644
--- a/gcc/testsuite/g++.dg/parse/crash25.C
+++ b/gcc/testsuite/g++.dg/parse/crash25.C
@@ -4,7 +4,7 @@
struct yyguts_t
{
- class TestScanner* yyextra_r; // { dg-error "forward declaration" }
+ class TestScanner* yyextra_r; // { dg-message "forward declaration" }
};
TestScanner::TestScanner() {} // { dg-error "invalid use" }
diff --git a/gcc/testsuite/g++.dg/parse/crash31.C b/gcc/testsuite/g++.dg/parse/crash31.C
index b0a7e1877ce..e7d6bdc1465 100644
--- a/gcc/testsuite/g++.dg/parse/crash31.C
+++ b/gcc/testsuite/g++.dg/parse/crash31.C
@@ -1,4 +1,4 @@
-struct A // { dg-error "forward declaration" }
+struct A // { dg-message "not complete" }
{
A : A; // { dg-error "expected|incomplete" }
A : B; // { dg-error "not declared|incomplete" }
diff --git a/gcc/testsuite/g++.dg/parse/crash41.C b/gcc/testsuite/g++.dg/parse/crash41.C
index 746dbbca8a1..c14fbadff9f 100644
--- a/gcc/testsuite/g++.dg/parse/crash41.C
+++ b/gcc/testsuite/g++.dg/parse/crash41.C
@@ -5,4 +5,4 @@ struct A
A(int)(); // { dg-error "declared" }
};
-template<int> void foo(bool b, A a) { b ? a : 0; } // { dg-error "no match" }
+template<int> void foo(bool b, A a) { b ? a : 0; } // { dg-error "?:" }
diff --git a/gcc/testsuite/g++.dg/parse/crash49.C b/gcc/testsuite/g++.dg/parse/crash49.C
index 07d7c3b2f95..a922ef3cfc7 100644
--- a/gcc/testsuite/g++.dg/parse/crash49.C
+++ b/gcc/testsuite/g++.dg/parse/crash49.C
@@ -1,7 +1,7 @@
// PR c++/37552
// { dg-do compile }
-extern struct A a[1]; // { dg-error "forward declaration" }
+extern struct A a[1]; // { dg-message "forward declaration" }
void
foo ()
diff --git a/gcc/testsuite/g++.dg/parse/crash5.C b/gcc/testsuite/g++.dg/parse/crash5.C
index 0ac70297992..d51f8ed7a51 100644
--- a/gcc/testsuite/g++.dg/parse/crash5.C
+++ b/gcc/testsuite/g++.dg/parse/crash5.C
@@ -8,8 +8,6 @@ class QString { }; // { dg-error "redefinition" }
const QString q () {
QString z; // { dg-error "matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 10 }
int x;
return x ? QString () : QString (); // { dg-error "matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 13 }
}
diff --git a/gcc/testsuite/g++.dg/parse/crash50.C b/gcc/testsuite/g++.dg/parse/crash50.C
index 711048de160..630eb25a94d 100644
--- a/gcc/testsuite/g++.dg/parse/crash50.C
+++ b/gcc/testsuite/g++.dg/parse/crash50.C
@@ -2,7 +2,7 @@
// Origin PR c++/38636
// { dg-do compile }
-struct A; // { dg-error "forward declaration of 'struct A'" }
+struct A; // { dg-message "forward declaration of 'struct A'" }
A::A(
diff --git a/gcc/testsuite/g++.dg/parse/crash54.C b/gcc/testsuite/g++.dg/parse/crash54.C
index 222082ab79b..89d59ef2c16 100644
--- a/gcc/testsuite/g++.dg/parse/crash54.C
+++ b/gcc/testsuite/g++.dg/parse/crash54.C
@@ -1,6 +1,6 @@
// PR c++/42057
-struct A; // { dg-error "forward declaration" }
+struct A; // { dg-message "forward declaration" }
struct B
{
diff --git a/gcc/testsuite/g++.dg/parse/dtor7.C b/gcc/testsuite/g++.dg/parse/dtor7.C
index a8095126667..343b2e42c23 100644
--- a/gcc/testsuite/g++.dg/parse/dtor7.C
+++ b/gcc/testsuite/g++.dg/parse/dtor7.C
@@ -1,4 +1,4 @@
// PR c++/25856
-struct A; // { dg-error "forward" }
+struct A; // { dg-message "forward" }
A::~A() {} // { dg-error "incomplete" }
diff --git a/gcc/testsuite/g++.dg/parse/error19.C b/gcc/testsuite/g++.dg/parse/error19.C
index 6d84f714246..a06d3e0c45a 100644
--- a/gcc/testsuite/g++.dg/parse/error19.C
+++ b/gcc/testsuite/g++.dg/parse/error19.C
@@ -1,7 +1,7 @@
// { dg-options "-fshow-column -fmessage-length=0 -ansi -pedantic-errors -Wno-long-long " }
// PR C++/17867
-struct A // { dg-message "8:operator=|no known conversion for implicit" }
+struct A // { dg-message "8:operator=" }
{
A(int);
};
@@ -10,6 +10,5 @@ const A& foo();
void bar()
{
- foo()=A(0); // { dg-error "8:no match for 'operator='" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 13 }
+ foo()=A(0); // { dg-error "8:no match|const" }
}
diff --git a/gcc/testsuite/g++.dg/parse/error28.C b/gcc/testsuite/g++.dg/parse/error28.C
index 3ca210aa6b7..8a8f22afc0e 100644
--- a/gcc/testsuite/g++.dg/parse/error28.C
+++ b/gcc/testsuite/g++.dg/parse/error28.C
@@ -7,6 +7,5 @@ struct der : public virtual virt { // { dg-message "8:der::der|candidate expects
};
struct top : public der {
top () {} // { dg-bogus "der\\(const" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 9 }
};
// { dg-error "10:no matching function for call to 'der" "" { target *-*-* } 9 }
diff --git a/gcc/testsuite/g++.dg/parse/error40.C b/gcc/testsuite/g++.dg/parse/error40.C
index 9ab7552ae83..643f1f56c53 100644
--- a/gcc/testsuite/g++.dg/parse/error40.C
+++ b/gcc/testsuite/g++.dg/parse/error40.C
@@ -1,7 +1,7 @@
// PR c++/31489
-class foo; // { dg-error "'class foo'" }
-struct bar; // { dg-error "'struct bar'" }
+class foo; // { dg-message "'class foo'" }
+struct bar; // { dg-message "'struct bar'" }
int main()
{
diff --git a/gcc/testsuite/g++.dg/parse/error54.C b/gcc/testsuite/g++.dg/parse/error54.C
new file mode 100644
index 00000000000..b49c76b0057
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error54.C
@@ -0,0 +1,19 @@
+// PR c++/51640
+
+class ex {};
+
+namespace t
+{
+ class ex2 : public ex {};
+}
+
+class ex2 : public ex {};
+
+void bar()
+{
+ using namespace t;
+
+ try {
+ } catch (ex2&) { // { dg-error "reference to 'ex2' is ambiguous" }
+ }
+}
diff --git a/gcc/testsuite/g++.dg/parse/fused-params1.C b/gcc/testsuite/g++.dg/parse/fused-params1.C
index 33732fc2871..ebb226befb9 100644
--- a/gcc/testsuite/g++.dg/parse/fused-params1.C
+++ b/gcc/testsuite/g++.dg/parse/fused-params1.C
@@ -2,7 +2,7 @@
// Origin: Alexander Zvyagin <Alexander.Zviagine@cern.ch>
// { dg-do compile }
-template <int N,typename T> struct A // { dg-error "" }
+template <int N,typename T> struct A // { dg-message "" }
{
typedef T X;
template <int M> void foo (const A<M,X>&);
diff --git a/gcc/testsuite/g++.dg/parse/new1.C b/gcc/testsuite/g++.dg/parse/new1.C
index d61c44633ce..d8c376617d2 100644
--- a/gcc/testsuite/g++.dg/parse/new1.C
+++ b/gcc/testsuite/g++.dg/parse/new1.C
@@ -1,4 +1,4 @@
-struct T; // { dg-error "forward" }
+struct T; // { dg-message "forward" }
T* manage(T* t);
template <class Obj> struct ObjectSlot0_ {
void create() {
diff --git a/gcc/testsuite/g++.dg/parse/pr58664.C b/gcc/testsuite/g++.dg/parse/pr58664.C
new file mode 100644
index 00000000000..489259a14a3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr58664.C
@@ -0,0 +1,66 @@
+// PR c++/58664
+// { dg-do compile { target c++11 } }
+
+struct F; // { dg-message "forward declaration" }
+
+union U // { dg-message "not complete" }
+{
+ U u; // { dg-error "field 'u' has incomplete type 'U'" }
+};
+
+union CU // { dg-message "not complete" }
+{
+ const CU u; // { dg-error "incomplete type" }
+};
+
+template<typename T>
+union UT // { dg-message "not complete" }
+{
+ UT u; // { dg-error "incomplete type" }
+};
+
+template union UT<int>;
+
+union UF
+{
+ F u; // { dg-error "field 'u' has incomplete type 'F'" }
+};
+
+template<typename T>
+union UFT
+{
+ F u; // { dg-error "incomplete type" }
+};
+
+template union UFT<int>;
+
+struct S // { dg-message "not complete" }
+{
+ S s; // { dg-error "field 's' has incomplete type 'S'" }
+};
+
+struct VS // { dg-message "not complete" }
+{
+ volatile VS s; // { dg-error "incomplete type" }
+};
+
+template<typename T>
+struct ST // { dg-message "not complete" }
+{
+ ST s; // { dg-error "incomplete type" }
+};
+
+template class ST<int>;
+
+struct SF
+{
+ F s; // { dg-error "field 's' has incomplete type 'F'" }
+};
+
+template<typename T>
+struct SFT
+{
+ F s; // { dg-error "incomplete type" }
+};
+
+template class SFT<int>;
diff --git a/gcc/testsuite/g++.dg/pr60969.C b/gcc/testsuite/g++.dg/pr60969.C
new file mode 100644
index 00000000000..4012e2ce72f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr60969.C
@@ -0,0 +1,32 @@
+/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
+/* { dg-options "-O2 -ftree-vectorize -march=pentium4 -mfpmath=387" } */
+
+struct A
+{
+ float f, g, h, k;
+ A () {}
+ A (float v0, float x, float y) : f(v0), g(x), h(y), k(0.0f) {}
+ A bar (A &a, float t) { return A (f + a.f * t, g + a.g * t, h + a.h * t); }
+};
+
+A
+baz (A &x, A &y, float t)
+{
+ return x.bar (y, t);
+}
+
+A *
+foo (A &s, A &t, A &u, A &v, int y, int z)
+{
+ A *x = new A[y * z];
+ for (int i = 0; i < 7; i++)
+ {
+ A s = baz (s, u, i / (float) z);
+ A t = baz (t, v, i / (float) z);
+ for (int j = 0; j < 7; j++)
+ x[i * y + j] = baz (s, t, j / (float) y);
+ }
+ return x;
+}
+
+/* { dg-final { scan-assembler-not "%mm" } } */
diff --git a/gcc/testsuite/g++.dg/pr61094.C b/gcc/testsuite/g++.dg/pr61094.C
new file mode 100644
index 00000000000..35adc256c21
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr61094.C
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+template <typename> struct A {
+ unsigned _width, _height, _depth, _spectrum;
+ template <typename t> A(t p1) {
+ int a = p1.size();
+ if (a) {
+ _width = p1._width;
+ _depth = _height = _spectrum = p1._spectrum;
+ }
+ }
+ long size() { return (long)_width * _height * _depth * _spectrum; }
+};
+
+int d;
+void fn1(void *);
+A<int> *fn2();
+void fn3() {
+ int b;
+ for (;;) {
+ A<char> c(*fn2());
+ fn1(&c);
+ if (d || !b)
+ throw;
+ }
+}
+
+
+
+
diff --git a/gcc/testsuite/g++.dg/rtti/dyncast6.C b/gcc/testsuite/g++.dg/rtti/dyncast6.C
index a6329e9441c..bfbf5117dd1 100644
--- a/gcc/testsuite/g++.dg/rtti/dyncast6.C
+++ b/gcc/testsuite/g++.dg/rtti/dyncast6.C
@@ -38,19 +38,19 @@ void r()
B b;
A& a1 = dynamic_cast<A&>(b);
- A& a2 = dynamic_cast<const A&>(b); // { dg-error "invalid" }
- A& a3 = dynamic_cast<volatile A&>(b); // { dg-error "invalid" }
- A& a4 = dynamic_cast<const volatile A&>(b); // { dg-error "invalid" }
+ A& a2 = dynamic_cast<const A&>(b); // { dg-error "" }
+ A& a3 = dynamic_cast<volatile A&>(b); // { dg-error "" }
+ A& a4 = dynamic_cast<const volatile A&>(b); // { dg-error "" }
const A& ca1 = dynamic_cast<A&>(b);
const A& ca2 = dynamic_cast<const A&>(b);
- const A& ca3 = dynamic_cast<volatile A&>(b); // { dg-error "invalid" }
- const A& ca4 = dynamic_cast<const volatile A&>(b); // { dg-error "invalid" }
+ const A& ca3 = dynamic_cast<volatile A&>(b); // { dg-error "" }
+ const A& ca4 = dynamic_cast<const volatile A&>(b); // { dg-error "" }
volatile A& va1 = dynamic_cast<A&>(b);
- volatile A& va2 = dynamic_cast<const A&>(b); // { dg-error "invalid" }
+ volatile A& va2 = dynamic_cast<const A&>(b); // { dg-error "" }
volatile A& va3 = dynamic_cast<volatile A&>(b);
- volatile A& va4 = dynamic_cast<const volatile A&>(b);// { dg-error "invalid" }
+ volatile A& va4 = dynamic_cast<const volatile A&>(b);// { dg-error "" }
const volatile A& cva1 = dynamic_cast<A&>(b);
const volatile A& cva2 = dynamic_cast<const A&>(b);
diff --git a/gcc/testsuite/g++.dg/tc1/dr152.C b/gcc/testsuite/g++.dg/tc1/dr152.C
index bf742ee9b8a..e787f8bcbfb 100644
--- a/gcc/testsuite/g++.dg/tc1/dr152.C
+++ b/gcc/testsuite/g++.dg/tc1/dr152.C
@@ -7,12 +7,11 @@ namespace N1 {
X(); // { dg-message "note" }
explicit X(const X&);
};
- void f(X); // { dg-error "initializing" }
+ void f(X); // { dg-message "initializing" }
int foo()
{
X x;
f(x); // { dg-error "matching" "matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 14 }
}
}
@@ -24,14 +23,13 @@ namespace N2 {
};
template <class T>
- void f(T ) {} // { dg-error "initializing" }
+ void f(T) {} // { dg-message "initializing" }
template <class T>
int foo()
{
X<T> x;
N2::f(x); // { dg-error "matching" "matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 33 }
}
template int foo<float>(); // { dg-message "required from here" }
diff --git a/gcc/testsuite/g++.dg/template/array28.C b/gcc/testsuite/g++.dg/template/array28.C
new file mode 100644
index 00000000000..18b629d447f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/array28.C
@@ -0,0 +1,7 @@
+typedef int (A)[];
+
+template<class T> void f(T (*)[1]); // { dg-error "array" }
+
+int main() {
+ f<int[]>(0); // { dg-error "no match" }
+}
diff --git a/gcc/testsuite/g++.dg/template/copy1.C b/gcc/testsuite/g++.dg/template/copy1.C
index c6b3ff80665..bf5a37ce0ab 100644
--- a/gcc/testsuite/g++.dg/template/copy1.C
+++ b/gcc/testsuite/g++.dg/template/copy1.C
@@ -6,10 +6,9 @@
struct A
{
- A(A&); // { dg-message "note" }
- template <class T> A(T); // { dg-message "note" }
+ A(A&); // { dg-message "A::A" }
+ template <class T> A(T); // { dg-message "A::A" }
};
-A a = 0; // { dg-error "no matching function" }
-// { dg-message "candidate" "candidate note" { target *-*-* } 13 }
+A a = 0; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/template/crash107.C b/gcc/testsuite/g++.dg/template/crash107.C
index bb405ac7eef..d92ee3394e2 100644
--- a/gcc/testsuite/g++.dg/template/crash107.C
+++ b/gcc/testsuite/g++.dg/template/crash107.C
@@ -14,7 +14,5 @@ template<typename FP_> struct Vec { // { dg-message "note" }
}
};
Vec<double> v(3,4,12); // { dg-error "no matching" }
-// { dg-message "note" "note" { target *-*-* } 16 }
Vec<double> V(12,4,3); // { dg-error "no matching" }
-// { dg-message "note" "note" { target *-*-* } 18 }
Vec<double> c = v^V; // { dg-message "required" }
diff --git a/gcc/testsuite/g++.dg/template/crash35.C b/gcc/testsuite/g++.dg/template/crash35.C
index 348d91d0caf..c457798dd02 100644
--- a/gcc/testsuite/g++.dg/template/crash35.C
+++ b/gcc/testsuite/g++.dg/template/crash35.C
@@ -1,7 +1,7 @@
// PR c++/20463
// { dg-do compile }
-template <typename T> struct C; // { dg-error "declaration" }
+template <typename T> struct C; // { dg-message "declaration" }
template <typename T> void C<T>::f() // { dg-error "invalid|template" }
{
diff --git a/gcc/testsuite/g++.dg/template/crash59.C b/gcc/testsuite/g++.dg/template/crash59.C
index 61d2188fc9e..ebc0e281c54 100644
--- a/gcc/testsuite/g++.dg/template/crash59.C
+++ b/gcc/testsuite/g++.dg/template/crash59.C
@@ -1,6 +1,6 @@
//PR c++/27329
-template<int> struct A // { dg-error "forward declaration" }
+template<int> struct A // { dg-message "forward declaration" }
! // { dg-error "expected unqualified-id" }
;
diff --git a/gcc/testsuite/g++.dg/template/crash77.C b/gcc/testsuite/g++.dg/template/crash77.C
index b4d6e8f4a67..21747792c2f 100644
--- a/gcc/testsuite/g++.dg/template/crash77.C
+++ b/gcc/testsuite/g++.dg/template/crash77.C
@@ -1,5 +1,5 @@
// PR c++/34603
-template<typename> struct A; // { dg-error "declaration" }
+template<typename> struct A; // { dg-message "declaration" }
template<typename T> A<T>::A( struct A; // { dg-error "definition|expected|incomplete" }
diff --git a/gcc/testsuite/g++.dg/template/dependent-expr5.C b/gcc/testsuite/g++.dg/template/dependent-expr5.C
index af0dfb912a2..ecb7a67da8e 100644
--- a/gcc/testsuite/g++.dg/template/dependent-expr5.C
+++ b/gcc/testsuite/g++.dg/template/dependent-expr5.C
@@ -53,7 +53,7 @@ struct foo {
bindb (&barf);
bindb (&foo::barf); // { dg-error "ambiguous" }
- // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 55 }
+
bind (&bark); // { dg-error "no matching function" }
// { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 58 }
@@ -69,7 +69,7 @@ struct foo {
bindb (&bark);
bindb (&bar::bark); // { dg-error "ambiguous" }
- // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 71 }
+
}
};
@@ -105,7 +105,7 @@ struct foo {
bindb (&barf);
bindb (&foo::barf); // { dg-error "ambiguous" }
- // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 107 }
+
bind (&bark); // { dg-error "no matching function" }
// { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 110 }
@@ -121,7 +121,7 @@ struct foo {
bindb (&bark);
bindb (&barT::bark); // { dg-error "ambiguous" }
- // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 123 }
+
}
};
diff --git a/gcc/testsuite/g++.dg/template/error2.C b/gcc/testsuite/g++.dg/template/error2.C
index be5ab1d450e..a7f199e51e4 100644
--- a/gcc/testsuite/g++.dg/template/error2.C
+++ b/gcc/testsuite/g++.dg/template/error2.C
@@ -7,8 +7,7 @@
template<class T> struct X
{
- T m; // { dg-error "void" "void" }
- // { dg-error "incomplete type" "incomplete" { target *-*-* } 10 }
+ T m; // { dg-error "incomplete type|invalid use" }
};
template<class T >
diff --git a/gcc/testsuite/g++.dg/template/error38.C b/gcc/testsuite/g++.dg/template/error38.C
index 14a21329988..6c25b9f9c0f 100644
--- a/gcc/testsuite/g++.dg/template/error38.C
+++ b/gcc/testsuite/g++.dg/template/error38.C
@@ -32,12 +32,8 @@ int main()
{
A<B> a;
a.f(); // { dg-error "" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 34 }
a.g(); // { dg-error "" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 36 }
f(i); // { dg-error "" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 39 }
f(p); // { dg-error "" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 41 }
}
diff --git a/gcc/testsuite/g++.dg/template/error40.C b/gcc/testsuite/g++.dg/template/error40.C
index 7746ed2cee3..c5df56fc1be 100644
--- a/gcc/testsuite/g++.dg/template/error40.C
+++ b/gcc/testsuite/g++.dg/template/error40.C
@@ -26,7 +26,5 @@ struct B
int main()
{
f(1); // { dg-error "" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 28 }
B<A<int> >().f(); // { dg-error "" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 30 }
}
diff --git a/gcc/testsuite/g++.dg/template/error46.C b/gcc/testsuite/g++.dg/template/error46.C
index 6cb085a182c..be0b813324f 100644
--- a/gcc/testsuite/g++.dg/template/error46.C
+++ b/gcc/testsuite/g++.dg/template/error46.C
@@ -8,4 +8,4 @@ void bar()
{
foo(A<0>(), A<1>()); // { dg-error "no matching" }
}
-// { dg-message "candidate|parameter 'N' ('0' and '1')" "" { target *-*-* } 9 }
+// { dg-message "deduced conflicting values" "" { target *-*-* } 9 }
diff --git a/gcc/testsuite/g++.dg/template/error47.C b/gcc/testsuite/g++.dg/template/error47.C
index 74a59892294..e598d141c29 100644
--- a/gcc/testsuite/g++.dg/template/error47.C
+++ b/gcc/testsuite/g++.dg/template/error47.C
@@ -6,4 +6,4 @@ void bar(void* p)
{
foo(0, p); // { dg-error "no matching" }
}
-// { dg-message "candidate|parameter 'T' ('int' and 'void*')" "" { target *-*-* } 7 }
+// { dg-message "parameter 'T' .'int' and 'void.'" "" { target *-*-* } 7 }
diff --git a/gcc/testsuite/g++.dg/template/error51.C b/gcc/testsuite/g++.dg/template/error51.C
index b3a6cfb3d27..304a13a70fb 100644
--- a/gcc/testsuite/g++.dg/template/error51.C
+++ b/gcc/testsuite/g++.dg/template/error51.C
@@ -2,7 +2,7 @@
template<int> void foo()
{
- struct A; // { dg-error "declaration" }
+ struct A; // { dg-message "declaration" }
struct B : A {}; // { dg-error "invalid use of incomplete" }
}
diff --git a/gcc/testsuite/g++.dg/template/incomplete1.C b/gcc/testsuite/g++.dg/template/incomplete1.C
index e4997ef0146..53bd8170e62 100644
--- a/gcc/testsuite/g++.dg/template/incomplete1.C
+++ b/gcc/testsuite/g++.dg/template/incomplete1.C
@@ -2,7 +2,7 @@
// Origin: Ivan Godard <igodard at pacbell dot net>
// PR c++/17447: Detect parameters of dependent types even in templates
-struct B; // { dg-error "forward declaration" }
+struct B; // { dg-message "forward declaration" }
template<typename T> struct A {
friend A& operator <<(A& a, B b) { return a; } // { dg-error "incomplete" }
diff --git a/gcc/testsuite/g++.dg/template/incomplete2.C b/gcc/testsuite/g++.dg/template/incomplete2.C
index b855569088f..bad16020baa 100644
--- a/gcc/testsuite/g++.dg/template/incomplete2.C
+++ b/gcc/testsuite/g++.dg/template/incomplete2.C
@@ -10,5 +10,4 @@ A a; // { dg-error "incomplete type" }
void bar()
{
foo<a>(); // { dg-error "(no matching function|could not convert)" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 12 }
}
diff --git a/gcc/testsuite/g++.dg/template/incomplete3.C b/gcc/testsuite/g++.dg/template/incomplete3.C
index 8a20bba74d5..9b2efb77b7e 100644
--- a/gcc/testsuite/g++.dg/template/incomplete3.C
+++ b/gcc/testsuite/g++.dg/template/incomplete3.C
@@ -1,5 +1,5 @@
// PR c++/27315
// { dg-do compile }
-struct A; // { dg-error "forward declaration" }
+struct A; // { dg-message "forward declaration" }
template void A::foo<0>(); // { dg-error "before|incomplete" }
diff --git a/gcc/testsuite/g++.dg/template/incomplete4.C b/gcc/testsuite/g++.dg/template/incomplete4.C
index f2832a73c4c..7cff66bdc04 100644
--- a/gcc/testsuite/g++.dg/template/incomplete4.C
+++ b/gcc/testsuite/g++.dg/template/incomplete4.C
@@ -1,11 +1,11 @@
// PR c++/33501
// { dg-do compile }
-class A; // { dg-error "forward declaration" }
+class A; // { dg-message "forward declaration" }
template <typename T> struct X
{
- static int f (T); // { dg-error "initializing" }
+ static int f (T); // { dg-message "initializing" }
static const T &make ();
};
diff --git a/gcc/testsuite/g++.dg/template/incomplete5.C b/gcc/testsuite/g++.dg/template/incomplete5.C
index f7802825fde..1bd21b95e8c 100644
--- a/gcc/testsuite/g++.dg/template/incomplete5.C
+++ b/gcc/testsuite/g++.dg/template/incomplete5.C
@@ -1,11 +1,11 @@
// PR c++/33501
// { dg-do compile }
-class A; // { dg-error "forward declaration" }
+class A; // { dg-message "forward declaration" }
template <typename T> struct X
{
- static int f (T); // { dg-error "initializing" }
+ static int f (T); // { dg-message "initializing" }
static const T &make ();
static const bool value = sizeof (f (make ())) == sizeof (int); // { dg-error "invalid use of incomplete type" }
};
diff --git a/gcc/testsuite/g++.dg/template/inherit8.C b/gcc/testsuite/g++.dg/template/inherit8.C
index 3176dc06d0b..62a0f1da1a9 100644
--- a/gcc/testsuite/g++.dg/template/inherit8.C
+++ b/gcc/testsuite/g++.dg/template/inherit8.C
@@ -4,7 +4,7 @@ template <typename T>
struct A
{
template <typename U>
- struct B : public A <B<U> > // { dg-error "declaration" }
+ struct B : public A <B<U> > // { dg-message "not complete" }
{
struct C : public B<U> // { dg-error "incomplete" }
{
diff --git a/gcc/testsuite/g++.dg/template/instantiate1.C b/gcc/testsuite/g++.dg/template/instantiate1.C
index dd501684e63..a9c8cf86968 100644
--- a/gcc/testsuite/g++.dg/template/instantiate1.C
+++ b/gcc/testsuite/g++.dg/template/instantiate1.C
@@ -12,7 +12,7 @@ template <class T> struct Y {
X<T> x; // { dg-message "required" }
};
-template <class T> struct Z { // { dg-error "declaration" }
+template <class T> struct Z { // { dg-message "declaration" }
Y<Z<T> > y; // { dg-message "required" }
};
diff --git a/gcc/testsuite/g++.dg/template/instantiate3.C b/gcc/testsuite/g++.dg/template/instantiate3.C
index c0754da9227..e99ec84c2ac 100644
--- a/gcc/testsuite/g++.dg/template/instantiate3.C
+++ b/gcc/testsuite/g++.dg/template/instantiate3.C
@@ -4,7 +4,7 @@
// PR c++/7639
// ICE when accessing member with incomplete type.
-class ACE_Null_Mutex; // { dg-error "forward declaration" }
+class ACE_Null_Mutex; // { dg-message "forward declaration" }
template <class TYPE>
struct ACE_Cleanup_Adapter
diff --git a/gcc/testsuite/g++.dg/template/instantiate5.C b/gcc/testsuite/g++.dg/template/instantiate5.C
index 2198087abf9..896313d14d5 100644
--- a/gcc/testsuite/g++.dg/template/instantiate5.C
+++ b/gcc/testsuite/g++.dg/template/instantiate5.C
@@ -19,7 +19,6 @@ struct B
template <typename T> struct C
{
virtual void bar() const { T::foo(); } // { dg-error "no matching function" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 21 }
};
C<B> c; // { dg-message "required" }
diff --git a/gcc/testsuite/g++.dg/template/local4.C b/gcc/testsuite/g++.dg/template/local4.C
index d842076bd80..95d2990ec88 100644
--- a/gcc/testsuite/g++.dg/template/local4.C
+++ b/gcc/testsuite/g++.dg/template/local4.C
@@ -6,5 +6,4 @@ template <typename T> void foo() {} // { dg-message "note" }
int main () {
struct S {};
foo<S> (); // { dg-error "(match|template argument for|trying to instantiate)" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 8 }
}
diff --git a/gcc/testsuite/g++.dg/template/local8.C b/gcc/testsuite/g++.dg/template/local8.C
new file mode 100644
index 00000000000..006bd8c40eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/local8.C
@@ -0,0 +1,18 @@
+// PR c++/56947
+
+struct A
+{
+ A (int);
+};
+
+template < typename >
+void Fn ()
+{
+ const int kCapacity = 0;
+ struct Q:A
+ {
+ Q ():A (kCapacity) { }
+ };
+ Q q;
+}
+template void Fn < int >();
diff --git a/gcc/testsuite/g++.dg/template/new3.C b/gcc/testsuite/g++.dg/template/new3.C
index 230330ec66c..461b47b5e90 100644
--- a/gcc/testsuite/g++.dg/template/new3.C
+++ b/gcc/testsuite/g++.dg/template/new3.C
@@ -6,7 +6,6 @@ struct C
void f() {
int* node;
new (&node) int(0); // { dg-error "new" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 8 }
}
};
diff --git a/gcc/testsuite/g++.dg/template/offsetof2.C b/gcc/testsuite/g++.dg/template/offsetof2.C
index da888f7a59e..3f08f9b0b8b 100644
--- a/gcc/testsuite/g++.dg/template/offsetof2.C
+++ b/gcc/testsuite/g++.dg/template/offsetof2.C
@@ -1,7 +1,7 @@
// PR c++/49085
template <class T>
-struct A // { dg-error "declaration" }
+struct A // { dg-message "not complete" }
{
int i, j;
int ar[__builtin_offsetof(A,j)]; // { dg-error "incomplete type" }
diff --git a/gcc/testsuite/g++.dg/template/operator9.C b/gcc/testsuite/g++.dg/template/operator9.C
index 46eef0a9ac7..dfd491d4f04 100644
--- a/gcc/testsuite/g++.dg/template/operator9.C
+++ b/gcc/testsuite/g++.dg/template/operator9.C
@@ -5,6 +5,5 @@ template<operator+> void foo(); // { dg-error "before|non-function|template" }
void bar()
{
foo(); // { dg-error "no matching function" }
- // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 7 }
}
diff --git a/gcc/testsuite/g++.dg/template/pr51199.C b/gcc/testsuite/g++.dg/template/pr51199.C
new file mode 100644
index 00000000000..e56b2549efa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr51199.C
@@ -0,0 +1,17 @@
+// PR c++/51199
+
+typedef void FC() const;
+
+template<class T>
+struct add_ref {
+ typedef T& type; // { dg-error "forming reference" }
+};
+
+typedef add_ref<FC>::type ref_type;
+
+template<class T>
+struct add_ptr {
+ typedef T* type; // { dg-error "forming pointer" }
+};
+
+typedef add_ptr<FC>::type ptr_type;
diff --git a/gcc/testsuite/g++.dg/template/pr54310.C b/gcc/testsuite/g++.dg/template/pr54310.C
new file mode 100644
index 00000000000..94e5f2494c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr54310.C
@@ -0,0 +1,19 @@
+// PR c++/54310
+
+template <typename T>
+struct meta
+{
+ typedef typename T::type type;
+};
+
+struct S{};
+
+template <typename T>
+typename meta<T>::type foo(T, S);
+
+int foo(int, int);
+
+int main()
+{
+ foo(0, 0);
+}
diff --git a/gcc/testsuite/g++.dg/template/ptrmem2.C b/gcc/testsuite/g++.dg/template/ptrmem2.C
index 5f03580c1b2..6aa251243af 100644
--- a/gcc/testsuite/g++.dg/template/ptrmem2.C
+++ b/gcc/testsuite/g++.dg/template/ptrmem2.C
@@ -12,5 +12,4 @@ template <typename T> T A::* Foo (); // { dg-error "reference" }
void Baz ()
{
Foo <int &> (); // { dg-error "no matching function" "" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 14 }
}
diff --git a/gcc/testsuite/g++.dg/template/ptrmem20.C b/gcc/testsuite/g++.dg/template/ptrmem20.C
index dee3c629a70..2d2453d73db 100644
--- a/gcc/testsuite/g++.dg/template/ptrmem20.C
+++ b/gcc/testsuite/g++.dg/template/ptrmem20.C
@@ -13,5 +13,4 @@ template<void (A::*)()> void bar(); // { dg-message "note" }
void baz()
{
bar<&B::foo>(); // { dg-error "not a valid template argument|no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 15 }
}
diff --git a/gcc/testsuite/g++.dg/template/qualttp5.C b/gcc/testsuite/g++.dg/template/qualttp5.C
index 8ac1952f9ab..7e74f6092e3 100644
--- a/gcc/testsuite/g++.dg/template/qualttp5.C
+++ b/gcc/testsuite/g++.dg/template/qualttp5.C
@@ -11,7 +11,6 @@ template <template <class> class TT> void f()
{
TT<int> y;
y = 0; // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 13 }
}
template <class T> struct C
diff --git a/gcc/testsuite/g++.dg/template/sfinae2.C b/gcc/testsuite/g++.dg/template/sfinae2.C
index c9e103114dd..38eb325c613 100644
--- a/gcc/testsuite/g++.dg/template/sfinae2.C
+++ b/gcc/testsuite/g++.dg/template/sfinae2.C
@@ -13,6 +13,5 @@ template<int I> void fn (char (*) [cl<I>::value] = 0 ); // { dg-error "zero-size
void foo (void)
{
fn<0> (); // { dg-error "no matching function" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 15 }
}
diff --git a/gcc/testsuite/g++.dg/template/spec22.C b/gcc/testsuite/g++.dg/template/spec22.C
index f916ea46894..7e627f16763 100644
--- a/gcc/testsuite/g++.dg/template/spec22.C
+++ b/gcc/testsuite/g++.dg/template/spec22.C
@@ -16,6 +16,6 @@ template <typename T> struct srp
};
ptr<int> parent_get()
{
- srp<int> parent; // { dg-message "candidate" }
+ srp<int> parent;
return parent; // { dg-error "is ambiguous" }
}
diff --git a/gcc/testsuite/g++.dg/template/spec23.C b/gcc/testsuite/g++.dg/template/spec23.C
index 3d401f00ef9..1c027fa4388 100644
--- a/gcc/testsuite/g++.dg/template/spec23.C
+++ b/gcc/testsuite/g++.dg/template/spec23.C
@@ -20,7 +20,6 @@ struct Bar
Foo Quux (Bar const &b)
{
return b; // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 22 }
}
diff --git a/gcc/testsuite/g++.dg/template/typedef4.C b/gcc/testsuite/g++.dg/template/typedef4.C
index 60fad068858..2676d8fec1d 100644
--- a/gcc/testsuite/g++.dg/template/typedef4.C
+++ b/gcc/testsuite/g++.dg/template/typedef4.C
@@ -6,5 +6,4 @@ template<typedef> void foo(); // { dg-error "no type|typedef declaration|templa
void bar()
{
foo<int>(); // { dg-error "matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 8 }
}
diff --git a/gcc/testsuite/g++.dg/tm/pr51928.C b/gcc/testsuite/g++.dg/tm/pr51928.C
index 22dbadd4bf5..5ea0b0457a1 100644
--- a/gcc/testsuite/g++.dg/tm/pr51928.C
+++ b/gcc/testsuite/g++.dg/tm/pr51928.C
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-fgnu-tm" } */
-struct A; // { dg-error "forward declaration of 'struct A'" }
+struct A; // { dg-message "forward declaration of 'struct A'" }
struct B
{
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr61009.C b/gcc/testsuite/g++.dg/tree-ssa/pr61009.C
new file mode 100644
index 00000000000..4e7bb1a1c7b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr61009.C
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-vrp -std=c++11 -fno-strict-aliasing -fdump-tree-dom1" } */
+
+#include <stdio.h>
+struct Field {
+ virtual int Compare(void*, void*);
+};
+extern int NKF, NR;
+extern int idxs[];
+extern Field* the_field;
+extern int *incs;
+extern char** fptrs;
+inline int doCmp(int this_row_offset, int field_idx) {
+ void *p = fptrs[field_idx] + this_row_offset * incs[field_idx];
+ return the_field->Compare(p,0);
+}
+bool Test(void) {
+
+ int row_offset = 0;
+
+ for (; row_offset < NR; ++row_offset) {
+
+ bool is_different = false;
+ for (int j = 0; j < NKF ; ++j) {
+ int field_idx = idxs[j];
+ int cmp = doCmp(row_offset, field_idx);
+ fprintf (stderr, "cmp=%d\n",cmp);
+
+ if (cmp == 0) {
+ continue;
+ }
+ if (cmp > 0) {
+ is_different = true;
+ break;
+ } else {
+ fprintf (stderr, "Incorrect\n");
+ return false;
+ }
+ }
+ if (!is_different) {
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// The block ending with cmp == 0 should not be threaded. ie,
+// there should be a single == 0 comparison in the dump file.
+
+// { dg-final { scan-tree-dump-times "== 0" 1 "dom1" } }
+// { dg-final { cleanup-tree-dump "dom1" } }
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr8781.C b/gcc/testsuite/g++.dg/tree-ssa/pr8781.C
index cc518a0d25a..bf754137232 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr8781.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr8781.C
@@ -24,5 +24,5 @@ int x()
/* We should optimize this to a direct call. */
-/* { dg-final { scan-tree-dump "Replacing call target with f" "fre1" } } */
+/* { dg-final { scan-tree-dump "converting indirect call to function int f()" "fre1" } } */
/* { dg-final { cleanup-tree-dump "fre1" } } */
diff --git a/gcc/testsuite/g++.dg/ubsan/float-cast-overflow-bf.C b/gcc/testsuite/g++.dg/ubsan/float-cast-overflow-bf.C
new file mode 100644
index 00000000000..d1df76da632
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/float-cast-overflow-bf.C
@@ -0,0 +1,62 @@
+// { dg-do run { target { int32 } } }
+// { dg-options "-fsanitize=float-cast-overflow" }
+
+#define INT_MAX __INT_MAX__
+#define INT_MIN (-__INT_MAX__ - 1)
+#define UINT_MAX 2 * (unsigned) __INT_MAX__ + 1
+
+struct S
+{
+ int i:1;
+} s;
+
+struct T
+{
+ unsigned int i:1;
+} t;
+
+int
+main (void)
+{
+ volatile double d;
+
+#define CHECK_BOUNDARY(VAR, VAL) \
+ (VAR) = (VAL) - 1.5; \
+ (VAR) = (VAL) - 1.0; \
+ (VAR) = (VAL) - 0.75; \
+ (VAR) = (VAL) - 0.5; \
+ (VAR) = (VAL) - 0.0000001; \
+ (VAR) = (VAL) - 0.0; \
+ (VAR) = (VAL); \
+ (VAR) = (VAL) + 0.0; \
+ (VAR) = (VAL) + 0.0000001; \
+ (VAR) = (VAL) + 0.5; \
+ (VAR) = (VAL) + 0.75; \
+ (VAR) = (VAL) + 1.0; \
+ (VAR) = (VAL) + 1.5;
+
+ /* Signed bit-field. (INT_MIN, INT_MAX) is valid. */
+ d = INT_MIN;
+ CHECK_BOUNDARY (s.i, d);
+ d = 0.0;
+ CHECK_BOUNDARY (s.i, d);
+ d = INT_MAX;
+ CHECK_BOUNDARY (s.i, d);
+
+ /* Unsigned bit-field. (0, UINT_MAX) is valid. */
+ d = UINT_MAX;
+ CHECK_BOUNDARY (t.i, d);
+ d = 0.0;
+ CHECK_BOUNDARY (t.i, d);
+
+ return 0;
+}
+
+/* { dg-output "value -2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/g++.dg/ubsan/pr61272.C b/gcc/testsuite/g++.dg/ubsan/pr61272.C
new file mode 100644
index 00000000000..064678d37b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/pr61272.C
@@ -0,0 +1,24 @@
+// PR sanitizer/61272
+// { dg-do compile }
+// { dg-options "-fsanitize=undefined -std=c++11" }
+
+namespace std
+{
+ template < typename _Tp > class allocator;
+ template < typename _Alloc > struct allocator_traits {
+ private:
+ template < typename _Tp > auto construct ( _Alloc & __a, _Tp * __p)-> // { dg-error "is private" }
+ decltype (_S_construct (__a, __p)) { }
+ };
+ namespace __gnu_cxx
+ {
+ template < typename _Alloc > struct __alloc_traits:std::allocator_traits < _Alloc > // { dg-error "within this context" }
+ {
+ typedef std::allocator_traits < _Alloc > _Base_type;
+ using _Base_type::construct;
+ };
+ template < typename _Tp, typename _Alloc > struct _Vector_base { typedef typename __gnu_cxx::__alloc_traits < _Alloc >::template rebind < _Tp >::other _Tp_alloc_type; }; // { dg-error "no class template" }
+ template < typename _Tp, typename _Alloc = std::allocator < _Tp > >class vector : protected _Vector_base < _Tp, _Alloc > { };
+ template < typename NumberT > struct Point2d { };
+ typedef Point2d < int >GdsPoint;
+ class GdsPointList : public vector < GdsPoint > {};}}
diff --git a/gcc/testsuite/g++.dg/warn/Wdelete-incomplete-1.C b/gcc/testsuite/g++.dg/warn/Wdelete-incomplete-1.C
index 69689ba3488..729ea21017b 100644
--- a/gcc/testsuite/g++.dg/warn/Wdelete-incomplete-1.C
+++ b/gcc/testsuite/g++.dg/warn/Wdelete-incomplete-1.C
@@ -1,6 +1,6 @@
// PR c++/43452
-class Foo; // { dg-warning "forward" }
+class Foo; // { dg-message "forward" }
int main() {
Foo* p; // { dg-warning "incomplete" }
delete [] p; // { dg-warning "problem" }
diff --git a/gcc/testsuite/g++.dg/warn/incomplete1.C b/gcc/testsuite/g++.dg/warn/incomplete1.C
index 9dc645d82f9..1fa27123e6b 100644
--- a/gcc/testsuite/g++.dg/warn/incomplete1.C
+++ b/gcc/testsuite/g++.dg/warn/incomplete1.C
@@ -9,7 +9,7 @@
// (But the deletion does not constitute an ill-formed program. So the
// program should nevertheless compile, but it should give a warning.)
-class A; // { dg-warning "forward declaration of 'class A'" "" }
+class A; // { dg-message "forward declaration of 'class A'" "" }
A *a; // { dg-warning "'a' has incomplete type" "" }
diff --git a/gcc/testsuite/g++.dg/warn/incomplete2.C b/gcc/testsuite/g++.dg/warn/incomplete2.C
index 30be26749c9..bfaf6be310c 100644
--- a/gcc/testsuite/g++.dg/warn/incomplete2.C
+++ b/gcc/testsuite/g++.dg/warn/incomplete2.C
@@ -1,9 +1,9 @@
// PR c++/33501
// { dg-do compile }
-class A; // { dg-error "forward declaration" }
+class A; // { dg-message "forward declaration" }
-int f (A); // { dg-error "initializing" }
+int f (A); // { dg-message "initializing" }
const A &make ();
int
diff --git a/gcc/testsuite/g++.dg/warn/return-reference.C b/gcc/testsuite/g++.dg/warn/return-reference.C
index 83021900dbd..710e87c8cbd 100644
--- a/gcc/testsuite/g++.dg/warn/return-reference.C
+++ b/gcc/testsuite/g++.dg/warn/return-reference.C
@@ -7,7 +7,7 @@ foo1()
{
static int empty;
const int* x = bar();
- return (x ? *x : empty); // { dg-bogus ".*" "" { xfail *-*-* } }
+ return (x ? *x : empty); // { dg-bogus ".*" }
}
const int&
diff --git a/gcc/testsuite/g++.old-deja/g++.benjamin/15799.C b/gcc/testsuite/g++.old-deja/g++.benjamin/15799.C
index 24725c999b0..35d882b21b3 100644
--- a/gcc/testsuite/g++.old-deja/g++.benjamin/15799.C
+++ b/gcc/testsuite/g++.old-deja/g++.benjamin/15799.C
@@ -24,7 +24,6 @@ enum { first, last};
void foo(void) {
sanjose obj(first); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 26 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.benjamin/15800-1.C b/gcc/testsuite/g++.old-deja/g++.benjamin/15800-1.C
index 4f6d878e885..5f2fe1047cd 100644
--- a/gcc/testsuite/g++.old-deja/g++.benjamin/15800-1.C
+++ b/gcc/testsuite/g++.old-deja/g++.benjamin/15800-1.C
@@ -12,7 +12,6 @@ extern panama dig();
void foo() {
panama obj;
- obj = dig(); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 15 }
+ obj = dig(); // { dg-error "rvalue" }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.bob/inherit2.C b/gcc/testsuite/g++.old-deja/g++.bob/inherit2.C
index 6e26ecfa639..f92e8e12047 100644
--- a/gcc/testsuite/g++.old-deja/g++.bob/inherit2.C
+++ b/gcc/testsuite/g++.old-deja/g++.bob/inherit2.C
@@ -15,7 +15,7 @@ public:
B(void) {}
};
-void f(B b) { // { dg-error "initializing" }
+void f(B b) { // { dg-message "initializing" }
}
void g() {
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/ambiguity1.C b/gcc/testsuite/g++.old-deja/g++.brendan/ambiguity1.C
index 4706d7e8a71..23e38e6a154 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/ambiguity1.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/ambiguity1.C
@@ -14,5 +14,4 @@ void myfunc (const B& t0); // { dg-message "note" }
int main ()
{
myfunc(1); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 16 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash29.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash29.C
index 38c9d49a19d..8b63c9f8036 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/crash29.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash29.C
@@ -15,6 +15,5 @@ int
main()
{
new GlobalAddress(Value()); // internal error occured here// { dg-error "no matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 17 }
//new GlobalAddress(new Value()); // This line is correct code
}
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash48.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash48.C
index fe759406ee1..58a5bf4eac0 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/crash48.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash48.C
@@ -13,12 +13,10 @@ class bug { // { dg-message "bug::bug|candidate expects" }
bug::bug(int size) // { dg-message "bug::bug|candidate expects" }
{
numbers = new internal(size * size);// { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 15 }
}
int
main()
{
bug test; // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 22 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/cvt3.C b/gcc/testsuite/g++.old-deja/g++.brendan/cvt3.C
index 8be5d6ed333..8b253a10a14 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/cvt3.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/cvt3.C
@@ -44,6 +44,5 @@ public:
void
foo (bar yylval, bar *yyvsp)
{
- nnyacc::assign(yylval.valueList, yyvsp[0].valueList);// { dg-error "no matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 47 }
+ nnyacc::assign(yylval.valueList, yyvsp[0].valueList);// { dg-error "no matching|rvalue" }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/friend4.C b/gcc/testsuite/g++.old-deja/g++.brendan/friend4.C
index 4d436e5c9c6..dc55280751d 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/friend4.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/friend4.C
@@ -2,5 +2,5 @@
// GROUPS passed friends
// do_friend should complain that foo was declared as a friend of
// A before A was defined
-struct A; // { dg-error "forward" }
+struct A; // { dg-message "forward" }
struct B { friend A::foo (); };// { dg-error "" } .*
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/overload1.C b/gcc/testsuite/g++.old-deja/g++.brendan/overload1.C
index 1b9415b0ed0..e7aca7e077d 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/overload1.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/overload1.C
@@ -17,6 +17,5 @@ int main ()
Bar b;
b.f ();// { dg-error "no matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 19 }
b.f (10);
}
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/overload4.C b/gcc/testsuite/g++.old-deja/g++.brendan/overload4.C
index 6206d0b9eb1..61842100d00 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/overload4.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/overload4.C
@@ -18,7 +18,6 @@
B::WantsNew ( (NewObject) A::NewOne );
// This used to die in convert_harshness_{ansi,old} cuz it
// didn't know what to do about a void type.
- B::WantsNew ( A::NewOne );// { dg-error "no matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 21 }
+ B::WantsNew ( A::NewOne );// { dg-error "no matching|conversion" }
}
};
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/overload9.C b/gcc/testsuite/g++.old-deja/g++.brendan/overload9.C
index b24a1f6479f..0e245679ce6 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/overload9.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/overload9.C
@@ -1,13 +1,13 @@
// { dg-do assemble }
// GROUPS passed overloading
-class CLogger // { dg-message "candidate" }
+class CLogger
{
public:
void operator() (int,const char *) {}; // { dg-message "note" }
void operator() (int,const char *, ...) {}; // { dg-message "note" }
} Log;
-class CGLogger : public CLogger // { dg-message "candidate" }
+class CGLogger : public CLogger
{
} GLog;
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900121_01.C b/gcc/testsuite/g++.old-deja/g++.bugs/900121_01.C
index 32591635824..da619b88337 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900121_01.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900121_01.C
@@ -7,7 +7,7 @@
// keywords: abort, incomplete types, reference types, formal parameters
-struct s0; // { dg-error "" } forward declaration
+struct s0; // { dg-message "" } forward declaration
void function (struct s0 &arg1, struct s0 &arg2)
{
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900127_01.C b/gcc/testsuite/g++.old-deja/g++.bugs/900127_01.C
index a066d584880..1c315b7fadd 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900127_01.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900127_01.C
@@ -21,7 +21,6 @@ void bar (f_ptr_t2); // { dg-message "note" }
void function ()
{
bar (foo); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 23 }
}
int main () { return 0; }
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900205_04.C b/gcc/testsuite/g++.old-deja/g++.bugs/900205_04.C
index 3d8625e5c8d..4290144f89f 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900205_04.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900205_04.C
@@ -24,7 +24,6 @@ struct0::struct0 (int, void *) // { dg-message "note" }
}
struct struct0_derived_struct_0 : public struct0 { // { dg-error "no matching|deleted" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 26 }
};
struct0_derived_struct_0 object; // { dg-message "synthesized|deleted" }
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900214_01.C b/gcc/testsuite/g++.old-deja/g++.bugs/900214_01.C
index 88cafbfc181..4b161bf89c0 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900214_01.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900214_01.C
@@ -8,7 +8,7 @@
// keywords: friends, incomplete types, function members
-struct A; // { dg-error "" } forward declaration
+struct A; // { dg-message "" } forward declaration
struct B {
friend void A::foo(); // { dg-error "" } type A is incomplete
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C b/gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C
index cad19a2c305..588251d3cf0 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C
@@ -25,7 +25,6 @@ struct D : public B {
void h(D* pd)
{
pd->f(1); // { dg-error "no matching" } D::f(struct B) hides B::f(int)
- // { dg-message "candidate" "candidate note" { target *-*-* } 27 }
}
int main () { return 0; }
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900404_03.C b/gcc/testsuite/g++.old-deja/g++.bugs/900404_03.C
index 7e2829f7b09..6f7ea3f4581 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900404_03.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900404_03.C
@@ -23,7 +23,6 @@ char c;
void test ()
{
function0 (c,c); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 25 }
}
int main () { return 0; }
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900514_03.C b/gcc/testsuite/g++.old-deja/g++.bugs/900514_03.C
index e2460d99bd0..fc4d2108456 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900514_03.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900514_03.C
@@ -29,7 +29,7 @@ struct t_0_st_0 {
operator t_0_st_1 ();// { dg-message "note" }
};
-t_0_st_0 t_0_st_0_obj0; // { dg-message "candidate" }
+t_0_st_0 t_0_st_0_obj0;
void t_0_assignment ()
{
@@ -63,7 +63,7 @@ struct t_1_st_0 {
operator t_1_st_1 (); // { dg-message "note" }
};
-t_1_st_0 t_1_st_0_obj0; // { dg-message "candidate" }
+t_1_st_0 t_1_st_0_obj0;
void t_1_assignment ()
{
@@ -71,10 +71,8 @@ void t_1_assignment ()
t_1_st_1 t_1_st_1_obj1;
t_1_st_1 t_1_st_1_obj2;
- t_1_st_1_obj0 = t_1_st_0_obj0; // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 74 }
- t_1_st_1_obj1 = t_1_st_1 (t_1_st_0_obj0); // { dg-error "no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 76 }
+ t_1_st_1_obj0 = t_1_st_0_obj0; // { dg-error "no match|conversion" }
+ t_1_st_1_obj1 = t_1_st_1 (t_1_st_0_obj0); // { dg-error "no match|rvalue" }
}
void t_1_local_init ()
@@ -98,7 +96,7 @@ struct t_2_st_0 {
operator t_2_st_1 (); // { dg-message "note" }
};
-t_2_st_0 t_2_st_0_obj0; // { dg-message "candidate" }
+t_2_st_0 t_2_st_0_obj0;
void t_2_assignment ()
{
diff --git a/gcc/testsuite/g++.old-deja/g++.eh/catch1.C b/gcc/testsuite/g++.old-deja/g++.eh/catch1.C
index 7aa70ac97b3..67779d945ea 100644
--- a/gcc/testsuite/g++.old-deja/g++.eh/catch1.C
+++ b/gcc/testsuite/g++.old-deja/g++.eh/catch1.C
@@ -5,7 +5,7 @@
// We cannot catch an incomplete type, or ptr to one
-struct A; // { dg-error "" } forward decl
+struct A; // { dg-message "" } forward decl
void fn()
{
diff --git a/gcc/testsuite/g++.old-deja/g++.eh/ctor1.C b/gcc/testsuite/g++.old-deja/g++.eh/ctor1.C
index 0e7218f0c8f..9b4adaf0e4a 100644
--- a/gcc/testsuite/g++.old-deja/g++.eh/ctor1.C
+++ b/gcc/testsuite/g++.old-deja/g++.eh/ctor1.C
@@ -1,7 +1,7 @@
// { dg-do assemble }
struct A
{
- A(); // { dg-message "A::A|candidate expects" } candidate
+ A();
A(A&); // { dg-message "A::A|no known conversion" } referenced below
};
@@ -10,8 +10,7 @@ main ()
{
try
{
- throw A(); // { dg-error "no matching" "match" } can't copy
- // { dg-message "candidate" "candidate note" { target *-*-* } 13 }
+ throw A(); // { dg-error "rvalue" "" } can't copy
// { dg-error "thrown expression" "expr" { target *-*-* } 13 }
}
catch (...) { }
diff --git a/gcc/testsuite/g++.old-deja/g++.eh/spec6.C b/gcc/testsuite/g++.old-deja/g++.eh/spec6.C
index 7780c4a9daf..85e9b4e7c4e 100644
--- a/gcc/testsuite/g++.old-deja/g++.eh/spec6.C
+++ b/gcc/testsuite/g++.old-deja/g++.eh/spec6.C
@@ -7,7 +7,7 @@
// [except.spec] 1, a type in an exception specifier shall not be incomplete,
// or pointer or ref to incomplete
-struct X; // { dg-error "" } forward declaration.*
+struct X; // { dg-message "" } forward declaration.*
void fn1() throw(X); // { dg-error "" } invalid use of undefined type
void fn2() throw(X *); // { dg-error "" } invalid use of undefined type
void fn3() throw(X &); // { dg-error "" } invalid use of undefined tyoe
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/conversion10.C b/gcc/testsuite/g++.old-deja/g++.jason/conversion10.C
index 8cbba413da7..0eeceebaae7 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/conversion10.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/conversion10.C
@@ -1,4 +1,5 @@
// { dg-do assemble }
+// { dg-options "" }
// PRMS Id: 9019
// Bug: g++ doesn't find conversion to const char *.
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/conversion11.C b/gcc/testsuite/g++.old-deja/g++.jason/conversion11.C
index 6621a27b6a2..a7c0fbea974 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/conversion11.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/conversion11.C
@@ -23,7 +23,5 @@ void foo(Something* pX)
{
DoSomething(1); // { dg-error "could not convert" }
pX->DoSomething(1); // { dg-error "no matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 25 }
(*pX).DoSomething(1); // { dg-error "no matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 27 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/crash3.C b/gcc/testsuite/g++.old-deja/g++.jason/crash3.C
index 9dcf6368aad..e94cc7c9781 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/crash3.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/crash3.C
@@ -10,5 +10,4 @@ struct Node // { dg-message "note" }
void bug(int i)
{
Node* q = new Node(i); // { dg-error "no matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 12 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/overload16.C b/gcc/testsuite/g++.old-deja/g++.jason/overload16.C
index fba33eda70d..50503a678a0 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/overload16.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/overload16.C
@@ -4,5 +4,4 @@ void f (long); // { dg-message "note" }
int main()
{
f (1 & 0xffffff00UL); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 6 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/overload28.C b/gcc/testsuite/g++.old-deja/g++.jason/overload28.C
index fe0dae1031f..46bf918d047 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/overload28.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/overload28.C
@@ -9,5 +9,4 @@ struct Foo {
int main()
{
Foo* f1 = new Foo(); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 11 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/scoping10.C b/gcc/testsuite/g++.old-deja/g++.jason/scoping10.C
index a1b563297fc..8106a357807 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/scoping10.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/scoping10.C
@@ -10,7 +10,6 @@ struct B : public A {
void h () {
extern void g (); // { dg-message "" }
f("foo"); // { dg-error "" } hidden
- // { dg-message "candidate" "candidate note" { target *-*-* } 12 }
g("foo"); // { dg-error "" } hidden
}
};
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/template30.C b/gcc/testsuite/g++.old-deja/g++.jason/template30.C
index 9414c06cee2..0304ba56205 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/template30.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/template30.C
@@ -11,5 +11,4 @@ int func(T, U) // { dg-message "note" }
int main ()
{
func (0, 1); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 13 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/temporary2.C b/gcc/testsuite/g++.old-deja/g++.jason/temporary2.C
index da216ae5cc7..e55738477f2 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/temporary2.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/temporary2.C
@@ -2,7 +2,7 @@
class X // Indentation has been done so to see the similarities.
{
public:
- X() {} // { dg-message "note" } referenced below
+ X() {}
X(X& x) {x.i=7;} // { dg-message "note" } Both functions modify the
void bar(X& x) {x.i=7;} // { dg-message "note" } reference parameter x.
int i;
@@ -12,8 +12,6 @@ X foo() { X x; return x; }
int main()
{
- X x(foo()); // { dg-error "no match" } Compiler doesn't warn about temporary reference.
- // { dg-message "candidate" "candidate note" { target *-*-* } 15 }
- x.bar(foo()); // { dg-error "no match" } The same mistake is warned about in this case.
- // { dg-message "candidate" "candidate note" { target *-*-* } 17 }
+ X x(foo()); // { dg-error "rvalue" } Compiler doesn't warn about temporary reference.
+ x.bar(foo()); // { dg-error "rvalue" } The same mistake is warned about in this case.
}
diff --git a/gcc/testsuite/g++.old-deja/g++.law/arg1.C b/gcc/testsuite/g++.old-deja/g++.law/arg1.C
index 3fc42bccc1b..2a87633d10a 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/arg1.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/arg1.C
@@ -25,8 +25,6 @@ int main()
B b;
a.f(0);// { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 27 }
b.f(0);// { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 29 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.law/arg11.C b/gcc/testsuite/g++.old-deja/g++.law/arg11.C
index fc9357964f4..bd88844e486 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/arg11.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/arg11.C
@@ -18,6 +18,5 @@ foo(S *o)
{ // Neither call has a usable constructor for conversions of char[5] to Ack.
function("adsf");// { dg-error "could not convert" }
o->method("adsf");// { dg-error "no matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 20 }
return 0;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.law/arm9.C b/gcc/testsuite/g++.old-deja/g++.law/arm9.C
index 979ef808820..c603aab01fc 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/arm9.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/arm9.C
@@ -24,7 +24,6 @@ void B::set (f2 f) { std::cout << "called B\n|no known conversion";} // { dg-mes
int main() {
B b;
b.set(F1); // ARM page 309: should call A.set(f1) and that what g++ does,// { dg-error "match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 26 }
// but 13.1 of ARM clearly states that it should call B::set()
// or generate an error because overloading works only for
// functions within the same scope (first page of chapter 13)
diff --git a/gcc/testsuite/g++.old-deja/g++.law/ctors11.C b/gcc/testsuite/g++.old-deja/g++.law/ctors11.C
index c8b59b67926..39ee76b0ae7 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/ctors11.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/ctors11.C
@@ -18,5 +18,4 @@ public:
int main()
{
B(10);// { dg-error "match" } B doesn't have a constructor taking int
- // { dg-message "candidate" "candidate note" { target *-*-* } 20 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.law/ctors17.C b/gcc/testsuite/g++.old-deja/g++.law/ctors17.C
index 071a36008f8..0d61c49abd7 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/ctors17.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/ctors17.C
@@ -20,5 +20,4 @@ int main()
X *y = new X(10, "123");
// the compiler must reject this constructor call:
X *x = new X("abc");// { dg-error "match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 22 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.law/ctors5.C b/gcc/testsuite/g++.old-deja/g++.law/ctors5.C
index 1776be949bb..8015c4bfc25 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/ctors5.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/ctors5.C
@@ -31,7 +31,6 @@ X::X( int xi ) // { dg-error "14:return type specification for constructor inval
const X X::x0( 0 );
Y::Y() // { dg-error "6:no matching function for call to 'X::X\\(\\)'" }
-// { dg-message "candidate" "candidate note" { target *-*-* } 33 }
{
xx = X::x0;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.law/ctors9.C b/gcc/testsuite/g++.old-deja/g++.law/ctors9.C
index d94495a253e..43ba1262c95 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/ctors9.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/ctors9.C
@@ -33,7 +33,6 @@ int blort(Foo& f)
int main()
{
var_Foo b(2);// { dg-error "match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 35 }
b->a = 0;
int x = blort(b);
return x;
diff --git a/gcc/testsuite/g++.old-deja/g++.law/cvt20.C b/gcc/testsuite/g++.old-deja/g++.law/cvt20.C
index 9389a107ff7..f5c703bccfd 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/cvt20.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/cvt20.C
@@ -9,7 +9,7 @@
// Compiles fine with Sun CC 2.1
-void f(char *& x) // { dg-message "passing argument" }
+void f(const char *& x) // { dg-message "argument" }
{
x++;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.law/enum4.C b/gcc/testsuite/g++.old-deja/g++.law/enum4.C
index 6695061210d..363f1149344 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/enum4.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/enum4.C
@@ -24,7 +24,6 @@ int main()
Enum e = enumerator1;
Struct s;
int x = funct(e+1);// { dg-error "invalid" }
- int y = s.getI(e+1);// { dg-error "match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 27 }
+ int y = s.getI(e+1);// { dg-error "invalid" }
return x+y;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.law/init8.C b/gcc/testsuite/g++.old-deja/g++.law/init8.C
index 5ed619b670d..829dd9be5a5 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/init8.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/init8.C
@@ -8,7 +8,7 @@
const int ic = 1;
-void f(int& arg) // { dg-message "passing argument 1" }
+void f(int& arg) // { dg-message "argument 1" }
{
if (arg) ;
}
@@ -16,7 +16,7 @@ const int& icr = ic;
int main(void)
{
- f(icr); // { dg-error "invalid initialization" }
+ f(icr); // { dg-error "const" }
return 0;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.law/missed-error2.C b/gcc/testsuite/g++.old-deja/g++.law/missed-error2.C
index 7d058fd896e..42f70aeb997 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/missed-error2.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/missed-error2.C
@@ -32,6 +32,5 @@ static void foo(int i, int j, double x, double y) {
std::cout << "Max(int): " << max(i,j) << " Max(double): " <<
max(x,y) << '\n';
std::cout << "Max(int, double): " << max(i, y) << '\n';// { dg-error "" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 34 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.law/operators9.C b/gcc/testsuite/g++.old-deja/g++.law/operators9.C
index 3c50cbdd0e7..8d5b686d9ae 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/operators9.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/operators9.C
@@ -16,6 +16,5 @@ public:
void
test(B &b1, const B &b2)
{
- b1 = b2;// { dg-error "match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 19 }
+ b1 = b2;// { dg-error "const" }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/net2.C b/gcc/testsuite/g++.old-deja/g++.mike/net2.C
index dfc57e149aa..f2240ddfc18 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/net2.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/net2.C
@@ -11,4 +11,3 @@ class A { // { dg-message "note" } copy ctor candidate
};
A a(0); // { dg-error "ambiguous" }
-// { dg-message "candidate" "candidate note" { target *-*-* } 13 }
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/net22.C b/gcc/testsuite/g++.old-deja/g++.mike/net22.C
index 604aef9bcc0..e5e1cb1081d 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/net22.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/net22.C
@@ -10,6 +10,5 @@ class Child : public Parent { // { dg-message "note" } called
int main() {
Child c( "String initializer" ); // { dg-error "match" } bad
- // { dg-message "candidate" "candidate note" { target *-*-* } 12 }
return 0;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/net8.C b/gcc/testsuite/g++.old-deja/g++.mike/net8.C
index d1f6864513b..6c2cd7f92dd 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/net8.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/net8.C
@@ -11,14 +11,14 @@ public:
int bar;
};
-void func(Base&); // { dg-message "passing argument 1" }
+void func(Base&); // { dg-message "argument 1" }
void func2(const Derived& d) {
- func(d); // { dg-error "invalid initialization" }
+ func(d); // { dg-error "" }
}
void
-foo (int& a) // { dg-message "in passing argument 1" }
+foo (int& a) // { dg-message "argument 1" }
{
}
@@ -27,6 +27,6 @@ int main ()
int b;
const int*const a = &b;
*a = 10; // { dg-error "read-only location" }
- foo (*a); // { dg-error "invalid initialization" }
+ foo (*a); // { dg-error "qualifiers" }
return 0;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p1989.C b/gcc/testsuite/g++.old-deja/g++.mike/p1989.C
index fdede63e406..376d1f5a949 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p1989.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p1989.C
@@ -196,8 +196,7 @@ Pix
List_DLS<T>::search(const T& item) const
{
for (Pix x=this->first(); 0 != x; this->next(x)) {
- if (item == this->operator()(x)) // { dg-error "match" } const subversion
- // { dg-message "candidate" "candidate note" { target *-*-* } 199 }
+ if (item == this->operator()(x)) // { dg-error "qualifiers" } const subversion
return x;
}
return 0;
@@ -486,8 +485,8 @@ class STRLIdentifier {
char buf[10];
};
-extern int operator==(vertex<STRLIdentifier*>&, vertex<STRLIdentifier*>&); // { dg-message "note" } const subversion
-extern int operator==(STRLIdentifier&, STRLIdentifier&); // { dg-message "note" } fn ref in err msg
+extern int operator==(vertex<STRLIdentifier*>&, vertex<STRLIdentifier*>&); // { dg-message "argument 1" } const subversion
+extern int operator==(STRLIdentifier&, STRLIdentifier&);
extern int x(List_DLSp<STRLIdentifier *>);
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p2431.C b/gcc/testsuite/g++.old-deja/g++.mike/p2431.C
index 4e74899a1d8..8a7ede660ba 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p2431.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p2431.C
@@ -18,7 +18,6 @@ class C
C()
{
B b;
- A a = b;// { dg-error "match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 21 }
+ A a = b;// { dg-error "rvalue" }
}
};
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p438.C b/gcc/testsuite/g++.old-deja/g++.mike/p438.C
index 6e78af16515..18f926775e2 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p438.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p438.C
@@ -19,6 +19,5 @@ void C::test() const
{
D d;
- d.a(*this); // { dg-error "match" } *this is const, so should get error
- // { dg-message "candidate" "candidate note" { target *-*-* } 22 }
+ d.a(*this); // { dg-error "const" } *this is const, so should get error
}
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p701.C b/gcc/testsuite/g++.old-deja/g++.mike/p701.C
index 8e9a345e35a..99ef1f4d6c8 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p701.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p701.C
@@ -7,7 +7,7 @@ extern "C"
}
-void Munge(int& x) // { dg-message "passing argument 1" }
+void Munge(int& x) // { dg-message "argument 1" }
{
x = 2;
}
@@ -24,7 +24,7 @@ class A
void
A::Safe() const
{
- Munge(i); // { dg-error "invalid initialization" }
+ Munge(i); // { dg-error "const" }
}
int main()
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p7868.C b/gcc/testsuite/g++.old-deja/g++.mike/p7868.C
index 48bdf8b2500..8a94b3ecb1a 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p7868.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p7868.C
@@ -4,13 +4,13 @@
struct DIAGTYP {
};
struct DIAGTYP1 {
- struct DIAGTYP; // { dg-error "" } forward declaration
+ struct DIAGTYP; // { dg-message "" } forward declaration
void bar() { new struct DIAGTYP; } // { dg-error "" } undefined
void foo() { new struct DIAGTYP1; }
};
int main () {
- struct DIAGTYP; // { dg-error "" } forward declaration
+ struct DIAGTYP; // { dg-message "" } forward declaration
struct DIAGTYP *lerror_desc;
lerror_desc= new struct DIAGTYP; // { dg-error "" } undefined
}
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p807a.C b/gcc/testsuite/g++.old-deja/g++.mike/p807a.C
index 04c9c4867e9..39d4f9aadcd 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p807a.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p807a.C
@@ -18,5 +18,5 @@ public:
operator A(); // { dg-message "note" } fn ref in err msg
};
-B b; // { dg-message "candidate" }
+B b;
A a = b; // { dg-error "ambiguous" } should fail as it is ambigious.
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p9068.C b/gcc/testsuite/g++.old-deja/g++.mike/p9068.C
index 2c62f5c79ab..a33f60f58e4 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p9068.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p9068.C
@@ -14,7 +14,6 @@ public:
void foo (ostream& lhs, const C& rhs)
{
lhs << rhs.i; // { dg-error "match" } no such i for any opr << ()
- // { dg-message "candidate" "candidate note" { target *-*-* } 16 }
}
int& C::i () {
diff --git a/gcc/testsuite/g++.old-deja/g++.niklas/t120.C b/gcc/testsuite/g++.old-deja/g++.niklas/t120.C
index 7a54e051b1e..3f5baea67a2 100644
--- a/gcc/testsuite/g++.old-deja/g++.niklas/t120.C
+++ b/gcc/testsuite/g++.old-deja/g++.niklas/t120.C
@@ -2,5 +2,5 @@
// GROUPS passed niklas ellipsis
typedef void (*T) (...);
void f ();
-struct S { void g (T); void h() { g(f); } };// { dg-error "match" "match" }
+struct S { void g (T); void h() { g(f); } };// { dg-error "" "match" }
// { dg-message "candidate|S::g|no known conversion" "match candidate text" { target *-*-* } 5 }
diff --git a/gcc/testsuite/g++.old-deja/g++.niklas/t121.C b/gcc/testsuite/g++.old-deja/g++.niklas/t121.C
index b0c9253da84..a2aa62fbde6 100644
--- a/gcc/testsuite/g++.old-deja/g++.niklas/t121.C
+++ b/gcc/testsuite/g++.old-deja/g++.niklas/t121.C
@@ -2,5 +2,5 @@
// GROUPS passed niklas ellipsis
void f ();
void g1 (void (*) (...)); void h1 () { g1 (f); }// { dg-error "invalid conversion" }
-struct S { void g2 (void (*) (...)); void h2 () { g2 (f); } };// { dg-error "match" "match" }
+struct S { void g2 (void (*) (...)); void h2 () { g2 (f); } };// { dg-error "invalid conversion" "match" }
// { dg-message "candidate|S::g2|no known conversion" "match candidate text" { target *-*-* } 5 }
diff --git a/gcc/testsuite/g++.old-deja/g++.niklas/t128.C b/gcc/testsuite/g++.old-deja/g++.niklas/t128.C
index cf0a4f71b8e..19e3ca1dab0 100644
--- a/gcc/testsuite/g++.old-deja/g++.niklas/t128.C
+++ b/gcc/testsuite/g++.old-deja/g++.niklas/t128.C
@@ -3,4 +3,3 @@
struct A { A (int); };
struct B : A {}; // { dg-message "note" } without ctor // ERROR - candidates
void f () { B (0); }// { dg-error "match" } .*
-// { dg-message "candidate" "candidate note" { target *-*-* } 5 }
diff --git a/gcc/testsuite/g++.old-deja/g++.ns/overload2.C b/gcc/testsuite/g++.old-deja/g++.ns/overload2.C
index facfa3f5698..85df6bd694b 100644
--- a/gcc/testsuite/g++.old-deja/g++.ns/overload2.C
+++ b/gcc/testsuite/g++.old-deja/g++.ns/overload2.C
@@ -10,5 +10,4 @@ void f(); // { dg-message "note" }
void g()
{
f(); // { dg-error "ambiguous" } ambiguous, ::f or A::f ?
- // { dg-message "candidate" "candidate note" { target *-*-* } 12 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.ns/using12.C b/gcc/testsuite/g++.old-deja/g++.ns/using12.C
index 343cfefc459..ba06b5a3f7f 100644
--- a/gcc/testsuite/g++.old-deja/g++.ns/using12.C
+++ b/gcc/testsuite/g++.old-deja/g++.ns/using12.C
@@ -16,5 +16,4 @@ void fn (int i)
using foo::x;
using baz::x;
x(i); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 18 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/crash24.C b/gcc/testsuite/g++.old-deja/g++.other/crash24.C
index b1fa01c9b49..a4d655a796a 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/crash24.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/crash24.C
@@ -3,7 +3,7 @@
class foo {
public:
- class __iterator;
+ class __iterator; // { dg-message "declaration" }
friend class __iterator;
typedef __iterator const_iterator;
virtual ~foo() { }
@@ -12,8 +12,7 @@ class foo {
static void iteratorTest(const foo &x)
{
foo::const_iterator i = x.begin(); // { dg-error "incomplete type" "incomplete type" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 14 }
- // { dg-error "no matching" "no matching" { target *-*-* } 14 }
+ // { dg-error "const foo" "" { target *-*-* } 14 }
for (; i; ++i)
*i;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/crash38.C b/gcc/testsuite/g++.old-deja/g++.other/crash38.C
index d07115e51ca..87e55556128 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/crash38.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/crash38.C
@@ -6,7 +6,7 @@
// Bug 611. We ICEd when calling a member function returning an incomplete
// type by value.
-struct X; // { dg-error "" } forward ref
+struct X; // { dg-message "" } forward ref
struct Y
{
diff --git a/gcc/testsuite/g++.old-deja/g++.other/enum2.C b/gcc/testsuite/g++.old-deja/g++.other/enum2.C
index 40328bfc6b9..7fc269d9de0 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/enum2.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/enum2.C
@@ -5,7 +5,7 @@
// We'd like the enum location to be its identifier.
-enum thing // { dg-error "" } previous def
+enum thing // { dg-message "" } previous def
{
val1
};
diff --git a/gcc/testsuite/g++.old-deja/g++.other/expr1.C b/gcc/testsuite/g++.old-deja/g++.other/expr1.C
index 87166f0ae2d..831876d01cb 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/expr1.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/expr1.C
@@ -2,7 +2,7 @@
// Simplified from bug report by Trevor Taylor <ttaylor@powerup.com.au>
-struct T { // { dg-message "candidate" }
+struct T {
int operator()(int) { } // { dg-message "operator|candidate expects" }
};
diff --git a/gcc/testsuite/g++.old-deja/g++.other/incomplete.C b/gcc/testsuite/g++.old-deja/g++.other/incomplete.C
index a00ea1c7d2e..7f0bc9409e8 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/incomplete.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/incomplete.C
@@ -4,7 +4,7 @@
// a void parm. We need to distinguish between a parmlist of (void), and
// some ill-formed ones.
-struct S; // { dg-error "" } forward ref
+struct S; // { dg-message "" } forward ref
void f(S); // ok
void f(S s) {} // { dg-error "" } incomplete type
diff --git a/gcc/testsuite/g++.old-deja/g++.other/overload11.C b/gcc/testsuite/g++.old-deja/g++.other/overload11.C
index 0b910e48a04..9b5b44bd32d 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/overload11.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/overload11.C
@@ -34,7 +34,6 @@ int main (int argc, char **argv)
(ovl) (1); // ok
(&ovl) (1); // ok
(ovl) (); // { dg-error "" } no matching candidates
- // { dg-message "candidate" "candidate note" { target *-*-* } 36 }
(&ovl) (); // { dg-error "" } not suitable for overload resolution
// 13.3.1.1 indicates that the following are errors -- the primary expression
diff --git a/gcc/testsuite/g++.old-deja/g++.other/vaarg3.C b/gcc/testsuite/g++.old-deja/g++.other/vaarg3.C
index 3408a181188..134a89c97f6 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/vaarg3.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/vaarg3.C
@@ -10,7 +10,7 @@
struct X {int m;};
struct Y { Y(const Y&); };
-struct Z; // { dg-error "forward decl" }
+struct Z; // { dg-message "forward decl" }
void fn1(va_list args)
{
int i = va_arg (args, int);
diff --git a/gcc/testsuite/g++.old-deja/g++.other/volatile1.C b/gcc/testsuite/g++.old-deja/g++.other/volatile1.C
index ca28ec8e443..7d818fbe9e1 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/volatile1.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/volatile1.C
@@ -15,7 +15,6 @@ ret_v_f_class()
int main(void)
{
volatile f_class vf;
- 0 ? ret_v_f_class() : vf; // { dg-error "match" } can't copy volatile lvalue
- // { dg-message "candidate" "candidate note" { target *-*-* } 18 }
+ 0 ? ret_v_f_class() : vf; // { dg-error "volatile" } can't copy volatile lvalue
return 0;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/auto_ptr.C b/gcc/testsuite/g++.old-deja/g++.pt/auto_ptr.C
index ecfa4de18f9..4a363a27f30 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/auto_ptr.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/auto_ptr.C
@@ -11,7 +11,7 @@ template<typename X> struct auto_ptr {
explicit auto_ptr(X* p =0) throw() : px(p) {}
auto_ptr(auto_ptr& r) throw() : px(r.release()) {} // { dg-message "note" } candidate
template<typename Y>
- auto_ptr(auto_ptr<Y>& r) throw() : px(r.release()) {}// { dg-message "note" } candidate
+ auto_ptr(auto_ptr<Y>& r) throw() : px(r.release()) {}
auto_ptr& operator=(auto_ptr& r) throw() {
reset(r.release());
@@ -30,7 +30,7 @@ template<typename X> struct auto_ptr {
X* release() throw() { X* p=px; px=0; return p; }
void reset(X* p=0) throw() { if (px != p) delete px, px = p; }
- auto_ptr(auto_ptr_ref<X> r) throw() : px(r.py) {} // { dg-message "note" }
+ auto_ptr(auto_ptr_ref<X> r) throw() : px(r.py) {}
template<typename Y> operator auto_ptr_ref<Y>() throw() {
return auto_ptr_ref<Y>(release());
}
@@ -44,13 +44,12 @@ struct Derived : Base { Derived() {} };
auto_ptr<Derived> f() { auto_ptr<Derived> null(0); return null; }
void g(auto_ptr<Derived>) { }
-void h(auto_ptr<Base>) { } // { dg-error "initializing" }
+void h(auto_ptr<Base>) { } // { dg-message "initializing" }
int main() {
auto_ptr<Base> x(f());
auto_ptr<Derived> y(f());
x = y;
g(f());
- h(f()); // { dg-error "match" "match" } no usable copy ctor
- // { dg-message "candidate" "candidate note" { target *-*-* } 54 }
+ h(f()); // { dg-error "rvalue" "" } no usable copy ctor
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash60.C b/gcc/testsuite/g++.old-deja/g++.pt/crash60.C
index 1be4678e1f4..9f643471d92 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/crash60.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/crash60.C
@@ -15,5 +15,4 @@ struct S { void f( int ); };
void f()
{
k( E(), (S*)0, &S::f ); // { dg-error "" } no match
- // { dg-message "candidate" "candidate note" { target *-*-* } 17 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash9.C b/gcc/testsuite/g++.old-deja/g++.pt/crash9.C
index f2d811dda1a..f54d6387c29 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/crash9.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/crash9.C
@@ -1,9 +1,9 @@
// { dg-do assemble }
template <class T>
-void f(T) {} // { dg-error "initializing" }
+void f(T) {} // { dg-message "initializing" }
-class C; // { dg-error "forward declaration" }
+class C; // { dg-message "forward declaration" }
void g(const C& c)
{
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit38.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit38.C
index 1831e45a355..3e74829380f 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/explicit38.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit38.C
@@ -5,5 +5,4 @@ void f(int j); // { dg-message "note" }
void g()
{
f<7, 12>(3); // { dg-error "" } no matching function.
- // { dg-message "candidate" "candidate note" { target *-*-* } 7 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit39.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit39.C
index 995d8c0750b..1be66e89b6c 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/explicit39.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit39.C
@@ -5,5 +5,4 @@ void f(int i); // { dg-message "note" }
void g()
{
f<7>(3); // { dg-error "" } no matching function.
- // { dg-message "candidate" "candidate note" { target *-*-* } 7 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit41.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit41.C
index c27d1312381..13062ed373e 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/explicit41.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit41.C
@@ -6,5 +6,4 @@ void g()
{
int i;
f<i>(7); // { dg-error "" } template argument 1 is invalid.
- // { dg-message "candidate" "candidate note" { target *-*-* } 8 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit67.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit67.C
index c0863a072a1..534309f0c98 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/explicit67.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit67.C
@@ -16,8 +16,6 @@ void foo(); // { dg-message "note" }
void bar()
{
foo<S::f>(); // { dg-error "" } no matching function
- // { dg-message "candidate" "candidate note" { target *-*-* } 18 }
foo<g>(); // { dg-error "" } no matching function
- // { dg-message "candidate" "candidate note" { target *-*-* } 20 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C b/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
index 84765142fe3..3130d32cadb 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
@@ -1,7 +1,7 @@
// { dg-do assemble }
// { dg-options "-fshow-column" }
-struct A { // { dg-error "" } forward declaration
+struct A { // { dg-message "" } forward declaration
friend struct B : A { // { dg-error "invalid use of incomplete type 'struct A" "invalid" }
int x;
}; // { dg-error "class definition may not be declared a friend" "may not" { target *-*-* } { 5 } }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ptrmem10.C b/gcc/testsuite/g++.old-deja/g++.pt/ptrmem10.C
index 6d61079b4c2..8600e8292f2 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/ptrmem10.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/ptrmem10.C
@@ -22,7 +22,6 @@ template <typename T> void foo (int (A::*)(T)); // { dg-message "note" } candi
void A::baz ()
{
foo (&A::f); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 24 }
foo (A::f);
foo (&(A::f));
foo (f);
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec35.C b/gcc/testsuite/g++.old-deja/g++.pt/spec35.C
index fc5d5262b55..581bb8ed537 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/spec35.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/spec35.C
@@ -24,12 +24,8 @@ template <typename T> int Baz (T *); // { dg-message "note" } candi
int Baz (int const *ptr, int *ptr2)
{
Baz (ptr2); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 26 }
Bar (ptr2); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 28 }
Foo (ptr2); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 30 }
Qux (ptr2); // { dg-error "ambiguous" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 32 }
return 0;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/t05.C b/gcc/testsuite/g++.old-deja/g++.pt/t05.C
index bf4f1ea8d25..f1eda15db83 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/t05.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/t05.C
@@ -1,10 +1,9 @@
// { dg-do assemble }
-template <class A> class B { // { dg-message "note" }
+template <class A> class B {
A a;
public:
B(A&aa); // { dg-message "note" }
~B();
};
-static B<int> b_int (3); // { dg-error "no matching function" }
-// { dg-message "candidate" "candidate note" { target *-*-* } 9 }
+static B<int> b_int (3); // { dg-error "no match|rvalue" }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/t24.C b/gcc/testsuite/g++.old-deja/g++.pt/t24.C
index 77d1c990950..890b7f72f6f 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/t24.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/t24.C
@@ -5,5 +5,4 @@ template <class X> int f (X x, X y) { return 23; } // { dg-message "note" }
int foo () {
return f (7); // { dg-error "" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 7 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename8.C b/gcc/testsuite/g++.old-deja/g++.pt/typename8.C
index 4861cf301ed..581d6ce764d 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/typename8.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/typename8.C
@@ -17,7 +17,7 @@ public:
}
};
-class B : public A< B > // { dg-error "" } forward declaration
+class B : public A< B > // { dg-message "" } forward declaration
{
public:
typedef int myT;
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/unify6.C b/gcc/testsuite/g++.old-deja/g++.pt/unify6.C
index a6f76744d22..d122ec2dcb9 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/unify6.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/unify6.C
@@ -24,9 +24,7 @@ template<class T> void foo(T const *){} // { dg-error "pointer to reference" }
void f()
{
foo<int &>(); // { dg-error "" } attempt to build int & const *
- // { dg-message "candidate" "candidate note" { target *-*-* } 26 }
foo<void ()>(); // { dg-error "" } attempt to build void (const *)()
- // { dg-message "candidate" "candidate note" { target *-*-* } 28 }
}
typedef void (*Fptr)();
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/unify8.C b/gcc/testsuite/g++.old-deja/g++.pt/unify8.C
index 3a86d977ec3..2d9abd5f9e3 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/unify8.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/unify8.C
@@ -16,6 +16,6 @@ void Foo (float); // { dg-message "note" } candidate
void baz (int **p1)
{
Foo (p1); // { dg-error "match" } no such function
- // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 18 }
+ // { dg-message "(candidate|incompatible cv-qualifiers|conversion)" "candidate note" { target *-*-* } 18 }
Bar (p1); // OK
}
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C
index b44c33d273c..6dc2c55be58 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C
@@ -66,7 +66,6 @@ int main()
{
// no edge weighting, therefore type Empty:
Graph<std::string, Empty> V(true); // { dg-error "no match" } no bool constructor
- // { dg-message "candidate" "candidate note" { target *-*-* } 68 }
// ReadGraph(V, "gra1.dat");
// display of vertices with successors
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb119.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb119.C
index 329393aeadf..c4b3ffe6509 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb119.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb119.C
@@ -7,6 +7,5 @@ void f() // { dg-message "note" }
int main()
{
f<bool>(); // { dg-error "" } .*
- // { dg-message "candidate" "candidate note" { target *-*-* } 9 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb131.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb131.C
index 67445308c1a..6a0f1c35c0f 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb131.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb131.C
@@ -16,7 +16,5 @@ struct a {
a::a()
{
foo( &junk ); // { dg-error "match" } junk is an unqualified-id.
- // { dg-message "candidate" "candidate note" { target *-*-* } 18 }
foo( &bar ); // { dg-error "match" } bar is an unqualified-id.
- // { dg-message "candidate" "candidate note" { target *-*-* } 20 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb22.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb22.C
index a78ea41085a..e9d50deaf63 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb22.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb22.C
@@ -25,5 +25,4 @@ bool f()
{
return 3 == MyInt(); // { dg-error "ambiguous" "err" }
// { dg-message "operator==" "match candidate text" { target *-*-* } 26 }
- // { dg-message "candidates" "note" { target *-*-* } 26 }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb69.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb69.C
index 1ada9123429..9620b87be44 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb69.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb69.C
@@ -12,7 +12,6 @@ struct foo { // { dg-message "note" } candidate
struct bar : foo {
typedef int an_int;
bar() : bar::an_int(3) {} // { dg-error "match" "match" } not a base
- // { dg-message "candidate" "candidate note" { target *-*-* } 14 }
// { dg-message "expected" "exp" { target *-*-* } 14 }
};
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/ice990323-1.C b/gcc/testsuite/g++.old-deja/g++.robertl/ice990323-1.C
index 41fed6ff502..cecf0aac50f 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/ice990323-1.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/ice990323-1.C
@@ -4,6 +4,6 @@
struct A {};
void f()
{
- struct A; // { dg-error "" } forward ref
+ struct A; // { dg-message "" } forward ref
throw *(new A); // { dg-error "" } invalid use of undefined type
}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr61222-1.c b/gcc/testsuite/gcc.c-torture/compile/pr61222-1.c
new file mode 100644
index 00000000000..88901937559
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr61222-1.c
@@ -0,0 +1,23 @@
+int a, b, d, e;
+char c;
+
+void
+foo ()
+{
+ for (; a; a++)
+ {
+ d = ((b == 0) ^ (129 + a));
+ c = d * 9;
+ e = c < 1;
+ if (e)
+ for (;;)
+ ;
+ }
+}
+
+int
+main ()
+{
+ foo ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr61222-2.c b/gcc/testsuite/gcc.c-torture/compile/pr61222-2.c
new file mode 100644
index 00000000000..23611c13b15
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr61222-2.c
@@ -0,0 +1,7 @@
+int a, b, d;
+int main (void)
+{
+ int c = a && 1;
+ d = 1 << (((c | (b - 842)) << 1) + 1);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
index 1952dbd7029..9299bb9205a 100644
--- a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
+++ b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
@@ -42,6 +42,10 @@
#elif defined (__CRIS__)
/* No SIGFPE for CRIS integer division. */
# define DO_TEST 0
+#elif defined (__MMIX__)
+/* By default we emit a sequence with DIVU, which "never signals an
+ exceptional condition, even when dividing by zero". */
+# define DO_TEST 0
#elif defined (__arc__)
/* No SIGFPE for ARC integer division. */
# define DO_TEST 0
@@ -88,7 +92,7 @@ sigfpe (int signum __attribute__ ((unused)))
eliminate the assignment to the global k. */
static int i;
static int j;
-int k;
+int k __attribute__ ((used));
int
main ()
diff --git a/gcc/testsuite/gcc.c-torture/execute/bswap-2.c b/gcc/testsuite/gcc.c-torture/execute/bswap-2.c
new file mode 100644
index 00000000000..38f18fd6c95
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/bswap-2.c
@@ -0,0 +1,90 @@
+#ifdef __UINT32_TYPE__
+typedef __UINT32_TYPE__ uint32_t;
+#else
+typedef __UINT32_TYPE__ unsigned;
+#endif
+
+struct bitfield {
+ unsigned char f0:7;
+ unsigned char f1:7;
+ unsigned char f2:7;
+ unsigned char f3:7;
+};
+
+struct ok {
+ unsigned char f0;
+ unsigned char f1;
+ unsigned char f2;
+ unsigned char f3;
+};
+
+union bf_or_uint32 {
+ struct ok inval;
+ struct bitfield bfval;
+};
+
+__attribute__ ((noinline, noclone)) uint32_t
+partial_read_le32 (union bf_or_uint32 in)
+{
+ return in.bfval.f0 | (in.bfval.f1 << 8)
+ | (in.bfval.f2 << 16) | (in.bfval.f3 << 24);
+}
+
+__attribute__ ((noinline, noclone)) uint32_t
+partial_read_be32 (union bf_or_uint32 in)
+{
+ return in.bfval.f3 | (in.bfval.f2 << 8)
+ | (in.bfval.f1 << 16) | (in.bfval.f0 << 24);
+}
+
+__attribute__ ((noinline, noclone)) uint32_t
+fake_read_le32 (char *x, char *y)
+{
+ unsigned char c0, c1, c2, c3;
+
+ c0 = x[0];
+ c1 = x[1];
+ *y = 1;
+ c2 = x[2];
+ c3 = x[3];
+ return c0 | c1 << 8 | c2 << 16 | c3 << 24;
+}
+
+__attribute__ ((noinline, noclone)) uint32_t
+fake_read_be32 (char *x, char *y)
+{
+ unsigned char c0, c1, c2, c3;
+
+ c0 = x[0];
+ c1 = x[1];
+ *y = 1;
+ c2 = x[2];
+ c3 = x[3];
+ return c3 | c2 << 8 | c1 << 16 | c0 << 24;
+}
+
+int
+main ()
+{
+ union bf_or_uint32 bfin;
+ uint32_t out;
+ char cin[] = { 0x83, 0x85, 0x87, 0x89 };
+
+ if (sizeof (uint32_t) * __CHAR_BIT__ != 32)
+ return 0;
+ bfin.inval = (struct ok) { 0x83, 0x85, 0x87, 0x89 };
+ out = partial_read_le32 (bfin);
+ if (out != 0x09070503 && out != 0x88868482 && out != 0x78306141)
+ __builtin_abort ();
+ bfin.inval = (struct ok) { 0x83, 0x85, 0x87, 0x89 };
+ out = partial_read_be32 (bfin);
+ if (out != 0x03050709 && out != 0x82848688 && out != 0x41613078)
+ __builtin_abort ();
+ out = fake_read_le32 (cin, &cin[2]);
+ if (out != 0x89018583)
+ __builtin_abort ();
+ out = fake_read_be32 (cin, &cin[2]);
+ if (out != 0x83850189)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-18.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-18.c
index 7bf111a50ea..bab91ce3889 100644
--- a/gcc/testsuite/gcc.dg/Wstrict-overflow-18.c
+++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-18.c
@@ -1,11 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow" } */
-/* Don't warn about an overflow when folding i > 0. The loop analysis
- should determine that i does not wrap.
-
- The test is really bogus, p->a - p->b can be larger than INT_MAX
- and thus i can very well wrap. */
+/* Warn about an overflow when folding i > 0, p->a - p->b can be larger
+ than INT_MAX and thus i can wrap. */
struct c { unsigned int a; unsigned int b; };
extern void bar (struct c *);
@@ -17,7 +14,7 @@ foo (struct c *p)
for (i = 0; i < p->a - p->b; ++i)
{
- if (i > 0) /* { dg-bogus "warning" "" } */
+ if (i > 0) /* { dg-warning "signed overflow" "" } */
sum += 2;
bar (p);
}
diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-25.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-25.c
new file mode 100644
index 00000000000..00916446371
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-25.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=3" } */
+
+/* We can only simplify the conditional when using strict overflow
+ semantics. */
+
+int
+foo (int x, int y)
+{
+ return x - y < 0; /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */
+}
diff --git a/gcc/testsuite/gcc.dg/debug/pr35154.c b/gcc/testsuite/gcc.dg/debug/pr35154.c
index fa658be2cbe..7f6a6eaa0ec 100644
--- a/gcc/testsuite/gcc.dg/debug/pr35154.c
+++ b/gcc/testsuite/gcc.dg/debug/pr35154.c
@@ -2,6 +2,7 @@
proper structure. These should be lettered G for the struct that gives
the name to the .comm, and should be V or S for .lcomm symbols. */
+__attribute__ ((used))
static char i_outer;
struct {
char f1;
@@ -15,7 +16,7 @@ struct {
int
main()
{
- static char i_inner[2];
+ static char i_inner[2] __attribute__ ((used));
i_inner[0] = 'a'; i_inner[1] = 'b';
opta.f1 = 'c';
opta.f2 = 'd';
diff --git a/gcc/testsuite/gcc.dg/dfp/wtr-conversion-1.c b/gcc/testsuite/gcc.dg/dfp/wtr-conversion-1.c
index 4eff0072590..b85ff3e7c7d 100644
--- a/gcc/testsuite/gcc.dg/dfp/wtr-conversion-1.c
+++ b/gcc/testsuite/gcc.dg/dfp/wtr-conversion-1.c
@@ -3,7 +3,7 @@
Based on gcc.dg/wtr-conversion-1.c */
/* { dg-do compile } */
-/* { dg-options "-Wtraditional" } */
+/* { dg-options "-Wtraditional-conversion" } */
extern void foo_i (int);
extern void foo_f (float);
diff --git a/gcc/testsuite/gcc.dg/fold-compare-8.c b/gcc/testsuite/gcc.dg/fold-compare-8.c
new file mode 100644
index 00000000000..b6e42fdef10
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-compare-8.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-original" } */
+
+int
+foo (int x, int y)
+{
+ return x - y < 0;
+}
+
+/* { dg-final { scan-tree-dump "x < y" "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
diff --git a/gcc/testsuite/gcc.dg/fstack-protector-strong.c b/gcc/testsuite/gcc.dg/fstack-protector-strong.c
index 7c232fff243..da33abb3d7d 100644
--- a/gcc/testsuite/gcc.dg/fstack-protector-strong.c
+++ b/gcc/testsuite/gcc.dg/fstack-protector-strong.c
@@ -131,4 +131,22 @@ foo10 ()
return bb.three;
}
-/* { dg-final { scan-assembler-times "stack_chk_fail" 10 } } */
+struct B
+{
+ /* Discourage passing this struct in registers. */
+ int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
+};
+
+struct B global3 (void);
+
+int foo11 ()
+{
+ return global3 ().a1;
+}
+
+void foo12 ()
+{
+ global3 ();
+}
+
+/* { dg-final { scan-assembler-times "stack_chk_fail" 12 } } */
diff --git a/gcc/testsuite/gcc.dg/init-string-1.c b/gcc/testsuite/gcc.dg/init-string-1.c
index ace3b34562e..a33f741aea1 100644
--- a/gcc/testsuite/gcc.dg/init-string-1.c
+++ b/gcc/testsuite/gcc.dg/init-string-1.c
@@ -30,7 +30,7 @@ struct s j = {
1,
(L"j")
}; /* { dg-bogus "warning" "warning in place of error" } */
-/* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 32 } */
+/* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 31 } */
struct s k = {
(("k")), /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 35 } */
@@ -48,7 +48,7 @@ struct s m = {
.c = L"m",
.a = ("m")
}; /* { dg-bogus "warning" "warning in place of error" } */
-/* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 50 } */
+/* { dg-error "parenthesized|near init" "paren array" { target *-*-* } 49 } */
char *n = (char []){ "n" };
diff --git a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c
index 54d3e761573..fc7b142afdf 100644
--- a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c
+++ b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target { { x86_64-*-* && lp64 } || { powerpc*-*-* && lp64 } } } } */
-/* { dg-options "-O3 -fdump-rtl-ira -fdump-rtl-pro_and_epilogue" } */
+/* { dg-options "-O3 -fdump-rtl-ira -fdump-rtl-pro_and_epilogue -fno-use-caller-save" } */
long __attribute__((noinline, noclone))
foo (long a)
@@ -7,7 +7,7 @@ foo (long a)
return a + 5;
}
-static long g;
+static long g __attribute__ ((used));
long __attribute__((noinline, noclone))
bar (long a)
diff --git a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c
index ed08494cfa0..2e5a9cfdc29 100644
--- a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c
+++ b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target { { x86_64-*-* && lp64 } || { powerpc*-*-* && lp64 } } } } */
-/* { dg-options "-O3 -fdump-rtl-ira -fdump-rtl-pro_and_epilogue" } */
+/* { dg-options "-O3 -fdump-rtl-ira -fdump-rtl-pro_and_epilogue -fno-use-caller-save" } */
long __attribute__((noinline, noclone))
foo (long a)
diff --git a/gcc/testsuite/gcc.dg/lto/pr61278_0.c b/gcc/testsuite/gcc.dg/lto/pr61278_0.c
new file mode 100644
index 00000000000..36cdabc0f22
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr61278_0.c
@@ -0,0 +1,30 @@
+/* { dg-lto-do link } */
+/* { dg-lto-options { { -flto -O0 } } } */
+/* { dg-extra-ld-options " -flto -O1 " } */
+
+static unsigned int
+fn1 (int p1, int p2)
+{
+ return 0;
+}
+
+char a, b, c;
+
+char
+foo (char *p)
+{
+ int i;
+ for (b = 1 ; b > 0; b++)
+ {
+ for (i = 0; i < 2; i++)
+ ;
+ for (a = 1; a > 0; a++)
+ {
+ char d[1] = { 0 };
+ if (*p)
+ break;
+ c ^= fn1 (fn1 (fn1 (0, 0), 0), 0);
+ }
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/lto/pr61278_1.c b/gcc/testsuite/gcc.dg/lto/pr61278_1.c
new file mode 100644
index 00000000000..6e7f0eb7b2e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr61278_1.c
@@ -0,0 +1,10 @@
+extern char foo (char *);
+
+char d;
+
+int
+main ()
+{
+ foo (&d);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/nonnull-2.c b/gcc/testsuite/gcc.dg/nonnull-2.c
index bd36d232d38..d570a467e6a 100644
--- a/gcc/testsuite/gcc.dg/nonnull-2.c
+++ b/gcc/testsuite/gcc.dg/nonnull-2.c
@@ -6,7 +6,7 @@ extern void func1 () __attribute__((nonnull)); /* { dg-error "without arguments"
extern void func2 (char *) __attribute__((nonnull(2))); /* { dg-error "out-of-range operand" } */
-extern void func3 (char *) __attribute__((nonnull(foo))); /* { dg-error "invalid operand number" } */
+extern void func3 (char *) __attribute__((nonnull(foo))); /* { dg-error "invalid operand number|undeclared" } */
extern void func4 (int) __attribute__((nonnull(1))); /* { dg-error "references non-pointer" } */
diff --git a/gcc/testsuite/gcc.dg/optimize-bswapdi-1.c b/gcc/testsuite/gcc.dg/optimize-bswapdi-1.c
index 7d557f369c3..6142e55c51d 100644
--- a/gcc/testsuite/gcc.dg/optimize-bswapdi-1.c
+++ b/gcc/testsuite/gcc.dg/optimize-bswapdi-1.c
@@ -1,6 +1,6 @@
-/* { dg-do compile { target arm*-*-* alpha*-*-* ia64*-*-* x86_64-*-* s390x-*-* powerpc*-*-* rs6000-*-* } } */
+/* { dg-do compile } */
+/* { dg-require-effective-target bswap64 } */
/* { dg-require-effective-target stdint_types } */
-/* { dg-require-effective-target lp64 } */
/* { dg-options "-O2 -fdump-tree-bswap" } */
#include <stdint.h>
diff --git a/gcc/testsuite/gcc.dg/optimize-bswapdi-2.c b/gcc/testsuite/gcc.dg/optimize-bswapdi-2.c
index 6e2821db990..b8ad2c13c40 100644
--- a/gcc/testsuite/gcc.dg/optimize-bswapdi-2.c
+++ b/gcc/testsuite/gcc.dg/optimize-bswapdi-2.c
@@ -1,6 +1,6 @@
-/* { dg-do compile { target arm*-*-* alpha*-*-* ia64*-*-* x86_64-*-* s390x-*-* powerpc*-*-* rs6000-*-* } } */
+/* { dg-do compile } */
+/* { dg-require-effective-target bswap64 } */
/* { dg-require-effective-target stdint_types } */
-/* { dg-require-effective-target lp64 } */
/* { dg-options "-O2 -fdump-tree-bswap" } */
#include <stdint.h>
diff --git a/gcc/testsuite/gcc.dg/optimize-bswapdi-3.c b/gcc/testsuite/gcc.dg/optimize-bswapdi-3.c
new file mode 100644
index 00000000000..0a8bf2e739d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/optimize-bswapdi-3.c
@@ -0,0 +1,64 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target bswap64 } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-options "-O2 -fdump-tree-bswap" } */
+
+#include <stdint.h>
+
+unsigned char data[8];
+
+struct uint64_st {
+ unsigned char u0, u1, u2, u3, u4, u5, u6, u7;
+};
+
+uint64_t read_le64_1 (void)
+{
+ return (uint64_t) data[0] | ((uint64_t) data[1] << 8)
+ | ((uint64_t) data[2] << 16) | ((uint64_t) data[3] << 24)
+ | ((uint64_t) data[4] << 32) | ((uint64_t) data[5] << 40)
+ | ((uint64_t) data[6] << 48) | ((uint64_t) data[7] << 56);
+}
+
+uint64_t read_le64_2 (struct uint64_st data)
+{
+ return (uint64_t) data.u0 | ((uint64_t) data.u1 << 8)
+ | ((uint64_t) data.u2 << 16) | ((uint64_t) data.u3 << 24)
+ | ((uint64_t) data.u4 << 32) | ((uint64_t) data.u5 << 40)
+ | ((uint64_t) data.u6 << 48) | ((uint64_t) data.u7 << 56);
+}
+
+uint64_t read_le64_3 (unsigned char *data)
+{
+ return (uint64_t) *data | ((uint64_t) *(data + 1) << 8)
+ | ((uint64_t) *(data + 2) << 16) | ((uint64_t) *(data + 3) << 24)
+ | ((uint64_t) *(data + 4) << 32) | ((uint64_t) *(data + 5) << 40)
+ | ((uint64_t) *(data + 6) << 48) | ((uint64_t) *(data + 7) << 56);
+}
+
+uint64_t read_be64_1 (void)
+{
+ return (uint64_t) data[7] | ((uint64_t) data[6] << 8)
+ | ((uint64_t) data[5] << 16) | ((uint64_t) data[4] << 24)
+ | ((uint64_t) data[3] << 32) | ((uint64_t) data[2] << 40)
+ | ((uint64_t) data[1] << 48) | ((uint64_t) data[0] << 56);
+}
+
+uint64_t read_be64_2 (struct uint64_st data)
+{
+ return (uint64_t) data.u7 | ((uint64_t) data.u6 << 8)
+ | ((uint64_t) data.u5 << 16) | ((uint64_t) data.u4 << 24)
+ | ((uint64_t) data.u3 << 32) | ((uint64_t) data.u2 << 40)
+ | ((uint64_t) data.u1 << 48) | ((uint64_t) data.u0 << 56);
+}
+
+uint64_t read_be64_3 (unsigned char *data)
+{
+ return (uint64_t) *(data + 7) | ((uint64_t) *(data + 6) << 8)
+ | ((uint64_t) *(data + 5) << 16) | ((uint64_t) *(data + 4) << 24)
+ | ((uint64_t) *(data + 3) << 32) | ((uint64_t) *(data + 2) << 40)
+ | ((uint64_t) *(data + 1) << 48) | ((uint64_t) *data << 56);
+}
+
+/* { dg-final { scan-tree-dump-times "64 bit load in host endianness found at" 3 "bswap" } } */
+/* { dg-final { scan-tree-dump-times "64 bit bswap implementation found at" 3 "bswap" { xfail alpha*-*-* arm*-*-* } } } */
+/* { dg-final { cleanup-tree-dump "bswap" } } */
diff --git a/gcc/testsuite/gcc.dg/optimize-bswaphi-1.c b/gcc/testsuite/gcc.dg/optimize-bswaphi-1.c
new file mode 100644
index 00000000000..65bff98f9f9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/optimize-bswaphi-1.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target bswap16 } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-options "-O2 -fdump-tree-bswap" } */
+/* { dg-options "-O2 -fdump-tree-bswap -march=z900" { target s390-*-* } } */
+
+#include <stdint.h>
+
+unsigned char data[2];
+
+struct uint16_st {
+ unsigned char u0, u1;
+};
+
+uint32_t read_le16_1 (void)
+{
+ return data[0] | (data[1] << 8);
+}
+
+uint32_t read_le16_2 (struct uint16_st data)
+{
+ return data.u0 | (data.u1 << 8);
+}
+
+uint32_t read_le16_3 (unsigned char *data)
+{
+ return *data | (*(data + 1) << 8);
+}
+
+uint32_t read_be16_1 (void)
+{
+ return data[1] | (data[0] << 8);
+}
+
+uint32_t read_be16_2 (struct uint16_st data)
+{
+ return data.u1 | (data.u0 << 8);
+}
+
+uint32_t read_be16_3 (unsigned char *data)
+{
+ return *(data + 1) | (*data << 8);
+}
+
+/* { dg-final { scan-tree-dump-times "16 bit load in host endianness found at" 3 "bswap" } } */
+/* { dg-final { scan-tree-dump-times "16 bit bswap implementation found at" 3 "bswap" { xfail alpha*-*-* arm*-*-* } } } */
+/* { dg-final { cleanup-tree-dump "bswap" } } */
diff --git a/gcc/testsuite/gcc.dg/optimize-bswapsi-1.c b/gcc/testsuite/gcc.dg/optimize-bswapsi-1.c
index 78238e30955..33d0bb0fa77 100644
--- a/gcc/testsuite/gcc.dg/optimize-bswapsi-1.c
+++ b/gcc/testsuite/gcc.dg/optimize-bswapsi-1.c
@@ -1,4 +1,5 @@
-/* { dg-do compile { target arm*-*-* alpha*-*-* i?86-*-* powerpc*-*-* rs6000-*-* x86_64-*-* s390*-*-* } } */
+/* { dg-do compile } */
+/* { dg-require-effective-target bswap32 } */
/* { dg-require-effective-target stdint_types } */
/* { dg-options "-O2 -fdump-tree-bswap" } */
/* { dg-options "-O2 -fdump-tree-bswap -march=z900" { target s390-*-* } } */
diff --git a/gcc/testsuite/gcc.dg/optimize-bswapsi-2.c b/gcc/testsuite/gcc.dg/optimize-bswapsi-2.c
new file mode 100644
index 00000000000..518b5108378
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/optimize-bswapsi-2.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target bswap32 } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-options "-O2 -fdump-tree-bswap" } */
+/* { dg-options "-O2 -fdump-tree-bswap -march=z900" { target s390-*-* } } */
+
+#include <stdint.h>
+
+extern unsigned char data[4];
+
+struct uint32_st {
+ unsigned char u0, u1, u2, u3;
+};
+
+uint32_t read_le32_1 (void)
+{
+ return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+}
+
+uint32_t read_le32_2 (struct uint32_st data)
+{
+ return data.u0 | (data.u1 << 8) | (data.u2 << 16) | (data.u3 << 24);
+}
+
+uint32_t read_le32_3 (unsigned char *data)
+{
+ return *data | (*(data + 1) << 8) | (*(data + 2) << 16)
+ | (*(data + 3) << 24);
+}
+
+uint32_t read_be32_1 (void)
+{
+ return data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
+}
+
+uint32_t read_be32_2 (struct uint32_st data)
+{
+ return data.u3 | (data.u2 << 8) | (data.u1 << 16) | (data.u0 << 24);
+}
+
+uint32_t read_be32_3 (unsigned char *data)
+{
+ return *(data + 3) | (*(data + 2) << 8) | (*(data + 1) << 16)
+ | (*data << 24);
+}
+
+/* { dg-final { scan-tree-dump-times "32 bit load in host endianness found at" 3 "bswap" } } */
+/* { dg-final { scan-tree-dump-times "32 bit bswap implementation found at" 3 "bswap" { xfail alpha*-*-* arm*-*-* } } } */
+/* { dg-final { cleanup-tree-dump "bswap" } } */
diff --git a/gcc/testsuite/gcc.dg/pedwarn-init.c b/gcc/testsuite/gcc.dg/pedwarn-init.c
new file mode 100644
index 00000000000..12611154bee
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pedwarn-init.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wpedantic" } */
+/* { dg-prune-output ".*near initialization for.*" } */
+
+typedef unsigned vec __attribute__ ((vector_size (2 * sizeof (int))));
+union u { int a; double d; };
+struct S { int i; char fam[]; };
+
+int i;
+vec v = { 1, 2, 3 }; /* { dg-warning "17:excess elements in vector initializer" } */
+int a1 = { 1, 2 }; /* { dg-warning "15:excess elements in scalar initializer" } */
+int a2[2] = { 1, 2, 3 }; /* { dg-warning "21:excess elements in array initializer" } */
+int a3[] = { [1 ? 1 : i] = 0 }; /* { dg-warning "15:array index in initializer is not an integer constant expression" } */
+int a4[] = { [1 ... 1 ? 2 : i] = 0 }; /* { dg-warning "15:array index in initializer is not an integer constant expression" } */
+char a5[] = ("lol"); /* { dg-warning "13:array initialized from parenthesized string constant" } */
+char a6[] = { ("foo") }; /* { dg-warning "13:array initialized from parenthesized string constant" } */
+char *a7 = (char []) { ("bar") }; /* { dg-warning "12:array initialized from parenthesized string constant" } */
+union u u = { 1, 1.0 }; /* { dg-warning "18:excess elements in union initializer" } */
+struct S s = { 1, 2 }; /* { dg-warning "14:initialization of a flexible array member" } */
diff --git a/gcc/testsuite/gcc.dg/pr55570.c b/gcc/testsuite/gcc.dg/pr55570.c
index 903bb033df9..5f5555ee47b 100644
--- a/gcc/testsuite/gcc.dg/pr55570.c
+++ b/gcc/testsuite/gcc.dg/pr55570.c
@@ -1,4 +1,4 @@
/* PR c/55570 */
/* { dg-do compile } */
-char array[16] __attribute__((aligned (SOME_NOT_DEFINED_MACRO))); /* { dg-error "requested alignment is not an integer constant" } */
+char array[16] __attribute__((aligned (SOME_NOT_DEFINED_MACRO))); /* { dg-error "undeclared here" } */
diff --git a/gcc/testsuite/gcc.dg/pr56724-1.c b/gcc/testsuite/gcc.dg/pr56724-1.c
new file mode 100644
index 00000000000..4276c3f154b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr56724-1.c
@@ -0,0 +1,33 @@
+/* PR c/56724 */
+/* { dg-do compile } */
+/* { dg-options "-Wtraditional-conversion" } */
+
+extern void foo (int p[2][]); /* { dg-error "array type has incomplete element type" } */
+extern void foo_i (int, int);
+extern void foo_u (unsigned int);
+extern void foo_f (int, float);
+extern void foo_ll (long long);
+extern void foo_cd (int, int, __complex__ double);
+extern signed char sc;
+extern int i;
+extern unsigned int u;
+extern float f;
+extern double d;
+extern __complex__ double cd;
+
+void
+fn ()
+{
+ int p[1][1];
+ foo (p); /* { dg-error "8:type of formal parameter" } */
+ foo_i (1, f); /* { dg-warning "13:passing argument" } */
+ foo_i (1, cd); /* { dg-warning "13:passing argument" } */
+ foo_cd (1, 2, f); /* { dg-warning "17:passing argument" } */
+ foo_f (9, i); /* { dg-warning "13:passing argument" } */
+ foo_cd (2, 2, i); /* { dg-warning "17:passing argument" } */
+ foo_f (2, cd); /* { dg-warning "13:passing argument" } */
+ foo_f (2, d); /* { dg-warning "13:passing argument" } */
+ foo_ll (sc); /* { dg-warning "11:passing argument" } */
+ foo_u (i); /* { dg-warning "10:passing argument" } */
+ foo_i (1, u); /* { dg-warning "13:passing argument" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr56724-2.c b/gcc/testsuite/gcc.dg/pr56724-2.c
new file mode 100644
index 00000000000..4abb7d899e7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr56724-2.c
@@ -0,0 +1,31 @@
+/* PR c/56724 */
+/* { dg-do compile } */
+/* { dg-options "-Wc++-compat -Wpedantic" } */
+
+enum E1 { A };
+enum E2 { B };
+extern void foo_E (enum E1);
+extern void foo_v (void *p);
+extern void foo_sc (int, int, signed char *);
+extern unsigned char *uc;
+extern signed char sc;
+extern const signed char *csc;
+extern float *f;
+
+void
+foo (void)
+{
+ void (*fp)(void);
+ const void (*ffp)(void);
+ foo_v (fp); /* { dg-warning "10:ISO C forbids passing argument" } */
+ foo_E (B); /* { dg-warning "10:enum conversion when passing argument" } */
+ foo_sc (1, 2, uc); /* { dg-warning "17:pointer targets in passing argument" } */
+ foo_sc (1, 2, f); /* { dg-warning "17:passing argument" } */
+ foo_sc (1, 2, sc); /* { dg-warning "17:passing argument" } */
+ foo_sc (uc, 2, &sc); /* { dg-warning "11:passing argument" } */
+ foo_sc (1, 2, csc); /* { dg-warning "17:passing argument" } */
+}
+
+typedef void (*fp)(void);
+typedef void (*nrfp)(void) __attribute__((noreturn));
+void f1 (nrfp); void f2 (fp x) { f1 (x); } extern int e; /* { dg-warning "38:passing argument" } */
diff --git a/gcc/testsuite/gcc.dg/pr60866.c b/gcc/testsuite/gcc.dg/pr60866.c
new file mode 100644
index 00000000000..020878d41de
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr60866.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target powerpc*-*-* ia64-*-* x86_64-*-* } } */
+/* { dg-options "-O -fselective-scheduling -fno-if-conversion -fschedule-insns" } */
+
+int n;
+
+void
+foo (int w, int **dnroot, int **dn)
+{
+ int *child;
+ int *xchild = xchild;
+ for (; w < n; w++)
+ if (!dnroot)
+ {
+ dnroot = dn;
+ for (child = *dn; child; child = xchild)
+ ;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr61045.c b/gcc/testsuite/gcc.dg/pr61045.c
new file mode 100644
index 00000000000..1808cdc259f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr61045.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-fstrict-overflow" } */
+
+int main ()
+{
+ int a = 0;
+ int b = __INT_MAX__;
+ int t = (a - 2) > (b - 1);
+ if (t != 0)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr61053.c b/gcc/testsuite/gcc.dg/pr61053.c
new file mode 100644
index 00000000000..4fd531974f7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr61053.c
@@ -0,0 +1,75 @@
+/* PR c/61053 */
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+_Alignas (char) char cc;
+_Alignas (short int) char cs;
+_Alignas (int) char ci;
+_Alignas (long int) char cl;
+_Alignas (long long int) char cll;
+_Alignas (float) char cf;
+_Alignas (double) char cd;
+_Alignas (long double) char cld;
+
+_Alignas (char) short int sc; /* { dg-error "cannot reduce alignment" } */
+_Alignas (short int) short int ss;
+_Alignas (int) short int si;
+_Alignas (long int) short int sl;
+_Alignas (long long int) short int sll;
+_Alignas (float) short int sf;
+_Alignas (double) short int sd;
+_Alignas (long double) short int sld;
+
+_Alignas (char) int ic; /* { dg-error "cannot reduce alignment" } */
+_Alignas (short int) int is; /* { dg-error "cannot reduce alignment" } */
+_Alignas (int) int ii;
+_Alignas (long int) int il;
+_Alignas (long long int) int ill;
+_Alignas (float) int if_;
+_Alignas (double) int id;
+_Alignas (long double) int ild;
+
+_Alignas (char) long int lic; /* { dg-error "cannot reduce alignment" } */
+_Alignas (short int) long int lis; /* { dg-error "cannot reduce alignment" } */
+_Alignas (int) long int lii; /* { dg-error "cannot reduce alignment" "" { target { ! { ia32 } } } } */
+_Alignas (long int) long int lil;
+_Alignas (long long int) long int lill;
+_Alignas (float) long int lif; /* { dg-error "cannot reduce alignment" "" { target { ! { ia32 } } } } */
+_Alignas (double) long int lid;
+_Alignas (long double) long int lild;
+
+_Alignas (char) long long int llic; /* { dg-error "cannot reduce alignment" } */
+_Alignas (short int) long long int llis; /* { dg-error "cannot reduce alignment" } */
+_Alignas (int) long long int llii; /* { dg-error "cannot reduce alignment" "" { target { ! { ia32 } } } } */
+_Alignas (long int) long long int llil;
+_Alignas (long long int) long long int llill;
+_Alignas (float) long long int llif; /* { dg-error "cannot reduce alignment" "" { target { ! { ia32 } } } } */
+_Alignas (double) long long int llid;
+_Alignas (long double) long long int llild;
+
+_Alignas (char) float fc; /* { dg-error "cannot reduce alignment" } */
+_Alignas (short int) float fs; /* { dg-error "cannot reduce alignment" } */
+_Alignas (int) float fi;
+_Alignas (long int) float fl;
+_Alignas (long long int) float fll;
+_Alignas (float) float ff;
+_Alignas (double) float fd;
+_Alignas (long double) float fld;
+
+_Alignas (char) double dc; /* { dg-error "cannot reduce alignment" } */
+_Alignas (short int) double ds; /* { dg-error "cannot reduce alignment" } */
+_Alignas (int) double di; /* { dg-error "cannot reduce alignment" "" { target { ! { ia32 } } } } */
+_Alignas (long int) double dl;
+_Alignas (long long int) double dll;
+_Alignas (float) double df; /* { dg-error "cannot reduce alignment" "" { target { ! { ia32 } } } } */
+_Alignas (double) double dd;
+_Alignas (long double) double dld;
+
+_Alignas (char) long double ldc; /* { dg-error "cannot reduce alignment" } */
+_Alignas (short int) long double lds; /* { dg-error "cannot reduce alignment" } */
+_Alignas (int) long double ldi; /* { dg-error "cannot reduce alignment" "" { target { ! { ia32 } } } } */
+_Alignas (long int) long double ldl; /* { dg-error "cannot reduce alignment" "" { target { ! { ia32 } } } } */
+_Alignas (long long int) long double ldll; /* { dg-error "cannot reduce alignment" "" { target { ! { ia32 } } } } */
+_Alignas (float) long double ldf; /* { dg-error "cannot reduce alignment" "" { target { ! { ia32 } } } } */
+_Alignas (double) long double ldd; /* { dg-error "cannot reduce alignment" "" { target { ! { ia32 } } } } */
+_Alignas (long double) long double ldld;
diff --git a/gcc/testsuite/gcc.dg/pr61060.c b/gcc/testsuite/gcc.dg/pr61060.c
new file mode 100644
index 00000000000..d2a13650765
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr61060.c
@@ -0,0 +1,19 @@
+/* PR target/61060 */
+/* { dg-do compile } */
+/* { dg-options "-O0 -ftree-ter" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern inline __attribute__ ((gnu_inline, always_inline, artificial))
+void *memset (void *dest, int ch, size_t len)
+{
+ return __builtin_memset (dest, ch, len);
+}
+
+char buf[10];
+
+void
+foo (void)
+{
+ memset (buf, sizeof (buf), 0);
+}
diff --git a/gcc/testsuite/gcc.dg/pr61077.c b/gcc/testsuite/gcc.dg/pr61077.c
new file mode 100644
index 00000000000..c0513f71f70
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr61077.c
@@ -0,0 +1,12 @@
+/* PR c/61077 */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -Wall" } */
+
+_Atomic int
+main (_Atomic int argc, _Atomic char **argv)
+/* { dg-warning "qualified return type" "return" { target *-*-* } 6 } */
+/* { dg-warning "qualified parameter type.*int" "parameter" { target *-*-* } 6 } */
+/* { dg-warning "qualified parameter type.*char" "parameter" { target *-*-* } 6 } */
+{
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr61096-1.c b/gcc/testsuite/gcc.dg/pr61096-1.c
new file mode 100644
index 00000000000..3f7d60c0e5d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr61096-1.c
@@ -0,0 +1,61 @@
+/* PR c/61077 */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -fshort-enums -fshort-wchar -Wpedantic" } */
+/* { dg-prune-output ".*near initialization for.*" } */
+
+typedef enum { A } schar;
+extern int e;
+struct S
+{
+ int a[3];
+};
+struct f
+{
+ int w;
+ int x[];
+};
+struct g
+{
+ struct f f; /* { dg-warning "invalid use of structure with flexible array member" } */
+};
+
+char w1[] = L"foo"; /* { dg-error "13:char-array initialized from wide string" } */
+__WCHAR_TYPE__ w2[] = "foo"; /* { dg-error "23:wide character array initialized from non-wide string" } */
+__WCHAR_TYPE__ w3[] = U"foo"; /* { dg-error "23:wide character array initialized from incompatible wide string" } */
+schar a1[] = "foo"; /* { dg-error "14:array of inappropriate type initialized from string constant" } */
+int a2[] = (int[]) { 1 }; /* { dg-error "12:array initialized from non-constant array expression" } */
+
+int a3 = e; /* { dg-error "10:initializer element is not constant" } */
+int a4 = (e, 1); /* { dg-error "10:initializer element is not constant" } */
+int a5 = a1[0]; /* { dg-error "10:initializer element is not constant" } */
+int a6 = &a3 - &a4; /* { dg-error "10:initializer element is not" } */
+int a7[] = a7; /* { dg-error "12:invalid initializer" } */
+
+struct S s = { { 1 }, { 3 } }; /* { dg-error "23:extra brace group at end of initializer" } */
+/* { dg-warning "23:excess elements in struct initializer" "" { target *-*-* } 34 } */
+struct g g1 = { {0, { 1 } } }; /* { dg-error "21:initialization of flexible array member in a nested context" } */
+struct g g2 = { .f[0] = 1 }; /* { dg-error "20:array index in non-array initializer" } */
+
+__extension__ int a8 = { }; /* { dg-error "24:empty scalar initializer" } */
+int a9[10] = {[1.2] = 2 }; /* { dg-error "16:array index in initializer not of integer type" } */
+int a10[10] = {[e] = 2 }; /* { dg-error "17:nonconstant array index in initializer" } */
+__extension__ int a11[10] = {[1 ... e] = 1 }; /* { dg-error "31:nonconstant array index in initializer" } */
+int a12 = {[1] = 2 }; /* { dg-error "13:array index in non-array initializer" } */
+int a13[2] = {[-1] = 4 }; /* { dg-error "16:array index in initializer exceeds array bounds" } */
+int a14[2] = {[64] = 4 }; /* { dg-error "16:array index in initializer exceeds array bounds" } */
+__extension__ int a15[10] = {[2 ... 1] = 4 }; /* { dg-error "31:empty index range in initializer" } */
+__extension__ int a16[10] = {[2 ... 100] = 4 }; /* { dg-error "31:array index range in initializer exceeds array bounds" } */
+int a17[] = { .B = 1 }; /* { dg-error "15:field name not in record or union initializer" } */
+int a18[] = { e }; /* { dg-error "15:initializer element is not constant" } */
+char a19[1] = { "x", "x" }; /* { dg-error "22:excess elements in char array initializer" } */
+
+void
+bar (void)
+{
+ struct f f = { 2, "c" }; /* { dg-error "21:non-static initialization of a flexible array member" } */
+}
+
+struct
+{
+ char *v;
+} sx[] = { .v = 0 }; /* { dg-error "12:field name not in record or union initializer" } */
diff --git a/gcc/testsuite/gcc.dg/pr61096-2.c b/gcc/testsuite/gcc.dg/pr61096-2.c
new file mode 100644
index 00000000000..fbea4d9db6b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr61096-2.c
@@ -0,0 +1,10 @@
+/* PR c/61077 */
+/* { dg-do compile } */
+
+struct s { char c[1]; };
+extern struct s foo (void);
+void
+bar (void)
+{
+ char *t = (foo ()).c; /* { dg-error "13:invalid use of non-lvalue array" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr61158.c b/gcc/testsuite/gcc.dg/pr61158.c
new file mode 100644
index 00000000000..d0ba7f3876b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr61158.c
@@ -0,0 +1,12 @@
+/* PR tree-optimization/61158 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-original" } */
+
+unsigned long long
+foo (unsigned int x)
+{
+ return ((unsigned long long) x & 0x00ff000000000000ULL) >> 40;
+}
+
+/* { dg-final { scan-tree-dump "return 0;" "original" { target { ilp32 || lp64 } } } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
diff --git a/gcc/testsuite/gcc.dg/pr61162.c b/gcc/testsuite/gcc.dg/pr61162.c
new file mode 100644
index 00000000000..00e64b9d758
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr61162.c
@@ -0,0 +1,12 @@
+/* PR c/61162 */
+/* { dg-do compile } */
+/* { dg-options "-Wc++-compat" } */
+
+enum e { A };
+enum e
+fn1 (void)
+{
+ enum e e, q = 0; /* { dg-warning "17:enum conversion in initialization is invalid" } */
+ e = 0; /* { dg-warning "5:enum conversion in assignment is invalid" } */
+ 1; return 0; /* { dg-warning "6:enum conversion in return is invalid" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr61220.c b/gcc/testsuite/gcc.dg/pr61220.c
new file mode 100644
index 00000000000..d45d1c3c9f1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr61220.c
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -g" } */
+
+int a, c, d, e, f, g, h, i, j, k;
+
+struct S0
+{
+ int f0;
+ int f1;
+ int f2;
+};
+
+struct S1
+{
+ int f0;
+ int f1;
+ struct S0 f2;
+} b;
+
+void
+fn1 (struct S1 p)
+{
+ for (; k; k++)
+ h = j ? a : a - 1;
+ d &= i;
+}
+
+int
+main ()
+{
+ int l[5] = { 0 };
+ fn1 (b);
+ for (c = 0; c < 3; c++)
+ for (g = 0; g < 3; g++)
+ l[c * 2] = e = l[c];
+ if (f)
+ fn1 (b);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/shrink-wrap-loop.c b/gcc/testsuite/gcc.dg/shrink-wrap-loop.c
new file mode 100644
index 00000000000..e72edfa6c44
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/shrink-wrap-loop.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { { x86_64-*-* && lp64 } || { arm_thumb2 } } } } */
+/* { dg-options "-O2 -fdump-rtl-pro_and_epilogue" } */
+
+int foo (int *p1, int *p2);
+
+int
+test (int *p1, int *p2)
+{
+ int *p;
+
+ for (p = p2; p != 0; p++)
+ {
+ if (!foo (p, p1))
+ return 0;
+ }
+
+ return 1;
+}
+/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" } } */
+/* { dg-final { cleanup-rtl-dump "pro_and_epilogue" } } */
diff --git a/gcc/testsuite/gcc.dg/sibcall-3.c b/gcc/testsuite/gcc.dg/sibcall-3.c
index e02a410e6d9..eafe8dd8456 100644
--- a/gcc/testsuite/gcc.dg/sibcall-3.c
+++ b/gcc/testsuite/gcc.dg/sibcall-3.c
@@ -5,7 +5,7 @@
Copyright (C) 2002 Free Software Foundation Inc.
Contributed by Hans-Peter Nilsson <hp@bitrange.com> */
-/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* nds32*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */
+/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* msp430*-*-* nds32*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */
/* -mlongcall disables sibcall patterns. */
/* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */
/* { dg-options "-O2 -foptimize-sibling-calls" } */
diff --git a/gcc/testsuite/gcc.dg/sibcall-4.c b/gcc/testsuite/gcc.dg/sibcall-4.c
index a66ed079862..1e039c66854 100644
--- a/gcc/testsuite/gcc.dg/sibcall-4.c
+++ b/gcc/testsuite/gcc.dg/sibcall-4.c
@@ -5,7 +5,7 @@
Copyright (C) 2002 Free Software Foundation Inc.
Contributed by Hans-Peter Nilsson <hp@bitrange.com> */
-/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* nds32*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */
+/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* msp430*-*-* nds32*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */
/* -mlongcall disables sibcall patterns. */
/* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */
/* { dg-options "-O2 -foptimize-sibling-calls" } */
diff --git a/gcc/testsuite/gcc.dg/tm/wrap-2.c b/gcc/testsuite/gcc.dg/tm/wrap-2.c
index 29486335a44..372d666be7f 100644
--- a/gcc/testsuite/gcc.dg/tm/wrap-2.c
+++ b/gcc/testsuite/gcc.dg/tm/wrap-2.c
@@ -10,7 +10,7 @@ int f7(void);
void g1(void) W(f1);
void g2(void) W(f2); /* { dg-error "is not compatible" } */
void g3(void) W(i3); /* { dg-error "is not a function" } */
-void g4(void) W(f4); /* { dg-error "is not a function" } */
+void g4(void) W(f4); /* { dg-error "undeclared" } */
void g5(void) W(1); /* { dg-error "not an identifier" } */
void g6(void) W("f1"); /* { dg-error "not an identifier" } */
void g7(void) W(f7); /* { dg-error "is not compatible" } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr61095.c b/gcc/testsuite/gcc.dg/torture/pr61095.c
new file mode 100644
index 00000000000..fa584e0353d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr61095.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-require-effective-target lp64 } */
+
+extern void __attribute__ ((noreturn)) abort (void);
+
+int __attribute__ ((noinline, noclone))
+foo (unsigned long addr) {
+ unsigned long *p = (unsigned long*)((addr & 0xffff83fffffffff8UL) * 4);
+ unsigned long xxx = (unsigned long)(p + 1);
+ return xxx >= 0x3c000000000UL;
+}
+
+int
+main (void)
+{
+ if (foo (0))
+ abort ();
+ if (foo (0x7c0000000000UL))
+ abort ();
+ if (!foo (0xfc0000000000UL))
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr61136.c b/gcc/testsuite/gcc.dg/torture/pr61136.c
new file mode 100644
index 00000000000..4fc908a25c9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr61136.c
@@ -0,0 +1,5 @@
+unsigned long long
+foo (int a)
+{
+ return a * 7 & 1ULL << 63;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr61221.c b/gcc/testsuite/gcc.dg/torture/pr61221.c
new file mode 100644
index 00000000000..2524382ba1a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr61221.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+
+void __assert_fail (void);
+
+int **a, b, c, e, *j;
+short *d, **f;
+
+int *
+foo ()
+{
+ *a = j;
+ if (!(1 & e))
+ __assert_fail ();
+ return 0;
+}
+
+void
+bar ()
+{
+ int *g = &b;
+ short **h = &d;
+ if ((f = &d) != h)
+ for (; b;)
+ {
+ int i = 1;
+ if (i)
+ g = foo ();
+ c = 0;
+ }
+ if (!g)
+ __assert_fail ();
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr61346.c b/gcc/testsuite/gcc.dg/torture/pr61346.c
new file mode 100644
index 00000000000..e27b9cac5b3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr61346.c
@@ -0,0 +1,162 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+typedef int int32_t __attribute__ ((mode (SI)));
+typedef int int64_t __attribute__ ((mode (DI)));
+typedef __SIZE_TYPE__ size_t;
+
+struct slice
+{
+ unsigned char *data;
+ int64_t len;
+ int64_t cap;
+};
+
+void fail (int32_t) __attribute__ ((noinline));
+void
+fail (int32_t c)
+{
+ if (c != 0)
+ abort ();
+}
+
+struct decode_rune_ret
+{
+ int32_t r;
+ int64_t width;
+};
+
+struct decode_rune_ret decode_rune (struct slice) __attribute__ ((noinline));
+struct decode_rune_ret
+decode_rune (struct slice s)
+{
+ struct decode_rune_ret dr;
+ dr.r = s.data[0];
+ dr.width = 1;
+ return dr;
+}
+
+_Bool is_space (int32_t) __attribute__ ((noinline));
+_Bool
+is_space (int32_t r)
+{
+ return r == ' ';
+}
+
+struct ret
+{
+ int64_t advance;
+ struct slice token;
+};
+
+struct ret scanwords (struct slice, _Bool) __attribute__ ((noinline));
+
+struct ret
+scanwords (struct slice data, _Bool ateof)
+{
+ int64_t advance;
+ struct slice token;
+ int64_t start = 0;
+ {
+ int64_t width;
+ for (width = 0; start < data.len; start += width)
+ {
+ int32_t r = 0;
+ struct slice s;
+ if (start > data.cap || start < 0)
+ fail (3);
+ s.data = data.data + (size_t) start;
+ s.len = data.len - start;
+ s.cap = data.cap - start;
+ struct decode_rune_ret dr = decode_rune (s);
+ r = dr.r;
+ width = dr.width;
+ if (!is_space (r))
+ break;
+ }
+ }
+ _Bool tmp = ateof;
+ if (tmp != 0)
+ goto L1;
+ else
+ goto L2;
+ L1:
+ tmp = data.len == 0;
+ L2:
+ if (tmp != 0)
+ goto L11;
+ else
+ goto L12;
+ L11:
+ {
+ struct ret r;
+ advance = 0;
+ token.data = 0;
+ token.len = 0;
+ token.cap = 0;
+ r.advance = advance;
+ r.token = token;
+ return r;
+ }
+ L12:;
+ int64_t width;
+ int64_t i;
+ for (width = 0, i = start; i < data.len; i += width)
+ {
+ int32_t r;
+ struct slice s;
+ if (i > data.cap || i < 0)
+ fail (3);
+ s.data = data.data + i;
+ s.len = data.len - i;
+ s.cap = data.cap - i;
+ struct decode_rune_ret dr = decode_rune (s);
+ r = dr.r;
+ width = dr.width;
+ if (is_space (r))
+ {
+ if (i < start || i > data.cap || i < 0)
+ fail (3);
+ if (start > data.cap || start < 0)
+ fail (3);
+ struct ret r;
+ advance = i + width;
+ token.data = data.data + (size_t) start;
+ token.len = i - start;
+ token.cap = data.cap - start;
+ r.advance = advance;
+ r.token = token;
+ return r;
+ }
+ }
+ {
+ struct ret r;
+ advance = 0;
+ token.data = 0;
+ token.len = 0;
+ token.cap = 0;
+ r.advance = advance;
+ r.token = token;
+ return r;
+ }
+}
+
+int
+main ()
+{
+ unsigned char buf[1000];
+ struct slice s;
+ __builtin_memset (buf, 0, sizeof (buf));
+ buf[0] = ' ';
+ buf[1] = 'a';
+ buf[2] = ' ';
+ s.data = buf;
+ s.len = 3;
+ s.cap = sizeof (buf);
+ struct ret r;
+ r = scanwords (s, 1);
+ if (r.advance != 3 || r.token.data[0] != 'a' || r.token.len != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-33.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-33.c
new file mode 100644
index 00000000000..cbc0812a238
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-33.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-O -fdump-tree-fre1-details" } */
+
+int j;
+int main ()
+{
+ int i = 1;
+ int **p;
+ j = 0;
+ p = __builtin_malloc (sizeof (int *));
+ *p = &i;
+ p = __builtin_realloc (p, 2 * sizeof (int *));
+ **p = 0;
+ if (i != 0)
+ __builtin_abort ();
+ return j;
+}
+
+/* { dg-final { scan-tree-dump "Replaced j with 0" "fre1" } } */
+/* { dg-final { cleanup-tree-dump "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lower_base.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lower_base.c
new file mode 100644
index 00000000000..3b2b81f46a4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lower_base.c
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ivopts-details" } */
+#include <string.h>
+#include <stdlib.h>
+
+#define MAX_NUM (256)
+
+void
+sort_pointers (size_t n, void **pointers, void **work)
+{
+ typedef unsigned char digit_t;
+ unsigned int count[MAX_NUM];
+ int big_endian_p;
+ size_t i;
+ size_t j;
+
+ if ((sizeof (void *) / sizeof (digit_t)) % 2 != 0)
+ abort ();
+
+ for (i = 0, j = 0; i < sizeof (size_t); ++i)
+ {
+ j *= MAX_NUM;
+ j += i;
+ }
+
+ big_endian_p = (((char *)&j)[0] == 0);
+ for (i = 0; i < sizeof (void *) / sizeof (digit_t); ++i)
+ {
+ digit_t *digit;
+ digit_t *bias;
+ digit_t *top;
+ unsigned int *countp;
+ void **pointerp;
+
+ if (big_endian_p)
+ j = sizeof (void *) / sizeof (digit_t) - i;
+ else
+ j = i;
+
+ memset (count, 0, MAX_NUM * sizeof (unsigned int));
+ bias = ((digit_t *) pointers) + j;
+ top = ((digit_t *) (pointers + n)) + j;
+ for (digit = bias;
+ digit < top;
+ digit += sizeof (void *) / sizeof (digit_t))
+ ++count[*digit];
+
+ for (countp = count + 1; countp < count + MAX_NUM; ++countp)
+ *countp += countp[-1];
+
+ for (pointerp = pointers + n - 1; pointerp >= pointers; --pointerp)
+ work[--count[((digit_t *) pointerp)[j]]] = *pointerp;
+
+ pointerp = pointers;
+ pointers = work;
+ work = pointerp;
+ }
+}
+
+/* { dg-final { scan-tree-dump-not "base \[^\\n\]*&MEM\\\[" "ivopts" } } */
+/* { dg-final { cleanup-tree-dump "ivopts" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-12.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-12.c
new file mode 100644
index 00000000000..b52c6d711a7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-12.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-phiopt1" } */
+
+int f(int a, int b, int c) {
+ if (c > 5) return c;
+ if (a == 0) return b;
+ return a + b;
+}
+
+unsigned rot(unsigned x, int n) {
+ const int bits = __CHAR_BIT__ * __SIZEOF_INT__;
+ return (n == 0) ? x : ((x << n) | (x >> (bits - n)));
+}
+
+unsigned m(unsigned a, unsigned b) {
+ if (a == 0)
+ return 0;
+ else
+ return a & b;
+}
+
+/* { dg-final { scan-tree-dump-times "goto" 2 "phiopt1" } } */
+/* { dg-final { cleanup-tree-dump "phiopt1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-13.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-13.c
new file mode 100644
index 00000000000..3e09c218890
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-13.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+// Division is expensive
+long f(long a, long b) {
+ if (__builtin_expect(b == 1, 1)) return a;
+ return a / b;
+}
+
+/* { dg-final { scan-tree-dump-times "goto " 2 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c
index 6378d1aa729..a991e049035 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c
@@ -9,6 +9,7 @@ void foo (void)
{
int toread;
int bytes;
+ __attribute__ ((used))
static char eof_reached = 0;
toread = blocksize;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c
index 3940692cd6c..1d30ac7519f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c
@@ -19,6 +19,6 @@ int ffff(int i)
/* We should not use extra temporaries apart from for i1 + i2. */
-/* { dg-final { scan-tree-dump-times "int" 6 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "int" 5 "gimple" } } */
/* { dg-final { scan-tree-dump-times "int D\\\." 1 "gimple" } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c b/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c
index 6d0904bb06b..c7da3bd5d06 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c
@@ -13,6 +13,6 @@ int qqq (int a)
/* We should not use an extra temporary for the result of the
function call. */
-/* { dg-final { scan-tree-dump-times "int" 4 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "int" 3 "gimple" } } */
/* { dg-final { scan-tree-dump-times "int D\\\." 1 "gimple" } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61090.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61090.c
new file mode 100644
index 00000000000..fff289572ac
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61090.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+struct i {
+ int c;
+};
+
+static int
+p(struct i a)
+{
+ return 0;
+}
+
+void
+h(void)
+{
+ struct i z[] = {{ 0 }};
+ int e[] = {};
+ int x;
+ e[0] = p(z[x]) + z[x].c;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61140.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61140.c
new file mode 100644
index 00000000000..2f175cb7e2d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61140.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+int a[1] = { 1 }, b = 1, c;
+
+int
+main ()
+{
+ for (; c < 1; c++)
+ if (a[0])
+ {
+ a[0] &= 1;
+ b = 0;
+ }
+ if (b)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61150.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61150.c
new file mode 100644
index 00000000000..c11798cace4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61150.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+int a, b, c, d = 1;
+
+int
+main ()
+{
+ int e = d;
+ for (b = 0; b < 5; b++)
+ {
+ for (a = 0; a < 1; a++)
+ {
+ if (e)
+ break;
+ for (c = 0; c < 1; c++)
+ ;
+ }
+ e |= 1;
+ }
+ if (c)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61197.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61197.c
new file mode 100644
index 00000000000..919578b7ff7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61197.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+int a, b = 1, *c = &a;
+
+int
+foo ()
+{
+ if (b)
+ b |= 1;
+ else
+ {
+ b = 1;
+ return 0;
+ }
+ return 1;
+}
+
+int
+main ()
+{
+ *c = foo ();
+ if (a != 1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-6.c
index 3d020067ca7..cf496291f8d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-6.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-6.c
@@ -3,6 +3,7 @@
int foo11 (int c)
{
+ __attribute__ ((used))
static int local1, local2;
local1 = 0;
local2 += c;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-39.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-39.c
new file mode 100644
index 00000000000..a30926caccd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-39.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1" } */
+
+int foo (int i)
+{
+ int k = i + 1;
+ int j = i + 1;
+ if (k != j)
+ k = k + 1;
+ if (k != j)
+ k = k + 1;
+ k = k - i;
+ return k;
+}
+
+/* We should be able to value-number the final assignment to k to 1. */
+
+/* { dg-final { scan-tree-dump "k_. = 1;" "fre1" } } */
+/* { dg-final { cleanup-tree-dump "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-40.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-40.c
new file mode 100644
index 00000000000..577f9fe8e5e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-40.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1" } */
+
+int x;
+int foo (int *p)
+{
+ x = 0;
+ if (x)
+ *p = 1;
+ return x;
+}
+
+/* The final load of x should be replaced as well as the
+ aliasing store via *p is not reachable. */
+
+/* { dg-final { scan-tree-dump-not "= x;" "fre1" } } */
+/* { dg-final { cleanup-tree-dump "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-41.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-41.c
new file mode 100644
index 00000000000..82ca746e173
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-41.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1" } */
+
+int x;
+int foo (void)
+{
+ x = 1;
+ return __builtin_ffs (x);
+}
+
+/* { dg-final { scan-tree-dump-not "ffs" "fre1" } } */
+/* { dg-final { cleanup-tree-dump "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c
index f08ef7fde60..dab57fa391b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c
@@ -17,7 +17,9 @@ foo (__SIZE_TYPE__ i, struct s *array)
return 0;
}
/* We should eliminate two address calculations, and one load. */
+/* We also elimiate the PHI node feeding the return because the case
+ returning 1 is unreachable. */
/* We used to eliminate a cast but that was before POINTER_PLUS_EXPR
was added. */
-/* { dg-final { scan-tree-dump-times "Eliminated: 3" 1 "fre1"} } */
+/* { dg-final { scan-tree-dump-times "Eliminated: 4" 1 "fre1"} } */
/* { dg-final { cleanup-tree-dump "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-2.c b/gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-2.c
index c348bdfe25b..66a5442a9ef 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-fre1" } */
+/* { dg-options "-O2 -fdump-tree-cddce1" } */
struct S { unsigned f; };
@@ -12,8 +12,8 @@ foo ( struct S *p)
}
-/* There should only be one load of p->f because fwprop can change
- *(int *)&p->f into just (int)p->f. */
-/* { dg-final { scan-tree-dump-times "= \[^\n\]*p_.\\\(D\\\)" 1 "fre1" } } */
-/* { dg-final { cleanup-tree-dump "fre1" } } */
+/* There should only be one load of p->f because FRE removes the redundancy
+ by realizing it can cast the result of either to the other. */
+/* { dg-final { scan-tree-dump-times "= \[^\n\]*p_.\\\(D\\\)" 1 "cddce1" } } */
+/* { dg-final { cleanup-tree-dump "cddce1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c
new file mode 100644
index 00000000000..a84ba8e2903
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
+
+void bar (void);
+int foo (int i, int j)
+{
+ int res = 1;
+ if (i < j)
+ {
+ /* We should be able to simplify the following conditional
+ during propagation. */
+ if (i > j)
+ res = 0;
+ }
+ /* And compute res as having a value-range of [1,1]. */
+ if (res)
+ return i;
+ return j;
+}
+
+/* { dg-final { scan-tree-dump "res_.: \\\[1, 1\\\]" "vrp1" } } */
+/* { dg-final { scan-tree-dump-not "Threaded" "vrp1" } } */
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/writeonly.c b/gcc/testsuite/gcc.dg/tree-ssa/writeonly.c
new file mode 100644
index 00000000000..156cf3ef6a8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/writeonly.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+static struct a {int magic1,b;} a;
+volatile int magic2;
+static struct b {int a,b,c,d,e,f;} magic3;
+
+struct b foo();
+
+t()
+{
+ a.magic1 = 1;
+ magic2 = 1;
+ magic3 = foo();
+}
+/* { dg-final { scan-tree-dump-not "magic1" "optimized"} } */
+/* { dg-final { scan-tree-dump-not "magic3" "optimized"} } */
+/* { dg-final { scan-tree-dump "magic2" "optimized"} } */
+/* { dg-final { scan-tree-dump "foo" "optimized"} } */
+
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-bf.c b/gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-bf.c
new file mode 100644
index 00000000000..298d0d91849
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-bf.c
@@ -0,0 +1,72 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=float-cast-overflow" } */
+
+struct
+{
+ int i:1;
+} s;
+
+struct
+{
+ unsigned int i:1;
+} t;
+
+int
+main (void)
+{
+ volatile double d;
+
+#define CHECK_BOUNDARY(VAR, VAL) \
+ (VAR) = (VAL) - 1.5; \
+ (VAR) = (VAL) - 1.0; \
+ (VAR) = (VAL) - 0.5; \
+ (VAR) = (VAL) - 0.0000001; \
+ (VAR) = (VAL) - 0.0; \
+ (VAR) = (VAL); \
+ (VAR) = (VAL) + 0.0; \
+ (VAR) = (VAL) + 0.0000001; \
+ (VAR) = (VAL) + 0.5; \
+ (VAR) = (VAL) + 1.0; \
+ (VAR) = (VAL) + 1.5;
+
+ /* Signed bit-field. (-1, 0) is valid. */
+ d = -1.0;
+ CHECK_BOUNDARY (s.i, d);
+ d = 0.0;
+ CHECK_BOUNDARY (s.i, d);
+ d = 1.0;
+ CHECK_BOUNDARY (s.i, d);
+
+ /* Unsigned bit-field. (0, 1) is valid. */
+ d = -1.0;
+ CHECK_BOUNDARY (t.i, d);
+ d = 0.0;
+ CHECK_BOUNDARY (t.i, d);
+ d = 1.0;
+ CHECK_BOUNDARY (t.i, d);
+
+ return 0;
+}
+
+/* { dg-output "value -2.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -2 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 2 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 2.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -2.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -2 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 2 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*value 2.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/gcc.dg/uninit-13.c b/gcc/testsuite/gcc.dg/uninit-13.c
index 631e8de3ada..5e88a8a9454 100644
--- a/gcc/testsuite/gcc.dg/uninit-13.c
+++ b/gcc/testsuite/gcc.dg/uninit-13.c
@@ -5,6 +5,6 @@ typedef _Complex float C;
C foo()
{
C f;
- __imag__ f = 0; /* { dg-warning "is used" "unconditional" } */
- return f;
+ __imag__ f = 0;
+ return f; /* { dg-warning "is used" "unconditional" } */
}
diff --git a/gcc/testsuite/gcc.dg/uninit-17-O0.c b/gcc/testsuite/gcc.dg/uninit-17-O0.c
new file mode 100644
index 00000000000..0eaef053367
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-17-O0.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized" } */
+
+typedef _Complex float C;
+C foo(int cond)
+{
+ C f;
+ __imag__ f = 0;
+ if (cond)
+ {
+ __real__ f = 1;
+ return f;
+ }
+ return f;
+}
diff --git a/gcc/testsuite/gcc.dg/uninit-17.c b/gcc/testsuite/gcc.dg/uninit-17.c
new file mode 100644
index 00000000000..8a95f15c5ae
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-17.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized" } */
+
+typedef _Complex float C;
+C foo(int cond)
+{
+ C f;
+ __imag__ f = 0;
+ if (cond)
+ {
+ __real__ f = 1;
+ return f;
+ }
+ return f; /* { dg-warning "may be used" "unconditional" } */
+}
diff --git a/gcc/testsuite/gcc.dg/unused-8a.c b/gcc/testsuite/gcc.dg/unused-8a.c
new file mode 100644
index 00000000000..b9b56905156
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/unused-8a.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -Wextra -Wno-unused" } */
+
+void foo(int x) { }
diff --git a/gcc/testsuite/gcc.dg/unused-8b.c b/gcc/testsuite/gcc.dg/unused-8b.c
new file mode 100644
index 00000000000..5b4b894937c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/unused-8b.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -Wno-unused -Wextra" } */
+
+void foo(int x) { }
diff --git a/gcc/testsuite/gcc.dg/vect/pr52252-ld.c b/gcc/testsuite/gcc.dg/vect/pr52252-ld.c
index 6e3cb52b85d..e37b177f8f3 100644
--- a/gcc/testsuite/gcc.dg/vect/pr52252-ld.c
+++ b/gcc/testsuite/gcc.dg/vect/pr52252-ld.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -g -ftree-vectorize -mssse3 -fdump-tree-vect-details" { target { i?86-*-* x86_64-*-* } } } */
-
+/* { dg-additional-options "-mssse3" { target { i?86-*-* x86_64-*-* } } } */
#define byte unsigned char
void
@@ -26,5 +25,5 @@ matrix_mul (byte *in, byte *out, int size)
}
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { i?86-*-* x86_64-*-* } } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr61194.c b/gcc/testsuite/gcc.dg/vect/pr61194.c
new file mode 100644
index 00000000000..e10cff4b96c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr61194.c
@@ -0,0 +1,43 @@
+/* { dg-require-effective-target vect_cond_mixed } */
+/* { dg-additional-options "-ftree-loop-if-convert-stores" } */
+
+#include "tree-vect.h"
+
+static float x[1024];
+static float y[1024];
+static float z[1024];
+static float w[1024];
+
+void __attribute__((noinline,noclone)) barX()
+{
+ int i;
+ for (i=0; i<1024; ++i)
+ z[i] = ((x[i]>0) & (w[i]<0)) ? z[i] : y[i];
+}
+
+int main()
+{
+ int i;
+
+ check_vect ();
+
+ for (i = 0; i < 1024; ++i)
+ {
+ x[i] = -10 + i;
+ w[i] = 100 - i;
+ z[i] = 0.;
+ y[i] = 1.;
+ __asm__ volatile ("" : : : "memory");
+ }
+
+ barX();
+
+ for (i = 0; i < 1024; ++i)
+ if (z[i] != ((x[i]>0 && w[i]<0) ? 0. : 1.))
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect.exp b/gcc/testsuite/gcc.dg/vect/vect.exp
index fa11e7e5eea..e8d866b991c 100644
--- a/gcc/testsuite/gcc.dg/vect/vect.exp
+++ b/gcc/testsuite/gcc.dg/vect/vect.exp
@@ -18,6 +18,7 @@
# Load support procs.
load_lib gcc-dg.exp
+load_lib clearcap.exp
# Set up flags used for tests that don't specify options.
global DEFAULT_VECTCFLAGS
@@ -41,30 +42,9 @@ if ![check_vect_support_and_set_flags] {
# These flags are used for all targets.
lappend DEFAULT_VECTCFLAGS "-ftree-vectorize" "-fno-vect-cost-model" "-fno-common"
-# If the linker used understands -M <mapfile>, pass it to clear hardware
-# capabilities set by the Sun assembler.
-# Try mapfile syntax v2 first which is the only way to clear hwcap_2 flags.
-set clearcap_ldflags "-Wl,-M,$srcdir/gcc.target/i386/clearcapv2.map"
-
-if ![check_no_compiler_messages mapfilev2 executable {
- int main (void) { return 0; }
-} $clearcap_ldflags ] {
- # If this doesn't work, fall back to the less capable v1 syntax.
- set clearcap_ldflags "-Wl,-M,$srcdir/gcc.target/i386/clearcap.map"
-
- if ![check_no_compiler_messages mapfile executable {
- int main (void) { return 0; }
- } $clearcap_ldflags ] {
- unset clearcap_ldflags
- }
-}
-
-if [info exists clearcap_ldflags] {
- lappend DEFAULT_VECTCFLAGS $clearcap_ldflags
-}
-
# Initialize `dg'.
dg-init
+clearcap-init
global VEC_FLAGS
set VEC_FLAGS $DEFAULT_VECTCFLAGS
@@ -308,4 +288,5 @@ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/no-tree-sra-bb-slp-*.\[cS\]]
set dg-do-what-default ${save-dg-do-what-default}
# All done.
+clearcap-finish
dg-finish
diff --git a/gcc/testsuite/gcc.dg/wtr-conversion-1.c b/gcc/testsuite/gcc.dg/wtr-conversion-1.c
index 72094c21840..9d2cd999939 100644
--- a/gcc/testsuite/gcc.dg/wtr-conversion-1.c
+++ b/gcc/testsuite/gcc.dg/wtr-conversion-1.c
@@ -2,7 +2,7 @@
Note, gcc should omit these warnings in system header files.
By Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 4/09/2001. */
/* { dg-do compile } */
-/* { dg-options "-Wtraditional" } */
+/* { dg-options "-Wtraditional-conversion" } */
extern void foo_i (int);
extern void foo_f (float);
diff --git a/gcc/testsuite/gcc.target/aarch64/pr61325.c b/gcc/testsuite/gcc.target/aarch64/pr61325.c
new file mode 100644
index 00000000000..45ece53446f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr61325.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+typedef unsigned int wchar_t;
+typedef long unsigned int size_t;
+
+size_t
+wcstombs(char *s , const wchar_t *pwcs , size_t n)
+{
+ int count = 0;
+
+ if (n != 0) {
+ do {
+ if ((*s++ = (char) *pwcs++) == 0)
+ break;
+ count++;
+ } while (--n != 0);
+ }
+ return count;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/tail_indirect_call_1.c b/gcc/testsuite/gcc.target/aarch64/tail_indirect_call_1.c
new file mode 100644
index 00000000000..4759d20df9c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/tail_indirect_call_1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef void FP (int);
+
+/* { dg-final { scan-assembler "br" } } */
+/* { dg-final { scan-assembler-not "blr" } } */
+void
+f1 (FP fp, int n)
+{
+ (fp) (n);
+}
+
+void
+f2 (int n, FP fp)
+{
+ (fp) (n);
+}
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextQf32_1.c b/gcc/testsuite/gcc.target/arm/simd/vextQf32_1.c
new file mode 100644
index 00000000000..c1da6d38a5d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextQf32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextQf32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/extq_f32.x"
+
+/* { dg-final { scan-assembler-times "vext\.32\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 3 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextQp16_1.c b/gcc/testsuite/gcc.target/arm/simd/vextQp16_1.c
new file mode 100644
index 00000000000..adc086181b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextQp16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextQp16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/extq_p16.x"
+
+/* { dg-final { scan-assembler-times "vext\.16\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 7 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextQp64_1.c b/gcc/testsuite/gcc.target/arm/simd/vextQp64_1.c
new file mode 100644
index 00000000000..e8b688da2b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextQp64_1.c
@@ -0,0 +1,33 @@
+/* Test the `vextQp64' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_crypto_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_crypto } */
+
+#include "arm_neon.h"
+
+extern void abort (void);
+
+poly64x2_t
+test_vextq_p64_1 (poly64x2_t a, poly64x2_t b)
+{
+ return vextq_p64(a, b, 1);
+}
+
+int
+main (int argc, char **argv)
+{
+ int i, off;
+ poly64x2_t in1 = {0, 1};
+ poly64x2_t in2 = {2, 3};
+ poly64x2_t actual = test_vextq_p64_1 (in1, in2);
+ for (i = 0; i < 2; i++)
+ if (actual[i] != i + 1)
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "vext\.64\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextQp8_1.c b/gcc/testsuite/gcc.target/arm/simd/vextQp8_1.c
new file mode 100644
index 00000000000..5f2cc53e367
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextQp8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextQp8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/extq_p8.x"
+
+/* { dg-final { scan-assembler-times "vext\.8\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 15 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextQs16_1.c b/gcc/testsuite/gcc.target/arm/simd/vextQs16_1.c
new file mode 100644
index 00000000000..c0d791dcef3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextQs16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextQs16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/extq_s16.x"
+
+/* { dg-final { scan-assembler-times "vext\.16\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 7 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextQs32_1.c b/gcc/testsuite/gcc.target/arm/simd/vextQs32_1.c
new file mode 100644
index 00000000000..ed5b21091cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextQs32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextQs32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/extq_s32.x"
+
+/* { dg-final { scan-assembler-times "vext\.32\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 3 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextQs64_1.c b/gcc/testsuite/gcc.target/arm/simd/vextQs64_1.c
new file mode 100644
index 00000000000..dbbee47c58b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextQs64_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextQs64' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/extq_s64.x"
+
+/* { dg-final { scan-assembler-times "vext\.64\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextQs8_1.c b/gcc/testsuite/gcc.target/arm/simd/vextQs8_1.c
new file mode 100644
index 00000000000..0ebdce38165
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextQs8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextQs8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/extq_s8.x"
+
+/* { dg-final { scan-assembler-times "vext\.8\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 15 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextQu16_1.c b/gcc/testsuite/gcc.target/arm/simd/vextQu16_1.c
new file mode 100644
index 00000000000..136f2b8741f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextQu16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextQu16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/extq_u16.x"
+
+/* { dg-final { scan-assembler-times "vext\.16\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 7 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextQu32_1.c b/gcc/testsuite/gcc.target/arm/simd/vextQu32_1.c
new file mode 100644
index 00000000000..66ce035c5a2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextQu32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextQu32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/extq_u32.x"
+
+/* { dg-final { scan-assembler-times "vext\.32\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 3 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextQu64_1.c b/gcc/testsuite/gcc.target/arm/simd/vextQu64_1.c
new file mode 100644
index 00000000000..ebe4abd069f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextQu64_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextQu64' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/extq_u64.x"
+
+/* { dg-final { scan-assembler-times "vext\.64\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextQu8_1.c b/gcc/testsuite/gcc.target/arm/simd/vextQu8_1.c
new file mode 100644
index 00000000000..432ac0a5674
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextQu8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextQu8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/extq_u8.x"
+
+/* { dg-final { scan-assembler-times "vext\.8\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 15 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextf32_1.c b/gcc/testsuite/gcc.target/arm/simd/vextf32_1.c
new file mode 100644
index 00000000000..99e0bad0ed0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextf32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextf32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/ext_f32.x"
+
+/* { dg-final { scan-assembler-times "vext\.32\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextp16_1.c b/gcc/testsuite/gcc.target/arm/simd/vextp16_1.c
new file mode 100644
index 00000000000..00695bf6419
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextp16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextp16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/ext_p16.x"
+
+/* { dg-final { scan-assembler-times "vext\.16\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 3 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextp64_1.c b/gcc/testsuite/gcc.target/arm/simd/vextp64_1.c
new file mode 100644
index 00000000000..8783e166ea7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextp64_1.c
@@ -0,0 +1,26 @@
+/* Test the `vextp64' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_crypto_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_crypto } */
+
+#include "arm_neon.h"
+
+extern void abort (void);
+
+int
+main (int argc, char **argv)
+{
+ int i;
+ poly64x1_t in1 = {0};
+ poly64x1_t in2 = {1};
+ poly64x1_t actual = vext_p64 (in1, in2, 0);
+ if (actual != in1)
+ abort ();
+
+ return 0;
+}
+
+/* Don't scan assembler for vext - it can be optimized into a move from r0.
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextp8_1.c b/gcc/testsuite/gcc.target/arm/simd/vextp8_1.c
new file mode 100644
index 00000000000..2ba72c1ac0c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextp8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextp8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/ext_p8.x"
+
+/* { dg-final { scan-assembler-times "vext\.8\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 7 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vexts16_1.c b/gcc/testsuite/gcc.target/arm/simd/vexts16_1.c
new file mode 100644
index 00000000000..4fa57d6b696
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vexts16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vexts16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/ext_s16.x"
+
+/* { dg-final { scan-assembler-times "vext\.16\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 3 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vexts32_1.c b/gcc/testsuite/gcc.target/arm/simd/vexts32_1.c
new file mode 100644
index 00000000000..3cd59360e28
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vexts32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vexts32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/ext_s32.x"
+
+/* { dg-final { scan-assembler-times "vext\.32\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vexts64_1.c b/gcc/testsuite/gcc.target/arm/simd/vexts64_1.c
new file mode 100644
index 00000000000..7bb20121988
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vexts64_1.c
@@ -0,0 +1,12 @@
+/* Test the `vexts64' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/ext_s64.x"
+
+/* Don't scan assembler for vext - it can be optimized into a move from r0. */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vexts8_1.c b/gcc/testsuite/gcc.target/arm/simd/vexts8_1.c
new file mode 100644
index 00000000000..194e198b98e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vexts8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vexts8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/ext_s8.x"
+
+/* { dg-final { scan-assembler-times "vext\.8\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 7 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextu16_1.c b/gcc/testsuite/gcc.target/arm/simd/vextu16_1.c
new file mode 100644
index 00000000000..f69c2bdc77f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextu16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextu16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/ext_u16.x"
+
+/* { dg-final { scan-assembler-times "vext\.16\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 3 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextu32_1.c b/gcc/testsuite/gcc.target/arm/simd/vextu32_1.c
new file mode 100644
index 00000000000..b76e383cadb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextu32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextu32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/ext_u32.x"
+
+/* { dg-final { scan-assembler-times "vext\.32\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextu64_1.c b/gcc/testsuite/gcc.target/arm/simd/vextu64_1.c
new file mode 100644
index 00000000000..39ffc56cba7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextu64_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextu64' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/ext_u64.x"
+
+/* Don't scan assembler for vext - it can be optimized into a move from r0. */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vextu8_1.c b/gcc/testsuite/gcc.target/arm/simd/vextu8_1.c
new file mode 100644
index 00000000000..a9d62b31dff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vextu8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vextu8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O3 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/ext_u8.x"
+
+/* { dg-final { scan-assembler-times "vext\.8\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 7 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev16p8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev16p8_1.c
new file mode 100644
index 00000000000..fddb32fbb8b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev16p8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev16p8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev16p8.x"
+
+/* { dg-final { scan-assembler "vrev16\.8\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev16qp8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev16qp8_1.c
new file mode 100644
index 00000000000..b4634b8dbde
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev16qp8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev16q_p8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev16qp8.x"
+
+/* { dg-final { scan-assembler "vrev16\.8\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev16qs8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev16qs8_1.c
new file mode 100644
index 00000000000..691799b6b94
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev16qs8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev16q_s8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev16qs8.x"
+
+/* { dg-final { scan-assembler "vrev16\.8\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev16qu8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev16qu8_1.c
new file mode 100644
index 00000000000..f6ab4ac5cd1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev16qu8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev16q_u8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev16qu8.x"
+
+/* { dg-final { scan-assembler "vrev16\.8\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev16s8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev16s8_1.c
new file mode 100644
index 00000000000..0a03721f29c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev16s8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev16s8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev16s8.x"
+
+/* { dg-final { scan-assembler "vrev16\.8\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev16u8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev16u8_1.c
new file mode 100644
index 00000000000..7e5f54808ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev16u8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev16u8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev16u8.x"
+
+/* { dg-final { scan-assembler "vrev16\.8\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev32p16_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev32p16_1.c
new file mode 100644
index 00000000000..f3643fa96da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev32p16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev32p16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev32p16.x"
+
+/* { dg-final { scan-assembler "vrev32\.16\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev32p8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev32p8_1.c
new file mode 100644
index 00000000000..d823e59ff1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev32p8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev32p8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev32p8.x"
+
+/* { dg-final { scan-assembler "vrev32\.8\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev32qp16_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev32qp16_1.c
new file mode 100644
index 00000000000..f8ba8a916ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev32qp16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev32q_p16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev32qp16.x"
+
+/* { dg-final { scan-assembler "vrev32\.16\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev32qp8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev32qp8_1.c
new file mode 100644
index 00000000000..0ddf6081a82
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev32qp8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev32q_p8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev32qp8.x"
+
+/* { dg-final { scan-assembler "vrev32\.8\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev32qs16_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev32qs16_1.c
new file mode 100644
index 00000000000..30d0314c202
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev32qs16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev32q_s16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev32qs16.x"
+
+/* { dg-final { scan-assembler "vrev32\.16\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev32qs8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev32qs8_1.c
new file mode 100644
index 00000000000..03ddd2be25c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev32qs8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev32q_s8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev32qs8.x"
+
+/* { dg-final { scan-assembler "vrev32\.8\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev32qu16_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev32qu16_1.c
new file mode 100644
index 00000000000..71765437b65
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev32qu16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev32q_u16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev32qu16.x"
+
+/* { dg-final { scan-assembler "vrev32\.16\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev32qu8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev32qu8_1.c
new file mode 100644
index 00000000000..403292c7cd8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev32qu8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev32q_u8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev32qu8.x"
+
+/* { dg-final { scan-assembler "vrev32\.8\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev32s16_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev32s16_1.c
new file mode 100644
index 00000000000..e182ab988ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev32s16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev32s16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev32s16.x"
+
+/* { dg-final { scan-assembler "vrev32\.16\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev32s8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev32s8_1.c
new file mode 100644
index 00000000000..a48c4155176
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev32s8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev32s8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev32s8.x"
+
+/* { dg-final { scan-assembler "vrev32\.8\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev32u16_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev32u16_1.c
new file mode 100644
index 00000000000..076f8ab885b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev32u16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev32u16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev32u16.x"
+
+/* { dg-final { scan-assembler "vrev32\.16\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev32u8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev32u8_1.c
new file mode 100644
index 00000000000..240d4596e8c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev32u8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev32u8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev32u8.x"
+
+/* { dg-final { scan-assembler "vrev32\.8\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64f32_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64f32_1.c
new file mode 100644
index 00000000000..f5d3bcae564
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64f32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64f32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64f32.x"
+
+/* { dg-final { scan-assembler "vrev64\.32\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64p16_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64p16_1.c
new file mode 100644
index 00000000000..8c685c0f8ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64p16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64p16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64p16.x"
+
+/* { dg-final { scan-assembler "vrev64\.16\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64p8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64p8_1.c
new file mode 100644
index 00000000000..67ac1e49117
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64p8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64p8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64p8.x"
+
+/* { dg-final { scan-assembler "vrev64\.8\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64qf32_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64qf32_1.c
new file mode 100644
index 00000000000..74130b7d821
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64qf32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64q_f32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64qf32.x"
+
+/* { dg-final { scan-assembler "vrev64\.32\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64qp16_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64qp16_1.c
new file mode 100644
index 00000000000..71f3b4ba4b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64qp16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64q_p16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64qp16.x"
+
+/* { dg-final { scan-assembler "vrev64\.16\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64qp8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64qp8_1.c
new file mode 100644
index 00000000000..324a738c660
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64qp8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64q_p8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64qp8.x"
+
+/* { dg-final { scan-assembler "vrev64\.8\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64qs16_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64qs16_1.c
new file mode 100644
index 00000000000..9a373ec4100
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64qs16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64q_s16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64qs16.x"
+
+/* { dg-final { scan-assembler "vrev64\.16\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64qs32_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64qs32_1.c
new file mode 100644
index 00000000000..0f10c6cb078
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64qs32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64q_s32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64qs32.x"
+
+/* { dg-final { scan-assembler "vrev64\.32\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64qs8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64qs8_1.c
new file mode 100644
index 00000000000..cf380143be6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64qs8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64q_s8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64qs8.x"
+
+/* { dg-final { scan-assembler "vrev64\.8\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64qu16_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64qu16_1.c
new file mode 100644
index 00000000000..010d6dbb805
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64qu16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64q_u16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64qu16.x"
+
+/* { dg-final { scan-assembler "vrev64\.16\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64qu32_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64qu32_1.c
new file mode 100644
index 00000000000..908769cc682
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64qu32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64q_u32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64qu32.x"
+
+/* { dg-final { scan-assembler "vrev64\.32\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64qu8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64qu8_1.c
new file mode 100644
index 00000000000..2fa07d12980
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64qu8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64q_u8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64qu8.x"
+
+/* { dg-final { scan-assembler "vrev64\.8\[ \t\]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64s16_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64s16_1.c
new file mode 100644
index 00000000000..f14319c3214
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64s16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64s16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64s16.x"
+
+/* { dg-final { scan-assembler "vrev64\.16\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64s32_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64s32_1.c
new file mode 100644
index 00000000000..ead57225f3e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64s32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64s32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64s32.x"
+
+/* { dg-final { scan-assembler "vrev64\.32\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64s8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64s8_1.c
new file mode 100644
index 00000000000..29d684dcd1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64s8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64s8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64s8.x"
+
+/* { dg-final { scan-assembler "vrev64\.8\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64u16_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64u16_1.c
new file mode 100644
index 00000000000..feddacce2b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64u16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64u16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64u16.x"
+
+/* { dg-final { scan-assembler "vrev64\.16\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64u32_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64u32_1.c
new file mode 100644
index 00000000000..92a81f44041
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64u32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64u32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64u32.x"
+
+/* { dg-final { scan-assembler "vrev64\.32\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vrev64u8_1.c b/gcc/testsuite/gcc.target/arm/simd/vrev64u8_1.c
new file mode 100644
index 00000000000..f904af5ca77
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vrev64u8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vrev64u8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vrev64u8.x"
+
+/* { dg-final { scan-assembler "vrev64\.8\[ \t\]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+!?\(\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnf32_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnf32_1.c
new file mode 100644
index 00000000000..0f9b6c9b8bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnf32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnf32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnf32.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.32\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnp16_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnp16_1.c
new file mode 100644
index 00000000000..0ff43198109
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnp16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnp16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnp16.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.16\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnp8_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnp8_1.c
new file mode 100644
index 00000000000..2b047e4d759
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnp8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnp8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnp8.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.8\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnqf32_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnqf32_1.c
new file mode 100644
index 00000000000..dd4e8836f3c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnqf32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnQf32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnqf32.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.32\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnqp16_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnqp16_1.c
new file mode 100644
index 00000000000..374eee396de
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnqp16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnQp16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnqp16.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.16\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnqp8_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnqp8_1.c
new file mode 100644
index 00000000000..b252fd5f3b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnqp8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnQp8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnqp8.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.8\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnqs16_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnqs16_1.c
new file mode 100644
index 00000000000..5f06d2a3b12
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnqs16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnQs16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnqs16.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.16\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnqs32_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnqs32_1.c
new file mode 100644
index 00000000000..221175c46c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnqs32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnQs32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnqs32.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.32\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnqs8_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnqs8_1.c
new file mode 100644
index 00000000000..9352b37a783
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnqs8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnQs8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnqs8.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.8\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnqu16_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnqu16_1.c
new file mode 100644
index 00000000000..7f40109b2a3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnqu16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnQu16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnqu16.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.16\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnqu32_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnqu32_1.c
new file mode 100644
index 00000000000..1c61fc34f7c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnqu32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnQu32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnqu32.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.32\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnqu8_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnqu8_1.c
new file mode 100644
index 00000000000..82f911d5a78
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnqu8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnQu8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnqu8.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.8\[ \t\]+\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrns16_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrns16_1.c
new file mode 100644
index 00000000000..af2c68f381f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrns16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrns16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrns16.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.16\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrns32_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrns32_1.c
new file mode 100644
index 00000000000..35a98ea9551
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrns32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrns32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrns32.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.32\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrns8_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrns8_1.c
new file mode 100644
index 00000000000..395015d1330
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrns8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrns8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrns8.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.8\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnu16_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnu16_1.c
new file mode 100644
index 00000000000..df0d963a5fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnu16_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnu16' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnu16.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.16\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnu32_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnu32_1.c
new file mode 100644
index 00000000000..764ed623f07
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnu32_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnu32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnu32.x"
+
+/* { dg-final { scan-assembler-times "vuzp\.32\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vtrnu8_1.c b/gcc/testsuite/gcc.target/arm/simd/vtrnu8_1.c
new file mode 100644
index 00000000000..f5b4d68966e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vtrnu8_1.c
@@ -0,0 +1,12 @@
+/* Test the `vtrnu8' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-save-temps -O1 -fno-inline" } */
+/* { dg-add-options arm_neon } */
+
+#include "arm_neon.h"
+#include "../../aarch64/simd/vtrnu8.x"
+
+/* { dg-final { scan-assembler-times "vtrn\.8\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+!?\(?:\[ \t\]+@\[a-zA-Z0-9 \]+\)?\n" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/avr/pr60991.c b/gcc/testsuite/gcc.target/avr/pr60991.c
new file mode 100644
index 00000000000..a09f42a62b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr60991.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+
+/* This testcase (simplified from the original bug report) exposes
+ PR60991. The code generated for writing the __int24 value corrupts
+ the frame pointer if the offset is <= 63 + MAX_LD_OFFSET */
+
+#include <stdlib.h>
+
+int main(void)
+{
+ volatile char junk[62];
+ junk[0] = 5;
+ volatile __int24 staticConfig = 0;
+
+ if (junk[0] != 5)
+ abort();
+
+ exit(0);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr61055.c b/gcc/testsuite/gcc.target/avr/torture/pr61055.c
new file mode 100644
index 00000000000..9dd1f427d00
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr61055.c
@@ -0,0 +1,88 @@
+/* { dg-do run } */
+/* { dg-options { -fno-peephole2 } } */
+
+#include <stdlib.h>
+
+typedef __UINT16_TYPE__ uint16_t;
+typedef __INT16_TYPE__ int16_t;
+typedef __UINT8_TYPE__ uint8_t;
+
+uint8_t __attribute__((noinline,noclone))
+fun_inc (uint8_t c0)
+{
+ register uint8_t c asm ("r15") = c0;
+
+ /* Force target value into R15 (lower register) */
+ asm ("" : "+l" (c));
+
+ c++;
+ if (c >= 0x80)
+ c = 0;
+
+ asm ("" : "+l" (c));
+
+ return c;
+}
+
+uint8_t __attribute__((noinline,noclone))
+fun_dec (uint8_t c0)
+{
+ register uint8_t c asm ("r15") = c0;
+
+ /* Force target value into R15 (lower register) */
+ asm ("" : "+l" (c));
+
+ c--;
+ if (c < 0x80)
+ c = 0;
+
+ asm ("" : "+l" (c));
+
+ return c;
+}
+
+
+uint8_t __attribute__((noinline,noclone))
+fun_neg (uint8_t c0)
+{
+ register uint8_t c asm ("r15") = c0;
+
+ c = -c;
+ if (c >= 0x80)
+ c = 0;
+
+ return c;
+}
+
+uint16_t __attribute__((noinline,noclone))
+fun_adiw (uint16_t c0)
+{
+ register uint16_t c asm ("r24") = c0;
+
+ /* Force target value into R24 (for ADIW) */
+ asm ("" : "+r" (c));
+
+ c += 2;
+ if (c >= 0x8000)
+ c = 0;
+
+ asm ("" : "+r" (c));
+
+ return c;
+}
+
+
+int main()
+{
+ if (fun_inc (0x7f) != 0)
+ abort();
+
+ if (fun_neg (0x80) != 0)
+ abort();
+
+ if (fun_adiw (0x7ffe) != 0)
+ abort();
+
+ exit (0);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c
index 30b42aa38c2..6802b748001 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c
@@ -11,5 +11,5 @@ avx_test (char **cp, char **ep)
}
/* { dg-final { scan-assembler-not "(avx_loaddqu256|vmovdqu\[^\n\r]*movv32qi_internal)" } } */
-/* { dg-final { scan-assembler "(sse2_loaddqu|vmovdqu\[^\n\r]*movv16qi_internal)" } } */
+/* { dg-final { scan-assembler "(sse2_loaddqu|(vmovdqu|vmovups)\[^\n\r]*movv16qi_internal)" } } */
/* { dg-final { scan-assembler "vinsert.128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/clearcap.map b/gcc/testsuite/gcc.target/i386/clearcap.map
deleted file mode 100644
index 147f922d1e5..00000000000
--- a/gcc/testsuite/gcc.target/i386/clearcap.map
+++ /dev/null
@@ -1,3 +0,0 @@
-# clear all hardware capabilities emitted by Sun as: the tests here
-# guard against execution at runtime
-hwcap_1 = V0x0 OVERRIDE;
diff --git a/gcc/testsuite/gcc.target/i386/clearcapv2.map b/gcc/testsuite/gcc.target/i386/clearcapv2.map
deleted file mode 100644
index 95cb14cc5d2..00000000000
--- a/gcc/testsuite/gcc.target/i386/clearcapv2.map
+++ /dev/null
@@ -1,7 +0,0 @@
-# clear all hardware capabilities emitted by Sun as: the tests here
-# guard against execution at runtime
-# uses mapfile v2 syntax which is the only way to clear AT_SUN_CAP_HW2 flags
-$mapfile_version 2
-CAPABILITY {
- HW = ;
-};
diff --git a/gcc/testsuite/gcc.target/i386/clflushopt-1.c b/gcc/testsuite/gcc.target/i386/clflushopt-1.c
new file mode 100644
index 00000000000..756937305f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/clflushopt-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mclflushopt" } */
+/* { dg-final { scan-assembler "clflushopt\[ \\t\]" } } */
+
+#include "x86intrin.h"
+
+void
+test_clflushopt (void *__A)
+{
+ _mm_clflushopt (__A);
+}
diff --git a/gcc/testsuite/gcc.target/i386/fuse-caller-save.c b/gcc/testsuite/gcc.target/i386/fuse-caller-save.c
new file mode 100644
index 00000000000..8618409c78a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fuse-caller-save.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fuse-caller-save" } */
+/* { dg-additional-options "-mregparm=1" { target ia32 } } */
+
+/* Testing -fuse-caller-save optimization option. */
+
+static int __attribute__((noinline))
+bar (int x)
+{
+ return x + 3;
+}
+
+int __attribute__((noinline))
+foo (int y)
+{
+ return y + bar (y);
+}
+
+int
+main (void)
+{
+ return !(foo (5) == 13);
+}
+
+/* { dg-final { scan-assembler-not "\.cfi_def_cfa_offset" } } */
+/* { dg-final { scan-assembler-not "\.cfi_offset" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/i386.exp b/gcc/testsuite/gcc.target/i386/i386.exp
index 080e302b782..d9b36cd30da 100644
--- a/gcc/testsuite/gcc.target/i386/i386.exp
+++ b/gcc/testsuite/gcc.target/i386/i386.exp
@@ -23,6 +23,7 @@ if { ![istarget i?86*-*-*] && ![istarget x86_64-*-*] } then {
# Load support procs.
load_lib gcc-dg.exp
+load_lib clearcap.exp
# Return 1 if attribute ms_hook_prologue is supported.
proc check_effective_target_ms_hook_prologue { } {
@@ -307,39 +308,6 @@ proc check_effective_target_sha { } {
} "-O2 -msha" ]
}
-# If the linker used understands -M <mapfile>, pass it to clear hardware
-# capabilities set by the Sun assembler.
-# Try mapfile syntax v2 first which is the only way to clear hwcap_2 flags.
-set clearcap_ldflags "-Wl,-M,$srcdir/$subdir/clearcapv2.map"
-
-if ![check_no_compiler_messages mapfilev2 executable {
- int main (void) { return 0; }
-} $clearcap_ldflags ] {
- # If this doesn't work, fall back to the less capable v1 syntax.
- set clearcap_ldflags "-Wl,-M,$srcdir/$subdir/clearcap.map"
-
- if ![check_no_compiler_messages mapfile executable {
- int main (void) { return 0; }
- } $clearcap_ldflags ] {
- unset clearcap_ldflags
- }
-}
-
-if [info exists clearcap_ldflags] {
- if { [info procs gcc_target_compile] != [list] \
- && [info procs saved_gcc_target_compile] == [list] } {
- rename gcc_target_compile saved_gcc_target_compile
-
- proc gcc_target_compile { source dest type options } {
- global clearcap_ldflags
- # Always pass -Wl,-M,<mapfile>, but don't let it show up in gcc.sum.
- lappend options "additional_flags=$clearcap_ldflags"
-
- return [saved_gcc_target_compile $source $dest $type $options]
- }
- }
-}
-
# If a testcase doesn't have special options, use these.
global DEFAULT_CFLAGS
if ![info exists DEFAULT_CFLAGS] then {
@@ -348,6 +316,7 @@ if ![info exists DEFAULT_CFLAGS] then {
# Initialize `dg'.
dg-init
+clearcap-init
# Special case compilation of vect-args.c so we don't have to
# replicate it 10 times.
@@ -367,4 +336,5 @@ set tests [prune $tests $srcdir/$subdir/vect-args.c]
dg-runtest $tests "" $DEFAULT_CFLAGS
# All done.
+clearcap-finish
dg-finish
diff --git a/gcc/testsuite/gcc.target/i386/pause-2.c b/gcc/testsuite/gcc.target/i386/pause-2.c
new file mode 100644
index 00000000000..d8b25195801
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pause-2.c
@@ -0,0 +1,12 @@
+/* Test that pause instruction works even when SSE is not enabled. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -dp" } */
+/* { dg-final { scan-assembler-times "\\*pause" 1 } } */
+
+#include <xmmintrin.h>
+
+void
+foo (void)
+{
+ _mm_pause ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr49002-1.c b/gcc/testsuite/gcc.target/i386/pr49002-1.c
index 7553e8290e5..646fb2bceb6 100644
--- a/gcc/testsuite/gcc.target/i386/pr49002-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr49002-1.c
@@ -13,4 +13,4 @@ void foo(const __m128d *from, __m256d *to, int s)
/* Ensure we load into xmm, not ymm. */
/* { dg-final { scan-assembler-not "vmovapd\[\t \]*\[^,\]*,\[\t \]*%ymm" } } */
-/* { dg-final { scan-assembler "vmovapd\[\t \]*\[^,\]*,\[\t \]*%xmm" } } */
+/* { dg-final { scan-assembler "vmovap\[ds\]\[\t \]*\[^,\]*,\[\t \]*%xmm" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr53712.c b/gcc/testsuite/gcc.target/i386/pr53712.c
index 5c47e20c300..394afc566b9 100644
--- a/gcc/testsuite/gcc.target/i386/pr53712.c
+++ b/gcc/testsuite/gcc.target/i386/pr53712.c
@@ -10,4 +10,4 @@ int test (const char *s1, const char *s2)
return __builtin_ia32_pcmpistri128 (s1chars, s2chars, 0);
}
-/* { dg-final { scan-assembler-times "movdqu" 1 } } */
+/* { dg-final { scan-assembler-times "movdqu|movups" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr53907.c b/gcc/testsuite/gcc.target/i386/pr53907.c
index 27e2e02985f..dbf5b99b3b8 100644
--- a/gcc/testsuite/gcc.target/i386/pr53907.c
+++ b/gcc/testsuite/gcc.target/i386/pr53907.c
@@ -13,4 +13,4 @@ __m128i x(char *s)
return sz;
}
-/* { dg-final { scan-assembler "movdqa" } } */
+/* { dg-final { scan-assembler "movdqa|movaps" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr58066.c b/gcc/testsuite/gcc.target/i386/pr58066.c
new file mode 100644
index 00000000000..c8feb4ee9e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr58066.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-require-effective-target fpic } */
+/* { dg-options "-fPIC -fomit-frame-pointer -O2 -fdump-rtl-final" } */
+
+/* Check whether the stack frame starting addresses of tls expanded calls
+ in foo and goo are 16bytes aligned. */
+static __thread char ccc1;
+void* foo()
+{
+ return &ccc1;
+}
+
+__thread char ccc2;
+void* goo()
+{
+ return &ccc2;
+}
+
+/* { dg-final { scan-rtl-dump "Function foo.*set\[^\r\n\]*sp\\)\[\r\n\]\[^\r\n\]*plus\[^\r\n\]*sp\\)\[\r\n\]\[^\r\n\]*const_int -8.*UNSPEC_TLS.*Function goo" "final" } } */
+/* { dg-final { scan-rtl-dump "Function goo.*set\[^\r\n\]*sp\\)\[\r\n\]\[^\r\n\]*plus\[^\r\n\]*sp\\)\[\r\n\]\[^\r\n\]*const_int -8.*UNSPEC_TLS" "final" } } */
+/* { dg-final { cleanup-rtl-dump "final" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr59539-1.c b/gcc/testsuite/gcc.target/i386/pr59539-1.c
index 9b34053c4cb..68342ff15f2 100644
--- a/gcc/testsuite/gcc.target/i386/pr59539-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr59539-1.c
@@ -13,4 +13,4 @@ foo (void *p1, void *p2)
return _mm_movemask_epi8 (result);
}
-/* { dg-final { scan-assembler-times "vmovdqu" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqu|vmovups" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr60901.c b/gcc/testsuite/gcc.target/i386/pr60901.c
new file mode 100644
index 00000000000..f0f25a1dc2c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr60901.c
@@ -0,0 +1,17 @@
+/* { dg-options "-O -fselective-scheduling -fschedule-insns -fsel-sched-pipelining -fsel-sched-pipelining-outer-loops -fno-tree-dominator-opts" } */
+
+extern int n;
+extern void bar (void);
+extern int baz (int);
+
+void
+foo (void)
+{
+ int i, j;
+ for (j = 0; j < n; j++)
+ {
+ for (i = 1; i < j; i++)
+ bar ();
+ baz (0);
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr61215.c b/gcc/testsuite/gcc.target/i386/pr61215.c
new file mode 100644
index 00000000000..03a7a2cc97c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr61215.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-O2 -march=i686" } */
+
+void fn1 (int *, ...);
+int fn2 (int p1)
+{
+ fn1 (0, (short)(int)&p1);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/sibcall-1.c b/gcc/testsuite/gcc.target/i386/sibcall-1.c
new file mode 100644
index 00000000000..5f0dc298bd2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sibcall-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2" } */
+
+extern int (*foo)(int);
+
+int boo (int a)
+{
+ return (*foo) (a);
+}
+
+/* { dg-final { scan-assembler-not "mov" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sibcall-2.c b/gcc/testsuite/gcc.target/i386/sibcall-2.c
new file mode 100644
index 00000000000..4c7e39c08b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sibcall-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2" } */
+
+extern int doo1 (int);
+extern int doo2 (int);
+extern void bar (char *);
+
+int foo (int a)
+{
+ char s[256];
+ bar (s);
+ return (a < 0 ? doo1 : doo2) (a);
+}
+
+/* { dg-final { scan-assembler-not "call\[ \t\]*.%eax" { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.target/i386/sibcall-3.c b/gcc/testsuite/gcc.target/i386/sibcall-3.c
new file mode 100644
index 00000000000..8154e8f1731
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sibcall-3.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2" } */
+
+extern
+#ifdef _WIN32
+ __declspec (dllimport)
+#endif
+ void foo (int a);
+
+void bar (int a)
+{
+ return foo (a);
+}
+
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*.%eax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sibcall-4.c b/gcc/testsuite/gcc.target/i386/sibcall-4.c
new file mode 100644
index 00000000000..c00a60e4d12
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sibcall-4.c
@@ -0,0 +1,14 @@
+/* Testcase for PR target/46219. */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+void male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+}
+
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*.%eax" { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.target/i386/sibcall-5.c b/gcc/testsuite/gcc.target/i386/sibcall-5.c
index 7cf67dbe16a..ec003c9962e 100644
--- a/gcc/testsuite/gcc.target/i386/sibcall-5.c
+++ b/gcc/testsuite/gcc.target/i386/sibcall-5.c
@@ -1,6 +1,5 @@
/* Check that indirect sibcalls understand regparm. */
-/* { dg-do run } */
-/* { dg-require-effective-target ia32 } */
+/* { dg-do run { target ia32 } } */
/* { dg-options "-O2" } */
extern void abort (void);
diff --git a/gcc/testsuite/gcc.target/i386/sibcall-6.c b/gcc/testsuite/gcc.target/i386/sibcall-6.c
new file mode 100644
index 00000000000..7f552b8df42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sibcall-6.c
@@ -0,0 +1,36 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2" } */
+
+typedef void *ira_loop_tree_node_t;
+
+extern int end (int);
+extern int doo (int);
+
+void
+ira_traverse_loop_tree (int bb_p, ira_loop_tree_node_t loop_node,
+ void (*preorder_func) (ira_loop_tree_node_t),
+ void (*postorder_func) (ira_loop_tree_node_t))
+{
+ int l, r = 0x1, h = 0, j = 0;
+
+ if (preorder_func)
+ (*preorder_func) (loop_node);
+
+ if (bb_p)
+ {
+ for (l = 0; l < end (l); l++)
+ {
+ r += doo (l);
+ h += (l + 1) * 3;
+ h %= (l + 1);
+ r -= doo (h);
+ j += (l + 1) * 7;
+ j %= (l + 1);
+ r += doo (j);
+ }
+ }
+
+ if (postorder_func)
+ (*postorder_func) (loop_node);
+}
+/* { dg-final { scan-assembler "jmp\[ \t\]*.%eax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse-12.c b/gcc/testsuite/gcc.target/i386/sse-12.c
index 51de357cc97..88a7613e043 100644
--- a/gcc/testsuite/gcc.target/i386/sse-12.c
+++ b/gcc/testsuite/gcc.target/i386/sse-12.c
@@ -3,7 +3,7 @@
popcntintrin.h and mm_malloc.h are usable
with -O -std=c89 -pedantic-errors. */
/* { dg-do compile } */
-/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1" } */
+/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt" } */
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/sse-13.c b/gcc/testsuite/gcc.target/i386/sse-13.c
index 171e242382e..de54a45a2e0 100644
--- a/gcc/testsuite/gcc.target/i386/sse-13.c
+++ b/gcc/testsuite/gcc.target/i386/sse-13.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1" } */
+/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt" } */
#include <mm_malloc.h>
diff --git a/gcc/testsuite/gcc.target/i386/sse-14.c b/gcc/testsuite/gcc.target/i386/sse-14.c
index d9a5feddaea..2641b801a03 100644
--- a/gcc/testsuite/gcc.target/i386/sse-14.c
+++ b/gcc/testsuite/gcc.target/i386/sse-14.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1" } */
+/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt" } */
#include <mm_malloc.h>
diff --git a/gcc/testsuite/gcc.target/i386/sse-22.c b/gcc/testsuite/gcc.target/i386/sse-22.c
index e9f227a2a81..26b805d4a41 100644
--- a/gcc/testsuite/gcc.target/i386/sse-22.c
+++ b/gcc/testsuite/gcc.target/i386/sse-22.c
@@ -694,7 +694,7 @@ test_2 (_mm_clmulepi64_si128, __m128i, __m128i, __m128i, 1)
/* x86intrin.h (FMA4/XOP/LWP/BMI/BMI2/TBM/LZCNT/FMA). */
#ifdef DIFFERENT_PRAGMAS
-#pragma GCC target ("fma4,xop,lwp,bmi,bmi2,tbm,lzcnt,fma,rdseed,prfchw,adx,fxsr,xsaveopt")
+#pragma GCC target ("fma4,xop,lwp,bmi,bmi2,tbm,lzcnt,fma,rdseed,prfchw,adx,fxsr,xsaveopt,xsavec,xsaves,clflushopt")
#endif
#include <x86intrin.h>
/* xopintrin.h */
diff --git a/gcc/testsuite/gcc.target/i386/sse-23.c b/gcc/testsuite/gcc.target/i386/sse-23.c
index d227babb8cb..fe61e17df97 100644
--- a/gcc/testsuite/gcc.target/i386/sse-23.c
+++ b/gcc/testsuite/gcc.target/i386/sse-23.c
@@ -385,7 +385,7 @@
/* shaintrin.h */
#define __builtin_ia32_sha1rnds4(A, B, C) __builtin_ia32_sha1rnds4(A, B, 1)
-#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,fma,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1")
+#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,fma,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,xsavec,xsaves,clflushopt")
#include <wmmintrin.h>
#include <smmintrin.h>
#include <mm3dnow.h>
diff --git a/gcc/testsuite/gcc.target/i386/ssp-strong-reg.c b/gcc/testsuite/gcc.target/i386/ssp-strong-reg.c
new file mode 100644
index 00000000000..9fe56641b9e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ssp-strong-reg.c
@@ -0,0 +1,19 @@
+/* Test that structs returned in registers do not lead to
+ instrumentation with -fstack-protector-strong. */
+
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-options "-O2 -fstack-protector-strong" } */
+
+struct S {
+ int a;
+ int b;
+};
+
+struct S f (void);
+
+int g (void)
+{
+ return f ().a;
+}
+
+/* { dg-final { scan-assembler-times "stack_chk_fail" 0 } } */
diff --git a/gcc/testsuite/gcc.target/i386/vectorize1.c b/gcc/testsuite/gcc.target/i386/vectorize1.c
index f673e44c963..974ffd82628 100644
--- a/gcc/testsuite/gcc.target/i386/vectorize1.c
+++ b/gcc/testsuite/gcc.target/i386/vectorize1.c
@@ -10,6 +10,7 @@ typedef struct
int set_names (void)
{
+ __attribute__ ((used))
static tx_typ tt1;
int ln;
for (ln = 0; ln < 8; ln++)
diff --git a/gcc/testsuite/gcc.target/i386/xop-imul32widen-vector.c b/gcc/testsuite/gcc.target/i386/xop-imul32widen-vector.c
index 0730987e1a6..94a40595648 100644
--- a/gcc/testsuite/gcc.target/i386/xop-imul32widen-vector.c
+++ b/gcc/testsuite/gcc.target/i386/xop-imul32widen-vector.c
@@ -3,7 +3,7 @@
/* { dg-do compile } */
/* { dg-require-effective-target lp64 } */
-/* { dg-options "-O2 -mxop -ftree-vectorize" } */
+/* { dg-options "-O2 -mxop -mno-avx2 -ftree-vectorize" } */
extern void exit (int);
diff --git a/gcc/testsuite/gcc.target/i386/xop-imul64-vector.c b/gcc/testsuite/gcc.target/i386/xop-imul64-vector.c
index 382677e6050..fbf605f31ec 100644
--- a/gcc/testsuite/gcc.target/i386/xop-imul64-vector.c
+++ b/gcc/testsuite/gcc.target/i386/xop-imul64-vector.c
@@ -3,7 +3,7 @@
/* { dg-do compile } */
/* { dg-require-effective-target lp64 } */
-/* { dg-options "-O2 -mxop -ftree-vectorize" } */
+/* { dg-options "-O2 -mxop -mno-avx2 -ftree-vectorize" } */
extern void exit (int);
diff --git a/gcc/testsuite/gcc.target/i386/xop-rotate1-vector.c b/gcc/testsuite/gcc.target/i386/xop-rotate1-vector.c
index f2b9eb8455d..a6d88fb4fb4 100644
--- a/gcc/testsuite/gcc.target/i386/xop-rotate1-vector.c
+++ b/gcc/testsuite/gcc.target/i386/xop-rotate1-vector.c
@@ -2,7 +2,7 @@
into prot on XOP systems. */
/* { dg-do compile { target { ! { ia32 } } } } */
-/* { dg-options "-O2 -mxop -ftree-vectorize" } */
+/* { dg-options "-O2 -mxop -mno-avx2 -ftree-vectorize" } */
extern void exit (int);
diff --git a/gcc/testsuite/gcc.target/i386/xop-rotate2-vector.c b/gcc/testsuite/gcc.target/i386/xop-rotate2-vector.c
index 11d40023f87..11435a72a34 100644
--- a/gcc/testsuite/gcc.target/i386/xop-rotate2-vector.c
+++ b/gcc/testsuite/gcc.target/i386/xop-rotate2-vector.c
@@ -2,7 +2,7 @@
into prot on XOP systems. */
/* { dg-do compile { target { ! { ia32 } } } } */
-/* { dg-options "-O2 -mxop -ftree-vectorize" } */
+/* { dg-options "-O2 -mxop -mno-avx2 -ftree-vectorize" } */
extern void exit (int);
diff --git a/gcc/testsuite/gcc.target/i386/xop-rotate3-vector.c b/gcc/testsuite/gcc.target/i386/xop-rotate3-vector.c
index eb3c6143159..af324c5c9c3 100644
--- a/gcc/testsuite/gcc.target/i386/xop-rotate3-vector.c
+++ b/gcc/testsuite/gcc.target/i386/xop-rotate3-vector.c
@@ -2,7 +2,7 @@
into prot on XOP systems. */
/* { dg-do compile { target { ! { ia32 } } } } */
-/* { dg-options "-O2 -mxop -ftree-vectorize" } */
+/* { dg-options "-O2 -mxop -mno-avx2 -ftree-vectorize" } */
extern void exit (int);
diff --git a/gcc/testsuite/gcc.target/i386/xop-shift1-vector.c b/gcc/testsuite/gcc.target/i386/xop-shift1-vector.c
index 16b3a6b7556..12e1caf7ae4 100644
--- a/gcc/testsuite/gcc.target/i386/xop-shift1-vector.c
+++ b/gcc/testsuite/gcc.target/i386/xop-shift1-vector.c
@@ -2,7 +2,7 @@
psha/pshl on XOP systems. */
/* { dg-do compile { target { ! { ia32 } } } } */
-/* { dg-options "-O2 -mxop -ftree-vectorize" } */
+/* { dg-options "-O2 -mxop -mno-avx2 -ftree-vectorize" } */
extern void exit (int);
diff --git a/gcc/testsuite/gcc.target/i386/xop-shift2-vector.c b/gcc/testsuite/gcc.target/i386/xop-shift2-vector.c
index 1f1ed630ee9..5533721f1d9 100644
--- a/gcc/testsuite/gcc.target/i386/xop-shift2-vector.c
+++ b/gcc/testsuite/gcc.target/i386/xop-shift2-vector.c
@@ -2,7 +2,7 @@
psha/pshl on XOP systems. */
/* { dg-do compile { target { ! { ia32 } } } } */
-/* { dg-options "-O2 -mxop -ftree-vectorize" } */
+/* { dg-options "-O2 -mxop -mno-avx2 -ftree-vectorize" } */
extern void exit (int);
diff --git a/gcc/testsuite/gcc.target/i386/xop-shift3-vector.c b/gcc/testsuite/gcc.target/i386/xop-shift3-vector.c
index de6417876ea..e12edcefba3 100644
--- a/gcc/testsuite/gcc.target/i386/xop-shift3-vector.c
+++ b/gcc/testsuite/gcc.target/i386/xop-shift3-vector.c
@@ -2,7 +2,7 @@
psha/pshl on XOP systems. */
/* { dg-do compile { target { ! { ia32 } } } } */
-/* { dg-options "-O2 -mxop -ftree-vectorize" } */
+/* { dg-options "-O2 -mxop -mno-avx2 -ftree-vectorize" } */
extern void exit (int);
diff --git a/gcc/testsuite/gcc.target/i386/xsavec-1.c b/gcc/testsuite/gcc.target/i386/xsavec-1.c
new file mode 100644
index 00000000000..3be71b8b04e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xsavec-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mxsavec" } */
+/* { dg-final { scan-assembler "xsavec\[ \\t\]" } } */
+
+#include "x86intrin.h"
+
+void
+test_xsavec (void *__A, long long __B)
+{
+ _xsavec (__A, __B);
+}
diff --git a/gcc/testsuite/gcc.target/i386/xsavec64-1.c b/gcc/testsuite/gcc.target/i386/xsavec64-1.c
new file mode 100644
index 00000000000..5d4faff6fe0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xsavec64-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mxsavec" } */
+/* { dg-final { scan-assembler "xsavec64\[ \\t\]" } } */
+
+#include "x86intrin.h"
+
+void
+test_xsavec (void *__A, long long __B)
+{
+ _xsavec64 (__A, __B);
+}
diff --git a/gcc/testsuite/gcc.target/i386/xsaves-1.c b/gcc/testsuite/gcc.target/i386/xsaves-1.c
new file mode 100644
index 00000000000..05ff765489d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xsaves-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mxsaves" } */
+/* { dg-final { scan-assembler "xsaves\[ \\t\]" } } */
+/* { dg-final { scan-assembler "xrstors\[ \\t\]" } } */
+
+#include "x86intrin.h"
+
+void
+test_xsaves (void *__A, long long __B)
+{
+ _xsaves (__A, __B);
+ _xrstors (__A, __B);
+}
diff --git a/gcc/testsuite/gcc.target/i386/xsaves64-1.c b/gcc/testsuite/gcc.target/i386/xsaves64-1.c
new file mode 100644
index 00000000000..a3725d2d6c2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xsaves64-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mxsaves" } */
+/* { dg-final { scan-assembler "xsaves64\[ \\t\]" } } */
+/* { dg-final { scan-assembler "xrstors64\[ \\t\]" } } */
+
+#include "x86intrin.h"
+
+void
+test_xsaves (void *__A, long long __B)
+{
+ _xsaves64 (__A, __B);
+ _xrstors64 (__A, __B);
+}
diff --git a/gcc/testsuite/gcc.target/ia64/visibility-1.c b/gcc/testsuite/gcc.target/ia64/visibility-1.c
index fdccab3c750..8a7a43f9a3a 100644
--- a/gcc/testsuite/gcc.target/ia64/visibility-1.c
+++ b/gcc/testsuite/gcc.target/ia64/visibility-1.c
@@ -11,11 +11,11 @@
/* { dg-final { scan-assembler "gprel.*variable_m" } } */
/* { dg-final { scan-assembler "ltoff.*variable_n" } } */
-static int variable_i;
+static int variable_i __attribute__ ((used));
int variable_j __attribute__((visibility ("hidden")));
int variable_k;
struct A { char a[64]; };
-static struct A variable_l __attribute__((section (".sbss")));
+static struct A variable_l __attribute__((used, section (".sbss")));
struct A variable_m __attribute__((visibility ("hidden"), section(".sbss")));
struct A variable_n __attribute__((section (".sbss")));
diff --git a/gcc/testsuite/gcc.target/microblaze/others/break_handler.c b/gcc/testsuite/gcc.target/microblaze/others/break_handler.c
new file mode 100644
index 00000000000..1ccafd06408
--- /dev/null
+++ b/gcc/testsuite/gcc.target/microblaze/others/break_handler.c
@@ -0,0 +1,15 @@
+int func () __attribute__ ((break_handler));
+volatile int intr_occurred;
+
+int func ()
+{
+
+ /* { dg-final { scan-assembler "rtbd\tr(\[0-9]\|\[1-2]\[0-9]\|3\[0-1]),8" } } */
+ intr_occurred += 1;
+}
+int main()
+{
+ /* { dg-final { scan-assembler "brki\tr16" } } */
+ func();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/mips/fuse-caller-save-micromips.c b/gcc/testsuite/gcc.target/mips/fuse-caller-save-micromips.c
new file mode 100644
index 00000000000..6ad01c7b389
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/fuse-caller-save-micromips.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fuse-caller-save (-mmicromips)" } */
+/* At -O0 and -O1, the register allocator behaves more conservatively, and
+ the fuse-caller-save optimization doesnt' trigger. */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" } } */
+/* Testing -fuse-caller-save optimization option. */
+
+#define ATTRIBUTE MICROMIPS
+#include "fuse-caller-save.h"
+
+/* Check that there are only 2 stack-saves: r31 in main and foo. */
+
+/* Check that there only 2 sw/sd. */
+/* { dg-final { scan-assembler-times "(?n)s\[wd\]\t\\\$.*,.*\\(\\\$sp\\)" 2 } } */
+
+/* Check that the first caller-save register is unused. */
+/* { dg-final { scan-assembler-not "\\\$16" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fuse-caller-save-mips16.c b/gcc/testsuite/gcc.target/mips/fuse-caller-save-mips16.c
new file mode 100644
index 00000000000..a7c6cf4a047
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/fuse-caller-save-mips16.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fuse-caller-save (-mips16)" } */
+/* At -O0 and -O1, the register allocator behaves more conservatively, and
+ the fuse-caller-save optimization doesnt' trigger. */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" } } */
+/* Testing -fuse-caller-save optimization option. */
+
+#define ATTRIBUTE MIPS16
+#include "fuse-caller-save.h"
+
+/* Check that there are only 2 stack-saves: r31 in main and foo. */
+
+/* Check that there only 2 sw/sd. */
+/* { dg-final { scan-assembler-times "(?n)s\[wd\]\t\\\$.*,.*\\(\\\$sp\\)" 2 } } */
+
+/* Check that the first caller-save register is unused. */
+/* { dg-final { scan-assembler-not "\\\$16" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fuse-caller-save.c b/gcc/testsuite/gcc.target/mips/fuse-caller-save.c
new file mode 100644
index 00000000000..72c08fe5cb3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/fuse-caller-save.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fuse-caller-save" } */
+/* At -O0 and -O1, the register allocator behaves more conservatively, and
+ the fuse-caller-save optimization doesnt' trigger. */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" } } */
+/* Testing -fuse-caller-save optimization option. */
+
+#define ATTRIBUTE NOCOMPRESSION
+#include "fuse-caller-save.h"
+
+/* Check that there are only 2 stack-saves: r31 in main and foo. */
+
+/* Check that there only 2 sw/sd. */
+/* { dg-final { scan-assembler-times "(?n)s\[wd\]\t\\\$.*,.*\\(\\\$sp\\)" 2 } } */
+
+/* Check that the first caller-save register is unused. */
+/* { dg-final { scan-assembler-not "\\\$16" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fuse-caller-save.h b/gcc/testsuite/gcc.target/mips/fuse-caller-save.h
new file mode 100644
index 00000000000..edf6039f9b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/fuse-caller-save.h
@@ -0,0 +1,17 @@
+static int __attribute__((noinline)) ATTRIBUTE
+bar (int x)
+{
+ return x + 3;
+}
+
+int __attribute__((noinline)) ATTRIBUTE
+foo (int y)
+{
+ return y + bar (y);
+}
+
+int ATTRIBUTE
+main (void)
+{
+ return !(foo (5) == 13);
+}
diff --git a/gcc/testsuite/gcc.target/mips/loongson-simd.c b/gcc/testsuite/gcc.target/mips/loongson-simd.c
index ae3565f4795..160da6be4d1 100644
--- a/gcc/testsuite/gcc.target/mips/loongson-simd.c
+++ b/gcc/testsuite/gcc.target/mips/loongson-simd.c
@@ -19,10 +19,10 @@ along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
/* { dg-do run } */
-/* loongson.h does not handle or check for MIPS16ness. There doesn't
- seem any good reason for it to, given that the Loongson processors
- do not support MIPS16. */
-/* { dg-options "isa=loongson -mhard-float -mno-mips16 -flax-vector-conversions" } */
+/* loongson.h does not handle or check for MIPS16ness or
+ microMIPSness. There doesn't seem any good reason for it to, given
+ that the Loongson processors do not support either. */
+/* { dg-options "isa=loongson -mhard-float -mno-micromips -mno-mips16 -flax-vector-conversions" } */
#include "loongson.h"
#include <stdio.h>
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp
index 8c72cff7223..6ad816098d1 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -305,6 +305,7 @@ foreach option {
tree-vectorize
unroll-all-loops
unroll-loops
+ use-caller-save
} {
lappend mips_option_groups $option "-f(no-|)$option"
}
diff --git a/gcc/testsuite/gcc.target/mips/near-far-1.c b/gcc/testsuite/gcc.target/mips/near-far-1.c
index ac0cc1ef79b..8806e930fc3 100644
--- a/gcc/testsuite/gcc.target/mips/near-far-1.c
+++ b/gcc/testsuite/gcc.target/mips/near-far-1.c
@@ -16,5 +16,5 @@ int test ()
/* { dg-final { scan-assembler-not "\tjal\tlong_call_func\n" } } */
/* { dg-final { scan-assembler-not "\tjal\tfar_func\n" } } */
-/* { dg-final { scan-assembler "\tjal\tnear_func\n" } } */
+/* { dg-final { scan-assembler "\tjal(|s)\tnear_func\n" } } */
/* { dg-final { scan-assembler-not "\tjal\tnormal_func\n" } } */
diff --git a/gcc/testsuite/gcc.target/mips/near-far-2.c b/gcc/testsuite/gcc.target/mips/near-far-2.c
index c954b444cb0..b4062a744cf 100644
--- a/gcc/testsuite/gcc.target/mips/near-far-2.c
+++ b/gcc/testsuite/gcc.target/mips/near-far-2.c
@@ -14,7 +14,7 @@ int test ()
+ normal_func ());
}
-/* { dg-final { scan-assembler-not "\tjal\tlong_call_func\n" } } */
-/* { dg-final { scan-assembler-not "\tjal\tfar_func\n" } } */
-/* { dg-final { scan-assembler "\tjal\tnear_func\n" } } */
-/* { dg-final { scan-assembler "\tjal\tnormal_func\n" } } */
+/* { dg-final { scan-assembler-not "\tjal(|s)\tlong_call_func\n" } } */
+/* { dg-final { scan-assembler-not "\tjal(|s)\tfar_func\n" } } */
+/* { dg-final { scan-assembler "\tjal(|s)\tnear_func\n" } } */
+/* { dg-final { scan-assembler "\tjal(|s)\tnormal_func\n" } } */
diff --git a/gcc/testsuite/gcc.target/mips/near-far-4.c b/gcc/testsuite/gcc.target/mips/near-far-4.c
index 0ea07b06205..969f68f3811 100644
--- a/gcc/testsuite/gcc.target/mips/near-far-4.c
+++ b/gcc/testsuite/gcc.target/mips/near-far-4.c
@@ -13,5 +13,5 @@ NOMIPS16 int test4 () { return normal_func (); }
/* { dg-final { scan-assembler-not "\tj\tlong_call_func\n" } } */
/* { dg-final { scan-assembler-not "\tj\tfar_func\n" } } */
-/* { dg-final { scan-assembler "\tj(|al)\tnear_func\n" } } */
-/* { dg-final { scan-assembler "\tj(|al)\tnormal_func\n" } } */
+/* { dg-final { scan-assembler "\tj(|al|als)\tnear_func\n" } } */
+/* { dg-final { scan-assembler "\tj(|al|als)\tnormal_func\n" } } */
diff --git a/gcc/testsuite/gcc.target/nios2/custom-fp-lto.c b/gcc/testsuite/gcc.target/nios2/custom-fp-lto.c
new file mode 100644
index 00000000000..c7c04ffa18a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nios2/custom-fp-lto.c
@@ -0,0 +1,29 @@
+/* Test specification of custom instructions via pragma in the presence
+ of LTO. This test case formerly failed due to PR60179. */
+
+/* { dg-do link } */
+/* { dg-require-effective-target lto } */
+/* { dg-options "-O1 -flto -flto-partition=one -save-temps" } */
+
+/* -O1 in the options is significant. Without it FP operations may not be
+ optimized to custom instructions. */
+
+#include <stdio.h>
+#include <math.h>
+
+#pragma GCC target ("custom-fabss=224")
+
+float
+custom_fp (float operand_a)
+{
+ return fabsf (operand_a);
+}
+
+int
+main (int argc, char *argv[])
+{
+ return custom_fp ((float)argc) > 1.0;
+}
+
+/* { dg-final { scan-lto-assembler "custom\\t224, " } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/htm-ttest.c b/gcc/testsuite/gcc.target/powerpc/htm-ttest.c
new file mode 100644
index 00000000000..29cbd5b90b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/htm-ttest.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_htm_ok } */
+/* { dg-options "-O2 -mhtm" } */
+
+/* { dg-final { scan-assembler "rlwinm r?\[0-9\]+,r?\[0-9\]+,3,30,31" { target { ilp32 } } } } */
+/* { dg-final { scan-assembler "rldicl r?\[0-9\]+,r?\[0-9\]+,35,62" { target { lp64 } } } } */
+
+#include <htmintrin.h>
+long
+ttest (void)
+{
+ return _HTM_STATE(__builtin_ttest());
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pack03.c b/gcc/testsuite/gcc.target/powerpc/pack03.c
index bc582f232d6..dfaf2efa07e 100644
--- a/gcc/testsuite/gcc.target/powerpc/pack03.c
+++ b/gcc/testsuite/gcc.target/powerpc/pack03.c
@@ -1,7 +1,7 @@
/* { dg-do run { target { powerpc*-*-linux* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
-/* { dg-require-effective-target dfprt } */
+/* { dg-require-effective-target dfp_hw } */
/* { dg-options "-O2 -mhard-dfp" } */
#include <stddef.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/vsxcopy.c b/gcc/testsuite/gcc.target/powerpc/vsxcopy.c
new file mode 100644
index 00000000000..fc1f0bd387a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsxcopy.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target { powerpc64*-*-* } } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O1" } */
+/* { dg-final { scan-assembler "lxvd2x" } } */
+/* { dg-final { scan-assembler "stxvd2x" } } */
+/* { dg-final { scan-assembler-not "xxpermdi" } } */
+
+typedef float vecf __attribute__ ((vector_size (16)));
+extern vecf j, k;
+
+void fun (void)
+{
+ j = k;
+}
+
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-14.c b/gcc/testsuite/gcc.target/sh/pr51244-14.c
index 844eb3a5693..61a5dc93b28 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-14.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-14.c
@@ -8,11 +8,12 @@
tst r0,r0
bf/s .L35
where the negated T bit store did not combine properly. Since there are
- other movt insns we only check for the xor and the extu. */
+ other movt insns and the sequence will try to utilize the 'movt_movrt'
+ patterns, we only check for the extu. */
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
-/* { dg-final { scan-assembler-not "xor|extu" } } */
+/* { dg-final { scan-assembler-not "extu" } } */
typedef struct transaction_s transaction_t;
diff --git a/gcc/testsuite/gcc.target/sh/pr53976-1.c b/gcc/testsuite/gcc.target/sh/pr53976-1.c
index 4893b0668a5..68f8cdcc430 100644
--- a/gcc/testsuite/gcc.target/sh/pr53976-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr53976-1.c
@@ -24,14 +24,7 @@ test_01 (long long a, long long b)
}
int
-test_02 (const char* a)
-{
- /* Must not see a sett after the inlined strlen. */
- return __builtin_strlen (a);
-}
-
-int
-test_03 (int a, int b, int c, int d)
+test_02 (int a, int b, int c, int d)
{
/* One of the blocks should have a sett and the other one should not. */
if (d > 4)
diff --git a/gcc/testsuite/gcc.target/sh/pr54236-3.c b/gcc/testsuite/gcc.target/sh/pr54236-3.c
new file mode 100644
index 00000000000..fc0d111a9e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/pr54236-3.c
@@ -0,0 +1,31 @@
+/* Tests to check the utilization of the addc and subc instructions.
+ If everything works as expected we won't see any movt instructions in
+ these cases. */
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
+/* { dg-final { scan-assembler-times "addc" 1 } } */
+/* { dg-final { scan-assembler-times "subc" 1 } } */
+/* { dg-final { scan-assembler-not "movt" } } */
+
+int
+test_000 (int* x, unsigned int c)
+{
+ /* 1x addc */
+ int s = 0;
+ unsigned int i;
+ for (i = 0; i < c; ++i)
+ s += ! (x[i] & 0x3000);
+ return s;
+}
+
+int
+test_001 (int* x, unsigned int c)
+{
+ /* 1x subc */
+ int s = 0;
+ unsigned int i;
+ for (i = 0; i < c; ++i)
+ s -= ! (x[i] & 0x3000);
+ return s;
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr61195.c b/gcc/testsuite/gcc.target/sh/pr61195.c
new file mode 100644
index 00000000000..f3fb10b7bf4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/pr61195.c
@@ -0,0 +1,19 @@
+/* Verify that we don't switch mode for single moves. */
+/* { dg-do compile } */
+/* { dg-require-effective-target hard_float } */
+/* { dg-skip-if "" { *-*-* } { "mfmovd" } { "" } } */
+/* { dg-final { scan-assembler-not "fpscr" } } */
+
+float *g;
+
+float
+foo(float f)
+{
+ return f;
+}
+
+float
+foo1(void)
+{
+ return *g;
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx/abi-avx.exp b/gcc/testsuite/gcc.target/x86_64/abi/avx/abi-avx.exp
index d6fc1874f18..624b7ea75f2 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/avx/abi-avx.exp
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx/abi-avx.exp
@@ -20,6 +20,7 @@
load_lib c-torture.exp
load_lib target-supports.exp
load_lib torture-options.exp
+load_lib clearcap.exp
if { (![istarget x86_64-*-*] && ![istarget i?86-*-*])
|| ![is-effective-target lp64]
@@ -28,20 +29,10 @@ if { (![istarget x86_64-*-*] && ![istarget i?86-*-*])
}
-# If the linker used understands -M <mapfile>, pass it to clear hardware
-# capabilities set by the Sun assembler.
-set flags ""
-set clearcap_ldflags "-Wl,-M,$srcdir/gcc.target/i386/clearcap.map"
-
-if [check_no_compiler_messages mapfile executable {
- int main (void) { return 0; }
- } $clearcap_ldflags ] {
- set flags $clearcap_ldflags
-}
-
torture-init
+clearcap-init
set-torture-options $C_TORTURE_OPTIONS
-set additional_flags "-W -Wall -mavx $flags"
+set additional_flags "-W -Wall -mavx"
foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
if {[runtest_file_p $runtests $src]} {
@@ -58,4 +49,5 @@ foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
}
}
+clearcap-finish
torture-finish
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512f/abi-avx512f.exp b/gcc/testsuite/gcc.target/x86_64/abi/avx512f/abi-avx512f.exp
index cef6fa14154..f8f991e9276 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/avx512f/abi-avx512f.exp
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512f/abi-avx512f.exp
@@ -20,6 +20,7 @@
load_lib c-torture.exp
load_lib target-supports.exp
load_lib torture-options.exp
+load_lib clearcap.exp
if { (![istarget x86_64-*-*] && ![istarget i?86-*-*])
|| ![is-effective-target lp64]
@@ -28,20 +29,10 @@ if { (![istarget x86_64-*-*] && ![istarget i?86-*-*])
}
-# If the linker used understands -M <mapfile>, pass it to clear hardware
-# capabilities set by the Sun assembler.
-set flags ""
-set clearcap_ldflags "-Wl,-M,$srcdir/gcc.target/i386/clearcap.map"
-
-if [check_no_compiler_messages mapfile executable {
- int main (void) { return 0; }
- } $clearcap_ldflags ] {
- set flags $clearcap_ldflags
-}
-
torture-init
+clearcap-init
set-torture-options $C_TORTURE_OPTIONS
-set additional_flags "-W -Wall -mavx512f $flags"
+set additional_flags "-W -Wall -mavx512f"
foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
if {[runtest_file_p $runtests $src]} {
@@ -58,4 +49,5 @@ foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
}
}
+clearcap-finish
torture-finish
diff --git a/gcc/testsuite/gfortran.dg/arrayio_14.f90 b/gcc/testsuite/gfortran.dg/arrayio_14.f90
new file mode 100644
index 00000000000..3d878c75644
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/arrayio_14.f90
@@ -0,0 +1,18 @@
+! { dg-do run }
+! PR61173.f90 Bogus END condition
+module bd
+ character(len=25, kind=1), dimension(:), allocatable, save :: source
+ contains
+ subroutine init_data
+ allocate(source(2))
+ source=[" 1 1 1 ", " 4 4 4 "]
+ end subroutine init_data
+end module bd
+program read_internal
+ use bd
+ integer :: x(6),i
+
+ call init_data
+ read(source,*) (x(i), i=1,6)
+ if (any(x/=[1,1,1,4,4,4])) call abort
+end program read_internal
diff --git a/gcc/testsuite/gfortran.dg/associate_16.f90 b/gcc/testsuite/gfortran.dg/associate_16.f90
new file mode 100644
index 00000000000..9129388b25b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/associate_16.f90
@@ -0,0 +1,23 @@
+! { dg-do compile }
+! PR 60834 - this used to ICE.
+
+module m
+ implicit none
+ type :: t
+ real :: diffusion=1.
+ end type
+contains
+ subroutine solve(this, x)
+ class(t), intent(in) :: this
+ real, intent(in) :: x(:)
+ integer :: i
+ integer, parameter :: n(1:5)=[(i,i=1, 5)]
+
+ associate( nu=>this%diffusion)
+ associate( exponential=>exp(-(x(i)-n) ))
+ do i = 1, size(x)
+ end do
+ end associate
+ end associate
+ end subroutine solve
+end module m
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_5.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_5.f90
index a7949969b90..f3d633d12ab 100644
--- a/gcc/testsuite/gfortran.dg/assumed_rank_5.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_5.f90
@@ -5,5 +5,5 @@
!
!
subroutine foo(x)
- integer :: x(..) ! { dg-error "TS 29113: Assumed-rank array" }
+ integer :: x(..) ! { dg-error "TS 29113/TS 18508: Assumed-rank array" }
end subroutine foo
diff --git a/gcc/testsuite/gfortran.dg/assumed_type_4.f90 b/gcc/testsuite/gfortran.dg/assumed_type_4.f90
index 1ea982e9add..e940c454039 100644
--- a/gcc/testsuite/gfortran.dg/assumed_type_4.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_type_4.f90
@@ -6,5 +6,5 @@
! Test TYPE(*)
subroutine one(a)
- type(*) :: a ! { dg-error "TS 29113: Assumed type" }
+ type(*) :: a ! { dg-error "TS 29113/TS 18508: Assumed type" }
end subroutine one
diff --git a/gcc/testsuite/gfortran.dg/bind_c_array_params.f03 b/gcc/testsuite/gfortran.dg/bind_c_array_params.f03
index 0e9903c6390..16045170bf8 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_array_params.f03
+++ b/gcc/testsuite/gfortran.dg/bind_c_array_params.f03
@@ -5,11 +5,11 @@ use, intrinsic :: iso_c_binding
implicit none
contains
- subroutine sub0(assumed_array) bind(c) ! { dg-error "TS 29113: Assumed-shape array 'assumed_array' at .1. as dummy argument to the BIND.C. procedure 'sub0'" }
+ subroutine sub0(assumed_array) bind(c) ! { dg-error "TS 29113/TS 18508: Assumed-shape array 'assumed_array' at .1. as dummy argument to the BIND.C. procedure 'sub0'" }
integer(c_int), dimension(:) :: assumed_array
end subroutine sub0
- subroutine sub1(deferred_array) bind(c) ! { dg-error "TS 29113: Variable 'deferred_array' at .1. with POINTER attribute in procedure 'sub1' with BIND.C." }
+ subroutine sub1(deferred_array) bind(c) ! { dg-error "TS 29113/TS 18508: Variable 'deferred_array' at .1. with POINTER attribute in procedure 'sub1' with BIND.C." }
integer(c_int), pointer :: deferred_array(:)
end subroutine sub1
end module bind_c_array_params
diff --git a/gcc/testsuite/gfortran.dg/bind_c_array_params_2.f90 b/gcc/testsuite/gfortran.dg/bind_c_array_params_2.f90
index 54c95cf7791..85ca709200f 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_array_params_2.f90
+++ b/gcc/testsuite/gfortran.dg/bind_c_array_params_2.f90
@@ -16,7 +16,7 @@ integer :: aa(4,4)
call test(aa)
end
-! { dg-final { scan-assembler-times "myBindC" 1 { target { ! { hppa*-*-hpux* } } } } }
-! { dg-final { scan-assembler-times "myBindC,%r2" 1 { target { hppa*-*-hpux* } } } }
+! { dg-final { scan-assembler-times "call\[^\n\r\]*myBindC" 1 { target { ! { hppa*-*-hpux* } } } } }
+! { dg-final { scan-assembler-times "call\[^\n\r\]*myBindC,%r2" 1 { target { hppa*-*-hpux* } } } }
! { dg-final { scan-tree-dump-times "test \\\(&parm\\." 1 "original" } }
! { dg-final { cleanup-tree-dump "original" } }
diff --git a/gcc/testsuite/gfortran.dg/bind_c_usage_28.f90 b/gcc/testsuite/gfortran.dg/bind_c_usage_28.f90
index ff03ef48f17..bb9b5e85f7d 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_usage_28.f90
+++ b/gcc/testsuite/gfortran.dg/bind_c_usage_28.f90
@@ -8,11 +8,11 @@ type, bind(C) :: cstruct
integer :: i
end type
interface
- subroutine psub(this) bind(c, name='Psub') ! { dg-error "TS 29113: Variable 'this' at .1. with POINTER attribute in procedure 'psub' with BIND.C." }
+ subroutine psub(this) bind(c, name='Psub') ! { dg-error "TS 29113/TS 18508: Variable 'this' at .1. with POINTER attribute in procedure 'psub' with BIND.C." }
import :: c_float, cstruct
real(c_float), pointer :: this(:)
end subroutine psub
- subroutine psub2(that) bind(c, name='Psub2') ! { dg-error "TS 29113: Variable 'that' at .1. with ALLOCATABLE attribute in procedure 'psub2' with BIND.C." }
+ subroutine psub2(that) bind(c, name='Psub2') ! { dg-error "TS 29113/TS 18508: Variable 'that' at .1. with ALLOCATABLE attribute in procedure 'psub2' with BIND.C." }
import :: c_float, cstruct
type(cstruct), allocatable :: that(:)
end subroutine psub2
diff --git a/gcc/testsuite/gfortran.dg/c_funloc_tests_5.f03 b/gcc/testsuite/gfortran.dg/c_funloc_tests_5.f03
index ae321a998dc..8c1843bdf1d 100644
--- a/gcc/testsuite/gfortran.dg/c_funloc_tests_5.f03
+++ b/gcc/testsuite/gfortran.dg/c_funloc_tests_5.f03
@@ -8,9 +8,9 @@ contains
subroutine sub0() bind(c)
type(c_funptr) :: my_c_funptr
- my_c_funptr = c_funloc(sub1) ! { dg-error "TS 29113: Noninteroperable procedure at .1. to C_FUNLOC" }
+ my_c_funptr = c_funloc(sub1) ! { dg-error "TS 29113/TS 18508: Noninteroperable procedure at .1. to C_FUNLOC" }
- my_c_funptr = c_funloc(func0) ! { dg-error "TS 29113: Noninteroperable procedure at .1. to C_FUNLOC" }
+ my_c_funptr = c_funloc(func0) ! { dg-error "TS 29113/TS 18508: Noninteroperable procedure at .1. to C_FUNLOC" }
end subroutine sub0
subroutine sub1()
diff --git a/gcc/testsuite/gfortran.dg/c_funloc_tests_6.f90 b/gcc/testsuite/gfortran.dg/c_funloc_tests_6.f90
index 1a7f0362d16..d426e81a862 100644
--- a/gcc/testsuite/gfortran.dg/c_funloc_tests_6.f90
+++ b/gcc/testsuite/gfortran.dg/c_funloc_tests_6.f90
@@ -26,6 +26,6 @@ cfp = c_loc (int) ! { dg-error "Can't convert TYPE.c_ptr. to TYPE.c_funptr." }
call c_f_pointer (cfp, int) ! { dg-error "Argument CPTR at .1. to C_F_POINTER shall have the type TYPE.C_PTR." }
call c_f_procpointer (cp, fsub) ! { dg-error "Argument CPTR at .1. to C_F_PROCPOINTER shall have the type TYPE.C_FUNPTR." }
-cfp = c_funloc (noCsub) ! { dg-error "TS 29113: Noninteroperable procedure at .1. to C_FUNLOC" }
-call c_f_procpointer (cfp, fint) ! { dg-error "TS 29113: Noninteroperable procedure pointer at .1. to C_F_PROCPOINTER" }
+cfp = c_funloc (noCsub) ! { dg-error "TS 29113/TS 18508: Noninteroperable procedure at .1. to C_FUNLOC" }
+call c_f_procpointer (cfp, fint) ! { dg-error "TS 29113/TS 18508: Noninteroperable procedure pointer at .1. to C_F_PROCPOINTER" }
end
diff --git a/gcc/testsuite/gfortran.dg/c_loc_tests_11.f03 b/gcc/testsuite/gfortran.dg/c_loc_tests_11.f03
index c00e5ed1640..d009ce09652 100644
--- a/gcc/testsuite/gfortran.dg/c_loc_tests_11.f03
+++ b/gcc/testsuite/gfortran.dg/c_loc_tests_11.f03
@@ -43,7 +43,7 @@ contains
integer(c_int), intent(in) :: handle
get_foo_address = c_loc(foo_pool(handle)%v)
- get_foo_address = c_loc(foo_pool2(handle)%v) ! { dg-error "TS 29113: Noninteroperable array at .1. as argument to C_LOC: Expression is a noninteroperable derived type" }
+ get_foo_address = c_loc(foo_pool2(handle)%v) ! { dg-error "TS 29113/TS 18508: Noninteroperable array at .1. as argument to C_LOC: Expression is a noninteroperable derived type" }
end function get_foo_address
diff --git a/gcc/testsuite/gfortran.dg/coarray/collectives_1.f90 b/gcc/testsuite/gfortran.dg/coarray/collectives_1.f90
new file mode 100644
index 00000000000..14049389167
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray/collectives_1.f90
@@ -0,0 +1,44 @@
+! { dg-do run }
+!
+! CO_SUM/CO_MIN/CO_MAX
+!
+program test
+ implicit none
+ intrinsic co_max
+ intrinsic co_min
+ intrinsic co_sum
+ call test_min
+ call test_max
+ call test_sum
+contains
+ subroutine test_min
+ integer :: val
+ val = this_image ()
+ call co_max (val, result_image=1)
+ if (this_image() == 1) then
+ !write(*,*) "Maximal value", val
+ if (val /= num_images()) call abort()
+ end if
+ end subroutine test_min
+
+ subroutine test_max
+ integer :: val
+ val = this_image ()
+ call co_min (val, result_image=1)
+ if (this_image() == 1) then
+ !write(*,*) "Minimal value", val
+ if (val /= 1) call abort()
+ end if
+ end subroutine test_max
+
+ subroutine test_sum
+ integer :: val, n
+ val = this_image ()
+ call co_sum (val, result_image=1)
+ if (this_image() == 1) then
+ !write(*,*) "The sum is ", val
+ n = num_images()
+ if (val /= (n**2 + n)/2) call abort()
+ end if
+ end subroutine test_sum
+end program test
diff --git a/gcc/testsuite/gfortran.dg/coarray_10.f90 b/gcc/testsuite/gfortran.dg/coarray_10.f90
index 78abb5ad191..53917b58ff3 100644
--- a/gcc/testsuite/gfortran.dg/coarray_10.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_10.f90
@@ -21,7 +21,7 @@ subroutine this_image_check()
integer,save :: z(4)[*], i
j = this_image(a,dim=3) ! { dg-error "not a valid codimension index" }
- j = this_image(dim=3) ! { dg-error "DIM argument without ARRAY argument" }
+ j = this_image(dim=3) ! { dg-error "DIM argument without COARRAY argument" }
i = image_index(i, [ 1 ]) ! { dg-error "Expected coarray variable" }
i = image_index(z, 2) ! { dg-error "must be a rank one array" }
end subroutine this_image_check
diff --git a/gcc/testsuite/gfortran.dg/coarray_collectives_1.f90 b/gcc/testsuite/gfortran.dg/coarray_collectives_1.f90
new file mode 100644
index 00000000000..a09a81f6b1d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_collectives_1.f90
@@ -0,0 +1,38 @@
+! { dg-do compile }
+! { dg-options "-fcoarray=single" }
+!
+!
+! CO_SUM/CO_MIN/CO_MAX
+!
+program test
+ implicit none
+ intrinsic co_max
+ intrinsic co_min
+ intrinsic co_sum
+ integer :: val, i
+ character(len=30) :: errmsg
+ integer(8) :: i8
+ character(len=19, kind=4) :: msg4
+
+ call co_sum("abc") ! { dg-error "must be a numeric type" }
+ call co_max(cmplx(1.0,0.0)) ! { dg-error "shall be of type integer, real or character" }
+ call co_min(cmplx(0.0,1.0)) ! { dg-error "shall be of type integer, real or character" }
+
+ call co_sum(1) ! { dg-error "must be a variable" }
+ call co_min("abc") ! { dg-error "must be a variable" }
+ call co_max(2.3) ! { dg-error "must be a variable" }
+
+ call co_sum(val, result_image=[1,2]) ! { dg-error "must be a scalar" }
+ call co_sum(val, result_image=1.0) ! { dg-error "must be INTEGER" }
+ call co_min(val, stat=[1,2]) ! { dg-error "must be a scalar" }
+ call co_min(val, stat=1.0) ! { dg-error "must be INTEGER" }
+ call co_min(val, stat=1) ! { dg-error "must be a variable" }
+ call co_min(val, stat=i, result_image=1) ! OK
+ call co_max(val, stat=i, errmsg=errmsg, result_image=1) ! OK
+ call co_max(val, stat=i, errmsg=[errmsg], result_image=1) ! { dg-error "must be a scalar" }
+ call co_max(val, stat=i, errmsg=5, result_image=1) ! { dg-error "must be CHARACTER" }
+ call co_sum(val, errmsg="abc") ! { dg-error "must be a variable" }
+
+ call co_sum(val, stat=i8) ! { dg-error "The stat= argument at .1. must be a kind=4 integer variable" }
+ call co_min(val, errmsg=msg4) ! { dg-error "The errmsg= argument at .1. must be a default-kind character variable" }
+end program test
diff --git a/gcc/testsuite/gfortran.dg/coarray_collectives_2.f90 b/gcc/testsuite/gfortran.dg/coarray_collectives_2.f90
new file mode 100644
index 00000000000..7494d3d4ada
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_collectives_2.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! { dg-options "-fcoarray=single -std=f2008" }
+!
+!
+! CO_SUM/CO_MIN/CO_MAX
+!
+program test
+ implicit none
+ intrinsic co_max ! { dg-error "is not available in the current standard settings but new in TS 29113/TS 18508." }
+ intrinsic co_min ! { dg-error "is not available in the current standard settings but new in TS 29113/TS 18508." }
+ intrinsic co_sum ! { dg-error "is not available in the current standard settings but new in TS 29113/TS 18508." }
+end program test
diff --git a/gcc/testsuite/gfortran.dg/coarray_collectives_3.f90 b/gcc/testsuite/gfortran.dg/coarray_collectives_3.f90
new file mode 100644
index 00000000000..971ee6ad170
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_collectives_3.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+!
+! CO_SUM/CO_MIN/CO_MAX
+!
+program test
+ implicit none
+ intrinsic co_max
+ integer :: val
+ call co_max(val) ! { dg-error "Coarrays disabled at .1., use -fcoarray= to enable" }
+end program test
diff --git a/gcc/testsuite/gfortran.dg/coarray_collectives_4.f90 b/gcc/testsuite/gfortran.dg/coarray_collectives_4.f90
new file mode 100644
index 00000000000..8b3da94642a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_collectives_4.f90
@@ -0,0 +1,20 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original -fcoarray=single" }
+!
+! CO_SUM/CO_MIN/CO_MAX
+!
+program test
+ implicit none
+ intrinsic co_max
+ integer :: stat1, stat2, stat3
+ real :: val
+ call co_max(val, stat=stat1)
+ call co_min(val, stat=stat2)
+ call co_sum(val, stat=stat3)
+end program test
+
+! { dg-final { scan-tree-dump-times "stat1 = 0;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "stat2 = 0;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "stat3 = 0;" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
+
diff --git a/gcc/testsuite/gfortran.dg/coarray_collectives_5.f90 b/gcc/testsuite/gfortran.dg/coarray_collectives_5.f90
new file mode 100644
index 00000000000..15894d28ad0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_collectives_5.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original -fcoarray=lib" }
+!
+! CO_SUM/CO_MIN/CO_MAX
+!
+program test
+ implicit none
+ intrinsic co_max
+ integer :: stat1, stat2, stat3
+ real :: val
+ call co_max(val, stat=stat1)
+ call co_min(val, stat=stat2)
+ call co_sum(val, stat=stat3)
+end program test
+
+! { dg-final { scan-tree-dump-times "_gfortran_caf_co_max \\(&desc.., 0B, 0, &stat1, 0B, 0, 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_co_min \\(&desc.., 0B, 0, &stat2, 0B, 0, 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_co_sum \\(&desc.., 0B, 0, &stat3, 0B, 0\\);" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray_collectives_6.f90 b/gcc/testsuite/gfortran.dg/coarray_collectives_6.f90
new file mode 100644
index 00000000000..630ce9d53f9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_collectives_6.f90
@@ -0,0 +1,26 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original -fcoarray=lib" }
+!
+! CO_SUM/CO_MIN/CO_MAX
+!
+program test
+ implicit none
+ intrinsic co_max
+ integer :: stat1, stat2, stat3
+ character(len=6) :: errmesg1
+ character(len=7) :: errmesg2
+ character(len=8) :: errmesg3
+ real :: val1
+ complex, allocatable :: val2(:)
+ character(len=99) :: val3
+ integer :: res
+
+ call co_max(val1, stat=stat1, errmsg=errmesg1)
+ call co_sum(val2, result_image=4, stat=stat2, errmsg=errmesg2)
+ call co_min(val3, result_image=res,stat=stat3, errmsg=errmesg3)
+end program test
+
+! { dg-final { scan-tree-dump-times "_gfortran_caf_co_max \\(&desc.., 0B, 0, &stat1, errmesg1, 0, 6\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_co_sum \\(&val2, 0B, 4, &stat2, errmesg2, 7\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_co_min \\(&desc.., 0B, res, &stat3, errmesg3, 99, 8\\);" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray_this_image_1.f90 b/gcc/testsuite/gfortran.dg/coarray_this_image_1.f90
new file mode 100644
index 00000000000..bbdbab7f236
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_this_image_1.f90
@@ -0,0 +1,20 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original -fcoarray=single" }
+!
+j1 = this_image(distance=4)
+j2 = this_image(5)
+k1 = num_images()
+k2 = num_images(6)
+k3 = num_images(distance=7)
+k4 = num_images(distance=8, failed=.true.)
+k5 = num_images(failed=.false.)
+end
+
+! { dg-final { scan-tree-dump-times "j1 = 1;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "j2 = 1;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "k1 = 1;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "k2 = 1;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "k3 = 1;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "k4 = 0;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "k5 = 1;" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray_this_image_2.f90 b/gcc/testsuite/gfortran.dg/coarray_this_image_2.f90
new file mode 100644
index 00000000000..35156baad7a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_this_image_2.f90
@@ -0,0 +1,20 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original -fcoarray=lib" }
+!
+j1 = this_image(distance=4)
+j2 = this_image(5)
+k1 = num_images()
+k2 = num_images(6)
+k3 = num_images(distance=7)
+k4 = num_images(distance=8, failed=.true.)
+k5 = num_images(failed=.false.)
+end
+
+! { dg-final { scan-tree-dump-times "j1 = _gfortran_caf_this_image \\(4\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "j2 = _gfortran_caf_this_image \\(5\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "k1 = _gfortran_caf_num_images \\(0, -1\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "k2 = _gfortran_caf_num_images \\(6, -1\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "k3 = _gfortran_caf_num_images \\(7, -1\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "k4 = _gfortran_caf_num_images \\(8, 1\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "k5 = _gfortran_caf_num_images \\(0, 0\\);" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/affinity-1.f90 b/gcc/testsuite/gfortran.dg/gomp/affinity-1.f90
new file mode 100644
index 00000000000..b6e20b9ce63
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/affinity-1.f90
@@ -0,0 +1,19 @@
+ integer :: i, j
+ integer, dimension (10, 10) :: a
+!$omp parallel do default(none)proc_bind(master)shared(a)
+ do i = 1, 10
+ j = 4
+ do j = 1, 10
+ a(i, j) = i + j
+ end do
+ j = 8
+ end do
+!$omp end parallel do
+!$omp parallel proc_bind (close)
+!$omp parallel default(none) proc_bind (spread) firstprivate(a) private (i)
+ do i = 1, 10
+ a(i, i) = i
+ enddo
+!$omp end parallel
+!$omp endparallel
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/omp_do_concurrent.f90 b/gcc/testsuite/gfortran.dg/gomp/omp_do_concurrent.f90
new file mode 100644
index 00000000000..83204791d95
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/omp_do_concurrent.f90
@@ -0,0 +1,13 @@
+! { dg-do compile }
+! { dg-options "-fopenmp" }
+!
+! PR fortran/60127
+!
+! OpenMP 4.0 doesn't permit DO CONCURRENT (yet)
+!
+
+!$omp do
+do concurrent(i=1:5) ! { dg-error "OMP DO cannot be a DO CONCURRENT loop" }
+print *, 'Hello'
+end do
+end
diff --git a/gcc/testsuite/gfortran.dg/namelist_85.f90 b/gcc/testsuite/gfortran.dg/namelist_85.f90
new file mode 100644
index 00000000000..17752856ad3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/namelist_85.f90
@@ -0,0 +1,66 @@
+! { dg-do run }
+! { dg-options -std=gnu }
+! PR55117 Programs fails namelist read (contains derived types objects)
+program test_type_extension
+
+ type tk_t
+ real :: x
+ end type tk_t
+
+ type, extends(tk_t) :: tke_t
+ character(8) :: string
+ end type tke_t
+
+ type, extends(tke_t) :: deep
+ integer :: int1
+ real :: y
+ character(10) :: the_name
+ end type deep
+
+ type other
+ integer :: one_oh
+ integer :: two_oh
+ end type other
+
+ type plain_type
+ integer :: var1
+ type(other) :: var2
+ real :: var3
+ end type plain_type
+
+ type some_other
+ complex :: varx
+ type(tke_t) :: tke
+ type (plain_type) :: varpy
+ real :: vary
+ end type some_other
+
+ type(deep) :: trouble
+ type(some_other) :: somethinelse
+ type(tke_t) :: tke
+ integer :: answer
+
+ namelist /test_NML/ trouble, somethinelse, tke, answer
+
+ tke%x = 0.0
+ tke%string = "xxxxxxxx"
+ answer = 5
+ trouble%x = 5.34
+ trouble%y = 4.25
+ trouble%string = "yyyy"
+ trouble%the_name = "mischief"
+
+ open(10, status="scratch")
+
+ write(10,*) "&TEST_NML"
+ write(10,*) "TKE%X= 3.14 ,"
+ write(10,*) "TKE%STRING='kf7rcc',"
+ write(10,*) "ANSWER= 42,"
+ write(10,*) "/"
+ rewind(10)
+
+ read(10,NML=test_NML)
+ if (tke%x - 3.14000010 > .00001) call abort
+ if (tke%string /= "kf7rcc") call abort
+ if (answer /= 42) call abort ! hitchkikers guide to the galaxy
+end program test_type_extension
diff --git a/gcc/testsuite/gfortran.dg/namelist_utf8.f90 b/gcc/testsuite/gfortran.dg/namelist_utf8.f90
index c494b8c3b77..6a9dde314ea 100644
--- a/gcc/testsuite/gfortran.dg/namelist_utf8.f90
+++ b/gcc/testsuite/gfortran.dg/namelist_utf8.f90
@@ -1,4 +1,4 @@
-! { dg-do run }
+! { dg-do run { xfail powerpc*-apple-darwin* } }
! PR52539 UTF-8 support for namelist read and write
character(len=10, kind=4) :: str, str2
@@ -6,9 +6,9 @@ character(len=25, kind=4) :: str3
namelist /nml/ str
-str = 4_'a'//char (int (z'4F60'),4) &
+str = 4_'1a'//char (int (z'4F60'),4) &
//char (int (z'597D'), 4)//4_'b'
-
+open(6, encoding='utf-8')
open(99, encoding='utf-8',form='formatted')
write(99, '(3a)') '&nml str = "', str, '" /'
write(99, '(a)') str
@@ -23,7 +23,7 @@ rewind(99)
read(99,'(A)') str3
if (str3 /= 4_'&nml str = "' // str // 4_'" /') call abort
-read(99,'(A)') str3
+read(99,*) str3
if (str3 /= str) call abort
close(99, status='delete')
diff --git a/gcc/testsuite/gfortran.dg/pr48636-2.f90 b/gcc/testsuite/gfortran.dg/pr48636-2.f90
index 75012c77502..bab77fa43b5 100644
--- a/gcc/testsuite/gfortran.dg/pr48636-2.f90
+++ b/gcc/testsuite/gfortran.dg/pr48636-2.f90
@@ -33,6 +33,6 @@ program main
print *,x
end program main
-! { dg-final { scan-ipa-dump "Creating a specialized node of bar/\[0-9\]*\\." "cp" } }
+! { dg-final { scan-ipa-dump "Creating a specialized node of \[^\n\r\]*bar/\[0-9\]*\\." "cp" } }
! { dg-final { scan-ipa-dump-times "Aggregate replacements\[^=\]*=\[^=\]*=\[^=\]*=\[^=\]*=\[^=\]*=\[^=\]*=\[^=\]*=\[^=\]*=\[^=\]*=" 2 "cp" } }
! { dg-final { cleanup-ipa-dump "cp" } }
diff --git a/gcc/testsuite/gfortran.dg/pr52835.f90 b/gcc/testsuite/gfortran.dg/pr52835.f90
index a72951ab6ee..3141b88b258 100644
--- a/gcc/testsuite/gfortran.dg/pr52835.f90
+++ b/gcc/testsuite/gfortran.dg/pr52835.f90
@@ -12,5 +12,5 @@ subroutine foo (x, y, z, n)
end do
end subroutine
-! { dg-final { scan-tree-dump "bar " "optimized" } }
+! { dg-final { scan-tree-dump "bar\[ _\]" "optimized" } }
! { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc/testsuite/gfortran.dg/pr61209.f90 b/gcc/testsuite/gfortran.dg/pr61209.f90
new file mode 100644
index 00000000000..481714daeee
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr61209.f90
@@ -0,0 +1,46 @@
+! { dg-do compile }
+! { dg-options "-O -fbounds-check" }
+MODULE array_types
+ INTERFACE array_data
+ MODULE PROCEDURE array_data_i1d
+ END INTERFACE
+ TYPE array_i1d_type
+ END TYPE array_i1d_type
+ TYPE array_i1d_obj
+ TYPE(array_i1d_type), POINTER :: low
+ END TYPE array_i1d_obj
+ TYPE dbcsr_type
+ TYPE(array_i1d_obj) :: local_rows
+ LOGICAL :: local_indexing
+ END TYPE dbcsr_type
+ TYPE dbcsr_obj
+ TYPE(dbcsr_type) :: m
+ END TYPE dbcsr_obj
+CONTAINS
+ FUNCTION array_data_i1d(array) RESULT (DATA)
+ TYPE(array_i1d_obj), INTENT(IN) :: array
+ INTEGER, DIMENSION(:), POINTER :: DATA
+ IF (ASSOCIATED (array%low)) THEN
+ ENDIF
+ END FUNCTION array_data_i1d
+ SUBROUTINE dbcsr_make_index_list (matrix, thread_redist)
+ TYPE(dbcsr_obj), INTENT(INOUT) :: matrix
+ LOGICAL, INTENT(IN) :: thread_redist
+ INTEGER, ALLOCATABLE, DIMENSION(:, :) :: blki
+ INTEGER, DIMENSION(:), POINTER :: local_rows, td
+ INTEGER :: blk
+ nthreads = 0
+ IF (nthreads .GT. 0 .AND. thread_redist) THEN
+ IF (matrix%m%local_indexing) THEN
+ local_rows => array_data (matrix%m%local_rows)
+ ENDIF
+ CALL dbcsr_build_row_index_inplace (thr_c, nthreads)
+ IF (matrix%m%local_indexing) THEN
+ DO blk = 1, nblks
+ IF (td(local_rows(blki(1, blk))) .EQ. ithread) THEN
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+ END SUBROUTINE dbcsr_make_index_list
+END MODULE
diff --git a/gcc/testsuite/gfortran.dg/pr61335.f90 b/gcc/testsuite/gfortran.dg/pr61335.f90
new file mode 100644
index 00000000000..7961f270515
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr61335.f90
@@ -0,0 +1,117 @@
+! { dg-do run }
+! { dg-additional-options "-fbounds-check" }
+MODULE cp_units
+
+ INTEGER, PARAMETER :: default_string_length=80, dp=KIND(0.0D0)
+
+ LOGICAL, PRIVATE, PARAMETER :: debug_this_module=.TRUE.
+ CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_units'
+ INTEGER, SAVE, PRIVATE :: last_unit_id=0, last_unit_set_id=0
+
+ INTEGER, PARAMETER, PUBLIC :: cp_unit_max_kinds=8, cp_unit_basic_desc_length=15,&
+ cp_unit_desc_length=cp_unit_max_kinds*cp_unit_basic_desc_length, cp_ukind_max=9
+
+CONTAINS
+
+ FUNCTION cp_to_string(i) RESULT(res)
+ INTEGER, INTENT(in) :: i
+ CHARACTER(len=6) :: res
+
+ INTEGER :: iostat
+ REAL(KIND=dp) :: tmp_r
+
+ IF (i>999999 .OR. i<-99999) THEN
+ tmp_r=i
+ WRITE (res,fmt='(es6.1)',iostat=iostat) tmp_r
+ ELSE
+ WRITE (res,fmt='(i6)',iostat=iostat) i
+ END IF
+ IF (iostat/=0) THEN
+ STOP 7
+ END IF
+ END FUNCTION cp_to_string
+
+ SUBROUTINE cp_unit_create(string)
+ CHARACTER(len=*), INTENT(in) :: string
+
+ CHARACTER(len=*), PARAMETER :: routineN = 'cp_unit_create', &
+ routineP = moduleN//':'//routineN
+
+ CHARACTER(default_string_length) :: desc
+ CHARACTER(LEN=40) :: formatstr
+ INTEGER :: i_high, i_low, i_unit, &
+ len_string, next_power
+ INTEGER, DIMENSION(cp_unit_max_kinds) :: kind_id, power, unit_id
+ LOGICAL :: failure
+
+ failure=.FALSE.
+ unit_id=cp_units_none
+ kind_id=cp_ukind_none
+ power=0
+ i_low=1
+ i_high=1
+ len_string=LEN(string)
+ i_unit=0
+ next_power=1
+ DO WHILE(i_low<len_string)
+ IF (string(i_low:i_low)/=' ') EXIT
+ i_low=i_low+1
+ END DO
+ i_high=i_low
+ DO WHILE(i_high<=len_string)
+ IF ( string(i_high:i_high)==' '.OR.string(i_high:i_high)=='^'.OR.&
+ string(i_high:i_high)=='*'.OR.string(i_high:i_high)=='/') EXIT
+ i_high=i_high+1
+ END DO
+ DO WHILE(.NOT.failure)
+ IF (i_high<=i_low.OR.i_low>len_string) EXIT
+ i_unit=i_unit+1
+ IF (i_unit>cp_unit_max_kinds) THEN
+ EXIT
+ END IF
+ power(i_unit)=next_power
+ ! parse op
+ i_low=i_high
+ DO WHILE(i_low<=len_string)
+ IF (string(i_low:i_low)/=' ') EXIT
+ i_low=i_low+1
+ END DO
+ i_high=i_low
+ DO WHILE(i_high<=len_string)
+ IF ( string(i_high:i_high)==' '.OR.string(i_high:i_high)=='^'.OR.&
+ string(i_high:i_high)=='*'.OR.string(i_high:i_high)=='/') EXIT
+ i_high=i_high+1
+ END DO
+ IF (i_high<i_low.OR.i_low>len_string) EXIT
+
+ IF (i_high<=len_string) THEN
+ IF (string(i_low:i_high)=='^') THEN
+ i_low=i_high+1
+ DO WHILE(i_low<=len_string)
+ IF (string(i_low:i_low)/=' ') EXIT
+ i_low=i_low+1
+ END DO
+ i_high=i_low
+ DO WHILE(i_high<=len_string)
+ SELECT CASE(string(i_high:i_high))
+ CASE('+','-','0','1','2','3','4','5','6','7','8','9')
+ i_high=i_high+1
+ CASE default
+ EXIT
+ END SELECT
+ END DO
+ IF (i_high<=i_low.OR.i_low>len_string) THEN
+ write(6,*) "BUG : XXX"//string//"XXX integer expected"
+ STOP 1
+ EXIT
+ END IF
+ END IF
+ ENDIF
+ END DO
+ END SUBROUTINE cp_unit_create
+
+END MODULE cp_units
+
+USE cp_units
+CALL cp_unit_create("fs^-1")
+END
diff --git a/gcc/testsuite/gnat.dg/aliasing1.adb b/gcc/testsuite/gnat.dg/aliasing1.adb
index b2b7d123b1f..bffc4225b47 100644
--- a/gcc/testsuite/gnat.dg/aliasing1.adb
+++ b/gcc/testsuite/gnat.dg/aliasing1.adb
@@ -18,5 +18,5 @@ package body Aliasing1 is
end Aliasing1;
--- { dg-final { scan-tree-dump-not "__gnat_rcheck" "optimized" } }
+-- { dg-final { scan-tree-dump-not "gnat_rcheck" "optimized" } }
-- { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc/testsuite/gnat.dg/enum3.adb b/gcc/testsuite/gnat.dg/enum3.adb
new file mode 100644
index 00000000000..1cb6c4b5648
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/enum3.adb
@@ -0,0 +1,23 @@
+-- { dg-do run }
+
+procedure Enum3 is
+ type Enum is (Aaa, Bbb, Ccc);
+ for Enum use (1,2,4);
+begin
+ for Lo in Enum loop
+ for Hi in Enum loop
+ declare
+ subtype S is Enum range Lo .. Hi;
+ type Vector is array (S) of Integer;
+ Vec : Vector;
+ begin
+ for I in S loop
+ Vec (I) := 0;
+ end loop;
+ if Vec /= (S => 0) then
+ raise Program_Error;
+ end if;
+ end;
+ end loop;
+ end loop;
+end;
diff --git a/gcc/testsuite/gnat.dg/opt35.adb b/gcc/testsuite/gnat.dg/opt35.adb
new file mode 100644
index 00000000000..b0defe07ca6
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt35.adb
@@ -0,0 +1,25 @@
+-- { dg-do run }
+-- { dg-options "-O" }
+
+with Opt35_Pkg; use Opt35_Pkg;
+
+procedure Opt35 is
+ I : Integer := -1;
+ N : Natural := 0;
+begin
+ begin
+ I := F(0);
+ exception
+ when E => N := N + 1;
+ end;
+
+ begin
+ I := I + F(0);
+ exception
+ when E => N := N + 1;
+ end;
+
+ if N /= 2 or I = 0 then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/opt35_pkg.adb b/gcc/testsuite/gnat.dg/opt35_pkg.adb
new file mode 100644
index 00000000000..8e868c49d97
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt35_pkg.adb
@@ -0,0 +1,11 @@
+package body Opt35_Pkg is
+
+ function F (I : Integer) return Integer is
+ begin
+ if I = 0 then
+ raise E;
+ end if;
+ return -I;
+ end;
+
+end Opt35_Pkg;
diff --git a/gcc/testsuite/gnat.dg/opt35_pkg.ads b/gcc/testsuite/gnat.dg/opt35_pkg.ads
new file mode 100644
index 00000000000..3fcd3f341d8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt35_pkg.ads
@@ -0,0 +1,9 @@
+package Opt35_Pkg is
+
+ pragma Pure;
+
+ E : Exception;
+
+ function F (I : Integer) return Integer;
+
+end Opt35_Pkg;
diff --git a/gcc/testsuite/gnat.dg/opt36.adb b/gcc/testsuite/gnat.dg/opt36.adb
new file mode 100644
index 00000000000..137db768319
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt36.adb
@@ -0,0 +1,23 @@
+-- { dg-do run }
+-- { dg-options "-O2" }
+
+with Opt35_Pkg; use Opt35_Pkg;
+
+procedure Opt36 is
+ I : Integer := -1;
+ N : Natural := 0;
+begin
+ loop
+ begin
+ I := I + 1;
+ I := I + F(0);
+ exception
+ when E => N := N + 1;
+ end;
+ exit when I = 1;
+ end loop;
+
+ if N /= 2 or I = 0 then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/opt37.adb b/gcc/testsuite/gnat.dg/opt37.adb
new file mode 100644
index 00000000000..fe37f903783
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt37.adb
@@ -0,0 +1,42 @@
+-- { dg-compile }
+-- { dg-options "-O2 -gnato -fdump-tree-optimized" }
+
+package body Opt37 is
+
+ function To_Unchecked (Bits : T_Bit_Array) return Unsigned32 is
+ Value : Unsigned32 := 0;
+ begin
+ for I in Bits'Range loop
+ Value := Value * 2 + Unsigned32 (Bits(I));
+ end loop;
+ return Value;
+ end;
+
+ function To_Scalar (Bits : T_Bit_Array) return Positive is
+ Tmp : Unsigned32;
+ Value : Positive;
+ begin
+ Tmp := To_Unchecked (Bits);
+ if Tmp in 0 .. Unsigned32 (Positive'last) then
+ Value := Positive (Tmp);
+ else
+ Value := -Positive (Unsigned32'last - Tmp);
+ if Value > Positive'first then
+ Value := Value - 1;
+ else
+ raise Program_Error;
+ end if;
+ end if;
+ return Value;
+ end;
+
+ function Func (Bit_Array : T_Bit_Array;
+ Bit_Index : T_Bit_Index) return Positive is
+ begin
+ return To_Scalar (Bit_Array (Bit_Index .. Bit_Index + 1));
+ end;
+
+end Opt37;
+
+-- { dg-final { scan-tree-dump-not "alloca" "optimized" } }
+-- { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc/testsuite/gnat.dg/opt37.ads b/gcc/testsuite/gnat.dg/opt37.ads
new file mode 100644
index 00000000000..7507679933c
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt37.ads
@@ -0,0 +1,18 @@
+package Opt37 is
+
+ type T_Bit is range 0 .. 1;
+ for T_Bit'Size use 1;
+
+ type Positive is range 0 .. (2 ** 31) - 1;
+ type Unsigned32 is mod 2 ** 32;
+
+ subtype T_Bit_Count is Positive;
+ subtype T_Bit_Index is T_Bit_Count range 1 .. T_Bit_Count'Last;
+
+ type T_Bit_Array is array (T_Bit_Count range <>) of T_Bit;
+ pragma Pack (T_Bit_Array);
+
+ function Func (Bit_Array : in T_Bit_Array;
+ Bit_Index : in T_Bit_Index) return Positive;
+
+end Opt37;
diff --git a/gcc/testsuite/gnat.dg/overflow_fixed.adb b/gcc/testsuite/gnat.dg/overflow_fixed.adb
new file mode 100644
index 00000000000..6ece5152333
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/overflow_fixed.adb
@@ -0,0 +1,19 @@
+-- { dg-do run }
+-- { dg-options "-gnato -O" }
+
+procedure Overflow_Fixed is
+
+ type Unsigned_8_Bit is mod 2**8;
+
+ procedure Fixed_To_Eight (Value : Duration) is
+ Item : Unsigned_8_Bit;
+ begin
+ Item := Unsigned_8_Bit(Value);
+ raise Program_Error;
+ exception
+ when Constraint_Error => null; -- expected case
+ end;
+
+begin
+ Fixed_To_Eight (-0.5);
+end;
diff --git a/gcc/testsuite/gnat.dg/volatile12.adb b/gcc/testsuite/gnat.dg/volatile12.adb
new file mode 100644
index 00000000000..91f3831ecde
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/volatile12.adb
@@ -0,0 +1,7 @@
+-- { dg-do compile }
+
+package body Volatile12 is
+
+ procedure Proc (A : Arr) is begin null; end;
+
+end Volatile12;
diff --git a/gcc/testsuite/gnat.dg/volatile12.ads b/gcc/testsuite/gnat.dg/volatile12.ads
new file mode 100644
index 00000000000..c37d249aa0a
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/volatile12.ads
@@ -0,0 +1,7 @@
+package Volatile12 is
+
+ type Arr is array (Integer range <>) of Integer with Volatile;
+
+ procedure Proc (A : Arr);
+
+end Volatile12;
diff --git a/gcc/testsuite/lib/asan-dg.exp b/gcc/testsuite/lib/asan-dg.exp
index 9ba39db15e4..7a12160bb19 100644
--- a/gcc/testsuite/lib/asan-dg.exp
+++ b/gcc/testsuite/lib/asan-dg.exp
@@ -23,6 +23,21 @@ proc check_effective_target_faddress_sanitizer {} {
} "-fsanitize=address"]
}
+proc asan_include_flags {} {
+ global srcdir
+ global TESTING_IN_BUILD_TREE
+
+ set flags ""
+
+ if { [is_remote host] || ! [info exists TESTING_IN_BUILD_TREE] } {
+ return "${flags}"
+ }
+
+ set flags "-I$srcdir/../../libsanitizer/include"
+
+ return "$flags"
+}
+
#
# asan_link_flags -- compute library path and flags to find libasan.
# (originally from g++.exp)
@@ -80,17 +95,19 @@ proc asan_init { args } {
}
}
+ set include_flags "[asan_include_flags]"
+
if [info exists TEST_ALWAYS_FLAGS] {
set asan_saved_TEST_ALWAYS_FLAGS $TEST_ALWAYS_FLAGS
}
if [info exists ALWAYS_CXXFLAGS] {
set ALWAYS_CXXFLAGS [concat "{ldflags=$link_flags}" $ALWAYS_CXXFLAGS]
- set ALWAYS_CXXFLAGS [concat "{additional_flags=-fsanitize=address -g}" $ALWAYS_CXXFLAGS]
+ set ALWAYS_CXXFLAGS [concat "{additional_flags=-fsanitize=address -g $include_flags}" $ALWAYS_CXXFLAGS]
} else {
if [info exists TEST_ALWAYS_FLAGS] {
- set TEST_ALWAYS_FLAGS "$link_flags -fsanitize=address -g $TEST_ALWAYS_FLAGS"
+ set TEST_ALWAYS_FLAGS "$link_flags -fsanitize=address -g $include_flags $TEST_ALWAYS_FLAGS"
} else {
- set TEST_ALWAYS_FLAGS "$link_flags -fsanitize=address -g"
+ set TEST_ALWAYS_FLAGS "$link_flags -fsanitize=address -g $include_flags"
}
}
if { $link_flags != "" } {
diff --git a/gcc/testsuite/lib/c-compat.exp b/gcc/testsuite/lib/c-compat.exp
index 95a1fb9d71f..f5b461e473d 100644
--- a/gcc/testsuite/lib/c-compat.exp
+++ b/gcc/testsuite/lib/c-compat.exp
@@ -28,6 +28,7 @@ global compat_skip_list
# compilers for compatibility tests.
load_lib target-supports.exp
+load_lib target-libpath.exp
#
# compat-use-alt-compiler -- make the alternate compiler the default
@@ -47,6 +48,7 @@ proc compat-use-alt-compiler { } {
if { $compat_alt_color == 0 } then {
regsub -- "-fdiagnostics-color=never" $TEST_ALWAYS_FLAGS "" TEST_ALWAYS_FLAGS
}
+ restore_gcc_exec_prefix_env_var
}
}
@@ -64,6 +66,7 @@ proc compat-use-tst-compiler { } {
if { $compat_same_alt == 0 } then {
set GCC_UNDER_TEST $compat_save_gcc_under_test
set TEST_ALWAYS_FLAGS $compat_save_TEST_ALWAYS_FLAGS
+ set_gcc_exec_prefix_env_var
}
}
diff --git a/gcc/testsuite/lib/clearcap.exp b/gcc/testsuite/lib/clearcap.exp
new file mode 100644
index 00000000000..044881fbd3f
--- /dev/null
+++ b/gcc/testsuite/lib/clearcap.exp
@@ -0,0 +1,58 @@
+# Copyright (C) 2014 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Clear hardware capabilities on Solaris.
+if [istarget *-*-solaris2*] {
+ set clearcap_ldflags "-mclear-hwcap"
+}
+
+#
+# clearcap-init -- called at the start of each subdir of tests
+#
+
+proc clearcap-init { args } {
+ global TEST_ALWAYS_FLAGS
+ global ALWAYS_CXXFLAGS
+ global clearcap_saved_TEST_ALWAYS_FLAGS
+ global clearcap_ldflags
+
+ if [info exists TEST_ALWAYS_FLAGS] {
+ set clearcap_saved_TEST_ALWAYS_FLAGS $TEST_ALWAYS_FLAGS
+ }
+ if [info exists clearcap_ldflags] {
+ if [info exists ALWAYS_CXXFLAGS] {
+ set ALWAYS_CXXFLAGS [concat "{ldflags=$clearcap_ldflags}" $ALWAYS_CXXFLAGS]
+ } else {
+ append TEST_ALWAYS_FLAGS " $clearcap_ldflags"
+ }
+ }
+ return 0
+}
+
+#
+# clearcap-finish -- called at the start of each subdir of tests
+#
+
+proc clearcap-finish { args } {
+ global TEST_ALWAYS_FLAGS
+ global clearcap_saved_TEST_ALWAYS_FLAGS
+
+ if [info exists clearcap_saved_TEST_ALWAYS_FLAGS] {
+ set TEST_ALWAYS_FLAGS $clearcap_saved_TEST_ALWAYS_FLAGS
+ } else {
+ unset TEST_ALWAYS_FLAGS
+ }
+}
diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
index 6e3e9d8fb67..e382b3d0192 100644
--- a/gcc/testsuite/lib/scanasm.exp
+++ b/gcc/testsuite/lib/scanasm.exp
@@ -500,3 +500,13 @@ proc dg-function-on-line { args } {
append final-code "$cmd\n"
}
+
+# Look for a pattern in the .exe.ltrans0.s file produced by the
+# compiler. See dg-scan for details.
+
+proc scan-lto-assembler { args } {
+ set testcase [testname-for-summary]
+ set output_file "[file rootname [file tail $testcase]].exe.ltrans0.s"
+ verbose "output_file: $output_file"
+ dg-scan "scan-assembler" 1 $testcase $output_file $args
+}
diff --git a/gcc/testsuite/lib/target-libpath.exp b/gcc/testsuite/lib/target-libpath.exp
index 1891088c44a..175f3cd599e 100644
--- a/gcc/testsuite/lib/target-libpath.exp
+++ b/gcc/testsuite/lib/target-libpath.exp
@@ -28,6 +28,21 @@ set orig_gcc_exec_prefix_checked 0
#######################################
+# proc set_gcc_exec_prefix_env_var { }
+#######################################
+
+proc set_gcc_exec_prefix_env_var { } {
+ global TEST_GCC_EXEC_PREFIX
+ global env
+
+ # Set GCC_EXEC_PREFIX for the compiler under test to pick up files not in
+ # the build tree from a specified location (normally the install tree).
+ if [info exists TEST_GCC_EXEC_PREFIX] {
+ setenv GCC_EXEC_PREFIX "$TEST_GCC_EXEC_PREFIX"
+ }
+}
+
+#######################################
# proc set_ld_library_path_env_vars { }
#######################################
@@ -49,7 +64,6 @@ proc set_ld_library_path_env_vars { } {
global orig_ld_library_path_64
global orig_dyld_library_path
global orig_gcc_exec_prefix
- global TEST_GCC_EXEC_PREFIX
global env
# Save the original GCC_EXEC_PREFIX.
@@ -61,11 +75,7 @@ proc set_ld_library_path_env_vars { } {
set orig_gcc_exec_prefix_checked 1
}
- # Set GCC_EXEC_PREFIX for the compiler under test to pick up files not in
- # the build tree from a specified location (normally the install tree).
- if [info exists TEST_GCC_EXEC_PREFIX] {
- setenv GCC_EXEC_PREFIX "$TEST_GCC_EXEC_PREFIX"
- }
+ set_gcc_exec_prefix_env_var
# Setting the ld library path causes trouble when testing cross-compilers.
if { [is_remote target] } {
@@ -164,6 +174,22 @@ proc set_ld_library_path_env_vars { } {
}
#######################################
+# proc restore_gcc_exec_prefix_env_var { }
+#######################################
+
+proc restore_gcc_exec_prefix_env_var { } {
+ global orig_gcc_exec_prefix_saved
+ global orig_gcc_exec_prefix
+ global env
+
+ if { $orig_gcc_exec_prefix_saved } {
+ setenv GCC_EXEC_PREFIX "$orig_gcc_exec_prefix"
+ } elseif [info exists env(GCC_EXEC_PREFIX)] {
+ unsetenv GCC_EXEC_PREFIX
+ }
+}
+
+#######################################
# proc restore_ld_library_path_env_vars { }
#######################################
@@ -175,21 +201,15 @@ proc restore_ld_library_path_env_vars { } {
global orig_ld_library_path_32_saved
global orig_ld_library_path_64_saved
global orig_dyld_library_path_saved
- global orig_gcc_exec_prefix_saved
global orig_ld_library_path
global orig_ld_run_path
global orig_shlib_path
global orig_ld_library_path_32
global orig_ld_library_path_64
global orig_dyld_library_path
- global orig_gcc_exec_prefix
global env
- if { $orig_gcc_exec_prefix_saved } {
- setenv GCC_EXEC_PREFIX "$orig_gcc_exec_prefix"
- } elseif [info exists env(GCC_EXEC_PREFIX)] {
- unsetenv GCC_EXEC_PREFIX
- }
+ restore_gcc_exec_prefix_env_var
if { $orig_environment_saved == 0 } {
return
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index ef370fef356..5ec16088355 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -1956,6 +1956,32 @@ proc check_effective_target_dfprt { } {
}]
}
+# Return 1 if the target supports executing DFP hardware instructions,
+# 0 otherwise. Cache the result.
+
+proc check_dfp_hw_available { } {
+ return [check_cached_effective_target dfp_hw_available {
+ # For now, disable on Darwin
+ if { [istarget powerpc-*-eabi] || [istarget powerpc*-*-eabispe] || [istarget *-*-darwin*]} {
+ expr 0
+ } else {
+ check_runtime_nocache dfp_hw_available {
+ volatile _Decimal64 r;
+ volatile _Decimal64 a = 4.0DD;
+ volatile _Decimal64 b = 2.0DD;
+ int main()
+ {
+ asm volatile ("dadd %0,%1,%2" : "=d" (r) : "d" (a), "d" (b));
+ asm volatile ("dsub %0,%1,%2" : "=d" (r) : "d" (a), "d" (b));
+ asm volatile ("dmul %0,%1,%2" : "=d" (r) : "d" (a), "d" (b));
+ asm volatile ("ddiv %0,%1,%2" : "=d" (r) : "d" (a), "d" (b));
+ return 0;
+ }
+ } "-mcpu=power6 -mhard-float"
+ }
+ }]
+}
+
# Return 1 if the target supports compiling and assembling UCN, 0 otherwise.
proc check_effective_target_ucn_nocache { } {
@@ -3280,7 +3306,10 @@ proc check_effective_target_vect_bswap { } {
verbose "check_effective_target_vect_bswap: using cached result" 2
} else {
set et_vect_bswap_saved 0
- if { [istarget aarch64*-*-*] } {
+ if { [istarget aarch64*-*-*]
+ || ([istarget arm*-*-*]
+ && [check_effective_target_arm_neon])
+ } {
set et_vect_bswap_saved 1
}
}
@@ -4778,6 +4807,90 @@ proc check_effective_target_sync_long_long_runtime { } {
}
}
+# Return 1 if the target supports byte swap instructions.
+
+proc check_effective_target_bswap { } {
+ global et_bswap_saved
+
+ if [info exists et_bswap_saved] {
+ verbose "check_effective_target_bswap: using cached result" 2
+ } else {
+ set et_bswap_saved 0
+ if { [istarget aarch64-*-*]
+ || [istarget alpha*-*-*]
+ || [istarget arm*-*-*]
+ || [istarget i?86-*-*]
+ || [istarget m68k-*-*]
+ || [istarget powerpc*-*-*]
+ || [istarget rs6000-*-*]
+ || [istarget s390*-*-*]
+ || [istarget x86_64-*-*] } {
+ set et_bswap_saved 1
+ }
+ }
+
+ verbose "check_effective_target_bswap: returning $et_bswap_saved" 2
+ return $et_bswap_saved
+}
+
+# Return 1 if the target supports 16-bit byte swap instructions.
+
+proc check_effective_target_bswap16 { } {
+ global et_bswap16_saved
+
+ if [info exists et_bswap16_saved] {
+ verbose "check_effective_target_bswap16: using cached result" 2
+ } else {
+ set et_bswap16_saved 0
+ if { [is-effective-target bswap]
+ && ![istarget alpha*-*-*]
+ && ![istarget i?86-*-*]
+ && ![istarget x86_64-*-*] } {
+ set et_bswap16_saved 1
+ }
+ }
+
+ verbose "check_effective_target_bswap16: returning $et_bswap16_saved" 2
+ return $et_bswap16_saved
+}
+
+# Return 1 if the target supports 32-bit byte swap instructions.
+
+proc check_effective_target_bswap32 { } {
+ global et_bswap32_saved
+
+ if [info exists et_bswap32_saved] {
+ verbose "check_effective_target_bswap32: using cached result" 2
+ } else {
+ set et_bswap32_saved 0
+ if { [is-effective-target bswap] } {
+ set et_bswap32_saved 1
+ }
+ }
+
+ verbose "check_effective_target_bswap32: returning $et_bswap32_saved" 2
+ return $et_bswap32_saved
+}
+
+# Return 1 if the target supports 64-bit byte swap instructions.
+
+proc check_effective_target_bswap64 { } {
+ global et_bswap64_saved
+
+ if [info exists et_bswap64_saved] {
+ verbose "check_effective_target_bswap64: using cached result" 2
+ } else {
+ set et_bswap64_saved 0
+ if { [is-effective-target bswap]
+ && [is-effective-target lp64] } {
+ set et_bswap64_saved 1
+ }
+ }
+
+ verbose "check_effective_target_bswap64: returning $et_bswap64_saved" 2
+ return $et_bswap64_saved
+}
+
# Return 1 if the target supports atomic operations on "int" and "long".
proc check_effective_target_sync_int_long { } {
@@ -4936,6 +5049,7 @@ proc is-effective-target { arg } {
"vsx_hw" { set selected [check_vsx_hw_available] }
"p8vector_hw" { set selected [check_p8vector_hw_available] }
"ppc_recip_hw" { set selected [check_ppc_recip_hw_available] }
+ "dfp_hw" { set selected [check_dfp_hw_available] }
"named_sections" { set selected [check_named_sections_available] }
"gc_sections" { set selected [check_gc_sections_available] }
"cxa_atexit" { set selected [check_cxa_atexit_available] }
@@ -4958,6 +5072,7 @@ proc is-effective-target-keyword { arg } {
"vsx_hw" { return 1 }
"p8vector_hw" { return 1 }
"ppc_recip_hw" { return 1 }
+ "dfp_hw" { return 1 }
"named_sections" { return 1 }
"gc_sections" { return 1 }
"cxa_atexit" { return 1 }
@@ -5257,7 +5372,11 @@ proc check_avx_available { } {
# Return true if 32- and 16-bytes vectors are available.
proc check_effective_target_vect_sizes_32B_16B { } {
- return [check_avx_available];
+ if { [check_avx_available] && ![check_prefer_avx128] } {
+ return 1;
+ } else {
+ return 0;
+ }
}
# Return true if 128-bits vectors are preferred even if 256-bits vectors
@@ -5290,6 +5409,9 @@ proc check_effective_target_avx512f { } {
# Return 1 if avx instructions can be compiled.
proc check_effective_target_avx { } {
+ if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
+ return 0
+ }
return [check_no_compiler_messages avx object {
void _mm256_zeroall (void)
{
@@ -5758,6 +5880,7 @@ proc check_effective_target_logical_op_short_circuit {} {
|| [istarget arc*-*-*]
|| [istarget avr*-*-*]
|| [istarget crisv32-*-*] || [istarget cris-*-*]
+ || [istarget mmix-*-*]
|| [istarget s390*-*-*]
|| [check_effective_target_arm_cortex_m] } {
return 1
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-3.mm b/gcc/testsuite/obj-c++.dg/exceptions-3.mm
index bf0be018e03..3e6a77513ad 100644
--- a/gcc/testsuite/obj-c++.dg/exceptions-3.mm
+++ b/gcc/testsuite/obj-c++.dg/exceptions-3.mm
@@ -73,7 +73,6 @@ int test (id object)
{ /* { dg-error "no matching function" "" { target *-*-* } 72 } */
dummy++; /* { dg-message "MyObject" "" { target *-*-* } 13 } */
} /* { dg-message "candidate" "" { target *-*-* } 13 } */
- /* { dg-message "candidates" "" { target *-*-* } 72 } */
@try { @throw object; }
@catch (static MyObject *x) /* { dg-error "storage class" } */
{
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-5.mm b/gcc/testsuite/obj-c++.dg/exceptions-5.mm
index 1ea9a6f4610..087533bcbbb 100644
--- a/gcc/testsuite/obj-c++.dg/exceptions-5.mm
+++ b/gcc/testsuite/obj-c++.dg/exceptions-5.mm
@@ -73,7 +73,6 @@ int test (id object)
{ /* { dg-error "no matching function" "" { target *-*-* } 72 } */
dummy++; /* { dg-message "MyObject" "" { target *-*-* } 13 } */
} /* { dg-message "candidate" "" { target *-*-* } 13 } */
- /* { dg-message "candidate" "" { target *-*-* } 72 } */
@try { @throw object; }
@catch (static MyObject *) /* { dg-error "storage class" } */
diff --git a/gcc/testsuite/objc.dg/ivar-scope-1.m b/gcc/testsuite/objc.dg/ivar-scope-1.m
new file mode 100644
index 00000000000..34443a442fe
--- /dev/null
+++ b/gcc/testsuite/objc.dg/ivar-scope-1.m
@@ -0,0 +1,24 @@
+/* Test instance variable scope. */
+/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
+/* { dg-do compile } */
+#include <objc/objc.h>
+
+@interface MyClass
+{
+ int someivar;
+}
+- (void) test;
+@end
+
+@implementation MyClass
+- (void) test
+{
+ int a;
+
+ /* Make sure instance variables do have local scope when
+ -fno-local-ivar isn't specified. */
+
+ a = self->someivar; /* No warning or error. */
+ a = someivar; /* No error. */
+}
+@end
diff --git a/gcc/testsuite/objc.dg/ivar-scope-2.m b/gcc/testsuite/objc.dg/ivar-scope-2.m
new file mode 100644
index 00000000000..ff795d08d6a
--- /dev/null
+++ b/gcc/testsuite/objc.dg/ivar-scope-2.m
@@ -0,0 +1,34 @@
+/* Test instance variable scope. */
+/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-local-ivars" } */
+#include <objc/objc.h>
+
+@interface MyClass
+{
+ int someivar;
+}
+- (void) testscope;
+- (void) testshadowing;
+@end
+
+@implementation MyClass
+- (void) testscope
+{
+ int a;
+
+ a = self->someivar; /* No warning or error. */
+ a = someivar; /* { dg-error ".someivar. undeclared" } */
+}
+
+- (void) testshadowing
+{
+ int someivar = 1;
+ int a;
+
+ /* Since instance variables don't have local scope no shadowing
+ should occur. */
+
+ a = someivar; /* No warning. */
+}
+@end
diff --git a/gcc/testsuite/objc.dg/ivar-scope-3.m b/gcc/testsuite/objc.dg/ivar-scope-3.m
new file mode 100644
index 00000000000..0bf7aa1a114
--- /dev/null
+++ b/gcc/testsuite/objc.dg/ivar-scope-3.m
@@ -0,0 +1,60 @@
+/* Test instance variable scope. */
+/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
+/* { dg-do run } */
+/* { dg-additional-options "-Wno-shadow-ivar" } */
+#include "../objc-obj-c++-shared/TestsuiteObject.m"
+#include <objc/objc.h>
+
+extern void abort(void);
+
+int someivar = 1;
+
+@interface MyClass: TestsuiteObject
+{
+ int someivar;
+}
+- (int) get;
+- (int) getHidden;
+@end
+
+@implementation MyClass
+- init
+{
+ someivar = 2;
+
+ return self;
+}
+
+- (int) get
+{
+ return someivar;
+}
+
+- (int) getHidden
+{
+ int someivar = 3;
+
+ return someivar;
+}
+@end
+
+int main(void)
+{
+ MyClass *object;
+
+ object = [[MyClass alloc] init];
+
+ /* Check whether the instance variable hides the global variable. */
+
+ if ([object get] != 2) {
+ abort();
+ }
+
+ /* Check whether the local variable hides the instance variable. */
+
+ if ([object getHidden] != 3) {
+ abort();
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/ivar-scope-4.m b/gcc/testsuite/objc.dg/ivar-scope-4.m
new file mode 100644
index 00000000000..f7209724be9
--- /dev/null
+++ b/gcc/testsuite/objc.dg/ivar-scope-4.m
@@ -0,0 +1,83 @@
+/* Test instance variable scope. */
+/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
+/* { dg-do run } */
+/* { dg-additional-options "-Wno-shadow-ivar -fno-local-ivars" } */
+#include "../objc-obj-c++-shared/runtime.h"
+#include <objc/objc.h>
+
+extern void abort(void);
+
+int someivar = 1;
+
+/* The testsuite object depends on local variable scope so we need to
+ implement our own minimal base object here. */
+
+@interface MyClass
+{
+ Class isa;
+ int someivar;
+}
+
++ (id) alloc;
+- (id) init;
+- (int) getGlobal;
+- (int) getInstance;
+- (int) getHidden;
+@end
+
+@implementation MyClass
++ (id) alloc
+{
+ return class_createInstance (self, 0);
+}
+
+- (id) init
+{
+ self->someivar = 2;
+
+ return self;
+}
+
+- (int) getGlobal
+{
+ return someivar;
+}
+
+- (int) getInstance
+{
+ return self->someivar;
+}
+
+- (int) getHidden
+{
+ int someivar = 3;
+
+ return someivar;
+}
+@end
+
+int main(void)
+{
+ id object;
+
+ object = [[MyClass alloc] init];
+
+ /* Check for aliasing between instance variable and global
+ variable. */
+
+ if ([object getGlobal] != 1) {
+ abort();
+ }
+
+ if ([object getInstance] != 2) {
+ abort();
+ }
+
+ /* Check whether the local variable hides the instance variable. */
+
+ if ([object getHidden] != 3) {
+ abort();
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/objc.dg/ivar-visibility-1.m b/gcc/testsuite/objc.dg/ivar-visibility-1.m
new file mode 100644
index 00000000000..5a222591d19
--- /dev/null
+++ b/gcc/testsuite/objc.dg/ivar-visibility-1.m
@@ -0,0 +1,33 @@
+/* Test instance variable visibility. */
+/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
+/* { dg-do compile } */
+#include <objc/objc.h>
+
+@interface MySuperClass
+{
+ int someivar;
+}
+@end
+
+@implementation MySuperClass
+@end
+
+
+@interface MyClass : MySuperClass
+@end
+
+@implementation MyClass
+@end
+
+@interface MyOtherClass
+- (void) test: (MyClass *) object;
+@end
+
+@implementation MyOtherClass
+- (void) test: (MyClass *) object
+{
+ int a;
+
+ a = object->someivar; /* { dg-error "instance variable .someivar. is declared protected" } */
+}
+@end
diff --git a/gcc/testsuite/objc.dg/ivar-visibility-2.m b/gcc/testsuite/objc.dg/ivar-visibility-2.m
new file mode 100644
index 00000000000..eb41c8f4db0
--- /dev/null
+++ b/gcc/testsuite/objc.dg/ivar-visibility-2.m
@@ -0,0 +1,34 @@
+/* Test instance variable visibility. */
+/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
+/* { dg-do compile } */
+/* { dg-additional-options "-fivar-visibility=protected" } */
+#include <objc/objc.h>
+
+@interface MySuperClass
+{
+ int someivar;
+}
+@end
+
+@implementation MySuperClass
+@end
+
+
+@interface MyClass : MySuperClass
+@end
+
+@implementation MyClass
+@end
+
+@interface MyOtherClass
+- (void) test: (MyClass *) object;
+@end
+
+@implementation MyOtherClass
+- (void) test: (MyClass *) object
+{
+ int a;
+
+ a = object->someivar; /* { dg-error "instance variable .someivar. is declared protected" } */
+}
+@end
diff --git a/gcc/testsuite/objc.dg/ivar-visibility-3.m b/gcc/testsuite/objc.dg/ivar-visibility-3.m
new file mode 100644
index 00000000000..ecc6f99c760
--- /dev/null
+++ b/gcc/testsuite/objc.dg/ivar-visibility-3.m
@@ -0,0 +1,34 @@
+/* Test instance variable visibility. */
+/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
+/* { dg-do compile } */
+/* { dg-additional-options "-fivar-visibility=private" } */
+#include <objc/objc.h>
+
+@interface MySuperClass
+{
+ int someivar;
+}
+@end
+
+@implementation MySuperClass
+@end
+
+
+@interface MyClass : MySuperClass
+@end
+
+@implementation MyClass
+@end
+
+@interface MyOtherClass
+- (void) test: (MyClass *) object;
+@end
+
+@implementation MyOtherClass
+- (void) test: (MyClass *) object
+{
+ int a;
+
+ a = object->someivar; /* { dg-error "instance variable .someivar. is declared private" } */
+}
+@end
diff --git a/gcc/testsuite/objc.dg/ivar-visibility-4.m b/gcc/testsuite/objc.dg/ivar-visibility-4.m
new file mode 100644
index 00000000000..adfeb449e55
--- /dev/null
+++ b/gcc/testsuite/objc.dg/ivar-visibility-4.m
@@ -0,0 +1,36 @@
+/* Test instance variable visibility. */
+/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
+/* { dg-do compile } */
+/* { dg-additional-options "-fivar-visibility=public" } */
+#include <objc/objc.h>
+
+@interface MySuperClass
+{
+ int someivar;
+}
+@end
+
+@implementation MySuperClass
+@end
+
+
+@interface MyClass : MySuperClass
+@end
+
+@implementation MyClass
+@end
+
+@interface MyOtherClass
+- (void) test: (MyClass *) object;
+@end
+
+@implementation MyOtherClass
+- (void) test: (MyClass *) object
+{
+ int a;
+
+ /* someivar is public so we shouldn't get any errors here. */
+
+ a = object->someivar;
+}
+@end
diff --git a/gcc/testsuite/objc.dg/shadow-1.m b/gcc/testsuite/objc.dg/shadow-1.m
new file mode 100644
index 00000000000..739a0d0312e
--- /dev/null
+++ b/gcc/testsuite/objc.dg/shadow-1.m
@@ -0,0 +1,33 @@
+/* Test disabling of warnings for shadowing instance variables. */
+/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
+/* { dg-do compile } */
+/* { dg-additional-options "-Wno-shadow-ivar" } */
+#include <objc/objc.h>
+
+@interface MyClass
+{
+@private
+ int private;
+
+@protected
+ int protected;
+
+@public
+ int public;
+}
+- (void) test;
+@end
+
+@implementation MyClass
+- (void) test
+{
+ int private = 12;
+ int protected = 12;
+ int public = 12;
+ int a;
+
+ a = private; /* No warning. */
+ a = protected; /* No warning. */
+ a = public; /* No warning. */
+}
+@end
diff --git a/gcc/testsuite/objc.dg/shadow-2.m b/gcc/testsuite/objc.dg/shadow-2.m
new file mode 100644
index 00000000000..16261b94a21
--- /dev/null
+++ b/gcc/testsuite/objc.dg/shadow-2.m
@@ -0,0 +1,33 @@
+/* Test disabling of warnings for shadowing instance variables. */
+/* Author: Dimitris Papavasiliou <dpapavas@gmail.com>. */
+/* { dg-do compile } */
+/* { dg-additional-options "-Wno-shadow" } */
+#include <objc/objc.h>
+
+@interface MyClass
+{
+@private
+ int private;
+
+@protected
+ int protected;
+
+@public
+ int public;
+}
+- (void) test;
+@end
+
+@implementation MyClass
+- (void) test
+{
+ int private = 12;
+ int protected = 12;
+ int public = 12;
+ int a;
+
+ a = private; /* No warning. */
+ a = protected; /* No warning. */
+ a = public; /* No warning. */
+}
+@end
diff --git a/gcc/timevar.def b/gcc/timevar.def
index 2db1943c308..cbb64d5b73f 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -71,6 +71,7 @@ DEFTIMEVAR (TV_IPA_DEVIRT , "ipa devirtualization")
DEFTIMEVAR (TV_IPA_CONSTANT_PROP , "ipa cp")
DEFTIMEVAR (TV_IPA_INLINING , "ipa inlining heuristics")
DEFTIMEVAR (TV_IPA_FNSPLIT , "ipa function splitting")
+DEFTIMEVAR (TV_IPA_COMDATS , "ipa comdats")
DEFTIMEVAR (TV_IPA_OPT , "ipa various optimizations")
DEFTIMEVAR (TV_IPA_LTO_GIMPLE_IN , "ipa lto gimple in")
DEFTIMEVAR (TV_IPA_LTO_GIMPLE_OUT , "ipa lto gimple out")
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 4c334bd451a..fa4c74ef31f 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -957,7 +957,7 @@ init_asm_output (const char *name)
static void *
realloc_for_line_map (void *ptr, size_t len)
{
- return GGC_RESIZEVAR (void, ptr, len);
+ return ggc_realloc (ptr, len);
}
/* A helper function: used as the allocator function for
@@ -1156,7 +1156,7 @@ general_init (const char *argv0)
table. */
init_ggc ();
init_stringpool ();
- line_table = ggc_alloc_line_maps ();
+ line_table = ggc_alloc<line_maps> ();
linemap_init (line_table);
line_table->reallocator = realloc_for_line_map;
line_table->round_alloc_size = ggc_round_alloc_size;
@@ -1601,6 +1601,9 @@ backend_init_target (void)
/* Depends on HARD_FRAME_POINTER_REGNUM. */
init_reload ();
+ /* Depends on the enabled attribute. */
+ recog_init ();
+
/* The following initialization functions need to generate rtl, so
provide a dummy function context for them. */
init_dummy_function_start ();
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index c0e44c78ebe..7c9f163e7df 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -479,7 +479,7 @@ record_tm_replacement (tree from, tree to)
if (tm_wrap_map == NULL)
tm_wrap_map = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0);
- h = ggc_alloc_tree_map ();
+ h = ggc_alloc<tree_map> ();
h->hash = htab_hash_pointer (from);
h->base.from = from;
h->to = to;
@@ -3070,7 +3070,7 @@ split_bb_make_tm_edge (gimple stmt, basic_block dest_bb,
struct tm_restart_node *n = (struct tm_restart_node *) *slot;
if (n == NULL)
{
- n = ggc_alloc_tm_restart_node ();
+ n = ggc_alloc<tm_restart_node> ();
*n = dummy;
}
else
@@ -4852,7 +4852,7 @@ ipa_tm_create_version_alias (struct cgraph_node *node, void *data)
/* Perform the same remapping to the comdat group. */
if (DECL_ONE_ONLY (new_decl))
- DECL_COMDAT_GROUP (new_decl) = tm_mangle (DECL_COMDAT_GROUP (old_decl));
+ varpool_get_node (new_decl)->set_comdat_group (tm_mangle (decl_comdat_group_id (old_decl)));
new_node = cgraph_same_body_alias (NULL, new_decl, info->new_decl);
new_node->tm_clone = true;
@@ -4892,7 +4892,7 @@ ipa_tm_create_version (struct cgraph_node *old_node)
/* Perform the same remapping to the comdat group. */
if (DECL_ONE_ONLY (new_decl))
- DECL_COMDAT_GROUP (new_decl) = tm_mangle (DECL_COMDAT_GROUP (old_decl));
+ varpool_get_node (new_decl)->set_comdat_group (tm_mangle (DECL_COMDAT_GROUP (old_decl)));
gcc_assert (!old_node->ipa_transforms_to_apply.exists ());
new_node = cgraph_copy_node_for_versioning (old_node, new_decl, vNULL, NULL);
diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c
index 1d292c4ad09..0b8577836d6 100644
--- a/gcc/tree-affine.c
+++ b/gcc/tree-affine.c
@@ -328,7 +328,14 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
if (bitpos % BITS_PER_UNIT != 0)
break;
aff_combination_const (comb, type, bitpos / BITS_PER_UNIT);
- core = build_fold_addr_expr (core);
+ if (TREE_CODE (core) == MEM_REF)
+ {
+ aff_combination_add_cst (comb, wi::to_widest (TREE_OPERAND (core, 1)));
+ core = TREE_OPERAND (core, 0);
+ }
+ else
+ core = build_fold_addr_expr (core);
+
if (TREE_CODE (core) == ADDR_EXPR)
aff_combination_add_elt (comb, core, 1);
else
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index bd304a5dff3..ba9ef2a4692 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -1877,6 +1877,12 @@ gimple_merge_blocks (basic_block a, basic_block b)
}
}
+ /* When merging two BBs, if their counts are different, the larger count
+ is selected as the new bb count. This is to handle inconsistent
+ profiles. */
+ a->count = MAX (a->count, b->count);
+ a->frequency = MAX (a->frequency, b->frequency);
+
/* Merge the sequences. */
last = gsi_last_bb (a);
gsi_insert_seq_after (&last, bb_seq (b), GSI_NEW_STMT);
@@ -6898,7 +6904,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
}
/* Initialize an empty loop tree. */
- struct loops *loops = ggc_alloc_cleared_loops ();
+ struct loops *loops = ggc_cleared_alloc<struct loops> ();
init_loops_structure (dest_cfun, loops, 1);
loops->state = LOOPS_MAY_HAVE_MULTIPLE_LATCHES;
set_loops_for_fn (dest_cfun, loops);
@@ -7091,12 +7097,6 @@ dump_function_to_file (tree fndecl, FILE *file, int flags)
struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
current_function_decl = fndecl;
-
- /* Print the return type of the function: */
- print_generic_expr (file, TREE_TYPE (TREE_TYPE (fun->decl)),
- dump_flags | TDF_SLIM);
- fprintf (file, "\n");
-
fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
arg = DECL_ARGUMENTS (fndecl);
@@ -8433,7 +8433,7 @@ execute_fixup_cfg (void)
FOR_EACH_BB_FN (bb, cfun)
{
bb->count = apply_scale (bb->count, count_scale);
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
{
gimple stmt = gsi_stmt (gsi);
tree decl = is_gimple_call (stmt)
@@ -8459,9 +8459,46 @@ execute_fixup_cfg (void)
todo |= TODO_cleanup_cfg;
}
+ /* Remove stores to variables we marked write-only.
+ Keep access when store has side effect, i.e. in case when source
+ is volatile. */
+ if (gimple_store_p (stmt)
+ && !gimple_has_side_effects (stmt))
+ {
+ tree lhs = get_base_address (gimple_get_lhs (stmt));
+
+ if (TREE_CODE (lhs) == VAR_DECL
+ && (TREE_STATIC (lhs) || DECL_EXTERNAL (lhs))
+ && varpool_get_node (lhs)->writeonly)
+ {
+ unlink_stmt_vdef (stmt);
+ gsi_remove (&gsi, true);
+ release_defs (stmt);
+ todo |= TODO_update_ssa | TODO_cleanup_cfg;
+ continue;
+ }
+ }
+ /* For calls we can simply remove LHS when it is known
+ to be write-only. */
+ if (is_gimple_call (stmt)
+ && gimple_get_lhs (stmt))
+ {
+ tree lhs = get_base_address (gimple_get_lhs (stmt));
+
+ if (TREE_CODE (lhs) == VAR_DECL
+ && (TREE_STATIC (lhs) || DECL_EXTERNAL (lhs))
+ && varpool_get_node (lhs)->writeonly)
+ {
+ gimple_call_set_lhs (stmt, NULL);
+ update_stmt (stmt);
+ todo |= TODO_update_ssa | TODO_cleanup_cfg;
+ }
+ }
+
if (maybe_clean_eh_stmt (stmt)
&& gimple_purge_dead_eh_edges (bb))
todo |= TODO_cleanup_cfg;
+ gsi_next (&gsi);
}
FOR_EACH_EDGE (e, ei, bb->succs)
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index 7e12c30f37c..cf542fd230c 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -831,12 +831,15 @@ expand_complex_move (gimple_stmt_iterator *gsi, tree type)
{
tree x;
gimple t;
+ location_t loc;
+ loc = gimple_location (stmt);
r = extract_component (gsi, rhs, 0, false);
i = extract_component (gsi, rhs, 1, false);
x = build1 (REALPART_EXPR, inner_type, unshare_expr (lhs));
t = gimple_build_assign (x, r);
+ gimple_set_location (t, loc);
gsi_insert_before (gsi, t, GSI_SAME_STMT);
if (stmt == gsi_stmt (*gsi))
@@ -849,6 +852,7 @@ expand_complex_move (gimple_stmt_iterator *gsi, tree type)
{
x = build1 (IMAGPART_EXPR, inner_type, unshare_expr (lhs));
t = gimple_build_assign (x, i);
+ gimple_set_location (t, loc);
gsi_insert_before (gsi, t, GSI_SAME_STMT);
stmt = gsi_stmt (*gsi);
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 72ef8e143a2..ebe584939f7 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -410,6 +410,8 @@ enum tree_index {
TI_UINT32_TYPE,
TI_UINT64_TYPE,
+ TI_VOID,
+
TI_INTEGER_ZERO,
TI_INTEGER_ONE,
TI_INTEGER_THREE,
@@ -1440,7 +1442,7 @@ struct GTY(()) tree_decl_with_vis {
struct tree_decl_with_rtl common;
tree assembler_name;
tree section_name;
- tree comdat_group;
+ struct symtab_node *symtab_node;
/* Belong to VAR_DECL exclusively. */
unsigned defer_output : 1;
diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
index 9d819e4a0ff..f4075fc5bd7 100644
--- a/gcc/tree-data-ref.h
+++ b/gcc/tree-data-ref.h
@@ -565,7 +565,7 @@ lambda_vector_gcd (lambda_vector vector, int size)
static inline lambda_vector
lambda_vector_new (int size)
{
- return (lambda_vector) ggc_alloc_cleared_atomic (sizeof (int) * size);
+ return ggc_cleared_vec_alloc<int> (size);
}
/* Clear out vector VEC1 of length SIZE. */
diff --git a/gcc/tree-dfa.h b/gcc/tree-dfa.h
index 7b076c7f73f..fe135879074 100644
--- a/gcc/tree-dfa.h
+++ b/gcc/tree-dfa.h
@@ -103,7 +103,8 @@ get_addr_base_and_unit_offset_1 (tree exp, HOST_WIDE_INT *poffset,
TREE_CODE (unit_size) == INTEGER_CST))
{
offset_int woffset
- = offset_int::from (wi::sub (index, low_bound), SIGNED);
+ = wi::sext (wi::to_offset (index) - wi::to_offset (low_bound),
+ TYPE_PRECISION (TREE_TYPE (index)));
woffset *= wi::to_offset (unit_size);
byte_offset += woffset.to_shwi ();
}
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 624f2775f7c..db02cbdb1b5 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -82,7 +82,7 @@ add_stmt_to_eh_lp_fn (struct function *ifun, gimple t, int num)
gcc_assert (num != 0);
- n = ggc_alloc_throw_stmt_node ();
+ n = ggc_alloc<throw_stmt_node> ();
n->stmt = t;
n->lp_nr = num;
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 987e81506b7..7e75cce662f 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -67,6 +67,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "target.h"
#include "cfgloop.h"
+#include "builtins.h"
#include "rtl.h" /* FIXME: For asm_str_count. */
@@ -1483,6 +1484,11 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
/* Create a new deep copy of the statement. */
copy = gimple_copy (stmt);
+ /* Clear flags that need revisiting. */
+ if (is_gimple_call (copy)
+ && gimple_call_tail_p (copy))
+ gimple_call_set_tail (copy, false);
+
/* Remap the region numbers for __builtin_eh_{pointer,filter},
RESX and EH_DISPATCH. */
if (id->eh_map)
@@ -1979,7 +1985,8 @@ copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb,
flags = old_edge->flags;
/* Return edges do get a FALLTHRU flag when the get inlined. */
- if (old_edge->dest->index == EXIT_BLOCK && !old_edge->flags
+ if (old_edge->dest->index == EXIT_BLOCK
+ && !(old_edge->flags & (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE|EDGE_FAKE))
&& old_edge->dest->aux != EXIT_BLOCK_PTR_FOR_FN (cfun))
flags |= EDGE_FALLTHRU;
new_edge = make_edge (new_bb, (basic_block) old_edge->dest->aux, flags);
@@ -4349,7 +4356,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
function in any way before this point, as this CALL_EXPR may be
a self-referential call; if we're calling ourselves, we need to
duplicate our body before altering anything. */
- copy_body (id, bb->count,
+ copy_body (id, cg_edge->callee->count,
GCOV_COMPUTE_SCALE (cg_edge->frequency, CGRAPH_FREQ_BASE),
bb, return_block, NULL);
diff --git a/gcc/tree-iterator.c b/gcc/tree-iterator.c
index 37ee7522ba1..c4412bad4d5 100644
--- a/gcc/tree-iterator.c
+++ b/gcc/tree-iterator.c
@@ -131,7 +131,7 @@ tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
}
else
{
- head = ggc_alloc_tree_statement_list_node ();
+ head = ggc_alloc<tree_statement_list_node> ();
head->prev = NULL;
head->next = NULL;
head->stmt = t;
@@ -207,7 +207,7 @@ tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
}
else
{
- head = ggc_alloc_tree_statement_list_node ();
+ head = ggc_alloc<tree_statement_list_node> ();
head->prev = NULL;
head->next = NULL;
head->stmt = t;
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 9c175de4e9d..ba2cc765709 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -1112,6 +1112,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
case OMP_CLAUSE_FINAL:
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
+ case OMP_CLAUSE_DEPEND:
wi->val_only = true;
wi->is_lhs = false;
convert_nonlocal_reference_op (&OMP_CLAUSE_OPERAND (clause, 0),
@@ -1651,6 +1652,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
case OMP_CLAUSE_FINAL:
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
+ case OMP_CLAUSE_DEPEND:
wi->val_only = true;
wi->is_lhs = false;
convert_local_reference_op (&OMP_CLAUSE_OPERAND (clause, 0), &dummy,
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index 3c606b02d41..93f8373f92a 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-propagate.h"
#include "tree-phinodes.h"
#include "ssa-iterators.h"
+#include "builtins.h"
struct object_size_info
{
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index c025b1f0719..3888bb66189 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -472,6 +472,7 @@ extern simple_ipa_opt_pass *make_pass_ipa_tm (gcc::context *ctxt);
extern simple_ipa_opt_pass *make_pass_omp_simd_clone (gcc::context *ctxt);
extern ipa_opt_pass_d *make_pass_ipa_profile (gcc::context *ctxt);
extern ipa_opt_pass_d *make_pass_ipa_cdtor_merge (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_comdats (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_cleanup_cfg_post_optimizing (gcc::context
*ctxt);
diff --git a/gcc/tree-phinodes.c b/gcc/tree-phinodes.c
index 0be431e6068..5bd82335698 100644
--- a/gcc/tree-phinodes.c
+++ b/gcc/tree-phinodes.c
@@ -124,7 +124,7 @@ allocate_phi_node (size_t len)
else
{
phi = static_cast <gimple_statement_phi *> (
- ggc_internal_alloc_stat (size MEM_STAT_INFO));
+ ggc_internal_alloc (size));
if (GATHER_STATISTICS)
{
enum gimple_alloc_kind kind = gimple_alloc_kind (GIMPLE_PHI);
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index d516a9ddaa0..c5b4aeeb4cd 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -3487,12 +3487,6 @@ pp_double_int (pretty_printer *pp, double_int d, bool uns)
pp_wide_integer (pp, d.low);
else if (d.fits_uhwi ())
pp_unsigned_wide_integer (pp, d.low);
- else if (HOST_BITS_PER_DOUBLE_INT == HOST_BITS_PER_WIDEST_INT)
- pp_scalar (pp,
- uns
- ? HOST_WIDEST_INT_PRINT_UNSIGNED : HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) ((((unsigned HOST_WIDEST_INT) d.high << 1)
- << (HOST_BITS_PER_WIDE_INT - 1)) | d.low));
else
{
unsigned HOST_WIDE_INT low = d.low;
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index af723082962..44758556f9b 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -332,7 +332,7 @@ new_scev_info_str (basic_block instantiated_below, tree var)
{
struct scev_info_str *res;
- res = ggc_alloc_scev_info_str ();
+ res = ggc_alloc<scev_info_str> ();
res->name_version = SSA_NAME_VERSION (var);
res->chrec = chrec_not_analyzed_yet;
res->instantiated_below = instantiated_below->index;
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 72c485be521..db91c8b8175 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -112,6 +112,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-pretty-print.h"
#include "ipa-inline.h"
#include "ipa-utils.h"
+#include "builtins.h"
/* Enumeration of all aggregate reductions we can do. */
enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */
@@ -2812,7 +2813,7 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
{
tree ref;
- ref = build_ref_for_model (loc, orig_expr, 0, access, NULL, false);
+ ref = build_ref_for_model (loc, orig_expr, 0, access, gsi, false);
if (write)
{
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 479fa9ce0f0..0371070a67e 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -1594,6 +1594,7 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
/* These read memory pointed to by the first argument. */
case BUILT_IN_STRDUP:
case BUILT_IN_STRNDUP:
+ case BUILT_IN_REALLOC:
{
ao_ref dref;
tree size = NULL_TREE;
@@ -1991,6 +1992,15 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
tree ptr = gimple_call_arg (call, 0);
return ptr_deref_may_alias_ref_p_1 (ptr, ref);
}
+ /* Realloc serves both as allocation point and deallocation point. */
+ case BUILT_IN_REALLOC:
+ {
+ tree ptr = gimple_call_arg (call, 0);
+ /* Unix98 specifies that errno is set on allocation failure. */
+ return ((flag_errno_math
+ && targetm.ref_may_alias_errno (ref))
+ || ptr_deref_may_alias_ref_p_1 (ptr, ref));
+ }
case BUILT_IN_GAMMA_R:
case BUILT_IN_GAMMAF_R:
case BUILT_IN_GAMMAL_R:
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index d7410122c46..66b897743ec 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -154,6 +154,7 @@ along with GCC; see the file COPYING3. If not see
#include "dbgcnt.h"
#include "params.h"
#include "wide-int-print.h"
+#include "builtins.h"
/* Possible lattice values. */
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 5b5adca90b2..c980dfd85e6 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -522,6 +522,14 @@ hashable_expr_equal_p (const struct hashable_expr *expr0,
expr1->ops.call.args[i], 0))
return false;
+ if (stmt_could_throw_p (expr0->ops.call.fn_from))
+ {
+ int lp0 = lookup_stmt_eh_lp (expr0->ops.call.fn_from);
+ int lp1 = lookup_stmt_eh_lp (expr1->ops.call.fn_from);
+ if ((lp0 > 0 || lp1 > 0) && lp0 != lp1)
+ return false;
+ }
+
return true;
}
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 563abe0d2cc..33fede2665a 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see
#include "optabs.h"
#include "tree-ssa-propagate.h"
#include "tree-ssa-dom.h"
+#include "builtins.h"
/* This pass propagates the RHS of assignment statements into use
sites of the LHS of the assignment. It's basically a specialized
@@ -2642,49 +2643,47 @@ associate_plusminus (gimple_stmt_iterator *gsi)
gimple_set_modified (stmt, true);
}
}
- else if (CONVERT_EXPR_CODE_P (def_code) && code == MINUS_EXPR
+ else if (code == MINUS_EXPR
+ && CONVERT_EXPR_CODE_P (def_code)
+ && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
&& TREE_CODE (rhs2) == SSA_NAME)
{
- /* (T)(ptr + adj) - (T)ptr -> (T)adj. */
+ /* (T)(P + A) - (T)P -> (T)A. */
gimple def_stmt2 = SSA_NAME_DEF_STMT (rhs2);
- if (TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
- && is_gimple_assign (def_stmt2)
+ if (is_gimple_assign (def_stmt2)
&& can_propagate_from (def_stmt2)
&& CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2))
&& TREE_CODE (gimple_assign_rhs1 (def_stmt2)) == SSA_NAME)
{
- /* Now we have (T)A - (T)ptr. */
- tree ptr = gimple_assign_rhs1 (def_stmt2);
+ /* Now we have (T)X - (T)P. */
+ tree p = gimple_assign_rhs1 (def_stmt2);
def_stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt));
if (is_gimple_assign (def_stmt2)
- && gimple_assign_rhs_code (def_stmt2) == POINTER_PLUS_EXPR
- && gimple_assign_rhs1 (def_stmt2) == ptr)
+ && can_propagate_from (def_stmt2)
+ && (gimple_assign_rhs_code (def_stmt2) == POINTER_PLUS_EXPR
+ || gimple_assign_rhs_code (def_stmt2) == PLUS_EXPR)
+ && gimple_assign_rhs1 (def_stmt2) == p)
{
- /* And finally (T)(ptr + X) - (T)ptr. */
- tree adj = gimple_assign_rhs2 (def_stmt2);
- /* If the conversion of the pointer adjustment to the
- final type requires a sign- or zero-extension we
- have to punt - it is not defined which one is
- correct. */
- if (TYPE_PRECISION (TREE_TYPE (rhs1))
- <= TYPE_PRECISION (TREE_TYPE (adj))
- || (TREE_CODE (adj) == INTEGER_CST
- && tree_int_cst_sign_bit (adj) == 0))
+ /* And finally (T)(P + A) - (T)P. */
+ tree a = gimple_assign_rhs2 (def_stmt2);
+ /* For pointer types, if the conversion of A to the final
+ type requires a sign- or zero-extension, then we have
+ to punt - it is not defined which one is correct. */
+ if (!POINTER_TYPE_P (TREE_TYPE (rhs1))
+ || TYPE_PRECISION (TREE_TYPE (rhs1))
+ <= TYPE_PRECISION (TREE_TYPE (a))
+ || (TREE_CODE (a) == INTEGER_CST
+ && tree_int_cst_sign_bit (a) == 0))
{
if (useless_type_conversion_p (TREE_TYPE (rhs1),
- TREE_TYPE (adj)))
- {
- code = TREE_CODE (adj);
- rhs1 = adj;
- }
+ TREE_TYPE (a)))
+ code = TREE_CODE (a);
else
- {
- code = NOP_EXPR;
- rhs1 = adj;
- }
+ code = NOP_EXPR;
+ rhs1 = a;
rhs2 = NULL_TREE;
gimple_assign_set_rhs_with_ops (gsi, code, rhs1,
- NULL_TREE);
+ rhs2);
gcc_assert (gsi_stmt (*gsi) == stmt);
gimple_set_modified (stmt, true);
}
diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c
index e332918fd16..1bbc1cd3b6a 100644
--- a/gcc/tree-ssa-loop-ivcanon.c
+++ b/gcc/tree-ssa-loop-ivcanon.c
@@ -68,6 +68,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "target.h"
#include "tree-cfgcleanup.h"
+#include "builtins.h"
/* Specifies types of loops that may be unrolled. */
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index b0d39271798..7546ff6fe83 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -109,6 +109,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-propagate.h"
#include "expmed.h"
#include "tree-ssa-address.h"
+#include "builtins.h"
/* FIXME: Expressions are expanded to RTL in this pass to determine the
cost of different addressing modes. This should be moved to a TBD
@@ -928,36 +929,60 @@ determine_base_object (tree expr)
}
}
+/* Return true if address expression with non-DECL_P operand appears
+ in EXPR. */
+
+static bool
+contain_complex_addr_expr (tree expr)
+{
+ bool res = false;
+
+ STRIP_NOPS (expr);
+ switch (TREE_CODE (expr))
+ {
+ case POINTER_PLUS_EXPR:
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ res |= contain_complex_addr_expr (TREE_OPERAND (expr, 0));
+ res |= contain_complex_addr_expr (TREE_OPERAND (expr, 1));
+ break;
+
+ case ADDR_EXPR:
+ return (!DECL_P (TREE_OPERAND (expr, 0)));
+
+ default:
+ return false;
+ }
+
+ return res;
+}
+
/* Allocates an induction variable with given initial value BASE and step STEP
for loop LOOP. */
static struct iv *
alloc_iv (tree base, tree step)
{
- tree base_object = base;
+ tree expr = base;
struct iv *iv = XCNEW (struct iv);
gcc_assert (step != NULL_TREE);
- /* Lower all address expressions except ones with DECL_P as operand.
+ /* Lower address expression in base except ones with DECL_P as operand.
By doing this:
1) More accurate cost can be computed for address expressions;
2) Duplicate candidates won't be created for bases in different
forms, like &a[0] and &a. */
- STRIP_NOPS (base_object);
- if (TREE_CODE (base_object) == ADDR_EXPR
- && !DECL_P (TREE_OPERAND (base_object, 0)))
+ STRIP_NOPS (expr);
+ if ((TREE_CODE (expr) == ADDR_EXPR && !DECL_P (TREE_OPERAND (expr, 0)))
+ || contain_complex_addr_expr (expr))
{
aff_tree comb;
- widest_int size;
- base_object = get_inner_reference_aff (TREE_OPERAND (base_object, 0),
- &comb, &size);
- gcc_assert (base_object != NULL_TREE);
- base_object = build_fold_addr_expr (base_object);
+ tree_to_aff_combination (expr, TREE_TYPE (base), &comb);
base = fold_convert (TREE_TYPE (base), aff_combination_to_tree (&comb));
}
iv->base = base;
- iv->base_object = determine_base_object (base_object);
+ iv->base_object = determine_base_object (base);
iv->step = step;
iv->biv_p = false;
iv->have_use_for = false;
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index a48ad10424e..73376bc8e75 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -2674,7 +2674,7 @@ record_estimate (struct loop *loop, tree bound, const widest_int &i_bound,
|| loop->nb_iterations == NULL_TREE
|| TREE_CODE (loop->nb_iterations) != INTEGER_CST))
{
- struct nb_iter_bound *elt = ggc_alloc_nb_iter_bound ();
+ struct nb_iter_bound *elt = ggc_alloc<nb_iter_bound> ();
elt->bound = i_bound;
elt->stmt = at_stmt;
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 336626d0886..68dfa17b85e 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -98,6 +98,7 @@ along with GCC; see the file COPYING3. If not see
#include "is-a.h"
#include "gimple.h"
#include "gimple-iterator.h"
+#include "gimplify.h"
#include "gimplify-me.h"
#include "stor-layout.h"
#include "gimple-ssa.h"
@@ -113,6 +114,7 @@ along with GCC; see the file COPYING3. If not see
#include "alloc-pool.h"
#include "target.h"
#include "gimple-pretty-print.h"
+#include "builtins.h"
/* FIXME: RTL headers have to be included here for optabs. */
#include "rtl.h" /* Because optabs.h wants enum rtx_code. */
@@ -170,15 +172,15 @@ static struct
static struct
{
- /* Number of hand-written 16-bit bswaps found. */
+ /* Number of hand-written 16-bit nop / bswaps found. */
int found_16bit;
- /* Number of hand-written 32-bit bswaps found. */
+ /* Number of hand-written 32-bit nop / bswaps found. */
int found_32bit;
- /* Number of hand-written 64-bit bswaps found. */
+ /* Number of hand-written 64-bit nop / bswaps found. */
int found_64bit;
-} bswap_stats;
+} nop_stats, bswap_stats;
static struct
{
@@ -1604,13 +1606,43 @@ make_pass_cse_sincos (gcc::context *ctxt)
0 - byte has the value 0
1..size - byte contains the content of the byte
- number indexed with that value minus one */
+ number indexed with that value minus one.
+
+ To detect permutations on memory sources (arrays and structures), a symbolic
+ number is also associated a base address (the array or structure the load is
+ made from), an offset from the base address and a range which gives the
+ difference between the highest and lowest accessed memory location to make
+ such a symbolic number. The range is thus different from size which reflects
+ the size of the type of current expression. Note that for non memory source,
+ range holds the same value as size.
+
+ For instance, for an array char a[], (short) a[0] | (short) a[3] would have
+ a size of 2 but a range of 4 while (short) a[0] | ((short) a[0] << 1) would
+ still have a size of 2 but this time a range of 1. */
struct symbolic_number {
- unsigned HOST_WIDEST_INT n;
+ uint64_t n;
int size;
+ tree base_addr;
+ tree offset;
+ HOST_WIDE_INT bytepos;
+ tree alias_set;
+ tree vuse;
+ unsigned HOST_WIDE_INT range;
};
+/* The number which the find_bswap_or_nop_1 result should match in
+ order to have a nop. The number is masked according to the size of
+ the symbolic number before using it. */
+#define CMPNOP (sizeof (int64_t) < 8 ? 0 : \
+ (uint64_t)0x08070605 << 32 | 0x04030201)
+
+/* The number which the find_bswap_or_nop_1 result should match in
+ order to have a byte swap. The number is masked according to the
+ size of the symbolic number before using it. */
+#define CMPXCHG (sizeof (int64_t) < 8 ? 0 : \
+ (uint64_t)0x01020304 << 32 | 0x05060708)
+
/* Perform a SHIFT or ROTATE operation by COUNT bits on symbolic
number N. Return false if the requested operation is not permitted
on a symbolic number. */
@@ -1625,8 +1657,8 @@ do_shift_rotate (enum tree_code code,
/* Zero out the extra bits of N in order to avoid them being shifted
into the significant bits. */
- if (n->size < (int)sizeof (HOST_WIDEST_INT))
- n->n &= ((unsigned HOST_WIDEST_INT)1 << (n->size * BITS_PER_UNIT)) - 1;
+ if (n->size < (int)sizeof (int64_t))
+ n->n &= ((uint64_t)1 << (n->size * BITS_PER_UNIT)) - 1;
switch (code)
{
@@ -1646,8 +1678,8 @@ do_shift_rotate (enum tree_code code,
return false;
}
/* Zero unused bits for size. */
- if (n->size < (int)sizeof (HOST_WIDEST_INT))
- n->n &= ((unsigned HOST_WIDEST_INT)1 << (n->size * BITS_PER_UNIT)) - 1;
+ if (n->size < (int)sizeof (int64_t))
+ n->n &= ((uint64_t)1 << (n->size * BITS_PER_UNIT)) - 1;
return true;
}
@@ -1670,13 +1702,76 @@ verify_symbolic_number_p (struct symbolic_number *n, gimple stmt)
return true;
}
-/* find_bswap_1 invokes itself recursively with N and tries to perform
- the operation given by the rhs of STMT on the result. If the
- operation could successfully be executed the function returns the
- tree expression of the source operand and NULL otherwise. */
+/* Check if STMT might be a byte swap or a nop from a memory source and returns
+ the answer. If so, REF is that memory source and the base of the memory area
+ accessed and the offset of the access from that base are recorded in N. */
+
+bool
+find_bswap_or_nop_load (gimple stmt, tree ref, struct symbolic_number *n)
+{
+ /* Leaf node is an array or component ref. Memorize its base and
+ offset from base to compare to other such leaf node. */
+ HOST_WIDE_INT bitsize, bitpos;
+ enum machine_mode mode;
+ int unsignedp, volatilep;
+
+ if (!gimple_assign_load_p (stmt) || gimple_has_volatile_ops (stmt))
+ return false;
+
+ n->base_addr = get_inner_reference (ref, &bitsize, &bitpos, &n->offset,
+ &mode, &unsignedp, &volatilep, false);
+
+ if (TREE_CODE (n->base_addr) == MEM_REF)
+ {
+ offset_int bit_offset = 0;
+ tree off = TREE_OPERAND (n->base_addr, 1);
+
+ if (!integer_zerop (off))
+ {
+ offset_int boff, coff = mem_ref_offset (n->base_addr);
+ boff = wi::lshift (coff, LOG2_BITS_PER_UNIT);
+ bit_offset += boff;
+ }
+
+ n->base_addr = TREE_OPERAND (n->base_addr, 0);
+
+ /* Avoid returning a negative bitpos as this may wreak havoc later. */
+ if (wi::neg_p (bit_offset))
+ {
+ offset_int mask = wi::mask <offset_int> (LOG2_BITS_PER_UNIT, false);
+ offset_int tem = bit_offset.and_not (mask);
+ /* TEM is the bitpos rounded to BITS_PER_UNIT towards -Inf.
+ Subtract it to BIT_OFFSET and add it (scaled) to OFFSET. */
+ bit_offset -= tem;
+ tem = wi::arshift (tem, LOG2_BITS_PER_UNIT);
+ if (n->offset)
+ n->offset = size_binop (PLUS_EXPR, n->offset,
+ wide_int_to_tree (sizetype, tem));
+ else
+ n->offset = wide_int_to_tree (sizetype, tem);
+ }
+
+ bitpos += bit_offset.to_shwi ();
+ }
+
+ if (bitpos % BITS_PER_UNIT)
+ return false;
+ if (bitsize % BITS_PER_UNIT)
+ return false;
+
+ n->bytepos = bitpos / BITS_PER_UNIT;
+ n->alias_set = reference_alias_ptr_type (ref);
+ n->vuse = gimple_vuse (stmt);
+ return true;
+}
+
+/* find_bswap_or_nop_1 invokes itself recursively with N and tries to perform
+ the operation given by the rhs of STMT on the result. If the operation
+ could successfully be executed the function returns the tree expression of
+ the source operand and NULL otherwise. */
static tree
-find_bswap_1 (gimple stmt, struct symbolic_number *n, int limit)
+find_bswap_or_nop_1 (gimple stmt, struct symbolic_number *n, int limit)
{
enum tree_code code;
tree rhs1, rhs2 = NULL;
@@ -1689,6 +1784,9 @@ find_bswap_1 (gimple stmt, struct symbolic_number *n, int limit)
rhs1 = gimple_assign_rhs1 (stmt);
+ if (find_bswap_or_nop_load (stmt, rhs1, n))
+ return rhs1;
+
if (TREE_CODE (rhs1) != SSA_NAME)
return NULL_TREE;
@@ -1715,11 +1813,11 @@ find_bswap_1 (gimple stmt, struct symbolic_number *n, int limit)
&& code != CONVERT_EXPR)
return NULL_TREE;
- source_expr1 = find_bswap_1 (rhs1_stmt, n, limit - 1);
+ source_expr1 = find_bswap_or_nop_1 (rhs1_stmt, n, limit - 1);
- /* If find_bswap_1 returned NULL STMT is a leaf node and we have
- to initialize the symbolic number. */
- if (!source_expr1)
+ /* If find_bswap_or_nop_1 returned NULL, STMT is a leaf node and
+ we have to initialize the symbolic number. */
+ if (!source_expr1 || gimple_assign_load_p (rhs1_stmt))
{
/* Set up the symbolic number N by setting each byte to a
value between 1 and the byte size of rhs1. The highest
@@ -1729,14 +1827,18 @@ find_bswap_1 (gimple stmt, struct symbolic_number *n, int limit)
if (n->size % BITS_PER_UNIT != 0)
return NULL_TREE;
n->size /= BITS_PER_UNIT;
- n->n = (sizeof (HOST_WIDEST_INT) < 8 ? 0 :
- (unsigned HOST_WIDEST_INT)0x08070605 << 32 | 0x04030201);
+ n->range = n->size;
+ n->n = CMPNOP;
- if (n->size < (int)sizeof (HOST_WIDEST_INT))
- n->n &= ((unsigned HOST_WIDEST_INT)1 <<
+ if (n->size < (int)sizeof (int64_t))
+ n->n &= ((uint64_t)1 <<
(n->size * BITS_PER_UNIT)) - 1;
- source_expr1 = rhs1;
+ if (!source_expr1)
+ {
+ n->base_addr = n->offset = n->alias_set = n->vuse = NULL_TREE;
+ source_expr1 = rhs1;
+ }
}
switch (code)
@@ -1744,8 +1846,8 @@ find_bswap_1 (gimple stmt, struct symbolic_number *n, int limit)
case BIT_AND_EXPR:
{
int i;
- unsigned HOST_WIDEST_INT val = widest_int_cst_value (rhs2);
- unsigned HOST_WIDEST_INT tmp = val;
+ uint64_t val = int_cst_value (rhs2);
+ uint64_t tmp = val;
/* Only constants masking full bytes are allowed. */
for (i = 0; i < n->size; i++, tmp >>= BITS_PER_UNIT)
@@ -1770,13 +1872,15 @@ find_bswap_1 (gimple stmt, struct symbolic_number *n, int limit)
if (type_size % BITS_PER_UNIT != 0)
return NULL_TREE;
- if (type_size / BITS_PER_UNIT < (int)(sizeof (HOST_WIDEST_INT)))
+ if (type_size / BITS_PER_UNIT < (int)(sizeof (int64_t)))
{
/* If STMT casts to a smaller type mask out the bits not
belonging to the target type. */
- n->n &= ((unsigned HOST_WIDEST_INT)1 << type_size) - 1;
+ n->n &= ((uint64_t)1 << type_size) - 1;
}
n->size = type_size / BITS_PER_UNIT;
+ if (!n->base_addr)
+ n->range = n->size;
}
break;
default:
@@ -1791,7 +1895,7 @@ find_bswap_1 (gimple stmt, struct symbolic_number *n, int limit)
{
int i;
struct symbolic_number n1, n2;
- unsigned HOST_WIDEST_INT mask;
+ uint64_t mask;
tree source_expr2;
if (code != BIT_IOR_EXPR)
@@ -1805,21 +1909,83 @@ find_bswap_1 (gimple stmt, struct symbolic_number *n, int limit)
switch (code)
{
case BIT_IOR_EXPR:
- source_expr1 = find_bswap_1 (rhs1_stmt, &n1, limit - 1);
+ source_expr1 = find_bswap_or_nop_1 (rhs1_stmt, &n1, limit - 1);
if (!source_expr1)
return NULL_TREE;
- source_expr2 = find_bswap_1 (rhs2_stmt, &n2, limit - 1);
+ source_expr2 = find_bswap_or_nop_1 (rhs2_stmt, &n2, limit - 1);
+
+ if (n1.size != n2.size || !source_expr2)
+ return NULL_TREE;
- if (source_expr1 != source_expr2
- || n1.size != n2.size)
+ if (!n1.vuse != !n2.vuse ||
+ (n1.vuse && !operand_equal_p (n1.vuse, n2.vuse, 0)))
return NULL_TREE;
+ if (source_expr1 != source_expr2)
+ {
+ int64_t inc, mask;
+ unsigned i;
+ HOST_WIDE_INT off_sub;
+ struct symbolic_number *n_ptr;
+
+ if (!n1.base_addr || !n2.base_addr
+ || !operand_equal_p (n1.base_addr, n2.base_addr, 0))
+ return NULL_TREE;
+ if (!n1.offset != !n2.offset ||
+ (n1.offset && !operand_equal_p (n1.offset, n2.offset, 0)))
+ return NULL_TREE;
+
+ /* We swap n1 with n2 to have n1 < n2. */
+ if (n2.bytepos < n1.bytepos)
+ {
+ struct symbolic_number tmpn;
+
+ tmpn = n2;
+ n2 = n1;
+ n1 = tmpn;
+ source_expr1 = source_expr2;
+ }
+
+ off_sub = n2.bytepos - n1.bytepos;
+
+ /* Check that the range of memory covered < biggest int size. */
+ if (off_sub + n2.range > (int) sizeof (int64_t))
+ return NULL_TREE;
+ n->range = n2.range + off_sub;
+
+ /* Reinterpret byte marks in symbolic number holding the value of
+ bigger weight according to host endianness. */
+ inc = BYTES_BIG_ENDIAN ? off_sub + n2.range - n1.range : off_sub;
+ mask = 0xFF;
+ if (BYTES_BIG_ENDIAN)
+ n_ptr = &n1;
+ else
+ n_ptr = &n2;
+ for (i = 0; i < sizeof (int64_t); i++, inc <<= 8,
+ mask <<= 8)
+ {
+ if (n_ptr->n & mask)
+ n_ptr->n += inc;
+ }
+ }
+ else
+ n->range = n1.range;
+
+ if (!n1.alias_set
+ || alias_ptr_types_compatible_p (n1.alias_set, n2.alias_set))
+ n->alias_set = n1.alias_set;
+ else
+ n->alias_set = ptr_type_node;
+ n->vuse = n1.vuse;
+ n->base_addr = n1.base_addr;
+ n->offset = n1.offset;
+ n->bytepos = n1.bytepos;
n->size = n1.size;
for (i = 0, mask = 0xff; i < n->size; i++, mask <<= BITS_PER_UNIT)
{
- unsigned HOST_WIDEST_INT masked1, masked2;
+ uint64_t masked1, masked2;
masked1 = n1.n & mask;
masked2 = n2.n & mask;
@@ -1840,57 +2006,75 @@ find_bswap_1 (gimple stmt, struct symbolic_number *n, int limit)
return NULL_TREE;
}
-/* Check if STMT completes a bswap implementation consisting of ORs,
- SHIFTs and ANDs. Return the source tree expression on which the
- byte swap is performed and NULL if no bswap was found. */
+/* Check if STMT completes a bswap implementation or a read in a given
+ endianness consisting of ORs, SHIFTs and ANDs and sets *BSWAP
+ accordingly. It also sets N to represent the kind of operations
+ performed: size of the resulting expression and whether it works on
+ a memory source, and if so alias-set and vuse. At last, the
+ function returns the source tree expression. */
static tree
-find_bswap (gimple stmt)
+find_bswap_or_nop (gimple stmt, struct symbolic_number *n, bool *bswap)
{
-/* The number which the find_bswap result should match in order to
- have a full byte swap. The number is shifted to the left according
- to the size of the symbolic number before using it. */
- unsigned HOST_WIDEST_INT cmp =
- sizeof (HOST_WIDEST_INT) < 8 ? 0 :
- (unsigned HOST_WIDEST_INT)0x01020304 << 32 | 0x05060708;
-
- struct symbolic_number n;
+/* The number which the find_bswap_or_nop_1 result should match in order
+ to have a full byte swap. The number is shifted to the right
+ according to the size of the symbolic number before using it. */
+ uint64_t cmpxchg = CMPXCHG;
+ uint64_t cmpnop = CMPNOP;
+
tree source_expr;
int limit;
/* The last parameter determines the depth search limit. It usually
- correlates directly to the number of bytes to be touched. We
- increase that number by three here in order to also
- cover signed -> unsigned converions of the src operand as can be seen
+ correlates directly to the number n of bytes to be touched. We
+ increase that number by log2(n) + 1 here in order to also
+ cover signed -> unsigned conversions of the src operand as can be seen
in libgcc, and for initial shift/and operation of the src operand. */
limit = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (gimple_expr_type (stmt)));
limit += 1 + (int) ceil_log2 ((unsigned HOST_WIDE_INT) limit);
- source_expr = find_bswap_1 (stmt, &n, limit);
+ source_expr = find_bswap_or_nop_1 (stmt, n, limit);
if (!source_expr)
return NULL_TREE;
- /* Zero out the extra bits of N and CMP. */
- if (n.size < (int)sizeof (HOST_WIDEST_INT))
+ /* Find real size of result (highest non zero byte). */
+ if (n->base_addr)
{
- unsigned HOST_WIDEST_INT mask =
- ((unsigned HOST_WIDEST_INT)1 << (n.size * BITS_PER_UNIT)) - 1;
+ int rsize;
+ uint64_t tmpn;
- n.n &= mask;
- cmp >>= (sizeof (HOST_WIDEST_INT) - n.size) * BITS_PER_UNIT;
+ for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_UNIT, rsize++);
+ n->range = rsize;
}
- /* A complete byte swap should make the symbolic number to start
- with the largest digit in the highest order byte. */
- if (cmp != n.n)
+ /* Zero out the extra bits of N and CMP*. */
+ if (n->range < (int)sizeof (int64_t))
+ {
+ uint64_t mask;
+
+ mask = ((uint64_t)1 << (n->range * BITS_PER_UNIT)) - 1;
+ cmpxchg >>= (sizeof (int64_t) - n->range) * BITS_PER_UNIT;
+ cmpnop &= mask;
+ }
+
+ /* A complete byte swap should make the symbolic number to start with
+ the largest digit in the highest order byte. Unchanged symbolic
+ number indicates a read with same endianness as host architecture. */
+ if (n->n == cmpnop)
+ *bswap = false;
+ else if (n->n == cmpxchg)
+ *bswap = true;
+ else
+ return NULL_TREE;
+
+ /* Useless bit manipulation performed by code. */
+ if (!n->base_addr && n->n == cmpnop)
return NULL_TREE;
+ n->range *= BITS_PER_UNIT;
return source_expr;
}
-/* Find manual byte swap implementations and turn them into a bswap
- builtin invokation. */
-
namespace {
const pass_data pass_data_optimize_bswap =
@@ -1924,6 +2108,156 @@ public:
}; // class pass_optimize_bswap
+/* Perform the bswap optimization: replace the statement STMT at GSI
+ with load type, VUSE and set-alias as described by N if a memory
+ source is involved (N->base_addr is non null), followed by the
+ builtin bswap invocation in FNDECL if BSWAP is true. SRC gives
+ the source on which STMT is operating and N->range gives the
+ size of the expression involved for maintaining some statistics. */
+
+static bool
+bswap_replace (gimple stmt, gimple_stmt_iterator *gsi, tree src, tree fndecl,
+ tree bswap_type, tree load_type, struct symbolic_number *n,
+ bool bswap)
+{
+ tree tmp, tgt;
+ gimple call;
+
+ tgt = gimple_assign_lhs (stmt);
+
+ /* Need to load the value from memory first. */
+ if (n->base_addr)
+ {
+ tree addr_expr, addr_tmp, val_expr, val_tmp;
+ tree load_offset_ptr, aligned_load_type;
+ gimple addr_stmt, load_stmt;
+ unsigned align;
+
+ align = get_object_alignment (src);
+ if (bswap && SLOW_UNALIGNED_ACCESS (TYPE_MODE (load_type), align))
+ return false;
+
+ /* Compute address to load from and cast according to the size
+ of the load. */
+ addr_expr = build_fold_addr_expr (unshare_expr (src));
+ if (is_gimple_min_invariant (addr_expr))
+ addr_tmp = addr_expr;
+ else
+ {
+ addr_tmp = make_temp_ssa_name (TREE_TYPE (addr_expr), NULL,
+ "load_src");
+ addr_stmt = gimple_build_assign (addr_tmp, addr_expr);
+ gsi_insert_before (gsi, addr_stmt, GSI_SAME_STMT);
+ }
+
+ /* Perform the load. */
+ aligned_load_type = load_type;
+ if (align < TYPE_ALIGN (load_type))
+ aligned_load_type = build_aligned_type (load_type, align);
+ load_offset_ptr = build_int_cst (n->alias_set, 0);
+ val_expr = fold_build2 (MEM_REF, aligned_load_type, addr_tmp,
+ load_offset_ptr);
+
+ if (!bswap)
+ {
+ if (n->range == 16)
+ nop_stats.found_16bit++;
+ else if (n->range == 32)
+ nop_stats.found_32bit++;
+ else
+ {
+ gcc_assert (n->range == 64);
+ nop_stats.found_64bit++;
+ }
+
+ /* Convert the result of load if necessary. */
+ if (!useless_type_conversion_p (TREE_TYPE (tgt), load_type))
+ {
+ val_tmp = make_temp_ssa_name (aligned_load_type, NULL,
+ "load_dst");
+ load_stmt = gimple_build_assign (val_tmp, val_expr);
+ gimple_set_vuse (load_stmt, n->vuse);
+ gsi_insert_before (gsi, load_stmt, GSI_SAME_STMT);
+ gimple_assign_set_rhs_with_ops_1 (gsi, NOP_EXPR, val_tmp,
+ NULL_TREE, NULL_TREE);
+ }
+ else
+ gimple_assign_set_rhs_with_ops_1 (gsi, MEM_REF, val_expr,
+ NULL_TREE, NULL_TREE);
+ update_stmt (gsi_stmt (*gsi));
+
+ if (dump_file)
+ {
+ fprintf (dump_file,
+ "%d bit load in host endianness found at: ",
+ (int)n->range);
+ print_gimple_stmt (dump_file, stmt, 0, 0);
+ }
+ return true;
+ }
+ else
+ {
+ val_tmp = make_temp_ssa_name (aligned_load_type, NULL, "load_dst");
+ load_stmt = gimple_build_assign (val_tmp, val_expr);
+ gimple_set_vuse (load_stmt, n->vuse);
+ gsi_insert_before (gsi, load_stmt, GSI_SAME_STMT);
+ }
+ src = val_tmp;
+ }
+
+ if (n->range == 16)
+ bswap_stats.found_16bit++;
+ else if (n->range == 32)
+ bswap_stats.found_32bit++;
+ else
+ {
+ gcc_assert (n->range == 64);
+ bswap_stats.found_64bit++;
+ }
+
+ tmp = src;
+
+ /* Convert the src expression if necessary. */
+ if (!useless_type_conversion_p (TREE_TYPE (tmp), bswap_type))
+ {
+ gimple convert_stmt;
+ tmp = make_temp_ssa_name (bswap_type, NULL, "bswapsrc");
+ convert_stmt = gimple_build_assign_with_ops (NOP_EXPR, tmp, src, NULL);
+ gsi_insert_before (gsi, convert_stmt, GSI_SAME_STMT);
+ }
+
+ call = gimple_build_call (fndecl, 1, tmp);
+
+ tmp = tgt;
+
+ /* Convert the result if necessary. */
+ if (!useless_type_conversion_p (TREE_TYPE (tgt), bswap_type))
+ {
+ gimple convert_stmt;
+ tmp = make_temp_ssa_name (bswap_type, NULL, "bswapdst");
+ convert_stmt = gimple_build_assign_with_ops (NOP_EXPR, tgt, tmp, NULL);
+ gsi_insert_after (gsi, convert_stmt, GSI_SAME_STMT);
+ }
+
+ gimple_call_set_lhs (call, tmp);
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "%d bit bswap implementation found at: ",
+ (int)n->range);
+ print_gimple_stmt (dump_file, stmt, 0, 0);
+ }
+
+ gsi_insert_after (gsi, call, GSI_SAME_STMT);
+ gsi_remove (gsi, true);
+ return true;
+}
+
+/* Find manual byte swap implementations as well as load in a given
+ endianness. Byte swaps are turned into a bswap builtin invokation
+ while endian loads are converted to bswap builtin invokation or
+ simple load according to the host endianness. */
+
unsigned int
pass_optimize_bswap::execute (function *fun)
{
@@ -1935,9 +2269,6 @@ pass_optimize_bswap::execute (function *fun)
if (BITS_PER_UNIT != 8)
return 0;
- if (sizeof (HOST_WIDEST_INT) < 8)
- return 0;
-
bswap16_p = (builtin_decl_explicit_p (BUILT_IN_BSWAP16)
&& optab_handler (bswap_optab, HImode) != CODE_FOR_nothing);
bswap32_p = (builtin_decl_explicit_p (BUILT_IN_BSWAP32)
@@ -1946,9 +2277,6 @@ pass_optimize_bswap::execute (function *fun)
&& (optab_handler (bswap_optab, DImode) != CODE_FOR_nothing
|| (bswap32_p && word_mode == SImode)));
- if (!bswap16_p && !bswap32_p && !bswap64_p)
- return 0;
-
/* Determine the argument type of the builtins. The code later on
assumes that the return and argument type are the same. */
if (bswap16_p)
@@ -1969,6 +2297,7 @@ pass_optimize_bswap::execute (function *fun)
bswap64_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
}
+ memset (&nop_stats, 0, sizeof (nop_stats));
memset (&bswap_stats, 0, sizeof (bswap_stats));
FOR_EACH_BB_FN (bb, fun)
@@ -1982,21 +2311,24 @@ pass_optimize_bswap::execute (function *fun)
for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
{
gimple stmt = gsi_stmt (gsi);
- tree bswap_src, bswap_type;
- tree bswap_tmp;
- tree fndecl = NULL_TREE;
- int type_size;
- gimple call;
+ tree fndecl = NULL_TREE, bswap_type = NULL_TREE;
+ tree src, load_type;
+ struct symbolic_number n;
+ bool bswap;
if (!is_gimple_assign (stmt)
|| gimple_assign_rhs_code (stmt) != BIT_IOR_EXPR)
continue;
- type_size = TYPE_PRECISION (gimple_expr_type (stmt));
+ src = find_bswap_or_nop (stmt, &n, &bswap);
+
+ if (!src)
+ continue;
- switch (type_size)
+ switch (n.range)
{
case 16:
+ load_type = uint16_type_node;
if (bswap16_p)
{
fndecl = builtin_decl_explicit (BUILT_IN_BSWAP16);
@@ -2004,6 +2336,7 @@ pass_optimize_bswap::execute (function *fun)
}
break;
case 32:
+ load_type = uint32_type_node;
if (bswap32_p)
{
fndecl = builtin_decl_explicit (BUILT_IN_BSWAP32);
@@ -2011,6 +2344,7 @@ pass_optimize_bswap::execute (function *fun)
}
break;
case 64:
+ load_type = uint64_type_node;
if (bswap64_p)
{
fndecl = builtin_decl_explicit (BUILT_IN_BSWAP64);
@@ -2021,62 +2355,21 @@ pass_optimize_bswap::execute (function *fun)
continue;
}
- if (!fndecl)
+ if (bswap && !fndecl)
continue;
- bswap_src = find_bswap (stmt);
-
- if (!bswap_src)
- continue;
-
- changed = true;
- if (type_size == 16)
- bswap_stats.found_16bit++;
- else if (type_size == 32)
- bswap_stats.found_32bit++;
- else
- bswap_stats.found_64bit++;
-
- bswap_tmp = bswap_src;
-
- /* Convert the src expression if necessary. */
- if (!useless_type_conversion_p (TREE_TYPE (bswap_tmp), bswap_type))
- {
- gimple convert_stmt;
- bswap_tmp = make_temp_ssa_name (bswap_type, NULL, "bswapsrc");
- convert_stmt = gimple_build_assign_with_ops
- (NOP_EXPR, bswap_tmp, bswap_src, NULL);
- gsi_insert_before (&gsi, convert_stmt, GSI_SAME_STMT);
- }
-
- call = gimple_build_call (fndecl, 1, bswap_tmp);
-
- bswap_tmp = gimple_assign_lhs (stmt);
-
- /* Convert the result if necessary. */
- if (!useless_type_conversion_p (TREE_TYPE (bswap_tmp), bswap_type))
- {
- gimple convert_stmt;
- bswap_tmp = make_temp_ssa_name (bswap_type, NULL, "bswapdst");
- convert_stmt = gimple_build_assign_with_ops
- (NOP_EXPR, gimple_assign_lhs (stmt), bswap_tmp, NULL);
- gsi_insert_after (&gsi, convert_stmt, GSI_SAME_STMT);
- }
-
- gimple_call_set_lhs (call, bswap_tmp);
-
- if (dump_file)
- {
- fprintf (dump_file, "%d bit bswap implementation found at: ",
- (int)type_size);
- print_gimple_stmt (dump_file, stmt, 0, 0);
- }
-
- gsi_insert_after (&gsi, call, GSI_SAME_STMT);
- gsi_remove (&gsi, true);
+ if (bswap_replace (stmt, &gsi, src, fndecl, bswap_type, load_type,
+ &n, bswap))
+ changed = true;
}
}
+ statistics_counter_event (fun, "16-bit nop implementations found",
+ nop_stats.found_16bit);
+ statistics_counter_event (fun, "32-bit nop implementations found",
+ nop_stats.found_32bit);
+ statistics_counter_event (fun, "64-bit nop implementations found",
+ nop_stats.found_64bit);
statistics_counter_event (fun, "16-bit bswap implementations found",
bswap_stats.found_16bit);
statistics_counter_event (fun, "32-bit bswap implementations found",
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 03d3e4d271a..492eee76835 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -276,8 +276,8 @@ ssa_operand_alloc (struct function *fn, unsigned size)
}
- ptr = ggc_alloc_ssa_operand_memory_d (sizeof (void *)
- + gimple_ssa_operands (fn)->ssa_operand_mem_size);
+ ptr = (ssa_operand_memory_d *) ggc_internal_alloc
+ (sizeof (void *) + gimple_ssa_operands (fn)->ssa_operand_mem_size);
ptr->next = gimple_ssa_operands (fn)->operand_memory;
gimple_ssa_operands (fn)->operand_memory = ptr;
diff --git a/gcc/tree-ssa-operands.h b/gcc/tree-ssa-operands.h
index 5f9edd4e3e8..42fe5a721e5 100644
--- a/gcc/tree-ssa-operands.h
+++ b/gcc/tree-ssa-operands.h
@@ -45,7 +45,7 @@ typedef struct use_optype_d *use_optype_p;
operand memory manager. Operands are suballocated out of this block. The
MEM array varies in size. */
-struct GTY((chain_next("%h.next"), variable_size)) ssa_operand_memory_d {
+struct GTY((chain_next("%h.next"))) ssa_operand_memory_d {
struct ssa_operand_memory_d *next;
char mem[1];
};
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index 28a6ea76e85..e3b6f1dd6a3 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see
#include "expr.h"
#include "optabs.h"
#include "tree-scalar-evolution.h"
+#include "tree-inline.h"
#ifndef HAVE_conditional_move
#define HAVE_conditional_move (0)
@@ -659,6 +660,64 @@ operand_equal_for_value_replacement (const_tree arg0, const_tree arg1,
return false;
}
+/* Returns true if ARG is a neutral element for operation CODE
+ on the RIGHT side. */
+
+static bool
+neutral_element_p (tree_code code, tree arg, bool right)
+{
+ switch (code)
+ {
+ case PLUS_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ return integer_zerop (arg);
+
+ case LROTATE_EXPR:
+ case RROTATE_EXPR:
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case MINUS_EXPR:
+ case POINTER_PLUS_EXPR:
+ return right && integer_zerop (arg);
+
+ case MULT_EXPR:
+ return integer_onep (arg);
+
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case EXACT_DIV_EXPR:
+ return right && integer_onep (arg);
+
+ case BIT_AND_EXPR:
+ return integer_all_onesp (arg);
+
+ default:
+ return false;
+ }
+}
+
+/* Returns true if ARG is an absorbing element for operation CODE. */
+
+static bool
+absorbing_element_p (tree_code code, tree arg)
+{
+ switch (code)
+ {
+ case BIT_IOR_EXPR:
+ return integer_all_onesp (arg);
+
+ case MULT_EXPR:
+ case BIT_AND_EXPR:
+ return integer_zerop (arg);
+
+ default:
+ return false;
+ }
+}
+
/* The function value_replacement does the main work of doing the value
replacement. Return non-zero if the replacement is done. Otherwise return
0. If we remove the middle basic block, return 2.
@@ -683,9 +742,7 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
/* If there is a statement in MIDDLE_BB that defines one of the PHI
arguments, then adjust arg0 or arg1. */
- gsi = gsi_after_labels (middle_bb);
- if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
- gsi_next_nondebug (&gsi);
+ gsi = gsi_start_nondebug_after_labels_bb (middle_bb);
while (!gsi_end_p (gsi))
{
gimple stmt = gsi_stmt (gsi);
@@ -781,6 +838,59 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
}
}
+
+ /* Now optimize (x != 0) ? x + y : y to just y.
+ The following condition is too restrictive, there can easily be another
+ stmt in middle_bb, for instance a CONVERT_EXPR for the second argument. */
+ gimple assign = last_and_only_stmt (middle_bb);
+ if (!assign || gimple_code (assign) != GIMPLE_ASSIGN
+ || gimple_assign_rhs_class (assign) != GIMPLE_BINARY_RHS
+ || (!INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+ && !POINTER_TYPE_P (TREE_TYPE (arg0))))
+ return 0;
+
+ /* Only transform if it removes the condition. */
+ if (!single_non_singleton_phi_for_edges (phi_nodes (gimple_bb (phi)), e0, e1))
+ return 0;
+
+ /* Size-wise, this is always profitable. */
+ if (optimize_bb_for_speed_p (cond_bb)
+ /* The special case is useless if it has a low probability. */
+ && profile_status_for_fn (cfun) != PROFILE_ABSENT
+ && EDGE_PRED (middle_bb, 0)->probability < PROB_EVEN
+ /* If assign is cheap, there is no point avoiding it. */
+ && estimate_num_insns (assign, &eni_time_weights)
+ >= 3 * estimate_num_insns (cond, &eni_time_weights))
+ return 0;
+
+ tree lhs = gimple_assign_lhs (assign);
+ tree rhs1 = gimple_assign_rhs1 (assign);
+ tree rhs2 = gimple_assign_rhs2 (assign);
+ enum tree_code code_def = gimple_assign_rhs_code (assign);
+ tree cond_lhs = gimple_cond_lhs (cond);
+ tree cond_rhs = gimple_cond_rhs (cond);
+
+ if (((code == NE_EXPR && e1 == false_edge)
+ || (code == EQ_EXPR && e1 == true_edge))
+ && arg0 == lhs
+ && ((arg1 == rhs1
+ && operand_equal_for_phi_arg_p (rhs2, cond_lhs)
+ && neutral_element_p (code_def, cond_rhs, true))
+ || (arg1 == rhs2
+ && operand_equal_for_phi_arg_p (rhs1, cond_lhs)
+ && neutral_element_p (code_def, cond_rhs, false))
+ || (operand_equal_for_phi_arg_p (arg1, cond_rhs)
+ && (operand_equal_for_phi_arg_p (rhs2, cond_lhs)
+ || operand_equal_for_phi_arg_p (rhs1, cond_lhs))
+ && absorbing_element_p (code_def, cond_rhs))))
+ {
+ gsi = gsi_for_stmt (cond);
+ gimple_stmt_iterator gsi_from = gsi_for_stmt (assign);
+ gsi_move_before (&gsi_from, &gsi);
+ replace_phi_edge_with_variable (cond_bb, e1, phi, lhs);
+ return 2;
+ }
+
return 0;
}
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index f634f5efd29..f497f907906 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -3915,7 +3915,6 @@ compute_avail (void)
/* Local state for the eliminate domwalk. */
static vec<gimple> el_to_remove;
-static vec<gimple> el_to_update;
static unsigned int el_todo;
static vec<tree> el_avail;
static vec<tree> el_avail_stack;
@@ -4010,6 +4009,15 @@ eliminate_dom_walker::before_dom_children (basic_block b)
/* Mark new bb. */
el_avail_stack.safe_push (NULL_TREE);
+ /* If this block is not reachable do nothing. */
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, b->preds)
+ if (e->flags & EDGE_EXECUTABLE)
+ break;
+ if (!e)
+ return;
+
for (gsi = gsi_start_phis (b); !gsi_end_p (gsi);)
{
gimple stmt, phi = gsi_stmt (gsi);
@@ -4146,9 +4154,14 @@ eliminate_dom_walker::before_dom_children (basic_block b)
print_gimple_stmt (dump_file, stmt, 0, 0);
}
pre_stats.eliminations++;
+
+ tree vdef = gimple_vdef (stmt);
+ tree vuse = gimple_vuse (stmt);
propagate_tree_value_into_stmt (&gsi, sprime);
stmt = gsi_stmt (gsi);
update_stmt (stmt);
+ if (vdef != gimple_vdef (stmt))
+ VN_INFO (vdef)->valnum = vuse;
/* If we removed EH side-effects from the statement, clean
its EH information. */
@@ -4246,9 +4259,14 @@ eliminate_dom_walker::before_dom_children (basic_block b)
sprime = fold_convert (gimple_expr_type (stmt), sprime);
pre_stats.eliminations++;
+
+ tree vdef = gimple_vdef (stmt);
+ tree vuse = gimple_vuse (stmt);
propagate_tree_value_into_stmt (&gsi, sprime);
stmt = gsi_stmt (gsi);
update_stmt (stmt);
+ if (vdef != gimple_vdef (stmt))
+ VN_INFO (vdef)->valnum = vuse;
/* If we removed EH side-effects from the statement, clean
its EH information. */
@@ -4347,22 +4365,27 @@ eliminate_dom_walker::before_dom_children (basic_block b)
continue;
if (gimple_call_addr_fndecl (fn) != NULL_TREE
&& useless_type_conversion_p (TREE_TYPE (orig_fn),
- TREE_TYPE (fn)))
+ TREE_TYPE (fn))
+ && dbg_cnt (devirt))
{
bool can_make_abnormal_goto
= stmt_can_make_abnormal_goto (stmt);
bool was_noreturn = gimple_call_noreturn_p (stmt);
- if (dump_file && (dump_flags & TDF_DETAILS))
+ if (dump_enabled_p ())
{
- fprintf (dump_file, "Replacing call target with ");
- print_generic_expr (dump_file, fn, 0);
- fprintf (dump_file, " in ");
- print_gimple_stmt (dump_file, stmt, 0, 0);
+ location_t loc = gimple_location (stmt);
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+ "converting indirect call to function %s\n",
+ cgraph_get_node (gimple_call_addr_fndecl (fn))->name ());
}
gimple_call_set_fn (stmt, fn);
- el_to_update.safe_push (stmt);
+ tree vdef = gimple_vdef (stmt);
+ tree vuse = gimple_vuse (stmt);
+ update_stmt (stmt);
+ if (vdef != gimple_vdef (stmt))
+ VN_INFO (vdef)->valnum = vuse;
/* When changing a call into a noreturn call, cfg cleanup
is needed to fix up the noreturn call. */
@@ -4421,7 +4444,6 @@ eliminate (void)
need_ab_cleanup = BITMAP_ALLOC (NULL);
el_to_remove.create (0);
- el_to_update.create (0);
el_todo = 0;
el_avail.create (0);
el_avail_stack.create (0);
@@ -4473,13 +4495,6 @@ eliminate (void)
}
el_to_remove.release ();
- /* We cannot update call statements with virtual operands during
- SSA walk. This might remove them which in turn makes our
- VN lattice invalid. */
- FOR_EACH_VEC_ELT (el_to_update, i, stmt)
- update_stmt (stmt);
- el_to_update.release ();
-
return el_todo;
}
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 59e46dc6420..1988835aa32 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -153,7 +153,7 @@ static sbitmap bb_in_list;
definition has changed. SSA edges are def-use edges in the SSA
web. For each D-U edge, we store the target statement or PHI node
U. */
-static GTY(()) vec<gimple, va_gc> *interesting_ssa_edges;
+static vec<gimple> interesting_ssa_edges;
/* Identical to INTERESTING_SSA_EDGES. For performance reasons, the
list of SSA edges is split into two. One contains all SSA edges
@@ -169,7 +169,7 @@ static GTY(()) vec<gimple, va_gc> *interesting_ssa_edges;
don't use a separate worklist for VARYING edges, we end up with
situations where lattice values move from
UNDEFINED->INTERESTING->VARYING instead of UNDEFINED->VARYING. */
-static GTY(()) vec<gimple, va_gc> *varying_ssa_edges;
+static vec<gimple> varying_ssa_edges;
/* Return true if the block worklist empty. */
@@ -271,9 +271,9 @@ add_ssa_edge (tree var, bool is_varying)
{
gimple_set_plf (use_stmt, STMT_IN_SSA_EDGE_WORKLIST, true);
if (is_varying)
- vec_safe_push (varying_ssa_edges, use_stmt);
+ varying_ssa_edges.safe_push (use_stmt);
else
- vec_safe_push (interesting_ssa_edges, use_stmt);
+ interesting_ssa_edges.safe_push (use_stmt);
}
}
}
@@ -301,7 +301,7 @@ add_control_edge (edge e)
cfg_blocks_add (bb);
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Adding Destination of edge (%d -> %d) to worklist\n\n",
+ fprintf (dump_file, "\nAdding Destination of edge (%d -> %d) to worklist\n",
e->src->index, e->dest->index);
}
@@ -369,15 +369,15 @@ simulate_stmt (gimple stmt)
SSA edge is added to it in simulate_stmt. */
static void
-process_ssa_edge_worklist (vec<gimple, va_gc> **worklist)
+process_ssa_edge_worklist (vec<gimple> *worklist)
{
/* Drain the entire worklist. */
- while ((*worklist)->length () > 0)
+ while (worklist->length () > 0)
{
basic_block bb;
/* Pull the statement to simulate off the worklist. */
- gimple stmt = (*worklist)->pop ();
+ gimple stmt = worklist->pop ();
/* If this statement was already visited by simulate_block, then
we don't need to visit it again here. */
@@ -492,8 +492,8 @@ ssa_prop_init (void)
basic_block bb;
/* Worklists of SSA edges. */
- vec_alloc (interesting_ssa_edges, 20);
- vec_alloc (varying_ssa_edges, 20);
+ interesting_ssa_edges.create (20);
+ varying_ssa_edges.create (20);
executable_blocks = sbitmap_alloc (last_basic_block_for_fn (cfun));
bitmap_clear (executable_blocks);
@@ -535,8 +535,8 @@ ssa_prop_init (void)
static void
ssa_prop_fini (void)
{
- vec_free (interesting_ssa_edges);
- vec_free (varying_ssa_edges);
+ interesting_ssa_edges.release ();
+ varying_ssa_edges.release ();
cfg_blocks.release ();
sbitmap_free (bb_in_list);
sbitmap_free (executable_blocks);
@@ -859,8 +859,8 @@ ssa_propagate (ssa_prop_visit_stmt_fn visit_stmt,
/* Iterate until the worklists are empty. */
while (!cfg_blocks_empty_p ()
- || interesting_ssa_edges->length () > 0
- || varying_ssa_edges->length () > 0)
+ || interesting_ssa_edges.length () > 0
+ || varying_ssa_edges.length () > 0)
{
if (!cfg_blocks_empty_p ())
{
@@ -1464,5 +1464,3 @@ propagate_tree_value_into_stmt (gimple_stmt_iterator *gsi, tree val)
else
gcc_unreachable ();
}
-
-#include "gt-tree-ssa-propagate.h"
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 357ac08381c..3d811f06893 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "params.h"
#include "diagnostic-core.h"
+#include "builtins.h"
/* This is a simple global reassociation pass. It is, in part, based
on the LLVM pass of the same name (They do some things more/less
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 05a5fe8e73f..2583375f32b 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -51,6 +51,8 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "tree-ssa-propagate.h"
#include "tree-ssa-sccvn.h"
+#include "tree-cfg.h"
+#include "domwalk.h"
/* This algorithm is based on the SCC algorithm presented by Keith
Cooper and L. Taylor Simpson in "SCC-Based Value numbering"
@@ -316,6 +318,25 @@ static int *rpo_numbers;
#define SSA_VAL(x) (VN_INFO ((x))->valnum)
+/* Return the SSA value of the VUSE x, supporting released VDEFs
+ during elimination which will value-number the VDEF to the
+ associated VUSE (but not substitute in the whole lattice). */
+
+static inline tree
+vuse_ssa_val (tree x)
+{
+ if (!x)
+ return NULL_TREE;
+
+ do
+ {
+ x = SSA_VAL (x);
+ }
+ while (SSA_NAME_IN_FREE_LIST (x));
+
+ return x;
+}
+
/* This represents the top of the VN lattice, which is the universal
value. */
@@ -414,8 +435,8 @@ vn_get_expr_for (tree name)
if (!is_gimple_assign (def_stmt))
return vn->valnum;
- /* FIXME tuples. This is incomplete and likely will miss some
- simplifications. */
+ /* Note that we can valueize here because we clear the cached
+ simplified expressions after each optimistic iteration. */
code = gimple_assign_rhs_code (def_stmt);
switch (TREE_CODE_CLASS (code))
{
@@ -427,20 +448,21 @@ vn_get_expr_for (tree name)
0)) == SSA_NAME)
expr = fold_build1 (code,
gimple_expr_type (def_stmt),
- TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0));
+ vn_valueize (TREE_OPERAND
+ (gimple_assign_rhs1 (def_stmt), 0)));
break;
case tcc_unary:
expr = fold_build1 (code,
gimple_expr_type (def_stmt),
- gimple_assign_rhs1 (def_stmt));
+ vn_valueize (gimple_assign_rhs1 (def_stmt)));
break;
case tcc_binary:
expr = fold_build2 (code,
gimple_expr_type (def_stmt),
- gimple_assign_rhs1 (def_stmt),
- gimple_assign_rhs2 (def_stmt));
+ vn_valueize (gimple_assign_rhs1 (def_stmt)),
+ vn_valueize (gimple_assign_rhs2 (def_stmt)));
break;
case tcc_exceptional:
@@ -641,9 +663,6 @@ vn_reference_eq (const_vn_reference_t const vr1, const_vn_reference_t const vr2)
{
unsigned i, j;
- if (vr1->hashcode != vr2->hashcode)
- return false;
-
/* Early out if this is not a hash collision. */
if (vr1->hashcode != vr2->hashcode)
return false;
@@ -1103,6 +1122,7 @@ copy_reference_ops_from_call (gimple call,
vn_reference_op_s temp;
unsigned i;
tree lhs = gimple_call_lhs (call);
+ int lr;
/* If 2 calls have a different non-ssa lhs, vdef value numbers should be
different. By adding the lhs here in the vector, we ensure that the
@@ -1117,12 +1137,14 @@ copy_reference_ops_from_call (gimple call,
result->safe_push (temp);
}
- /* Copy the type, opcode, function being called and static chain. */
+ /* Copy the type, opcode, function, static chain and EH region, if any. */
memset (&temp, 0, sizeof (temp));
temp.type = gimple_call_return_type (call);
temp.opcode = CALL_EXPR;
temp.op0 = gimple_call_fn (call);
temp.op1 = gimple_call_chain (call);
+ if (stmt_could_throw_p (call) && (lr = lookup_stmt_eh_lp (call)) > 0)
+ temp.op2 = size_int (lr);
temp.off = -1;
result->safe_push (temp);
@@ -1492,7 +1514,7 @@ vn_reference_lookup_2 (ao_ref *op ATTRIBUTE_UNUSED, tree vuse,
/* Fixup vuse and hash. */
if (vr->vuse)
vr->hashcode = vr->hashcode - SSA_NAME_VERSION (vr->vuse);
- vr->vuse = SSA_VAL (vuse);
+ vr->vuse = vuse_ssa_val (vuse);
if (vr->vuse)
vr->hashcode = vr->hashcode + SSA_NAME_VERSION (vr->vuse);
@@ -1591,7 +1613,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
conditional calls to free falsely clobbering ref because
of imprecise points-to info of the argument. */
tree oldargs[4];
- bool valueized_anything;
+ bool valueized_anything = false;
for (unsigned i = 0; i < gimple_call_num_args (def_stmt); ++i)
{
oldargs[i] = gimple_call_arg (def_stmt, i);
@@ -2032,7 +2054,7 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
vnresult = &tmp;
*vnresult = NULL;
- vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
+ vr1.vuse = vuse_ssa_val (vuse);
shared_lookup_references.truncate (0);
shared_lookup_references.safe_grow (operands.length ());
memcpy (shared_lookup_references.address (),
@@ -2087,7 +2109,7 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
if (vnresult)
*vnresult = NULL;
- vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
+ vr1.vuse = vuse_ssa_val (vuse);
vr1.operands = operands
= valueize_shared_reference_ops_from_ref (op, &valuezied_anything);
vr1.type = TREE_TYPE (op);
@@ -2660,6 +2682,25 @@ set_ssa_val_to (tree from, tree to)
tree currval = SSA_VAL (from);
HOST_WIDE_INT toff, coff;
+ /* The only thing we allow as value numbers are ssa_names
+ and invariants. So assert that here. We don't allow VN_TOP
+ as visiting a stmt should produce a value-number other than
+ that.
+ ??? Still VN_TOP can happen for unreachable code, so force
+ it to varying in that case. Not all code is prepared to
+ get VN_TOP on valueization. */
+ if (to == VN_TOP)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Forcing value number to varying on "
+ "receiving VN_TOP\n");
+ to = from;
+ }
+
+ gcc_assert (to != NULL_TREE
+ && (TREE_CODE (to) == SSA_NAME
+ || is_gimple_min_invariant (to)));
+
if (from != to)
{
if (currval == from)
@@ -2679,13 +2720,6 @@ set_ssa_val_to (tree from, tree to)
to = from;
}
- /* The only thing we allow as value numbers are VN_TOP, ssa_names
- and invariants. So assert that here. */
- gcc_assert (to != NULL_TREE
- && (to == VN_TOP
- || TREE_CODE (to) == SSA_NAME
- || is_gimple_min_invariant (to)));
-
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Setting value number of ");
@@ -2759,7 +2793,6 @@ defs_to_varying (gimple stmt)
}
static bool expr_has_constants (tree expr);
-static tree valueize_expr (tree expr);
/* Visit a copy between LHS and RHS, return true if the value number
changed. */
@@ -2900,7 +2933,7 @@ visit_reference_op_load (tree lhs, tree op, gimple stmt)
|| TREE_CODE (val) == VIEW_CONVERT_EXPR)
&& TREE_CODE (TREE_OPERAND (val, 0)) == SSA_NAME)
{
- tree tem = valueize_expr (vn_get_expr_for (TREE_OPERAND (val, 0)));
+ tree tem = vn_get_expr_for (TREE_OPERAND (val, 0));
if ((CONVERT_EXPR_P (tem)
|| TREE_CODE (tem) == VIEW_CONVERT_EXPR)
&& (tem = fold_unary_ignore_overflow (TREE_CODE (val),
@@ -3071,7 +3104,6 @@ visit_phi (gimple phi)
tree result;
tree sameval = VN_TOP;
bool allsame = true;
- unsigned i;
/* TODO: We could check for this in init_sccvn, and replace this
with a gcc_assert. */
@@ -3080,27 +3112,30 @@ visit_phi (gimple phi)
/* See if all non-TOP arguments have the same value. TOP is
equivalent to everything, so we can ignore it. */
- for (i = 0; i < gimple_phi_num_args (phi); i++)
- {
- tree def = PHI_ARG_DEF (phi, i);
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, gimple_bb (phi)->preds)
+ if (e->flags & EDGE_EXECUTABLE)
+ {
+ tree def = PHI_ARG_DEF_FROM_EDGE (phi, e);
- if (TREE_CODE (def) == SSA_NAME)
- def = SSA_VAL (def);
- if (def == VN_TOP)
- continue;
- if (sameval == VN_TOP)
- {
- sameval = def;
- }
- else
- {
- if (!expressions_equal_p (def, sameval))
- {
- allsame = false;
- break;
- }
- }
- }
+ if (TREE_CODE (def) == SSA_NAME)
+ def = SSA_VAL (def);
+ if (def == VN_TOP)
+ continue;
+ if (sameval == VN_TOP)
+ {
+ sameval = def;
+ }
+ else
+ {
+ if (!expressions_equal_p (def, sameval))
+ {
+ allsame = false;
+ break;
+ }
+ }
+ }
/* If all value numbered to the same value, the phi node has that
value. */
@@ -3109,12 +3144,14 @@ visit_phi (gimple phi)
if (is_gimple_min_invariant (sameval))
{
VN_INFO (PHI_RESULT (phi))->has_constants = true;
- VN_INFO (PHI_RESULT (phi))->expr = sameval;
+ if (sameval != VN_TOP)
+ VN_INFO (PHI_RESULT (phi))->expr = sameval;
}
else
{
VN_INFO (PHI_RESULT (phi))->has_constants = false;
- VN_INFO (PHI_RESULT (phi))->expr = sameval;
+ if (sameval != VN_TOP)
+ VN_INFO (PHI_RESULT (phi))->expr = sameval;
}
if (TREE_CODE (sameval) == SSA_NAME)
@@ -3210,26 +3247,6 @@ stmt_has_constants (gimple stmt)
return false;
}
-/* Replace SSA_NAMES in expr with their value numbers, and return the
- result.
- This is performed in place. */
-
-static tree
-valueize_expr (tree expr)
-{
- switch (TREE_CODE_CLASS (TREE_CODE (expr)))
- {
- case tcc_binary:
- TREE_OPERAND (expr, 1) = vn_valueize (TREE_OPERAND (expr, 1));
- /* Fallthru. */
- case tcc_unary:
- TREE_OPERAND (expr, 0) = vn_valueize (TREE_OPERAND (expr, 0));
- break;
- default:;
- }
- return expr;
-}
-
/* Simplify the binary expression RHS, and return the result if
simplified. */
@@ -3250,7 +3267,7 @@ simplify_binary_expression (gimple stmt)
if (VN_INFO (op0)->has_constants
|| TREE_CODE_CLASS (code) == tcc_comparison
|| code == COMPLEX_EXPR)
- op0 = valueize_expr (vn_get_expr_for (op0));
+ op0 = vn_get_expr_for (op0);
else
op0 = vn_valueize (op0);
}
@@ -3259,7 +3276,7 @@ simplify_binary_expression (gimple stmt)
{
if (VN_INFO (op1)->has_constants
|| code == COMPLEX_EXPR)
- op1 = valueize_expr (vn_get_expr_for (op1));
+ op1 = vn_get_expr_for (op1);
else
op1 = vn_valueize (op1);
}
@@ -3321,7 +3338,7 @@ simplify_unary_expression (gimple stmt)
orig_op0 = op0;
if (VN_INFO (op0)->has_constants)
- op0 = valueize_expr (vn_get_expr_for (op0));
+ op0 = vn_get_expr_for (op0);
else if (CONVERT_EXPR_CODE_P (code)
|| code == REALPART_EXPR
|| code == IMAGPART_EXPR
@@ -3330,7 +3347,7 @@ simplify_unary_expression (gimple stmt)
{
/* We want to do tree-combining on conversion-like expressions.
Make sure we feed only SSA_NAMEs or constants to fold though. */
- tree tem = valueize_expr (vn_get_expr_for (op0));
+ tree tem = vn_get_expr_for (op0);
if (UNARY_CLASS_P (tem)
|| BINARY_CLASS_P (tem)
|| TREE_CODE (tem) == VIEW_CONVERT_EXPR
@@ -3586,28 +3603,70 @@ visit_use (tree use)
else if (is_gimple_call (stmt))
{
tree lhs = gimple_call_lhs (stmt);
-
- /* ??? We could try to simplify calls. */
-
if (lhs && TREE_CODE (lhs) == SSA_NAME)
{
- if (stmt_has_constants (stmt))
- VN_INFO (lhs)->has_constants = true;
- else
+ /* Try constant folding based on our current lattice. */
+ tree simplified = gimple_fold_stmt_to_constant_1 (stmt,
+ vn_valueize);
+ if (simplified)
{
- /* We reset expr and constantness here because we may
- have been value numbering optimistically, and
- iterating. They may become non-constant in this case,
- even if they were optimistically constant. */
- VN_INFO (lhs)->has_constants = false;
- VN_INFO (lhs)->expr = NULL_TREE;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "call ");
+ print_gimple_expr (dump_file, stmt, 0, 0);
+ fprintf (dump_file, " simplified to ");
+ print_generic_expr (dump_file, simplified, 0);
+ if (TREE_CODE (lhs) == SSA_NAME)
+ fprintf (dump_file, " has constants %d\n",
+ expr_has_constants (simplified));
+ else
+ fprintf (dump_file, "\n");
+ }
}
-
- if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
+ /* Setting value numbers to constants will occasionally
+ screw up phi congruence because constants are not
+ uniquely associated with a single ssa name that can be
+ looked up. */
+ if (simplified
+ && is_gimple_min_invariant (simplified))
+ {
+ VN_INFO (lhs)->expr = simplified;
+ VN_INFO (lhs)->has_constants = true;
+ changed = set_ssa_val_to (lhs, simplified);
+ if (gimple_vdef (stmt))
+ changed |= set_ssa_val_to (gimple_vdef (stmt),
+ gimple_vuse (stmt));
+ goto done;
+ }
+ else if (simplified
+ && TREE_CODE (simplified) == SSA_NAME)
{
- changed = defs_to_varying (stmt);
+ changed = visit_copy (lhs, simplified);
+ if (gimple_vdef (stmt))
+ changed |= set_ssa_val_to (gimple_vdef (stmt),
+ gimple_vuse (stmt));
goto done;
}
+ else
+ {
+ if (stmt_has_constants (stmt))
+ VN_INFO (lhs)->has_constants = true;
+ else
+ {
+ /* We reset expr and constantness here because we may
+ have been value numbering optimistically, and
+ iterating. They may become non-constant in this case,
+ even if they were optimistically constant. */
+ VN_INFO (lhs)->has_constants = false;
+ VN_INFO (lhs)->expr = NULL_TREE;
+ }
+
+ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
+ {
+ changed = defs_to_varying (stmt);
+ goto done;
+ }
+ }
}
if (!gimple_call_internal_p (stmt)
@@ -3774,6 +3833,9 @@ process_scc (vec<tree> scc)
}
}
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ print_scc (dump_file, scc);
+
/* Iterate over the SCC with the optimistic table until it stops
changing. */
current_info = optimistic_info;
@@ -3799,6 +3861,8 @@ process_scc (vec<tree> scc)
changed |= visit_use (var);
}
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Processing SCC needed %d iterations\n", iterations);
statistics_histogram_event (cfun, "SCC iterations", iterations);
/* Finally, copy the contents of the no longer used optimistic
@@ -3850,9 +3914,6 @@ extract_and_process_scc_for_name (tree name)
if (scc.length () > 1)
sort_scc (scc);
- if (dump_file && (dump_flags & TDF_DETAILS))
- print_scc (dump_file, scc);
-
process_scc (scc);
return true;
@@ -4118,6 +4179,119 @@ set_hashtable_value_ids (void)
set_value_id_for_result (vr->result, &vr->value_id);
}
+class cond_dom_walker : public dom_walker
+{
+public:
+ cond_dom_walker () : dom_walker (CDI_DOMINATORS), fail (false) {}
+
+ virtual void before_dom_children (basic_block);
+
+ bool fail;
+};
+
+void
+cond_dom_walker::before_dom_children (basic_block bb)
+{
+ edge e;
+ edge_iterator ei;
+
+ if (fail)
+ return;
+
+ /* If any of the predecessor edges that do not come from blocks dominated
+ by us are still marked as possibly executable consider this block
+ reachable. */
+ bool reachable = bb == ENTRY_BLOCK_PTR_FOR_FN (cfun);
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (!dominated_by_p (CDI_DOMINATORS, e->src, bb))
+ reachable |= (e->flags & EDGE_EXECUTABLE);
+
+ /* If the block is not reachable all outgoing edges are not
+ executable. */
+ if (!reachable)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Marking all outgoing edges of unreachable "
+ "BB %d as not executable\n", bb->index);
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ e->flags &= ~EDGE_EXECUTABLE;
+ return;
+ }
+
+ gimple stmt = last_stmt (bb);
+ if (!stmt)
+ return;
+
+ enum gimple_code code = gimple_code (stmt);
+ if (code != GIMPLE_COND
+ && code != GIMPLE_SWITCH
+ && code != GIMPLE_GOTO)
+ return;
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Value-numbering operands of stmt ending BB %d: ",
+ bb->index);
+ print_gimple_stmt (dump_file, stmt, 0, 0);
+ }
+
+ /* Value-number the last stmts SSA uses. */
+ ssa_op_iter i;
+ tree op;
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
+ if (VN_INFO (op)->visited == false
+ && !DFS (op))
+ {
+ fail = true;
+ return;
+ }
+
+ /* ??? We can even handle stmts with outgoing EH or ABNORMAL edges
+ if value-numbering can prove they are not reachable. Handling
+ computed gotos is also possible. */
+ tree val;
+ switch (code)
+ {
+ case GIMPLE_COND:
+ {
+ tree lhs = gimple_cond_lhs (stmt);
+ tree rhs = gimple_cond_rhs (stmt);
+ /* Work hard in computing the condition and take into account
+ the valueization of the defining stmt. */
+ if (TREE_CODE (lhs) == SSA_NAME)
+ lhs = vn_get_expr_for (lhs);
+ if (TREE_CODE (rhs) == SSA_NAME)
+ rhs = vn_get_expr_for (rhs);
+ val = fold_binary (gimple_cond_code (stmt),
+ boolean_type_node, lhs, rhs);
+ break;
+ }
+ case GIMPLE_SWITCH:
+ val = gimple_switch_index (stmt);
+ break;
+ case GIMPLE_GOTO:
+ val = gimple_goto_dest (stmt);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (!val)
+ return;
+
+ edge taken = find_taken_edge (bb, vn_valueize (val));
+ if (!taken)
+ return;
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Marking all edges out of BB %d but (%d -> %d) as "
+ "not executable\n", bb->index, bb->index, taken->dest->index);
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e != taken)
+ e->flags &= ~EDGE_EXECUTABLE;
+}
+
/* Do SCCVN. Returns true if it finished, false if we bailed out
due to resource constraints. DEFAULT_VN_WALK_KIND_ specifies
how we use the alias oracle walking during the VN process. */
@@ -4125,6 +4299,7 @@ set_hashtable_value_ids (void)
bool
run_scc_vn (vn_lookup_kind default_vn_walk_kind_)
{
+ basic_block bb;
size_t i;
tree param;
@@ -4139,9 +4314,32 @@ run_scc_vn (vn_lookup_kind default_vn_walk_kind_)
{
tree def = ssa_default_def (cfun, param);
if (def)
- VN_INFO (def)->valnum = def;
+ {
+ VN_INFO (def)->visited = true;
+ VN_INFO (def)->valnum = def;
+ }
+ }
+
+ /* Mark all edges as possibly executable. */
+ FOR_ALL_BB_FN (bb, cfun)
+ {
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ e->flags |= EDGE_EXECUTABLE;
+ }
+
+ /* Walk all blocks in dominator order, value-numbering the last stmts
+ SSA uses and decide whether outgoing edges are not executable. */
+ cond_dom_walker walker;
+ walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ if (walker.fail)
+ {
+ free_scc_vn ();
+ return false;
}
+ /* Value-number remaining SSA names. */
for (i = 1; i < num_ssa_names; ++i)
{
tree name = ssa_name (i);
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 5d3a323e54a..99e97d67a85 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -3974,7 +3974,6 @@ handle_lhs_call (gimple stmt, tree lhs, int flags, vec<ce_s> rhsc,
/* If the call returns an argument unmodified override the rhs
constraints. */
- flags = gimple_call_return_flags (stmt);
if (flags & ERF_RETURNS_ARG
&& (flags & ERF_RETURN_ARG_MASK) < gimple_call_num_args (stmt))
{
@@ -4299,9 +4298,11 @@ find_func_aliases_for_builtin_call (struct function *fn, gimple t)
return true;
case BUILT_IN_STRDUP:
case BUILT_IN_STRNDUP:
+ case BUILT_IN_REALLOC:
if (gimple_call_lhs (t))
{
- handle_lhs_call (t, gimple_call_lhs (t), gimple_call_flags (t),
+ handle_lhs_call (t, gimple_call_lhs (t),
+ gimple_call_return_flags (t) | ERF_NOALIAS,
vNULL, fndecl);
get_constraint_for_ptr_offset (gimple_call_lhs (t),
NULL_TREE, &lhsc);
@@ -4312,6 +4313,17 @@ find_func_aliases_for_builtin_call (struct function *fn, gimple t)
process_all_all_constraints (lhsc, rhsc);
lhsc.release ();
rhsc.release ();
+ /* For realloc the resulting pointer can be equal to the
+ argument as well. But only doing this wouldn't be
+ correct because with ptr == 0 realloc behaves like malloc. */
+ if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_REALLOC)
+ {
+ get_constraint_for (gimple_call_lhs (t), &lhsc);
+ get_constraint_for (gimple_call_arg (t, 0), &rhsc);
+ process_all_all_constraints (lhsc, rhsc);
+ lhsc.release ();
+ rhsc.release ();
+ }
return true;
}
break;
@@ -4535,7 +4547,8 @@ find_func_aliases_for_call (struct function *fn, gimple t)
else
handle_rhs_call (t, &rhsc);
if (gimple_call_lhs (t))
- handle_lhs_call (t, gimple_call_lhs (t), flags, rhsc, fndecl);
+ handle_lhs_call (t, gimple_call_lhs (t),
+ gimple_call_return_flags (t), rhsc, fndecl);
rhsc.release ();
}
else
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 7621348944f..69e5a6b5629 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "params.h"
#include "tree-ssa-threadedge.h"
+#include "builtins.h"
/* To avoid code explosion due to jump threading, we limit the
number of statements we are going to copy. This variable
@@ -966,9 +967,14 @@ thread_around_empty_blocks (edge taken_edge,
SIMPLIFY is a pass-specific function used to simplify statements.
Our caller is responsible for restoring the state of the expression
- and const_and_copies stacks. */
+ and const_and_copies stacks.
-static bool
+ Positive return value is success. Zero return value is failure, but
+ the block can still be duplicated as a joiner in a jump thread path,
+ negative indicates the block should not be duplicated and thus is not
+ suitable for a joiner in a jump threading path. */
+
+static int
thread_through_normal_block (edge e,
gimple dummy_cond,
bool handle_dominating_asserts,
@@ -990,7 +996,7 @@ thread_through_normal_block (edge e,
/* PHIs create temporary equivalences. */
if (!record_temporary_equivalences_from_phis (e, stack, *backedge_seen_p,
src_map, dst_map))
- return false;
+ return 0;
/* Now walk each statement recording any context sensitive
temporary equivalences we can detect. */
@@ -998,8 +1004,16 @@ thread_through_normal_block (edge e,
= record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify,
*backedge_seen_p,
src_map, dst_map);
+
+ /* If we didn't look at all the statements, the most likely reason is
+ there were too many and thus duplicating this block is not profitable.
+
+ Also note if we do not look at all the statements, then we may not
+ have invalidated equivalences that are no longer valid if we threaded
+ around a loop. Thus we must signal to our caller that this block
+ is not suitable for use as a joiner in a threading path. */
if (!stmt)
- return false;
+ return -1;
/* If we stopped at a COND_EXPR or SWITCH_EXPR, see if we know which arm
will be taken. */
@@ -1023,7 +1037,7 @@ thread_through_normal_block (edge e,
if (dest == NULL
|| dest == e->dest
|| bitmap_bit_p (visited, dest->index))
- return false;
+ return 0;
/* Only push the EDGE_START_JUMP_THREAD marker if this is
first edge on the path. */
@@ -1057,10 +1071,10 @@ thread_through_normal_block (edge e,
visited,
path,
backedge_seen_p);
- return true;
+ return 1;
}
}
- return false;
+ return 0;
}
/* We are exiting E->src, see if E->dest ends with a conditional
@@ -1112,9 +1126,12 @@ thread_across_edge (gimple dummy_cond,
if (backedge_seen)
simplify = dummy_simplify;
- if (thread_through_normal_block (e, dummy_cond, handle_dominating_asserts,
- stack, simplify, path, visited,
- &backedge_seen, src_map, dst_map))
+ int threaded = thread_through_normal_block (e, dummy_cond,
+ handle_dominating_asserts,
+ stack, simplify, path,
+ visited, &backedge_seen,
+ src_map, dst_map);
+ if (threaded > 0)
{
propagate_threaded_block_debug_into (path->last ()->e->dest,
e->dest);
@@ -1127,10 +1144,27 @@ thread_across_edge (gimple dummy_cond,
}
else
{
- /* There should be no edges on the path, so no need to walk through
- the vector entries. */
+ /* Negative and zero return values indicate no threading was possible,
+ thus there should be no edges on the thread path and no need to walk
+ through the vector entries. */
gcc_assert (path->length () == 0);
path->release ();
+
+ /* A negative status indicates the target block was deemed too big to
+ duplicate. Just quit now rather than trying to use the block as
+ a joiner in a jump threading path.
+
+ This prevents unnecessary code growth, but more importantly if we
+ do not look at all the statements in the block, then we may have
+ missed some invalidations if we had traversed a backedge! */
+ if (threaded < 0)
+ {
+ BITMAP_FREE (visited);
+ BITMAP_FREE (src_map);
+ BITMAP_FREE (dst_map);
+ remove_temporary_equivalences (stack);
+ return;
+ }
}
/* We were unable to determine what out edge from E->dest is taken. However,
@@ -1212,7 +1246,7 @@ thread_across_edge (gimple dummy_cond,
handle_dominating_asserts,
stack, simplify, path, visited,
&backedge_seen,
- src_map, dst_map);
+ src_map, dst_map) > 0;
/* If we were able to thread through a successor of E->dest, then
record the jump threading opportunity. */
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 96e9e609f83..8b298faeb5c 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -123,17 +123,25 @@ uninit_undefined_value_p (tree t) {
/* Emit a warning for EXPR based on variable VAR at the point in the
program T, an SSA_NAME, is used being uninitialized. The exact
- warning text is in MSGID and LOCUS may contain a location or be null.
- WC is the warning code. */
+ warning text is in MSGID and DATA is the gimple stmt with info about
+ the location in source code. When DATA is a GIMPLE_PHI, PHIARG_IDX
+ gives which argument of the phi node to take the location from. WC
+ is the warning code. */
static void
-warn_uninit (enum opt_code wc, tree t,
- tree expr, tree var, const char *gmsgid, void *data)
+warn_uninit (enum opt_code wc, tree t, tree expr, tree var,
+ const char *gmsgid, void *data, location_t phiarg_loc)
{
gimple context = (gimple) data;
location_t location, cfun_loc;
expanded_location xloc, floc;
+ /* Ignore COMPLEX_EXPR as initializing only a part of a complex
+ turns in a COMPLEX_EXPR with the not initialized part being
+ set to its previous (undefined) value. */
+ if (is_gimple_assign (context)
+ && gimple_assign_rhs_code (context) == COMPLEX_EXPR)
+ return;
if (!has_undefined_value_p (t))
return;
@@ -146,9 +154,12 @@ warn_uninit (enum opt_code wc, tree t,
|| TREE_NO_WARNING (expr))
return;
- location = (context != NULL && gimple_has_location (context))
- ? gimple_location (context)
- : DECL_SOURCE_LOCATION (var);
+ if (context != NULL && gimple_has_location (context))
+ location = gimple_location (context);
+ else if (phiarg_loc != UNKNOWN_LOCATION)
+ location = phiarg_loc;
+ else
+ location = DECL_SOURCE_LOCATION (var);
location = linemap_resolve_location (line_table, location,
LRK_SPELLING_LOCATION,
NULL);
@@ -200,12 +211,12 @@ warn_uninitialized_vars (bool warn_possibly_uninitialized)
warn_uninit (OPT_Wuninitialized, use,
SSA_NAME_VAR (use), SSA_NAME_VAR (use),
"%qD is used uninitialized in this function",
- stmt);
+ stmt, UNKNOWN_LOCATION);
else if (warn_possibly_uninitialized)
warn_uninit (OPT_Wmaybe_uninitialized, use,
SSA_NAME_VAR (use), SSA_NAME_VAR (use),
"%qD may be used uninitialized in this function",
- stmt);
+ stmt, UNKNOWN_LOCATION);
}
/* For memory the only cheap thing we can do is see if we
@@ -236,12 +247,12 @@ warn_uninitialized_vars (bool warn_possibly_uninitialized)
warn_uninit (OPT_Wuninitialized, use,
gimple_assign_rhs1 (stmt), base,
"%qE is used uninitialized in this function",
- stmt);
+ stmt, UNKNOWN_LOCATION);
else if (warn_possibly_uninitialized)
warn_uninit (OPT_Wmaybe_uninitialized, use,
gimple_assign_rhs1 (stmt), base,
"%qE may be used uninitialized in this function",
- stmt);
+ stmt, UNKNOWN_LOCATION);
}
}
}
@@ -2246,6 +2257,8 @@ warn_uninitialized_phi (gimple phi, vec<gimple> *worklist,
unsigned uninit_opnds;
gimple uninit_use_stmt = 0;
tree uninit_op;
+ int phiarg_index;
+ location_t loc;
/* Don't look at virtual operands. */
if (virtual_operand_p (gimple_phi_result (phi)))
@@ -2270,13 +2283,18 @@ warn_uninitialized_phi (gimple phi, vec<gimple> *worklist,
if (!uninit_use_stmt)
return;
- uninit_op = gimple_phi_arg_def (phi, MASK_FIRST_SET_BIT (uninit_opnds));
+ phiarg_index = MASK_FIRST_SET_BIT (uninit_opnds);
+ uninit_op = gimple_phi_arg_def (phi, phiarg_index);
if (SSA_NAME_VAR (uninit_op) == NULL_TREE)
return;
+ if (gimple_phi_arg_has_location (phi, phiarg_index))
+ loc = gimple_phi_arg_location (phi, phiarg_index);
+ else
+ loc = UNKNOWN_LOCATION;
warn_uninit (OPT_Wmaybe_uninitialized, uninit_op, SSA_NAME_VAR (uninit_op),
SSA_NAME_VAR (uninit_op),
"%qD may be used uninitialized in this function",
- uninit_use_stmt);
+ uninit_use_stmt, loc);
}
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 856325e0de4..f6f1effcf9c 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1120,7 +1120,7 @@ uid_ssaname_map_hash (const void *item)
void
init_tree_ssa (struct function *fn)
{
- fn->gimple_df = ggc_alloc_cleared_gimple_df ();
+ fn->gimple_df = ggc_cleared_alloc<gimple_df> ();
fn->gimple_df->default_defs = htab_create_ggc (20, uid_ssaname_map_hash,
uid_ssaname_map_eq, NULL);
pt_solution_reset (&fn->gimple_df->escaped);
@@ -1246,6 +1246,7 @@ tree_ssa_strip_useless_type_conversions (tree exp)
bool
ssa_undefined_value_p (tree t)
{
+ gimple def_stmt;
tree var = SSA_NAME_VAR (t);
if (!var)
@@ -1262,7 +1263,22 @@ ssa_undefined_value_p (tree t)
return false;
/* The value is undefined iff its definition statement is empty. */
- return gimple_nop_p (SSA_NAME_DEF_STMT (t));
+ def_stmt = SSA_NAME_DEF_STMT (t);
+ if (gimple_nop_p (def_stmt))
+ return true;
+
+ /* Check if the complex was not only partially defined. */
+ if (is_gimple_assign (def_stmt)
+ && gimple_assign_rhs_code (def_stmt) == COMPLEX_EXPR)
+ {
+ tree rhs1, rhs2;
+
+ rhs1 = gimple_assign_rhs1 (def_stmt);
+ rhs2 = gimple_assign_rhs2 (def_stmt);
+ return (TREE_CODE (rhs1) == SSA_NAME && ssa_undefined_value_p (rhs1))
+ || (TREE_CODE (rhs2) == SSA_NAME && ssa_undefined_value_p (rhs2));
+ }
+ return false;
}
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index fa7eaf3b476..7f6a6af9ca5 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -199,7 +199,7 @@ set_range_info (tree name, enum value_range_type range_type,
{
size_t size = (sizeof (range_info_def)
+ trailing_wide_ints <3>::extra_size (precision));
- ri = ggc_alloc_range_info_def (size);
+ ri = static_cast<range_info_def *> (ggc_internal_alloc (size));
ri->ints.set_precision (precision);
SSA_NAME_RANGE_INFO (name) = ri;
ri->set_nonzero_bits (wi::shwi (-1, precision));
@@ -271,7 +271,8 @@ get_nonzero_bits (const_tree name)
{
struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
if (pi && pi->align)
- return wi::shwi (-(int) pi->align | pi->misalign, precision);
+ return wi::shwi (-(HOST_WIDE_INT) pi->align
+ | (HOST_WIDE_INT) pi->misalign, precision);
return wi::shwi (-1, precision);
}
@@ -427,7 +428,7 @@ get_ptr_info (tree t)
pi = SSA_NAME_PTR_INFO (t);
if (pi == NULL)
{
- pi = ggc_alloc_cleared_ptr_info_def ();
+ pi = ggc_cleared_alloc<ptr_info_def> ();
pt_solution_reset (&pi->pt);
mark_ptr_info_alignment_unknown (pi);
SSA_NAME_PTR_INFO (t) = pi;
@@ -471,7 +472,7 @@ duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info)
if (!ptr_info)
return;
- new_ptr_info = ggc_alloc_ptr_info_def ();
+ new_ptr_info = ggc_alloc<ptr_info_def> ();
*new_ptr_info = *ptr_info;
SSA_NAME_PTR_INFO (name) = new_ptr_info;
@@ -495,7 +496,7 @@ duplicate_ssa_name_range_info (tree name, enum value_range_type range_type,
unsigned int precision = TYPE_PRECISION (TREE_TYPE (name));
size_t size = (sizeof (range_info_def)
+ trailing_wide_ints <3>::extra_size (precision));
- new_range_info = ggc_alloc_range_info_def (size);
+ new_range_info = static_cast<range_info_def *> (ggc_internal_alloc (size));
memcpy (new_range_info, range_info, size);
gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index fc5ecfc9855..da7c096b826 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "data-streamer.h"
#include "streamer-hooks.h"
#include "lto-streamer.h"
+#include "builtins.h"
/* Read a STRING_CST from the string table in DATA_IN using input
block IB. */
@@ -168,6 +169,9 @@ unpack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
REAL_VALUE_TYPE r;
REAL_VALUE_TYPE *rp;
+ /* Clear all bits of the real value type so that we can later do
+ bitwise comparisons to see if two values are the same. */
+ memset (&r, 0, sizeof r);
r.cl = (unsigned) bp_unpack_value (bp, 2);
r.decimal = (unsigned) bp_unpack_value (bp, 1);
r.sign = (unsigned) bp_unpack_value (bp, 1);
@@ -177,7 +181,7 @@ unpack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
for (i = 0; i < SIGSZ; i++)
r.sig[i] = (unsigned long) bp_unpack_value (bp, HOST_BITS_PER_LONG);
- rp = ggc_alloc_real_value ();
+ rp = ggc_alloc<real_value> ();
memcpy (rp, &r, sizeof (REAL_VALUE_TYPE));
TREE_REAL_CST_PTR (expr) = rp;
}
@@ -189,7 +193,7 @@ unpack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
static void
unpack_ts_fixed_cst_value_fields (struct bitpack_d *bp, tree expr)
{
- FIXED_VALUE_TYPE *fp = ggc_alloc_fixed_value ();
+ FIXED_VALUE_TYPE *fp = ggc_alloc<fixed_value> ();
fp->mode = bp_unpack_enum (bp, machine_mode, MAX_MACHINE_MODE);
fp->data.low = bp_unpack_var_len_int (bp);
fp->data.high = bp_unpack_var_len_int (bp);
@@ -565,7 +569,7 @@ streamer_alloc_tree (struct lto_input_block *ib, struct data_in *data_in,
enum tree_code code;
tree result;
#ifdef LTO_STREAMER_DEBUG
- HOST_WIDEST_INT orig_address_in_writer;
+ HOST_WIDE_INT orig_address_in_writer;
#endif
result = NULL_TREE;
@@ -757,7 +761,6 @@ lto_input_ts_decl_with_vis_tree_pointers (struct lto_input_block *ib,
}
DECL_SECTION_NAME (expr) = stream_read_tree (ib, data_in);
- DECL_COMDAT_GROUP (expr) = stream_read_tree (ib, data_in);
}
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index 5858047b4b5..f7799bccd5f 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -662,7 +662,6 @@ write_ts_decl_with_vis_tree_pointers (struct output_block *ob, tree expr,
stream_write_tree (ob, NULL_TREE, false);
stream_write_tree (ob, DECL_SECTION_NAME (expr), ref_p);
- stream_write_tree (ob, DECL_COMDAT_GROUP (expr), ref_p);
}
@@ -991,8 +990,8 @@ streamer_write_tree_header (struct output_block *ob, tree expr)
and the writer do not agree on a streamed node, the pointer
value for EXPR can be used to track down the differences in
the debugger. */
- gcc_assert ((HOST_WIDEST_INT) (intptr_t) expr == (intptr_t) expr);
- streamer_write_hwi (ob, (HOST_WIDEST_INT) (intptr_t) expr);
+ gcc_assert ((HOST_WIDE_INT) (intptr_t) expr == (intptr_t) expr);
+ streamer_write_hwi (ob, (HOST_WIDE_INT) (intptr_t) expr);
#endif
/* The text in strings and identifiers are completely emitted in
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index c48640550e7..a4c439fb19a 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -57,6 +57,7 @@ along with GCC; see the file COPYING3. If not see
/* Need to include rtl.h, expr.h, etc. for optabs. */
#include "expr.h"
#include "optabs.h"
+#include "builtins.h"
/* Return true if load- or store-lanes optab OPTAB is implemented for
COUNT vectors of type VECTYPE. NAME is the name of OPTAB. */
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 094cf047e05..b504f4241db 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see
#include "recog.h" /* FIXME: for insn_data */
#include "diagnostic-core.h"
#include "dumpfile.h"
+#include "builtins.h"
/* Pattern recognition functions */
static gimple vect_recog_widen_sum_pattern (vec<gimple> *, tree *,
@@ -2889,7 +2890,12 @@ adjust_bool_pattern (tree var, tree out_type, tree trueval,
S5 e_b = c_b | d_b;
S6 f_T = (TYPE) e_b;
- where type 'TYPE' is an integral type.
+ where type 'TYPE' is an integral type. Or a similar pattern
+ ending in
+
+ S6 f_Y = e_b ? r_Y : s_Y;
+
+ as results from if-conversion of a complex condition.
Input:
@@ -2972,6 +2978,45 @@ vect_recog_bool_pattern (vec<gimple> *stmts, tree *type_in,
return pattern_stmt;
}
+ else if (rhs_code == COND_EXPR
+ && TREE_CODE (var) == SSA_NAME)
+ {
+ vectype = get_vectype_for_scalar_type (TREE_TYPE (lhs));
+ if (vectype == NULL_TREE)
+ return NULL;
+
+ /* Build a scalar type for the boolean result that when
+ vectorized matches the vector type of the result in
+ size and number of elements. */
+ unsigned prec
+ = wi::udiv_trunc (TYPE_SIZE (vectype),
+ TYPE_VECTOR_SUBPARTS (vectype)).to_uhwi ();
+ tree type
+ = build_nonstandard_integer_type (prec,
+ TYPE_UNSIGNED (TREE_TYPE (var)));
+ if (get_vectype_for_scalar_type (type) == NULL_TREE)
+ return NULL;
+
+ if (!check_bool_pattern (var, loop_vinfo, bb_vinfo))
+ return NULL;
+
+ rhs = adjust_bool_pattern (var, type, NULL_TREE, stmts);
+ lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
+ pattern_stmt
+ = gimple_build_assign_with_ops (COND_EXPR, lhs,
+ build2 (NE_EXPR, boolean_type_node,
+ rhs, build_int_cst (type, 0)),
+ gimple_assign_rhs2 (last_stmt),
+ gimple_assign_rhs3 (last_stmt));
+ *type_out = vectype;
+ *type_in = vectype;
+ stmts->safe_push (last_stmt);
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "vect_recog_bool_pattern: detected:\n");
+
+ return pattern_stmt;
+ }
else if (rhs_code == SSA_NAME
&& STMT_VINFO_DATA_REF (stmt_vinfo))
{
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index ec9cc68bfab..8c61775897d 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-vectorizer.h"
#include "dumpfile.h"
#include "cgraph.h"
+#include "builtins.h"
/* For lang_hooks.types.type_for_mode. */
#include "langhooks.h"
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 633c329030f..034fa0720d2 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -293,9 +293,8 @@ positive_overflow_infinity (tree type)
static inline bool
is_negative_overflow_infinity (const_tree val)
{
- return (needs_overflow_infinity (TREE_TYPE (val))
- && CONSTANT_CLASS_P (val)
- && TREE_OVERFLOW (val)
+ return (TREE_OVERFLOW_P (val)
+ && needs_overflow_infinity (TREE_TYPE (val))
&& vrp_val_is_min (val));
}
@@ -304,9 +303,8 @@ is_negative_overflow_infinity (const_tree val)
static inline bool
is_positive_overflow_infinity (const_tree val)
{
- return (needs_overflow_infinity (TREE_TYPE (val))
- && CONSTANT_CLASS_P (val)
- && TREE_OVERFLOW (val)
+ return (TREE_OVERFLOW_P (val)
+ && needs_overflow_infinity (TREE_TYPE (val))
&& vrp_val_is_max (val));
}
@@ -315,9 +313,8 @@ is_positive_overflow_infinity (const_tree val)
static inline bool
is_overflow_infinity (const_tree val)
{
- return (needs_overflow_infinity (TREE_TYPE (val))
- && CONSTANT_CLASS_P (val)
- && TREE_OVERFLOW (val)
+ return (TREE_OVERFLOW_P (val)
+ && needs_overflow_infinity (TREE_TYPE (val))
&& (vrp_val_is_min (val) || vrp_val_is_max (val)));
}
@@ -791,9 +788,7 @@ vrp_operand_equal_p (const_tree val1, const_tree val2)
return true;
if (!val1 || !val2 || !operand_equal_p (val1, val2, 0))
return false;
- if (is_overflow_infinity (val1))
- return is_overflow_infinity (val2);
- return true;
+ return is_overflow_infinity (val1) == is_overflow_infinity (val2);
}
/* Return true, if the bitmaps B1 and B2 are equal. */
@@ -1815,7 +1810,7 @@ extract_range_from_ssa_name (value_range_t *vr, tree var)
{
value_range_t *var_vr = get_value_range (var);
- if (var_vr->type != VR_UNDEFINED && var_vr->type != VR_VARYING)
+ if (var_vr->type != VR_VARYING)
copy_value_range (vr, var_vr);
else
set_value_range (vr, VR_RANGE, var, var, NULL);
@@ -6684,7 +6679,7 @@ vrp_visit_assignment_or_call (gimple stmt, tree *output_p)
print_generic_expr (dump_file, lhs, 0);
fprintf (dump_file, ": ");
dump_value_range (dump_file, &new_vr);
- fprintf (dump_file, "\n\n");
+ fprintf (dump_file, "\n");
}
if (new_vr.type == VR_VARYING)
@@ -6924,14 +6919,15 @@ vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code code,
vr0 = (TREE_CODE (op0) == SSA_NAME) ? get_value_range (op0) : NULL;
vr1 = (TREE_CODE (op1) == SSA_NAME) ? get_value_range (op1) : NULL;
+ tree res = NULL_TREE;
if (vr0 && vr1)
- return compare_ranges (code, vr0, vr1, strict_overflow_p);
- else if (vr0 && vr1 == NULL)
- return compare_range_with_value (code, vr0, op1, strict_overflow_p);
- else if (vr0 == NULL && vr1)
- return (compare_range_with_value
+ res = compare_ranges (code, vr0, vr1, strict_overflow_p);
+ if (!res && vr0)
+ res = compare_range_with_value (code, vr0, op1, strict_overflow_p);
+ if (!res && vr1)
+ res = (compare_range_with_value
(swap_tree_comparison (code), vr1, op0, strict_overflow_p));
- return NULL;
+ return res;
}
/* Helper function for vrp_evaluate_conditional_warnv. */
@@ -7477,7 +7473,6 @@ vrp_visit_stmt (gimple stmt, edge *taken_edge_p, tree *output_p)
{
fprintf (dump_file, "\nVisiting statement:\n");
print_gimple_stmt (dump_file, stmt, 0, dump_flags);
- fprintf (dump_file, "\n");
}
if (!stmt_interesting_for_vrp (stmt))
@@ -8246,7 +8241,7 @@ vrp_visit_phi_node (gimple phi)
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file,
- "\n Argument #%d (%d -> %d %sexecutable)\n",
+ " Argument #%d (%d -> %d %sexecutable)\n",
(int) i, e->src->index, e->dest->index,
(e->flags & EDGE_EXECUTABLE) ? "" : "not ");
}
@@ -8264,16 +8259,30 @@ vrp_visit_phi_node (gimple phi)
/* Do not allow equivalences or symbolic ranges to leak in from
backedges. That creates invalid equivalencies.
See PR53465 and PR54767. */
- if (e->flags & EDGE_DFS_BACK
- && (vr_arg.type == VR_RANGE
- || vr_arg.type == VR_ANTI_RANGE))
+ if (e->flags & EDGE_DFS_BACK)
+ {
+ if (vr_arg.type == VR_RANGE
+ || vr_arg.type == VR_ANTI_RANGE)
+ {
+ vr_arg.equiv = NULL;
+ if (symbolic_range_p (&vr_arg))
+ {
+ vr_arg.type = VR_VARYING;
+ vr_arg.min = NULL_TREE;
+ vr_arg.max = NULL_TREE;
+ }
+ }
+ }
+ else
{
- vr_arg.equiv = NULL;
- if (symbolic_range_p (&vr_arg))
+ /* If the non-backedge arguments range is VR_VARYING then
+ we can still try recording a simple equivalence. */
+ if (vr_arg.type == VR_VARYING)
{
- vr_arg.type = VR_VARYING;
- vr_arg.min = NULL_TREE;
- vr_arg.max = NULL_TREE;
+ vr_arg.type = VR_RANGE;
+ vr_arg.min = arg;
+ vr_arg.max = arg;
+ vr_arg.equiv = NULL;
}
}
}
@@ -8292,7 +8301,7 @@ vrp_visit_phi_node (gimple phi)
{
fprintf (dump_file, "\t");
print_generic_expr (dump_file, arg, dump_flags);
- fprintf (dump_file, "\n\tValue: ");
+ fprintf (dump_file, ": ");
dump_value_range (dump_file, &vr_arg);
fprintf (dump_file, "\n");
}
@@ -8327,8 +8336,14 @@ vrp_visit_phi_node (gimple phi)
&& edges == old_edges
&& lhs_vr->type != VR_UNDEFINED)
{
+ /* Compare old and new ranges, fall back to varying if the
+ values are not comparable. */
int cmp_min = compare_values (lhs_vr->min, vr_result.min);
+ if (cmp_min == -2)
+ goto varying;
int cmp_max = compare_values (lhs_vr->max, vr_result.max);
+ if (cmp_max == -2)
+ goto varying;
/* For non VR_RANGE or for pointers fall back to varying if
the range changed. */
@@ -8394,7 +8409,7 @@ update_range:
print_generic_expr (dump_file, lhs, 0);
fprintf (dump_file, ": ");
dump_value_range (dump_file, &vr_result);
- fprintf (dump_file, "\n\n");
+ fprintf (dump_file, "\n");
}
return SSA_PROP_INTERESTING;
diff --git a/gcc/tree.c b/gcc/tree.c
index a578c926923..de16549a099 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -76,6 +76,7 @@ along with GCC; see the file COPYING3. If not see
#include "debug.h"
#include "intl.h"
#include "wide-int.h"
+#include "builtins.h"
/* Tree code classes. */
@@ -253,7 +254,7 @@ unsigned const char omp_clause_num_ops[] =
4, /* OMP_CLAUSE_REDUCTION */
1, /* OMP_CLAUSE_COPYIN */
1, /* OMP_CLAUSE_COPYPRIVATE */
- 2, /* OMP_CLAUSE_LINEAR */
+ 3, /* OMP_CLAUSE_LINEAR */
2, /* OMP_CLAUSE_ALIGNED */
1, /* OMP_CLAUSE_DEPEND */
1, /* OMP_CLAUSE_UNIFORM */
@@ -383,6 +384,7 @@ tree_node_structure_for_code (enum tree_code code)
switch (code)
{
/* tcc_constant cases. */
+ case VOID_CST: return TS_TYPED;
case INTEGER_CST: return TS_INT_CST;
case REAL_CST: return TS_REAL_CST;
case FIXED_CST: return TS_FIXED_CST;
@@ -602,6 +604,28 @@ decl_assembler_name (tree decl)
return DECL_WITH_VIS_CHECK (decl)->decl_with_vis.assembler_name;
}
+/* When the target supports COMDAT groups, this indicates which group the
+ DECL is associated with. This can be either an IDENTIFIER_NODE or a
+ decl, in which case its DECL_ASSEMBLER_NAME identifies the group. */
+tree
+decl_comdat_group (tree node)
+{
+ struct symtab_node *snode = symtab_get_node (node);
+ if (!snode)
+ return NULL;
+ return snode->get_comdat_group ();
+}
+
+/* Likewise, but make sure it's been reduced to an IDENTIFIER_NODE. */
+tree
+decl_comdat_group_id (tree node)
+{
+ struct symtab_node *snode = symtab_get_node (node);
+ if (!snode)
+ return NULL;
+ return snode->get_comdat_group_id ();
+}
+
/* Compute the number of bytes occupied by a tree with code CODE.
This function cannot be used for nodes that have variable sizes,
including TREE_VEC, INTEGER_CST, STRING_CST, and CALL_EXPR. */
@@ -652,6 +676,7 @@ tree_code_size (enum tree_code code)
case tcc_constant: /* a constant */
switch (code)
{
+ case VOID_CST: return sizeof (struct tree_typed);
case INTEGER_CST: gcc_unreachable ();
case REAL_CST: return sizeof (struct tree_real_cst);
case FIXED_CST: return sizeof (struct tree_fixed_cst);
@@ -970,14 +995,20 @@ copy_node_stat (tree node MEM_STAT_DECL)
}
/* DECL_DEBUG_EXPR is copied explicitely by callers. */
if (TREE_CODE (node) == VAR_DECL)
- DECL_HAS_DEBUG_EXPR_P (t) = 0;
+ {
+ DECL_HAS_DEBUG_EXPR_P (t) = 0;
+ t->decl_with_vis.symtab_node = NULL;
+ }
if (TREE_CODE (node) == VAR_DECL && DECL_HAS_INIT_PRIORITY_P (node))
{
SET_DECL_INIT_PRIORITY (t, DECL_INIT_PRIORITY (node));
DECL_HAS_INIT_PRIORITY_P (t) = 1;
}
if (TREE_CODE (node) == FUNCTION_DECL)
- DECL_STRUCT_FUNCTION (t) = NULL;
+ {
+ DECL_STRUCT_FUNCTION (t) = NULL;
+ t->decl_with_vis.symtab_node = NULL;
+ }
}
else if (TREE_CODE_CLASS (code) == tcc_type)
{
@@ -1670,7 +1701,7 @@ build_fixed (tree type, FIXED_VALUE_TYPE f)
FIXED_VALUE_TYPE *fp;
v = make_node (FIXED_CST);
- fp = ggc_alloc_fixed_value ();
+ fp = ggc_alloc<fixed_value> ();
memcpy (fp, &f, sizeof (FIXED_VALUE_TYPE));
TREE_TYPE (v) = type;
@@ -1691,7 +1722,7 @@ build_real (tree type, REAL_VALUE_TYPE d)
Consider doing it via real_convert now. */
v = make_node (REAL_CST);
- dp = ggc_alloc_real_value ();
+ dp = ggc_alloc<real_value> ();
memcpy (dp, &d, sizeof (REAL_VALUE_TYPE));
TREE_TYPE (v) = type;
@@ -1748,7 +1779,7 @@ build_string (int len, const char *str)
record_node_allocation_statistics (STRING_CST, length);
- s = ggc_alloc_tree_node (length);
+ s = (tree) ggc_internal_alloc (length);
memset (s, 0, sizeof (struct tree_typed));
TREE_SET_CODE (s, STRING_CST);
@@ -2016,7 +2047,7 @@ grow_tree_vec_stat (tree v, int len MEM_STAT_DECL)
record_node_allocation_statistics (TREE_VEC, length - oldlength);
- v = (tree) ggc_realloc_stat (v, length PASS_MEM_STAT);
+ v = (tree) ggc_realloc (v, length PASS_MEM_STAT);
TREE_VEC_LENGTH (v) = len;
@@ -5236,7 +5267,6 @@ find_decls_types_r (tree *tp, int *ws, void *data)
else if (TREE_CODE (t) == VAR_DECL)
{
fld_worklist_push (DECL_SECTION_NAME (t), fld);
- fld_worklist_push (DECL_COMDAT_GROUP (t), fld);
}
if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
@@ -6407,7 +6437,7 @@ decl_priority_info (tree decl)
h = (struct tree_priority_map *) *loc;
if (!h)
{
- h = ggc_alloc_cleared_tree_priority_map ();
+ h = ggc_cleared_alloc<tree_priority_map> ();
*loc = h;
h->base.from = decl;
h->init = DEFAULT_INIT_PRIORITY;
@@ -6490,7 +6520,7 @@ decl_debug_expr_insert (tree from, tree to)
struct tree_decl_map *h;
void **loc;
- h = ggc_alloc_tree_decl_map ();
+ h = ggc_alloc<tree_decl_map> ();
h->base.from = from;
h->to = to;
loc = htab_find_slot_with_hash (debug_expr_for_decl, h, DECL_UID (from),
@@ -6521,7 +6551,7 @@ decl_value_expr_insert (tree from, tree to)
struct tree_decl_map *h;
void **loc;
- h = ggc_alloc_tree_decl_map ();
+ h = ggc_alloc<tree_decl_map> ();
h->base.from = from;
h->to = to;
loc = htab_find_slot_with_hash (value_expr_for_decl, h, DECL_UID (from),
@@ -6562,7 +6592,7 @@ decl_debug_args_insert (tree from)
if (debug_args_for_decl == NULL)
debug_args_for_decl = htab_create_ggc (64, tree_vec_map_hash,
tree_vec_map_eq, 0);
- h = ggc_alloc_tree_vec_map ();
+ h = ggc_alloc<tree_vec_map> ();
h->base.from = from;
h->to = NULL;
loc = htab_find_slot_with_hash (debug_args_for_decl, h, DECL_UID (from),
@@ -6747,7 +6777,7 @@ type_hash_add (hashval_t hashcode, tree type)
struct type_hash *h;
void **loc;
- h = ggc_alloc_type_hash ();
+ h = ggc_alloc<type_hash> ();
h->hash = hashcode;
h->type = type;
loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT);
@@ -7360,6 +7390,8 @@ iterative_hash_expr (const_tree t, hashval_t val)
{
/* Alas, constants aren't shared, so we can't rely on pointer
identity. */
+ case VOID_CST:
+ return iterative_hash_hashval_t (0, val);
case INTEGER_CST:
for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
val = iterative_hash_host_wide_int (TREE_INT_CST_ELT (t, i), val);
@@ -9631,6 +9663,9 @@ build_common_tree_nodes (bool signed_char, bool short_double)
TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
TYPE_USER_ALIGN (void_type_node) = 0;
+ void_node = make_node (VOID_CST);
+ TREE_TYPE (void_node) = void_type_node;
+
null_pointer_node = build_int_cst (build_pointer_type (void_type_node), 0);
layout_type (TREE_TYPE (null_pointer_node));
@@ -10314,7 +10349,7 @@ build_omp_clause (location_t loc, enum omp_clause_code code)
record_node_allocation_statistics (OMP_CLAUSE, size);
- t = ggc_alloc_tree_node (size);
+ t = (tree) ggc_internal_alloc (size);
memset (t, 0, size);
TREE_SET_CODE (t, OMP_CLAUSE);
OMP_CLAUSE_SET_CODE (t, code);
@@ -10433,6 +10468,91 @@ build_call_vec (tree return_type, tree fn, vec<tree, va_gc> *args)
return ret;
}
+/* Conveniently construct a function call expression. FNDECL names the
+ function to be called and N arguments are passed in the array
+ ARGARRAY. */
+
+tree
+build_call_expr_loc_array (location_t loc, tree fndecl, int n, tree *argarray)
+{
+ tree fntype = TREE_TYPE (fndecl);
+ tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
+
+ return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
+}
+
+/* Conveniently construct a function call expression. FNDECL names the
+ function to be called and the arguments are passed in the vector
+ VEC. */
+
+tree
+build_call_expr_loc_vec (location_t loc, tree fndecl, vec<tree, va_gc> *vec)
+{
+ return build_call_expr_loc_array (loc, fndecl, vec_safe_length (vec),
+ vec_safe_address (vec));
+}
+
+
+/* Conveniently construct a function call expression. FNDECL names the
+ function to be called, N is the number of arguments, and the "..."
+ parameters are the argument expressions. */
+
+tree
+build_call_expr_loc (location_t loc, tree fndecl, int n, ...)
+{
+ va_list ap;
+ tree *argarray = XALLOCAVEC (tree, n);
+ int i;
+
+ va_start (ap, n);
+ for (i = 0; i < n; i++)
+ argarray[i] = va_arg (ap, tree);
+ va_end (ap);
+ return build_call_expr_loc_array (loc, fndecl, n, argarray);
+}
+
+/* Like build_call_expr_loc (UNKNOWN_LOCATION, ...). Duplicated because
+ varargs macros aren't supported by all bootstrap compilers. */
+
+tree
+build_call_expr (tree fndecl, int n, ...)
+{
+ va_list ap;
+ tree *argarray = XALLOCAVEC (tree, n);
+ int i;
+
+ va_start (ap, n);
+ for (i = 0; i < n; i++)
+ argarray[i] = va_arg (ap, tree);
+ va_end (ap);
+ return build_call_expr_loc_array (UNKNOWN_LOCATION, fndecl, n, argarray);
+}
+
+/* Create a new constant string literal and return a char* pointer to it.
+ The STRING_CST value is the LEN characters at STR. */
+tree
+build_string_literal (int len, const char *str)
+{
+ tree t, elem, index, type;
+
+ t = build_string (len, str);
+ elem = build_type_variant (char_type_node, 1, 0);
+ index = build_index_type (size_int (len - 1));
+ type = build_array_type (elem, index);
+ TREE_TYPE (t) = type;
+ TREE_CONSTANT (t) = 1;
+ TREE_READONLY (t) = 1;
+ TREE_STATIC (t) = 1;
+
+ type = build_pointer_type (elem);
+ t = build1 (ADDR_EXPR, type,
+ build4 (ARRAY_REF, elem,
+ t, integer_zero_node, NULL_TREE, NULL_TREE));
+ return t;
+}
+
+
+
/* Return true if T (assumed to be a DECL) must be assigned a memory
location. */
@@ -10469,40 +10589,6 @@ int_cst_value (const_tree x)
return val;
}
-/* Return value of a constant X and sign-extend it. */
-
-HOST_WIDEST_INT
-widest_int_cst_value (const_tree x)
-{
- unsigned bits = TYPE_PRECISION (TREE_TYPE (x));
- unsigned HOST_WIDEST_INT val = TREE_INT_CST_LOW (x);
-
-#if HOST_BITS_PER_WIDEST_INT > HOST_BITS_PER_WIDE_INT
- gcc_assert (HOST_BITS_PER_WIDEST_INT >= HOST_BITS_PER_DOUBLE_INT);
- gcc_assert (TREE_INT_CST_NUNITS (x) == 2);
-
- if (TREE_INT_CST_NUNITS (x) == 1)
- val = HOST_WIDE_INT (val);
- else
- val |= (((unsigned HOST_WIDEST_INT) TREE_INT_CST_ELT (x, 1))
- << HOST_BITS_PER_WIDE_INT);
-#else
- /* Make sure the sign-extended value will fit in a HOST_WIDE_INT. */
- gcc_assert (TREE_INT_CST_NUNITS (x) == 1);
-#endif
-
- if (bits < HOST_BITS_PER_WIDEST_INT)
- {
- bool negative = ((val >> (bits - 1)) & 1) != 0;
- if (negative)
- val |= (~(unsigned HOST_WIDEST_INT) 0) << (bits - 1) << 1;
- else
- val &= ~((~(unsigned HOST_WIDEST_INT) 0) << (bits - 1) << 1);
- }
-
- return val;
-}
-
/* If TYPE is an integral or pointer type, return an integer type with
the same precision which is unsigned iff UNSIGNEDP is true, or itself
if TYPE is already an integer type of signedness UNSIGNEDP. */
@@ -10960,8 +11046,13 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
}
- case OMP_CLAUSE_ALIGNED:
case OMP_CLAUSE_LINEAR:
+ WALK_SUBTREE (OMP_CLAUSE_DECL (*tp));
+ WALK_SUBTREE (OMP_CLAUSE_LINEAR_STEP (*tp));
+ WALK_SUBTREE (OMP_CLAUSE_LINEAR_STMT (*tp));
+ WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
+
+ case OMP_CLAUSE_ALIGNED:
case OMP_CLAUSE_FROM:
case OMP_CLAUSE_TO:
case OMP_CLAUSE_MAP:
diff --git a/gcc/tree.def b/gcc/tree.def
index a6247a7e00a..464c8c7b099 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -257,6 +257,8 @@ DEFTREECODE (LANG_TYPE, "lang_type", tcc_type, 0)
/* First, the constants. */
+DEFTREECODE (VOID_CST, "void_cst", tcc_constant, 0)
+
/* Contents are in an array of HOST_WIDE_INTs.
We often access these constants both in their native precision and
diff --git a/gcc/tree.h b/gcc/tree.h
index 3e8e625ab9f..5392fddfef7 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1333,6 +1333,9 @@ extern void protected_set_expr_location (tree, location_t);
#define OMP_CLAUSE_LINEAR_STEP(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR), 1)
+#define OMP_CLAUSE_LINEAR_STMT(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR), 2)
+
#define OMP_CLAUSE_LINEAR_GIMPLE_SEQ(NODE) \
(OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_init
@@ -2320,11 +2323,12 @@ extern void decl_value_expr_insert (tree, tree);
(DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.comdat_flag)
#define DECL_COMDAT_GROUP(NODE) \
- (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.comdat_group)
+ decl_comdat_group (NODE)
/* Used in TREE_PUBLIC decls to indicate that copies of this DECL in
multiple translation units should be merged. */
-#define DECL_ONE_ONLY(NODE) (DECL_COMDAT_GROUP (NODE) != NULL_TREE)
+#define DECL_ONE_ONLY(NODE) (DECL_COMDAT_GROUP (NODE) != NULL_TREE \
+ && (TREE_PUBLIC (NODE) || DECL_EXTERNAL (NODE)))
/* The name of the object as the assembler will see it (but before any
translations made by ASM_OUTPUT_LABELREF). Often this is the same
@@ -3242,6 +3246,8 @@ tree_operand_check_code (const_tree __t, enum tree_code __code, int __i,
#define uint32_type_node global_trees[TI_UINT32_TYPE]
#define uint64_type_node global_trees[TI_UINT64_TYPE]
+#define void_node global_trees[TI_VOID]
+
#define integer_zero_node global_trees[TI_INTEGER_ZERO]
#define integer_one_node global_trees[TI_INTEGER_ONE]
#define integer_three_node global_trees[TI_INTEGER_THREE]
@@ -3425,6 +3431,8 @@ tree_operand_check_code (const_tree __t, enum tree_code __code, int __i,
|| ((NODE) && TREE_TYPE ((NODE)) == error_mark_node))
extern tree decl_assembler_name (tree);
+extern tree decl_comdat_group (tree);
+extern tree decl_comdat_group_id (tree);
/* Compute the number of bytes occupied by 'node'. This routine only
looks at TREE_CODE and, if the code is TREE_VEC, TREE_VEC_LENGTH. */
@@ -3616,6 +3624,11 @@ extern tree build_call_valist (tree, tree, int, va_list);
build_call_array_loc (UNKNOWN_LOCATION, T1, T2, N, T3)
extern tree build_call_array_loc (location_t, tree, tree, int, const tree *);
extern tree build_call_vec (tree, tree, vec<tree, va_gc> *);
+extern tree build_call_expr_loc_array (location_t, tree, int, tree *);
+extern tree build_call_expr_loc_vec (location_t, tree, vec<tree, va_gc> *);
+extern tree build_call_expr_loc (location_t, tree, int, ...);
+extern tree build_call_expr (tree, int, ...);
+extern tree build_string_literal (int, const char *);
/* Construct various nodes representing data types. */
@@ -4264,7 +4277,6 @@ extern tree build_range_type (tree, tree, tree);
extern tree build_nonshared_range_type (tree, tree, tree);
extern bool subrange_type_for_debug_p (const_tree, tree *, tree *);
extern HOST_WIDE_INT int_cst_value (const_tree);
-extern HOST_WIDEST_INT widest_int_cst_value (const_tree);
extern tree tree_block (tree);
extern void tree_set_block (tree, tree);
extern location_t *block_nonartificial_location (tree);
@@ -4570,7 +4582,6 @@ namespace wi
unsigned int get_len () const;
};
- template <>
template <int N>
struct int_traits <extended_tree <N> >
{
@@ -4739,46 +4750,4 @@ extern tree get_inner_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
extern tree array_ref_low_bound (tree);
-/* In builtins.c. */
-
-/* Non-zero if __builtin_constant_p should be folded right away. */
-extern bool force_folding_builtin_constant_p;
-
-extern bool avoid_folding_inline_builtin (tree);
-extern tree fold_call_expr (location_t, tree, bool);
-extern tree fold_builtin_fputs (location_t, tree, tree, bool, bool, tree);
-extern tree fold_builtin_strcpy (location_t, tree, tree, tree, tree);
-extern tree fold_builtin_strncpy (location_t, tree, tree, tree, tree, tree);
-extern tree fold_builtin_strcat (location_t, tree, tree, tree);
-extern tree fold_builtin_memory_chk (location_t, tree, tree, tree, tree, tree, tree, bool,
- enum built_in_function);
-extern tree fold_builtin_stxcpy_chk (location_t, tree, tree, tree, tree, tree, bool,
- enum built_in_function);
-extern tree fold_builtin_stxncpy_chk (location_t, tree, tree, tree, tree, tree, bool,
- enum built_in_function);
-extern tree fold_builtin_expect (location_t, tree, tree, tree);
-extern bool fold_builtin_next_arg (tree, bool);
-extern enum built_in_function builtin_mathfn_code (const_tree);
-extern tree fold_builtin_call_array (location_t, tree, tree, int, tree *);
-extern tree build_call_expr_loc_array (location_t, tree, int, tree *);
-extern tree build_call_expr_loc_vec (location_t, tree, vec<tree, va_gc> *);
-extern tree build_call_expr_loc (location_t, tree, int, ...);
-extern tree build_call_expr (tree, int, ...);
-extern tree mathfn_built_in (tree, enum built_in_function fn);
-extern tree c_strlen (tree, int);
-extern tree build_string_literal (int, const char *);
-extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
-extern bool is_builtin_fn (tree);
-extern bool get_object_alignment_1 (tree, unsigned int *,
- unsigned HOST_WIDE_INT *);
-extern unsigned int get_object_alignment (tree);
-extern bool get_pointer_alignment_1 (tree, unsigned int *,
- unsigned HOST_WIDE_INT *);
-extern unsigned int get_pointer_alignment (tree);
-extern tree fold_call_stmt (gimple, bool);
-extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum built_in_function);
-extern void set_builtin_user_assembler_name (tree decl, const char *asmspec);
-extern bool is_simple_builtin (tree);
-extern bool is_inexpensive_builtin (tree);
-
#endif /* GCC_TREE_H */
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index d9d740c7cd3..4de6d6e8ae3 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -47,6 +47,8 @@ along with GCC; see the file COPYING3. If not see
#include "asan.h"
#include "gimplify-me.h"
#include "intl.h"
+#include "realmpfr.h"
+#include "dfp.h"
/* Map from a tree to a VAR_DECL tree. */
@@ -99,7 +101,7 @@ decl_for_type_insert (tree type, tree decl)
struct tree_type_map *h;
void **slot;
- h = ggc_alloc_tree_type_map ();
+ h = ggc_alloc<tree_type_map> ();
h->type.from = type;
h->decl = decl;
slot = htab_find_slot_with_hash (decl_tree_for_type, h, TYPE_UID (type),
@@ -267,9 +269,14 @@ static unsigned short
get_ubsan_type_info_for_type (tree type)
{
gcc_assert (TYPE_SIZE (type) && tree_fits_uhwi_p (TYPE_SIZE (type)));
- int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
- gcc_assert (prec != -1);
- return (prec << 1) | !TYPE_UNSIGNED (type);
+ if (TREE_CODE (type) == REAL_TYPE)
+ return tree_to_uhwi (TYPE_SIZE (type));
+ else
+ {
+ int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
+ gcc_assert (prec != -1);
+ return (prec << 1) | !TYPE_UNSIGNED (type);
+ }
}
/* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
@@ -359,7 +366,14 @@ ubsan_type_descriptor (tree type, bool want_pointer_type_p)
tkind = 0x0000;
break;
case REAL_TYPE:
- tkind = 0x0001;
+ /* FIXME: libubsan right now only supports float, double and
+ long double type formats. */
+ if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
+ || TYPE_MODE (type) == TYPE_MODE (double_type_node)
+ || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
+ tkind = 0x0001;
+ else
+ tkind = 0xffff;
break;
default:
tkind = 0xffff;
@@ -531,9 +545,9 @@ ubsan_instrument_unreachable (location_t loc)
bool
is_ubsan_builtin_p (tree t)
{
- gcc_checking_assert (TREE_CODE (t) == FUNCTION_DECL);
- return strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
- "__builtin___ubsan_", 18) == 0;
+ return TREE_CODE (t) == FUNCTION_DECL
+ && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
+ "__builtin___ubsan_", 18) == 0;
}
/* Expand UBSAN_NULL internal call. */
@@ -891,6 +905,130 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi)
gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
}
+/* Instrument float point-to-integer conversion. TYPE is an integer type of
+ destination, EXPR is floating-point expression. */
+
+tree
+ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
+{
+ tree expr_type = TREE_TYPE (expr);
+ tree t, tt, fn, min, max;
+ enum machine_mode mode = TYPE_MODE (expr_type);
+ int prec = TYPE_PRECISION (type);
+ bool uns_p = TYPE_UNSIGNED (type);
+
+ /* Float to integer conversion first truncates toward zero, so
+ even signed char c = 127.875f; is not problematic.
+ Therefore, we should complain only if EXPR is unordered or smaller
+ or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
+ TYPE_MAX_VALUE + 1.0. */
+ if (REAL_MODE_FORMAT (mode)->b == 2)
+ {
+ /* For maximum, TYPE_MAX_VALUE might not be representable
+ in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
+ EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
+ either representable or infinity. */
+ REAL_VALUE_TYPE maxval = dconst1;
+ SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
+ real_convert (&maxval, mode, &maxval);
+ max = build_real (expr_type, maxval);
+
+ /* For unsigned, assume -1.0 is always representable. */
+ if (uns_p)
+ min = build_minus_one_cst (expr_type);
+ else
+ {
+ /* TYPE_MIN_VALUE is generally representable (or -inf),
+ but TYPE_MIN_VALUE - 1.0 might not be. */
+ REAL_VALUE_TYPE minval = dconstm1, minval2;
+ SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
+ real_convert (&minval, mode, &minval);
+ real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
+ real_convert (&minval2, mode, &minval2);
+ if (real_compare (EQ_EXPR, &minval, &minval2)
+ && !real_isinf (&minval))
+ {
+ /* If TYPE_MIN_VALUE - 1.0 is not representable and
+ rounds to TYPE_MIN_VALUE, we need to subtract
+ more. As REAL_MODE_FORMAT (mode)->p is the number
+ of base digits, we want to subtract a number that
+ will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
+ times smaller than minval. */
+ minval2 = dconst1;
+ gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
+ SET_REAL_EXP (&minval2,
+ REAL_EXP (&minval2) + prec - 1
+ - REAL_MODE_FORMAT (mode)->p + 1);
+ real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
+ real_convert (&minval2, mode, &minval2);
+ }
+ min = build_real (expr_type, minval2);
+ }
+ }
+ else if (REAL_MODE_FORMAT (mode)->b == 10)
+ {
+ /* For _Decimal128 up to 34 decimal digits, - sign,
+ dot, e, exponent. */
+ char buf[64];
+ mpfr_t m;
+ int p = REAL_MODE_FORMAT (mode)->p;
+ REAL_VALUE_TYPE maxval, minval;
+
+ /* Use mpfr_snprintf rounding to compute the smallest
+ representable decimal number greater or equal than
+ 1 << (prec - !uns_p). */
+ mpfr_init2 (m, prec + 2);
+ mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
+ mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
+ decimal_real_from_string (&maxval, buf);
+ max = build_real (expr_type, maxval);
+
+ /* For unsigned, assume -1.0 is always representable. */
+ if (uns_p)
+ min = build_minus_one_cst (expr_type);
+ else
+ {
+ /* Use mpfr_snprintf rounding to compute the largest
+ representable decimal number less or equal than
+ (-1 << (prec - 1)) - 1. */
+ mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
+ mpfr_sub_ui (m, m, 1, GMP_RNDN);
+ mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
+ decimal_real_from_string (&minval, buf);
+ min = build_real (expr_type, minval);
+ }
+ mpfr_clear (m);
+ }
+ else
+ return NULL_TREE;
+
+ if (flag_sanitize_undefined_trap_on_error)
+ fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
+ else
+ {
+ /* Create the __ubsan_handle_float_cast_overflow fn call. */
+ tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", NULL,
+ NULL,
+ ubsan_type_descriptor (expr_type, false),
+ ubsan_type_descriptor (type, false),
+ NULL_TREE);
+ enum built_in_function bcode
+ = flag_sanitize_recover
+ ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
+ : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
+ fn = builtin_decl_explicit (bcode);
+ fn = build_call_expr_loc (loc, fn, 2,
+ build_fold_addr_expr_loc (loc, data),
+ ubsan_encode_value (expr, false));
+ }
+
+ t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
+ tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
+ return fold_build3 (COND_EXPR, void_type_node,
+ fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt),
+ fn, integer_zero_node);
+}
+
namespace {
const pass_data pass_data_ubsan =
diff --git a/gcc/ubsan.h b/gcc/ubsan.h
index 67cc6e915e3..b0084192b7e 100644
--- a/gcc/ubsan.h
+++ b/gcc/ubsan.h
@@ -44,6 +44,7 @@ extern tree ubsan_type_descriptor (tree, bool);
extern tree ubsan_encode_value (tree, bool = false);
extern bool is_ubsan_builtin_p (tree);
extern tree ubsan_build_overflow_builtin (tree_code, location_t, tree, tree, tree);
+extern tree ubsan_instrument_float_cast (location_t, tree, tree);
#endif /* GCC_UBSAN_H */
diff --git a/gcc/value-prof.c b/gcc/value-prof.c
index 0d033ef6284..5b194976570 100644
--- a/gcc/value-prof.c
+++ b/gcc/value-prof.c
@@ -266,11 +266,11 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
unsigned int i;
fprintf (dump_file, " [");
for (i = 0; i < hist->hdata.intvl.steps; i++)
- fprintf (dump_file, " %d:"HOST_WIDEST_INT_PRINT_DEC,
+ fprintf (dump_file, " %d:%"PRId64,
hist->hdata.intvl.int_start + i,
- (HOST_WIDEST_INT) hist->hvalue.counters[i]);
- fprintf (dump_file, " ] outside range:"HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) hist->hvalue.counters[i]);
+ (int64_t) hist->hvalue.counters[i]);
+ fprintf (dump_file, " ] outside range:%"PRId64,
+ (int64_t) hist->hvalue.counters[i]);
}
fprintf (dump_file, ".\n");
break;
@@ -279,10 +279,10 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
fprintf (dump_file, "Pow2 counter ");
if (hist->hvalue.counters)
{
- fprintf (dump_file, "pow2:"HOST_WIDEST_INT_PRINT_DEC
- " nonpow2:"HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) hist->hvalue.counters[0],
- (HOST_WIDEST_INT) hist->hvalue.counters[1]);
+ fprintf (dump_file, "pow2:%"PRId64
+ " nonpow2:%"PRId64,
+ (int64_t) hist->hvalue.counters[0],
+ (int64_t) hist->hvalue.counters[1]);
}
fprintf (dump_file, ".\n");
break;
@@ -291,12 +291,12 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
fprintf (dump_file, "Single value ");
if (hist->hvalue.counters)
{
- fprintf (dump_file, "value:"HOST_WIDEST_INT_PRINT_DEC
- " match:"HOST_WIDEST_INT_PRINT_DEC
- " wrong:"HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) hist->hvalue.counters[0],
- (HOST_WIDEST_INT) hist->hvalue.counters[1],
- (HOST_WIDEST_INT) hist->hvalue.counters[2]);
+ fprintf (dump_file, "value:%"PRId64
+ " match:%"PRId64
+ " wrong:%"PRId64,
+ (int64_t) hist->hvalue.counters[0],
+ (int64_t) hist->hvalue.counters[1],
+ (int64_t) hist->hvalue.counters[2]);
}
fprintf (dump_file, ".\n");
break;
@@ -305,10 +305,10 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
fprintf (dump_file, "Average value ");
if (hist->hvalue.counters)
{
- fprintf (dump_file, "sum:"HOST_WIDEST_INT_PRINT_DEC
- " times:"HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) hist->hvalue.counters[0],
- (HOST_WIDEST_INT) hist->hvalue.counters[1]);
+ fprintf (dump_file, "sum:%"PRId64
+ " times:%"PRId64,
+ (int64_t) hist->hvalue.counters[0],
+ (int64_t) hist->hvalue.counters[1]);
}
fprintf (dump_file, ".\n");
break;
@@ -317,8 +317,8 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
fprintf (dump_file, "IOR value ");
if (hist->hvalue.counters)
{
- fprintf (dump_file, "ior:"HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) hist->hvalue.counters[0]);
+ fprintf (dump_file, "ior:%"PRId64,
+ (int64_t) hist->hvalue.counters[0]);
}
fprintf (dump_file, ".\n");
break;
@@ -327,12 +327,12 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
fprintf (dump_file, "Constant delta ");
if (hist->hvalue.counters)
{
- fprintf (dump_file, "value:"HOST_WIDEST_INT_PRINT_DEC
- " match:"HOST_WIDEST_INT_PRINT_DEC
- " wrong:"HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) hist->hvalue.counters[0],
- (HOST_WIDEST_INT) hist->hvalue.counters[1],
- (HOST_WIDEST_INT) hist->hvalue.counters[2]);
+ fprintf (dump_file, "value:%"PRId64
+ " match:%"PRId64
+ " wrong:%"PRId64,
+ (int64_t) hist->hvalue.counters[0],
+ (int64_t) hist->hvalue.counters[1],
+ (int64_t) hist->hvalue.counters[2]);
}
fprintf (dump_file, ".\n");
break;
@@ -340,12 +340,12 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
fprintf (dump_file, "Indirect call ");
if (hist->hvalue.counters)
{
- fprintf (dump_file, "value:"HOST_WIDEST_INT_PRINT_DEC
- " match:"HOST_WIDEST_INT_PRINT_DEC
- " all:"HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) hist->hvalue.counters[0],
- (HOST_WIDEST_INT) hist->hvalue.counters[1],
- (HOST_WIDEST_INT) hist->hvalue.counters[2]);
+ fprintf (dump_file, "value:%"PRId64
+ " match:%"PRId64
+ " all:%"PRId64,
+ (int64_t) hist->hvalue.counters[0],
+ (int64_t) hist->hvalue.counters[1],
+ (int64_t) hist->hvalue.counters[2]);
}
fprintf (dump_file, ".\n");
break;
@@ -353,8 +353,8 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
fprintf (dump_file, "Time profile ");
if (hist->hvalue.counters)
{
- fprintf (dump_file, "time:"HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) hist->hvalue.counters[0]);
+ fprintf (dump_file, "time:%"PRId64,
+ (int64_t) hist->hvalue.counters[0]);
}
fprintf (dump_file, ".\n");
break;
@@ -1541,8 +1541,8 @@ gimple_ic_transform (gimple_stmt_iterator *gsi)
print_generic_expr (dump_file, direct_call->decl, TDF_SLIM);
fprintf (dump_file, " transformation on insn postponned to ipa-profile");
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
- fprintf (dump_file, "hist->count "HOST_WIDEST_INT_PRINT_DEC
- " hist->all "HOST_WIDEST_INT_PRINT_DEC"\n", count, all);
+ fprintf (dump_file, "hist->count %"PRId64
+ " hist->all %"PRId64"\n", count, all);
}
return true;
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index f36a1e9a692..9e71165e1c7 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -8748,8 +8748,7 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
note_vl = NULL_RTX;
if (!complete)
- note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, NULL_RTX,
- (int) initialized);
+ note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, NULL_RTX, initialized);
else if (n_var_parts == 1)
{
rtx expr_list;
@@ -8759,8 +8758,7 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
else
expr_list = loc[0];
- note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, expr_list,
- (int) initialized);
+ note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, expr_list, initialized);
}
else if (n_var_parts)
{
@@ -8773,7 +8771,7 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
parallel = gen_rtx_PARALLEL (VOIDmode,
gen_rtvec_v (n_var_parts, loc));
note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl,
- parallel, (int) initialized);
+ parallel, initialized);
}
if (where != EMIT_NOTE_BEFORE_INSN)
diff --git a/gcc/varasm.c b/gcc/varasm.c
index f8930b989b8..375838ad9f5 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -114,7 +114,6 @@ static hashval_t const_desc_hash (const void *);
static int const_desc_eq (const void *, const void *);
static hashval_t const_hash_1 (const tree);
static int compare_constant (const tree, const tree);
-static tree copy_constant (tree);
static void output_constant_def_contents (rtx);
static void output_addressed_constants (tree);
static unsigned HOST_WIDE_INT output_constant (tree, unsigned HOST_WIDE_INT,
@@ -242,7 +241,7 @@ get_unnamed_section (unsigned int flags, void (*callback) (const void *),
{
section *sect;
- sect = ggc_alloc_section ();
+ sect = ggc_alloc<section> ();
sect->unnamed.common.flags = flags | SECTION_UNNAMED;
sect->unnamed.callback = callback;
sect->unnamed.data = data;
@@ -259,7 +258,7 @@ get_noswitch_section (unsigned int flags, noswitch_section_callback callback)
{
section *sect;
- sect = ggc_alloc_section ();
+ sect = ggc_alloc<section> ();
sect->noswitch.common.flags = flags | SECTION_NOSWITCH;
sect->noswitch.callback = callback;
@@ -280,7 +279,7 @@ get_section (const char *name, unsigned int flags, tree decl)
flags |= SECTION_NAMED;
if (*slot == NULL)
{
- sect = ggc_alloc_section ();
+ sect = ggc_alloc<section> ();
sect->named.common.flags = flags;
sect->named.name = ggc_strdup (name);
sect->named.decl = decl;
@@ -361,7 +360,7 @@ get_block_for_section (section *sect)
block = (struct object_block *) *slot;
if (block == NULL)
{
- block = ggc_alloc_cleared_object_block ();
+ block = ggc_cleared_alloc<object_block> ();
block->sect = sect;
*slot = block;
}
@@ -381,7 +380,7 @@ create_block_symbol (const char *label, struct object_block *block,
/* Create the extended SYMBOL_REF. */
size = RTX_HDR_SIZE + sizeof (struct block_symbol);
- symbol = ggc_alloc_rtx_def (size);
+ symbol = (rtx) ggc_internal_alloc (size);
/* Initialize the normal SYMBOL_REF fields. */
memset (symbol, 0, size);
@@ -428,7 +427,7 @@ resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED,
if (DECL_SECTION_NAME (decl) == NULL_TREE
&& targetm_common.have_named_sections
&& (flag_function_or_data_sections
- || DECL_ONE_ONLY (decl)))
+ || DECL_COMDAT_GROUP (decl)))
{
targetm.asm_out.unique_section (decl, reloc);
DECL_HAS_IMPLICIT_SECTION_NAME_P (decl) = true;
@@ -517,7 +516,7 @@ get_named_text_section (tree decl,
/* Do not try to split gnu_linkonce functions. This gets somewhat
slipperly. */
- if (DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP)
+ if (DECL_COMDAT_GROUP (decl) && !HAVE_COMDAT_GROUP)
return NULL;
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
name = targetm.strip_name_encoding (name);
@@ -687,7 +686,7 @@ default_function_rodata_section (tree decl)
{
const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
- if (DECL_ONE_ONLY (decl) && HAVE_COMDAT_GROUP)
+ if (DECL_COMDAT_GROUP (decl) && HAVE_COMDAT_GROUP)
{
const char *dot;
size_t len;
@@ -704,7 +703,7 @@ default_function_rodata_section (tree decl)
return get_section (rname, SECTION_LINKONCE, decl);
}
/* For .gnu.linkonce.t.foo we want to use .gnu.linkonce.r.foo. */
- else if (DECL_ONE_ONLY (decl)
+ else if (DECL_COMDAT_GROUP (decl)
&& strncmp (name, ".gnu.linkonce.t.", 16) == 0)
{
size_t len = strlen (name) + 1;
@@ -996,7 +995,8 @@ align_variable (tree decl, bool dont_output_data)
and for code accessing the variable as guaranteed alignment, we
can only increase the alignment if it is a performance optimization
if the references to it must bind to the current definition. */
- if (decl_binds_to_current_def_p (decl))
+ if (decl_binds_to_current_def_p (decl)
+ && !DECL_VIRTUAL_P (decl))
{
#ifdef DATA_ALIGNMENT
unsigned int data_align = DATA_ALIGNMENT (TREE_TYPE (decl), align);
@@ -1082,6 +1082,9 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
{
addr_space_t as = ADDR_SPACE_GENERIC;
int reloc;
+ symtab_node *snode = symtab_get_node (decl);
+ if (snode)
+ decl = symtab_alias_ultimate_target (snode)->decl;
if (TREE_TYPE (decl) != error_mark_node)
as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
@@ -1142,7 +1145,7 @@ get_block_for_decl (tree decl)
/* There's no point using object blocks for something that is
isolated by definition. */
- if (DECL_ONE_ONLY (decl))
+ if (DECL_COMDAT_GROUP (decl))
return NULL;
}
@@ -3099,71 +3102,6 @@ compare_constant (const tree t1, const tree t2)
gcc_unreachable ();
}
-/* Make a copy of the whole tree structure for a constant. This
- handles the same types of nodes that compare_constant handles. */
-
-static tree
-copy_constant (tree exp)
-{
- switch (TREE_CODE (exp))
- {
- case ADDR_EXPR:
- /* For ADDR_EXPR, we do not want to copy the decl whose address
- is requested. We do want to copy constants though. */
- if (CONSTANT_CLASS_P (TREE_OPERAND (exp, 0)))
- return build1 (TREE_CODE (exp), TREE_TYPE (exp),
- copy_constant (TREE_OPERAND (exp, 0)));
- else
- return copy_node (exp);
-
- case INTEGER_CST:
- case REAL_CST:
- case FIXED_CST:
- case STRING_CST:
- return copy_node (exp);
-
- case COMPLEX_CST:
- return build_complex (TREE_TYPE (exp),
- copy_constant (TREE_REALPART (exp)),
- copy_constant (TREE_IMAGPART (exp)));
-
- case PLUS_EXPR:
- case POINTER_PLUS_EXPR:
- case MINUS_EXPR:
- return build2 (TREE_CODE (exp), TREE_TYPE (exp),
- copy_constant (TREE_OPERAND (exp, 0)),
- copy_constant (TREE_OPERAND (exp, 1)));
-
- CASE_CONVERT:
- case VIEW_CONVERT_EXPR:
- return build1 (TREE_CODE (exp), TREE_TYPE (exp),
- copy_constant (TREE_OPERAND (exp, 0)));
-
- case VECTOR_CST:
- return build_vector (TREE_TYPE (exp), VECTOR_CST_ELTS (exp));
-
- case CONSTRUCTOR:
- {
- tree copy = copy_node (exp);
- vec<constructor_elt, va_gc> *v;
- unsigned HOST_WIDE_INT idx;
- tree purpose, value;
-
- vec_alloc (v, vec_safe_length (CONSTRUCTOR_ELTS (exp)));
- FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (exp), idx, purpose, value)
- {
- constructor_elt ce = {purpose, copy_constant (value)};
- v->quick_push (ce);
- }
- CONSTRUCTOR_ELTS (copy) = v;
- return copy;
- }
-
- default:
- gcc_unreachable ();
- }
-}
-
/* Return the section into which constant EXP should be placed. */
static section *
@@ -3203,8 +3141,8 @@ build_constant_desc (tree exp)
int labelno;
tree decl;
- desc = ggc_alloc_constant_descriptor_tree ();
- desc->value = copy_constant (exp);
+ desc = ggc_alloc<constant_descriptor_tree> ();
+ desc->value = exp;
/* Create a string containing the label name, in LABEL. */
labelno = const_labelno++;
@@ -3616,7 +3554,7 @@ create_constant_pool (void)
{
struct rtx_constant_pool *pool;
- pool = ggc_alloc_rtx_constant_pool ();
+ pool = ggc_alloc<rtx_constant_pool> ();
pool->const_rtx_htab = htab_create_ggc (31, const_desc_rtx_hash,
const_desc_rtx_eq, NULL);
pool->first = NULL;
@@ -3682,7 +3620,7 @@ force_const_mem (enum machine_mode mode, rtx x)
return copy_rtx (desc->mem);
/* Otherwise, create a new descriptor. */
- desc = ggc_alloc_constant_descriptor_rtx ();
+ desc = ggc_alloc<constant_descriptor_rtx> ();
*slot = desc;
/* Align the location counter as required by EXP's data type. */
@@ -5081,24 +5019,27 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
this_time = MIN (end_offset - next_offset, BITS_PER_UNIT - next_bit);
if (BYTES_BIG_ENDIAN)
{
- /* On big-endian machine, take the most significant bits
- first (of the bits that are significant)
- and put them into bytes from the most significant end. */
+ /* On big-endian machine, take the most significant bits (of the
+ bits that are significant) first and put them into bytes from
+ the most significant end. */
shift = end_offset - next_offset - this_time;
/* Don't try to take a bunch of bits that cross
- the word boundary in the INTEGER_CST. We can
- only select bits from the LOW or HIGH part
- not from both. */
+ the word boundary in the INTEGER_CST. We can
+ only select bits from one element. */
if ((shift / HOST_BITS_PER_WIDE_INT)
- != ((shift + this_time) / HOST_BITS_PER_WIDE_INT))
- this_time = (shift + this_time) & (HOST_BITS_PER_WIDE_INT - 1);
+ != ((shift + this_time - 1) / HOST_BITS_PER_WIDE_INT))
+ {
+ const int end = shift + this_time - 1;
+ shift = end & -HOST_BITS_PER_WIDE_INT;
+ this_time = end - shift + 1;
+ }
/* Now get the bits from the appropriate constant word. */
value = TREE_INT_CST_ELT (local->val, shift / HOST_BITS_PER_WIDE_INT);
shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
- /* Get the result. This works only when:
+ /* Get the result. This works only when:
1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
local->byte |= (((value >> shift)
& (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
@@ -5106,25 +5047,24 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
}
else
{
- /* On little-endian machines,
- take first the least significant bits of the value
- and pack them starting at the least significant
+ /* On little-endian machines, take the least significant bits of
+ the value first and pack them starting at the least significant
bits of the bytes. */
shift = next_offset - byte_relative_ebitpos;
/* Don't try to take a bunch of bits that cross
- the word boundary in the INTEGER_CST. We can
- only select bits from the LOW or HIGH part
- not from both. */
+ the word boundary in the INTEGER_CST. We can
+ only select bits from one element. */
if ((shift / HOST_BITS_PER_WIDE_INT)
- != ((shift + this_time) / HOST_BITS_PER_WIDE_INT))
- this_time = (HOST_BITS_PER_WIDE_INT - shift);
+ != ((shift + this_time - 1) / HOST_BITS_PER_WIDE_INT))
+ this_time
+ = HOST_BITS_PER_WIDE_INT - (shift & (HOST_BITS_PER_WIDE_INT - 1));
/* Now get the bits from the appropriate constant word. */
value = TREE_INT_CST_ELT (local->val, shift / HOST_BITS_PER_WIDE_INT);
shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
- /* Get the result. This works only when:
+ /* Get the result. This works only when:
1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
local->byte |= (((value >> shift)
& (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
@@ -5712,7 +5652,7 @@ record_tm_clone_pair (tree o, tree n)
if (tm_clone_hash == NULL)
tm_clone_hash = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0);
- h = ggc_alloc_tree_map ();
+ h = ggc_alloc<tree_map> ();
h->hash = htab_hash_pointer (o);
h->base.from = o;
h->to = n;
@@ -5916,17 +5856,23 @@ supports_one_only (void)
void
make_decl_one_only (tree decl, tree comdat_group)
{
+ struct symtab_node *symbol;
gcc_assert (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == FUNCTION_DECL);
TREE_PUBLIC (decl) = 1;
+ if (TREE_CODE (decl) == VAR_DECL)
+ symbol = varpool_node_for_decl (decl);
+ else
+ symbol = cgraph_get_create_node (decl);
+
if (SUPPORTS_ONE_ONLY)
{
#ifdef MAKE_DECL_ONE_ONLY
MAKE_DECL_ONE_ONLY (decl);
#endif
- DECL_COMDAT_GROUP (decl) = comdat_group;
+ symbol->set_comdat_group (comdat_group);
}
else if (TREE_CODE (decl) == VAR_DECL
&& (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
@@ -6076,7 +6022,7 @@ default_section_type_flags (tree decl, const char *name, int reloc)
flags |= SECTION_RELRO;
}
- if (decl && DECL_P (decl) && DECL_ONE_ONLY (decl))
+ if (decl && DECL_P (decl) && DECL_COMDAT_GROUP (decl))
flags |= SECTION_LINKONCE;
if (strcmp (name, ".vtable_map_vars") == 0)
@@ -7075,7 +7021,16 @@ place_block_symbol (rtx symbol)
}
else
{
+ struct symtab_node *snode;
decl = SYMBOL_REF_DECL (symbol);
+
+ snode = symtab_get_node (decl);
+ if (snode->alias)
+ {
+ rtx target = DECL_RTL (symtab_alias_ultimate_target (snode)->decl);
+ SYMBOL_REF_BLOCK_OFFSET (symbol) = SYMBOL_REF_BLOCK_OFFSET (target);
+ return;
+ }
alignment = get_variable_align (decl);
size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
if ((flag_sanitize & SANITIZE_ADDRESS)
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 69172c69dba..1697bb401a3 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -135,7 +135,7 @@ varpool_call_variable_insertion_hooks (varpool_node *node)
varpool_node *
varpool_create_empty_node (void)
{
- varpool_node *node = ggc_alloc_cleared_varpool_node ();
+ varpool_node *node = ggc_cleared_alloc<varpool_node> ();
node->type = SYMTAB_VARIABLE;
return node;
}
@@ -211,6 +211,8 @@ dump_varpool_node (FILE *f, varpool_node *node)
fprintf (f, " read-only");
if (ctor_for_folding (node->decl) != error_mark_node)
fprintf (f, " const-value-known");
+ if (node->writeonly)
+ fprintf (f, " write-only");
fprintf (f, "\n");
}
@@ -353,7 +355,6 @@ varpool_add_new_variable (tree decl)
enum availability
cgraph_variable_initializer_availability (varpool_node *node)
{
- gcc_assert (cgraph_function_flags_ready);
if (!node->definition)
return AVAIL_NOT_AVAILABLE;
if (!TREE_PUBLIC (node->decl))
diff --git a/gcc/vec.h b/gcc/vec.h
index 587302344d5..2e5313dd146 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -48,9 +48,10 @@ along with GCC; see the file COPYING3. If not see
weak. There are files compiled with -DGENERATOR_FILE that already
include ggc.h. We only need to provide these definitions if ggc.h
has not been included. Sigh. */
+
extern void ggc_free (void *);
extern size_t ggc_round_alloc_size (size_t requested_size);
- extern void *ggc_realloc_stat (void *, size_t MEM_STAT_DECL);
+ extern void *ggc_realloc (void *, size_t CXX_MEM_STAT_INFO);
# endif // GCC_GGC_H
#endif // VEC_GC_ENABLED
@@ -396,7 +397,7 @@ va_gc::reserve (vec<T, A, vl_embed> *&v, unsigned reserve, bool exact
size = vec_offset + alloc * elt_size;
unsigned nelem = v ? v->length () : 0;
- v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc_stat (v, size
+ v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc (v, size
PASS_MEM_STAT));
v->embedded_init (alloc, nelem);
}
diff --git a/gcc/vmsdbg.h b/gcc/vmsdbg.h
index db1a416a8ba..8e656cee6cd 100644
--- a/gcc/vmsdbg.h
+++ b/gcc/vmsdbg.h
@@ -216,13 +216,7 @@ typedef struct _DST_SRC_COMMAND
unsigned char dst_b_src_df_length;
unsigned char dst_b_src_df_flags;
unsigned short int dst_w_src_df_fileid;
-#ifdef HAVE_LONG_LONG
- long long dst_q_src_df_rms_cdt;
-#else
-#ifdef HAVE___INT64
- __int64 dst_q_src_df_rms_cdt;
-#endif
-#endif
+ int64_t dst_q_src_df_rms_cdt;
unsigned int dst_l_src_df_rms_ebk;
unsigned short int dst_w_src_df_rms_ffb;
unsigned char dst_b_src_df_rms_rfo;
diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc
index 69a15bcd148..ed7f01bd19e 100644
--- a/gcc/wide-int.cc
+++ b/gcc/wide-int.cc
@@ -27,13 +27,29 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "dumpfile.h"
-#if GCC_VERSION >= 3000
+
+#define HOST_BITS_PER_HALF_WIDE_INT 32
+#if HOST_BITS_PER_HALF_WIDE_INT == HOST_BITS_PER_LONG
+# define HOST_HALF_WIDE_INT long
+#elif HOST_BITS_PER_HALF_WIDE_INT == HOST_BITS_PER_INT
+# define HOST_HALF_WIDE_INT int
+#else
+#error Please add support for HOST_HALF_WIDE_INT
+#endif
+
#define W_TYPE_SIZE HOST_BITS_PER_WIDE_INT
+/* Do not include longlong.h when compiler is clang-based. See PR61146. */
+#if GCC_VERSION >= 3000 && (W_TYPE_SIZE == 32 || defined (__SIZEOF_INT128__)) && !defined(__clang__)
typedef unsigned HOST_HALF_WIDE_INT UHWtype;
typedef unsigned HOST_WIDE_INT UWtype;
typedef unsigned int UQItype __attribute__ ((mode (QI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef unsigned int UDItype __attribute__ ((mode (DI)));
+#if W_TYPE_SIZE == 32
+typedef unsigned int UDWtype __attribute__ ((mode (DI)));
+#else
+typedef unsigned int UDWtype __attribute__ ((mode (TI)));
+#endif
#include "longlong.h"
#endif
diff --git a/gcc/wide-int.h b/gcc/wide-int.h
index 46a1c22998f..bb51ed2c82a 100644
--- a/gcc/wide-int.h
+++ b/gcc/wide-int.h
@@ -530,6 +530,9 @@ namespace wi
BINARY_FUNCTION mod_round (const T1 &, const T2 &, signop, bool * = 0);
template <typename T1, typename T2>
+ bool multiple_of_p (const T1 &, const T2 &, signop);
+
+ template <typename T1, typename T2>
bool multiple_of_p (const T1 &, const T2 &, signop,
WI_BINARY_RESULT (T1, T2) *);
@@ -1443,12 +1446,22 @@ namespace wi
: public primitive_int_traits <unsigned int, false> {};
template <>
- struct int_traits <HOST_WIDE_INT>
- : public primitive_int_traits <HOST_WIDE_INT, true> {};
+ struct int_traits <long>
+ : public primitive_int_traits <long, true> {};
+
+ template <>
+ struct int_traits <unsigned long>
+ : public primitive_int_traits <unsigned long, false> {};
+
+#if defined HAVE_LONG_LONG
+ template <>
+ struct int_traits <long long>
+ : public primitive_int_traits <long long, true> {};
template <>
- struct int_traits <unsigned HOST_WIDE_INT>
- : public primitive_int_traits <unsigned HOST_WIDE_INT, false> {};
+ struct int_traits <unsigned long long>
+ : public primitive_int_traits <unsigned long long, false> {};
+#endif
}
namespace wi
@@ -2791,6 +2804,15 @@ wi::mod_round (const T1 &x, const T2 &y, signop sgn, bool *overflow)
return remainder;
}
+/* Return true if X is a multiple of Y. Treat X and Y as having the
+ signedness given by SGN. */
+template <typename T1, typename T2>
+inline bool
+wi::multiple_of_p (const T1 &x, const T2 &y, signop sgn)
+{
+ return wi::mod_trunc (x, y, sgn) == 0;
+}
+
/* Return true if X is a multiple of Y, storing X / Y in *RES if so.
Treat X and Y as having the signedness given by SGN. */
template <typename T1, typename T2>
diff --git a/include/ChangeLog b/include/ChangeLog
index 1655306019c..ff33d291e74 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,7 @@
+2014-05-21 John Marino <gnugcc@marino.st>
+
+ * liberty.h: Use basename function on DragonFly.
+
2014-05-01 Steve Ellcey <sellcey@mips.com>
* include/longlong.h: Use 'defined()' to check __mips16.
diff --git a/include/libiberty.h b/include/libiberty.h
index 78c42eb88f1..7fd07036b75 100644
--- a/include/libiberty.h
+++ b/include/libiberty.h
@@ -106,7 +106,10 @@ extern int countargv (char**);
to find the declaration so provide a fully prototyped one. If it
is 1, we found it so don't provide any declaration at all. */
#if !HAVE_DECL_BASENAME
-#if defined (__GNU_LIBRARY__ ) || defined (__linux__) || defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__) || defined (__CYGWIN__) || defined (__CYGWIN32__) || defined (__MINGW32__) || defined (HAVE_DECL_BASENAME)
+#if defined (__GNU_LIBRARY__ ) || defined (__linux__) \
+ || defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__) \
+ || defined (__CYGWIN__) || defined (__CYGWIN32__) || defined (__MINGW32__) \
+ || defined (__DragonFly__) || defined (HAVE_DECL_BASENAME)
extern char *basename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1);
#else
/* Do not allow basename to be used if there is no prototype seen. We
diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog
index 8a1a8e74a32..adb54d8f5c3 100644
--- a/libbacktrace/ChangeLog
+++ b/libbacktrace/ChangeLog
@@ -1,3 +1,11 @@
+2014-05-08 Ian Lance Taylor <iant@google.com>
+
+ * mmap.c (backtrace_free): If freeing a large aligned block of
+ memory, call munmap rather than holding onto it.
+ (backtrace_vector_grow): When growing a vector, double the number
+ of pages requested. When releasing the old version of a grown
+ vector, pass the correct size to backtrace_free.
+
2014-03-07 Ian Lance Taylor <iant@google.com>
* sort.c (backtrace_qsort): Use middle element as pivot.
diff --git a/libbacktrace/mmap.c b/libbacktrace/mmap.c
index b530e382388..5a9f6299bc0 100644
--- a/libbacktrace/mmap.c
+++ b/libbacktrace/mmap.c
@@ -164,6 +164,26 @@ backtrace_free (struct backtrace_state *state, void *addr, size_t size,
{
int locked;
+ /* If we are freeing a large aligned block, just release it back to
+ the system. This case arises when growing a vector for a large
+ binary with lots of debug info. Calling munmap here may cause us
+ to call mmap again if there is also a large shared library; we
+ just live with that. */
+ if (size >= 16 * 4096)
+ {
+ size_t pagesize;
+
+ pagesize = getpagesize ();
+ if (((uintptr_t) addr & (pagesize - 1)) == 0
+ && (size & (pagesize - 1)) == 0)
+ {
+ /* If munmap fails for some reason, just add the block to
+ the freelist. */
+ if (munmap (addr, size) == 0)
+ return;
+ }
+ }
+
/* If we can acquire the lock, add the new space to the free list.
If we can't acquire the lock, just leak the memory.
__sync_lock_test_and_set returns the old state of the lock, so we
@@ -209,14 +229,18 @@ backtrace_vector_grow (struct backtrace_state *state,size_t size,
alc = pagesize;
}
else
- alc = (alc + pagesize - 1) & ~ (pagesize - 1);
+ {
+ alc *= 2;
+ alc = (alc + pagesize - 1) & ~ (pagesize - 1);
+ }
base = backtrace_alloc (state, alc, error_callback, data);
if (base == NULL)
return NULL;
if (vec->base != NULL)
{
memcpy (base, vec->base, vec->size);
- backtrace_free (state, vec->base, vec->alc, error_callback, data);
+ backtrace_free (state, vec->base, vec->size + vec->alc,
+ error_callback, data);
}
vec->base = base;
vec->alc = alc - vec->size;
diff --git a/libcilkrts/ChangeLog b/libcilkrts/ChangeLog
index bb3913b10d9..3881c82b8e7 100644
--- a/libcilkrts/ChangeLog
+++ b/libcilkrts/ChangeLog
@@ -1,3 +1,7 @@
+2014-05-21 John Marino <gnugcc@marino.st>
+
+ * runtime/os-unix.c (__DragonFly__): New target.
+
2014-04-11 Barry Tannenbaum <barry.m.tannenbaum@intel.com>
PR other/60644
diff --git a/libcilkrts/runtime/os-unix.c b/libcilkrts/runtime/os-unix.c
index c9ddbbc5961..cb582dd7591 100644
--- a/libcilkrts/runtime/os-unix.c
+++ b/libcilkrts/runtime/os-unix.c
@@ -54,6 +54,8 @@
#elif defined __APPLE__
# include <sys/sysctl.h>
// Uses sysconf(_SC_NPROCESSORS_ONLN) in verbose output
+#elif defined __DragonFly__
+// No additional include files
#elif defined __FreeBSD__
// No additional include files
#elif defined __CYGWIN__
@@ -374,7 +376,7 @@ COMMON_SYSDEP int __cilkrts_hardware_cpu_count(void)
assert((unsigned)count == count);
return count;
-#elif defined __FreeBSD__ || defined __CYGWIN__
+#elif defined __FreeBSD__ || defined __CYGWIN__ || defined __DragonFly__
int ncores = sysconf(_SC_NPROCESSORS_ONLN);
return ncores;
@@ -402,6 +404,9 @@ COMMON_SYSDEP void __cilkrts_yield(void)
// On MacOS, call sched_yield to yield quantum. I'm not sure why we
// don't do this on Linux also.
sched_yield();
+#elif defined(__DragonFly__)
+ // On DragonFly BSD, call sched_yield to yield quantum.
+ sched_yield();
#elif defined(__MIC__)
// On MIC, pthread_yield() really trashes things. Arch's measurements
// showed that calling _mm_delay_32() (or doing nothing) was a better
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 20171bc8e9e..8288423941d 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,38 @@
+2014-05-26 Richard Biener <rguenther@suse.de>
+
+ * configure.ac: Remove long long and __int64 type checks,
+ add check for uint64_t and fail if that wasn't found.
+ * include/cpplib.h (cpp_num_part): Use uint64_t.
+ * config.in: Regenerate.
+ * configure: Likewise.
+
+2014-05-21 Marek Polacek <polacek@redhat.com>
+
+ PR c/61212
+ * files.c (find_file_in_dir): Add parens around &&.
+
+2014-05-20 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ PR c++/61038
+ * macro.c (stringify_arg (cpp_reader *, macro_arg *)):
+ Check for user-defined literal strings and user-defined literal chars
+ to escape necessary characters.
+
+2014-05-20 Richard Biener <rguenther@suse.de>
+
+ * configure.ac: Copy gcc logic of detecting a 64bit type.
+ Remove HOST_WIDE_INT define.
+ * include/cpplib.h: typedef cpp_num_part to a 64bit type,
+ similar to how hwint.h does it.
+ * config.in: Regenerate.
+ * configure: Likewise.
+
+2014-05-09 Joey Ye <joey.ye@arm.com>
+
+ * files.c (find_file_in_dir): Always try to shorten for DOS
+ non-system headers.
+ * init.c (ENABLE_CANONICAL_SYSTEM_HEADERS): Default enabled for DOS.
+
2014-05-07 Richard Biener <rguenther@suse.de>
* configure.ac: Always set need_64bit_hwint to yes.
diff --git a/libcpp/config.in b/libcpp/config.in
index 1b0b25555cf..8df00ec2357 100644
--- a/libcpp/config.in
+++ b/libcpp/config.in
@@ -228,10 +228,6 @@
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
-/* Define to the widest efficient host integer type at least as wide as the
- target's size_t type. */
-#undef HOST_WIDE_INT
-
/* Define as const if the declaration of iconv() needs const. */
#undef ICONV_CONST
@@ -332,6 +328,11 @@
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
+/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+#undef _UINT64_T
+
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
@@ -353,6 +354,10 @@
/* Define to `int' if <sys/types.h> does not define. */
#undef ssize_t
+/* Define to the type of an unsigned integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint64_t
+
/* Define to the type of an unsigned integer type wide enough to hold a
pointer, if such a type exists, and if the system does not define it. */
#undef uintptr_t
diff --git a/libcpp/configure b/libcpp/configure
index a9472f37c3a..096ac8b5f21 100755
--- a/libcpp/configure
+++ b/libcpp/configure
@@ -1822,6 +1822,58 @@ $as_echo "$ac_res" >&6; }
} # ac_fn_c_check_type
+# ac_fn_c_find_uintX_t LINENO BITS VAR
+# ------------------------------------
+# Finds an unsigned integer type with width BITS, setting cache variable VAR
+# accordingly.
+ac_fn_c_find_uintX_t ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5
+$as_echo_n "checking for uint$2_t... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \
+ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) -1 >> ($2 - 1) == 1)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ case $ac_type in #(
+ uint$2_t) :
+ eval "$3=yes" ;; #(
+ *) :
+ eval "$3=\$ac_type" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ eval as_val=\$$3
+ if test "x$as_val" = x""no; then :
+
+else
+ break
+fi
+ done
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_find_uintX_t
+
# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
# --------------------------------------------
# Tries to find the compile-time value of EXPR in a program that includes
@@ -5566,6 +5618,23 @@ _ACEOF
fi
+ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t"
+case $ac_cv_c_uint64_t in #(
+ no|yes) ;; #(
+ *)
+
+$as_echo "#define _UINT64_T 1" >>confdefs.h
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint64_t $ac_cv_c_uint64_t
+_ACEOF
+;;
+ esac
+
+if test x"$ac_cv_c_uint64_t" = x"no"; then
+ as_fn_error "uint64_t not found" "$LINENO" 5
+fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5
$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
if test "${ac_cv_struct_tm+set}" = set; then :
@@ -7151,41 +7220,6 @@ $as_echo "#define ENABLE_CANONICAL_SYSTEM_HEADERS 1" >>confdefs.h
fi
-
-case $target in
- aarch64*-*-* | \
- alpha*-*-* | \
- arm*-*-* | \
- x86_64-*-* | \
- ia64-*-* | \
- hppa*64*-*-* | \
- i[34567]86-*-* | x86_64-*-solaris2.1[0-9]* | \
- mips*-*-* | \
- mmix-*-* | \
- powerpc*-*-* | \
- rs6000*-*-* | \
- s390*-*-* | \
- sparc*-*-* | \
- spu-*-* | \
- sh[123456789lbe]*-*-* | sh-*-* | \
- tilegx*-*-* | tilepro*-*-* )
- need_64bit_hwint=yes ;;
- *)
- need_64bit_hwint=yes ;;
-esac
-
-case $need_64bit_hwint:$ac_cv_sizeof_long in
- *:8 | no:*) host_wide_int=long ;;
- *) host_wide_int='long long' ;;
-esac
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define HOST_WIDE_INT $host_wide_int
-_ACEOF
-
-
case $target in
i?86-* | x86_64-*)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
diff --git a/libcpp/configure.ac b/libcpp/configure.ac
index f2bca1fbd52..5f008a4a67f 100644
--- a/libcpp/configure.ac
+++ b/libcpp/configure.ac
@@ -64,6 +64,10 @@ AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
AC_TYPE_UINTPTR_T
AC_CHECK_TYPE(ptrdiff_t, int)
+AC_TYPE_UINT64_T
+if test x"$ac_cv_c_uint64_t" = x"no"; then
+ AC_MSG_ERROR([uint64_t not found])
+fi
AC_STRUCT_TM
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
@@ -180,39 +184,6 @@ if test $enable_canonical_system_headers != no; then
1, [Define to enable system headers canonicalization.])
fi
-m4_changequote(,)
-case $target in
- aarch64*-*-* | \
- alpha*-*-* | \
- arm*-*-* | \
- x86_64-*-* | \
- ia64-*-* | \
- hppa*64*-*-* | \
- i[34567]86-*-* | x86_64-*-solaris2.1[0-9]* | \
- mips*-*-* | \
- mmix-*-* | \
- powerpc*-*-* | \
- rs6000*-*-* | \
- s390*-*-* | \
- sparc*-*-* | \
- spu-*-* | \
- sh[123456789lbe]*-*-* | sh-*-* | \
- tilegx*-*-* | tilepro*-*-* )
- need_64bit_hwint=yes ;;
- *)
- need_64bit_hwint=yes ;;
-esac
-
-case $need_64bit_hwint:$ac_cv_sizeof_long in
- *:8 | no:*) host_wide_int=long ;;
- *) host_wide_int='long long' ;;
-esac
-m4_changequote([,])
-
-AC_DEFINE_UNQUOTED(HOST_WIDE_INT, $host_wide_int,
-[Define to the widest efficient host integer type at least
- as wide as the target's size_t type.])
-
case $target in
i?86-* | x86_64-*)
AC_TRY_COMPILE([], [asm ("pcmpestri %0, %%xmm0, %%xmm1" : : "i"(0))],
diff --git a/libcpp/files.c b/libcpp/files.c
index 7e887785444..91bc9dd0782 100644
--- a/libcpp/files.c
+++ b/libcpp/files.c
@@ -387,8 +387,14 @@ find_file_in_dir (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)
char *copy;
void **pp;
- /* We try to canonicalize system headers. */
- if (CPP_OPTION (pfile, canonical_system_headers) && file->dir->sysp)
+ /* We try to canonicalize system headers. For DOS based file
+ * system, we always try to shorten non-system headers, as DOS
+ * has a tighter constraint on max path length. */
+ if ((CPP_OPTION (pfile, canonical_system_headers) && file->dir->sysp)
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+ || !file->dir->sysp
+#endif
+ )
{
char * canonical_path = maybe_shorter_path (path);
if (canonical_path)
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index a9db7abbd26..a83452b9145 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -819,7 +819,10 @@ extern int cpp_defined (cpp_reader *, const unsigned char *, int);
/* A preprocessing number. Code assumes that any unused high bits of
the double integer are set to zero. */
-typedef unsigned HOST_WIDE_INT cpp_num_part;
+
+/* This type has to be equal to unsigned HOST_WIDE_INT, see
+ gcc/c-family/c-lex.c. */
+typedef uint64_t cpp_num_part;
typedef struct cpp_num cpp_num;
struct cpp_num
{
diff --git a/libcpp/init.c b/libcpp/init.c
index f10413ab3eb..b80951544d4 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -27,8 +27,12 @@ along with this program; see the file COPYING3. If not see
#include "filenames.h"
#ifndef ENABLE_CANONICAL_SYSTEM_HEADERS
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+#define ENABLE_CANONICAL_SYSTEM_HEADERS 1
+#else
#define ENABLE_CANONICAL_SYSTEM_HEADERS 0
#endif
+#endif
static void init_library (void);
static void mark_named_operators (cpp_reader *, int);
diff --git a/libcpp/macro.c b/libcpp/macro.c
index 11e50f4849c..c3db9a277a3 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -494,6 +494,9 @@ stringify_arg (cpp_reader *pfile, macro_arg *arg)
|| token->type == CPP_STRING16 || token->type == CPP_CHAR16
|| token->type == CPP_UTF8STRING);
+ escape_it = escape_it || cpp_userdef_string_p (token->type)
+ || cpp_userdef_char_p (token->type);
+
/* Room for each char being written in octal, initial space and
final quote and NUL. */
len = cpp_token_len (token);
diff --git a/libffi/ChangeLog b/libffi/ChangeLog
index 75bfd8036a0..424c9a50e03 100644
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,3 +1,16 @@
+2014-05-20 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * testsuite/lib/libffi.exp (load_gcc_lib): Register loaded libs.
+
+2014-05-13 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ Fix current cygwin-64 build problems.
+ * src/java_raw_api.c: Remove if !defined(FFI_NO_RAW_API).
+ * src/x86/ffi.c: Add if defined(__CYGWIN__).
+ * src/x86/win64.S (ffi_closure_win64, ffi_call_win64): Added
+ handling for FFI_TYPE_UINT64, FFI_TYPE_POINTER and FFI_TYPE_INT.
+ Added SEH information. Fixed formatting.
+
2014-04-22 Jakub Jelinek <jakub@redhat.com>
PR other/43620
diff --git a/libffi/src/java_raw_api.c b/libffi/src/java_raw_api.c
index 522c8bfd67e..d8e79ea1d45 100644
--- a/libffi/src/java_raw_api.c
+++ b/libffi/src/java_raw_api.c
@@ -39,7 +39,7 @@
#include <ffi_common.h>
#include <stdlib.h>
-#if !defined(NO_JAVA_RAW_API) && !defined(FFI_NO_RAW_API)
+#if !defined(NO_JAVA_RAW_API)
size_t
ffi_java_raw_size (ffi_cif *cif)
@@ -353,4 +353,4 @@ ffi_prep_java_raw_closure (ffi_java_raw_closure* cl,
#endif /* FFI_CLOSURES */
#endif /* !FFI_NATIVE_RAW_API */
-#endif /* !FFI_NO_RAW_API */
+#endif /* !NO_JAVA_RAW_API */
diff --git a/libffi/src/x86/ffi.c b/libffi/src/x86/ffi.c
index 611e2219716..6338de2a0f2 100644
--- a/libffi/src/x86/ffi.c
+++ b/libffi/src/x86/ffi.c
@@ -28,7 +28,7 @@
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
-#if !defined(__x86_64__) || defined(_WIN64)
+#if !defined(__x86_64__) || defined(_WIN64) || defined(__CYGWIN__)
#ifdef _WIN64
#include <windows.h>
diff --git a/libffi/src/x86/win64.S b/libffi/src/x86/win64.S
index 1394cf177b6..687f97c451d 100644
--- a/libffi/src/x86/win64.S
+++ b/libffi/src/x86/win64.S
@@ -1,8 +1,8 @@
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
-
-/* Constants for ffi_call_win64 */
+
+/* Constants for ffi_call_win64 */
#define STACK 0
#define PREP_ARGS_FN 32
#define ECIF 40
@@ -12,8 +12,8 @@
#define FN 72
/* ffi_call_win64 (void (*prep_args_fn)(char *, extended_cif *),
- extended_cif *ecif, unsigned bytes, unsigned flags,
- unsigned *rvalue, void (*fn)());
+ extended_cif *ecif, unsigned bytes, unsigned flags,
+ unsigned *rvalue, void (*fn)());
*/
#ifdef _MSC_VER
@@ -31,11 +31,11 @@ _TEXT SEGMENT
;;;
;;; It must move the parameters passed in registers to their stack location,
;;; call ffi_closure_win64_inner for the actual work, then return the result.
-;;;
+;;;
ffi_closure_win64 PROC FRAME
;; copy register arguments onto stack
test r11, 1
- jne first_is_float
+ jne first_is_float
mov QWORD PTR [rsp+8], rcx
jmp second
first_is_float:
@@ -43,7 +43,7 @@ first_is_float:
second:
test r11, 2
- jne second_is_float
+ jne second_is_float
mov QWORD PTR [rsp+16], rdx
jmp third
second_is_float:
@@ -51,7 +51,7 @@ second_is_float:
third:
test r11, 4
- jne third_is_float
+ jne third_is_float
mov QWORD PTR [rsp+24], r8
jmp fourth
third_is_float:
@@ -59,16 +59,16 @@ third_is_float:
fourth:
test r11, 8
- jne fourth_is_float
+ jne fourth_is_float
mov QWORD PTR [rsp+32], r9
jmp done
fourth_is_float:
movlpd QWORD PTR [rsp+32], xmm3
done:
- .ALLOCSTACK 40
+ .ALLOCSTACK 40
sub rsp, 40
- .ENDPROLOG
+ .ENDPROLOG
mov rcx, rax ; context is first parameter
mov rdx, rsp ; stack is second parameter
add rdx, 48 ; point to start of arguments
@@ -76,23 +76,23 @@ done:
call rax ; call the real closure function
add rsp, 40
movd xmm0, rax ; If the closure returned a float,
- ; ffi_closure_win64_inner wrote it to rax
+ ; ffi_closure_win64_inner wrote it to rax
ret 0
ffi_closure_win64 ENDP
ffi_call_win64 PROC FRAME
- ;; copy registers onto stack
+ ;; copy registers onto stack
mov QWORD PTR [rsp+32], r9
mov QWORD PTR [rsp+24], r8
mov QWORD PTR [rsp+16], rdx
mov QWORD PTR [rsp+8], rcx
- .PUSHREG rbp
+ .PUSHREG rbp
push rbp
- .ALLOCSTACK 48
+ .ALLOCSTACK 48
sub rsp, 48 ; 00000030H
- .SETFRAME rbp, 32
+ .SETFRAME rbp, 32
lea rbp, QWORD PTR [rsp+32]
- .ENDPROLOG
+ .ENDPROLOG
mov eax, DWORD PTR CIF_BYTES[rbp]
add rax, 15
@@ -209,20 +209,45 @@ ret_float$:
ret_double$:
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_DOUBLE
- jne SHORT ret_sint64$
+ jne SHORT ret_uint64$
mov rax, QWORD PTR RVALUE[rbp]
movlpd QWORD PTR [rax], xmm0
jmp SHORT ret_void$
+ret_uint64$:
+ cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT64
+ jne SHORT ret_sint64$
+
+ mov rcx, QWORD PTR RVALUE[rbp]
+ mov QWORD PTR [rcx], rax
+ jmp SHORT ret_void$
+
ret_sint64$:
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64
- jne ret_void$
+ jne SHORT ret_pointer$
mov rcx, QWORD PTR RVALUE[rbp]
mov QWORD PTR [rcx], rax
jmp SHORT ret_void$
-
+
+ret_pointer$:
+ cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_POINTER
+ jne SHORT ret_int$
+
+ mov rcx, QWORD PTR RVALUE[rbp]
+ mov QWORD PTR [rcx], rax
+ jmp SHORT ret_void$
+
+ret_int$:
+ cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_INT
+ jne SHORT ret_void$
+
+ mov rcx, QWORD PTR RVALUE[rbp]
+ cdqe
+ mov QWORD PTR [rcx], rax
+ jmp SHORT ret_void$
+
ret_void$:
xor rax, rax
@@ -252,13 +277,14 @@ END
#
# It must move the parameters passed in registers to their stack location,
# call ffi_closure_win64_inner for the actual work, then return the result.
-#
+#
.balign 16
- .globl SYMBOL_NAME(ffi_closure_win64)
+ .globl SYMBOL_NAME(ffi_closure_win64)
+ .seh_proc SYMBOL_NAME(ffi_closure_win64)
SYMBOL_NAME(ffi_closure_win64):
# copy register arguments onto stack
test $1,%r11
- jne .Lfirst_is_float
+ jne .Lfirst_is_float
mov %rcx, 8(%rsp)
jmp .Lsecond
.Lfirst_is_float:
@@ -266,7 +292,7 @@ SYMBOL_NAME(ffi_closure_win64):
.Lsecond:
test $2, %r11
- jne .Lsecond_is_float
+ jne .Lsecond_is_float
mov %rdx, 16(%rsp)
jmp .Lthird
.Lsecond_is_float:
@@ -274,7 +300,7 @@ SYMBOL_NAME(ffi_closure_win64):
.Lthird:
test $4, %r11
- jne .Lthird_is_float
+ jne .Lthird_is_float
mov %r8,24(%rsp)
jmp .Lfourth
.Lthird_is_float:
@@ -282,16 +308,16 @@ SYMBOL_NAME(ffi_closure_win64):
.Lfourth:
test $8, %r11
- jne .Lfourth_is_float
+ jne .Lfourth_is_float
mov %r9, 32(%rsp)
jmp .Ldone
.Lfourth_is_float:
movlpd %xmm3, 32(%rsp)
.Ldone:
-#.ALLOCSTACK 40
+ .seh_stackalloc 40
sub $40, %rsp
-#.ENDPROLOG
+ .seh_endprologue
mov %rax, %rcx # context is first parameter
mov %rsp, %rdx # stack is second parameter
add $48, %rdx # point to start of arguments
@@ -299,25 +325,26 @@ SYMBOL_NAME(ffi_closure_win64):
callq *%rax # call the real closure function
add $40, %rsp
movq %rax, %xmm0 # If the closure returned a float,
- # ffi_closure_win64_inner wrote it to rax
+ # ffi_closure_win64_inner wrote it to rax
retq
-.ffi_closure_win64_end:
+ .seh_endproc
.balign 16
- .globl SYMBOL_NAME(ffi_call_win64)
+ .globl SYMBOL_NAME(ffi_call_win64)
+ .seh_proc SYMBOL_NAME(ffi_call_win64)
SYMBOL_NAME(ffi_call_win64):
- # copy registers onto stack
+ # copy registers onto stack
mov %r9,32(%rsp)
mov %r8,24(%rsp)
mov %rdx,16(%rsp)
mov %rcx,8(%rsp)
- #.PUSHREG rbp
+ .seh_pushreg rbp
push %rbp
- #.ALLOCSTACK 48
+ .seh_stackalloc 48
sub $48,%rsp
- #.SETFRAME rbp, 32
+ .seh_setframe rbp, 32
lea 32(%rsp),%rbp
- #.ENDPROLOG
+ .seh_endprologue
mov CIF_BYTES(%rbp),%eax
add $15, %rax
@@ -366,15 +393,15 @@ Lch_done:
.Lret_struct2b:
cmpl $FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp)
jne .Lret_struct1b
-
+
mov RVALUE(%rbp), %rcx
mov %ax, (%rcx)
jmp .Lret_void
-
+
.Lret_struct1b:
cmpl $FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp)
jne .Lret_uint8
-
+
mov RVALUE(%rbp), %rcx
mov %al, (%rcx)
jmp .Lret_void
@@ -382,45 +409,45 @@ Lch_done:
.Lret_uint8:
cmpl $FFI_TYPE_UINT8, CIF_FLAGS(%rbp)
jne .Lret_sint8
-
- mov RVALUE(%rbp), %rcx
- movzbq %al, %rax
+
+ mov RVALUE(%rbp), %rcx
+ movzbq %al, %rax
movq %rax, (%rcx)
jmp .Lret_void
.Lret_sint8:
cmpl $FFI_TYPE_SINT8, CIF_FLAGS(%rbp)
jne .Lret_uint16
-
- mov RVALUE(%rbp), %rcx
- movsbq %al, %rax
+
+ mov RVALUE(%rbp), %rcx
+ movsbq %al, %rax
movq %rax, (%rcx)
jmp .Lret_void
.Lret_uint16:
cmpl $FFI_TYPE_UINT16, CIF_FLAGS(%rbp)
jne .Lret_sint16
-
- mov RVALUE(%rbp), %rcx
- movzwq %ax, %rax
+
+ mov RVALUE(%rbp), %rcx
+ movzwq %ax, %rax
movq %rax, (%rcx)
jmp .Lret_void
.Lret_sint16:
cmpl $FFI_TYPE_SINT16, CIF_FLAGS(%rbp)
jne .Lret_uint32
-
- mov RVALUE(%rbp), %rcx
- movswq %ax, %rax
+
+ mov RVALUE(%rbp), %rcx
+ movswq %ax, %rax
movq %rax, (%rcx)
jmp .Lret_void
.Lret_uint32:
cmpl $FFI_TYPE_UINT32, CIF_FLAGS(%rbp)
jne .Lret_sint32
-
- mov RVALUE(%rbp), %rcx
- movl %eax, %eax
+
+ mov RVALUE(%rbp), %rcx
+ movl %eax, %eax
movq %rax, (%rcx)
jmp .Lret_void
@@ -443,26 +470,51 @@ Lch_done:
.Lret_double:
cmpl $FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp)
- jne .Lret_sint64
+ jne .Lret_uint64
mov RVALUE(%rbp), %rax
movlpd %xmm0, (%rax)
jmp .Lret_void
+.Lret_uint64:
+ cmpl $FFI_TYPE_UINT64, CIF_FLAGS(%rbp)
+ jne .Lret_sint64
+
+ mov RVALUE(%rbp), %rcx
+ mov %rax, (%rcx)
+ jmp .Lret_void
+
.Lret_sint64:
cmpl $FFI_TYPE_SINT64, CIF_FLAGS(%rbp)
- jne .Lret_void
+ jne .Lret_pointer
+
+ mov RVALUE(%rbp), %rcx
+ mov %rax, (%rcx)
+ jmp .Lret_void
+
+.Lret_pointer:
+ cmpl $FFI_TYPE_POINTER, CIF_FLAGS(%rbp)
+ jne .Lret_int
mov RVALUE(%rbp), %rcx
mov %rax, (%rcx)
jmp .Lret_void
-
+
+.Lret_int:
+ cmpl $FFI_TYPE_INT, CIF_FLAGS(%rbp)
+ jne .Lret_void
+
+ mov RVALUE(%rbp), %rcx
+ cltq
+ movq %rax, (%rcx)
+ jmp .Lret_void
+
.Lret_void:
xor %rax, %rax
lea 16(%rbp), %rsp
pop %rbp
retq
-.ffi_call_win64_end:
+ .seh_endproc
#endif /* !_MSC_VER */
diff --git a/libffi/testsuite/lib/libffi.exp b/libffi/testsuite/lib/libffi.exp
index 3c61baa1dff..25efce2de4d 100644
--- a/libffi/testsuite/lib/libffi.exp
+++ b/libffi/testsuite/lib/libffi.exp
@@ -15,8 +15,10 @@
# <http://www.gnu.org/licenses/>.
proc load_gcc_lib { filename } {
- global srcdir
+ global srcdir loaded_libs
+
load_file $srcdir/../../gcc/testsuite/lib/$filename
+ set loaded_libs($filename) ""
}
load_lib dg.exp
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index e562c30235d..04c8f73706e 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,42 @@
+2014-05-22 Nick Clifton <nickc@redhat.com>
+
+ * config/msp430/t-msp430 (HOST_LIBGCC2_CFLAGS): Add
+ -mhwmult=none.
+
+2014-05-22 Teresa Johnson <tejohnson@google.com>
+
+ * libgcov-driver.c (gcov_error): Move declaration before gcov-io.c
+ include.
+
+2014-05-20 John Marino <gnugcc@marino.st>
+
+ * config.host (*-*-dragonfly*): New target.
+ * crtstuff.c: Make dl_iterate_support generic on *bsd.
+ * enable-execute-stack-mprotect.c: Always mprotect on FreeBSD.
+ * unwind-dw2-fde-dip.c: Add dl_iterate_phr support for DragonFly.
+ * config/i386/dragonfly-unwind.h: New.
+
+2014-05-21 Maciej W. Rozycki <macro@codesourcery.com>
+
+ PR libgcc/60166
+ * config/arm/sfp-machine.h (_FP_NANFRAC_H, _FP_NANFRAC_S)
+ (_FP_NANFRAC_D, _FP_NANSIGN_Q): Set the quiet bit.
+
+2014-05-13 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * unwind-seh.c (_Unwind_Backtrace): Uncommented, finished
+ implementation.
+
+2014-05-12 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/arm/bpabi-lib.h (License): Add GCC Runtime Library Exception.
+
+2014-05-08 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR libgcc/61097
+ * config/t-slibgcc-sld: Only build and install libgcc-unwind.map
+ if --enable-shared.
+
2014-04-30 Bernd Edlinger <bernd.edlinger@hotmail.de>
Work around for current cygwin32 build problems.
diff --git a/libgcc/config.host b/libgcc/config.host
index f4a74287293..5f13a9f18bf 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -207,6 +207,11 @@ case ${host} in
tmake_file="$tmake_file t-darwin ${cpu_type}/t-darwin t-libgcc-pic t-slibgcc-darwin"
extra_parts="crt3.o crttms.o crttme.o"
;;
+*-*-dragonfly*)
+ tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic t-eh-dw2-dip"
+ tmake_file="$tmake_file t-slibgcc t-slibgcc-gld t-slibgcc-elf-ver"
+ extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o"
+ ;;
*-*-freebsd*)
# This is the generic ELF configuration of FreeBSD. Later
# machine-specific sections may refine and add to this
@@ -302,7 +307,8 @@ case ${host} in
esac
case ${host} in
-*-*-darwin* | *-*-freebsd* | *-*-netbsd* | *-*-openbsd* | *-*-solaris2*)
+*-*-darwin* | *-*-dragonfly* | *-*-freebsd* | *-*-netbsd* | *-*-openbsd* | \
+ *-*-solaris2*)
enable_execute_stack=enable-execute-stack-mprotect.c
;;
i[34567]86-*-mingw* | x86_64-*-mingw*)
@@ -545,6 +551,14 @@ i[34567]86-*-elf*)
x86_64-*-elf*)
tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
;;
+i[34567]86-*-dragonfly*)
+ tmake_file="${tmake_file} i386/t-dragonfly i386/t-crtstuff"
+ md_unwind_header=i386/dragonfly-unwind.h
+ ;;
+x86_64-*-dragonfly*)
+ tmake_file="${tmake_file} i386/t-dragonfly i386/t-crtstuff"
+ md_unwind_header=i386/dragonfly-unwind.h
+ ;;
i[34567]86-*-freebsd*)
tmake_file="${tmake_file} i386/t-freebsd i386/t-crtstuff"
;;
@@ -1262,6 +1276,7 @@ i[34567]86-*-darwin* | x86_64-*-darwin* | \
i[34567]86-*-solaris2* | x86_64-*-solaris2.1[0-9]* | \
i[34567]86-*-cygwin* | x86_64-*-cygwin* | \
i[34567]86-*-mingw* | x86_64-*-mingw* | \
+ i[34567]86-*-dragonfly* | x86_64-*-dragonfly* | \
i[34567]86-*-freebsd* | x86_64-*-freebsd* | \
i[34567]86-*-openbsd* | x86_64-*-openbsd*)
tmake_file="${tmake_file} t-softfp-tf"
diff --git a/libgcc/config/arm/bpabi-lib.h b/libgcc/config/arm/bpabi-lib.h
index 193cc5604ad..d6e77969001 100644
--- a/libgcc/config/arm/bpabi-lib.h
+++ b/libgcc/config/arm/bpabi-lib.h
@@ -14,6 +14,10 @@
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
diff --git a/libgcc/config/arm/sfp-machine.h b/libgcc/config/arm/sfp-machine.h
index 4f2b15d7e55..b7b5171e702 100644
--- a/libgcc/config/arm/sfp-machine.h
+++ b/libgcc/config/arm/sfp-machine.h
@@ -21,10 +21,10 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
/* According to RTABI, QNAN is only with the most significant bit of the
significand set, and all other significand bits zero. */
-#define _FP_NANFRAC_H 0
-#define _FP_NANFRAC_S 0
-#define _FP_NANFRAC_D 0, 0
-#define _FP_NANFRAC_Q 0, 0, 0, 0
+#define _FP_NANFRAC_H _FP_QNANBIT_H
+#define _FP_NANFRAC_S _FP_QNANBIT_S
+#define _FP_NANFRAC_D _FP_QNANBIT_D, 0
+#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0, 0, 0
#define _FP_NANSIGN_H 0
#define _FP_NANSIGN_S 0
#define _FP_NANSIGN_D 0
diff --git a/libgcc/config/i386/dragonfly-unwind.h b/libgcc/config/i386/dragonfly-unwind.h
new file mode 100644
index 00000000000..cfea5e313e7
--- /dev/null
+++ b/libgcc/config/i386/dragonfly-unwind.h
@@ -0,0 +1,180 @@
+/* DWARF2 EH unwinding support for DragonFly BSD: AMD x86-64 and x86.
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ Contributed by John Marino <gnugcc@marino.st>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <signal.h>
+#include <sys/ucontext.h>
+#include <machine/sigframe.h>
+
+
+#define REG_NAME(reg) sf_uc.uc_mcontext.mc_## reg
+
+#ifdef __x86_64__
+#define MD_FALLBACK_FRAME_STATE_FOR x86_64_dragonfly_fallback_frame_state
+
+
+static void
+x86_64_sigtramp_range (unsigned char **start, unsigned char **end)
+{
+ unsigned long ps_strings;
+ int mib[2];
+ size_t len;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PS_STRINGS;
+ len = sizeof (ps_strings);
+ sysctl (mib, 2, &ps_strings, &len, NULL, 0);
+
+ *start = (unsigned char *)ps_strings - 32;
+ *end = (unsigned char *)ps_strings;
+}
+
+
+static _Unwind_Reason_Code
+x86_64_dragonfly_fallback_frame_state
+(struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+ unsigned char *pc = context->ra;
+ unsigned char *sigtramp_start, *sigtramp_end;
+ struct sigframe *sf;
+ long new_cfa;
+
+ x86_64_sigtramp_range(&sigtramp_start, &sigtramp_end);
+ if (pc >= sigtramp_end || pc < sigtramp_start)
+ return _URC_END_OF_STACK;
+
+ sf = (struct sigframe *) context->cfa;
+ new_cfa = sf->REG_NAME(rsp);
+ fs->regs.cfa_how = CFA_REG_OFFSET;
+ /* Register 7 is rsp */
+ fs->regs.cfa_reg = 7;
+ fs->regs.cfa_offset = new_cfa - (long) context->cfa;
+
+ /* The SVR4 register numbering macros aren't usable in libgcc. */
+ fs->regs.reg[0].how = REG_SAVED_OFFSET;
+ fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(rax) - new_cfa;
+ fs->regs.reg[1].how = REG_SAVED_OFFSET;
+ fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(rdx) - new_cfa;
+ fs->regs.reg[2].how = REG_SAVED_OFFSET;
+ fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(rcx) - new_cfa;
+ fs->regs.reg[3].how = REG_SAVED_OFFSET;
+ fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(rbx) - new_cfa;
+ fs->regs.reg[4].how = REG_SAVED_OFFSET;
+ fs->regs.reg[4].loc.offset = (long)&sf->REG_NAME(rsi) - new_cfa;
+ fs->regs.reg[5].how = REG_SAVED_OFFSET;
+ fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(rdi) - new_cfa;
+ fs->regs.reg[6].how = REG_SAVED_OFFSET;
+ fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(rbp) - new_cfa;
+ fs->regs.reg[8].how = REG_SAVED_OFFSET;
+ fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(r8) - new_cfa;
+ fs->regs.reg[9].how = REG_SAVED_OFFSET;
+ fs->regs.reg[9].loc.offset = (long)&sf->REG_NAME(r9) - new_cfa;
+ fs->regs.reg[10].how = REG_SAVED_OFFSET;
+ fs->regs.reg[10].loc.offset = (long)&sf->REG_NAME(r10) - new_cfa;
+ fs->regs.reg[11].how = REG_SAVED_OFFSET;
+ fs->regs.reg[11].loc.offset = (long)&sf->REG_NAME(r11) - new_cfa;
+ fs->regs.reg[12].how = REG_SAVED_OFFSET;
+ fs->regs.reg[12].loc.offset = (long)&sf->REG_NAME(r12) - new_cfa;
+ fs->regs.reg[13].how = REG_SAVED_OFFSET;
+ fs->regs.reg[13].loc.offset = (long)&sf->REG_NAME(r13) - new_cfa;
+ fs->regs.reg[14].how = REG_SAVED_OFFSET;
+ fs->regs.reg[14].loc.offset = (long)&sf->REG_NAME(r14) - new_cfa;
+ fs->regs.reg[15].how = REG_SAVED_OFFSET;
+ fs->regs.reg[15].loc.offset = (long)&sf->REG_NAME(r15) - new_cfa;
+ fs->regs.reg[16].how = REG_SAVED_OFFSET;
+ fs->regs.reg[16].loc.offset = (long)&sf->REG_NAME(rip) - new_cfa;
+ fs->retaddr_column = 16;
+ fs->signal_frame = 1;
+ return _URC_NO_REASON;
+}
+
+#else /* Next section is for i386 */
+
+#define MD_FALLBACK_FRAME_STATE_FOR x86_dragonfly_fallback_frame_state
+
+
+static void
+x86_sigtramp_range (unsigned char **start, unsigned char **end)
+{
+ unsigned long ps_strings;
+ int mib[2];
+ size_t len;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PS_STRINGS;
+ len = sizeof (ps_strings);
+ sysctl (mib, 2, &ps_strings, &len, NULL, 0);
+
+ *start = (unsigned char *)ps_strings - 128;
+ *end = (unsigned char *)ps_strings;
+}
+
+
+static _Unwind_Reason_Code
+x86_dragonfly_fallback_frame_state
+(struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+ unsigned char *pc = context->ra;
+ unsigned char *sigtramp_start, *sigtramp_end;
+ struct sigframe *sf;
+ long new_cfa;
+
+ x86_sigtramp_range(&sigtramp_start, &sigtramp_end);
+
+ if (pc >= sigtramp_end || pc < sigtramp_start)
+ return _URC_END_OF_STACK;
+
+ sf = (struct sigframe *) context->cfa;
+ new_cfa = sf->REG_NAME(esp);
+ fs->regs.cfa_how = CFA_REG_OFFSET;
+ fs->regs.cfa_reg = 4;
+ fs->regs.cfa_offset = new_cfa - (long) context->cfa;
+
+ /* The SVR4 register numbering macros aren't usable in libgcc. */
+ fs->regs.reg[0].how = REG_SAVED_OFFSET;
+ fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(eax) - new_cfa;
+ fs->regs.reg[3].how = REG_SAVED_OFFSET;
+ fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(ebx) - new_cfa;
+ fs->regs.reg[1].how = REG_SAVED_OFFSET;
+ fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(ecx) - new_cfa;
+ fs->regs.reg[2].how = REG_SAVED_OFFSET;
+ fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(edx) - new_cfa;
+ fs->regs.reg[6].how = REG_SAVED_OFFSET;
+ fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(esi) - new_cfa;
+ fs->regs.reg[7].how = REG_SAVED_OFFSET;
+ fs->regs.reg[7].loc.offset = (long)&sf->REG_NAME(edi) - new_cfa;
+ fs->regs.reg[5].how = REG_SAVED_OFFSET;
+ fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(ebp) - new_cfa;
+ fs->regs.reg[8].how = REG_SAVED_OFFSET;
+ fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(eip) - new_cfa;
+ fs->retaddr_column = 8;
+ fs->signal_frame = 1;
+ return _URC_NO_REASON;
+}
+#endif /* ifdef __x86_64__ */
diff --git a/libgcc/config/msp430/t-msp430 b/libgcc/config/msp430/t-msp430
index 7a7b68007a5..f82c123b555 100644
--- a/libgcc/config/msp430/t-msp430
+++ b/libgcc/config/msp430/t-msp430
@@ -42,7 +42,7 @@ LIB2ADD = \
$(srcdir)/config/msp430/floathisf.c \
$(srcdir)/config/msp430/cmpd.c
-HOST_LIBGCC2_CFLAGS += -Os -ffunction-sections -fdata-sections
+HOST_LIBGCC2_CFLAGS += -Os -ffunction-sections -fdata-sections -mhwmult=none
# Local Variables:
# mode: Makefile
diff --git a/libgcc/config/t-slibgcc-sld b/libgcc/config/t-slibgcc-sld
index ec6e5db0a3b..0b9539114e4 100644
--- a/libgcc/config/t-slibgcc-sld
+++ b/libgcc/config/t-slibgcc-sld
@@ -4,6 +4,8 @@
SHLIB_LDFLAGS = -Wl,-h,$(SHLIB_SONAME) -Wl,-z,text -Wl,-z,defs \
-Wl,-M,$(SHLIB_MAP)
+ifeq ($(enable_shared),yes)
+
# Linker mapfile to enforce direct binding to libgcc_s unwinder
# (PR target/59788).
libgcc-unwind.map: libgcc-std.ver
@@ -26,3 +28,5 @@ install-libgcc-unwind-map: libgcc-unwind.map
$(INSTALL_DATA) $< $(DESTDIR)$(slibdir)
install: install-libgcc-unwind-map
+
+endif
diff --git a/libgcc/crtstuff.c b/libgcc/crtstuff.c
index 12bed4b351d..2c56af32d60 100644
--- a/libgcc/crtstuff.c
+++ b/libgcc/crtstuff.c
@@ -79,11 +79,16 @@ call_ ## FUNC (void) \
}
#endif
+#if defined(TARGET_DL_ITERATE_PHDR) && \
+ (defined(__DragonFly__) || defined(__FreeBSD__))
+#define BSD_DL_ITERATE_PHDR_AVAILABLE
+#endif
+
#if defined(OBJECT_FORMAT_ELF) \
&& !defined(OBJECT_FORMAT_FLAT) \
&& defined(HAVE_LD_EH_FRAME_HDR) \
&& !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
- && defined(__FreeBSD__) && __FreeBSD__ >= 7
+ && defined(BSD_DL_ITERATE_PHDR_AVAILABLE)
#include <link.h>
# define USE_PT_GNU_EH_FRAME
#endif
diff --git a/libgcc/enable-execute-stack-mprotect.c b/libgcc/enable-execute-stack-mprotect.c
index 096abea2192..e3fb3b60afc 100644
--- a/libgcc/enable-execute-stack-mprotect.c
+++ b/libgcc/enable-execute-stack-mprotect.c
@@ -33,20 +33,7 @@ static int need_enable_exec_stack;
static void check_enabling (void) __attribute__ ((unused));
extern void __enable_execute_stack (void *);
-#if defined __FreeBSD__
-#include <sys/sysctl.h>
-
-static void __attribute__ ((constructor))
-check_enabling (void)
-{
- int prot = 0;
- size_t len = sizeof (prot);
-
- sysctlbyname ("kern.stackprot", &prot, &len, NULL, 0);
- if (prot != STACK_PROT_RWX)
- need_enable_exec_stack = 1;
-}
-#elif defined __sun__ && defined __svr4__
+#if defined __sun__ && defined __svr4__
static void __attribute__ ((constructor))
check_enabling (void)
{
diff --git a/libgcc/libgcov-driver.c b/libgcc/libgcov-driver.c
index f8abdb1e8ac..ef0505e617e 100644
--- a/libgcc/libgcov-driver.c
+++ b/libgcc/libgcov-driver.c
@@ -42,6 +42,10 @@ void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
#endif
#ifdef L_gcov
+
+/* A utility function for outputing errors. */
+static int gcov_error (const char *, ...);
+
#include "gcov-io.c"
/* The following functions can be called from outside of this file. */
@@ -108,9 +112,6 @@ reset_gcov_dump_complete (void)
gcov_dump_complete = 0;
}
-/* A utility function for outputing errors. */
-static int gcov_error (const char *, ...);
-
static struct gcov_fn_buffer *
free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
unsigned limit)
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
index d6c05216587..b7b9f9192f1 100644
--- a/libgcc/unwind-dw2-fde-dip.c
+++ b/libgcc/unwind-dw2-fde-dip.c
@@ -58,7 +58,8 @@
#endif
#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
- && defined(__FreeBSD__) && __FreeBSD__ >= 7
+ && defined(TARGET_DL_ITERATE_PHDR) \
+ && (defined(__DragonFly__) || defined(__FreeBSD__))
# define ElfW __ElfN
# define USE_PT_GNU_EH_FRAME
#endif
diff --git a/libgcc/unwind-seh.c b/libgcc/unwind-seh.c
index b4a3ca1e34b..c8187b37a16 100644
--- a/libgcc/unwind-seh.c
+++ b/libgcc/unwind-seh.c
@@ -431,43 +431,40 @@ _Unwind_DeleteException (struct _Unwind_Exception *exc)
/* Perform stack backtrace through unwind data. */
_Unwind_Reason_Code
-_Unwind_Backtrace(_Unwind_Trace_Fn trace ATTRIBUTE_UNUSED,
- void *trace_argument ATTRIBUTE_UNUSED)
+_Unwind_Backtrace(_Unwind_Trace_Fn trace,
+ void *trace_argument)
{
-#if 0
UNWIND_HISTORY_TABLE ms_history;
CONTEXT ms_context;
struct _Unwind_Context gcc_context;
+ DISPATCHER_CONTEXT disp_context;
memset (&ms_history, 0, sizeof(ms_history));
memset (&gcc_context, 0, sizeof(gcc_context));
+ memset (&disp_context, 0, sizeof(disp_context));
ms_context.ContextFlags = CONTEXT_ALL;
RtlCaptureContext (&ms_context);
- gcc_context.disp.ContextRecord = &ms_context;
- gcc_context.disp.HistoryTable = &ms_history;
+ gcc_context.disp = &disp_context;
+ gcc_context.disp->ContextRecord = &ms_context;
+ gcc_context.disp->HistoryTable = &ms_history;
while (1)
{
- gcc_context.disp.ControlPc = ms_context.Rip;
- gcc_context.disp.FunctionEntry
- = RtlLookupFunctionEntry (ms_context.Rip, &gcc_context.disp.ImageBase,
+ gcc_context.disp->ControlPc = ms_context.Rip;
+ gcc_context.disp->FunctionEntry
+ = RtlLookupFunctionEntry (ms_context.Rip, &gcc_context.disp->ImageBase,
&ms_history);
- if (gcc_context.disp.FunctionEntry)
- {
- gcc_context.disp.LanguageHandler
- = RtlVirtualUnwind (0, gcc_context.disp.ImageBase, ms_context.Rip,
- gcc_context.disp.FunctionEntry, &ms_context,
- &gcc_context.disp.HandlerData,
- &gcc_context.disp.EstablisherFrame, NULL);
- }
- else
- {
- ms_context.Rip = *(ULONG_PTR *)ms_context.Rsp;
- ms_context.Rsp += 8;
- }
+ if (!gcc_context.disp->FunctionEntry)
+ return _URC_END_OF_STACK;
+
+ gcc_context.disp->LanguageHandler
+ = RtlVirtualUnwind (0, gcc_context.disp->ImageBase, ms_context.Rip,
+ gcc_context.disp->FunctionEntry, &ms_context,
+ &gcc_context.disp->HandlerData,
+ &gcc_context.disp->EstablisherFrame, NULL);
/* Call trace function. */
if (trace (&gcc_context, trace_argument) != _URC_NO_REASON)
@@ -477,8 +474,5 @@ _Unwind_Backtrace(_Unwind_Trace_Fn trace ATTRIBUTE_UNUSED,
if (ms_context.Rip == 0)
return _URC_END_OF_STACK;
}
-#else
- return _URC_END_OF_STACK;
-#endif
}
#endif /* __SEH__ && !defined (__USING_SJLJ_EXCEPTIONS__) */
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 003f7ca58bf..5f9ddaf668f 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,132 @@
+2014-05-27 Uros Bizjak <ubizjak@gmail.com>
+
+ * intrinsics/getcwd.c: Include stdlib.h.
+
+2014-05-26 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * libgfortran.h (xrealloc): New prototype.
+ * runtime/memory.c (xrealloc): New function.
+ * io/fbuf.c (fbuf_alloc): Use xrealloc.
+ * io/list_read.c (push_char_default): Likewise.
+ (push_char4): Likewise.
+
+2014-05-26 Janne Blomqvist <jb@gcc.gnu.org>
+
+ PR libfortran/61310
+ * intrinsics/ctime.c (strctime): Rename to gf_ctime, use snprintf
+ instead of strftime.
+ (fdate): Use gf_ctime.
+ (fdate_sub): Likewise.
+ (ctime): Likewise.
+ (ctime_sub): Likewise.
+
+2014-05-26 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR libgfortran/55117
+ * io/list_read.c (extended_look_ahead): New helper function to
+ scan the namelist name and look for matches with the new '+'
+ extended type parent indicator. (str_comp_extended): New
+ helper function to compare the namelist name with the varname
+ namelist. (find_nml_name): Use the new helper functions to match
+ the extended type varnames.
+
+2014-05-23 Jerry DeLisle <jvdelisle@gcc.gnu>
+
+ PR libfortran/61173
+ * io/list_read.c (eat_spaces): If the next character pointed to
+ is a space, don't seek, must be at the end.
+
+2014-05-23 Hans-Peter Nilsson <hp@axis.com>
+
+ * configure.ac [with_newlib] (HAVE_STRNLEN, HAVE_STRNDUP): Define.
+ * configure: Regenerate.
+
+2014-05-23 Janne Blomqvist <jb@gcc.gnu.org>
+
+ PR libfortran/60324
+ * runtime/string.c: Include stdlib.h.
+
+2014-05-22 Janne Blomqvist <jb@gcc.gnu.org>
+
+ PR libfortran/60324
+ * config.h.in: Regenerated.
+ * configure: Regenerated.
+ * configure.ac (AC_CHECK_FUNCS_ONCE): Check for strnlen and
+ strndup.
+ * libgfortran.h (fc_strdup): New prototype.
+ * runtime/string.c (strnlen): New fallback function.
+ (strndup): New fallback function.
+ (fc_strdup): New function.
+ * io/close.c (st_close): Use fc_strdup.
+ * io/open.c (new_unit): Likewise.
+ (already_open): Likewise.
+ * io/unit.c (filename_from_unit): Likewise.
+ * io/unix.c (unpack_filename): Remove function.
+ (regular_file): Rename to regular_file2, add path argument.
+ (regular_file): New function calling regular_file2.
+ (compare_file_filename): Use fc_strdup.
+ (find_file): Likewise.
+ (delete_file): Likewise.
+ (file_exists): Likewise.
+ (file_size): Likewise.
+ (inquire_sequential): Likewise.
+ (inquire_direct): Likewise.
+ (inquire_formatted): Likewise.
+ (inquire_access): Likewise.
+ * io/unix.h (unpack_filename): Remove prototype.
+ * runtime/main.c (please_free_exe_path_when_done): Change type to
+ bool.
+ (store_exe_path): Use malloced buffer, grow as needed.
+
+2014-05-17 Jerry DeLisle <jvdelisle@gcc.gnu>
+
+ PR libfortran/52539
+ * io/io.h (gfc_unit): New function pointers *next_char_fn_ptr
+ and *push_char_fn_ptr.
+ *io/list_read.c (next_char): Create macro with this name to call
+ the new function pointer. Split the original next_char function
+ into three new functions. (next_char_default, next_char_internal,
+ next_char_utf8): New functions. (push_char): Create macro with
+ this name to call new function pointer. Split the original
+ push_char into three new functions. (push_char_default,
+ push_char_internal, push_char4): New functions. (set_workers):
+ New function to initilize the function pointers depending on the
+ type of IO to be performed. (list_formatted_read_scalar): Use
+ set_workers function. (finish_list_read): Likewise.
+ (namelist_read): Likewise.
+ (nml_get_obj_data): Use push_char_default.
+
+2014-05-16 Janne Blomqvist <jb@gcc.gnu.org>
+
+ PR libfortran/61187
+ * io/unix.c (raw_close): Check if s->fd is -1.
+ (fd_to_stream): Check return value of fstat(), handle error.
+
+2014-05-12 Janne Blomqvist <jb@gcc.gnu.org>
+
+ PR libfortran/61035
+ * intrinsics/getcwd.c (getcwd_i4_sub): Avoid potentially large
+ stack allocation, avoid extra copying in the common case.
+
+2014-05-12 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * configure.ac (AM_CFLAGS): Use -std=gnu11.
+ (CFLAGS): Likewise.
+ * configure: Regenerated.
+
+2014-05-11 Tobias Burnus <burnus@net-b.de>
+
+ * caf/libcaf.h (_gfortran_caf_num_images): Change type of
+ second argument to int.
+ * caf/mpi.c (_gfortran_caf_num_images): Ditto.
+ * caf/single.c (_gfortran_caf_num_images): Ditto.
+
+2014-05-08 Tobias Burnus <burnus@net-b.de>
+
+ * caf/libcaf.h (caf_vector_t, _gfortran_caf_co_sum,
+ _gfortran_caf_co_min, _gfortran_caf_co_max): Declare
+ * caf/single.c
+
2014-05-06 Jerry DeLisle <jvdelisle@gcc.gnu>
PR libfortran/61049
@@ -176,7 +305,7 @@
line_buffer_pos for line_buffer look ahead.
(read_logical, read_integer, parse_real, read_real, check_type):
Adjust location of free_line to after generating error messages
- to retain the correct item count for the message.
+ to retain the correct item count for the message.
2014-01-02 Richard Sandiford <rdsandiford@googlemail.com>
@@ -199,7 +328,7 @@
checks for library ok. (new_unit): Do cleanup after error.
(st_open): Do proper return after error.
* io/transfer.c (data_transfer_init): Likewise.
-
+
2013-12-11 Tobias Burnus <burnus@net-b.de>
* config/fpu-387.h (sigill_hdlr, get_fpu_rounding_mode): Emit SSE
diff --git a/libgfortran/caf/libcaf.h b/libgfortran/caf/libcaf.h
index 8b8fd3e2b8f..1c01f9f09b3 100644
--- a/libgfortran/caf/libcaf.h
+++ b/libgfortran/caf/libcaf.h
@@ -65,12 +65,23 @@ typedef struct caf_static_t {
}
caf_static_t;
+typedef struct caf_vector_t {
+ size_t nvec; /* size of the vector; 0 means dim triplet. */
+ union {
+ struct {
+ ptrdiff_t lower_bound, upper_bound, stride;
+ } triplet;
+ ptrdiff_t *vector;
+ } u;
+}
+caf_vector_t;
+
void _gfortran_caf_init (int *, char ***);
void _gfortran_caf_finalize (void);
int _gfortran_caf_this_image (int);
-int _gfortran_caf_num_images (int, bool);
+int _gfortran_caf_num_images (int, int);
void *_gfortran_caf_register (size_t, caf_register_t, caf_token_t *, int *,
char *, int);
@@ -92,4 +103,10 @@ void _gfortran_caf_error_stop_str (const char *, int32_t)
__attribute__ ((noreturn));
void _gfortran_caf_error_stop (int32_t) __attribute__ ((noreturn));
+void _gfortran_caf_co_sum (void *, caf_vector_t *, int, int *, char *, int);
+void _gfortran_caf_co_min (void *, caf_vector_t *, int, int *, char *, int,
+ int);
+void _gfortran_caf_co_max (void *, caf_vector_t *, int, int *, char *, int,
+ int);
+
#endif /* LIBCAF_H */
diff --git a/libgfortran/caf/mpi.c b/libgfortran/caf/mpi.c
index fe2baf4633c..8d8c7de21a9 100644
--- a/libgfortran/caf/mpi.c
+++ b/libgfortran/caf/mpi.c
@@ -123,7 +123,7 @@ _gfortran_caf_this_image (int distance __attribute__ ((unused)))
int
_gfortran_caf_num_images (int distance __attribute__ ((unused)),
- bool failed __attribute__ ((unused)))
+ int failed __attribute__ ((unused)))
{
return caf_num_images;
}
diff --git a/libgfortran/caf/single.c b/libgfortran/caf/single.c
index cf1ced85d90..521c93c34b0 100644
--- a/libgfortran/caf/single.c
+++ b/libgfortran/caf/single.c
@@ -87,7 +87,7 @@ _gfortran_caf_this_image (int distance __attribute__ ((unused)))
int
_gfortran_caf_num_images (int distance __attribute__ ((unused)),
- bool failed __attribute__ ((unused)))
+ int failed __attribute__ ((unused)))
{
return 1;
}
@@ -202,3 +202,39 @@ _gfortran_caf_error_stop (int32_t error)
fprintf (stderr, "ERROR STOP %d\n", error);
exit (error);
}
+
+
+void
+_gfortran_caf_co_sum (void *a __attribute__ ((unused)),
+ caf_vector_t vector[] __attribute__ ((unused)),
+ int result_image __attribute__ ((unused)),
+ int *stat, char *errmsg __attribute__ ((unused)),
+ int errmsg_len __attribute__ ((unused)))
+{
+ if (stat)
+ stat = 0;
+}
+
+void
+_gfortran_caf_co_min (void *a __attribute__ ((unused)),
+ caf_vector_t vector[] __attribute__ ((unused)),
+ int result_image __attribute__ ((unused)),
+ int *stat, char *errmsg __attribute__ ((unused)),
+ int src_len __attribute__ ((unused)),
+ int errmsg_len __attribute__ ((unused)))
+{
+ if (stat)
+ stat = 0;
+}
+
+void
+_gfortran_caf_co_max (void *a __attribute__ ((unused)),
+ caf_vector_t vector[] __attribute__ ((unused)),
+ int result_image __attribute__ ((unused)),
+ int *stat, char *errmsg __attribute__ ((unused)),
+ int src_len __attribute__ ((unused)),
+ int errmsg_len __attribute__ ((unused)))
+{
+ if (stat)
+ stat = 0;
+}
diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in
index 8298f8d7812..110fb6d5b9a 100644
--- a/libgfortran/config.h.in
+++ b/libgfortran/config.h.in
@@ -729,6 +729,12 @@
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
+/* Define to 1 if you have the `strndup' function. */
+#undef HAVE_STRNDUP
+
+/* Define to 1 if you have the `strnlen' function. */
+#undef HAVE_STRNLEN
+
/* Define to 1 if you have the `strtof' function. */
#undef HAVE_STRTOF
diff --git a/libgfortran/configure b/libgfortran/configure
index d3ced74e950..9841ebc0ae3 100755
--- a/libgfortran/configure
+++ b/libgfortran/configure
@@ -2599,6 +2599,8 @@ as_fn_append ac_func_list " getegid"
as_fn_append ac_func_list " secure_getenv"
as_fn_append ac_func_list " __secure_getenv"
as_fn_append ac_func_list " mkostemp"
+as_fn_append ac_func_list " strnlen"
+as_fn_append ac_func_list " strndup"
as_fn_append ac_header_list " math.h"
# Check that the precious variables saved in the cache have kept the same
# value.
@@ -5769,12 +5771,13 @@ fi
# Add -Wall -fno-repack-arrays -fno-underscoring if we are using GCC.
if test "x$GCC" = "xyes"; then
AM_FCFLAGS="-I . -Wall -Werror -fimplicit-none -fno-repack-arrays -fno-underscoring"
- ## We like to use C99 routines when available. This makes sure that
+ ## We like to use C11 and C99 routines when available. This makes
+ ## sure that
## __STDC_VERSION__ is set such that libc includes make them available.
- AM_CFLAGS="-std=gnu99 -Wall -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wextra -Wwrite-strings"
+ AM_CFLAGS="-std=gnu11 -Wall -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wextra -Wwrite-strings"
## Compile the following tests with the same system header contents
## that we'll encounter when compiling our own source files.
- CFLAGS="-std=gnu99 $CFLAGS"
+ CFLAGS="-std=gnu11 $CFLAGS"
fi
@@ -12343,7 +12346,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 12346 "configure"
+#line 12349 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12449,7 +12452,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 12452 "configure"
+#line 12455 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -16473,6 +16476,12 @@ $as_echo "#define HAVE_LOCALTIME_R 1" >>confdefs.h
$as_echo "#define HAVE_GMTIME_R 1" >>confdefs.h
+$as_echo "#define HAVE_STRNLEN 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_STRNDUP 1" >>confdefs.h
+
+
# At some point, we should differentiate between architectures
# like x86, which have long double versions, and alpha/powerpc/etc.,
# which don't. For the time being, punt.
@@ -16605,6 +16614,10 @@ done
+
+
+
+
fi
# Check strerror_r, cannot be above as versions with two and three arguments exist
diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac
index 24dbf2b4fa5..ab4c497e5f3 100644
--- a/libgfortran/configure.ac
+++ b/libgfortran/configure.ac
@@ -139,12 +139,13 @@ AM_PROG_CC_C_O
# Add -Wall -fno-repack-arrays -fno-underscoring if we are using GCC.
if test "x$GCC" = "xyes"; then
AM_FCFLAGS="-I . -Wall -Werror -fimplicit-none -fno-repack-arrays -fno-underscoring"
- ## We like to use C99 routines when available. This makes sure that
+ ## We like to use C11 and C99 routines when available. This makes
+ ## sure that
## __STDC_VERSION__ is set such that libc includes make them available.
- AM_CFLAGS="-std=gnu99 -Wall -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wextra -Wwrite-strings"
+ AM_CFLAGS="-std=gnu11 -Wall -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wextra -Wwrite-strings"
## Compile the following tests with the same system header contents
## that we'll encounter when compiling our own source files.
- CFLAGS="-std=gnu99 $CFLAGS"
+ CFLAGS="-std=gnu11 $CFLAGS"
fi
AC_SUBST(AM_FCFLAGS)
AC_SUBST(AM_CFLAGS)
@@ -272,6 +273,8 @@ if test "x${with_newlib}" = "xyes"; then
AC_DEFINE(HAVE_VSNPRINTF, 1, [Define if you have vsnprintf.])
AC_DEFINE(HAVE_LOCALTIME_R, 1, [Define if you have localtime_r.])
AC_DEFINE(HAVE_GMTIME_R, 1, [Define if you have gmtime_r.])
+ AC_DEFINE(HAVE_STRNLEN, 1, [Define if you have strnlen.])
+ AC_DEFINE(HAVE_STRNDUP, 1, [Define if you have strndup.])
# At some point, we should differentiate between architectures
# like x86, which have long double versions, and alpha/powerpc/etc.,
@@ -286,7 +289,7 @@ else
strcasestr getrlimit gettimeofday stat fstat lstat getpwuid vsnprintf dup \
getcwd localtime_r gmtime_r getpwuid_r ttyname_r clock_gettime \
readlink getgid getpid getppid getuid geteuid umask getegid \
- secure_getenv __secure_getenv mkostemp)
+ secure_getenv __secure_getenv mkostemp strnlen strndup)
fi
# Check strerror_r, cannot be above as versions with two and three arguments exist
diff --git a/libgfortran/intrinsics/ctime.c b/libgfortran/intrinsics/ctime.c
index db41f02cd41..9cda39b0e9a 100644
--- a/libgfortran/intrinsics/ctime.c
+++ b/libgfortran/intrinsics/ctime.c
@@ -31,31 +31,53 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <string.h>
-/* strftime-like function that fills a C string with %c format which
- is identical to ctime in the default locale. As ctime and ctime_r
- are poorly specified and their usage not recommended, the
- implementation instead uses strftime. */
-
-static size_t
-strctime (char *s, size_t max, const time_t *timep)
+/* Maximum space a ctime-like string might need. A "normal" ctime
+ string is 26 bytes, and in our case 24 bytes as we don't include
+ the trailing newline and null. However, the longest possible year
+ number is -2,147,481,748 (1900 - 2,147,483,648, since tm_year is a
+ 32-bit signed integer) so an extra 7 bytes are needed. */
+#define CTIME_BUFSZ 31
+
+
+/* Thread-safe ctime-like function that fills a Fortran
+ string. ctime_r is a portability headache and marked as obsolescent
+ in POSIX 2008, which recommends strftime in its place. However,
+ strftime(..., "%c",...) doesn't produce ctime-like output on
+ MinGW, so do it manually with snprintf. */
+
+static int
+gf_ctime (char *s, size_t max, const time_t timev)
{
struct tm ltm;
int failed;
+ char buf[CTIME_BUFSZ + 1];
/* Some targets provide a localtime_r based on a draft of the POSIX
standard where the return type is int rather than the
standardized struct tm*. */
- __builtin_choose_expr (__builtin_classify_type (localtime_r (timep, &ltm))
+ __builtin_choose_expr (__builtin_classify_type (localtime_r (&timev, &ltm))
== 5,
- failed = localtime_r (timep, &ltm) == NULL,
- failed = localtime_r (timep, &ltm) != 0);
+ failed = localtime_r (&timev, &ltm) == NULL,
+ failed = localtime_r (&timev, &ltm) != 0);
if (failed)
- return 0;
- return strftime (s, max, "%c", &ltm);
+ goto blank;
+ int n = snprintf (buf, sizeof (buf),
+ "%3.3s %3.3s%3d %.2d:%.2d:%.2d %d",
+ "SunMonTueWedThuFriSat" + ltm.tm_wday * 3,
+ "JanFebMarAprMayJunJulAugSepOctNovDec" + ltm.tm_mon * 3,
+ ltm.tm_mday, ltm.tm_hour, ltm.tm_min, ltm.tm_sec,
+ 1900 + ltm.tm_year);
+ if (n < 0)
+ goto blank;
+ if ((size_t) n <= max)
+ {
+ cf_strcpy (s, max, buf);
+ return n;
+ }
+ blank:
+ memset (s, ' ', max);
+ return 0;
}
-/* In the default locale, the date and time representation fits in 26
- bytes. However, other locales might need more space. */
-#define CSZ 100
extern void fdate (char **, gfc_charlen_type *);
export_proto(fdate);
@@ -64,8 +86,8 @@ void
fdate (char ** date, gfc_charlen_type * date_len)
{
time_t now = time(NULL);
- *date = xmalloc (CSZ);
- *date_len = strctime (*date, CSZ, &now);
+ *date = xmalloc (CTIME_BUFSZ);
+ *date_len = gf_ctime (*date, CTIME_BUFSZ, now);
}
@@ -76,10 +98,7 @@ void
fdate_sub (char * date, gfc_charlen_type date_len)
{
time_t now = time(NULL);
- char *s = xmalloc (date_len + 1);
- size_t n = strctime (s, date_len + 1, &now);
- fstrcpy (date, date_len, s, n);
- free (s);
+ gf_ctime (date, date_len, now);
}
@@ -91,8 +110,8 @@ void
PREFIX(ctime) (char ** date, gfc_charlen_type * date_len, GFC_INTEGER_8 t)
{
time_t now = t;
- *date = xmalloc (CSZ);
- *date_len = strctime (*date, CSZ, &now);
+ *date = xmalloc (CTIME_BUFSZ);
+ *date_len = gf_ctime (*date, CTIME_BUFSZ, now);
}
@@ -103,8 +122,5 @@ void
ctime_sub (GFC_INTEGER_8 * t, char * date, gfc_charlen_type date_len)
{
time_t now = *t;
- char *s = xmalloc (date_len + 1);
- size_t n = strctime (s, date_len + 1, &now);
- fstrcpy (date, date_len, s, n);
- free (s);
+ gf_ctime (date, date_len, now);
}
diff --git a/libgfortran/intrinsics/getcwd.c b/libgfortran/intrinsics/getcwd.c
index 161a288f172..94808edfc50 100644
--- a/libgfortran/intrinsics/getcwd.c
+++ b/libgfortran/intrinsics/getcwd.c
@@ -2,7 +2,7 @@
Copyright (C) 2004-2014 Free Software Foundation, Inc.
Contributed by Steven G. Kargl <kargls@comcast.net>.
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
@@ -25,6 +25,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "libgfortran.h"
+#include <stdlib.h>
#include <string.h>
#include <errno.h>
@@ -40,20 +41,35 @@ iexport_proto(getcwd_i4_sub);
void
getcwd_i4_sub (char *cwd, GFC_INTEGER_4 *status, gfc_charlen_type cwd_len)
{
- char str[cwd_len + 1];
- GFC_INTEGER_4 stat;
+ int err;
- memset(cwd, ' ', (size_t) cwd_len);
-
- if (!getcwd (str, (size_t) cwd_len + 1))
- stat = errno;
- else
+ if (getcwd (cwd, cwd_len))
{
- stat = 0;
- memcpy (cwd, str, strlen (str));
+ size_t len = strlen (cwd);
+ memset (cwd + len, ' ', cwd_len - len);
+ err = 0;
}
+ else if (errno == ERANGE)
+ {
+ /* There is a possibility that the previous attempt failed due
+ to not enough space for the terminating null byte. Try again
+ with a buffer one char longer. */
+ char *buf = xmalloc (cwd_len + 1);
+ if (getcwd (buf, cwd_len + 1))
+ {
+ memcpy (cwd, buf, cwd_len);
+ err = 0;
+ }
+ else
+ err = errno;
+ free (buf);
+ }
+ else
+ err = errno;
+ if (err)
+ memset (cwd, ' ', cwd_len);
if (status != NULL)
- *status = stat;
+ *status = err;
}
iexport(getcwd_i4_sub);
diff --git a/libgfortran/io/close.c b/libgfortran/io/close.c
index 63da0c420cd..55f49da831e 100644
--- a/libgfortran/io/close.c
+++ b/libgfortran/io/close.c
@@ -72,8 +72,7 @@ st_close (st_parameter_close *clp)
generate_error (&clp->common, LIBERROR_BAD_OPTION,
"Can't KEEP a scratch file on CLOSE");
#if !HAVE_UNLINK_OPEN_FILE
- path = (char *) gfc_alloca (u->file_len + 1);
- unpack_filename (path, u->file, u->file_len);
+ path = fc_strdup (u->file, u->file_len);
#endif
}
else
@@ -83,8 +82,7 @@ st_close (st_parameter_close *clp)
#if HAVE_UNLINK_OPEN_FILE
delete_file (u);
#else
- path = (char *) gfc_alloca (u->file_len + 1);
- unpack_filename (path, u->file, u->file_len);
+ path = fc_strdup (u->file, u->file_len);
#endif
}
}
@@ -93,7 +91,10 @@ st_close (st_parameter_close *clp)
#if !HAVE_UNLINK_OPEN_FILE
if (path != NULL)
- unlink (path);
+ {
+ unlink (path);
+ free (path);
+ }
#endif
}
diff --git a/libgfortran/io/fbuf.c b/libgfortran/io/fbuf.c
index 170ce9754c9..e24da62d99c 100644
--- a/libgfortran/io/fbuf.c
+++ b/libgfortran/io/fbuf.c
@@ -121,10 +121,7 @@ fbuf_alloc (gfc_unit * u, int len)
{
/* Round up to nearest multiple of the current buffer length. */
newlen = ((u->fbuf->pos + len) / u->fbuf->len + 1) * u->fbuf->len;
- dest = realloc (u->fbuf->buf, newlen);
- if (dest == NULL)
- return NULL;
- u->fbuf->buf = dest;
+ u->fbuf->buf = xrealloc (u->fbuf->buf, newlen);
u->fbuf->len = newlen;
}
diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h
index 3481c83d791..4e71d4953b1 100644
--- a/libgfortran/io/io.h
+++ b/libgfortran/io/io.h
@@ -575,6 +575,10 @@ typedef struct gfc_unit
/* Formatting buffer. */
struct fbuf *fbuf;
+
+ /* Function pointer, points to list_read worker functions. */
+ int (*next_char_fn_ptr) (st_parameter_dt *);
+ void (*push_char_fn_ptr) (st_parameter_dt *, int);
}
gfc_unit;
diff --git a/libgfortran/io/list_read.c b/libgfortran/io/list_read.c
index 893815e3d5a..a7e4f888f1c 100644
--- a/libgfortran/io/list_read.c
+++ b/libgfortran/io/list_read.c
@@ -67,12 +67,19 @@ typedef unsigned char uchar;
#define MSGLEN 100
-/* Save a character to a string buffer, enlarging it as necessary. */
+/* Wrappers for calling the current worker functions. */
+
+#define next_char(dtp) ((dtp)->u.p.current_unit->next_char_fn_ptr (dtp))
+#define push_char(dtp, c) ((dtp)->u.p.current_unit->push_char_fn_ptr (dtp, c))
+
+/* Worker function to save a default KIND=1 character to a string
+ buffer, enlarging it as necessary. */
+
static void
-push_char (st_parameter_dt *dtp, char c)
+push_char_default (st_parameter_dt *dtp, int c)
{
- char *new;
+
if (dtp->u.p.saved_string == NULL)
{
@@ -85,25 +92,24 @@ push_char (st_parameter_dt *dtp, char c)
if (dtp->u.p.saved_used >= dtp->u.p.saved_length)
{
dtp->u.p.saved_length = 2 * dtp->u.p.saved_length;
- new = realloc (dtp->u.p.saved_string, dtp->u.p.saved_length);
- if (new == NULL)
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- dtp->u.p.saved_string = new;
+ dtp->u.p.saved_string =
+ xrealloc (dtp->u.p.saved_string, dtp->u.p.saved_length);
// Also this should not be necessary.
- memset (new + dtp->u.p.saved_used, 0,
+ memset (dtp->u.p.saved_string + dtp->u.p.saved_used, 0,
dtp->u.p.saved_length - dtp->u.p.saved_used);
}
- dtp->u.p.saved_string[dtp->u.p.saved_used++] = c;
+ dtp->u.p.saved_string[dtp->u.p.saved_used++] = (char) c;
}
-/* Save a KIND=4 character to a string buffer, enlarging the buffer
- as necessary. */
+/* Worker function to save a KIND=4 character to a string buffer,
+ enlarging the buffer as necessary. */
+
static void
-push_char4 (st_parameter_dt *dtp, gfc_char4_t c)
+push_char4 (st_parameter_dt *dtp, int c)
{
gfc_char4_t *new, *p = (gfc_char4_t *) dtp->u.p.saved_string;
@@ -118,12 +124,9 @@ push_char4 (st_parameter_dt *dtp, gfc_char4_t c)
if (dtp->u.p.saved_used >= dtp->u.p.saved_length)
{
dtp->u.p.saved_length = 2 * dtp->u.p.saved_length;
- new = realloc (p, dtp->u.p.saved_length);
- if (new == NULL)
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- p = new;
+ p = xrealloc (p, dtp->u.p.saved_length * sizeof (gfc_char4_t));
- memset (new + dtp->u.p.saved_used, 0,
+ memset4 (new + dtp->u.p.saved_used, 0,
dtp->u.p.saved_length - dtp->u.p.saved_used);
}
@@ -162,13 +165,16 @@ free_line (st_parameter_dt *dtp)
}
+/* Unget saves the last character so when reading the next character,
+ we need to check to see if there is a character waiting. Similar,
+ if the line buffer is being used to read_logical, check it too. */
+
static int
-next_char (st_parameter_dt *dtp)
+check_buffers (st_parameter_dt *dtp)
{
- ssize_t length;
- gfc_offset record;
int c;
+ c = '\0';
if (dtp->u.p.last_char != EOF - 1)
{
dtp->u.p.at_eol = 0;
@@ -194,6 +200,43 @@ next_char (st_parameter_dt *dtp)
dtp->u.p.line_buffer_pos = 0;
dtp->u.p.line_buffer_enabled = 0;
}
+
+done:
+ dtp->u.p.at_eol = (c == '\n' || c == EOF);
+ return c;
+}
+
+
+/* Worker function for default character encoded file. */
+static int
+next_char_default (st_parameter_dt *dtp)
+{
+ int c;
+
+ /* Always check the unget and line buffer first. */
+ if ((c = check_buffers (dtp)))
+ return c;
+
+ c = fbuf_getc (dtp->u.p.current_unit);
+ if (c != EOF && is_stream_io (dtp))
+ dtp->u.p.current_unit->strm_pos++;
+
+ dtp->u.p.at_eol = (c == '\n' || c == EOF);
+ return c;
+}
+
+
+/* Worker function for internal and array I/O units. */
+static int
+next_char_internal (st_parameter_dt *dtp)
+{
+ ssize_t length;
+ gfc_offset record;
+ int c;
+
+ /* Always check the unget and line buffer first. */
+ if ((c = check_buffers (dtp)))
+ return c;
/* Handle the end-of-record and end-of-file conditions for
internal array unit. */
@@ -229,58 +272,50 @@ next_char (st_parameter_dt *dtp)
/* Get the next character and handle end-of-record conditions. */
- if (is_internal_unit (dtp))
+ if (dtp->common.unit) /* Check for kind=4 internal unit. */
+ length = sread (dtp->u.p.current_unit->s, &c, sizeof (gfc_char4_t));
+ else
+ {
+ char cc;
+ length = sread (dtp->u.p.current_unit->s, &cc, 1);
+ c = cc;
+ }
+
+ if (unlikely (length < 0))
{
- /* Check for kind=4 internal unit. */
- if (dtp->common.unit)
- length = sread (dtp->u.p.current_unit->s, &c, sizeof (gfc_char4_t));
- else
- {
- char cc;
- length = sread (dtp->u.p.current_unit->s, &cc, 1);
- c = cc;
- }
+ generate_error (&dtp->common, LIBERROR_OS, NULL);
+ return '\0';
+ }
- if (unlikely (length < 0))
+ if (is_array_io (dtp))
+ {
+ /* Check whether we hit EOF. */
+ if (unlikely (length == 0))
{
- generate_error (&dtp->common, LIBERROR_OS, NULL);
+ generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
return '\0';
- }
-
- if (is_array_io (dtp))
- {
- /* Check whether we hit EOF. */
- if (unlikely (length == 0))
- {
- generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
- return '\0';
- }
- dtp->u.p.current_unit->bytes_left--;
- }
- else
- {
- if (dtp->u.p.at_eof)
- return EOF;
- if (length == 0)
- {
- c = '\n';
- dtp->u.p.at_eof = 1;
- }
- }
+ }
+ dtp->u.p.current_unit->bytes_left--;
}
else
{
- c = fbuf_getc (dtp->u.p.current_unit);
- if (c != EOF && is_stream_io (dtp))
- dtp->u.p.current_unit->strm_pos++;
+ if (dtp->u.p.at_eof)
+ return EOF;
+ if (length == 0)
+ {
+ c = '\n';
+ dtp->u.p.at_eof = 1;
+ }
}
+
done:
dtp->u.p.at_eol = (c == '\n' || c == EOF);
return c;
}
-static gfc_char4_t
+/* Worker function for UTF encoded files. */
+static int
next_char_utf8 (st_parameter_dt *dtp)
{
static const uchar masks[6] = { 0x7F, 0x1F, 0x0F, 0x07, 0x02, 0x01 };
@@ -288,9 +323,12 @@ next_char_utf8 (st_parameter_dt *dtp)
int i, nb;
gfc_char4_t c;
- c = next_char (dtp);
+ /* Always check the unget and line buffer first. */
+ if (!(c = check_buffers (dtp)))
+ c = fbuf_getc (dtp->u.p.current_unit);
+
if (c < 0x80)
- return c;
+ goto utf_done;
/* The number of leading 1-bits in the first byte indicates how many
bytes follow. */
@@ -305,11 +343,9 @@ next_char_utf8 (st_parameter_dt *dtp)
/* Decode the bytes read. */
for (i = 1; i < nb; i++)
{
- gfc_char4_t n = next_char (dtp);
-
+ gfc_char4_t n = fbuf_getc (dtp->u.p.current_unit);
if ((n & 0xC0) != 0x80)
goto invalid;
-
c = ((c << 6) + (n & 0x3F));
}
@@ -324,7 +360,9 @@ next_char_utf8 (st_parameter_dt *dtp)
if (c > 0x7FFFFFFF || (c >= 0xD800 && c <= 0xDFFF))
goto invalid;
- return c;
+utf_done:
+ dtp->u.p.at_eol = (c == '\n' || c == (gfc_char4_t) EOF);
+ return (int) c;
invalid:
generate_error (&dtp->common, LIBERROR_READ_VALUE, "Invalid UTF-8 encoding");
@@ -355,7 +393,7 @@ eat_spaces (st_parameter_dt *dtp)
if (is_array_io (dtp))
{
gfc_offset offset = stell (dtp->u.p.current_unit->s);
- gfc_offset limit = dtp->u.p.current_unit->bytes_left;
+ gfc_offset limit = offset + dtp->u.p.current_unit->bytes_left;
if (dtp->common.unit) /* kind=4 */
{
@@ -367,13 +405,15 @@ eat_spaces (st_parameter_dt *dtp)
offset += (sizeof (gfc_char4_t));
dtp->u.p.current_unit->bytes_left--;
}
- while (offset < limit && (cc == (gfc_char4_t)' '
- || cc == (gfc_char4_t)'\t'));
+ while (offset < limit && cc == (gfc_char4_t)' ');
/* Back up, seek ahead, and fall through to complete the
process so that END conditions are handled correctly. */
dtp->u.p.current_unit->bytes_left++;
- sseek (dtp->u.p.current_unit->s,
- offset-(sizeof (gfc_char4_t)), SEEK_SET);
+
+ cc = dtp->internal_unit[offset];
+ if (cc != (gfc_char4_t)' ')
+ sseek (dtp->u.p.current_unit->s,
+ offset-(sizeof (gfc_char4_t)), SEEK_SET);
}
else
{
@@ -382,11 +422,13 @@ eat_spaces (st_parameter_dt *dtp)
c = dtp->internal_unit[offset++];
dtp->u.p.current_unit->bytes_left--;
}
- while (offset < limit && (c == ' ' || c == '\t'));
+ while (offset < limit && c == ' ');
/* Back up, seek ahead, and fall through to complete the
process so that END conditions are handled correctly. */
dtp->u.p.current_unit->bytes_left++;
- sseek (dtp->u.p.current_unit->s, offset-1, SEEK_SET);
+
+ if (dtp->internal_unit[offset] != ' ')
+ sseek (dtp->u.p.current_unit->s, offset - 1, SEEK_SET);
}
}
/* Now skip spaces, EOF and EOL are handled in next_char. */
@@ -1172,96 +1214,50 @@ read_character (st_parameter_dt *dtp, int length __attribute__ ((unused)))
get_string:
- if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
- for (;;)
- {
- if ((c = next_char_utf8 (dtp)) == EOF)
- goto done_eof;
- switch (c)
- {
- case '"':
- case '\'':
- if (c != quote)
- {
- push_char4 (dtp, c);
- break;
- }
-
- /* See if we have a doubled quote character or the end of
- the string. */
-
- if ((c = next_char_utf8 (dtp)) == EOF)
- goto done_eof;
- if (c == quote)
- {
- push_char4 (dtp, quote);
- break;
- }
-
- unget_char (dtp, c);
- goto done;
-
- CASE_SEPARATORS:
- if (quote == ' ')
- {
- unget_char (dtp, c);
- goto done;
- }
-
- if (c != '\n' && c != '\r')
- push_char4 (dtp, c);
- break;
-
- default:
- push_char4 (dtp, c);
- break;
- }
- }
- else
- for (;;)
- {
- if ((c = next_char (dtp)) == EOF)
- goto done_eof;
- switch (c)
- {
- case '"':
- case '\'':
- if (c != quote)
- {
- push_char (dtp, c);
- break;
- }
-
- /* See if we have a doubled quote character or the end of
- the string. */
+ for (;;)
+ {
+ if ((c = next_char (dtp)) == EOF)
+ goto done_eof;
+ switch (c)
+ {
+ case '"':
+ case '\'':
+ if (c != quote)
+ {
+ push_char (dtp, c);
+ break;
+ }
- if ((c = next_char (dtp)) == EOF)
- goto done_eof;
- if (c == quote)
- {
- push_char (dtp, quote);
- break;
- }
+ /* See if we have a doubled quote character or the end of
+ the string. */
- unget_char (dtp, c);
- goto done;
+ if ((c = next_char (dtp)) == EOF)
+ goto done_eof;
+ if (c == quote)
+ {
+ push_char (dtp, quote);
+ break;
+ }
- CASE_SEPARATORS:
- if (quote == ' ')
- {
- unget_char (dtp, c);
- goto done;
- }
+ unget_char (dtp, c);
+ goto done;
- if (c != '\n' && c != '\r')
- push_char (dtp, c);
- break;
+ CASE_SEPARATORS:
+ if (quote == ' ')
+ {
+ unget_char (dtp, c);
+ goto done;
+ }
- default:
+ if (c != '\n' && c != '\r')
push_char (dtp, c);
- break;
- }
- }
+ break;
+
+ default:
+ push_char (dtp, c);
+ break;
+ }
+ }
/* At this point, we have to have a separator, or else the string is
invalid. */
@@ -2025,6 +2021,30 @@ check_type (st_parameter_dt *dtp, bt type, int kind)
}
+/* Initialize the function pointers to select the correct versions of
+ next_char and push_char depending on what we are doing. */
+
+static void
+set_workers (st_parameter_dt *dtp)
+{
+ if (dtp->u.p.current_unit->flags.encoding == ENCODING_UTF8)
+ {
+ dtp->u.p.current_unit->next_char_fn_ptr = &next_char_utf8;
+ dtp->u.p.current_unit->push_char_fn_ptr = &push_char4;
+ }
+ else if (is_internal_unit (dtp))
+ {
+ dtp->u.p.current_unit->next_char_fn_ptr = &next_char_internal;
+ dtp->u.p.current_unit->push_char_fn_ptr = &push_char_default;
+ }
+ else
+ {
+ dtp->u.p.current_unit->next_char_fn_ptr = &next_char_default;
+ dtp->u.p.current_unit->push_char_fn_ptr = &push_char_default;
+ }
+
+}
+
/* Top level data transfer subroutine for list reads. Because we have
to deal with repeat counts, the data item is always saved after
reading, usually in the dtp->u.p.value[] array. If a repeat count is
@@ -2040,6 +2060,9 @@ list_formatted_read_scalar (st_parameter_dt *dtp, bt type, void *p,
dtp->u.p.namelist_mode = 0;
+ /* Set the next_char and push_char worker functions. */
+ set_workers (dtp);
+
if (dtp->u.p.first_item)
{
dtp->u.p.first_item = 0;
@@ -2162,7 +2185,7 @@ list_formatted_read_scalar (st_parameter_dt *dtp, bt type, void *p,
memcpy (p, dtp->u.p.saved_string, m);
else
for (i = 0; i < m; i++)
- *q++ = (unsigned char) dtp->u.p.saved_string[i];
+ *q++ = *r++;
}
}
else
@@ -2244,6 +2267,10 @@ finish_list_read (st_parameter_dt *dtp)
if (!is_internal_unit (dtp))
{
int c;
+
+ /* Set the next_char and push_char worker functions. */
+ set_workers (dtp);
+
c = next_char (dtp);
if (c == EOF)
{
@@ -2525,6 +2552,38 @@ err_ret:
return false;
}
+
+static bool
+extended_look_ahead (char *p, char *q)
+{
+ char *r, *s;
+
+ /* Scan ahead to find a '%' in the p string. */
+ for(r = p, s = q; *r && *s; s++)
+ if ((*s == '%' || *s == '+') && strcmp (r + 1, s + 1) == 0)
+ return true;
+ return false;
+}
+
+
+static bool
+strcmp_extended_type (char *p, char *q)
+{
+ char *r, *s;
+
+ for (r = p, s = q; *r && *s; r++, s++)
+ {
+ if (*r != *s)
+ {
+ if (*r == '%' && *s == '+' && extended_look_ahead (r, s))
+ return true;
+ break;
+ }
+ }
+ return false;
+}
+
+
static namelist_info *
find_nml_node (st_parameter_dt *dtp, char * var_name)
{
@@ -2536,6 +2595,11 @@ find_nml_node (st_parameter_dt *dtp, char * var_name)
t->touched = 1;
return t;
}
+ if (strcmp_extended_type (var_name, t->var_name))
+ {
+ t->touched = 1;
+ return t;
+ }
t = t->next;
}
return NULL;
@@ -3060,7 +3124,7 @@ get_name:
do
{
if (!is_separator (c))
- push_char (dtp, tolower(c));
+ push_char_default (dtp, tolower(c));
if ((c = next_char (dtp)) == EOF)
goto nml_err_ret;
}
@@ -3075,7 +3139,7 @@ get_name:
are present for an object. (iii) gives the same error message
as (i) */
- push_char (dtp, '\0');
+ push_char_default (dtp, '\0');
if (component_flag)
{
@@ -3314,6 +3378,9 @@ namelist_read (st_parameter_dt *dtp)
dtp->u.p.namelist_mode = 1;
dtp->u.p.input_complete = 0;
dtp->u.p.expanded_read = 0;
+
+ /* Set the next_char and push_char worker functions. */
+ set_workers (dtp);
/* Look for &namelist_name . Skip all characters, testing for $nmlname.
Exit on success or EOF. If '?' or '=?' encountered in stdin, print
diff --git a/libgfortran/io/open.c b/libgfortran/io/open.c
index 06fd59415fe..b803859ac3d 100644
--- a/libgfortran/io/open.c
+++ b/libgfortran/io/open.c
@@ -502,12 +502,9 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags)
s = open_external (opp, flags);
if (s == NULL)
{
- char *path, *msg;
- size_t msglen;
- path = (char *) gfc_alloca (opp->file_len + 1);
- msglen = opp->file_len + 51;
- msg = (char *) gfc_alloca (msglen);
- unpack_filename (path, opp->file, opp->file_len);
+ char *path = fc_strdup (opp->file, opp->file_len);
+ size_t msglen = opp->file_len + 51;
+ char *msg = xmalloc (msglen);
switch (errno)
{
@@ -529,10 +526,13 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags)
break;
default:
+ free (msg);
msg = NULL;
}
generate_error (&opp->common, LIBERROR_OS, msg);
+ free (msg);
+ free (path);
goto cleanup;
}
@@ -676,15 +676,6 @@ already_open (st_parameter_open *opp, gfc_unit * u, unit_flags * flags)
if (!compare_file_filename (u, opp->file, opp->file_len))
{
-#if !HAVE_UNLINK_OPEN_FILE
- char *path = NULL;
- if (u->file && u->flags.status == STATUS_SCRATCH)
- {
- path = (char *) gfc_alloca (u->file_len + 1);
- unpack_filename (path, u->file, u->file_len);
- }
-#endif
-
if (sclose (u->s) == -1)
{
unlock_unit (u);
@@ -699,8 +690,14 @@ already_open (st_parameter_open *opp, gfc_unit * u, unit_flags * flags)
u->file_len = 0;
#if !HAVE_UNLINK_OPEN_FILE
+ char *path = NULL;
+ if (u->file && u->flags.status == STATUS_SCRATCH)
+ path = fc_strdup (u->file, u->file_len);
if (path != NULL)
- unlink (path);
+ {
+ unlink (path);
+ free (path);
+ }
#endif
u = new_unit (opp, u, flags);
diff --git a/libgfortran/io/unit.c b/libgfortran/io/unit.c
index 385818adc1f..a406c9e8be9 100644
--- a/libgfortran/io/unit.c
+++ b/libgfortran/io/unit.c
@@ -786,7 +786,6 @@ unit_truncate (gfc_unit * u, gfc_offset pos, st_parameter_common * common)
char *
filename_from_unit (int n)
{
- char *filename;
gfc_unit *u;
int c;
@@ -805,11 +804,7 @@ filename_from_unit (int n)
/* Get the filename. */
if (u != NULL)
- {
- filename = (char *) xmalloc (u->file_len + 1);
- unpack_filename (filename, u->file, u->file_len);
- return filename;
- }
+ return fc_strdup (u->file, u->file_len);
else
return (char *) NULL;
}
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index 34c2d0cad16..3721b71f994 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -114,9 +114,6 @@ id_from_fd (const int fd)
typeof (b) _b = (b); \
_a < _b ? _a : _b; })
-#ifndef PATH_MAX
-#define PATH_MAX 1024
-#endif
/* These flags aren't defined on all targets (mingw32), so provide them
here. */
@@ -412,7 +409,9 @@ raw_close (unix_stream * s)
{
int retval;
- if (s->fd != STDOUT_FILENO
+ if (s->fd == -1)
+ retval = -1;
+ else if (s->fd != STDOUT_FILENO
&& s->fd != STDERR_FILENO
&& s->fd != STDIN_FILENO)
retval = close (s->fd);
@@ -1003,7 +1002,15 @@ fd_to_stream (int fd, bool unformatted)
/* Get the current length of the file. */
- fstat (fd, &statbuf);
+ if (fstat (fd, &statbuf) == -1)
+ {
+ s->st_dev = s->st_ino = -1;
+ s->file_length = 0;
+ if (errno == EBADF)
+ s->fd = -1;
+ raw_init (s);
+ return (stream *) s;
+ }
s->st_dev = statbuf.st_dev;
s->st_ino = statbuf.st_ino;
@@ -1050,26 +1057,6 @@ unit_to_fd (int unit)
}
-/* unpack_filename()-- Given a fortran string and a pointer to a
- * buffer that is PATH_MAX characters, convert the fortran string to a
- * C string in the buffer. Returns nonzero if this is not possible. */
-
-int
-unpack_filename (char *cstring, const char *fstring, int len)
-{
- if (fstring == NULL)
- return EFAULT;
- len = fstrlen (fstring, len);
- if (len >= PATH_MAX)
- return ENAMETOOLONG;
-
- memmove (cstring, fstring, len);
- cstring[len] = '\0';
-
- return 0;
-}
-
-
/* Set the close-on-exec flag for an existing fd, if the system
supports such. */
@@ -1234,27 +1221,18 @@ tempfile (st_parameter_open *opp)
}
-/* regular_file()-- Open a regular file.
+/* regular_file2()-- Open a regular file.
* Change flags->action if it is ACTION_UNSPECIFIED on entry,
* unless an error occurs.
* Returns the descriptor, which is less than zero on error. */
static int
-regular_file (st_parameter_open *opp, unit_flags *flags)
+regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags)
{
- char path[min(PATH_MAX, opp->file_len + 1)];
int mode;
int rwflag;
int crflag, crflag2;
int fd;
- int err;
-
- err = unpack_filename (path, opp->file, opp->file_len);
- if (err)
- {
- errno = err; /* Fake an OS error */
- return -1;
- }
#ifdef __CYGWIN__
if (opp->file_len == 7)
@@ -1394,6 +1372,18 @@ regular_file (st_parameter_open *opp, unit_flags *flags)
}
+/* Wrapper around regular_file2, to make sure we free the path after
+ we're done. */
+
+static int
+regular_file (st_parameter_open *opp, unit_flags *flags)
+{
+ char *path = fc_strdup (opp->file, opp->file_len);
+ int fd = regular_file2 (path, opp, flags);
+ free (path);
+ return fd;
+}
+
/* open_external()-- Open an external file, unix specific version.
* Change flags->action if it is ACTION_UNSPECIFIED on entry.
* Returns NULL on operating system error. */
@@ -1484,8 +1474,8 @@ error_stream (void)
int
compare_file_filename (gfc_unit *u, const char *name, int len)
{
- char path[min(PATH_MAX, len + 1)];
struct stat st;
+ int ret;
#ifdef HAVE_WORKING_STAT
unix_stream *s;
#else
@@ -1494,18 +1484,21 @@ compare_file_filename (gfc_unit *u, const char *name, int len)
# endif
#endif
- if (unpack_filename (path, name, len))
- return 0; /* Can't be the same */
+ char *path = fc_strdup (name, len);
/* If the filename doesn't exist, then there is no match with the
* existing file. */
if (stat (path, &st) < 0)
- return 0;
+ {
+ ret = 0;
+ goto done;
+ }
#ifdef HAVE_WORKING_STAT
s = (unix_stream *) (u->s);
- return (st.st_dev == s->st_dev) && (st.st_ino == s->st_ino);
+ ret = (st.st_dev == s->st_dev) && (st.st_ino == s->st_ino);
+ goto done;
#else
# ifdef __MINGW32__
@@ -1515,13 +1508,20 @@ compare_file_filename (gfc_unit *u, const char *name, int len)
id1 = id_from_path (path);
id2 = id_from_fd (((unix_stream *) (u->s))->fd);
if (id1 || id2)
- return (id1 == id2);
+ {
+ ret = (id1 == id2);
+ goto done;
+ }
# endif
if (len != u->file_len)
- return 0;
- return (memcmp(path, u->file, len) == 0);
+ ret = 0;
+ else
+ ret = (memcmp(path, u->file, len) == 0);
#endif
+ done:
+ free (path);
+ return ret;
}
@@ -1584,18 +1584,19 @@ find_file0 (gfc_unit *u, FIND_FILE0_DECL)
gfc_unit *
find_file (const char *file, gfc_charlen_type file_len)
{
- char path[min(PATH_MAX, file_len + 1)];
struct stat st[1];
gfc_unit *u;
#if defined(__MINGW32__) && !HAVE_WORKING_STAT
uint64_t id = 0ULL;
#endif
- if (unpack_filename (path, file, file_len))
- return NULL;
+ char *path = fc_strdup (file, file_len);
if (stat (path, &st[0]) < 0)
- return NULL;
+ {
+ u = NULL;
+ goto done;
+ }
#if defined(__MINGW32__) && !HAVE_WORKING_STAT
id = id_from_path (path);
@@ -1611,7 +1612,7 @@ retry:
{
/* assert (u->closed == 0); */
__gthread_mutex_unlock (&unit_lock);
- return u;
+ goto done;
}
inc_waiting_locked (u);
@@ -1631,6 +1632,8 @@ retry:
dec_waiting_unlocked (u);
}
+ done:
+ free (path);
return u;
}
@@ -1703,16 +1706,10 @@ flush_all_units (void)
int
delete_file (gfc_unit * u)
{
- char path[min(PATH_MAX, u->file_len + 1)];
- int err = unpack_filename (path, u->file, u->file_len);
-
- if (err)
- { /* Shouldn't be possible */
- errno = err;
- return 1;
- }
-
- return unlink (path);
+ char *path = fc_strdup (u->file, u->file_len);
+ int err = unlink (path);
+ free (path);
+ return err;
}
@@ -1722,12 +1719,10 @@ delete_file (gfc_unit * u)
int
file_exists (const char *file, gfc_charlen_type file_len)
{
- char path[min(PATH_MAX, file_len + 1)];
-
- if (unpack_filename (path, file, file_len))
- return 0;
-
- return !(access (path, F_OK));
+ char *path = fc_strdup (file, file_len);
+ int res = !(access (path, F_OK));
+ free (path);
+ return res;
}
@@ -1736,15 +1731,12 @@ file_exists (const char *file, gfc_charlen_type file_len)
GFC_IO_INT
file_size (const char *file, gfc_charlen_type file_len)
{
- char path[min(PATH_MAX, file_len + 1)];
+ char *path = fc_strdup (file, file_len);
struct stat statbuf;
-
- if (unpack_filename (path, file, file_len))
- return -1;
-
- if (stat (path, &statbuf) < 0)
+ int err = stat (path, &statbuf);
+ free (path);
+ if (err == -1)
return -1;
-
return (GFC_IO_INT) statbuf.st_size;
}
@@ -1757,11 +1749,15 @@ static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
const char *
inquire_sequential (const char *string, int len)
{
- char path[min(PATH_MAX, len + 1)];
struct stat statbuf;
- if (string == NULL ||
- unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
+ if (string == NULL)
+ return unknown;
+
+ char *path = fc_strdup (string, len);
+ int err = stat (path, &statbuf);
+ free (path);
+ if (err == -1)
return unknown;
if (S_ISREG (statbuf.st_mode) ||
@@ -1781,11 +1777,15 @@ inquire_sequential (const char *string, int len)
const char *
inquire_direct (const char *string, int len)
{
- char path[min(PATH_MAX, len + 1)];
struct stat statbuf;
- if (string == NULL ||
- unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
+ if (string == NULL)
+ return unknown;
+
+ char *path = fc_strdup (string, len);
+ int err = stat (path, &statbuf);
+ free (path);
+ if (err == -1)
return unknown;
if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
@@ -1805,11 +1805,15 @@ inquire_direct (const char *string, int len)
const char *
inquire_formatted (const char *string, int len)
{
- char path[min(PATH_MAX, len + 1)];
struct stat statbuf;
- if (string == NULL ||
- unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
+ if (string == NULL)
+ return unknown;
+
+ char *path = fc_strdup (string, len);
+ int err = stat (path, &statbuf);
+ free (path);
+ if (err == -1)
return unknown;
if (S_ISREG (statbuf.st_mode) ||
@@ -1840,10 +1844,12 @@ inquire_unformatted (const char *string, int len)
static const char *
inquire_access (const char *string, int len, int mode)
{
- char path[min(PATH_MAX, len + 1)];
-
- if (string == NULL || unpack_filename (path, string, len) ||
- access (path, mode) < 0)
+ if (string == NULL)
+ return no;
+ char *path = fc_strdup (string, len);
+ int res = access (path, mode);
+ free (path);
+ if (res == -1)
return no;
return yes;
diff --git a/libgfortran/io/unix.h b/libgfortran/io/unix.h
index 37561108c80..910f2c2e650 100644
--- a/libgfortran/io/unix.h
+++ b/libgfortran/io/unix.h
@@ -185,8 +185,4 @@ internal_proto(stream_isatty);
extern int stream_ttyname (stream *, char *, size_t);
internal_proto(stream_ttyname);
-extern int unpack_filename (char *, const char *, int);
-internal_proto(unpack_filename);
-
-
#endif
diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h
index 0d6f432a24b..b3e8a2e7cfd 100644
--- a/libgfortran/libgfortran.h
+++ b/libgfortran/libgfortran.h
@@ -771,6 +771,8 @@ internal_proto(xmalloc);
extern void *xcalloc (size_t, size_t) __attribute__ ((malloc));
internal_proto(xcalloc);
+extern void *xrealloc (void *, size_t);
+internal_proto(xrealloc);
/* environ.c */
@@ -822,6 +824,9 @@ extern gfc_charlen_type string_len_trim_char4 (gfc_charlen_type,
const gfc_char4_t *);
export_proto(string_len_trim_char4);
+extern char *fc_strdup(const char *, gfc_charlen_type);
+internal_proto(fc_strdup);
+
/* io/intrinsics.c */
extern void flush_all_units (void);
diff --git a/libgfortran/runtime/main.c b/libgfortran/runtime/main.c
index 58ec6cc4961..8a572ecd5ef 100644
--- a/libgfortran/runtime/main.c
+++ b/libgfortran/runtime/main.c
@@ -26,6 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#include <errno.h>
#ifdef HAVE_UNISTD_H
@@ -70,23 +71,18 @@ static int argc_save;
static char **argv_save;
static const char *exe_path;
-static int please_free_exe_path_when_done;
+static bool please_free_exe_path_when_done;
/* Save the path under which the program was called, for use in the
backtrace routines. */
void
store_exe_path (const char * argv0)
{
-#ifndef PATH_MAX
-#define PATH_MAX 1024
-#endif
-
#ifndef DIR_SEPARATOR
#define DIR_SEPARATOR '/'
#endif
- char buf[PATH_MAX], *path;
- const char *cwd;
+ char *cwd, *path;
/* This can only happen if store_exe_path is called multiple times. */
if (please_free_exe_path_when_done)
@@ -95,13 +91,27 @@ store_exe_path (const char * argv0)
/* Reading the /proc/self/exe symlink is Linux-specific(?), but if
it works it gives the correct answer. */
#ifdef HAVE_READLINK
- int len;
- if ((len = readlink ("/proc/self/exe", buf, sizeof (buf) - 1)) != -1)
+ ssize_t len, psize = 256;
+ while (1)
{
- buf[len] = '\0';
- exe_path = strdup (buf);
- please_free_exe_path_when_done = 1;
- return;
+ path = xmalloc (psize);
+ len = readlink ("/proc/self/exe", path, psize);
+ if (len < 0)
+ {
+ free (path);
+ break;
+ }
+ else if (len < psize)
+ {
+ path[len] = '\0';
+ exe_path = strdup (path);
+ free (path);
+ please_free_exe_path_when_done = true;
+ return;
+ }
+ /* The remaining option is len == psize. */
+ free (path);
+ psize *= 4;
}
#endif
@@ -117,12 +127,29 @@ store_exe_path (const char * argv0)
#endif
{
exe_path = argv0;
- please_free_exe_path_when_done = 0;
+ please_free_exe_path_when_done = false;
return;
}
#ifdef HAVE_GETCWD
- cwd = getcwd (buf, sizeof (buf));
+ size_t cwdsize = 256;
+ while (1)
+ {
+ cwd = xmalloc (cwdsize);
+ if (getcwd (cwd, cwdsize))
+ break;
+ else if (errno == ERANGE)
+ {
+ free (cwd);
+ cwdsize *= 4;
+ }
+ else
+ {
+ free (cwd);
+ cwd = NULL;
+ break;
+ }
+ }
#else
cwd = NULL;
#endif
@@ -130,7 +157,7 @@ store_exe_path (const char * argv0)
if (!cwd)
{
exe_path = argv0;
- please_free_exe_path_when_done = 0;
+ please_free_exe_path_when_done = false;
return;
}
@@ -138,10 +165,11 @@ store_exe_path (const char * argv0)
if the executable is not in the cwd, but at this point we're out
of better ideas. */
size_t pathlen = strlen (cwd) + 1 + strlen (argv0) + 1;
- path = malloc (pathlen);
+ path = xmalloc (pathlen);
snprintf (path, pathlen, "%s%c%s", cwd, DIR_SEPARATOR, argv0);
+ free (cwd);
exe_path = path;
- please_free_exe_path_when_done = 1;
+ please_free_exe_path_when_done = true;
}
diff --git a/libgfortran/runtime/memory.c b/libgfortran/runtime/memory.c
index efeea86f15a..b18b50532c7 100644
--- a/libgfortran/runtime/memory.c
+++ b/libgfortran/runtime/memory.c
@@ -58,3 +58,17 @@ xcalloc (size_t nmemb, size_t size)
return p;
}
+
+
+void *
+xrealloc (void *ptr, size_t size)
+{
+ if (size == 0)
+ size = 1;
+
+ void *newp = realloc (ptr, size);
+ if (!newp)
+ os_error ("Memory allocation failure in xrealloc");
+
+ return newp;
+}
diff --git a/libgfortran/runtime/string.c b/libgfortran/runtime/string.c
index a7f68bf5aa1..b95d1997a5c 100644
--- a/libgfortran/runtime/string.c
+++ b/libgfortran/runtime/string.c
@@ -24,6 +24,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "libgfortran.h"
#include <string.h>
+#include <stdlib.h>
/* Given a fortran string, return its length exclusive of the trailing
@@ -90,6 +91,49 @@ cf_strcpy (char *dest, gfc_charlen_type dest_len, const char *src)
}
+#ifndef HAVE_STRNLEN
+static size_t
+strnlen (const char *s, size_t maxlen)
+{
+ for (size_t ii = 0; ii < maxlen; ii++)
+ {
+ if (s[ii] == '\0')
+ return ii;
+ }
+ return maxlen;
+}
+#endif
+
+
+#ifndef HAVE_STRNDUP
+static char *
+strndup (const char *s, size_t n)
+{
+ size_t len = strnlen (s, n);
+ char *p = malloc (len + 1);
+ if (!p)
+ return NULL;
+ memcpy (p, s, len);
+ p[len] = '\0';
+ return p;
+}
+#endif
+
+
+/* Duplicate a non-null-terminated Fortran string to a malloced
+ null-terminated C string. */
+
+char *
+fc_strdup (const char *src, gfc_charlen_type src_len)
+{
+ gfc_charlen_type n = fstrlen (src, src_len);
+ char *p = strndup (src, n);
+ if (!p)
+ os_error ("Memory allocation failed in fc_strdup");
+ return p;
+}
+
+
/* Given a fortran string and an array of st_option structures, search through
the array to find a match. If the option is not found, we generate an error
if no default is provided. */
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index efdeeabdb87..91c5d1c6a87 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -30,6 +30,8 @@ toolexeclibgodir = $(nover_glibgo_toolexeclibdir)/go/$(gcc_version)/$(target_ali
LIBFFI = @LIBFFI@
LIBFFIINCS = @LIBFFIINCS@
+LIBATOMIC = @LIBATOMIC@
+
WARN_CFLAGS = $(WARN_FLAGS) $(WERROR)
# -I/-D flags to pass when compiling.
@@ -1949,8 +1951,7 @@ libgo_la_LDFLAGS = \
libgo_la_LIBADD = \
$(libgo_go_objs) ../libbacktrace/libbacktrace.la \
- ../libatomic/libatomic_convenience.la \
- $(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS)
+ $(LIBATOMIC) $(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS)
libgobegin_a_SOURCES = \
runtime/go-main.c
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 1b3aedf248f..53299835eab 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -171,10 +171,9 @@ am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo crypto.lo \
testing/iotest.lo testing/quick.lo unicode/utf16.lo \
unicode/utf8.lo
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \
- ../libbacktrace/libbacktrace.la \
- ../libatomic/libatomic_convenience.la $(am__DEPENDENCIES_1) \
+ ../libbacktrace/libbacktrace.la $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
@LIBGO_IS_LINUX_FALSE@am__objects_1 = lock_sema.lo thread-sema.lo
@LIBGO_IS_LINUX_TRUE@am__objects_1 = lock_futex.lo thread-linux.lo
@HAVE_SYS_MMAN_H_FALSE@am__objects_2 = mem_posix_memalign.lo
@@ -316,6 +315,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
+LIBATOMIC = @LIBATOMIC@
LIBFFI = @LIBFFI@
LIBFFIINCS = @LIBFFIINCS@
LIBOBJS = @LIBOBJS@
@@ -2020,8 +2020,7 @@ libgo_la_LDFLAGS = \
libgo_la_LIBADD = \
$(libgo_go_objs) ../libbacktrace/libbacktrace.la \
- ../libatomic/libatomic_convenience.la \
- $(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS)
+ $(LIBATOMIC) $(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS)
libgobegin_a_SOURCES = \
runtime/go-main.c
diff --git a/libgo/config.h.in b/libgo/config.h.in
index ca5dcb22587..9e622c64ff3 100644
--- a/libgo/config.h.in
+++ b/libgo/config.h.in
@@ -192,6 +192,9 @@
/* Define to 1 if you have the `renameat' function. */
#undef HAVE_RENAMEAT
+/* Define to 1 if you have the <sched.h> header file. */
+#undef HAVE_SCHED_H
+
/* Define to 1 if you have the `sem_timedwait' function. */
#undef HAVE_SEM_TIMEDWAIT
diff --git a/libgo/configure b/libgo/configure
index c477021f4e7..22f935200cc 100755
--- a/libgo/configure
+++ b/libgo/configure
@@ -676,6 +676,7 @@ LIBGO_IS_FREEBSD_TRUE
LIBGO_IS_DARWIN_FALSE
LIBGO_IS_DARWIN_TRUE
go_include
+LIBATOMIC
LIBFFIINCS
LIBFFI
nover_glibgo_toolexeclibdir
@@ -817,6 +818,7 @@ enable_libtool_lock
enable_werror
enable_version_specific_runtime_libs
with_libffi
+with_libatomic
with_system_libunwind
enable_sjlj_exceptions
'
@@ -1469,6 +1471,7 @@ Optional Packages:
--with-pic try to use only PIC/non-PIC objects [default=use
both]
--without-libffi don't use libffi
+ --without-libatomic don't use libatomic
--with-system-libunwind use installed libunwind
Some influential environment variables:
@@ -11115,7 +11118,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11118 "configure"
+#line 11121 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11221,7 +11224,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11224 "configure"
+#line 11227 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -13483,6 +13486,24 @@ fi
+# See if the user wants to configure without libatomic. This is useful if we are
+# on an architecture for which libgo does not need an atomic support library and
+# libatomic does not support our C compiler.
+
+# Check whether --with-libatomic was given.
+if test "${with_libatomic+set}" = set; then :
+ withval=$with_libatomic; :
+else
+ with_libatomic=${with_libatomic_default-yes}
+fi
+
+
+LIBATOMIC=
+if test "$with_libatomic" != no; then
+ LIBATOMIC=../libatomic/libatomic_convenience.la
+fi
+
+
# Used to tell GNU make to include a file without telling automake to
# include it.
go_include="-include"
@@ -14622,7 +14643,7 @@ no)
;;
esac
-for ac_header in sys/file.h sys/mman.h syscall.h sys/epoll.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/reboot.h netinet/icmp6.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h
+for ac_header in sched.h sys/file.h sys/mman.h syscall.h sys/epoll.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/reboot.h netinet/icmp6.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
diff --git a/libgo/configure.ac b/libgo/configure.ac
index e4e4b602790..1f5aea8c676 100644
--- a/libgo/configure.ac
+++ b/libgo/configure.ac
@@ -122,6 +122,21 @@ fi
AC_SUBST(LIBFFI)
AC_SUBST(LIBFFIINCS)
+# See if the user wants to configure without libatomic. This is useful if we are
+# on an architecture for which libgo does not need an atomic support library and
+# libatomic does not support our C compiler.
+AC_ARG_WITH(libatomic,
+ AS_HELP_STRING([--without-libatomic],
+ [don't use libatomic]),
+ [:],
+ [with_libatomic=${with_libatomic_default-yes}])
+
+LIBATOMIC=
+if test "$with_libatomic" != no; then
+ LIBATOMIC=../libatomic/libatomic_convenience.la
+fi
+AC_SUBST(LIBATOMIC)
+
# Used to tell GNU make to include a file without telling automake to
# include it.
go_include="-include"
@@ -475,7 +490,7 @@ no)
;;
esac
-AC_CHECK_HEADERS(sys/file.h sys/mman.h syscall.h sys/epoll.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/reboot.h netinet/icmp6.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h)
+AC_CHECK_HEADERS(sched.h sys/file.h sys/mman.h syscall.h sys/epoll.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/reboot.h netinet/icmp6.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h)
AC_CHECK_HEADERS([linux/filter.h linux/if_addr.h linux/if_ether.h linux/if_tun.h linux/netlink.h linux/rtnetlink.h], [], [],
[#ifdef HAVE_SYS_SOCKET_H
diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh
index 025729ccad1..bb6abfd04b0 100755
--- a/libgo/mksysinfo.sh
+++ b/libgo/mksysinfo.sh
@@ -163,6 +163,9 @@ cat > sysinfo.c <<EOF
#if defined(HAVE_NETINET_ICMP6_H)
#include <netinet/icmp6.h>
#endif
+#if defined(HAVE_SCHED_H)
+#include <sched.h>
+#endif
/* Constants that may only be defined as expressions on some systems,
expressions too complex for -fdump-go-spec to handle. These are
@@ -177,6 +180,18 @@ enum {
#ifdef TIOCSCTTY
TIOCSCTTY_val = TIOCSCTTY,
#endif
+#ifdef TIOCGPTN
+ TIOCGPTN_val = TIOCGPTN,
+#endif
+#ifdef TIOCSPTLCK
+ TIOCSPTLCK_val = TIOCSPTLCK,
+#endif
+#ifdef TIOCGDEV
+ TIOCGDEV_val = TIOCGDEV,
+#endif
+#ifdef TIOCSIG
+ TIOCSIG_val = TIOCSIG,
+#endif
};
EOF
@@ -775,6 +790,26 @@ if ! grep '^const TIOCSCTTY' ${OUT} >/dev/null 2>&1; then
echo 'const TIOCSCTTY = _TIOCSCTTY_val' >> ${OUT}
fi
fi
+if ! grep '^const TIOCGPTN' ${OUT} >/dev/null 2>&1; then
+ if grep '^const _TIOCGPTN_val' ${OUT} >/dev/null 2>&1; then
+ echo 'const TIOCGPTN = _TIOCGPTN_val' >> ${OUT}
+ fi
+fi
+if ! grep '^const TIOCSPTLCK' ${OUT} >/dev/null 2>&1; then
+ if grep '^const _TIOCSPTLCK_val' ${OUT} >/dev/null 2>&1; then
+ echo 'const TIOCSPTLCK = _TIOCSPTLCK_val' >> ${OUT}
+ fi
+fi
+if ! grep '^const TIOCGDEV' ${OUT} >/dev/null 2>&1; then
+ if grep '^const _TIOCGDEV_val' ${OUT} >/dev/null 2>&1; then
+ echo 'const TIOCGDEV = _TIOCGDEV_val' >> ${OUT}
+ fi
+fi
+if ! grep '^const TIOCSIG' ${OUT} >/dev/null 2>&1; then
+ if grep '^const _TIOCSIG_val' ${OUT} >/dev/null 2>&1; then
+ echo 'const TIOCSIG = _TIOCSIG_val' >> ${OUT}
+ fi
+fi
# The ioctl flags for terminal control
grep '^const _TC[GS]ET' gen-sysinfo.go | \
@@ -1130,6 +1165,10 @@ grep '^type _inotify_event ' gen-sysinfo.go | \
-e 's/\[0\]byte/[0]int8/' \
>> ${OUT}
+# The GNU/Linux CLONE flags.
+grep '^const _CLONE_' gen-sysinfo.go | \
+ sed -e 's/^\(const \)_\(CLONE_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
# The Solaris 11 Update 1 _zone_net_addr_t struct.
grep '^type _zone_net_addr_t ' gen-sysinfo.go | \
sed -e 's/_in6_addr/[16]byte/' \
diff --git a/libgo/runtime/go-cdiv.c b/libgo/runtime/go-cdiv.c
index 0a81e458c84..0355e26fc8e 100644
--- a/libgo/runtime/go-cdiv.c
+++ b/libgo/runtime/go-cdiv.c
@@ -4,6 +4,9 @@
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */
+#include <complex.h>
+#include <math.h>
+
/* Calls to these functions are generated by the Go frontend for
division of complex64 or complex128. We use these because Go's
complex division expects slightly different results from the GCC
@@ -13,33 +16,33 @@
the the whole number is Inf, but an operation involving NaN ought
to result in NaN, not Inf. */
-__complex float
-__go_complex64_div (__complex float a, __complex float b)
+complex float
+__go_complex64_div (complex float a, complex float b)
{
- if (__builtin_expect (b == 0+0i, 0))
+ if (__builtin_expect (b == 0, 0))
{
- if (!__builtin_isinff (__real__ a)
- && !__builtin_isinff (__imag__ a)
- && (__builtin_isnanf (__real__ a) || __builtin_isnanf (__imag__ a)))
+ if (!isinf (crealf (a))
+ && !isinf (cimagf (a))
+ && (isnan (crealf (a)) || isnan (cimagf (a))))
{
/* Pass "1" to nanf to match math/bits.go. */
- return __builtin_nanf("1") + __builtin_nanf("1")*1i;
+ return nanf("1") + nanf("1")*I;
}
}
return a / b;
}
-__complex double
-__go_complex128_div (__complex double a, __complex double b)
+complex double
+__go_complex128_div (complex double a, complex double b)
{
- if (__builtin_expect (b == 0+0i, 0))
+ if (__builtin_expect (b == 0, 0))
{
- if (!__builtin_isinf (__real__ a)
- && !__builtin_isinf (__imag__ a)
- && (__builtin_isnan (__real__ a) || __builtin_isnan (__imag__ a)))
+ if (!isinf (creal (a))
+ && !isinf (cimag (a))
+ && (isnan (creal (a)) || isnan (cimag (a))))
{
/* Pass "1" to nan to match math/bits.go. */
- return __builtin_nan("1") + __builtin_nan("1")*1i;
+ return nan("1") + nan("1")*I;
}
}
return a / b;
diff --git a/libgo/runtime/go-type-complex.c b/libgo/runtime/go-type-complex.c
index 106024f5c88..0f8f0627d73 100644
--- a/libgo/runtime/go-type-complex.c
+++ b/libgo/runtime/go-type-complex.c
@@ -4,13 +4,13 @@
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */
+#include <complex.h>
+#include <math.h>
+#include <stdint.h>
+#include <string.h>
#include "runtime.h"
#include "go-type.h"
-/* The 64-bit type. */
-
-typedef unsigned int DItype __attribute__ ((mode (DI)));
-
/* Hash function for float types. */
uintptr_t
@@ -18,69 +18,67 @@ __go_type_hash_complex (const void *vkey, uintptr_t key_size)
{
if (key_size == 8)
{
- union
- {
- unsigned char a[8];
- __complex float cf;
- DItype di;
- } ucf;
- __complex float cf;
+ const complex float *cfp;
+ complex float cf;
float cfr;
float cfi;
+ uint64_t fi;
+
+ cfp = (const complex float *) vkey;
+ cf = *cfp;
+
+ cfr = crealf (cf);
+ cfi = cimagf (cf);
- __builtin_memcpy (ucf.a, vkey, 8);
- cf = ucf.cf;
- cfr = __builtin_crealf (cf);
- cfi = __builtin_cimagf (cf);
- if (__builtin_isinff (cfr) || __builtin_isinff (cfi))
+ if (isinf (cfr) || isinf (cfi))
return 0;
/* NaN != NaN, so the hash code of a NaN is irrelevant. Make it
random so that not all NaNs wind up in the same place. */
- if (__builtin_isnanf (cfr) || __builtin_isnanf (cfi))
+ if (isnan (cfr) || isnan (cfi))
return runtime_fastrand1 ();
/* Avoid negative zero. */
if (cfr == 0 && cfi == 0)
return 0;
else if (cfr == 0)
- ucf.cf = cfi * 1.0iF;
+ cf = cfi * I;
else if (cfi == 0)
- ucf.cf = cfr;
+ cf = cfr;
- return ucf.di;
+ memcpy (&fi, &cf, 8);
+ return (uintptr_t) cfi;
}
else if (key_size == 16)
{
- union
- {
- unsigned char a[16];
- __complex double cd;
- DItype adi[2];
- } ucd;
- __complex double cd;
+ const complex double *cdp;
+ complex double cd;
double cdr;
double cdi;
+ uint64_t di[2];
- __builtin_memcpy (ucd.a, vkey, 16);
- cd = ucd.cd;
- cdr = __builtin_crealf (cd);
- cdi = __builtin_cimagf (cd);
- if (__builtin_isinf (cdr) || __builtin_isinf (cdi))
+ cdp = (const complex double *) vkey;
+ cd = *cdp;
+
+ cdr = creal (cd);
+ cdi = cimag (cd);
+
+ if (isinf (cdr) || isinf (cdi))
return 0;
- if (__builtin_isnan (cdr) || __builtin_isnan (cdi))
+ if (isnan (cdr) || isnan (cdi))
return runtime_fastrand1 ();
/* Avoid negative zero. */
if (cdr == 0 && cdi == 0)
return 0;
else if (cdr == 0)
- ucd.cd = cdi * 1.0i;
+ cd = cdi * I;
else if (cdi == 0)
- ucd.cd = cdr;
+ cd = cdr;
- return ucd.adi[0] ^ ucd.adi[1];
+ memcpy (&di, &cd, 16);
+ return di[0] ^ di[1];
}
else
runtime_throw ("__go_type_hash_complex: invalid complex size");
@@ -93,35 +91,23 @@ __go_type_equal_complex (const void *vk1, const void *vk2, uintptr_t key_size)
{
if (key_size == 8)
{
- union
- {
- unsigned char a[8];
- __complex float cf;
- } ucf;
- __complex float cf1;
- __complex float cf2;
-
- __builtin_memcpy (ucf.a, vk1, 8);
- cf1 = ucf.cf;
- __builtin_memcpy (ucf.a, vk2, 8);
- cf2 = ucf.cf;
- return cf1 == cf2;
+ const complex float *cfp1;
+ const complex float *cfp2;
+
+ cfp1 = (const complex float *) vk1;
+ cfp2 = (const complex float *) vk2;
+
+ return *cfp1 == *cfp2;
}
else if (key_size == 16)
{
- union
- {
- unsigned char a[16];
- __complex double cd;
- } ucd;
- __complex double cd1;
- __complex double cd2;
-
- __builtin_memcpy (ucd.a, vk1, 16);
- cd1 = ucd.cd;
- __builtin_memcpy (ucd.a, vk2, 16);
- cd2 = ucd.cd;
- return cd1 == cd2;
+ const complex double *cdp1;
+ const complex double *cdp2;
+
+ cdp1 = (const complex double *) vk1;
+ cdp2 = (const complex double *) vk2;
+
+ return *cdp1 == *cdp2;
}
else
runtime_throw ("__go_type_equal_complex: invalid complex size");
diff --git a/libgo/runtime/go-type-float.c b/libgo/runtime/go-type-float.c
index e1c03e42843..4ae73470de9 100644
--- a/libgo/runtime/go-type-float.c
+++ b/libgo/runtime/go-type-float.c
@@ -4,14 +4,11 @@
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */
+#include <math.h>
+#include <stdint.h>
#include "runtime.h"
#include "go-type.h"
-/* The 32-bit and 64-bit types. */
-
-typedef unsigned int SItype __attribute__ ((mode (SI)));
-typedef unsigned int DItype __attribute__ ((mode (DI)));
-
/* Hash function for float types. */
uintptr_t
@@ -19,45 +16,41 @@ __go_type_hash_float (const void *vkey, uintptr_t key_size)
{
if (key_size == 4)
{
- union
- {
- unsigned char a[4];
- float f;
- SItype si;
- } uf;
+ const float *fp;
float f;
+ uint32_t si;
- __builtin_memcpy (uf.a, vkey, 4);
- f = uf.f;
- if (__builtin_isinff (f) || f == 0)
+ fp = (const float *) vkey;
+ f = *fp;
+
+ if (isinf (f) || f == 0)
return 0;
/* NaN != NaN, so the hash code of a NaN is irrelevant. Make it
random so that not all NaNs wind up in the same place. */
- if (__builtin_isnanf (f))
+ if (isnan (f))
return runtime_fastrand1 ();
- return (uintptr_t) uf.si;
+ memcpy (&si, vkey, 4);
+ return (uintptr_t) si;
}
else if (key_size == 8)
{
- union
- {
- unsigned char a[8];
- double d;
- DItype di;
- } ud;
+ const double *dp;
double d;
+ uint64_t di;
+
+ dp = (const double *) vkey;
+ d = *dp;
- __builtin_memcpy (ud.a, vkey, 8);
- d = ud.d;
- if (__builtin_isinf (d) || d == 0)
+ if (isinf (d) || d == 0)
return 0;
- if (__builtin_isnan (d))
+ if (isnan (d))
return runtime_fastrand1 ();
- return (uintptr_t) ud.di;
+ memcpy (&di, vkey, 8);
+ return (uintptr_t) di;
}
else
runtime_throw ("__go_type_hash_float: invalid float size");
@@ -70,36 +63,23 @@ __go_type_equal_float (const void *vk1, const void *vk2, uintptr_t key_size)
{
if (key_size == 4)
{
- union
- {
- unsigned char a[4];
- float f;
- } uf;
- float f1;
- float f2;
-
- __builtin_memcpy (uf.a, vk1, 4);
- f1 = uf.f;
- __builtin_memcpy (uf.a, vk2, 4);
- f2 = uf.f;
- return f1 == f2;
+ const float *fp1;
+ const float *fp2;
+
+ fp1 = (const float *) vk1;
+ fp2 = (const float *) vk2;
+
+ return *fp1 == *fp2;
}
else if (key_size == 8)
{
- union
- {
- unsigned char a[8];
- double d;
- DItype di;
- } ud;
- double d1;
- double d2;
-
- __builtin_memcpy (ud.a, vk1, 8);
- d1 = ud.d;
- __builtin_memcpy (ud.a, vk2, 8);
- d2 = ud.d;
- return d1 == d2;
+ const double *dp1;
+ const double *dp2;
+
+ dp1 = (const double *) vk1;
+ dp2 = (const double *) vk2;
+
+ return *dp1 == *dp2;
}
else
runtime_throw ("__go_type_equal_float: invalid float size");
diff --git a/libgo/runtime/print.c b/libgo/runtime/print.c
index 766ddbdc499..ba0b86a2c56 100644
--- a/libgo/runtime/print.c
+++ b/libgo/runtime/print.c
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <complex.h>
+#include <math.h>
#include <stdarg.h>
#include "runtime.h"
#include "array.h"
@@ -9,7 +11,9 @@
//static Lock debuglock;
-static void go_vprintf(const char*, va_list);
+// Clang requires this function to not be inlined (see below).
+static void go_vprintf(const char*, va_list)
+__attribute__((noinline));
// write to goroutine-local buffer if diverting output,
// or else standard error.
@@ -59,6 +63,24 @@ runtime_prints(const char *s)
gwrite(s, runtime_findnull((const byte*)s));
}
+#if defined (__clang__) && (defined (__i386__) || defined (__x86_64__))
+// LLVM's code generator does not currently support split stacks for vararg
+// functions, so we disable the feature for this function under Clang. This
+// appears to be OK as long as:
+// - this function only calls non-inlined, internal-linkage (hence no dynamic
+// loader) functions compiled with split stacks (i.e. go_vprintf), which can
+// allocate more stack space as required;
+// - this function itself does not occupy more than BACKOFF bytes of stack space
+// (see libgcc/config/i386/morestack.S).
+// These conditions are currently known to be satisfied by Clang on x86-32 and
+// x86-64. Note that signal handlers receive slightly less stack space than they
+// would normally do if they happen to be called while this function is being
+// run. If this turns out to be a problem we could consider increasing BACKOFF.
+void
+runtime_printf(const char *s, ...)
+__attribute__((no_split_stack));
+#endif
+
void
runtime_printf(const char *s, ...)
{
@@ -105,7 +127,7 @@ go_vprintf(const char *s, va_list va)
runtime_printfloat(va_arg(va, float64));
break;
case 'C':
- runtime_printcomplex(va_arg(va, __complex double));
+ runtime_printcomplex(va_arg(va, complex double));
break;
case 'i':
runtime_printiface(va_arg(va, Iface));
@@ -174,13 +196,12 @@ runtime_printfloat(double v)
gwrite("NaN", 3);
return;
}
- i = __builtin_isinf_sign(v);
- if(i > 0) {
- gwrite("+Inf", 4);
- return;
- }
- if(i < 0) {
- gwrite("-Inf", 4);
+ if(isinf(v)) {
+ if(signbit(v)) {
+ gwrite("-Inf", 4);
+ } else {
+ gwrite("+Inf", 4);
+ }
return;
}
@@ -243,11 +264,11 @@ runtime_printfloat(double v)
}
void
-runtime_printcomplex(__complex double v)
+runtime_printcomplex(complex double v)
{
gwrite("(", 1);
- runtime_printfloat(__builtin_creal(v));
- runtime_printfloat(__builtin_cimag(v));
+ runtime_printfloat(creal(v));
+ runtime_printfloat(cimag(v));
gwrite("i)", 2);
}
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index ed0c1a03ba6..c627ac1d5d3 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -1117,7 +1117,8 @@ runtime_needm(void)
if(runtime_needextram) {
// Can happen if C/C++ code calls Go from a global ctor.
// Can not throw, because scheduler is not initialized yet.
- runtime_write(2, "fatal error: cgo callback before cgo call\n",
+ int rv __attribute__((unused));
+ rv = runtime_write(2, "fatal error: cgo callback before cgo call\n",
sizeof("fatal error: cgo callback before cgo call\n")-1);
runtime_exit(1);
}
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index da2416335ec..7a578502176 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -5,6 +5,7 @@
#include "config.h"
#include "go-assert.h"
+#include <complex.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -710,7 +711,7 @@ void runtime_printpointer(void*);
void runtime_printuint(uint64);
void runtime_printhex(uint64);
void runtime_printslice(Slice);
-void runtime_printcomplex(__complex double);
+void runtime_printcomplex(complex double);
void reflect_call(const struct __go_func_type *, FuncVal *, _Bool, _Bool,
void **, void **)
__asm__ (GOSYM_PREFIX "reflect.call");
diff --git a/libgo/runtime/yield.c b/libgo/runtime/yield.c
index 5c47719d48f..442d346db7d 100644
--- a/libgo/runtime/yield.c
+++ b/libgo/runtime/yield.c
@@ -14,6 +14,10 @@
#include <sys/select.h>
#endif
+#if defined (__i386__) || defined (__x86_64__)
+#include <xmmintrin.h>
+#endif
+
#include "runtime.h"
/* Spin wait. */
@@ -26,7 +30,7 @@ runtime_procyield (uint32 cnt)
for (i = 0; i < cnt; ++i)
{
#if defined (__i386__) || defined (__x86_64__)
- __builtin_ia32_pause ();
+ _mm_pause ();
#endif
}
}
diff --git a/libgo/testsuite/Makefile.in b/libgo/testsuite/Makefile.in
index 8f0e2ad9337..7f7fb74c589 100644
--- a/libgo/testsuite/Makefile.in
+++ b/libgo/testsuite/Makefile.in
@@ -96,6 +96,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
+LIBATOMIC = @LIBATOMIC@
LIBFFI = @LIBFFI@
LIBFFIINCS = @LIBFFIINCS@
LIBOBJS = @LIBOBJS@
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index c73e60ba2da..5eb8cc90ce3 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,40 @@
+2014-05-27 Uros Bizjak <ubizjak@gmail.com>
+
+ * testsuite/libgomp.fortran/declare-simd-1.f90: Require
+ vect_simd_clones effective target.
+ * testsuite/libgomp.fortran/declare-simd-2.f90: Ditto.
+
+2014-05-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/61252
+ * testsuite/libgomp.c++/simd-9.C: New test.
+
+2014-05-18 Uros Bizjak <ubizjak@gmail.com>
+
+ * libgomp.texi (Runitme Library Routines): Remove multiple @menu.
+ (Environment Variables) Move OMP_PROC_BIND and OMP_STACKSIZE node
+ texts according to their @menu entry positions.
+
+2014-05-11 Jakub Jelinek <jakub@redhat.com>
+
+ * testsuite/libgomp.fortran/cancel-do-1.f90: New test.
+ * testsuite/libgomp.fortran/cancel-do-2.f90: New test.
+ * testsuite/libgomp.fortran/cancel-parallel-1.f90: New test.
+ * testsuite/libgomp.fortran/cancel-parallel-3.f90: New test.
+ * testsuite/libgomp.fortran/cancel-sections-1.f90: New test.
+ * testsuite/libgomp.fortran/cancel-taskgroup-2.f90: New test.
+ * testsuite/libgomp.fortran/declare-simd-1.f90: New test.
+ * testsuite/libgomp.fortran/declare-simd-2.f90: New test.
+ * testsuite/libgomp.fortran/declare-simd-3.f90: New test.
+ * testsuite/libgomp.fortran/depend-1.f90: New test.
+ * testsuite/libgomp.fortran/depend-2.f90: New test.
+ * testsuite/libgomp.fortran/omp_atomic5.f90: New test.
+ * testsuite/libgomp.fortran/simd1.f90: New test.
+ * testsuite/libgomp.fortran/simd2.f90: New test.
+ * testsuite/libgomp.fortran/simd3.f90: New test.
+ * testsuite/libgomp.fortran/simd4.f90: New test.
+ * testsuite/libgomp.fortran/taskgroup1.f90: New test.
+
2014-05-02 Jakub Jelinek <jakub@redhat.com>
* testsuite/libgomp.c/simd-10.c: New test.
diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index 8461c5b0c7c..254be57b8a1 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -130,10 +130,10 @@ The runtime routines described here are defined by Section 3 of the OpenMP
specification in version 4.0. The routines are structured in following
three parts:
+@menu
Control threads, processors and the parallel environment. They have C
linkage, and do not throw exceptions.
-@menu
* omp_get_active_level:: Number of active parallel regions
* omp_get_ancestor_thread_num:: Ancestor thread ID
* omp_get_cancellation:: Whether cancellation support is enabled
@@ -162,11 +162,9 @@ linkage, and do not throw exceptions.
* omp_set_nested:: Enable/disable nested parallel regions
* omp_set_num_threads:: Set upper team size limit
* omp_set_schedule:: Set the runtime scheduling method
-@end menu
Initialize, set, test, unset and destroy simple and nested locks.
-@menu
* omp_init_lock:: Initialize simple lock
* omp_set_lock:: Wait for and set simple lock
* omp_test_lock:: Test and set simple lock if available
@@ -177,11 +175,9 @@ Initialize, set, test, unset and destroy simple and nested locks.
* omp_test_nest_lock:: Test and set nested lock if available
* omp_unset_nest_lock:: Unset nested lock
* omp_destroy_nest_lock:: Destroy nested lock
-@end menu
Portable, thread-based, wall clock timer.
-@menu
* omp_get_wtick:: Get timer precision.
* omp_get_wtime:: Elapsed wall clock time.
@end menu
@@ -1448,6 +1444,33 @@ level. If undefined one thread per CPU is used.
+@node OMP_PROC_BIND
+@section @env{OMP_PROC_BIND} -- Whether theads may be moved between CPUs
+@cindex Environment Variable
+@table @asis
+@item @emph{Description}:
+Specifies whether threads may be moved between processors. If set to
+@code{TRUE}, OpenMP theads should not be moved; if set to @code{FALSE}
+they may be moved. Alternatively, a comma separated list with the
+values @code{MASTER}, @code{CLOSE} and @code{SPREAD} can be used to specify
+the thread affinity policy for the corresponding nesting level. With
+@code{MASTER} the worker threads are in the same place partition as the
+master thread. With @code{CLOSE} those are kept close to the master thread
+in contiguous place partitions. And with @code{SPREAD} a sparse distribution
+across the place partitions is used.
+
+When undefined, @env{OMP_PROC_BIND} defaults to @code{TRUE} when
+@env{OMP_PLACES} or @env{GOMP_CPU_AFFINITY} is set and @code{FALSE} otherwise.
+
+@item @emph{See also}:
+@ref{OMP_PLACES}, @ref{GOMP_CPU_AFFINITY}, @ref{omp_get_proc_bind}
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.4
+@end table
+
+
+
@node OMP_PLACES
@section @env{OMP_PLACES} -- Specifies on which CPUs the theads should be placed
@cindex Environment Variable
@@ -1490,29 +1513,22 @@ between CPUs following no placement policy.
-@node OMP_PROC_BIND
-@section @env{OMP_PROC_BIND} -- Whether theads may be moved between CPUs
+@node OMP_STACKSIZE
+@section @env{OMP_STACKSIZE} -- Set default thread stack size
@cindex Environment Variable
@table @asis
@item @emph{Description}:
-Specifies whether threads may be moved between processors. If set to
-@code{TRUE}, OpenMP theads should not be moved; if set to @code{FALSE}
-they may be moved. Alternatively, a comma separated list with the
-values @code{MASTER}, @code{CLOSE} and @code{SPREAD} can be used to specify
-the thread affinity policy for the corresponding nesting level. With
-@code{MASTER} the worker threads are in the same place partition as the
-master thread. With @code{CLOSE} those are kept close to the master thread
-in contiguous place partitions. And with @code{SPREAD} a sparse distribution
-across the place partitions is used.
-
-When undefined, @env{OMP_PROC_BIND} defaults to @code{TRUE} when
-@env{OMP_PLACES} or @env{GOMP_CPU_AFFINITY} is set and @code{FALSE} otherwise.
-
-@item @emph{See also}:
-@ref{OMP_PLACES}, @ref{GOMP_CPU_AFFINITY}, @ref{omp_get_proc_bind}
+Set the default thread stack size in kilobytes, unless the number
+is suffixed by @code{B}, @code{K}, @code{M} or @code{G}, in which
+case the size is, respectively, in bytes, kilobytes, megabytes
+or gigabytes. This is different from @code{pthread_attr_setstacksize}
+which gets the number of bytes as an argument. If the stack size cannot
+be set due to system constraints, an error is reported and the initial
+stack size is left unchanged. If undefined, the stack size is system
+dependent.
-@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.4
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.7
@end table
@@ -1538,26 +1554,6 @@ dynamic scheduling and a chunk size of 1 is used.
-@node OMP_STACKSIZE
-@section @env{OMP_STACKSIZE} -- Set default thread stack size
-@cindex Environment Variable
-@table @asis
-@item @emph{Description}:
-Set the default thread stack size in kilobytes, unless the number
-is suffixed by @code{B}, @code{K}, @code{M} or @code{G}, in which
-case the size is, respectively, in bytes, kilobytes, megabytes
-or gigabytes. This is different from @code{pthread_attr_setstacksize}
-which gets the number of bytes as an argument. If the stack size cannot
-be set due to system constraints, an error is reported and the initial
-stack size is left unchanged. If undefined, the stack size is system
-dependent.
-
-@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.7
-@end table
-
-
-
@node OMP_THREAD_LIMIT
@section @env{OMP_THREAD_LIMIT} -- Set the maximum number of threads
@cindex Environment Variable
diff --git a/libgomp/testsuite/libgomp.c++/simd-9.C b/libgomp/testsuite/libgomp.c++/simd-9.C
new file mode 100644
index 00000000000..3c567b31c3e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/simd-9.C
@@ -0,0 +1,52 @@
+// { dg-do run }
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+extern "C" void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+#pragma omp declare reduction (foo:int:omp_out += omp_in) \
+ initializer (omp_priv = 0)
+
+__attribute__((noinline, noclone)) void
+foo (int &u, int &v)
+{
+ int i;
+ #pragma omp simd aligned(a : 32) reduction(foo:u) reduction(+:v)
+ for (i = 0; i < 1024; i++)
+ {
+ int x = a[i];
+ u += x;
+ v += x;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+bar (int &u, int &v)
+{
+ int i;
+ #pragma omp simd aligned(a : 32) reduction(foo:u) reduction(+:v) \
+ safelen(1)
+ for (i = 0; i < 1024; i++)
+ {
+ int x = a[i];
+ u += x;
+ v += x;
+ }
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ a[i] = (i & 31) + (i / 128);
+ int u = 0, v = 0;
+ foo (u, v);
+ if (u != 19456 || v != 19456)
+ abort ();
+ u = 0; v = 0;
+ bar (u, v);
+ if (u != 19456 || v != 19456)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.fortran/cancel-do-1.f90 b/libgomp/testsuite/libgomp.fortran/cancel-do-1.f90
new file mode 100644
index 00000000000..61713c4dd94
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/cancel-do-1.f90
@@ -0,0 +1,14 @@
+! { dg-do run }
+! { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+ use omp_lib
+ integer :: i
+
+ !$omp parallel num_threads(32)
+ !$omp do
+ do i = 0, 999
+ !$omp cancel do
+ if (omp_get_cancellation ()) call abort
+ enddo
+ !$omp endparallel
+end
diff --git a/libgomp/testsuite/libgomp.fortran/cancel-do-2.f90 b/libgomp/testsuite/libgomp.fortran/cancel-do-2.f90
new file mode 100644
index 00000000000..c748800cad5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/cancel-do-2.f90
@@ -0,0 +1,90 @@
+! { dg-do run }
+! { dg-options "-fno-inline -fno-ipa-sra -fno-ipa-cp -fno-ipa-cp-clone" }
+! { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+ use omp_lib
+ integer :: i
+ logical :: x(5)
+
+ x(:) = .false.
+ x(1) = .true.
+ x(3) = .true.
+ if (omp_get_cancellation ()) call foo (x)
+contains
+ subroutine foo (x)
+ use omp_lib
+ logical :: x(5)
+ integer :: v, w, i
+
+ v = 0
+ w = 0
+ !$omp parallel num_threads (32) shared (v, w)
+ !$omp do
+ do i = 0, 999
+ !$omp cancel do if (x(1))
+ call abort
+ end do
+ !$omp do
+ do i = 0, 999
+ !$omp cancel do if (x(2))
+ !$omp atomic
+ v = v + 1
+ !$omp endatomic
+ enddo
+ !$omp do
+ do i = 0, 999
+ !$omp cancel do if (x(3))
+ !$omp atomic
+ w = w + 8
+ !$omp end atomic
+ end do
+ !$omp do
+ do i = 0, 999
+ !$omp cancel do if (x(4))
+ !$omp atomic
+ v = v + 2
+ !$omp end atomic
+ end do
+ !$omp end do
+ !$omp end parallel
+ if (v.ne.3000.or.w.ne.0) call abort
+ !$omp parallel num_threads (32) shared (v, w)
+ ! None of these cancel directives should actually cancel anything,
+ ! but the compiler shouldn't know that and thus should use cancellable
+ ! barriers at the end of all the workshares.
+ !$omp cancel parallel if (omp_get_thread_num ().eq.1.and.x(5))
+ !$omp do
+ do i = 0, 999
+ !$omp cancel do if (x(1))
+ call abort
+ end do
+ !$omp cancel parallel if (omp_get_thread_num ().eq.2.and.x(5))
+ !$omp do
+ do i = 0, 999
+ !$omp cancel do if (x(2))
+ !$omp atomic
+ v = v + 1
+ !$omp endatomic
+ enddo
+ !$omp cancel parallel if (omp_get_thread_num ().eq.3.and.x(5))
+ !$omp do
+ do i = 0, 999
+ !$omp cancel do if (x(3))
+ !$omp atomic
+ w = w + 8
+ !$omp end atomic
+ end do
+ !$omp cancel parallel if (omp_get_thread_num ().eq.4.and.x(5))
+ !$omp do
+ do i = 0, 999
+ !$omp cancel do if (x(4))
+ !$omp atomic
+ v = v + 2
+ !$omp end atomic
+ end do
+ !$omp end do
+ !$omp cancel parallel if (omp_get_thread_num ().eq.5.and.x(5))
+ !$omp end parallel
+ if (v.ne.6000.or.w.ne.0) call abort
+ end subroutine
+end
diff --git a/libgomp/testsuite/libgomp.fortran/cancel-parallel-1.f90 b/libgomp/testsuite/libgomp.fortran/cancel-parallel-1.f90
new file mode 100644
index 00000000000..7d91ff5c169
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/cancel-parallel-1.f90
@@ -0,0 +1,10 @@
+! { dg-do run }
+! { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+ use omp_lib
+
+ !$omp parallel num_threads(32)
+ !$omp cancel parallel
+ if (omp_get_cancellation ()) call abort
+ !$omp end parallel
+end
diff --git a/libgomp/testsuite/libgomp.fortran/cancel-parallel-3.f90 b/libgomp/testsuite/libgomp.fortran/cancel-parallel-3.f90
new file mode 100644
index 00000000000..9d5ba8ffa38
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/cancel-parallel-3.f90
@@ -0,0 +1,38 @@
+! { dg-do run }
+! { dg-options "-fno-inline -fno-ipa-sra -fno-ipa-cp -fno-ipa-cp-clone" }
+! { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+ use omp_lib
+ integer :: x, i, j
+ common /x/ x
+
+ call omp_set_dynamic (.false.)
+ call omp_set_schedule (omp_sched_static, 1)
+ !$omp parallel num_threads(16) private (i, j)
+ call do_some_work
+ !$omp barrier
+ if (omp_get_thread_num ().eq.1) then
+ call sleep (2)
+ !$omp cancellation point parallel
+ end if
+ do j = 3, 16
+ !$omp do schedule(runtime)
+ do i = 0, j - 1
+ call do_some_work
+ end do
+ !$omp enddo nowait
+ end do
+ if (omp_get_thread_num ().eq.0) then
+ call sleep (1)
+ !$omp cancel parallel
+ end if
+ !$omp end parallel
+contains
+ subroutine do_some_work
+ integer :: x
+ common /x/ x
+ !$omp atomic
+ x = x + 1
+ !$omp end atomic
+ endsubroutine do_some_work
+end
diff --git a/libgomp/testsuite/libgomp.fortran/cancel-sections-1.f90 b/libgomp/testsuite/libgomp.fortran/cancel-sections-1.f90
new file mode 100644
index 00000000000..9ba8af84679
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/cancel-sections-1.f90
@@ -0,0 +1,23 @@
+! { dg-do run }
+! { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+ use omp_lib
+
+ if (omp_get_cancellation ()) then
+ !$omp parallel num_threads(32)
+ !$omp sections
+ !$omp cancel sections
+ call abort
+ !$omp section
+ !$omp cancel sections
+ call abort
+ !$omp section
+ !$omp cancel sections
+ call abort
+ !$omp section
+ !$omp cancel sections
+ call abort
+ !$omp end sections
+ !$omp end parallel
+ end if
+end
diff --git a/libgomp/testsuite/libgomp.fortran/cancel-taskgroup-2.f90 b/libgomp/testsuite/libgomp.fortran/cancel-taskgroup-2.f90
new file mode 100644
index 00000000000..c727a20ae41
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/cancel-taskgroup-2.f90
@@ -0,0 +1,28 @@
+! { dg-do run }
+! { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+ use omp_lib
+ integer :: i
+
+ !$omp parallel
+ !$omp taskgroup
+ !$omp task
+ !$omp cancel taskgroup
+ call abort
+ !$omp endtask
+ !$omp endtaskgroup
+ !$omp endparallel
+ !$omp parallel private (i)
+ !$omp barrier
+ !$omp single
+ !$omp taskgroup
+ do i = 0, 49
+ !$omp task
+ !$omp cancellation point taskgroup
+ !$omp cancel taskgroup if (i.gt.5)
+ !$omp end task
+ end do
+ !$omp end taskgroup
+ !$omp endsingle
+ !$omp end parallel
+end
diff --git a/libgomp/testsuite/libgomp.fortran/declare-simd-1.f90 b/libgomp/testsuite/libgomp.fortran/declare-simd-1.f90
new file mode 100644
index 00000000000..b141a3b3eda
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/declare-simd-1.f90
@@ -0,0 +1,93 @@
+! { dg-do run { target vect_simd_clones } }
+! { dg-options "-fno-inline" }
+! { dg-additional-options "-msse2" { target sse2_runtime } }
+! { dg-additional-options "-mavx" { target avx_runtime } }
+
+module declare_simd_1_mod
+ contains
+ real function foo (a, b, c)
+ !$omp declare simd (foo) simdlen (4) uniform (a) linear (b : 5)
+ double precision, value :: a
+ real, value :: c
+ !$omp declare simd (foo)
+ integer, value :: b
+ foo = a + b * c
+ end function foo
+end module declare_simd_1_mod
+ use declare_simd_1_mod
+ interface
+ function bar (a, b, c)
+ !$omp declare simd (bar)
+ integer, value :: b
+ real, value :: c
+ real :: bar
+ !$omp declare simd (bar) simdlen (4) linear (b : 2)
+ double precision, value :: a
+ end function bar
+ end interface
+ integer :: i
+ double precision :: a(128)
+ real :: b(128), d(128)
+ data d /171., 414., 745., 1164., 1671., 2266., 2949., 3720., 4579., &
+ & 5526., 6561., 7684., 8895., 10194., 11581., 13056., 14619., &
+ & 16270., 18009., 19836., 21751., 23754., 25845., 28024., &
+ & 30291., 32646., 35089., 37620., 40239., 42946., 45741., &
+ & 48624., 51595., 54654., 57801., 61036., 64359., 67770., &
+ & 71269., 74856., 78531., 82294., 86145., 90084., 94111., &
+ & 98226., 102429., 106720., 111099., 115566., 120121., 124764., &
+ & 129495., 134314., 139221., 144216., 149299., 154470., 159729., &
+ & 165076., 170511., 176034., 181645., 187344., 193131., 199006., &
+ & 204969., 211020., 217159., 223386., 229701., 236104., 242595., &
+ & 249174., 255841., 262596., 269439., 276370., 283389., 290496., &
+ & 297691., 304974., 312345., 319804., 327351., 334986., 342709., &
+ & 350520., 358419., 366406., 374481., 382644., 390895., 399234., &
+ & 407661., 416176., 424779., 433470., 442249., 451116., 460071., &
+ & 469114., 478245., 487464., 496771., 506166., 515649., 525220., &
+ & 534879., 544626., 554461., 564384., 574395., 584494., 594681., &
+ & 604956., 615319., 625770., 636309., 646936., 657651., 668454., &
+ & 679345., 690324., 701391., 712546., 723789., 735120./
+ !$omp simd
+ do i = 1, 128
+ a(i) = 7.0 * i + 16.0
+ b(i) = 5.0 * i + 12.0
+ end do
+ !$omp simd
+ do i = 1, 128
+ b(i) = foo (a(i), 3, b(i))
+ end do
+ !$omp simd
+ do i = 1, 128
+ b(i) = bar (a(i), 2 * i, b(i))
+ end do
+ if (any (b.ne.d)) call abort
+ !$omp simd
+ do i = 1, 128
+ b(i) = i * 2.0
+ end do
+ !$omp simd
+ do i = 1, 128
+ b(i) = baz (7.0_8, 2, b(i))
+ end do
+ do i = 1, 128
+ if (b(i).ne.(7.0 + 4.0 * i)) call abort
+ end do
+contains
+ function baz (x, y, z)
+ !$omp declare simd (baz) simdlen (8) uniform (x, y)
+ !$omp declare simd (baz)
+ integer, value :: y
+ real, value :: z
+ real :: baz
+ double precision, value :: x
+ baz = x + y * z
+ end function baz
+end
+function bar (a, b, c)
+ integer, value :: b
+ real, value :: c
+ real :: bar
+ double precision, value :: a
+ !$omp declare simd (bar)
+ !$omp declare simd (bar) simdlen (4) linear (b : 2)
+ bar = a + b * c
+end function bar
diff --git a/libgomp/testsuite/libgomp.fortran/declare-simd-2.f90 b/libgomp/testsuite/libgomp.fortran/declare-simd-2.f90
new file mode 100644
index 00000000000..30c63f706ef
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/declare-simd-2.f90
@@ -0,0 +1,25 @@
+! { dg-do run { target vect_simd_clones } }
+! { dg-options "-fno-inline" }
+! { dg-additional-sources declare-simd-3.f90 }
+! { dg-additional-options "-msse2" { target sse2_runtime } }
+! { dg-additional-options "-mavx" { target avx_runtime } }
+
+module declare_simd_2_mod
+ contains
+ real function foo (a, b, c)
+ !$omp declare simd (foo) simdlen (4) uniform (a) linear (b : 5)
+ double precision, value :: a
+ real, value :: c
+ !$omp declare simd (foo)
+ integer, value :: b
+ foo = a + b * c
+ end function foo
+end module declare_simd_2_mod
+
+ interface
+ subroutine bar ()
+ end subroutine bar
+ end interface
+
+ call bar ()
+end
diff --git a/libgomp/testsuite/libgomp.fortran/declare-simd-3.f90 b/libgomp/testsuite/libgomp.fortran/declare-simd-3.f90
new file mode 100644
index 00000000000..031625ec435
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/declare-simd-3.f90
@@ -0,0 +1,22 @@
+! Don't compile this anywhere, it is just auxiliary
+! file compiled together with declare-simd-2.f90
+! to verify inter-CU module handling of omp declare simd.
+! { dg-do compile { target { lp64 && { ! lp64 } } } }
+
+subroutine bar
+ use declare_simd_2_mod
+ real :: b(128)
+ integer :: i
+
+ !$omp simd
+ do i = 1, 128
+ b(i) = i * 2.0
+ end do
+ !$omp simd
+ do i = 1, 128
+ b(i) = foo (7.0_8, 5 * i, b(i))
+ end do
+ do i = 1, 128
+ if (b(i).ne.(7.0 + 10.0 * i * i)) call abort
+ end do
+end subroutine bar
diff --git a/libgomp/testsuite/libgomp.fortran/depend-1.f90 b/libgomp/testsuite/libgomp.fortran/depend-1.f90
new file mode 100644
index 00000000000..030d3fb6a55
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/depend-1.f90
@@ -0,0 +1,203 @@
+! { dg-do run }
+
+ call dep ()
+ call dep2 ()
+ call dep3 ()
+ call firstpriv ()
+ call antidep ()
+ call antidep2 ()
+ call antidep3 ()
+ call outdep ()
+ call concurrent ()
+ call concurrent2 ()
+ call concurrent3 ()
+contains
+ subroutine dep
+ integer :: x
+ x = 1
+ !$omp parallel
+ !$omp single
+ !$omp task shared (x) depend(out: x)
+ x = 2
+ !$omp end task
+ !$omp task shared (x) depend(in: x)
+ if (x.ne.2) call abort
+ !$omp end task
+ !$omp end single
+ !$omp end parallel
+ end subroutine dep
+
+ subroutine dep2
+ integer :: x
+ !$omp parallel
+ !$omp single private (x)
+ x = 1
+ !$omp task shared (x) depend(out: x)
+ x = 2
+ !$omp end task
+ !$omp task shared (x) depend(in: x)
+ if (x.ne.2) call abort
+ !$omp end task
+ !$omp taskwait
+ !$omp end single
+ !$omp end parallel
+ end subroutine dep2
+
+ subroutine dep3
+ integer :: x
+ !$omp parallel private (x)
+ x = 1
+ !$omp single
+ !$omp task shared (x) depend(out: x)
+ x = 2
+ !$omp endtask
+ !$omp task shared (x) depend(in: x)
+ if (x.ne.2) call abort
+ !$omp endtask
+ !$omp endsingle
+ !$omp endparallel
+ end subroutine dep3
+
+ subroutine firstpriv
+ integer :: x
+ !$omp parallel private (x)
+ !$omp single
+ x = 1
+ !$omp task depend(out: x)
+ x = 2
+ !$omp end task
+ !$omp task depend(in: x)
+ if (x.ne.1) call abort
+ !$omp end task
+ !$omp end single
+ !$omp end parallel
+ end subroutine firstpriv
+
+ subroutine antidep
+ integer :: x
+ x = 1
+ !$omp parallel
+ !$omp single
+ !$omp task shared(x) depend(in: x)
+ if (x.ne.1) call abort
+ !$omp end task
+ !$omp task shared(x) depend(out: x)
+ x = 2
+ !$omp end task
+ !$omp end single
+ !$omp end parallel
+ end subroutine antidep
+
+ subroutine antidep2
+ integer :: x
+ !$omp parallel private (x)
+ !$omp single
+ x = 1
+ !$omp taskgroup
+ !$omp task shared(x) depend(in: x)
+ if (x.ne.1) call abort
+ !$omp end task
+ !$omp task shared(x) depend(out: x)
+ x = 2
+ !$omp end task
+ !$omp end taskgroup
+ !$omp end single
+ !$omp end parallel
+ end subroutine antidep2
+
+ subroutine antidep3
+ integer :: x
+ !$omp parallel
+ x = 1
+ !$omp single
+ !$omp task shared(x) depend(in: x)
+ if (x.ne.1) call abort
+ !$omp end task
+ !$omp task shared(x) depend(out: x)
+ x = 2
+ !$omp end task
+ !$omp end single
+ !$omp end parallel
+ end subroutine antidep3
+
+ subroutine outdep
+ integer :: x
+ !$omp parallel private (x)
+ !$omp single
+ x = 0
+ !$omp task shared(x) depend(out: x)
+ x = 1
+ !$omp end task
+ !$omp task shared(x) depend(out: x)
+ x = 2
+ !$omp end task
+ !$omp taskwait
+ if (x.ne.2) call abort
+ !$omp end single
+ !$omp end parallel
+ end subroutine outdep
+
+ subroutine concurrent
+ integer :: x
+ x = 1
+ !$omp parallel
+ !$omp single
+ !$omp task shared (x) depend(out: x)
+ x = 2
+ !$omp end task
+ !$omp task shared (x) depend(in: x)
+ if (x.ne.2) call abort
+ !$omp end task
+ !$omp task shared (x) depend(in: x)
+ if (x.ne.2) call abort
+ !$omp end task
+ !$omp task shared (x) depend(in: x)
+ if (x.ne.2) call abort
+ !$omp end task
+ !$omp end single
+ !$omp end parallel
+ end subroutine concurrent
+
+ subroutine concurrent2
+ integer :: x
+ !$omp parallel private (x)
+ !$omp single
+ x = 1
+ !$omp task shared (x) depend(out: x)
+ x = 2;
+ !$omp end task
+ !$omp task shared (x) depend(in: x)
+ if (x.ne.2) call abort
+ !$omp end task
+ !$omp task shared (x) depend(in: x)
+ if (x.ne.2) call abort
+ !$omp end task
+ !$omp task shared (x) depend(in: x)
+ if (x.ne.2) call abort
+ !$omp end task
+ !$omp taskwait
+ !$omp end single
+ !$omp end parallel
+ end subroutine concurrent2
+
+ subroutine concurrent3
+ integer :: x
+ !$omp parallel private (x)
+ x = 1
+ !$omp single
+ !$omp task shared (x) depend(out: x)
+ x = 2
+ !$omp end task
+ !$omp task shared (x) depend(in: x)
+ if (x.ne.2) call abort
+ !$omp end task
+ !$omp task shared (x) depend(in: x)
+ if (x.ne.2) call abort
+ !$omp end task
+ !$omp task shared (x) depend(in: x)
+ if (x.ne.2) call abort
+ !$omp end task
+ !$omp end single
+ !$omp end parallel
+ end subroutine concurrent3
+end
diff --git a/libgomp/testsuite/libgomp.fortran/depend-2.f90 b/libgomp/testsuite/libgomp.fortran/depend-2.f90
new file mode 100644
index 00000000000..0694ce74206
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/depend-2.f90
@@ -0,0 +1,34 @@
+! { dg-do run }
+
+ integer :: x(3:6, 7:12), y
+ y = 1
+ !$omp parallel shared (x, y)
+ !$omp single
+ !$omp taskgroup
+ !$omp task depend(in: x(:, :))
+ if (y.ne.1) call abort
+ !$omp end task
+ !$omp task depend(out: x(:, :))
+ y = 2
+ !$omp end task
+ !$omp end taskgroup
+ !$omp taskgroup
+ !$omp task depend(in: x(4, 7))
+ if (y.ne.2) call abort
+ !$omp end task
+ !$omp task depend(out: x(4:4, 7:7))
+ y = 3
+ !$omp end task
+ !$omp end taskgroup
+ !$omp taskgroup
+ !$omp task depend(in: x(4:, 8:))
+ if (y.ne.3) call abort
+ !$omp end task
+ !$omp task depend(out: x(4:6, 8:12))
+ y = 4
+ !$omp end task
+ !$omp end taskgroup
+ !$omp end single
+ !$omp end parallel
+ if (y.ne.4) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/omp_atomic5.f90 b/libgomp/testsuite/libgomp.fortran/omp_atomic5.f90
new file mode 100644
index 00000000000..8e0641592fd
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/omp_atomic5.f90
@@ -0,0 +1,59 @@
+! { dg-do run }
+ integer (kind = 4) :: a, a2
+ integer (kind = 2) :: b, b2
+ real :: c
+ double precision :: d, d2, c2
+ integer, dimension (10) :: e
+ e(:) = 5
+ e(7) = 9
+!$omp atomic write seq_cst
+ a = 1
+!$omp atomic seq_cst, write
+ b = 2
+!$omp atomic write, seq_cst
+ c = 3
+!$omp atomic seq_cst write
+ d = 4
+!$omp atomic capture seq_cst
+ a2 = a
+ a = a + 4
+!$omp end atomic
+!$omp atomic capture, seq_cst
+ b = b - 18
+ b2 = b
+!$omp end atomic
+!$omp atomic seq_cst, capture
+ c2 = c
+ c = 2.0 * c
+!$omp end atomic
+!$omp atomic seq_cst capture
+ d = d / 2.0
+ d2 = d
+!$omp end atomic
+ if (a2 .ne. 1 .or. b2 .ne. -16 .or. c2 .ne. 3 .or. d2 .ne. 2) call abort
+!$omp atomic read seq_cst
+ a2 = a
+!$omp atomic seq_cst, read
+ c2 = c
+ if (a2 .ne. 5 .or. b2 .ne. -16 .or. c2 .ne. 6 .or. d2 .ne. 2) call abort
+ a2 = 10
+ if (a2 .ne. 10) call abort
+!$omp atomic capture
+ a2 = a
+ a = e(1) + e(6) + e(7) * 2
+!$omp endatomic
+ if (a2 .ne. 5) call abort
+!$omp atomic read
+ a2 = a
+!$omp end atomic
+ if (a2 .ne. 28) call abort
+!$omp atomic capture seq_cst
+ b2 = b
+ b = e(1) + e(7) + e(5) * 2
+!$omp end atomic
+ if (b2 .ne. -16) call abort
+!$omp atomic seq_cst, read
+ b2 = b
+!$omp end atomic
+ if (b2 .ne. 24) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/simd1.f90 b/libgomp/testsuite/libgomp.fortran/simd1.f90
new file mode 100644
index 00000000000..abd63b0643f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/simd1.f90
@@ -0,0 +1,23 @@
+! { dg-do run }
+! { dg-additional-options "-msse2" { target sse2_runtime } }
+! { dg-additional-options "-mavx" { target avx_runtime } }
+
+ integer :: i, j, k, l, r, a(30)
+ integer, target :: q(30)
+ integer, pointer :: p(:)
+ a(:) = 1
+ q(:) = 1
+ p => q
+ r = 0
+ j = 10
+ k = 20
+ !$omp simd safelen (8) reduction(+:r) linear(j, k : 2) &
+ !$omp& private (l) aligned(p : 4)
+ do i = 1, 30
+ l = j + k + a(i) + p(i)
+ r = r + l
+ j = j + 2
+ k = k + 2
+ end do
+ if (r.ne.2700.or.j.ne.70.or.k.ne.80) call abort
+end
diff --git a/libgomp/testsuite/libgomp.fortran/simd2.f90 b/libgomp/testsuite/libgomp.fortran/simd2.f90
new file mode 100644
index 00000000000..9b90bcdd019
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/simd2.f90
@@ -0,0 +1,101 @@
+! { dg-do run }
+! { dg-additional-options "-msse2" { target sse2_runtime } }
+! { dg-additional-options "-mavx" { target avx_runtime } }
+
+ integer :: a(1024), b(1024), k, m, i, s, t
+ k = 4
+ m = 2
+ t = 1
+ do i = 1, 1024
+ a(i) = i - 513
+ b(i) = modulo (i - 52, 39)
+ if (i.lt.52.and.b(i).ne.0) b(i) = b(i) - 39
+ end do
+ s = foo (b)
+ do i = 1, 1024
+ if (a(i).ne.((i - 513) * b(i))) call abort
+ if (i.lt.52.and.modulo (i - 52, 39).ne.0) then
+ if (b(i).ne.(modulo (i - 52, 39) - 39)) call abort
+ else
+ if (b(i).ne.(modulo (i - 52, 39))) call abort
+ end if
+ a(i) = i - 513
+ end do
+ if (k.ne.(4 + 3 * 1024).or.s.ne.1596127) call abort
+ k = 4
+ m = 2
+ t = 1
+ s = bar (b)
+ do i = 1, 1024
+ if (a(i).ne.((i - 513) * b(i))) call abort
+ if (i.lt.52.and.modulo (i - 52, 39).ne.0) then
+ if (b(i).ne.(modulo (i - 52, 39) - 39)) call abort
+ else
+ if (b(i).ne.(modulo (i - 52, 39))) call abort
+ end if
+ a(i) = i - 513
+ end do
+ if (k.ne.(4 + 3 * 1024).or.s.ne.1596127) call abort
+ k = 4
+ m = 2
+ t = 1
+ s = baz (b)
+ do i = 1, 1024
+ if (a(i).ne.((i - 513) * b(i))) call abort
+ if (i.lt.52.and.modulo (i - 52, 39).ne.0) then
+ if (b(i).ne.(modulo (i - 52, 39) - 39)) call abort
+ else
+ if (b(i).ne.(modulo (i - 52, 39))) call abort
+ end if
+ end do
+ if (k.ne.(4 + 3 * 1024).or.s.ne.1596127) call abort
+contains
+ function foo (p)
+ integer :: p(1024), u, v, i, s, foo
+ s = 0
+ !$omp simd linear(k : m + 1) reduction(+: s) lastprivate(u, v)
+ do i = 1, 1024
+ a(i) = a(i) * p(i)
+ u = p(i) + k
+ k = k + m + 1
+ v = p(i) + k
+ s = s + p(i) + k
+ end do
+ !$omp end simd
+ if (i.ne.1025) call abort
+ if (u.ne.(36 + 4 + 3 * 1023).or.v.ne.(36 + 4 + 3 * 1024)) call abort
+ foo = s
+ end function foo
+ function bar (p)
+ integer :: p(1024), u, v, i, s, bar
+ s = 0
+ !$omp simd linear(k : m + 1) reduction(+: s) lastprivate(u, v)
+ do i = 1, 1024, t
+ a(i) = a(i) * p(i)
+ u = p(i) + k
+ k = k + m + 1
+ v = p(i) + k
+ s = s + p(i) + k
+ end do
+ !$omp end simd
+ if (i.ne.1025) call abort
+ if (u.ne.(36 + 4 + 3 * 1023).or.v.ne.(36 + 4 + 3 * 1024)) call abort
+ bar = s
+ end function bar
+ function baz (p)
+ integer :: p(1024), u, v, i, s, baz
+ s = 0
+ !$omp simd linear(k : m + 1) reduction(+: s) lastprivate(u, v) &
+ !$omp & linear(i : t)
+ do i = 1, 1024, t
+ a(i) = a(i) * p(i)
+ u = p(i) + k
+ k = k + m + 1
+ v = p(i) + k
+ s = s + p(i) + k
+ end do
+ if (i.ne.1025) call abort
+ if (u.ne.(36 + 4 + 3 * 1023).or.v.ne.(36 + 4 + 3 * 1024)) call abort
+ baz = s
+ end function baz
+end
diff --git a/libgomp/testsuite/libgomp.fortran/simd3.f90 b/libgomp/testsuite/libgomp.fortran/simd3.f90
new file mode 100644
index 00000000000..df9f4cac3fe
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/simd3.f90
@@ -0,0 +1,109 @@
+! { dg-do run }
+! { dg-additional-options "-msse2" { target sse2_runtime } }
+! { dg-additional-options "-mavx" { target avx_runtime } }
+
+ integer :: a(1024), b(1024), k, m, i, s, t
+ k = 4
+ m = 2
+ t = 1
+ do i = 1, 1024
+ a(i) = i - 513
+ b(i) = modulo (i - 52, 39)
+ if (i.lt.52.and.b(i).ne.0) b(i) = b(i) - 39
+ end do
+ s = foo (b)
+ do i = 1, 1024
+ if (a(i).ne.((i - 513) * b(i))) call abort
+ if (i.lt.52.and.modulo (i - 52, 39).ne.0) then
+ if (b(i).ne.(modulo (i - 52, 39) - 39)) call abort
+ else
+ if (b(i).ne.(modulo (i - 52, 39))) call abort
+ end if
+ a(i) = i - 513
+ end do
+ if (k.ne.(4 + 3 * 1024).or.s.ne.1596127) call abort
+ k = 4
+ m = 2
+ t = 1
+ s = bar (b)
+ do i = 1, 1024
+ if (a(i).ne.((i - 513) * b(i))) call abort
+ if (i.lt.52.and.modulo (i - 52, 39).ne.0) then
+ if (b(i).ne.(modulo (i - 52, 39) - 39)) call abort
+ else
+ if (b(i).ne.(modulo (i - 52, 39))) call abort
+ end if
+ a(i) = i - 513
+ end do
+ if (k.ne.(4 + 3 * 1024).or.s.ne.1596127) call abort
+ k = 4
+ m = 2
+ t = 1
+ s = baz (b)
+ do i = 1, 1024
+ if (a(i).ne.((i - 513) * b(i))) call abort
+ if (i.lt.52.and.modulo (i - 52, 39).ne.0) then
+ if (b(i).ne.(modulo (i - 52, 39) - 39)) call abort
+ else
+ if (b(i).ne.(modulo (i - 52, 39))) call abort
+ end if
+ end do
+ if (k.ne.(4 + 3 * 1024).or.s.ne.1596127) call abort
+contains
+ function foo (p)
+ integer :: p(1024), u, v, i, s, foo
+ s = 0
+ !$omp parallel
+ !$omp do simd linear(k : m + 1) reduction(+: s) lastprivate(u, v) &
+ !$omp & schedule (static, 32)
+ do i = 1, 1024
+ a(i) = a(i) * p(i)
+ u = p(i) + k
+ k = k + m + 1
+ v = p(i) + k
+ s = s + p(i) + k
+ end do
+ !$omp end do simd
+ !$omp end parallel
+ if (i.ne.1025) call abort
+ if (u.ne.(36 + 4 + 3 * 1023).or.v.ne.(36 + 4 + 3 * 1024)) call abort
+ foo = s
+ end function foo
+ function bar (p)
+ integer :: p(1024), u, v, i, s, bar
+ s = 0
+ !$omp parallel
+ !$omp do simd linear(k : m + 1) reduction(+: s) lastprivate(u, v) &
+ !$omp & schedule (dynamic, 32)
+ do i = 1, 1024, t
+ a(i) = a(i) * p(i)
+ u = p(i) + k
+ k = k + m + 1
+ v = p(i) + k
+ s = s + p(i) + k
+ end do
+ !$omp end do simd
+ !$omp endparallel
+ if (i.ne.1025) call abort
+ if (u.ne.(36 + 4 + 3 * 1023).or.v.ne.(36 + 4 + 3 * 1024)) call abort
+ bar = s
+ end function bar
+ function baz (p)
+ integer :: p(1024), u, v, i, s, baz
+ s = 0
+ !$omp parallel
+ !$omp do simd linear(k : m + 1) reduction(+: s) lastprivate(u, v) &
+ !$omp & linear(i : t) schedule (static, 8)
+ do i = 1, 1024, t
+ a(i) = a(i) * p(i)
+ u = p(i) + k
+ k = k + m + 1
+ v = p(i) + k
+ s = s + p(i) + k
+ end do
+ !$omp end parallel
+ if (i.ne.1025) call abort
+ if (u.ne.(36 + 4 + 3 * 1023).or.v.ne.(36 + 4 + 3 * 1024)) call abort
+ baz = s
+ end function baz
+end
diff --git a/libgomp/testsuite/libgomp.fortran/simd4.f90 b/libgomp/testsuite/libgomp.fortran/simd4.f90
new file mode 100644
index 00000000000..a5b8ba0babd
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/simd4.f90
@@ -0,0 +1,103 @@
+! { dg-do run }
+! { dg-additional-options "-msse2" { target sse2_runtime } }
+! { dg-additional-options "-mavx" { target avx_runtime } }
+
+ integer :: a(1024), b(1024), k, m, i, s, t
+ k = 4
+ m = 2
+ t = 1
+ do i = 1, 1024
+ a(i) = i - 513
+ b(i) = modulo (i - 52, 39)
+ if (i.lt.52.and.b(i).ne.0) b(i) = b(i) - 39
+ end do
+ s = foo (b)
+ do i = 1, 1024
+ if (a(i).ne.((i - 513) * b(i))) call abort
+ if (i.lt.52.and.modulo (i - 52, 39).ne.0) then
+ if (b(i).ne.(modulo (i - 52, 39) - 39)) call abort
+ else
+ if (b(i).ne.(modulo (i - 52, 39))) call abort
+ end if
+ a(i) = i - 513
+ end do
+ if (k.ne.(4 + 3 * 1024).or.s.ne.1596127) call abort
+ k = 4
+ m = 2
+ t = 1
+ s = bar (b)
+ do i = 1, 1024
+ if (a(i).ne.((i - 513) * b(i))) call abort
+ if (i.lt.52.and.modulo (i - 52, 39).ne.0) then
+ if (b(i).ne.(modulo (i - 52, 39) - 39)) call abort
+ else
+ if (b(i).ne.(modulo (i - 52, 39))) call abort
+ end if
+ a(i) = i - 513
+ end do
+ if (k.ne.(4 + 3 * 1024).or.s.ne.1596127) call abort
+ k = 4
+ m = 2
+ t = 1
+ s = baz (b)
+ do i = 1, 1024
+ if (a(i).ne.((i - 513) * b(i))) call abort
+ if (i.lt.52.and.modulo (i - 52, 39).ne.0) then
+ if (b(i).ne.(modulo (i - 52, 39) - 39)) call abort
+ else
+ if (b(i).ne.(modulo (i - 52, 39))) call abort
+ end if
+ end do
+ if (k.ne.(4 + 3 * 1024).or.s.ne.1596127) call abort
+contains
+ function foo (p)
+ integer :: p(1024), u, v, i, s, foo
+ s = 0
+ !$omp parallel do simd linear(k : m + 1) reduction(+: s) &
+ !$omp & lastprivate(u, v) schedule (static, 32)
+ do i = 1, 1024
+ a(i) = a(i) * p(i)
+ u = p(i) + k
+ k = k + m + 1
+ v = p(i) + k
+ s = s + p(i) + k
+ end do
+ !$omp end parallel do simd
+ if (i.ne.1025) call abort
+ if (u.ne.(36 + 4 + 3 * 1023).or.v.ne.(36 + 4 + 3 * 1024)) call abort
+ foo = s
+ end function foo
+ function bar (p)
+ integer :: p(1024), u, v, i, s, bar
+ s = 0
+ !$omp parallel do simd linear(k : m + 1) reduction(+: s) &
+ !$omp & lastprivate(u, v) schedule (dynamic, 32)
+ do i = 1, 1024, t
+ a(i) = a(i) * p(i)
+ u = p(i) + k
+ k = k + m + 1
+ v = p(i) + k
+ s = s + p(i) + k
+ end do
+ !$omp endparalleldosimd
+ if (i.ne.1025) call abort
+ if (u.ne.(36 + 4 + 3 * 1023).or.v.ne.(36 + 4 + 3 * 1024)) call abort
+ bar = s
+ end function bar
+ function baz (p)
+ integer :: p(1024), u, v, i, s, baz
+ s = 0
+ !$omp parallel do simd linear(k : m + 1) reduction(+: s) &
+ !$omp & lastprivate(u, v) linear(i : t) schedule (static, 8)
+ do i = 1, 1024, t
+ a(i) = a(i) * p(i)
+ u = p(i) + k
+ k = k + m + 1
+ v = p(i) + k
+ s = s + p(i) + k
+ end do
+ if (i.ne.1025) call abort
+ if (u.ne.(36 + 4 + 3 * 1023).or.v.ne.(36 + 4 + 3 * 1024)) call abort
+ baz = s
+ end function baz
+end
diff --git a/libgomp/testsuite/libgomp.fortran/taskgroup1.f90 b/libgomp/testsuite/libgomp.fortran/taskgroup1.f90
new file mode 100644
index 00000000000..018d3e83b92
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/taskgroup1.f90
@@ -0,0 +1,80 @@
+ integer :: v(16), i
+ do i = 1, 16
+ v(i) = i
+ end do
+
+ !$omp parallel num_threads (4)
+ !$omp single
+ !$omp taskgroup
+ do i = 1, 16, 2
+ !$omp task
+ !$omp task
+ v(i) = v(i) + 1
+ !$omp end task
+ !$omp task
+ v(i + 1) = v(i + 1) + 1
+ !$omp end task
+ !$omp end task
+ end do
+ !$omp end taskgroup
+ do i = 1, 16
+ if (v(i).ne.(i + 1)) call abort
+ end do
+ !$omp taskgroup
+ do i = 1, 16, 2
+ !$omp task
+ !$omp task
+ v(i) = v(i) + 1
+ !$omp endtask
+ !$omp task
+ v(i + 1) = v(i + 1) + 1
+ !$omp endtask
+ !$omp taskwait
+ !$omp endtask
+ end do
+ !$omp endtaskgroup
+ do i = 1, 16
+ if (v(i).ne.(i + 2)) call abort
+ end do
+ !$omp taskgroup
+ do i = 1, 16, 2
+ !$omp task
+ !$omp task
+ v(i) = v(i) + 1
+ !$omp end task
+ v(i + 1) = v(i + 1) + 1
+ !$omp end task
+ end do
+ !$omp taskwait
+ do i = 1, 16, 2
+ !$omp task
+ v(i + 1) = v(i + 1) + 1
+ !$omp end task
+ end do
+ !$omp end taskgroup
+ do i = 1, 16, 2
+ if (v(i).ne.(i + 3)) call abort
+ if (v(i + 1).ne.(i + 5)) call abort
+ end do
+ !$omp taskgroup
+ do i = 1, 16, 2
+ !$omp taskgroup
+ !$omp task
+ v(i) = v(i) + 1
+ !$omp end task
+ !$omp task
+ v(i + 1) = v(i + 1) + 1
+ !$omp end task
+ !$omp end taskgroup
+ if (v(i).ne.(i + 4).or.v(i + 1).ne.(i + 6)) call abort
+ !$omp task
+ v(i) = v(i) + 1
+ !$omp end task
+ end do
+ !$omp end taskgroup
+ do i = 1, 16
+ if (v(i).ne.(i + 5)) call abort
+ end do
+ !$omp end single
+ !$omp end parallel
+end
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index d9a208b577d..8390e4c7841 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,34 @@
+2014-06-01 Ray Donnelly <mingw.android@gmail.com>
+
+ * pex-win32.c (argv_to_cmdline): Don't quote
+ args unnecessarily
+
+2014-05-28 Pedro Alves <palves@redhat.com>
+
+ * cp-demangle.c (d_dump): Handle DEMANGLE_COMPONENT_FUNCTION_PARAM
+ and DEMANGLE_COMPONENT_NUMBER.
+
+2014-05-22 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/demangle-expected: Fix last commit.
+
+2014-05-14 Andrew Burgess <aburgess@broadcom.com>
+
+ * cplus-dmem.c (internal_cplus_demangle): Free any resources
+ allocated by possible previous call to gnu_special.
+ (squangle_mop_up): Reset pointers to NULL after calling free.
+ * testsuite/demangle-expected: New test case.
+
+2014-05-08 Gary Benson <gbenson@redhat.com>
+
+ * cp-demangle.c (struct d_component_stack): New structure.
+ (struct d_print_info): New field component_stack.
+ (d_print_init): Initialize the above.
+ (d_print_comp_inner): Renamed from d_print_comp.
+ Do not restore template stack if it would cause a loop.
+ (d_print_comp): New function.
+ * testsuite/demangle-expected: New test cases.
+
2014-04-17 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/56781
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 3d5d33ef591..c0d2ffee7d9 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -275,6 +275,16 @@ struct d_growable_string
int allocation_failure;
};
+/* Stack of components, innermost first, used to avoid loops. */
+
+struct d_component_stack
+{
+ /* This component. */
+ const struct demangle_component *dc;
+ /* This component's parent. */
+ const struct d_component_stack *parent;
+};
+
/* A demangle component and some scope captured when it was first
traversed. */
@@ -327,6 +337,8 @@ struct d_print_info
int pack_index;
/* Number of d_print_flush calls so far. */
unsigned long int flush_count;
+ /* Stack of components, innermost first, used to avoid loops. */
+ const struct d_component_stack *component_stack;
/* Array of saved scopes for evaluating substitutions. */
struct d_saved_scope *saved_scopes;
/* Index of the next unused saved scope in the above array. */
@@ -563,6 +575,9 @@ d_dump (struct demangle_component *dc, int indent)
case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
printf ("template parameter %ld\n", dc->u.s_number.number);
return;
+ case DEMANGLE_COMPONENT_FUNCTION_PARAM:
+ printf ("function parameter %ld\n", dc->u.s_number.number);
+ return;
case DEMANGLE_COMPONENT_CTOR:
printf ("constructor %d\n", (int) dc->u.s_ctor.kind);
d_dump (dc->u.s_ctor.name, indent + 2);
@@ -748,6 +763,9 @@ d_dump (struct demangle_component *dc, int indent)
case DEMANGLE_COMPONENT_CHARACTER:
printf ("character '%c'\n", dc->u.s_character.character);
return;
+ case DEMANGLE_COMPONENT_NUMBER:
+ printf ("number %ld\n", dc->u.s_number.number);
+ return;
case DEMANGLE_COMPONENT_DECLTYPE:
printf ("decltype\n");
break;
@@ -3934,6 +3952,8 @@ d_print_init (struct d_print_info *dpi, demangle_callbackref callback,
dpi->demangle_failure = 0;
+ dpi->component_stack = NULL;
+
dpi->saved_scopes = NULL;
dpi->next_saved_scope = 0;
dpi->num_saved_scopes = 0;
@@ -4269,8 +4289,8 @@ d_get_saved_scope (struct d_print_info *dpi,
/* Subroutine to handle components. */
static void
-d_print_comp (struct d_print_info *dpi, int options,
- const struct demangle_component *dc)
+d_print_comp_inner (struct d_print_info *dpi, int options,
+ const struct demangle_component *dc)
{
/* Magic variable to let reference smashing skip over the next modifier
without needing to modify *dc. */
@@ -4673,11 +4693,30 @@ d_print_comp (struct d_print_info *dpi, int options,
}
else
{
+ const struct d_component_stack *dcse;
+ int found_self_or_parent = 0;
+
/* This traversal is reentering SUB as a substition.
- Restore the original templates temporarily. */
- saved_templates = dpi->templates;
- dpi->templates = scope->templates;
- need_template_restore = 1;
+ If we are not beneath SUB or DC in the tree then we
+ need to restore SUB's template stack temporarily. */
+ for (dcse = dpi->component_stack; dcse != NULL;
+ dcse = dcse->parent)
+ {
+ if (dcse->dc == sub
+ || (dcse->dc == dc
+ && dcse != dpi->component_stack))
+ {
+ found_self_or_parent = 1;
+ break;
+ }
+ }
+
+ if (!found_self_or_parent)
+ {
+ saved_templates = dpi->templates;
+ dpi->templates = scope->templates;
+ need_template_restore = 1;
+ }
}
a = d_lookup_template_argument (dpi, sub);
@@ -5316,6 +5355,21 @@ d_print_comp (struct d_print_info *dpi, int options,
}
}
+static void
+d_print_comp (struct d_print_info *dpi, int options,
+ const struct demangle_component *dc)
+{
+ struct d_component_stack self;
+
+ self.dc = dc;
+ self.parent = dpi->component_stack;
+ dpi->component_stack = &self;
+
+ d_print_comp_inner (dpi, options, dc);
+
+ dpi->component_stack = self.parent;
+}
+
/* Print a Java dentifier. For Java we try to handle encoded extended
Unicode characters. The C++ ABI doesn't mention Unicode encoding,
so we don't it for C++. Characters are encoded as
diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c
index e94848767e7..2dd0a8a5c84 100644
--- a/libiberty/cplus-dem.c
+++ b/libiberty/cplus-dem.c
@@ -1175,6 +1175,11 @@ internal_cplus_demangle (struct work_stuff *work, const char *mangled)
if ((AUTO_DEMANGLING || GNU_DEMANGLING))
{
success = gnu_special (work, &mangled, &decl);
+ if (!success)
+ {
+ delete_work_stuff (work);
+ string_delete (&decl);
+ }
}
if (!success)
{
@@ -1218,10 +1223,12 @@ squangle_mop_up (struct work_stuff *work)
if (work -> btypevec != NULL)
{
free ((char *) work -> btypevec);
+ work->btypevec = NULL;
}
if (work -> ktypevec != NULL)
{
free ((char *) work -> ktypevec);
+ work->ktypevec = NULL;
}
}
diff --git a/libiberty/pex-win32.c b/libiberty/pex-win32.c
index eae72c51dc0..8b9d4f04900 100644
--- a/libiberty/pex-win32.c
+++ b/libiberty/pex-win32.c
@@ -340,17 +340,25 @@ argv_to_cmdline (char *const *argv)
char *p;
size_t cmdline_len;
int i, j, k;
+ int needs_quotes;
cmdline_len = 0;
for (i = 0; argv[i]; i++)
{
- /* We quote every last argument. This simplifies the problem;
- we need only escape embedded double-quotes and immediately
+ /* We only quote arguments that contain spaces, \t or " characters to
+ prevent wasting 2 chars per argument of the CreateProcess 32k char
+ limit. We need only escape embedded double-quotes and immediately
preceeding backslash characters. A sequence of backslach characters
that is not follwed by a double quote character will not be
escaped. */
+ needs_quotes = 0;
for (j = 0; argv[i][j]; j++)
{
+ if (argv[i][j] == ' ' || argv[i][j] == '\t' || argv[i][j] == '"')
+ {
+ needs_quotes = 1;
+ }
+
if (argv[i][j] == '"')
{
/* Escape preceeding backslashes. */
@@ -362,16 +370,33 @@ argv_to_cmdline (char *const *argv)
}
/* Trailing backslashes also need to be escaped because they will be
followed by the terminating quote. */
- for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
- cmdline_len++;
+ if (needs_quotes)
+ {
+ for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
+ cmdline_len++;
+ }
cmdline_len += j;
- cmdline_len += 3; /* for leading and trailing quotes and space */
+ /* for leading and trailing quotes and space */
+ cmdline_len += needs_quotes * 2 + 1;
}
cmdline = XNEWVEC (char, cmdline_len);
p = cmdline;
for (i = 0; argv[i]; i++)
{
- *p++ = '"';
+ needs_quotes = 0;
+ for (j = 0; argv[i][j]; j++)
+ {
+ if (argv[i][j] == ' ' || argv[i][j] == '\t' || argv[i][j] == '"')
+ {
+ needs_quotes = 1;
+ break;
+ }
+ }
+
+ if (needs_quotes)
+ {
+ *p++ = '"';
+ }
for (j = 0; argv[i][j]; j++)
{
if (argv[i][j] == '"')
@@ -382,9 +407,12 @@ argv_to_cmdline (char *const *argv)
}
*p++ = argv[i][j];
}
- for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
- *p++ = '\\';
- *p++ = '"';
+ if (needs_quotes)
+ {
+ for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
+ *p++ = '\\';
+ *p++ = '"';
+ }
*p++ = ' ';
}
p[-1] = '\0';
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 3ff08e6e5f2..864ee7e0f9c 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -4294,6 +4294,7 @@ void n<void (A::*)() const &>(void (A::*)() const &)
--format=gnu-v3
_ZL1fIiEvv
void f<int>()
+# https://sourceware.org/bugzilla/show_bug.cgi?id=14963#c3
--format=gnu-v3
_ZSt7forwardIRN1x14refobjiteratorINS0_3refINS0_4mime30multipart_section_processorObjIZ15get_body_parserIZZN14mime_processor21make_section_iteratorERKNS2_INS3_10sectionObjENS0_10ptrrefBaseEEEbENKUlvE_clEvEUlSB_bE_ZZNS6_21make_section_iteratorESB_bENKSC_clEvEUlSB_E0_ENS1_INS2_INS0_20outputrefiteratorObjIiEES8_EEEERKSsSB_OT_OT0_EUlmE_NS3_32make_multipart_default_discarderISP_EEEES8_EEEEEOT_RNSt16remove_referenceISW_E4typeE
x::refobjiterator<x::ref<x::mime::multipart_section_processorObj<x::refobjiterator<x::ref<x::outputrefiteratorObj<int>, x::ptrrefBase> > get_body_parser<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}>(std::string const&, x::ref<x::mime::sectionObj, x::ptrrefBase> const&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}&&)::{lambda(unsigned long)#1}, x::mime::make_multipart_default_discarder<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&> >, x::ptrrefBase> >& std::forward<x::refobjiterator<x::ref<x::mime::multipart_section_processorObj<x::refobjiterator<x::ref<x::outputrefiteratorObj<int>, x::ptrrefBase> > get_body_parser<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}>(std::string const&, x::ref<x::mime::sectionObj, x::ptrrefBase> const&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}&&)::{lambda(unsigned long)#1}, x::mime::make_multipart_default_discarder<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&> >, x::ptrrefBase> >&>(std::remove_reference<x::mime::multipart_section_processorObj<x::refobjiterator<x::ref<x::outputrefiteratorObj<int>, x::ptrrefBase> > get_body_parser<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}>(std::string const&, x::ref<x::mime::sectionObj, x::ptrrefBase> const&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}&&)::{lambda(unsigned long)#1}, x::mime::make_multipart_default_discarder<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&> > >::type&)
@@ -4317,3 +4318,33 @@ A::operator C*<C>
_ZN1AcvT_IiEI1CEEv
A::operator C<int><C>()
A::operator C<int><C>
+# https://sourceware.org/bugzilla/show_bug.cgi?id=14963#c16
+--format=gnu-v3
+_ZN3mdr16in_cached_threadIRZNK4cudr6GPUSet17parallel_for_eachIZN5tns3d20shape_representation7compute7GPUImpl7executeERKNS_1AINS_7ptr_refIKjEELl3ELl3ENS_8c_strideILl1ELl0EEEEERKNS8_INS9_IjEELl4ELl1ESD_EEEUliRKNS1_7ContextERNS7_5StateEE_JSt6vectorISO_SaISO_EEEEEvOT_DpRT0_EUlSP_E_JSt17reference_wrapperISO_EEEENS_12ScopedFutureIDTclfp_spcl7forwardISW_Efp0_EEEEESV_DpOSW_
+mdr::ScopedFuture<decltype ({parm#1}(((forward<void cudr::GPUSet::parallel_for_each<tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > const&)::{lambda(int, cudr::Context const&, tns3d::shape_representation::compute::GPUImpl::State&)#1}, std::vector<tns3d::shape_representation::compute::GPUImpl::State, std::allocator<tns3d::shape_representation::compute::GPUImpl::State> > >(tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > const&)::{lambda(int, cudr::Context const&, tns3d::shape_representation::compute::GPUImpl::State&)#1}&&, std::vector<tns3d::shape_representation::compute::GPUImpl::State, std::allocator<tns3d::shape_representation::compute::GPUImpl::State> >&) const::{lambda(tns3d::shape_representation::compute::GPUImpl::State&)#1}&>)({parm#2}))...))> mdr::in_cached_thread<void cudr::GPUSet::parallel_for_each<tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > const&)::{lambda(int, cudr::Context const&, tns3d::shape_representation::compute::GPUImpl::State&)#1}, std::vector<tns3d::shape_representation::compute::GPUImpl::State, std::allocator<tns3d::shape_representation::compute::GPUImpl::State> > >(void cudr::GPUSet::parallel_for_each<tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > const&)::{lambda(int, cudr::Context const&, tns3d::shape_representation::compute::GPUImpl::State&)#1}, std::vector<tns3d::shape_representation::compute::GPUImpl::State, std::allocator<tns3d::shape_representation::compute::GPUImpl::State> > >(tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > const&)::{lambda(int, cudr::Context const&, tns3d::shape_representation::compute::GPUImpl::State&)#1}&&, std::vector<tns3d::shape_representation::compute::GPUImpl::State, std::allocator<tns3d::shape_representation::compute::GPUImpl::State> >&) const::{lambda(tns3d::shape_representation::compute::GPUImpl::State&)#1}&, std::vector<tns3d::shape_representation::compute::GPUImpl::State, std::allocator<tns3d::shape_representation::compute::GPUImpl::State> >&) const::{lambda(tns3d::shape_representation::compute::GPUImpl::State&)#1}&, std::reference_wrapper<tns3d::shape_representation::compute::GPUImpl::State> >(void cudr::GPUSet::parallel_for_each<tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > const&)::{lambda(int, cudr::Context const&, tns3d::shape_representation::compute::GPUImpl::State&)#1}, std::vector<tns3d::shape_representation::compute::GPUImpl::State, std::allocator<tns3d::shape_representation::compute::GPUImpl::State> > >(tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > const&)::{lambda(int, cudr::Context const&, tns3d::shape_representation::compute::GPUImpl::State&)#1}&&, std::vector<tns3d::shape_representation::compute::GPUImpl::State, std::allocator<tns3d::shape_representation::compute::GPUImpl::State> >&) const::{lambda(tns3d::shape_representation::compute::GPUImpl::State&)#1}&, (void cudr::GPUSet::parallel_for_each<tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > const&)::{lambda(int, cudr::Context const&, tns3d::shape_representation::compute::GPUImpl::State&)#1}, std::vector<tns3d::shape_representation::compute::GPUImpl::State, std::allocator<tns3d::shape_representation::compute::GPUImpl::State> > >(tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > const&)::{lambda(int, cudr::Context const&, tns3d::shape_representation::compute::GPUImpl::State&)#1}&&, std::vector<tns3d::shape_representation::compute::GPUImpl::State, std::allocator<tns3d::shape_representation::compute::GPUImpl::State> >&) const::{lambda(tns3d::shape_representation::compute::GPUImpl::State&)#1}&&&)...)
+# https://sourceware.org/bugzilla/show_bug.cgi?id=14963#c18
+--format=gnu-v3
+_ZNSt9_Any_data9_M_accessIPZN13ThreadManager10futureTaskISt5_BindIFSt7_Mem_fnIM6RunnerFvvEEPS5_EEEEvOT_EUlvE_EERSC_v
+void ThreadManager::futureTask<std::_Bind<std::_Mem_fn<void (Runner::*)()> (Runner*)> >(std::_Bind<std::_Mem_fn<void (Runner::*)()> (Runner*)>&&)::{lambda()#1}*& std::_Any_data::_M_access<void ThreadManager::futureTask<std::_Bind<std::_Mem_fn<void (Runner::*)()> (Runner*)> >(void ThreadManager::futureTask<std::_Bind<std::_Mem_fn<void (Runner::*)()> (Runner*)> >(std::_Bind<std::_Mem_fn<void (Runner::*)()> (Runner*)>&&)::{lambda()#1}*&&)::{lambda()#1}*>()
+# https://sourceware.org/bugzilla/show_bug.cgi?id=14963#c24
+# aka https://sourceware.org/bugzilla/show_bug.cgi?id=16593
+--format=gnu-v3
+_ZNSt9_Any_data9_M_accessIPZN3sel8Selector6SetObjI3FooJPKcMS4_FviEEEEvRT_DpT0_EUlvE_EESA_v
+void sel::Selector::SetObj<Foo, char const*, void (Foo::*)(int)>(Foo&, char const*, void (Foo::*)(int))::{lambda()#1}*& std::_Any_data::_M_access<void sel::Selector::SetObj<Foo, char const*, void (Foo::*)(int)>(void sel::Selector::SetObj<Foo, char const*, void (Foo::*)(int)>(Foo&, char const*, void (Foo::*)(int))::{lambda()#1}*&, char const*, void (Foo::*)(int))::{lambda()#1}*>()
+# https://sourceware.org/bugzilla/show_bug.cgi?id=16752#c1
+--format=gnu-v3
+_ZNSt9_Any_data9_M_accessIPZN13ThreadManager7newTaskIRSt5_BindIFSt7_Mem_fnIM5DiaryFivEEPS5_EEIEEESt6futureINSt9result_ofIFT_DpT0_EE4typeEEOSF_DpOSG_EUlvE_EERSF_v
+std::future<std::result_of<std::_Bind<std::_Mem_fn<int (Diary::*)()> (Diary*)>& ()>::type> ThreadManager::newTask<std::_Bind<std::_Mem_fn<int (Diary::*)()> (Diary*)>&>(std::_Bind<std::_Mem_fn<int (Diary::*)()> (Diary*)>&)::{lambda()#1}*& std::_Any_data::_M_access<std::future<std::result_of<std::_Bind<std::_Mem_fn<int (Diary::*)()> (Diary*)>& ()>::type> ThreadManager::newTask<std::_Bind<std::_Mem_fn<int (Diary::*)()> (Diary*)>&>(std::future<std::result_of<std::_Bind<std::_Mem_fn<int (Diary::*)()> (Diary*)>& ()>::type> ThreadManager::newTask<std::_Bind<std::_Mem_fn<int (Diary::*)()> (Diary*)>&>(std::_Bind<std::_Mem_fn<int (Diary::*)()> (Diary*)>&)::{lambda()#1}*&&)::{lambda()#1}*>()
+# https://sourceware.org/bugzilla/show_bug.cgi?id=16752#c6
+--format=gnu-v3
+_ZNSt9_Any_data9_M_accessIPZN6cereal18polymorphic_detail15getInputBindingINS1_16JSONInputArchiveEEENS1_6detail15InputBindingMapIT_E11SerializersERS7_jEUlPvRSt10unique_ptrIvNS5_12EmptyDeleterIvEEEE0_EESA_v
+cereal::detail::InputBindingMap<cereal::JSONInputArchive>::Serializers cereal::polymorphic_detail::getInputBinding<cereal::JSONInputArchive>(cereal::JSONInputArchive&, unsigned int)::{lambda(void*, std::unique_ptr<void, cereal::detail::EmptyDeleter<void> >&)#2}*& std::_Any_data::_M_access<cereal::detail::InputBindingMap<cereal::JSONInputArchive>::Serializers cereal::polymorphic_detail::getInputBinding<cereal::JSONInputArchive>(cereal::detail::InputBindingMap<cereal::JSONInputArchive>::Serializers cereal::polymorphic_detail::getInputBinding<cereal::JSONInputArchive>(cereal::JSONInputArchive&, unsigned int)::{lambda(void*, std::unique_ptr<void, cereal::detail::EmptyDeleter<void> >&)#2}*&, unsigned int)::{lambda(void*, std::unique_ptr<void, cereal::detail::EmptyDeleter<void> >&)#2}*>()
+# https://sourceware.org/bugzilla/show_bug.cgi?id=16845#c2
+--format=gnu-v3
+_ZNSt9_Any_data9_M_accessIPZ4postISt8functionIFvvEEEvOT_EUlvE_EERS5_v
+void post<std::function<void ()> >(std::function<void ()>&&)::{lambda()#1}*& std::_Any_data::_M_access<void post<std::function<void ()> >(void post<std::function<void ()> >(std::function<void ()>&&)::{lambda()#1}*&&)::{lambda()#1}*>()
+# https://sourceware.org/bugzilla/show_bug.cgi?id=16817
+--format=auto --no-params
+_QueueNotification_QueueController__$4PPPPPPPM_A_INotice___Z
+_QueueNotification_QueueController__$4PPPPPPPM_A_INotice___Z
+_QueueNotification_QueueController__$4PPPPPPPM_A_INotice___Z
diff --git a/libitm/ChangeLog b/libitm/ChangeLog
index 62005789c57..17bb0a66448 100644
--- a/libitm/ChangeLog
+++ b/libitm/ChangeLog
@@ -1,3 +1,20 @@
+2014-05-28 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * acinclude.m4 (LIBITM_CHECK_LINKER_HWCAP): Check for
+ -mclear-hwcap instead.
+ * configure: Regenerate.
+ * clearcap.map: Remove.
+
+2014-05-21 John Marino <gnugcc@marino.st>
+
+ * configure.tgt (*-*-dragonfly*): New target.
+
+2014-05-19 Richard Henderson <rth@redhat.com>
+
+ * config/aarch64/sjlj.S: New file.
+ * config/aarch64/target.h: New file.
+ * configure.tgt: Enable aarch64.
+
2014-04-09 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* config/generic/asmcfi.h: Also check for
diff --git a/libitm/acinclude.m4 b/libitm/acinclude.m4
index ca7e0a92118..a82f6d6179b 100644
--- a/libitm/acinclude.m4
+++ b/libitm/acinclude.m4
@@ -301,10 +301,10 @@ AC_DEFUN([LIBITM_CHECK_LINKER_FEATURES], [
dnl
dnl Check if the linker used supports linker maps to clear hardware
-dnl capabilities. This is only supported by Sun ld at the moment.
+dnl capabilities. This is only supported on Solaris at the moment.
dnl
dnl Defines:
-dnl HWCAP_LDFLAGS='-Wl,-M,clearcap.map' if possible
+dnl HWCAP_LDFLAGS=-mclear-hwcap if possible
dnl LD (as a side effect of testing)
dnl
AC_DEFUN([LIBITM_CHECK_LINKER_HWCAP], [
@@ -312,12 +312,12 @@ AC_DEFUN([LIBITM_CHECK_LINKER_HWCAP], [
AC_REQUIRE([AC_PROG_LD])
ac_save_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LFLAGS -Wl,-M,$srcdir/clearcap.map"
+ LDFLAGS="$LFLAGS -mclear-hwcap"
- AC_MSG_CHECKING([for ld that supports -Wl,-M,mapfile])
+ AC_MSG_CHECKING([for -mclear-hwcap])
AC_TRY_LINK([], [return 0;], [ac_hwcap_ldflags=yes],[ac_hwcap_ldflags=no])
if test "$ac_hwcap_ldflags" = "yes"; then
- HWCAP_LDFLAGS="-Wl,-M,$srcdir/clearcap.map $HWCAP_LDFLAGS"
+ HWCAP_LDFLAGS="-mclear-hwcap $HWCAP_LDFLAGS"
fi
AC_MSG_RESULT($ac_hwcap_ldflags)
diff --git a/libitm/clearcap.map b/libitm/clearcap.map
deleted file mode 100644
index bd8189b43ff..00000000000
--- a/libitm/clearcap.map
+++ /dev/null
@@ -1,14 +0,0 @@
-# Clear hardware capabilities emitted by Sun as: calls to the x86_avx.c
-# functions are only emitted with -mavx.
-#
-# The v1 mapfile syntax has no support for clearing specific capabilities,
-# so clear everything.
-#
-hwcap_1 = V0x0 OVERRIDE;
-#
-# If we can assume mapfile v2 syntax, we can specificially clear AVX.
-#
-#$mapfile_version 2
-#CAPABILITY {
-# HW -= AVX;
-#};
diff --git a/libitm/config/aarch64/sjlj.S b/libitm/config/aarch64/sjlj.S
new file mode 100644
index 00000000000..4207da96638
--- /dev/null
+++ b/libitm/config/aarch64/sjlj.S
@@ -0,0 +1,93 @@
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libitm 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 of the License, or
+ (at your option) any later version.
+
+ Libitm 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.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "asmcfi.h"
+
+ .text
+ .align 2
+ .global _ITM_beginTransaction
+ .type _ITM_beginTransaction, %function
+
+_ITM_beginTransaction:
+ cfi_startproc
+ mov x1, sp
+ stp x29, x30, [sp, -11*16]!
+ cfi_adjust_cfa_offset(11*16)
+ cfi_rel_offset(x29, 0)
+ cfi_rel_offset(x30, 8)
+ mov x29, sp
+ stp x19, x20, [sp, 1*16]
+ stp x21, x22, [sp, 2*16]
+ stp x23, x24, [sp, 3*16]
+ stp x25, x26, [sp, 4*16]
+ stp x27, x28, [sp, 5*16]
+ stp d8, d9, [sp, 6*16]
+ stp d10, d11, [sp, 7*16]
+ stp d12, d13, [sp, 8*16]
+ stp d14, d15, [sp, 9*16]
+ str x1, [sp, 10*16]
+
+ /* Invoke GTM_begin_transaction with the struct we just built. */
+ mov x1, sp
+ bl GTM_begin_transaction
+
+ /* Return; we don't need to restore any of the call-saved regs. */
+ ldp x29, x30, [sp]
+ add sp, sp, #11*16
+ cfi_adjust_cfa_offset(-11*16)
+ cfi_restore(x29)
+ cfi_restore(x30)
+ ret
+ cfi_endproc
+ .size _ITM_beginTransaction, . - _ITM_beginTransaction
+
+ .align 2
+ .global GTM_longjmp
+ .hidden GTM_longjmp
+ .type GTM_longjmp, %function
+
+GTM_longjmp:
+ /* The first parameter becomes the return value (x0).
+ The third parameter is ignored for now. */
+ cfi_startproc
+ ldp x19, x20, [x1, 1*16]
+ ldp x21, x22, [x1, 2*16]
+ ldp x23, x24, [x1, 3*16]
+ ldp x25, x26, [x1, 4*16]
+ ldp x27, x28, [x1, 5*16]
+ ldp d8, d9, [x1, 6*16]
+ ldp d10, d11, [x1, 7*16]
+ ldp d12, d13, [x1, 8*16]
+ ldp d14, d15, [x1, 9*16]
+ ldr x3, [x1, 10*16]
+ ldp x29, x30, [x1]
+ cfi_def_cfa(x1, 0)
+ mov sp, x3
+ br x30
+ cfi_endproc
+ .size GTM_longjmp, . - GTM_longjmp
+
+#ifdef __linux__
+.section .note.GNU-stack, "", %progbits
+#endif
diff --git a/libitm/config/aarch64/target.h b/libitm/config/aarch64/target.h
new file mode 100644
index 00000000000..cb0f33621e8
--- /dev/null
+++ b/libitm/config/aarch64/target.h
@@ -0,0 +1,45 @@
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libitm 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 of the License, or
+ (at your option) any later version.
+
+ Libitm 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.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+namespace GTM HIDDEN {
+
+typedef struct gtm_jmpbuf
+{
+ unsigned long long fp; /* x29 */
+ unsigned long long pc; /* x30 */
+ unsigned long long gr[10]; /* x19-x28 */
+ unsigned long long vr[8]; /* d8-d15 */
+ void *cfa;
+} gtm_jmpbuf;
+
+/* ??? The size of one line in hardware caches (in bytes). */
+#define HW_CACHELINE_SIZE 128
+
+static inline void
+cpu_relax (void)
+{
+ __asm volatile ("" : : : "memory");
+}
+
+} // namespace GTM
diff --git a/libitm/configure b/libitm/configure
index 031c19ce337..ce6d50a7d3a 100644
--- a/libitm/configure
+++ b/libitm/configure
@@ -16739,10 +16739,10 @@ with_gnu_ld=$lt_cv_prog_gnu_ld
ac_save_LDFLAGS="$LDFLAGS"
- LDFLAGS="$LFLAGS -Wl,-M,$srcdir/clearcap.map"
+ LDFLAGS="$LFLAGS -mclear-hwcap"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld that supports -Wl,-M,mapfile" >&5
-$as_echo_n "checking for ld that supports -Wl,-M,mapfile... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -mclear-hwcap" >&5
+$as_echo_n "checking for -mclear-hwcap... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -16762,7 +16762,7 @@ fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
if test "$ac_hwcap_ldflags" = "yes"; then
- HWCAP_LDFLAGS="-Wl,-M,$srcdir/clearcap.map $HWCAP_LDFLAGS"
+ HWCAP_LDFLAGS="-mclear-hwcap $HWCAP_LDFLAGS"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_hwcap_ldflags" >&5
$as_echo "$ac_hwcap_ldflags" >&6; }
diff --git a/libitm/configure.tgt b/libitm/configure.tgt
index 4694a9b8aa0..29b692f8570 100644
--- a/libitm/configure.tgt
+++ b/libitm/configure.tgt
@@ -46,6 +46,7 @@ fi
# Map the target cpu to an ARCH sub-directory. At the same time,
# work out any special compilation flags as necessary.
case "${target_cpu}" in
+ aarch64*) ARCH=aarch64 ;;
alpha*) ARCH=alpha ;;
rs6000 | powerpc*)
XCFLAGS="${XCFLAGS} -mhtm"
@@ -140,7 +141,7 @@ case "${target}" in
*-*-gnu* | *-*-k*bsd*-gnu \
| *-*-netbsd* | *-*-freebsd* | *-*-openbsd* \
| *-*-solaris2* | *-*-sysv4* | *-*-hpux11* \
- | *-*-darwin* | *-*-aix*)
+ | *-*-darwin* | *-*-aix* | *-*-dragonfly*)
# POSIX system. The OS is supported.
;;
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 661bb7a30c1..fea4b31c472 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,16 @@
+2014-05-20 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * testsuite/lib/libjava.exp (load_gcc_lib): Register loaded libs.
+
+2014-05-13 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ Fix current cygwin-64 build problems.
+ * configure.host: Added handling for x86_64-*-cygwin/mingw.
+ * boehm.cc (_Jv_GCAttachThread, _Jv_GCDetachThread): Don't compile if
+ GC_WIN32_THREADS is defined.
+ * java/lang/natClass.cc (_Jv_InterfaceAssignableFrom): Rename interface
+ to source_interface.
+
2014-04-22 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* configure.ac (THREADLIBS, THREADSPEC): Remove *-*-solaris2.9
diff --git a/libjava/boehm.cc b/libjava/boehm.cc
index 855d23cb024..043fd0030ca 100644
--- a/libjava/boehm.cc
+++ b/libjava/boehm.cc
@@ -747,7 +747,8 @@ _Jv_GCAttachThread ()
// The registration interface is only defined on posixy systems and
// only actually works if pthread_getattr_np is defined.
// FIXME: until gc7 it is simpler to disable this on solaris.
-#if defined(HAVE_PTHREAD_GETATTR_NP) && !defined(GC_SOLARIS_THREADS)
+#if defined(HAVE_PTHREAD_GETATTR_NP) && !defined(GC_SOLARIS_THREADS) \
+ && !defined(GC_WIN32_THREADS)
GC_register_my_thread ();
#endif
}
@@ -755,7 +756,8 @@ _Jv_GCAttachThread ()
void
_Jv_GCDetachThread ()
{
-#if defined(HAVE_PTHREAD_GETATTR_NP) && !defined(GC_SOLARIS_THREADS)
+#if defined(HAVE_PTHREAD_GETATTR_NP) && !defined(GC_SOLARIS_THREADS) \
+ && !defined(GC_WIN32_THREADS)
GC_unregister_my_thread ();
#endif
}
diff --git a/libjava/classpath/ChangeLog b/libjava/classpath/ChangeLog
index 4d9f1a6e49c..4389fc05507 100644
--- a/libjava/classpath/ChangeLog
+++ b/libjava/classpath/ChangeLog
@@ -1,3 +1,9 @@
+2014-05-13 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ Fix current cygwin-64 build problems.
+ * native/fdlibm/mprec.c (_REENT_CHECK_MP, _REENT_MP_FREELIST,
+ _REENT_MP_P5S, __ULong, __Long): Undefine previous definitions.
+
2013-09-20 Alan Modra <amodra@gmail.com>
* configure: Regenerate.
diff --git a/libjava/classpath/native/fdlibm/mprec.c b/libjava/classpath/native/fdlibm/mprec.c
index 8a7cdc03968..460c301054d 100644
--- a/libjava/classpath/native/fdlibm/mprec.c
+++ b/libjava/classpath/native/fdlibm/mprec.c
@@ -93,12 +93,17 @@
#define _reent _Jv_reent
#define _Bigint _Jv_Bigint
+#undef _REENT_CHECK_MP
#define _REENT_CHECK_MP(x)
+#undef _REENT_MP_FREELIST
#define _REENT_MP_FREELIST(x) ((x)->_freelist)
+#undef _REENT_MP_P5S
#define _REENT_MP_P5S(x) ((x)->_p5s)
-typedef unsigned long __ULong;
-typedef long __Long;
+#undef __ULong
+#define __ULong unsigned long
+#undef __Long
+#define __Long long
static void *
mprec_calloc (void *ignore, size_t x1, size_t x2)
diff --git a/libjava/configure.host b/libjava/configure.host
index f2d1bb5ed3b..c6f359c5492 100644
--- a/libjava/configure.host
+++ b/libjava/configure.host
@@ -365,6 +365,13 @@ EOF
esac
case "${host}" in
+ x86_64-*-cygwin* | x86_64-*-mingw*)
+ # Win32 DLLs are limited to 64k exported symbols each.
+ enable_libgcj_sublibs_default=yes
+ libgcj_sublib_ltflags='$(lt_host_flags) \
+ -Wl,-u,_ZN3org4ietf4jgss10GSSManagerC1Ev,-L..,-lgcj-noncore-dummy'
+ libgcj_sublib_core_extra_deps=libgcj-noncore-dummy.dll.a
+ ;;
*-cygwin* | *-mingw*)
fallback_backtrace_h=sysdep/i386/backtrace.h
# We need a frame pointer on Windows, so override BACKTRACESPEC
diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc
index b5ad91f2252..00766d0b102 100644
--- a/libjava/java/lang/natClass.cc
+++ b/libjava/java/lang/natClass.cc
@@ -1870,9 +1870,9 @@ _Jv_InterfaceAssignableFrom (jclass source, jclass iface)
{
for (int i = 0; i < source->interface_count; i++)
{
- jclass interface = source->interfaces[i];
- if (iface == interface
- || _Jv_InterfaceAssignableFrom (interface, iface))
+ jclass source_interface = source->interfaces[i];
+ if (iface == source_interface
+ || _Jv_InterfaceAssignableFrom (source_interface, iface))
return true;
}
diff --git a/libjava/testsuite/lib/libjava.exp b/libjava/testsuite/lib/libjava.exp
index 0de823b737c..0cfb25330a5 100644
--- a/libjava/testsuite/lib/libjava.exp
+++ b/libjava/testsuite/lib/libjava.exp
@@ -2,8 +2,10 @@
# Free Software Foundation
proc load_gcc_lib { filename } {
- global srcdir
+ global srcdir loaded_libs
+
load_file $srcdir/../../gcc/testsuite/lib/$filename
+ set loaded_libs($filename) ""
}
load_lib libgloss.exp
diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog
index 5a6cf6e66bd..b441ea3b705 100644
--- a/libsanitizer/ChangeLog
+++ b/libsanitizer/ChangeLog
@@ -1,3 +1,35 @@
+2014-05-30 Jakub Jelinek <jakub@redhat.com>
+
+ * sanitizer_common/sanitizer_stacktrace.cc: Cherry pick upstream
+ r209879.
+ * sanitizer_common/sanitizer_common.h: Likewise.
+ * asan/asan_mapping.h: Likewise.
+ * asan/asan_linux.cc: Likewise.
+ * tsan/tsan_mman.cc: Cherry pick upstream r209744.
+ * sanitizer_common/sanitizer_allocator.h: Likewise.
+
+2014-05-23 Marek Polacek <polacek@redhat.com>
+
+ * ubsan/ubsan_value.cc (getFloatValue): Handle 96-bit
+ floating-point types.
+
+2014-05-22 Kostya Serebryany <kcc@google.com>
+
+ * All source files: Merge from upstream r209283.
+ * asan/Makefile.am (asan_files): Added new files.
+ * asan/Makefile.in: Regenerate.
+ * tsan/Makefile.am (tsan_files): Added new files.
+ * tsan/Makefile.in: Regenerate.
+ * sanitizer_common/Makefile.am (sanitizer_common_files): Added new files.
+ * sanitizer_common/Makefile.in: Regenerate.
+
+2014-05-14 Yury Gribov <y.gribov@samsung.com>
+
+ PR sanitizer/61100
+ * Makefile.am (nodist_saninclude_HEADERS): Install
+ public headers.
+ * Makefile.in: Regenerate.
+
2014-03-07 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* libbacktrace/Makefile.am (libsanitizer_libbacktrace_la_SOURCES):
diff --git a/libsanitizer/MERGE b/libsanitizer/MERGE
index 4688f0c8693..84e88e10b77 100644
--- a/libsanitizer/MERGE
+++ b/libsanitizer/MERGE
@@ -1,4 +1,4 @@
-196489
+209283
The first line of this file holds the svn revision number of the
last merge done from the master library sources.
diff --git a/libsanitizer/Makefile.am b/libsanitizer/Makefile.am
index b0dc582ccfb..6b0c571c46e 100644
--- a/libsanitizer/Makefile.am
+++ b/libsanitizer/Makefile.am
@@ -1,7 +1,13 @@
ACLOCAL_AMFLAGS = -I .. -I ../config
+sanincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include/sanitizer
+
+nodist_saninclude_HEADERS =
+
if SANITIZER_SUPPORTED
SUBDIRS = sanitizer_common
+nodist_saninclude_HEADERS += \
+ include/sanitizer/common_interface_defs.h
if !USING_MAC_INTERPOSE
SUBDIRS += interception
endif
@@ -9,6 +15,9 @@ if LIBBACKTRACE_SUPPORTED
SUBDIRS += libbacktrace
endif
SUBDIRS += lsan asan ubsan
+nodist_saninclude_HEADERS += \
+ include/sanitizer/lsan_interface.h \
+ include/sanitizer/asan_interface.h
if TSAN_SUPPORTED
SUBDIRS += tsan
endif
diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in
index 60cbe2ee554..0b8924554dc 100644
--- a/libsanitizer/Makefile.in
+++ b/libsanitizer/Makefile.in
@@ -35,9 +35,12 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
-@SANITIZER_SUPPORTED_TRUE@@USING_MAC_INTERPOSE_FALSE@am__append_1 = interception
-@LIBBACKTRACE_SUPPORTED_TRUE@@SANITIZER_SUPPORTED_TRUE@am__append_2 = libbacktrace
-@SANITIZER_SUPPORTED_TRUE@@TSAN_SUPPORTED_TRUE@am__append_3 = tsan
+@SANITIZER_SUPPORTED_TRUE@am__append_1 = include/sanitizer/common_interface_defs.h \
+@SANITIZER_SUPPORTED_TRUE@ include/sanitizer/lsan_interface.h \
+@SANITIZER_SUPPORTED_TRUE@ include/sanitizer/asan_interface.h
+@SANITIZER_SUPPORTED_TRUE@@USING_MAC_INTERPOSE_FALSE@am__append_2 = interception
+@LIBBACKTRACE_SUPPORTED_TRUE@@SANITIZER_SUPPORTED_TRUE@am__append_3 = libbacktrace
+@SANITIZER_SUPPORTED_TRUE@@TSAN_SUPPORTED_TRUE@am__append_4 = tsan
subdir = .
DIST_COMMON = ChangeLog $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/configure $(am__configure_deps) \
@@ -98,8 +101,9 @@ am__nobase_list = $(am__nobase_strip_setup); \
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__installdirs = "$(DESTDIR)$(toolexeclibdir)"
-HEADERS = $(nodist_toolexeclib_HEADERS)
+am__installdirs = "$(DESTDIR)$(sanincludedir)" \
+ "$(DESTDIR)$(toolexeclibdir)"
+HEADERS = $(nodist_saninclude_HEADERS) $(nodist_toolexeclib_HEADERS)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
@@ -250,9 +254,11 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
ACLOCAL_AMFLAGS = -I .. -I ../config
-@SANITIZER_SUPPORTED_TRUE@SUBDIRS = sanitizer_common $(am__append_1) \
-@SANITIZER_SUPPORTED_TRUE@ $(am__append_2) lsan asan ubsan \
-@SANITIZER_SUPPORTED_TRUE@ $(am__append_3)
+sanincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include/sanitizer
+nodist_saninclude_HEADERS = $(am__append_1)
+@SANITIZER_SUPPORTED_TRUE@SUBDIRS = sanitizer_common $(am__append_2) \
+@SANITIZER_SUPPORTED_TRUE@ $(am__append_3) lsan asan ubsan \
+@SANITIZER_SUPPORTED_TRUE@ $(am__append_4)
gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
# Work around what appears to be a GNU make bug handling MAKEFLAGS
@@ -378,6 +384,26 @@ distclean-multi:
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean # $(MAKE)
maintainer-clean-multi:
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean # $(MAKE)
+install-nodist_sanincludeHEADERS: $(nodist_saninclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(sanincludedir)" || $(MKDIR_P) "$(DESTDIR)$(sanincludedir)"
+ @list='$(nodist_saninclude_HEADERS)'; test -n "$(sanincludedir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(sanincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(sanincludedir)" || exit $$?; \
+ done
+
+uninstall-nodist_sanincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nodist_saninclude_HEADERS)'; test -n "$(sanincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sanincludedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sanincludedir)" && rm -f $$files
install-nodist_toolexeclibHEADERS: $(nodist_toolexeclib_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(toolexeclibdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)"
@@ -538,7 +564,7 @@ check: check-recursive
all-am: Makefile all-multi $(HEADERS) config.h
installdirs: installdirs-recursive
installdirs-am:
- for dir in "$(DESTDIR)$(toolexeclibdir)"; do \
+ for dir in "$(DESTDIR)$(sanincludedir)" "$(DESTDIR)$(toolexeclibdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-recursive
@@ -588,7 +614,7 @@ info: info-recursive
info-am:
-install-data-am:
+install-data-am: install-nodist_sanincludeHEADERS
install-dvi: install-dvi-recursive
@@ -634,7 +660,8 @@ ps: ps-recursive
ps-am:
-uninstall-am: uninstall-nodist_toolexeclibHEADERS
+uninstall-am: uninstall-nodist_sanincludeHEADERS \
+ uninstall-nodist_toolexeclibHEADERS
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all all-multi \
clean-multi ctags-recursive distclean-multi install-am \
@@ -649,13 +676,14 @@ uninstall-am: uninstall-nodist_toolexeclibHEADERS
info-am install install-am install-data install-data-am \
install-dvi install-dvi-am install-exec install-exec-am \
install-html install-html-am install-info install-info-am \
- install-man install-multi install-nodist_toolexeclibHEADERS \
- install-pdf install-pdf-am install-ps install-ps-am \
- install-strip installcheck installcheck-am installdirs \
- installdirs-am maintainer-clean maintainer-clean-generic \
- maintainer-clean-multi mostlyclean mostlyclean-generic \
- mostlyclean-libtool mostlyclean-multi pdf pdf-am ps ps-am tags \
- tags-recursive uninstall uninstall-am \
+ install-man install-multi install-nodist_sanincludeHEADERS \
+ install-nodist_toolexeclibHEADERS install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic maintainer-clean-multi mostlyclean \
+ mostlyclean-generic mostlyclean-libtool mostlyclean-multi pdf \
+ pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+ uninstall-nodist_sanincludeHEADERS \
uninstall-nodist_toolexeclibHEADERS
diff --git a/libsanitizer/asan/Makefile.am b/libsanitizer/asan/Makefile.am
index 3f07a834c69..fdc2b4513d9 100644
--- a/libsanitizer/asan/Makefile.am
+++ b/libsanitizer/asan/Makefile.am
@@ -15,6 +15,7 @@ toolexeclib_LTLIBRARIES = libasan.la
nodist_toolexeclib_HEADERS = libasan_preinit.o
asan_files = \
+ asan_activation.cc \
asan_allocator2.cc \
asan_dll_thunk.cc \
asan_fake_stack.cc \
diff --git a/libsanitizer/asan/Makefile.in b/libsanitizer/asan/Makefile.in
index 273eb4b2645..cae6493fc9f 100644
--- a/libsanitizer/asan/Makefile.in
+++ b/libsanitizer/asan/Makefile.in
@@ -88,12 +88,13 @@ libasan_la_DEPENDENCIES = \
$(top_builddir)/sanitizer_common/libsanitizer_common.la \
$(top_builddir)/lsan/libsanitizer_lsan.la $(am__append_2) \
$(am__append_3) $(am__DEPENDENCIES_1)
-am__objects_1 = asan_allocator2.lo asan_dll_thunk.lo \
- asan_fake_stack.lo asan_globals.lo asan_interceptors.lo \
- asan_linux.lo asan_mac.lo asan_malloc_linux.lo \
- asan_malloc_mac.lo asan_malloc_win.lo asan_new_delete.lo \
- asan_poisoning.lo asan_posix.lo asan_report.lo asan_rtl.lo \
- asan_stack.lo asan_stats.lo asan_thread.lo asan_win.lo
+am__objects_1 = asan_activation.lo asan_allocator2.lo \
+ asan_dll_thunk.lo asan_fake_stack.lo asan_globals.lo \
+ asan_interceptors.lo asan_linux.lo asan_mac.lo \
+ asan_malloc_linux.lo asan_malloc_mac.lo asan_malloc_win.lo \
+ asan_new_delete.lo asan_poisoning.lo asan_posix.lo \
+ asan_report.lo asan_rtl.lo asan_stack.lo asan_stats.lo \
+ asan_thread.lo asan_win.lo
am_libasan_la_OBJECTS = $(am__objects_1)
libasan_la_OBJECTS = $(am_libasan_la_OBJECTS)
libasan_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
@@ -272,6 +273,7 @@ ACLOCAL_AMFLAGS = -I $(top_srcdir) -I $(top_srcdir)/config
toolexeclib_LTLIBRARIES = libasan.la
nodist_toolexeclib_HEADERS = libasan_preinit.o
asan_files = \
+ asan_activation.cc \
asan_allocator2.cc \
asan_dll_thunk.cc \
asan_fake_stack.cc \
@@ -412,6 +414,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_activation.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_allocator2.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_dll_thunk.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_fake_stack.Plo@am__quote@
diff --git a/libsanitizer/asan/asan_activation.cc b/libsanitizer/asan/asan_activation.cc
new file mode 100644
index 00000000000..235451c8aec
--- /dev/null
+++ b/libsanitizer/asan/asan_activation.cc
@@ -0,0 +1,72 @@
+//===-- asan_activation.cc --------------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan activation/deactivation logic.
+//===----------------------------------------------------------------------===//
+
+#include "asan_activation.h"
+#include "asan_allocator.h"
+#include "asan_flags.h"
+#include "asan_internal.h"
+#include "sanitizer_common/sanitizer_flags.h"
+
+namespace __asan {
+
+static struct AsanDeactivatedFlags {
+ int quarantine_size;
+ int max_redzone;
+ int malloc_context_size;
+ bool poison_heap;
+} asan_deactivated_flags;
+
+static bool asan_is_deactivated;
+
+void AsanStartDeactivated() {
+ VReport(1, "Deactivating ASan\n");
+ // Save flag values.
+ asan_deactivated_flags.quarantine_size = flags()->quarantine_size;
+ asan_deactivated_flags.max_redzone = flags()->max_redzone;
+ asan_deactivated_flags.poison_heap = flags()->poison_heap;
+ asan_deactivated_flags.malloc_context_size =
+ common_flags()->malloc_context_size;
+
+ flags()->quarantine_size = 0;
+ flags()->max_redzone = 16;
+ flags()->poison_heap = false;
+ common_flags()->malloc_context_size = 0;
+
+ asan_is_deactivated = true;
+}
+
+void AsanActivate() {
+ if (!asan_is_deactivated) return;
+ VReport(1, "Activating ASan\n");
+
+ // Restore flag values.
+ // FIXME: this is not atomic, and there may be other threads alive.
+ flags()->quarantine_size = asan_deactivated_flags.quarantine_size;
+ flags()->max_redzone = asan_deactivated_flags.max_redzone;
+ flags()->poison_heap = asan_deactivated_flags.poison_heap;
+ common_flags()->malloc_context_size =
+ asan_deactivated_flags.malloc_context_size;
+
+ ParseExtraActivationFlags();
+
+ ReInitializeAllocator();
+
+ asan_is_deactivated = false;
+ VReport(
+ 1,
+ "quarantine_size %d, max_redzone %d, poison_heap %d, malloc_context_size "
+ "%d\n",
+ flags()->quarantine_size, flags()->max_redzone, flags()->poison_heap,
+ common_flags()->malloc_context_size);
+}
+
+} // namespace __asan
diff --git a/libsanitizer/asan/asan_activation.h b/libsanitizer/asan/asan_activation.h
new file mode 100644
index 00000000000..01f2d46d222
--- /dev/null
+++ b/libsanitizer/asan/asan_activation.h
@@ -0,0 +1,21 @@
+//===-- asan_activation.h ---------------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan activation/deactivation logic.
+//===----------------------------------------------------------------------===//
+
+#ifndef ASAN_ACTIVATION_H
+#define ASAN_ACTIVATION_H
+
+namespace __asan {
+void AsanStartDeactivated();
+void AsanActivate();
+} // namespace __asan
+
+#endif // ASAN_ACTIVATION_H
diff --git a/libsanitizer/asan/asan_allocator.h b/libsanitizer/asan/asan_allocator.h
index 763f4a58ef9..174a5997d4b 100644
--- a/libsanitizer/asan/asan_allocator.h
+++ b/libsanitizer/asan/asan_allocator.h
@@ -15,6 +15,7 @@
#include "asan_internal.h"
#include "asan_interceptors.h"
+#include "sanitizer_common/sanitizer_allocator.h"
#include "sanitizer_common/sanitizer_list.h"
namespace __asan {
@@ -29,6 +30,7 @@ static const uptr kNumberOfSizeClasses = 255;
struct AsanChunk;
void InitializeAllocator();
+void ReInitializeAllocator();
class AsanChunkView {
public:
@@ -40,6 +42,7 @@ class AsanChunkView {
uptr UsedSize(); // Size requested by the user.
uptr AllocTid();
uptr FreeTid();
+ bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; }
void GetAllocStack(StackTrace *stack);
void GetFreeStack(StackTrace *stack);
bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) {
@@ -88,9 +91,46 @@ class AsanChunkFifoList: public IntrusiveList<AsanChunk> {
uptr size_;
};
+struct AsanMapUnmapCallback {
+ void OnMap(uptr p, uptr size) const;
+ void OnUnmap(uptr p, uptr size) const;
+};
+
+#if SANITIZER_CAN_USE_ALLOCATOR64
+# if defined(__powerpc64__)
+const uptr kAllocatorSpace = 0xa0000000000ULL;
+const uptr kAllocatorSize = 0x20000000000ULL; // 2T.
+# else
+const uptr kAllocatorSpace = 0x600000000000ULL;
+const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
+# endif
+typedef DefaultSizeClassMap SizeClassMap;
+typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0 /*metadata*/,
+ SizeClassMap, AsanMapUnmapCallback> PrimaryAllocator;
+#else // Fallback to SizeClassAllocator32.
+static const uptr kRegionSizeLog = 20;
+static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog;
+# if SANITIZER_WORDSIZE == 32
+typedef FlatByteMap<kNumRegions> ByteMap;
+# elif SANITIZER_WORDSIZE == 64
+typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap;
+# endif
+typedef CompactSizeClassMap SizeClassMap;
+typedef SizeClassAllocator32<0, SANITIZER_MMAP_RANGE_SIZE, 16,
+ SizeClassMap, kRegionSizeLog,
+ ByteMap,
+ AsanMapUnmapCallback> PrimaryAllocator;
+#endif // SANITIZER_CAN_USE_ALLOCATOR64
+
+typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
+typedef LargeMmapAllocator<AsanMapUnmapCallback> SecondaryAllocator;
+typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
+ SecondaryAllocator> Allocator;
+
+
struct AsanThreadLocalMallocStorage {
uptr quarantine_cache[16];
- uptr allocator2_cache[96 * (512 * 8 + 16)]; // Opaque.
+ AllocatorCache allocator2_cache;
void CommitBack();
private:
// These objects are allocated via mmap() and are zero-initialized.
diff --git a/libsanitizer/asan/asan_allocator2.cc b/libsanitizer/asan/asan_allocator2.cc
index b9d66dc7a4a..bbc1ff723a4 100644
--- a/libsanitizer/asan/asan_allocator2.cc
+++ b/libsanitizer/asan/asan_allocator2.cc
@@ -17,8 +17,8 @@
#include "asan_mapping.h"
#include "asan_poisoning.h"
#include "asan_report.h"
+#include "asan_stack.h"
#include "asan_thread.h"
-#include "sanitizer_common/sanitizer_allocator.h"
#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_list.h"
@@ -28,65 +28,30 @@
namespace __asan {
-struct AsanMapUnmapCallback {
- void OnMap(uptr p, uptr size) const {
- PoisonShadow(p, size, kAsanHeapLeftRedzoneMagic);
- // Statistics.
- AsanStats &thread_stats = GetCurrentThreadStats();
- thread_stats.mmaps++;
- thread_stats.mmaped += size;
- }
- void OnUnmap(uptr p, uptr size) const {
- PoisonShadow(p, size, 0);
- // We are about to unmap a chunk of user memory.
- // Mark the corresponding shadow memory as not needed.
- // Since asan's mapping is compacting, the shadow chunk may be
- // not page-aligned, so we only flush the page-aligned portion.
- uptr page_size = GetPageSizeCached();
- uptr shadow_beg = RoundUpTo(MemToShadow(p), page_size);
- uptr shadow_end = RoundDownTo(MemToShadow(p + size), page_size);
- FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg);
- // Statistics.
- AsanStats &thread_stats = GetCurrentThreadStats();
- thread_stats.munmaps++;
- thread_stats.munmaped += size;
- }
-};
-
-#if SANITIZER_WORDSIZE == 64
-#if defined(__powerpc64__)
-const uptr kAllocatorSpace = 0xa0000000000ULL;
-const uptr kAllocatorSize = 0x20000000000ULL; // 2T.
-#else
-const uptr kAllocatorSpace = 0x600000000000ULL;
-const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
-#endif
-typedef DefaultSizeClassMap SizeClassMap;
-typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0 /*metadata*/,
- SizeClassMap, AsanMapUnmapCallback> PrimaryAllocator;
-#elif SANITIZER_WORDSIZE == 32
-static const u64 kAddressSpaceSize = 1ULL << 32;
-typedef CompactSizeClassMap SizeClassMap;
-static const uptr kRegionSizeLog = 20;
-static const uptr kFlatByteMapSize = kAddressSpaceSize >> kRegionSizeLog;
-typedef SizeClassAllocator32<0, kAddressSpaceSize, 16,
- SizeClassMap, kRegionSizeLog,
- FlatByteMap<kFlatByteMapSize>,
- AsanMapUnmapCallback> PrimaryAllocator;
-#endif
-
-typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
-typedef LargeMmapAllocator<AsanMapUnmapCallback> SecondaryAllocator;
-typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
- SecondaryAllocator> Allocator;
+void AsanMapUnmapCallback::OnMap(uptr p, uptr size) const {
+ PoisonShadow(p, size, kAsanHeapLeftRedzoneMagic);
+ // Statistics.
+ AsanStats &thread_stats = GetCurrentThreadStats();
+ thread_stats.mmaps++;
+ thread_stats.mmaped += size;
+}
+void AsanMapUnmapCallback::OnUnmap(uptr p, uptr size) const {
+ PoisonShadow(p, size, 0);
+ // We are about to unmap a chunk of user memory.
+ // Mark the corresponding shadow memory as not needed.
+ FlushUnneededASanShadowMemory(p, size);
+ // Statistics.
+ AsanStats &thread_stats = GetCurrentThreadStats();
+ thread_stats.munmaps++;
+ thread_stats.munmaped += size;
+}
// We can not use THREADLOCAL because it is not supported on some of the
// platforms we care about (OSX 10.6, Android).
// static THREADLOCAL AllocatorCache cache;
AllocatorCache *GetAllocatorCache(AsanThreadLocalMallocStorage *ms) {
CHECK(ms);
- CHECK_LE(sizeof(AllocatorCache), sizeof(ms->allocator2_cache));
- return reinterpret_cast<AllocatorCache *>(ms->allocator2_cache);
+ return &ms->allocator2_cache;
}
static Allocator allocator;
@@ -132,7 +97,8 @@ static uptr ComputeRZLog(uptr user_requested_size) {
user_requested_size <= (1 << 14) - 256 ? 4 :
user_requested_size <= (1 << 15) - 512 ? 5 :
user_requested_size <= (1 << 16) - 1024 ? 6 : 7;
- return Max(rz_log, RZSize2Log(flags()->redzone));
+ return Min(Max(rz_log, RZSize2Log(flags()->redzone)),
+ RZSize2Log(flags()->max_redzone));
}
// The memory chunk allocated from the underlying allocator looks like this:
@@ -307,10 +273,14 @@ void InitializeAllocator() {
quarantine.Init((uptr)flags()->quarantine_size, kMaxThreadLocalQuarantine);
}
+void ReInitializeAllocator() {
+ quarantine.Init((uptr)flags()->quarantine_size, kMaxThreadLocalQuarantine);
+}
+
static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
AllocType alloc_type, bool can_fill) {
- if (!asan_inited)
- __asan_init();
+ if (UNLIKELY(!asan_inited))
+ AsanInitFromRtl();
Flags &fl = *flags();
CHECK(stack);
const uptr min_alignment = SHADOW_GRANULARITY;
@@ -355,6 +325,16 @@ static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
AllocatorCache *cache = &fallback_allocator_cache;
allocated = allocator.Allocate(cache, needed_size, 8, false);
}
+
+ if (*(u8 *)MEM_TO_SHADOW((uptr)allocated) == 0 && flags()->poison_heap) {
+ // Heap poisoning is enabled, but the allocator provides an unpoisoned
+ // chunk. This is possible if flags()->poison_heap was disabled for some
+ // time, for example, due to flags()->start_disabled.
+ // Anyway, poison the block before using it for anything else.
+ uptr allocated_size = allocator.GetActuallyAllocatedSize(allocated);
+ PoisonShadow((uptr)allocated, allocated_size, kAsanHeapLeftRedzoneMagic);
+ }
+
uptr alloc_beg = reinterpret_cast<uptr>(allocated);
uptr alloc_end = alloc_beg + needed_size;
uptr beg_plus_redzone = alloc_beg + rz_size;
@@ -708,8 +688,12 @@ uptr PointsIntoChunk(void* p) {
__asan::AsanChunk *m = __asan::GetAsanChunkByAddrFastLocked(addr);
if (!m) return 0;
uptr chunk = m->Beg();
- if ((m->chunk_state == __asan::CHUNK_ALLOCATED) &&
- m->AddrIsInside(addr, /*locked_version=*/true))
+ if (m->chunk_state != __asan::CHUNK_ALLOCATED)
+ return 0;
+ if (m->AddrIsInside(addr, /*locked_version=*/true))
+ return chunk;
+ if (IsSpecialCaseOfOperatorNew0(chunk, m->UsedSize(/*locked_version*/ true),
+ addr))
return chunk;
return 0;
}
@@ -778,7 +762,7 @@ uptr __asan_get_estimated_allocated_size(uptr size) {
return size;
}
-bool __asan_get_ownership(const void *p) {
+int __asan_get_ownership(const void *p) {
uptr ptr = reinterpret_cast<uptr>(p);
return (AllocationSize(ptr) > 0);
}
diff --git a/libsanitizer/asan/asan_asm_instrumentation.S b/libsanitizer/asan/asan_asm_instrumentation.S
new file mode 100644
index 00000000000..36a9d0b5e97
--- /dev/null
+++ b/libsanitizer/asan/asan_asm_instrumentation.S
@@ -0,0 +1,599 @@
+// This file was generated by gen_asm_instrumentation.sh. Please, do not edit
+.section .text
+#if defined(__x86_64__) || defined(__i386__)
+.globl __asan_report_store1
+.globl __asan_report_load1
+.globl __asan_report_store2
+.globl __asan_report_load2
+.globl __asan_report_store4
+.globl __asan_report_load4
+.globl __asan_report_store8
+.globl __asan_report_load8
+.globl __asan_report_store16
+.globl __asan_report_load16
+#endif // defined(__x86_64__) || defined(__i386__)
+#if defined(__i386__)
+// Sanitize 1-byte store. Takes one 4-byte address as an argument on
+// stack, nothing is returned.
+.globl __sanitizer_sanitize_store1
+.type __sanitizer_sanitize_store1, @function
+__sanitizer_sanitize_store1:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ pushfl
+ movl 8(%ebp), %eax
+ movl %eax, %ecx
+ shrl $0x3, %ecx
+ movb 0x20000000(%ecx), %cl
+ testb %cl, %cl
+ je .sanitize_store1_done
+ movl %eax, %edx
+ andl $0x7, %edx
+ movsbl %cl, %ecx
+ cmpl %ecx, %edx
+ jl .sanitize_store1_done
+ pushl %eax
+ cld
+ emms
+ call __asan_report_store1@PLT
+.sanitize_store1_done:
+ popfl
+ popl %edx
+ popl %ecx
+ popl %eax
+ leave
+ ret
+// Sanitize 1-byte load. Takes one 4-byte address as an argument on
+// stack, nothing is returned.
+.globl __sanitizer_sanitize_load1
+.type __sanitizer_sanitize_load1, @function
+__sanitizer_sanitize_load1:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ pushfl
+ movl 8(%ebp), %eax
+ movl %eax, %ecx
+ shrl $0x3, %ecx
+ movb 0x20000000(%ecx), %cl
+ testb %cl, %cl
+ je .sanitize_load1_done
+ movl %eax, %edx
+ andl $0x7, %edx
+ movsbl %cl, %ecx
+ cmpl %ecx, %edx
+ jl .sanitize_load1_done
+ pushl %eax
+ cld
+ emms
+ call __asan_report_load1@PLT
+.sanitize_load1_done:
+ popfl
+ popl %edx
+ popl %ecx
+ popl %eax
+ leave
+ ret
+// Sanitize 2-byte store. Takes one 4-byte address as an argument on
+// stack, nothing is returned.
+.globl __sanitizer_sanitize_store2
+.type __sanitizer_sanitize_store2, @function
+__sanitizer_sanitize_store2:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ pushfl
+ movl 8(%ebp), %eax
+ movl %eax, %ecx
+ shrl $0x3, %ecx
+ movb 0x20000000(%ecx), %cl
+ testb %cl, %cl
+ je .sanitize_store2_done
+ movl %eax, %edx
+ andl $0x7, %edx
+ incl %edx
+ movsbl %cl, %ecx
+ cmpl %ecx, %edx
+ jl .sanitize_store2_done
+ pushl %eax
+ cld
+ emms
+ call __asan_report_store2@PLT
+.sanitize_store2_done:
+ popfl
+ popl %edx
+ popl %ecx
+ popl %eax
+ leave
+ ret
+// Sanitize 2-byte load. Takes one 4-byte address as an argument on
+// stack, nothing is returned.
+.globl __sanitizer_sanitize_load2
+.type __sanitizer_sanitize_load2, @function
+__sanitizer_sanitize_load2:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ pushfl
+ movl 8(%ebp), %eax
+ movl %eax, %ecx
+ shrl $0x3, %ecx
+ movb 0x20000000(%ecx), %cl
+ testb %cl, %cl
+ je .sanitize_load2_done
+ movl %eax, %edx
+ andl $0x7, %edx
+ incl %edx
+ movsbl %cl, %ecx
+ cmpl %ecx, %edx
+ jl .sanitize_load2_done
+ pushl %eax
+ cld
+ emms
+ call __asan_report_load2@PLT
+.sanitize_load2_done:
+ popfl
+ popl %edx
+ popl %ecx
+ popl %eax
+ leave
+ ret
+// Sanitize 4-byte store. Takes one 4-byte address as an argument on
+// stack, nothing is returned.
+.globl __sanitizer_sanitize_store4
+.type __sanitizer_sanitize_store4, @function
+__sanitizer_sanitize_store4:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ pushfl
+ movl 8(%ebp), %eax
+ movl %eax, %ecx
+ shrl $0x3, %ecx
+ movb 0x20000000(%ecx), %cl
+ testb %cl, %cl
+ je .sanitize_store4_done
+ movl %eax, %edx
+ andl $0x7, %edx
+ addl $0x3, %edx
+ movsbl %cl, %ecx
+ cmpl %ecx, %edx
+ jl .sanitize_store4_done
+ pushl %eax
+ cld
+ emms
+ call __asan_report_store4@PLT
+.sanitize_store4_done:
+ popfl
+ popl %edx
+ popl %ecx
+ popl %eax
+ leave
+ ret
+// Sanitize 4-byte load. Takes one 4-byte address as an argument on
+// stack, nothing is returned.
+.globl __sanitizer_sanitize_load4
+.type __sanitizer_sanitize_load4, @function
+__sanitizer_sanitize_load4:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ pushfl
+ movl 8(%ebp), %eax
+ movl %eax, %ecx
+ shrl $0x3, %ecx
+ movb 0x20000000(%ecx), %cl
+ testb %cl, %cl
+ je .sanitize_load4_done
+ movl %eax, %edx
+ andl $0x7, %edx
+ addl $0x3, %edx
+ movsbl %cl, %ecx
+ cmpl %ecx, %edx
+ jl .sanitize_load4_done
+ pushl %eax
+ cld
+ emms
+ call __asan_report_load4@PLT
+.sanitize_load4_done:
+ popfl
+ popl %edx
+ popl %ecx
+ popl %eax
+ leave
+ ret
+// Sanitize 8-byte store. Takes one 4-byte address as an argument on
+// stack, nothing is returned.
+.globl __sanitizer_sanitize_store8
+.type __sanitizer_sanitize_store8, @function
+__sanitizer_sanitize_store8:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %eax
+ pushl %ecx
+ pushfl
+ movl 8(%ebp), %eax
+ movl %eax, %ecx
+ shrl $0x3, %ecx
+ cmpb $0x0, 0x20000000(%ecx)
+ je .sanitize_store8_done
+ pushl %eax
+ cld
+ emms
+ call __asan_report_store8@PLT
+.sanitize_store8_done:
+ popfl
+ popl %ecx
+ popl %eax
+ leave
+ ret
+// Sanitize 8-byte load. Takes one 4-byte address as an argument on
+// stack, nothing is returned.
+.globl __sanitizer_sanitize_load8
+.type __sanitizer_sanitize_load8, @function
+__sanitizer_sanitize_load8:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %eax
+ pushl %ecx
+ pushfl
+ movl 8(%ebp), %eax
+ movl %eax, %ecx
+ shrl $0x3, %ecx
+ cmpb $0x0, 0x20000000(%ecx)
+ je .sanitize_load8_done
+ pushl %eax
+ cld
+ emms
+ call __asan_report_load8@PLT
+.sanitize_load8_done:
+ popfl
+ popl %ecx
+ popl %eax
+ leave
+ ret
+// Sanitize 16-byte store. Takes one 4-byte address as an argument on
+// stack, nothing is returned.
+.globl __sanitizer_sanitize_store16
+.type __sanitizer_sanitize_store16, @function
+__sanitizer_sanitize_store16:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %eax
+ pushl %ecx
+ pushfl
+ movl 8(%ebp), %eax
+ movl %eax, %ecx
+ shrl $0x3, %ecx
+ cmpw $0x0, 0x20000000(%ecx)
+ je .sanitize_store16_done
+ pushl %eax
+ cld
+ emms
+ call __asan_report_store16@PLT
+.sanitize_store16_done:
+ popfl
+ popl %ecx
+ popl %eax
+ leave
+ ret
+// Sanitize 16-byte load. Takes one 4-byte address as an argument on
+// stack, nothing is returned.
+.globl __sanitizer_sanitize_load16
+.type __sanitizer_sanitize_load16, @function
+__sanitizer_sanitize_load16:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %eax
+ pushl %ecx
+ pushfl
+ movl 8(%ebp), %eax
+ movl %eax, %ecx
+ shrl $0x3, %ecx
+ cmpw $0x0, 0x20000000(%ecx)
+ je .sanitize_load16_done
+ pushl %eax
+ cld
+ emms
+ call __asan_report_load16@PLT
+.sanitize_load16_done:
+ popfl
+ popl %ecx
+ popl %eax
+ leave
+ ret
+#endif // defined(__i386__)
+#if defined(__x86_64__)
+// Sanitize 1-byte store. Takes one 8-byte address as an argument in %rdi,
+// nothing is returned.
+.globl __sanitizer_sanitize_store1
+.type __sanitizer_sanitize_store1, @function
+__sanitizer_sanitize_store1:
+ leaq -128(%rsp), %rsp
+ pushq %rax
+ pushq %rcx
+ pushfq
+ movq %rdi, %rax
+ shrq $0x3, %rax
+ movb 0x7fff8000(%rax), %al
+ test %al, %al
+ je .sanitize_store1_done
+ movl %edi, %ecx
+ andl $0x7, %ecx
+ movsbl %al, %eax
+ cmpl %eax, %ecx
+ jl .sanitize_store1_done
+ subq $8, %rsp
+ andq $-16, %rsp
+ cld
+ emms
+ call __asan_report_store1@PLT
+.sanitize_store1_done:
+ popfq
+ popq %rcx
+ popq %rax
+ leaq 128(%rsp), %rsp
+ ret
+// Sanitize 1-byte load. Takes one 8-byte address as an argument in %rdi,
+// nothing is returned.
+.globl __sanitizer_sanitize_load1
+.type __sanitizer_sanitize_load1, @function
+__sanitizer_sanitize_load1:
+ leaq -128(%rsp), %rsp
+ pushq %rax
+ pushq %rcx
+ pushfq
+ movq %rdi, %rax
+ shrq $0x3, %rax
+ movb 0x7fff8000(%rax), %al
+ test %al, %al
+ je .sanitize_load1_done
+ movl %edi, %ecx
+ andl $0x7, %ecx
+ movsbl %al, %eax
+ cmpl %eax, %ecx
+ jl .sanitize_load1_done
+ subq $8, %rsp
+ andq $-16, %rsp
+ cld
+ emms
+ call __asan_report_load1@PLT
+.sanitize_load1_done:
+ popfq
+ popq %rcx
+ popq %rax
+ leaq 128(%rsp), %rsp
+ ret
+// Sanitize 2-byte store. Takes one 8-byte address as an argument in %rdi,
+// nothing is returned.
+.globl __sanitizer_sanitize_store2
+.type __sanitizer_sanitize_store2, @function
+__sanitizer_sanitize_store2:
+ leaq -128(%rsp), %rsp
+ pushq %rax
+ pushq %rcx
+ pushfq
+ movq %rdi, %rax
+ shrq $0x3, %rax
+ movb 0x7fff8000(%rax), %al
+ test %al, %al
+ je .sanitize_store2_done
+ movl %edi, %ecx
+ andl $0x7, %ecx
+ incl %ecx
+ movsbl %al, %eax
+ cmpl %eax, %ecx
+ jl .sanitize_store2_done
+ subq $8, %rsp
+ andq $-16, %rsp
+ cld
+ emms
+ call __asan_report_store2@PLT
+.sanitize_store2_done:
+ popfq
+ popq %rcx
+ popq %rax
+ leaq 128(%rsp), %rsp
+ ret
+// Sanitize 2-byte load. Takes one 8-byte address as an argument in %rdi,
+// nothing is returned.
+.globl __sanitizer_sanitize_load2
+.type __sanitizer_sanitize_load2, @function
+__sanitizer_sanitize_load2:
+ leaq -128(%rsp), %rsp
+ pushq %rax
+ pushq %rcx
+ pushfq
+ movq %rdi, %rax
+ shrq $0x3, %rax
+ movb 0x7fff8000(%rax), %al
+ test %al, %al
+ je .sanitize_load2_done
+ movl %edi, %ecx
+ andl $0x7, %ecx
+ incl %ecx
+ movsbl %al, %eax
+ cmpl %eax, %ecx
+ jl .sanitize_load2_done
+ subq $8, %rsp
+ andq $-16, %rsp
+ cld
+ emms
+ call __asan_report_load2@PLT
+.sanitize_load2_done:
+ popfq
+ popq %rcx
+ popq %rax
+ leaq 128(%rsp), %rsp
+ ret
+// Sanitize 4-byte store. Takes one 8-byte address as an argument in %rdi,
+// nothing is returned.
+.globl __sanitizer_sanitize_store4
+.type __sanitizer_sanitize_store4, @function
+__sanitizer_sanitize_store4:
+ leaq -128(%rsp), %rsp
+ pushq %rax
+ pushq %rcx
+ pushfq
+ movq %rdi, %rax
+ shrq $0x3, %rax
+ movb 0x7fff8000(%rax), %al
+ test %al, %al
+ je .sanitize_store4_done
+ movl %edi, %ecx
+ andl $0x7, %ecx
+ addl $0x3, %ecx
+ movsbl %al, %eax
+ cmpl %eax, %ecx
+ jl .sanitize_store4_done
+ subq $8, %rsp
+ andq $-16, %rsp
+ cld
+ emms
+ call __asan_report_store4@PLT
+.sanitize_store4_done:
+ popfq
+ popq %rcx
+ popq %rax
+ leaq 128(%rsp), %rsp
+ ret
+// Sanitize 4-byte load. Takes one 8-byte address as an argument in %rdi,
+// nothing is returned.
+.globl __sanitizer_sanitize_load4
+.type __sanitizer_sanitize_load4, @function
+__sanitizer_sanitize_load4:
+ leaq -128(%rsp), %rsp
+ pushq %rax
+ pushq %rcx
+ pushfq
+ movq %rdi, %rax
+ shrq $0x3, %rax
+ movb 0x7fff8000(%rax), %al
+ test %al, %al
+ je .sanitize_load4_done
+ movl %edi, %ecx
+ andl $0x7, %ecx
+ addl $0x3, %ecx
+ movsbl %al, %eax
+ cmpl %eax, %ecx
+ jl .sanitize_load4_done
+ subq $8, %rsp
+ andq $-16, %rsp
+ cld
+ emms
+ call __asan_report_load4@PLT
+.sanitize_load4_done:
+ popfq
+ popq %rcx
+ popq %rax
+ leaq 128(%rsp), %rsp
+ ret
+// Sanitize 8-byte store. Takes one 8-byte address as an argument in %rdi,
+// nothing is returned.
+.globl __sanitizer_sanitize_store8
+.type __sanitizer_sanitize_store8, @function
+__sanitizer_sanitize_store8:
+ leaq -128(%rsp), %rsp
+ pushq %rax
+ pushfq
+ movq %rdi, %rax
+ shrq $0x3, %rax
+ cmpb $0x0, 0x7fff8000(%rax)
+ je .sanitize_store8_done
+ subq $8, %rsp
+ andq $-16, %rsp
+ cld
+ emms
+ call __asan_report_store8@PLT
+.sanitize_store8_done:
+ popfq
+ popq %rax
+ leaq 128(%rsp), %rsp
+ ret
+// Sanitize 8-byte load. Takes one 8-byte address as an argument in %rdi,
+// nothing is returned.
+.globl __sanitizer_sanitize_load8
+.type __sanitizer_sanitize_load8, @function
+__sanitizer_sanitize_load8:
+ leaq -128(%rsp), %rsp
+ pushq %rax
+ pushfq
+ movq %rdi, %rax
+ shrq $0x3, %rax
+ cmpb $0x0, 0x7fff8000(%rax)
+ je .sanitize_load8_done
+ subq $8, %rsp
+ andq $-16, %rsp
+ cld
+ emms
+ call __asan_report_load8@PLT
+.sanitize_load8_done:
+ popfq
+ popq %rax
+ leaq 128(%rsp), %rsp
+ ret
+// Sanitize 16-byte store. Takes one 8-byte address as an argument in %rdi,
+// nothing is returned.
+.globl __sanitizer_sanitize_store16
+.type __sanitizer_sanitize_store16, @function
+__sanitizer_sanitize_store16:
+ leaq -128(%rsp), %rsp
+ pushq %rax
+ pushfq
+ movq %rdi, %rax
+ shrq $0x3, %rax
+ cmpw $0x0, 0x7fff8000(%rax)
+ je .sanitize_store16_done
+ subq $8, %rsp
+ andq $-16, %rsp
+ cld
+ emms
+ call __asan_report_store16@PLT
+.sanitize_store16_done:
+ popfq
+ popq %rax
+ leaq 128(%rsp), %rsp
+ ret
+// Sanitize 16-byte load. Takes one 8-byte address as an argument in %rdi,
+// nothing is returned.
+.globl __sanitizer_sanitize_load16
+.type __sanitizer_sanitize_load16, @function
+__sanitizer_sanitize_load16:
+ leaq -128(%rsp), %rsp
+ pushq %rax
+ pushfq
+ movq %rdi, %rax
+ shrq $0x3, %rax
+ cmpw $0x0, 0x7fff8000(%rax)
+ je .sanitize_load16_done
+ subq $8, %rsp
+ andq $-16, %rsp
+ cld
+ emms
+ call __asan_report_load16@PLT
+.sanitize_load16_done:
+ popfq
+ popq %rax
+ leaq 128(%rsp), %rsp
+ ret
+#endif // defined(__x86_64__)
+/* We do not need executable stack. */
+#if defined(__arm__)
+ .section .note.GNU-stack,"",%progbits
+#else
+ .section .note.GNU-stack,"",@progbits
+#endif // defined(__arm__)
+#endif // __linux__
diff --git a/libsanitizer/asan/asan_dll_thunk.cc b/libsanitizer/asan/asan_dll_thunk.cc
index 19c31f0def8..5bed39ac066 100644
--- a/libsanitizer/asan/asan_dll_thunk.cc
+++ b/libsanitizer/asan/asan_dll_thunk.cc
@@ -18,6 +18,7 @@
// Using #ifdef rather than relying on Makefiles etc.
// simplifies the build procedure.
#ifdef ASAN_DLL_THUNK
+#include "sanitizer_common/sanitizer_interception.h"
// ----------------- Helper functions and macros --------------------- {{{1
extern "C" {
@@ -113,7 +114,50 @@ static void *getRealProcAddressOrDie(const char *name) {
}
// }}}
+// --------- Interface interception helper functions and macros ----------- {{{1
+// We need to intercept the ASan interface exported by the DLL thunk and forward
+// all the functions to the runtime in the main module.
+// However, we don't want to keep two lists of interface functions.
+// To avoid that, the list of interface functions should be defined using the
+// INTERFACE_FUNCTION macro. Then, all the interface can be intercepted at once
+// by calling INTERCEPT_ASAN_INTERFACE().
+
+// Use macro+template magic to automatically generate the list of interface
+// functions. Each interface function at line LINE defines a template class
+// with a static InterfaceInteceptor<LINE>::Execute() method intercepting the
+// function. The default implementation of InterfaceInteceptor<LINE> is to call
+// the Execute() method corresponding to the previous line.
+template<int LINE>
+struct InterfaceInteceptor {
+ static void Execute() { InterfaceInteceptor<LINE-1>::Execute(); }
+};
+
+// There shouldn't be any interface function with negative line number.
+template<>
+struct InterfaceInteceptor<0> {
+ static void Execute() {}
+};
+
+#define INTERFACE_FUNCTION(name) \
+ extern "C" void name() { __debugbreak(); } \
+ template<> struct InterfaceInteceptor<__LINE__> { \
+ static void Execute() { \
+ void *wrapper = getRealProcAddressOrDie(#name); \
+ if (!__interception::OverrideFunction((uptr)name, (uptr)wrapper, 0)) \
+ abort(); \
+ InterfaceInteceptor<__LINE__-1>::Execute(); \
+ } \
+ };
+
+// INTERCEPT_ASAN_INTERFACE must be used after the last INTERFACE_FUNCTION.
+#define INTERCEPT_ASAN_INTERFACE InterfaceInteceptor<__LINE__>::Execute
+
+static void InterceptASanInterface();
+// }}}
+
// ----------------- ASan own interface functions --------------------
+// Don't use the INTERFACE_FUNCTION machinery for this function as we actually
+// want to call it in the __asan_init interceptor.
WRAP_W_V(__asan_should_detect_stack_use_after_return)
extern "C" {
@@ -123,54 +167,75 @@ extern "C" {
// __asan_option_detect_stack_use_after_return afterwards.
void __asan_init_v3() {
typedef void (*fntype)();
- static fntype fn = (fntype)getRealProcAddressOrDie("__asan_init_v3");
+ static fntype fn = 0;
+ if (fn) return;
+
+ fn = (fntype)getRealProcAddressOrDie("__asan_init_v3");
fn();
__asan_option_detect_stack_use_after_return =
(__asan_should_detect_stack_use_after_return() != 0);
+
+ InterceptASanInterface();
}
}
-WRAP_V_V(__asan_handle_no_return)
-
-WRAP_V_W(__asan_report_store1)
-WRAP_V_W(__asan_report_store2)
-WRAP_V_W(__asan_report_store4)
-WRAP_V_W(__asan_report_store8)
-WRAP_V_W(__asan_report_store16)
-WRAP_V_WW(__asan_report_store_n)
-
-WRAP_V_W(__asan_report_load1)
-WRAP_V_W(__asan_report_load2)
-WRAP_V_W(__asan_report_load4)
-WRAP_V_W(__asan_report_load8)
-WRAP_V_W(__asan_report_load16)
-WRAP_V_WW(__asan_report_load_n)
-
-WRAP_V_WW(__asan_register_globals)
-WRAP_V_WW(__asan_unregister_globals)
-
-WRAP_W_WW(__asan_stack_malloc_0)
-WRAP_W_WW(__asan_stack_malloc_1)
-WRAP_W_WW(__asan_stack_malloc_2)
-WRAP_W_WW(__asan_stack_malloc_3)
-WRAP_W_WW(__asan_stack_malloc_4)
-WRAP_W_WW(__asan_stack_malloc_5)
-WRAP_W_WW(__asan_stack_malloc_6)
-WRAP_W_WW(__asan_stack_malloc_7)
-WRAP_W_WW(__asan_stack_malloc_8)
-WRAP_W_WW(__asan_stack_malloc_9)
-WRAP_W_WW(__asan_stack_malloc_10)
-
-WRAP_V_WWW(__asan_stack_free_0)
-WRAP_V_WWW(__asan_stack_free_1)
-WRAP_V_WWW(__asan_stack_free_2)
-WRAP_V_WWW(__asan_stack_free_4)
-WRAP_V_WWW(__asan_stack_free_5)
-WRAP_V_WWW(__asan_stack_free_6)
-WRAP_V_WWW(__asan_stack_free_7)
-WRAP_V_WWW(__asan_stack_free_8)
-WRAP_V_WWW(__asan_stack_free_9)
-WRAP_V_WWW(__asan_stack_free_10)
+INTERFACE_FUNCTION(__asan_handle_no_return)
+
+INTERFACE_FUNCTION(__asan_report_store1)
+INTERFACE_FUNCTION(__asan_report_store2)
+INTERFACE_FUNCTION(__asan_report_store4)
+INTERFACE_FUNCTION(__asan_report_store8)
+INTERFACE_FUNCTION(__asan_report_store16)
+INTERFACE_FUNCTION(__asan_report_store_n)
+
+INTERFACE_FUNCTION(__asan_report_load1)
+INTERFACE_FUNCTION(__asan_report_load2)
+INTERFACE_FUNCTION(__asan_report_load4)
+INTERFACE_FUNCTION(__asan_report_load8)
+INTERFACE_FUNCTION(__asan_report_load16)
+INTERFACE_FUNCTION(__asan_report_load_n)
+
+INTERFACE_FUNCTION(__asan_memcpy);
+INTERFACE_FUNCTION(__asan_memset);
+INTERFACE_FUNCTION(__asan_memmove);
+
+INTERFACE_FUNCTION(__asan_register_globals)
+INTERFACE_FUNCTION(__asan_unregister_globals)
+
+INTERFACE_FUNCTION(__asan_before_dynamic_init)
+INTERFACE_FUNCTION(__asan_after_dynamic_init)
+
+INTERFACE_FUNCTION(__asan_poison_stack_memory)
+INTERFACE_FUNCTION(__asan_unpoison_stack_memory)
+
+INTERFACE_FUNCTION(__asan_poison_memory_region)
+INTERFACE_FUNCTION(__asan_unpoison_memory_region)
+
+INTERFACE_FUNCTION(__asan_get_current_fake_stack)
+INTERFACE_FUNCTION(__asan_addr_is_in_fake_stack)
+
+INTERFACE_FUNCTION(__asan_stack_malloc_0)
+INTERFACE_FUNCTION(__asan_stack_malloc_1)
+INTERFACE_FUNCTION(__asan_stack_malloc_2)
+INTERFACE_FUNCTION(__asan_stack_malloc_3)
+INTERFACE_FUNCTION(__asan_stack_malloc_4)
+INTERFACE_FUNCTION(__asan_stack_malloc_5)
+INTERFACE_FUNCTION(__asan_stack_malloc_6)
+INTERFACE_FUNCTION(__asan_stack_malloc_7)
+INTERFACE_FUNCTION(__asan_stack_malloc_8)
+INTERFACE_FUNCTION(__asan_stack_malloc_9)
+INTERFACE_FUNCTION(__asan_stack_malloc_10)
+
+INTERFACE_FUNCTION(__asan_stack_free_0)
+INTERFACE_FUNCTION(__asan_stack_free_1)
+INTERFACE_FUNCTION(__asan_stack_free_2)
+INTERFACE_FUNCTION(__asan_stack_free_4)
+INTERFACE_FUNCTION(__asan_stack_free_5)
+INTERFACE_FUNCTION(__asan_stack_free_6)
+INTERFACE_FUNCTION(__asan_stack_free_7)
+INTERFACE_FUNCTION(__asan_stack_free_8)
+INTERFACE_FUNCTION(__asan_stack_free_9)
+INTERFACE_FUNCTION(__asan_stack_free_10)
// TODO(timurrrr): Add more interface functions on the as-needed basis.
@@ -190,7 +255,16 @@ WRAP_W_WWW(_realloc_dbg)
WRAP_W_WWW(_recalloc)
WRAP_W_W(_msize)
+WRAP_W_W(_expand)
+WRAP_W_W(_expand_dbg)
+
+// TODO(timurrrr): Might want to add support for _aligned_* allocation
+// functions to detect a bit more bugs. Those functions seem to wrap malloc().
// TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cc).
+void InterceptASanInterface() {
+ INTERCEPT_ASAN_INTERFACE();
+}
+
#endif // ASAN_DLL_THUNK
diff --git a/libsanitizer/asan/asan_fake_stack.cc b/libsanitizer/asan/asan_fake_stack.cc
index cf4122472ef..cfe96a0882f 100644
--- a/libsanitizer/asan/asan_fake_stack.cc
+++ b/libsanitizer/asan/asan_fake_stack.cc
@@ -40,21 +40,32 @@ FakeStack *FakeStack::Create(uptr stack_size_log) {
stack_size_log = kMinStackSizeLog;
if (stack_size_log > kMaxStackSizeLog)
stack_size_log = kMaxStackSizeLog;
+ uptr size = RequiredSize(stack_size_log);
FakeStack *res = reinterpret_cast<FakeStack *>(
- MmapOrDie(RequiredSize(stack_size_log), "FakeStack"));
+ flags()->uar_noreserve ? MmapNoReserveOrDie(size, "FakeStack")
+ : MmapOrDie(size, "FakeStack"));
res->stack_size_log_ = stack_size_log;
- if (common_flags()->verbosity) {
- u8 *p = reinterpret_cast<u8 *>(res);
- Report("T%d: FakeStack created: %p -- %p stack_size_log: %zd \n",
- GetCurrentTidOrInvalid(), p,
- p + FakeStack::RequiredSize(stack_size_log), stack_size_log);
- }
+ u8 *p = reinterpret_cast<u8 *>(res);
+ VReport(1, "T%d: FakeStack created: %p -- %p stack_size_log: %zd; "
+ "mmapped %zdK, noreserve=%d \n",
+ GetCurrentTidOrInvalid(), p,
+ p + FakeStack::RequiredSize(stack_size_log), stack_size_log,
+ size >> 10, flags()->uar_noreserve);
return res;
}
-void FakeStack::Destroy() {
+void FakeStack::Destroy(int tid) {
PoisonAll(0);
- UnmapOrDie(this, RequiredSize(stack_size_log_));
+ if (common_flags()->verbosity >= 2) {
+ InternalScopedString str(kNumberOfSizeClasses * 50);
+ for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++)
+ str.append("%zd: %zd/%zd; ", class_id, hint_position_[class_id],
+ NumberOfFrames(stack_size_log(), class_id));
+ Report("T%d: FakeStack destroyed: %s\n", tid, str.data());
+ }
+ uptr size = RequiredSize(stack_size_log_);
+ FlushUnneededASanShadowMemory(reinterpret_cast<uptr>(this), size);
+ UnmapOrDie(this, size);
}
void FakeStack::PoisonAll(u8 magic) {
@@ -91,7 +102,7 @@ FakeFrame *FakeStack::Allocate(uptr stack_size_log, uptr class_id,
return 0; // We are out of fake stack.
}
-uptr FakeStack::AddrIsInFakeStack(uptr ptr) {
+uptr FakeStack::AddrIsInFakeStack(uptr ptr, uptr *frame_beg, uptr *frame_end) {
uptr stack_size_log = this->stack_size_log();
uptr beg = reinterpret_cast<uptr>(GetFrame(stack_size_log, 0, 0));
uptr end = reinterpret_cast<uptr>(this) + RequiredSize(stack_size_log);
@@ -101,7 +112,10 @@ uptr FakeStack::AddrIsInFakeStack(uptr ptr) {
CHECK_LE(base, ptr);
CHECK_LT(ptr, base + (1UL << stack_size_log));
uptr pos = (ptr - base) >> (kMinStackFrameSizeLog + class_id);
- return base + pos * BytesInSizeClass(class_id);
+ uptr res = base + pos * BytesInSizeClass(class_id);
+ *frame_end = res + BytesInSizeClass(class_id);
+ *frame_beg = res + sizeof(FakeFrame);
+ return res;
}
void FakeStack::HandleNoReturn() {
@@ -195,14 +209,15 @@ ALWAYS_INLINE void OnFree(uptr ptr, uptr class_id, uptr size, uptr real_stack) {
} // namespace __asan
// ---------------------- Interface ---------------- {{{1
+using namespace __asan;
#define DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(class_id) \
extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr \
__asan_stack_malloc_##class_id(uptr size, uptr real_stack) { \
- return __asan::OnMalloc(class_id, size, real_stack); \
+ return OnMalloc(class_id, size, real_stack); \
} \
extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __asan_stack_free_##class_id( \
uptr ptr, uptr size, uptr real_stack) { \
- __asan::OnFree(ptr, class_id, size, real_stack); \
+ OnFree(ptr, class_id, size, real_stack); \
}
DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(0)
@@ -216,3 +231,23 @@ DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(7)
DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(8)
DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(9)
DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(10)
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__asan_get_current_fake_stack() { return GetFakeStackFast(); }
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg,
+ void **end) {
+ FakeStack *fs = reinterpret_cast<FakeStack*>(fake_stack);
+ if (!fs) return 0;
+ uptr frame_beg, frame_end;
+ FakeFrame *frame = reinterpret_cast<FakeFrame *>(fs->AddrIsInFakeStack(
+ reinterpret_cast<uptr>(addr), &frame_beg, &frame_end));
+ if (!frame) return 0;
+ if (frame->magic != kCurrentStackFrameMagic)
+ return 0;
+ if (beg) *beg = reinterpret_cast<void*>(frame_beg);
+ if (end) *end = reinterpret_cast<void*>(frame_end);
+ return reinterpret_cast<void*>(frame->real_stack);
+}
+} // extern "C"
diff --git a/libsanitizer/asan/asan_fake_stack.h b/libsanitizer/asan/asan_fake_stack.h
index 5196025681c..550a86e2972 100644
--- a/libsanitizer/asan/asan_fake_stack.h
+++ b/libsanitizer/asan/asan_fake_stack.h
@@ -63,7 +63,7 @@ class FakeStack {
// CTOR: create the FakeStack as a single mmap-ed object.
static FakeStack *Create(uptr stack_size_log);
- void Destroy();
+ void Destroy(int tid);
// stack_size_log is at least 15 (stack_size >= 32K).
static uptr SizeRequiredForFlags(uptr stack_size_log) {
@@ -127,7 +127,11 @@ class FakeStack {
void PoisonAll(u8 magic);
// Return the beginning of the FakeFrame or 0 if the address is not ours.
- uptr AddrIsInFakeStack(uptr addr);
+ uptr AddrIsInFakeStack(uptr addr, uptr *frame_beg, uptr *frame_end);
+ USED uptr AddrIsInFakeStack(uptr addr) {
+ uptr t1, t2;
+ return AddrIsInFakeStack(addr, &t1, &t2);
+ }
// Number of bytes in a fake frame of this size class.
static uptr BytesInSizeClass(uptr class_id) {
diff --git a/libsanitizer/asan/asan_flags.h b/libsanitizer/asan/asan_flags.h
index 62b5d3215d3..42463a69b99 100644
--- a/libsanitizer/asan/asan_flags.h
+++ b/libsanitizer/asan/asan_flags.h
@@ -26,88 +26,42 @@
namespace __asan {
struct Flags {
- // Size (in bytes) of quarantine used to detect use-after-free errors.
- // Lower value may reduce memory usage but increase the chance of
- // false negatives.
+ // Flag descriptions are in asan_rtl.cc.
int quarantine_size;
- // Size (in bytes) of redzones around heap objects.
- // Requirement: redzone >= 32, is a power of two.
int redzone;
- // If set, prints some debugging information and does additional checks.
+ int max_redzone;
bool debug;
- // Controls the way to handle globals (0 - don't detect buffer overflow
- // on globals, 1 - detect buffer overflow, 2 - print data about registered
- // globals).
int report_globals;
- // If set, attempts to catch initialization order issues.
bool check_initialization_order;
- // If set, uses custom wrappers and replacements for libc string functions
- // to find more errors.
bool replace_str;
- // If set, uses custom wrappers for memset/memcpy/memmove intinsics.
bool replace_intrin;
- // Used on Mac only.
bool mac_ignore_invalid_free;
- // Enables stack-use-after-return checking at run-time.
bool detect_stack_use_after_return;
- // The minimal fake stack size log.
- int uar_stack_size_log;
- // ASan allocator flag. max_malloc_fill_size is the maximal amount of bytes
- // that will be filled with malloc_fill_byte on malloc.
+ int min_uar_stack_size_log;
+ int max_uar_stack_size_log;
+ bool uar_noreserve;
int max_malloc_fill_size, malloc_fill_byte;
- // Override exit status if something was reported.
int exitcode;
- // If set, user may manually mark memory regions as poisoned or unpoisoned.
bool allow_user_poisoning;
- // Number of seconds to sleep between printing an error report and
- // terminating application. Useful for debug purposes (when one needs
- // to attach gdb, for example).
int sleep_before_dying;
- // If set, registers ASan custom segv handler.
- bool handle_segv;
- // If set, allows user register segv handler even if ASan registers one.
- bool allow_user_segv_handler;
- // If set, uses alternate stack for signal handling.
- bool use_sigaltstack;
- // Allow the users to work around the bug in Nvidia drivers prior to 295.*.
bool check_malloc_usable_size;
- // If set, explicitly unmaps (huge) shadow at exit.
bool unmap_shadow_on_exit;
- // If set, calls abort() instead of _exit() after printing an error report.
bool abort_on_error;
- // Print various statistics after printing an error message or if atexit=1.
bool print_stats;
- // Print the legend for the shadow bytes.
bool print_legend;
- // If set, prints ASan exit stats even after program terminates successfully.
bool atexit;
- // If set, coverage information will be dumped at shutdown time if the
- // appropriate instrumentation was enabled.
- bool coverage;
- // By default, disable core dumper on 64-bit - it makes little sense
- // to dump 16T+ core.
bool disable_core;
- // Allow the tool to re-exec the program. This may interfere badly with the
- // debugger.
bool allow_reexec;
- // If set, prints not only thread creation stacks for threads in error report,
- // but also thread creation stacks for threads that created those threads,
- // etc. up to main thread.
bool print_full_thread_history;
- // Poison (or not) the heap memory on [de]allocation. Zero value is useful
- // for benchmarking the allocator or instrumentator.
bool poison_heap;
- // If true, poison partially addressable 8-byte aligned words (default=true).
- // This flag affects heap and global buffers, but not stack buffers.
bool poison_partial;
- // Report errors on malloc/delete, new/free, new/delete[], etc.
bool alloc_dealloc_mismatch;
- // If true, assume that memcmp(p1, p2, n) always reads n bytes before
- // comparing p1 and p2.
bool strict_memcmp;
- // If true, assume that dynamic initializers can never access globals from
- // other modules, even if the latter are already initialized.
bool strict_init_order;
+ bool start_deactivated;
+ int detect_invalid_pointer_pairs;
+ bool detect_container_overflow;
+ int detect_odr_violation;
};
extern Flags asan_flags_dont_use_directly;
diff --git a/libsanitizer/asan/asan_globals.cc b/libsanitizer/asan/asan_globals.cc
index e97850a854a..132a564f4fe 100644
--- a/libsanitizer/asan/asan_globals.cc
+++ b/libsanitizer/asan/asan_globals.cc
@@ -90,6 +90,19 @@ static void RegisterGlobal(const Global *g) {
CHECK(AddrIsInMem(g->beg));
CHECK(AddrIsAlignedByGranularity(g->beg));
CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
+ if (flags()->detect_odr_violation) {
+ // Try detecting ODR (One Definition Rule) violation, i.e. the situation
+ // where two globals with the same name are defined in different modules.
+ if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) {
+ // This check may not be enough: if the first global is much larger
+ // the entire redzone of the second global may be within the first global.
+ for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
+ if (g->beg == l->g->beg &&
+ (flags()->detect_odr_violation >= 2 || g->size != l->g->size))
+ ReportODRViolation(g, l->g);
+ }
+ }
+ }
if (flags()->poison_heap)
PoisonRedZones(*g);
ListOfGlobals *l = new(allocator_for_globals) ListOfGlobals;
diff --git a/libsanitizer/asan/asan_intercepted_functions.h b/libsanitizer/asan/asan_intercepted_functions.h
deleted file mode 100644
index 19b53363a5b..00000000000
--- a/libsanitizer/asan/asan_intercepted_functions.h
+++ /dev/null
@@ -1,77 +0,0 @@
-//===-- asan_intercepted_functions.h ----------------------------*- C++ -*-===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of AddressSanitizer, an address sanity checker.
-//
-// ASan-private header containing prototypes for wrapper functions and wrappers
-//===----------------------------------------------------------------------===//
-#ifndef ASAN_INTERCEPTED_FUNCTIONS_H
-#define ASAN_INTERCEPTED_FUNCTIONS_H
-
-#include "sanitizer_common/sanitizer_platform_interceptors.h"
-
-// Use macro to describe if specific function should be
-// intercepted on a given platform.
-#if !SANITIZER_WINDOWS
-# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1
-# define ASAN_INTERCEPT__LONGJMP 1
-# define ASAN_INTERCEPT_STRDUP 1
-# define ASAN_INTERCEPT_INDEX 1
-# define ASAN_INTERCEPT_PTHREAD_CREATE 1
-# define ASAN_INTERCEPT_MLOCKX 1
-#else
-# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 0
-# define ASAN_INTERCEPT__LONGJMP 0
-# define ASAN_INTERCEPT_STRDUP 0
-# define ASAN_INTERCEPT_INDEX 0
-# define ASAN_INTERCEPT_PTHREAD_CREATE 0
-# define ASAN_INTERCEPT_MLOCKX 0
-#endif
-
-#if SANITIZER_LINUX
-# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 1
-#else
-# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 0
-#endif
-
-#if !SANITIZER_MAC
-# define ASAN_INTERCEPT_STRNLEN 1
-#else
-# define ASAN_INTERCEPT_STRNLEN 0
-#endif
-
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
-# define ASAN_INTERCEPT_SWAPCONTEXT 1
-#else
-# define ASAN_INTERCEPT_SWAPCONTEXT 0
-#endif
-
-#if !SANITIZER_ANDROID && !SANITIZER_WINDOWS
-# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 1
-#else
-# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 0
-#endif
-
-#if !SANITIZER_WINDOWS
-# define ASAN_INTERCEPT_SIGLONGJMP 1
-#else
-# define ASAN_INTERCEPT_SIGLONGJMP 0
-#endif
-
-#if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS
-# define ASAN_INTERCEPT___CXA_THROW 1
-#else
-# define ASAN_INTERCEPT___CXA_THROW 0
-#endif
-
-#if !SANITIZER_WINDOWS
-# define ASAN_INTERCEPT___CXA_ATEXIT 1
-#else
-# define ASAN_INTERCEPT___CXA_ATEXIT 0
-#endif
-
-#endif // ASAN_INTERCEPTED_FUNCTIONS_H
diff --git a/libsanitizer/asan/asan_interceptors.cc b/libsanitizer/asan/asan_interceptors.cc
index decbfea5f75..13deab5766e 100644
--- a/libsanitizer/asan/asan_interceptors.cc
+++ b/libsanitizer/asan/asan_interceptors.cc
@@ -12,14 +12,12 @@
#include "asan_interceptors.h"
#include "asan_allocator.h"
-#include "asan_intercepted_functions.h"
#include "asan_internal.h"
#include "asan_mapping.h"
#include "asan_poisoning.h"
#include "asan_report.h"
#include "asan_stack.h"
#include "asan_stats.h"
-#include "interception/interception.h"
#include "sanitizer_common/sanitizer_libc.h"
namespace __asan {
@@ -43,6 +41,10 @@ static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
uptr __offset = (uptr)(offset); \
uptr __size = (uptr)(size); \
uptr __bad = 0; \
+ if (__offset > __offset + __size) { \
+ GET_STACK_TRACE_FATAL_HERE; \
+ ReportStringFunctionSizeOverflow(__offset, __size, &stack); \
+ } \
if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \
(__bad = __asan_region_is_poisoned(__offset, __size))) { \
GET_CURRENT_PC_BP_SP; \
@@ -70,13 +72,6 @@ static inline bool RangesOverlap(const char *offset1, uptr length1,
} \
} while (0)
-#define ENSURE_ASAN_INITED() do { \
- CHECK(!asan_init_is_running); \
- if (!asan_inited) { \
- __asan_init(); \
- } \
-} while (0)
-
static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
#if ASAN_INTERCEPT_STRNLEN
if (REAL(strnlen) != 0) {
@@ -106,11 +101,10 @@ DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
#if !SANITIZER_MAC
-#define ASAN_INTERCEPT_FUNC(name) \
- do { \
- if ((!INTERCEPT_FUNCTION(name) || !REAL(name)) && \
- common_flags()->verbosity > 0) \
- Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
+#define ASAN_INTERCEPT_FUNC(name) \
+ do { \
+ if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \
+ VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \
} while (0)
#else
// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
@@ -118,19 +112,18 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
#endif // SANITIZER_MAC
#define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
-#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \
- do { \
- } while (false)
#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
ASAN_WRITE_RANGE(ptr, size)
#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
-#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
- do { \
- if (asan_init_is_running) return REAL(func)(__VA_ARGS__); \
- ctx = 0; \
- (void) ctx; \
- if (SANITIZER_MAC && !asan_inited) return REAL(func)(__VA_ARGS__); \
- ENSURE_ASAN_INITED(); \
+#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
+ do { \
+ if (asan_init_is_running) \
+ return REAL(func)(__VA_ARGS__); \
+ ctx = 0; \
+ (void) ctx; \
+ if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \
+ return REAL(func)(__VA_ARGS__); \
+ ENSURE_ASAN_INITED(); \
} while (false)
#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
do { \
@@ -194,20 +187,41 @@ INTERCEPTOR(int, pthread_create, void *thread,
#endif // ASAN_INTERCEPT_PTHREAD_CREATE
#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
+
+#if SANITIZER_ANDROID
+INTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
+ if (!AsanInterceptsSignal(signum) ||
+ common_flags()->allow_user_segv_handler) {
+ return REAL(bsd_signal)(signum, handler);
+ }
+ return 0;
+}
+#else
INTERCEPTOR(void*, signal, int signum, void *handler) {
- if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) {
+ if (!AsanInterceptsSignal(signum) ||
+ common_flags()->allow_user_segv_handler) {
return REAL(signal)(signum, handler);
}
return 0;
}
+#endif
INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
struct sigaction *oldact) {
- if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) {
+ if (!AsanInterceptsSignal(signum) ||
+ common_flags()->allow_user_segv_handler) {
return REAL(sigaction)(signum, act, oldact);
}
return 0;
}
+
+namespace __sanitizer {
+int real_sigaction(int signum, const void *act, void *oldact) {
+ return REAL(sigaction)(signum,
+ (struct sigaction *)act, (struct sigaction *)oldact);
+}
+} // namespace __sanitizer
+
#elif SANITIZER_POSIX
// We need to have defined REAL(sigaction) on posix systems.
DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
@@ -284,10 +298,9 @@ static void MlockIsUnsupported() {
static bool printed = false;
if (printed) return;
printed = true;
- if (common_flags()->verbosity > 0) {
- Printf("INFO: AddressSanitizer ignores "
- "mlock/mlockall/munlock/munlockall\n");
- }
+ VPrintf(1,
+ "INFO: AddressSanitizer ignores "
+ "mlock/mlockall/munlock/munlockall\n");
}
INTERCEPTOR(int, mlock, const void *addr, uptr len) {
@@ -315,7 +328,7 @@ static inline int CharCmp(unsigned char c1, unsigned char c2) {
}
INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
- if (!asan_inited) return internal_memcmp(a1, a2, size);
+ if (UNLIKELY(!asan_inited)) return internal_memcmp(a1, a2, size);
ENSURE_ASAN_INITED();
if (flags()->replace_intrin) {
if (flags()->strict_memcmp) {
@@ -342,24 +355,8 @@ INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
return REAL(memcmp(a1, a2, size));
}
-#define MEMMOVE_BODY { \
- if (!asan_inited) return internal_memmove(to, from, size); \
- if (asan_init_is_running) { \
- return REAL(memmove)(to, from, size); \
- } \
- ENSURE_ASAN_INITED(); \
- if (flags()->replace_intrin) { \
- ASAN_READ_RANGE(from, size); \
- ASAN_WRITE_RANGE(to, size); \
- } \
- return internal_memmove(to, from, size); \
-}
-
-INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) MEMMOVE_BODY
-
-INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
-#if !SANITIZER_MAC
- if (!asan_inited) return internal_memcpy(to, from, size);
+void *__asan_memcpy(void *to, const void *from, uptr size) {
+ if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size);
// memcpy is called during __asan_init() from the internals
// of printf(...).
if (asan_init_is_running) {
@@ -375,23 +372,11 @@ INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
ASAN_READ_RANGE(from, size);
ASAN_WRITE_RANGE(to, size);
}
- // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8, so
- // calling REAL(memcpy) here leads to infinite recursion.
- // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
- return internal_memcpy(to, from, size);
-#else
- // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
- // with WRAP(memcpy). As a result, false positives are reported for memmove()
- // calls. If we just disable error reporting with
- // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
- // internal_memcpy(), which may lead to crashes, see
- // http://llvm.org/bugs/show_bug.cgi?id=16362.
- MEMMOVE_BODY
-#endif // !SANITIZER_MAC
+ return REAL(memcpy)(to, from, size);
}
-INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
- if (!asan_inited) return internal_memset(block, c, size);
+void *__asan_memset(void *block, int c, uptr size) {
+ if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size);
// memset is called inside Printf.
if (asan_init_is_running) {
return REAL(memset)(block, c, size);
@@ -403,8 +388,41 @@ INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
return REAL(memset)(block, c, size);
}
+void *__asan_memmove(void *to, const void *from, uptr size) {
+ if (UNLIKELY(!asan_inited))
+ return internal_memmove(to, from, size);
+ ENSURE_ASAN_INITED();
+ if (flags()->replace_intrin) {
+ ASAN_READ_RANGE(from, size);
+ ASAN_WRITE_RANGE(to, size);
+ }
+ return internal_memmove(to, from, size);
+}
+
+INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
+ return __asan_memmove(to, from, size);
+}
+
+INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
+#if !SANITIZER_MAC
+ return __asan_memcpy(to, from, size);
+#else
+ // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
+ // with WRAP(memcpy). As a result, false positives are reported for memmove()
+ // calls. If we just disable error reporting with
+ // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
+ // internal_memcpy(), which may lead to crashes, see
+ // http://llvm.org/bugs/show_bug.cgi?id=16362.
+ return __asan_memmove(to, from, size);
+#endif // !SANITIZER_MAC
+}
+
+INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
+ return __asan_memset(block, c, size);
+}
+
INTERCEPTOR(char*, strchr, const char *str, int c) {
- if (!asan_inited) return internal_strchr(str, c);
+ if (UNLIKELY(!asan_inited)) return internal_strchr(str, c);
// strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
// used.
if (asan_init_is_running) {
@@ -473,7 +491,7 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
#if SANITIZER_MAC
- if (!asan_inited) return REAL(strcpy)(to, from); // NOLINT
+ if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT
#endif
// strcpy is called from malloc_default_purgeable_zone()
// in __asan::ReplaceSystemAlloc() on Mac.
@@ -492,7 +510,7 @@ INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
#if ASAN_INTERCEPT_STRDUP
INTERCEPTOR(char*, strdup, const char *s) {
- if (!asan_inited) return internal_strdup(s);
+ if (UNLIKELY(!asan_inited)) return internal_strdup(s);
ENSURE_ASAN_INITED();
uptr length = REAL(strlen)(s);
if (flags()->replace_str) {
@@ -506,7 +524,7 @@ INTERCEPTOR(char*, strdup, const char *s) {
#endif
INTERCEPTOR(uptr, strlen, const char *s) {
- if (!asan_inited) return internal_strlen(s);
+ if (UNLIKELY(!asan_inited)) return internal_strlen(s);
// strlen is called from malloc_default_purgeable_zone()
// in __asan::ReplaceSystemAlloc() on Mac.
if (asan_init_is_running) {
@@ -588,7 +606,7 @@ INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
INTERCEPTOR(int, atoi, const char *nptr) {
#if SANITIZER_MAC
- if (!asan_inited) return REAL(atoi)(nptr);
+ if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
#endif
ENSURE_ASAN_INITED();
if (!flags()->replace_str) {
@@ -607,7 +625,7 @@ INTERCEPTOR(int, atoi, const char *nptr) {
INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
#if SANITIZER_MAC
- if (!asan_inited) return REAL(atol)(nptr);
+ if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
#endif
ENSURE_ASAN_INITED();
if (!flags()->replace_str) {
@@ -664,7 +682,7 @@ static void AtCxaAtexit(void *unused) {
INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
void *dso_handle) {
#if SANITIZER_MAC
- if (!asan_inited) return REAL(__cxa_atexit)(func, arg, dso_handle);
+ if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
#endif
ENSURE_ASAN_INITED();
int res = REAL(__cxa_atexit)(func, arg, dso_handle);
@@ -705,7 +723,7 @@ void InitializeAsanInterceptors() {
static bool was_called_once;
CHECK(was_called_once == false);
was_called_once = true;
- SANITIZER_COMMON_INTERCEPTORS_INIT;
+ InitializeCommonInterceptors();
// Intercept mem* functions.
ASAN_INTERCEPT_FUNC(memcmp);
@@ -753,8 +771,12 @@ void InitializeAsanInterceptors() {
ASAN_INTERCEPT_FUNC(longjmp);
#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
ASAN_INTERCEPT_FUNC(sigaction);
+#if SANITIZER_ANDROID
+ ASAN_INTERCEPT_FUNC(bsd_signal);
+#else
ASAN_INTERCEPT_FUNC(signal);
#endif
+#endif
#if ASAN_INTERCEPT_SWAPCONTEXT
ASAN_INTERCEPT_FUNC(swapcontext);
#endif
@@ -785,9 +807,7 @@ void InitializeAsanInterceptors() {
InitializeWindowsInterceptors();
#endif
- if (common_flags()->verbosity > 0) {
- Report("AddressSanitizer: libc interceptors initialized\n");
- }
+ VReport(1, "AddressSanitizer: libc interceptors initialized\n");
}
} // namespace __asan
diff --git a/libsanitizer/asan/asan_interceptors.h b/libsanitizer/asan/asan_interceptors.h
index cae4c7f0125..af7cdc8a916 100644
--- a/libsanitizer/asan/asan_interceptors.h
+++ b/libsanitizer/asan/asan_interceptors.h
@@ -13,7 +13,68 @@
#define ASAN_INTERCEPTORS_H
#include "asan_internal.h"
-#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_interception.h"
+#include "sanitizer_common/sanitizer_platform_interceptors.h"
+
+// Use macro to describe if specific function should be
+// intercepted on a given platform.
+#if !SANITIZER_WINDOWS
+# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1
+# define ASAN_INTERCEPT__LONGJMP 1
+# define ASAN_INTERCEPT_STRDUP 1
+# define ASAN_INTERCEPT_INDEX 1
+# define ASAN_INTERCEPT_PTHREAD_CREATE 1
+# define ASAN_INTERCEPT_MLOCKX 1
+#else
+# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 0
+# define ASAN_INTERCEPT__LONGJMP 0
+# define ASAN_INTERCEPT_STRDUP 0
+# define ASAN_INTERCEPT_INDEX 0
+# define ASAN_INTERCEPT_PTHREAD_CREATE 0
+# define ASAN_INTERCEPT_MLOCKX 0
+#endif
+
+#if SANITIZER_FREEBSD || SANITIZER_LINUX
+# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 1
+#else
+# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 0
+#endif
+
+#if !SANITIZER_MAC
+# define ASAN_INTERCEPT_STRNLEN 1
+#else
+# define ASAN_INTERCEPT_STRNLEN 0
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+# define ASAN_INTERCEPT_SWAPCONTEXT 1
+#else
+# define ASAN_INTERCEPT_SWAPCONTEXT 0
+#endif
+
+#if !SANITIZER_WINDOWS
+# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 1
+#else
+# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 0
+#endif
+
+#if !SANITIZER_WINDOWS
+# define ASAN_INTERCEPT_SIGLONGJMP 1
+#else
+# define ASAN_INTERCEPT_SIGLONGJMP 0
+#endif
+
+#if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS
+# define ASAN_INTERCEPT___CXA_THROW 1
+#else
+# define ASAN_INTERCEPT___CXA_THROW 0
+#endif
+
+#if !SANITIZER_WINDOWS
+# define ASAN_INTERCEPT___CXA_ATEXIT 1
+#else
+# define ASAN_INTERCEPT___CXA_ATEXIT 0
+#endif
DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size)
DECLARE_REAL(void*, memcpy, void *to, const void *from, uptr size)
@@ -31,6 +92,13 @@ namespace __asan {
void InitializeAsanInterceptors();
+#define ENSURE_ASAN_INITED() do { \
+ CHECK(!asan_init_is_running); \
+ if (UNLIKELY(!asan_inited)) { \
+ AsanInitFromRtl(); \
+ } \
+} while (0)
+
} // namespace __asan
#endif // ASAN_INTERCEPTORS_H
diff --git a/libsanitizer/asan/asan_interface_internal.h b/libsanitizer/asan/asan_interface_internal.h
index 7deed9f4607..1940477f247 100644
--- a/libsanitizer/asan/asan_interface_internal.h
+++ b/libsanitizer/asan/asan_interface_internal.h
@@ -20,7 +20,7 @@ using __sanitizer::uptr;
extern "C" {
// This function should be called at the very beginning of the process,
// before any instrumented code is executed and before any call to malloc.
- // Everytime the asan ABI changes we also change the version number in this
+ // Every time the asan ABI changes we also change the version number in this
// name. Objects build with incompatible asan ABI version
// will not link with run-time.
// Changes between ABI versions:
@@ -75,7 +75,7 @@ extern "C" {
void __asan_unpoison_memory_region(void const volatile *addr, uptr size);
SANITIZER_INTERFACE_ATTRIBUTE
- bool __asan_address_is_poisoned(void const volatile *addr);
+ int __asan_address_is_poisoned(void const volatile *addr);
SANITIZER_INTERFACE_ATTRIBUTE
uptr __asan_region_is_poisoned(uptr beg, uptr size);
@@ -85,7 +85,7 @@ extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
void __asan_report_error(uptr pc, uptr bp, uptr sp,
- uptr addr, bool is_write, uptr access_size);
+ uptr addr, int is_write, uptr access_size);
SANITIZER_INTERFACE_ATTRIBUTE
int __asan_set_error_exit_code(int exit_code);
@@ -97,14 +97,10 @@ extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
/* OPTIONAL */ void __asan_on_error();
- SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
- /* OPTIONAL */ bool __asan_symbolize(const void *pc, char *out_buffer,
- int out_size);
-
SANITIZER_INTERFACE_ATTRIBUTE
uptr __asan_get_estimated_allocated_size(uptr size);
- SANITIZER_INTERFACE_ATTRIBUTE bool __asan_get_ownership(const void *p);
+ SANITIZER_INTERFACE_ATTRIBUTE int __asan_get_ownership(const void *p);
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_allocated_size(const void *p);
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_current_allocated_bytes();
SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_heap_size();
@@ -123,6 +119,29 @@ extern "C" {
// Global flag, copy of ASAN_OPTIONS=detect_stack_use_after_return
SANITIZER_INTERFACE_ATTRIBUTE
extern int __asan_option_detect_stack_use_after_return;
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ extern uptr *__asan_test_only_reported_buggy_pointer;
+
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load1(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load2(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load4(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load8(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load16(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store1(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store2(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store4(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store8(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store16(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN(uptr p, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN(uptr p, uptr size);
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void* __asan_memcpy(void *dst, const void *src, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void* __asan_memset(void *s, int c, uptr n);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void* __asan_memmove(void* dest, const void* src, uptr n);
} // extern "C"
#endif // ASAN_INTERFACE_INTERNAL_H
diff --git a/libsanitizer/asan/asan_internal.h b/libsanitizer/asan/asan_internal.h
index ede273a7170..d56943a0838 100644
--- a/libsanitizer/asan/asan_internal.h
+++ b/libsanitizer/asan/asan_internal.h
@@ -28,26 +28,11 @@
// Build-time configuration options.
-// If set, asan will install its own SEGV signal handler.
-#ifndef ASAN_NEEDS_SEGV
-# if SANITIZER_ANDROID == 1
-# define ASAN_NEEDS_SEGV 0
-# else
-# define ASAN_NEEDS_SEGV 1
-# endif
-#endif
-
// If set, asan will intercept C++ exception api call(s).
#ifndef ASAN_HAS_EXCEPTIONS
# define ASAN_HAS_EXCEPTIONS 1
#endif
-// If set, asan uses the values of SHADOW_SCALE and SHADOW_OFFSET
-// provided by the instrumented objects. Otherwise constants are used.
-#ifndef ASAN_FLEXIBLE_MAPPING_AND_OFFSET
-# define ASAN_FLEXIBLE_MAPPING_AND_OFFSET 0
-#endif
-
// If set, values like allocator chunk size, as well as defaults for some flags
// will be changed towards less memory overhead.
#ifndef ASAN_LOW_MEMORY
@@ -62,32 +47,41 @@
# define ASAN_USE_PREINIT_ARRAY (SANITIZER_LINUX && !SANITIZER_ANDROID)
#endif
+#ifndef ASAN_DYNAMIC
+# ifdef PIC
+# define ASAN_DYNAMIC 1
+# else
+# define ASAN_DYNAMIC 0
+# endif
+#endif
+
// All internal functions in asan reside inside the __asan namespace
// to avoid namespace collisions with the user programs.
-// Seperate namespace also makes it simpler to distinguish the asan run-time
+// Separate namespace also makes it simpler to distinguish the asan run-time
// functions from the instrumented user code in a profile.
namespace __asan {
class AsanThread;
using __sanitizer::StackTrace;
+void AsanInitFromRtl();
+
// asan_rtl.cc
void NORETURN ShowStatsAndAbort();
-void ReplaceOperatorsNewAndDelete();
// asan_malloc_linux.cc / asan_malloc_mac.cc
void ReplaceSystemMalloc();
// asan_linux.cc / asan_mac.cc / asan_win.cc
void *AsanDoesNotSupportStaticLinkage();
+void AsanCheckDynamicRTPrereqs();
+void AsanCheckIncompatibleRT();
void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp);
+void AsanOnSIGSEGV(int, void *siginfo, void *context);
void MaybeReexec();
bool AsanInterceptsSignal(int signum);
-void SetAlternateSignalStack();
-void UnsetAlternateSignalStack();
-void InstallSignalHandlers();
void ReadContextStack(void *context, uptr *stack, uptr *ssize);
void AsanPlatformThreadInit();
void StopInitOrderChecking();
@@ -100,7 +94,9 @@ void PlatformTSDDtor(void *tsd);
void AppendToErrorMessageBuffer(const char *buffer);
-// Platfrom-specific options.
+void ParseExtraActivationFlags();
+
+// Platform-specific options.
#if SANITIZER_MAC
bool PlatformHasDifferentMemcpyAndMemmove();
# define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE \
diff --git a/libsanitizer/asan/asan_linux.cc b/libsanitizer/asan/asan_linux.cc
index 0692eb1f455..c401d9df48b 100644
--- a/libsanitizer/asan/asan_linux.cc
+++ b/libsanitizer/asan/asan_linux.cc
@@ -11,11 +11,12 @@
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_platform.h"
-#if SANITIZER_LINUX
+#if SANITIZER_FREEBSD || SANITIZER_LINUX
#include "asan_interceptors.h"
#include "asan_internal.h"
#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_procmaps.h"
@@ -30,12 +31,41 @@
#include <unistd.h>
#include <unwind.h>
-#if !SANITIZER_ANDROID
-// FIXME: where to get ucontext on Android?
-#include <sys/ucontext.h>
+#if SANITIZER_FREEBSD
+#include <sys/link_elf.h>
#endif
+#if SANITIZER_ANDROID || SANITIZER_FREEBSD
+#include <ucontext.h>
extern "C" void* _DYNAMIC;
+#else
+#include <sys/ucontext.h>
+#include <dlfcn.h>
+#include <link.h>
+#endif
+
+// x86_64 FreeBSD 9.2 and older define 64-bit register names in both 64-bit
+// and 32-bit modes.
+#if SANITIZER_FREEBSD
+#include <sys/param.h>
+# if __FreeBSD_version <= 902001 // v9.2
+# define mc_eip mc_rip
+# define mc_ebp mc_rbp
+# define mc_esp mc_rsp
+# endif
+#endif
+
+typedef enum {
+ ASAN_RT_VERSION_UNDEFINED = 0,
+ ASAN_RT_VERSION_DYNAMIC,
+ ASAN_RT_VERSION_STATIC,
+} asan_rt_version_t;
+
+// FIXME: perhaps also store abi version here?
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+asan_rt_version_t __asan_rt_version;
+}
namespace __asan {
@@ -48,38 +78,122 @@ void *AsanDoesNotSupportStaticLinkage() {
return &_DYNAMIC; // defined in link.h
}
-void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
#if SANITIZER_ANDROID
- *pc = *sp = *bp = 0;
-#elif defined(__arm__)
+// FIXME: should we do anything for Android?
+void AsanCheckDynamicRTPrereqs() {}
+void AsanCheckIncompatibleRT() {}
+#else
+static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size,
+ void *data) {
+ // Continue until the first dynamic library is found
+ if (!info->dlpi_name || info->dlpi_name[0] == 0)
+ return 0;
+
+ *(const char **)data = info->dlpi_name;
+ return 1;
+}
+
+static bool IsDynamicRTName(const char *libname) {
+ return internal_strstr(libname, "libclang_rt.asan") ||
+ internal_strstr(libname, "libasan.so");
+}
+
+static void ReportIncompatibleRT() {
+ Report("Your application is linked against incompatible ASan runtimes.\n");
+ Die();
+}
+
+void AsanCheckDynamicRTPrereqs() {
+ // Ensure that dynamic RT is the first DSO in the list
+ const char *first_dso_name = 0;
+ dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
+ if (first_dso_name && !IsDynamicRTName(first_dso_name)) {
+ Report("ASan runtime does not come first in initial library list; "
+ "you should either link runtime to your application or "
+ "manually preload it with LD_PRELOAD.\n");
+ Die();
+ }
+}
+
+void AsanCheckIncompatibleRT() {
+ if (ASAN_DYNAMIC) {
+ if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
+ __asan_rt_version = ASAN_RT_VERSION_DYNAMIC;
+ } else if (__asan_rt_version != ASAN_RT_VERSION_DYNAMIC) {
+ ReportIncompatibleRT();
+ }
+ } else {
+ if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
+ // Ensure that dynamic runtime is not present. We should detect it
+ // as early as possible, otherwise ASan interceptors could bind to
+ // the functions in dynamic ASan runtime instead of the functions in
+ // system libraries, causing crashes later in ASan initialization.
+ MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+ char filename[128];
+ while (proc_maps.Next(0, 0, 0, filename, sizeof(filename), 0)) {
+ if (IsDynamicRTName(filename)) {
+ Report("Your application is linked against "
+ "incompatible ASan runtimes.\n");
+ Die();
+ }
+ }
+ __asan_rt_version = ASAN_RT_VERSION_STATIC;
+ } else if (__asan_rt_version != ASAN_RT_VERSION_STATIC) {
+ ReportIncompatibleRT();
+ }
+ }
+}
+#endif // SANITIZER_ANDROID
+
+void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
+#if defined(__arm__)
ucontext_t *ucontext = (ucontext_t*)context;
*pc = ucontext->uc_mcontext.arm_pc;
*bp = ucontext->uc_mcontext.arm_fp;
*sp = ucontext->uc_mcontext.arm_sp;
-# elif defined(__hppa__)
+#elif defined(__aarch64__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.pc;
+ *bp = ucontext->uc_mcontext.regs[29];
+ *sp = ucontext->uc_mcontext.sp;
+#elif defined(__hppa__)
ucontext_t *ucontext = (ucontext_t*)context;
*pc = ucontext->uc_mcontext.sc_iaoq[0];
/* GCC uses %r3 whenever a frame pointer is needed. */
*bp = ucontext->uc_mcontext.sc_gr[3];
*sp = ucontext->uc_mcontext.sc_gr[30];
-# elif defined(__x86_64__)
+#elif defined(__x86_64__)
+# if SANITIZER_FREEBSD
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.mc_rip;
+ *bp = ucontext->uc_mcontext.mc_rbp;
+ *sp = ucontext->uc_mcontext.mc_rsp;
+# else
ucontext_t *ucontext = (ucontext_t*)context;
*pc = ucontext->uc_mcontext.gregs[REG_RIP];
*bp = ucontext->uc_mcontext.gregs[REG_RBP];
*sp = ucontext->uc_mcontext.gregs[REG_RSP];
-# elif defined(__i386__)
+# endif
+#elif defined(__i386__)
+# if SANITIZER_FREEBSD
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.mc_eip;
+ *bp = ucontext->uc_mcontext.mc_ebp;
+ *sp = ucontext->uc_mcontext.mc_esp;
+# else
ucontext_t *ucontext = (ucontext_t*)context;
*pc = ucontext->uc_mcontext.gregs[REG_EIP];
*bp = ucontext->uc_mcontext.gregs[REG_EBP];
*sp = ucontext->uc_mcontext.gregs[REG_ESP];
-# elif defined(__powerpc__) || defined(__powerpc64__)
+# endif
+#elif defined(__powerpc__) || defined(__powerpc64__)
ucontext_t *ucontext = (ucontext_t*)context;
*pc = ucontext->uc_mcontext.regs->nip;
*sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
// The powerpc{,64}-linux ABIs do not specify r31 as the frame
// pointer, but GCC always uses r31 when we need a frame pointer.
*bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
-# elif defined(__sparc__)
+#elif defined(__sparc__)
ucontext_t *ucontext = (ucontext_t*)context;
uptr *stk_ptr;
# if defined (__arch64__)
@@ -93,7 +207,7 @@ void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
stk_ptr = (uptr *) *sp;
*bp = stk_ptr[15];
# endif
-# elif defined(__mips__)
+#elif defined(__mips__)
ucontext_t *ucontext = (ucontext_t*)context;
*pc = ucontext->uc_mcontext.gregs[31];
*bp = ucontext->uc_mcontext.gregs[30];
@@ -104,7 +218,7 @@ void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
}
bool AsanInterceptsSignal(int signum) {
- return signum == SIGSEGV && flags()->handle_segv;
+ return signum == SIGSEGV && common_flags()->handle_segv;
}
void AsanPlatformThreadInit() {
@@ -125,4 +239,4 @@ void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
} // namespace __asan
-#endif // SANITIZER_LINUX
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
diff --git a/libsanitizer/asan/asan_mac.cc b/libsanitizer/asan/asan_mac.cc
index 8d01843afaf..4a295e0e355 100644
--- a/libsanitizer/asan/asan_mac.cc
+++ b/libsanitizer/asan/asan_mac.cc
@@ -15,12 +15,12 @@
#include "asan_interceptors.h"
#include "asan_internal.h"
-#include "asan_mac.h"
#include "asan_mapping.h"
#include "asan_stack.h"
#include "asan_thread.h"
#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_mac.h"
#include <crt_externs.h> // for _NSGetArgv
#include <dlfcn.h> // for dladdr()
@@ -51,43 +51,6 @@ void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
# endif // SANITIZER_WORDSIZE
}
-MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED;
-
-MacosVersion GetMacosVersionInternal() {
- int mib[2] = { CTL_KERN, KERN_OSRELEASE };
- char version[100];
- uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]);
- for (uptr i = 0; i < maxlen; i++) version[i] = '\0';
- // Get the version length.
- CHECK_NE(sysctl(mib, 2, 0, &len, 0, 0), -1);
- CHECK_LT(len, maxlen);
- CHECK_NE(sysctl(mib, 2, version, &len, 0, 0), -1);
- switch (version[0]) {
- case '9': return MACOS_VERSION_LEOPARD;
- case '1': {
- switch (version[1]) {
- case '0': return MACOS_VERSION_SNOW_LEOPARD;
- case '1': return MACOS_VERSION_LION;
- case '2': return MACOS_VERSION_MOUNTAIN_LION;
- case '3': return MACOS_VERSION_MAVERICKS;
- default: return MACOS_VERSION_UNKNOWN;
- }
- }
- default: return MACOS_VERSION_UNKNOWN;
- }
-}
-
-MacosVersion GetMacosVersion() {
- atomic_uint32_t *cache =
- reinterpret_cast<atomic_uint32_t*>(&cached_macos_version);
- MacosVersion result =
- static_cast<MacosVersion>(atomic_load(cache, memory_order_acquire));
- if (result == MACOS_VERSION_UNINITIALIZED) {
- result = GetMacosVersionInternal();
- atomic_store(cache, result, memory_order_release);
- }
- return result;
-}
bool PlatformHasDifferentMemcpyAndMemmove() {
// On OS X 10.7 memcpy() and memmove() are both resolved
@@ -172,12 +135,10 @@ void MaybeReexec() {
// Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name.
setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0);
}
- if (common_flags()->verbosity >= 1) {
- Report("exec()-ing the program with\n");
- Report("%s=%s\n", kDyldInsertLibraries, new_env);
- Report("to enable ASan wrappers.\n");
- Report("Set ASAN_OPTIONS=allow_reexec=0 to disable this.\n");
- }
+ VReport(1, "exec()-ing the program with\n");
+ VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env);
+ VReport(1, "to enable ASan wrappers.\n");
+ VReport(1, "Set ASAN_OPTIONS=allow_reexec=0 to disable this.\n");
execv(program_name, *_NSGetArgv());
} else {
// DYLD_INSERT_LIBRARIES is set and contains the runtime library.
@@ -236,8 +197,15 @@ void *AsanDoesNotSupportStaticLinkage() {
return 0;
}
+// No-op. Mac does not support static linkage anyway.
+void AsanCheckDynamicRTPrereqs() {}
+
+// No-op. Mac does not support static linkage anyway.
+void AsanCheckIncompatibleRT() {}
+
bool AsanInterceptsSignal(int signum) {
- return (signum == SIGSEGV || signum == SIGBUS) && flags()->handle_segv;
+ return (signum == SIGSEGV || signum == SIGBUS) &&
+ common_flags()->handle_segv;
}
void AsanPlatformThreadInit() {
@@ -309,11 +277,10 @@ extern "C"
void asan_dispatch_call_block_and_release(void *block) {
GET_STACK_TRACE_THREAD;
asan_block_context_t *context = (asan_block_context_t*)block;
- if (common_flags()->verbosity >= 2) {
- Report("asan_dispatch_call_block_and_release(): "
- "context: %p, pthread_self: %p\n",
- block, pthread_self());
- }
+ VReport(2,
+ "asan_dispatch_call_block_and_release(): "
+ "context: %p, pthread_self: %p\n",
+ block, pthread_self());
asan_register_worker_thread(context->parent_tid, &stack);
// Call the original dispatcher for the block.
context->func(context->block);
@@ -347,10 +314,10 @@ asan_block_context_t *alloc_asan_context(void *ctxt, dispatch_function_t func,
if (common_flags()->verbosity >= 2) { \
Report(#dispatch_x_f "(): context: %p, pthread_self: %p\n", \
asan_ctxt, pthread_self()); \
- PRINT_CURRENT_STACK(); \
- } \
- return REAL(dispatch_x_f)(dq, (void*)asan_ctxt, \
- asan_dispatch_call_block_and_release); \
+ PRINT_CURRENT_STACK(); \
+ } \
+ return REAL(dispatch_x_f)(dq, (void*)asan_ctxt, \
+ asan_dispatch_call_block_and_release); \
}
INTERCEPT_DISPATCH_X_F_3(dispatch_async_f)
@@ -386,7 +353,6 @@ INTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group,
#if !defined(MISSING_BLOCKS_SUPPORT)
extern "C" {
-// FIXME: consolidate these declarations with asan_intercepted_functions.h.
void dispatch_async(dispatch_queue_t dq, void(^work)(void));
void dispatch_group_async(dispatch_group_t dg, dispatch_queue_t dq,
void(^work)(void));
diff --git a/libsanitizer/asan/asan_mac.h b/libsanitizer/asan/asan_mac.h
deleted file mode 100644
index 2d1d4b0bfb3..00000000000
--- a/libsanitizer/asan/asan_mac.h
+++ /dev/null
@@ -1,57 +0,0 @@
-//===-- asan_mac.h ----------------------------------------------*- C++ -*-===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of AddressSanitizer, an address sanity checker.
-//
-// Mac-specific ASan definitions.
-//===----------------------------------------------------------------------===//
-#ifndef ASAN_MAC_H
-#define ASAN_MAC_H
-
-// CF_RC_BITS, the layout of CFRuntimeBase and __CFStrIsConstant are internal
-// and subject to change in further CoreFoundation versions. Apple does not
-// guarantee any binary compatibility from release to release.
-
-// See http://opensource.apple.com/source/CF/CF-635.15/CFInternal.h
-#if defined(__BIG_ENDIAN__)
-#define CF_RC_BITS 0
-#endif
-
-#if defined(__LITTLE_ENDIAN__)
-#define CF_RC_BITS 3
-#endif
-
-// See http://opensource.apple.com/source/CF/CF-635.15/CFRuntime.h
-typedef struct __CFRuntimeBase {
- uptr _cfisa;
- u8 _cfinfo[4];
-#if __LP64__
- u32 _rc;
-#endif
-} CFRuntimeBase;
-
-enum MacosVersion {
- MACOS_VERSION_UNINITIALIZED = 0,
- MACOS_VERSION_UNKNOWN,
- MACOS_VERSION_LEOPARD,
- MACOS_VERSION_SNOW_LEOPARD,
- MACOS_VERSION_LION,
- MACOS_VERSION_MOUNTAIN_LION,
- MACOS_VERSION_MAVERICKS
-};
-
-// Used by asan_malloc_mac.cc and asan_mac.cc
-extern "C" void __CFInitialize();
-
-namespace __asan {
-
-MacosVersion GetMacosVersion();
-void MaybeReplaceCFAllocator();
-
-} // namespace __asan
-
-#endif // ASAN_MAC_H
diff --git a/libsanitizer/asan/asan_malloc_linux.cc b/libsanitizer/asan/asan_malloc_linux.cc
index e3495cb0900..ba908e322d9 100644
--- a/libsanitizer/asan/asan_malloc_linux.cc
+++ b/libsanitizer/asan/asan_malloc_linux.cc
@@ -13,8 +13,9 @@
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_platform.h"
-#if SANITIZER_LINUX
+#if SANITIZER_FREEBSD || SANITIZER_LINUX
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
#include "asan_allocator.h"
#include "asan_interceptors.h"
#include "asan_internal.h"
@@ -74,7 +75,7 @@ INTERCEPTOR(void*, malloc, uptr size) {
}
INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
- if (!asan_inited) {
+ if (UNLIKELY(!asan_inited)) {
// Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
const uptr kCallocPoolSize = 1024;
static uptr calloc_memory_for_dlsym[kCallocPoolSize];
@@ -99,8 +100,12 @@ INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
return asan_memalign(boundary, size, &stack, FROM_MALLOC);
}
-INTERCEPTOR(void*, __libc_memalign, uptr align, uptr s)
- ALIAS("memalign");
+INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ void *res = asan_memalign(boundary, size, &stack, FROM_MALLOC);
+ DTLS_on_libc_memalign(res, size * boundary);
+ return res;
+}
INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
GET_CURRENT_PC_BP_SP;
@@ -146,4 +151,4 @@ INTERCEPTOR(void, malloc_stats, void) {
__asan_print_accumulated_stats();
}
-#endif // SANITIZER_LINUX
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
diff --git a/libsanitizer/asan/asan_malloc_mac.cc b/libsanitizer/asan/asan_malloc_mac.cc
index 342e806e3b6..6a93ce1e808 100644
--- a/libsanitizer/asan/asan_malloc_mac.cc
+++ b/libsanitizer/asan/asan_malloc_mac.cc
@@ -22,10 +22,10 @@
#include "asan_allocator.h"
#include "asan_interceptors.h"
#include "asan_internal.h"
-#include "asan_mac.h"
#include "asan_report.h"
#include "asan_stack.h"
#include "asan_stats.h"
+#include "sanitizer_common/sanitizer_mac.h"
// Similar code is used in Google Perftools,
// http://code.google.com/p/google-perftools.
@@ -39,7 +39,7 @@ static malloc_zone_t asan_zone;
INTERCEPTOR(malloc_zone_t *, malloc_create_zone,
vm_size_t start_size, unsigned zone_flags) {
- if (!asan_inited) __asan_init();
+ ENSURE_ASAN_INITED();
GET_STACK_TRACE_MALLOC;
uptr page_size = GetPageSizeCached();
uptr allocated_size = RoundUpTo(sizeof(asan_zone), page_size);
@@ -58,34 +58,34 @@ INTERCEPTOR(malloc_zone_t *, malloc_create_zone,
}
INTERCEPTOR(malloc_zone_t *, malloc_default_zone, void) {
- if (!asan_inited) __asan_init();
+ ENSURE_ASAN_INITED();
return &asan_zone;
}
INTERCEPTOR(malloc_zone_t *, malloc_default_purgeable_zone, void) {
// FIXME: ASan should support purgeable allocations.
// https://code.google.com/p/address-sanitizer/issues/detail?id=139
- if (!asan_inited) __asan_init();
+ ENSURE_ASAN_INITED();
return &asan_zone;
}
INTERCEPTOR(void, malloc_make_purgeable, void *ptr) {
// FIXME: ASan should support purgeable allocations. Ignoring them is fine
// for now.
- if (!asan_inited) __asan_init();
+ ENSURE_ASAN_INITED();
}
INTERCEPTOR(int, malloc_make_nonpurgeable, void *ptr) {
// FIXME: ASan should support purgeable allocations. Ignoring them is fine
// for now.
- if (!asan_inited) __asan_init();
+ ENSURE_ASAN_INITED();
// Must return 0 if the contents were not purged since the last call to
// malloc_make_purgeable().
return 0;
}
INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) {
- if (!asan_inited) __asan_init();
+ ENSURE_ASAN_INITED();
// Allocate |strlen("asan-") + 1 + internal_strlen(name)| bytes.
size_t buflen = 6 + (name ? internal_strlen(name) : 0);
InternalScopedBuffer<char> new_name(buflen);
@@ -100,44 +100,44 @@ INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) {
}
INTERCEPTOR(void *, malloc, size_t size) {
- if (!asan_inited) __asan_init();
+ ENSURE_ASAN_INITED();
GET_STACK_TRACE_MALLOC;
void *res = asan_malloc(size, &stack);
return res;
}
INTERCEPTOR(void, free, void *ptr) {
- if (!asan_inited) __asan_init();
+ ENSURE_ASAN_INITED();
if (!ptr) return;
GET_STACK_TRACE_FREE;
asan_free(ptr, &stack, FROM_MALLOC);
}
INTERCEPTOR(void *, realloc, void *ptr, size_t size) {
- if (!asan_inited) __asan_init();
+ ENSURE_ASAN_INITED();
GET_STACK_TRACE_MALLOC;
return asan_realloc(ptr, size, &stack);
}
INTERCEPTOR(void *, calloc, size_t nmemb, size_t size) {
- if (!asan_inited) __asan_init();
+ ENSURE_ASAN_INITED();
GET_STACK_TRACE_MALLOC;
return asan_calloc(nmemb, size, &stack);
}
INTERCEPTOR(void *, valloc, size_t size) {
- if (!asan_inited) __asan_init();
+ ENSURE_ASAN_INITED();
GET_STACK_TRACE_MALLOC;
return asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC);
}
INTERCEPTOR(size_t, malloc_good_size, size_t size) {
- if (!asan_inited) __asan_init();
+ ENSURE_ASAN_INITED();
return asan_zone.introspect->good_size(&asan_zone, size);
}
INTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) {
- if (!asan_inited) __asan_init();
+ ENSURE_ASAN_INITED();
CHECK(memptr);
GET_STACK_TRACE_MALLOC;
void *result = asan_memalign(alignment, size, &stack, FROM_MALLOC);
@@ -157,7 +157,7 @@ size_t mz_size(malloc_zone_t* zone, const void* ptr) {
}
void *mz_malloc(malloc_zone_t *zone, size_t size) {
- if (!asan_inited) {
+ if (UNLIKELY(!asan_inited)) {
CHECK(system_malloc_zone);
return malloc_zone_malloc(system_malloc_zone, size);
}
@@ -166,7 +166,7 @@ void *mz_malloc(malloc_zone_t *zone, size_t size) {
}
void *mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) {
- if (!asan_inited) {
+ if (UNLIKELY(!asan_inited)) {
// Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
const size_t kCallocPoolSize = 1024;
static uptr calloc_memory_for_dlsym[kCallocPoolSize];
@@ -182,7 +182,7 @@ void *mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) {
}
void *mz_valloc(malloc_zone_t *zone, size_t size) {
- if (!asan_inited) {
+ if (UNLIKELY(!asan_inited)) {
CHECK(system_malloc_zone);
return malloc_zone_valloc(system_malloc_zone, size);
}
@@ -240,7 +240,7 @@ void mz_destroy(malloc_zone_t* zone) {
#if defined(MAC_OS_X_VERSION_10_6) && \
MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
void *mz_memalign(malloc_zone_t *zone, size_t align, size_t size) {
- if (!asan_inited) {
+ if (UNLIKELY(!asan_inited)) {
CHECK(system_malloc_zone);
return malloc_zone_memalign(system_malloc_zone, align, size);
}
diff --git a/libsanitizer/asan/asan_malloc_win.cc b/libsanitizer/asan/asan_malloc_win.cc
index 1f2495ffc50..8463d5ef2e9 100644
--- a/libsanitizer/asan/asan_malloc_win.cc
+++ b/libsanitizer/asan/asan_malloc_win.cc
@@ -17,7 +17,7 @@
#include "asan_interceptors.h"
#include "asan_internal.h"
#include "asan_stack.h"
-#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_interception.h"
#include <stddef.h>
@@ -101,6 +101,21 @@ size_t _msize(void *ptr) {
return asan_malloc_usable_size(ptr, pc, bp);
}
+SANITIZER_INTERFACE_ATTRIBUTE
+void *_expand(void *memblock, size_t size) {
+ // _expand is used in realloc-like functions to resize the buffer if possible.
+ // We don't want memory to stand still while resizing buffers, so return 0.
+ return 0;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *_expand_dbg(void *memblock, size_t size) {
+ return 0;
+}
+
+// TODO(timurrrr): Might want to add support for _aligned_* allocation
+// functions to detect a bit more bugs. Those functions seem to wrap malloc().
+
int _CrtDbgReport(int, const char*, int,
const char*, const char*, ...) {
ShowStatsAndAbort();
diff --git a/libsanitizer/asan/asan_mapping.h b/libsanitizer/asan/asan_mapping.h
index 1e37bc26e94..a1f84e24c46 100644
--- a/libsanitizer/asan/asan_mapping.h
+++ b/libsanitizer/asan/asan_mapping.h
@@ -41,54 +41,84 @@
// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow ||
// || `[0x000000000000, 0x00007fff7fff]` || LowMem ||
//
-// Default Linux/i386 mapping:
+// Default Linux/i386 mapping on x86_64 machine:
// || `[0x40000000, 0xffffffff]` || HighMem ||
// || `[0x28000000, 0x3fffffff]` || HighShadow ||
// || `[0x24000000, 0x27ffffff]` || ShadowGap ||
// || `[0x20000000, 0x23ffffff]` || LowShadow ||
// || `[0x00000000, 0x1fffffff]` || LowMem ||
//
+// Default Linux/i386 mapping on i386 machine
+// (addresses starting with 0xc0000000 are reserved
+// for kernel and thus not sanitized):
+// || `[0x38000000, 0xbfffffff]` || HighMem ||
+// || `[0x27000000, 0x37ffffff]` || HighShadow ||
+// || `[0x24000000, 0x26ffffff]` || ShadowGap ||
+// || `[0x20000000, 0x23ffffff]` || LowShadow ||
+// || `[0x00000000, 0x1fffffff]` || LowMem ||
+//
// Default Linux/MIPS mapping:
// || `[0x2aaa8000, 0xffffffff]` || HighMem ||
// || `[0x0fffd000, 0x2aaa7fff]` || HighShadow ||
// || `[0x0bffd000, 0x0fffcfff]` || ShadowGap ||
// || `[0x0aaa8000, 0x0bffcfff]` || LowShadow ||
// || `[0x00000000, 0x0aaa7fff]` || LowMem ||
+//
+// Shadow mapping on FreeBSD/x86-64 with SHADOW_OFFSET == 0x400000000000:
+// || `[0x500000000000, 0x7fffffffffff]` || HighMem ||
+// || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow ||
+// || `[0x480000000000, 0x49ffffffffff]` || ShadowGap ||
+// || `[0x400000000000, 0x47ffffffffff]` || LowShadow ||
+// || `[0x000000000000, 0x3fffffffffff]` || LowMem ||
+//
+// Shadow mapping on FreeBSD/i386 with SHADOW_OFFSET == 0x40000000:
+// || `[0x60000000, 0xffffffff]` || HighMem ||
+// || `[0x4c000000, 0x5fffffff]` || HighShadow ||
+// || `[0x48000000, 0x4bffffff]` || ShadowGap ||
+// || `[0x40000000, 0x47ffffff]` || LowShadow ||
+// || `[0x00000000, 0x3fffffff]` || LowMem ||
static const u64 kDefaultShadowScale = 3;
-static const u64 kDefaultShadowOffset32 = 1ULL << 29;
+static const u64 kDefaultShadowOffset32 = 1ULL << 29; // 0x20000000
+static const u64 kIosShadowOffset32 = 1ULL << 30; // 0x40000000
static const u64 kDefaultShadowOffset64 = 1ULL << 44;
static const u64 kDefaultShort64bitShadowOffset = 0x7FFF8000; // < 2G.
-static const u64 kPPC64_ShadowOffset64 = 1ULL << 41;
+static const u64 kAArch64_ShadowOffset64 = 1ULL << 36;
static const u64 kMIPS32_ShadowOffset32 = 0x0aaa8000;
+static const u64 kPPC64_ShadowOffset64 = 1ULL << 41;
+static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000
+static const u64 kFreeBSD_ShadowOffset64 = 1ULL << 46; // 0x400000000000
-#if ASAN_FLEXIBLE_MAPPING_AND_OFFSET == 1
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_scale;
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset;
-# define SHADOW_SCALE (__asan_mapping_scale)
-# define SHADOW_OFFSET (__asan_mapping_offset)
+#define SHADOW_SCALE kDefaultShadowScale
+#if SANITIZER_ANDROID
+# define SHADOW_OFFSET (0)
#else
-# define SHADOW_SCALE kDefaultShadowScale
-# if SANITIZER_ANDROID
-# define SHADOW_OFFSET (0)
-# else
-# if SANITIZER_WORDSIZE == 32
-# if defined(__mips__)
-# define SHADOW_OFFSET kMIPS32_ShadowOffset32
-# else
-# define SHADOW_OFFSET kDefaultShadowOffset32
-# endif
+# if SANITIZER_WORDSIZE == 32
+# if defined(__mips__)
+# define SHADOW_OFFSET kMIPS32_ShadowOffset32
+# elif SANITIZER_FREEBSD
+# define SHADOW_OFFSET kFreeBSD_ShadowOffset32
# else
-# if defined(__powerpc64__)
+# if SANITIZER_IOS
+# define SHADOW_OFFSET kIosShadowOffset32
+# else
+# define SHADOW_OFFSET kDefaultShadowOffset32
+# endif
+# endif
+# else
+# if defined(__aarch64__)
+# define SHADOW_OFFSET kAArch64_ShadowOffset64
+# elif defined(__powerpc64__)
# define SHADOW_OFFSET kPPC64_ShadowOffset64
-# elif SANITIZER_MAC
-# define SHADOW_OFFSET kDefaultShadowOffset64
-# else
-# define SHADOW_OFFSET kDefaultShort64bitShadowOffset
-# endif
+# elif SANITIZER_FREEBSD
+# define SHADOW_OFFSET kFreeBSD_ShadowOffset64
+# elif SANITIZER_MAC
+# define SHADOW_OFFSET kDefaultShadowOffset64
+# else
+# define SHADOW_OFFSET kDefaultShort64bitShadowOffset
# endif
# endif
-#endif // ASAN_FLEXIBLE_MAPPING_AND_OFFSET
+#endif
#define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE)
#define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) + (SHADOW_OFFSET))
diff --git a/libsanitizer/asan/asan_new_delete.cc b/libsanitizer/asan/asan_new_delete.cc
index beac8cdbdd5..a1ab2cd8c39 100644
--- a/libsanitizer/asan/asan_new_delete.cc
+++ b/libsanitizer/asan/asan_new_delete.cc
@@ -14,20 +14,14 @@
#include "asan_internal.h"
#include "asan_stack.h"
-#include <stddef.h>
+#include "sanitizer_common/sanitizer_interception.h"
-namespace __asan {
-// This function is a no-op. We need it to make sure that object file
-// with our replacements will actually be loaded from static ASan
-// run-time library at link-time.
-void ReplaceOperatorsNewAndDelete() { }
-}
+#include <stddef.h>
using namespace __asan; // NOLINT
-// On Android new() goes through malloc interceptors.
-// See also https://code.google.com/p/address-sanitizer/issues/detail?id=131.
-#if !SANITIZER_ANDROID
+// This code has issues on OSX.
+// See https://code.google.com/p/address-sanitizer/issues/detail?id=131.
// Fake std::nothrow_t to avoid including <new>.
namespace std {
@@ -46,6 +40,15 @@ struct nothrow_t {};
// To make sure that C++ allocation/deallocation operators are overridden on
// OS X we need to intercept them using their mangled names.
#if !SANITIZER_MAC
+// FreeBSD prior v9.2 have wrong definition of 'size_t'.
+// http://svnweb.freebsd.org/base?view=revision&revision=232261
+#if SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32
+#include <sys/param.h>
+#if __FreeBSD_version <= 902001 // v9.2
+#define size_t unsigned
+#endif // __FreeBSD_version
+#endif // SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32
+
INTERCEPTOR_ATTRIBUTE
void *operator new(size_t size) { OPERATOR_NEW_BODY(FROM_NEW); }
INTERCEPTOR_ATTRIBUTE
@@ -78,15 +81,21 @@ INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
#if !SANITIZER_MAC
INTERCEPTOR_ATTRIBUTE
-void operator delete(void *ptr) { OPERATOR_DELETE_BODY(FROM_NEW); }
+void operator delete(void *ptr) throw() {
+ OPERATOR_DELETE_BODY(FROM_NEW);
+}
INTERCEPTOR_ATTRIBUTE
-void operator delete[](void *ptr) { OPERATOR_DELETE_BODY(FROM_NEW_BR); }
+void operator delete[](void *ptr) throw() {
+ OPERATOR_DELETE_BODY(FROM_NEW_BR);
+}
INTERCEPTOR_ATTRIBUTE
-void operator delete(void *ptr, std::nothrow_t const&)
-{ OPERATOR_DELETE_BODY(FROM_NEW); }
+void operator delete(void *ptr, std::nothrow_t const&) {
+ OPERATOR_DELETE_BODY(FROM_NEW);
+}
INTERCEPTOR_ATTRIBUTE
-void operator delete[](void *ptr, std::nothrow_t const&)
-{ OPERATOR_DELETE_BODY(FROM_NEW_BR); }
+void operator delete[](void *ptr, std::nothrow_t const&) {
+ OPERATOR_DELETE_BODY(FROM_NEW_BR);
+}
#else // SANITIZER_MAC
INTERCEPTOR(void, _ZdlPv, void *ptr) {
@@ -102,5 +111,3 @@ INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) {
OPERATOR_DELETE_BODY(FROM_NEW_BR);
}
#endif
-
-#endif
diff --git a/libsanitizer/asan/asan_poisoning.cc b/libsanitizer/asan/asan_poisoning.cc
index 86d49909b68..a532c5c4388 100644
--- a/libsanitizer/asan/asan_poisoning.cc
+++ b/libsanitizer/asan/asan_poisoning.cc
@@ -11,6 +11,8 @@
//===----------------------------------------------------------------------===//
#include "asan_poisoning.h"
+#include "asan_report.h"
+#include "asan_stack.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_flags.h"
@@ -48,6 +50,15 @@ struct ShadowSegmentEndpoint {
}
};
+void FlushUnneededASanShadowMemory(uptr p, uptr size) {
+ // Since asan's mapping is compacting, the shadow chunk may be
+ // not page-aligned, so we only flush the page-aligned portion.
+ uptr page_size = GetPageSizeCached();
+ uptr shadow_beg = RoundUpTo(MemToShadow(p), page_size);
+ uptr shadow_end = RoundDownTo(MemToShadow(p + size), page_size);
+ FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg);
+}
+
} // namespace __asan
// ---------------------- Interface ---------------- {{{1
@@ -67,10 +78,8 @@ void __asan_poison_memory_region(void const volatile *addr, uptr size) {
if (!flags()->allow_user_poisoning || size == 0) return;
uptr beg_addr = (uptr)addr;
uptr end_addr = beg_addr + size;
- if (common_flags()->verbosity >= 1) {
- Printf("Trying to poison memory region [%p, %p)\n",
- (void*)beg_addr, (void*)end_addr);
- }
+ VPrintf(1, "Trying to poison memory region [%p, %p)\n", (void *)beg_addr,
+ (void *)end_addr);
ShadowSegmentEndpoint beg(beg_addr);
ShadowSegmentEndpoint end(end_addr);
if (beg.chunk == end.chunk) {
@@ -109,10 +118,8 @@ void __asan_unpoison_memory_region(void const volatile *addr, uptr size) {
if (!flags()->allow_user_poisoning || size == 0) return;
uptr beg_addr = (uptr)addr;
uptr end_addr = beg_addr + size;
- if (common_flags()->verbosity >= 1) {
- Printf("Trying to unpoison memory region [%p, %p)\n",
- (void*)beg_addr, (void*)end_addr);
- }
+ VPrintf(1, "Trying to unpoison memory region [%p, %p)\n", (void *)beg_addr,
+ (void *)end_addr);
ShadowSegmentEndpoint beg(beg_addr);
ShadowSegmentEndpoint end(end_addr);
if (beg.chunk == end.chunk) {
@@ -137,7 +144,7 @@ void __asan_unpoison_memory_region(void const volatile *addr, uptr size) {
}
}
-bool __asan_address_is_poisoned(void const volatile *addr) {
+int __asan_address_is_poisoned(void const volatile *addr) {
return __asan::AddressIsPoisoned((uptr)addr);
}
@@ -146,6 +153,7 @@ uptr __asan_region_is_poisoned(uptr beg, uptr size) {
uptr end = beg + size;
if (!AddrIsInMem(beg)) return beg;
if (!AddrIsInMem(end)) return end;
+ CHECK_LT(beg, end);
uptr aligned_b = RoundUpTo(beg, SHADOW_GRANULARITY);
uptr aligned_e = RoundDownTo(end, SHADOW_GRANULARITY);
uptr shadow_beg = MemToShadow(aligned_b);
@@ -243,14 +251,12 @@ static void PoisonAlignedStackMemory(uptr addr, uptr size, bool do_poison) {
}
void __asan_poison_stack_memory(uptr addr, uptr size) {
- if (common_flags()->verbosity > 0)
- Report("poisoning: %p %zx\n", (void*)addr, size);
+ VReport(1, "poisoning: %p %zx\n", (void *)addr, size);
PoisonAlignedStackMemory(addr, size, true);
}
void __asan_unpoison_stack_memory(uptr addr, uptr size) {
- if (common_flags()->verbosity > 0)
- Report("unpoisoning: %p %zx\n", (void*)addr, size);
+ VReport(1, "unpoisoning: %p %zx\n", (void *)addr, size);
PoisonAlignedStackMemory(addr, size, false);
}
@@ -258,33 +264,40 @@ void __sanitizer_annotate_contiguous_container(const void *beg_p,
const void *end_p,
const void *old_mid_p,
const void *new_mid_p) {
- if (common_flags()->verbosity >= 2)
- Printf("contiguous_container: %p %p %p %p\n", beg_p, end_p, old_mid_p,
- new_mid_p);
+ if (!flags()->detect_container_overflow) return;
+ VPrintf(2, "contiguous_container: %p %p %p %p\n", beg_p, end_p, old_mid_p,
+ new_mid_p);
uptr beg = reinterpret_cast<uptr>(beg_p);
- uptr end= reinterpret_cast<uptr>(end_p);
+ uptr end = reinterpret_cast<uptr>(end_p);
uptr old_mid = reinterpret_cast<uptr>(old_mid_p);
uptr new_mid = reinterpret_cast<uptr>(new_mid_p);
uptr granularity = SHADOW_GRANULARITY;
- CHECK(beg <= old_mid && beg <= new_mid && old_mid <= end && new_mid <= end &&
- IsAligned(beg, granularity));
+ if (!(beg <= old_mid && beg <= new_mid && old_mid <= end && new_mid <= end &&
+ IsAligned(beg, granularity))) {
+ GET_STACK_TRACE_FATAL_HERE;
+ ReportBadParamsToAnnotateContiguousContainer(beg, end, old_mid, new_mid,
+ &stack);
+ }
CHECK_LE(end - beg,
FIRST_32_SECOND_64(1UL << 30, 1UL << 34)); // Sanity check.
uptr a = RoundDownTo(Min(old_mid, new_mid), granularity);
uptr c = RoundUpTo(Max(old_mid, new_mid), granularity);
uptr d1 = RoundDownTo(old_mid, granularity);
- uptr d2 = RoundUpTo(old_mid, granularity);
+ // uptr d2 = RoundUpTo(old_mid, granularity);
// Currently we should be in this state:
// [a, d1) is good, [d2, c) is bad, [d1, d2) is partially good.
// Make a quick sanity check that we are indeed in this state.
- if (d1 != d2)
- CHECK_EQ(*(u8*)MemToShadow(d1), old_mid - d1);
+ //
+ // FIXME: Two of these three checks are disabled until we fix
+ // https://code.google.com/p/address-sanitizer/issues/detail?id=258.
+ // if (d1 != d2)
+ // CHECK_EQ(*(u8*)MemToShadow(d1), old_mid - d1);
if (a + granularity <= d1)
CHECK_EQ(*(u8*)MemToShadow(a), 0);
- if (d2 + granularity <= c && c <= end)
- CHECK_EQ(*(u8 *)MemToShadow(c - granularity),
- kAsanContiguousContainerOOBMagic);
+ // if (d2 + granularity <= c && c <= end)
+ // CHECK_EQ(*(u8 *)MemToShadow(c - granularity),
+ // kAsanContiguousContainerOOBMagic);
uptr b1 = RoundDownTo(new_mid, granularity);
uptr b2 = RoundUpTo(new_mid, granularity);
@@ -297,3 +310,42 @@ void __sanitizer_annotate_contiguous_container(const void *beg_p,
*(u8*)MemToShadow(b1) = static_cast<u8>(new_mid - b1);
}
}
+
+int __sanitizer_verify_contiguous_container(const void *beg_p,
+ const void *mid_p,
+ const void *end_p) {
+ if (!flags()->detect_container_overflow) return 1;
+ uptr beg = reinterpret_cast<uptr>(beg_p);
+ uptr end = reinterpret_cast<uptr>(end_p);
+ uptr mid = reinterpret_cast<uptr>(mid_p);
+ CHECK_LE(beg, mid);
+ CHECK_LE(mid, end);
+ // Check some bytes starting from beg, some bytes around mid, and some bytes
+ // ending with end.
+ uptr kMaxRangeToCheck = 32;
+ uptr r1_beg = beg;
+ uptr r1_end = Min(end + kMaxRangeToCheck, mid);
+ uptr r2_beg = Max(beg, mid - kMaxRangeToCheck);
+ uptr r2_end = Min(end, mid + kMaxRangeToCheck);
+ uptr r3_beg = Max(end - kMaxRangeToCheck, mid);
+ uptr r3_end = end;
+ for (uptr i = r1_beg; i < r1_end; i++)
+ if (AddressIsPoisoned(i))
+ return 0;
+ for (uptr i = r2_beg; i < mid; i++)
+ if (AddressIsPoisoned(i))
+ return 0;
+ for (uptr i = mid; i < r2_end; i++)
+ if (!AddressIsPoisoned(i))
+ return 0;
+ for (uptr i = r3_beg; i < r3_end; i++)
+ if (!AddressIsPoisoned(i))
+ return 0;
+ return 1;
+}
+// --- Implementation of LSan-specific functions --- {{{1
+namespace __lsan {
+bool WordIsPoisoned(uptr addr) {
+ return (__asan_region_is_poisoned(addr, sizeof(uptr)) != 0);
+}
+}
diff --git a/libsanitizer/asan/asan_poisoning.h b/libsanitizer/asan/asan_poisoning.h
index da79a0ff2e4..326d9ba1b67 100644
--- a/libsanitizer/asan/asan_poisoning.h
+++ b/libsanitizer/asan/asan_poisoning.h
@@ -13,6 +13,7 @@
#include "asan_interceptors.h"
#include "asan_internal.h"
#include "asan_mapping.h"
+#include "sanitizer_common/sanitizer_flags.h"
namespace __asan {
@@ -32,10 +33,35 @@ void PoisonShadowPartialRightRedzone(uptr addr,
ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,
u8 value) {
DCHECK(flags()->poison_heap);
+ uptr PageSize = GetPageSizeCached();
uptr shadow_beg = MEM_TO_SHADOW(aligned_beg);
uptr shadow_end = MEM_TO_SHADOW(
aligned_beg + aligned_size - SHADOW_GRANULARITY) + 1;
- REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
+ // FIXME: Page states are different on Windows, so using the same interface
+ // for mapping shadow and zeroing out pages doesn't "just work", so we should
+ // probably provide higher-level interface for these operations.
+ // For now, just memset on Windows.
+ if (value ||
+ SANITIZER_WINDOWS == 1 ||
+ shadow_end - shadow_beg < common_flags()->clear_shadow_mmap_threshold) {
+ REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
+ } else {
+ uptr page_beg = RoundUpTo(shadow_beg, PageSize);
+ uptr page_end = RoundDownTo(shadow_end, PageSize);
+
+ if (page_beg >= page_end) {
+ REAL(memset)((void *)shadow_beg, 0, shadow_end - shadow_beg);
+ } else {
+ if (page_beg != shadow_beg) {
+ REAL(memset)((void *)shadow_beg, 0, page_beg - shadow_beg);
+ }
+ if (page_end != shadow_end) {
+ REAL(memset)((void *)page_end, 0, shadow_end - page_end);
+ }
+ void *res = MmapFixedNoReserve(page_beg, page_end - page_beg);
+ CHECK_EQ(page_beg, res);
+ }
+ }
}
ALWAYS_INLINE void FastPoisonShadowPartialRightRedzone(
@@ -55,4 +81,8 @@ ALWAYS_INLINE void FastPoisonShadowPartialRightRedzone(
}
}
+// Calls __sanitizer::FlushUnneededShadowMemory() on
+// [MemToShadow(p), MemToShadow(p+size)] with proper rounding.
+void FlushUnneededASanShadowMemory(uptr p, uptr size);
+
} // namespace __asan
diff --git a/libsanitizer/asan/asan_posix.cc b/libsanitizer/asan/asan_posix.cc
index ac4ec9e0191..8f3798a2e59 100644
--- a/libsanitizer/asan/asan_posix.cc
+++ b/libsanitizer/asan/asan_posix.cc
@@ -11,7 +11,7 @@
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_platform.h"
-#if SANITIZER_LINUX || SANITIZER_MAC
+#if SANITIZER_POSIX
#include "asan_internal.h"
#include "asan_interceptors.h"
@@ -28,70 +28,27 @@
#include <sys/resource.h>
#include <unistd.h>
-static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough.
-
namespace __asan {
-static void MaybeInstallSigaction(int signum,
- void (*handler)(int, siginfo_t *, void *)) {
- if (!AsanInterceptsSignal(signum))
- return;
- struct sigaction sigact;
- REAL(memset)(&sigact, 0, sizeof(sigact));
- sigact.sa_sigaction = handler;
- sigact.sa_flags = SA_SIGINFO;
- if (flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;
- CHECK_EQ(0, REAL(sigaction)(signum, &sigact, 0));
- if (common_flags()->verbosity >= 1) {
- Report("Installed the sigaction for signal %d\n", signum);
- }
-}
-
-static void ASAN_OnSIGSEGV(int, siginfo_t *siginfo, void *context) {
- uptr addr = (uptr)siginfo->si_addr;
+void AsanOnSIGSEGV(int, void *siginfo, void *context) {
+ uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr;
+ int code = (int)((siginfo_t*)siginfo)->si_code;
// Write the first message using the bullet-proof write.
if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die();
uptr pc, sp, bp;
GetPcSpBp(context, &pc, &sp, &bp);
- ReportSIGSEGV(pc, sp, bp, addr);
-}
-
-void SetAlternateSignalStack() {
- stack_t altstack, oldstack;
- CHECK_EQ(0, sigaltstack(0, &oldstack));
- // If the alternate stack is already in place, do nothing.
- if ((oldstack.ss_flags & SS_DISABLE) == 0) return;
- // TODO(glider): the mapped stack should have the MAP_STACK flag in the
- // future. It is not required by man 2 sigaltstack now (they're using
- // malloc()).
- void* base = MmapOrDie(kAltStackSize, __FUNCTION__);
- altstack.ss_sp = base;
- altstack.ss_flags = 0;
- altstack.ss_size = kAltStackSize;
- CHECK_EQ(0, sigaltstack(&altstack, 0));
- if (common_flags()->verbosity > 0) {
- Report("Alternative stack for T%d set: [%p,%p)\n",
- GetCurrentTidOrInvalid(),
- altstack.ss_sp, (char*)altstack.ss_sp + altstack.ss_size);
- }
-}
-
-void UnsetAlternateSignalStack() {
- stack_t altstack, oldstack;
- altstack.ss_sp = 0;
- altstack.ss_flags = SS_DISABLE;
- altstack.ss_size = 0;
- CHECK_EQ(0, sigaltstack(&altstack, &oldstack));
- UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
-}
-void InstallSignalHandlers() {
- // Set the alternate signal stack for the main thread.
- // This will cause SetAlternateSignalStack to be called twice, but the stack
- // will be actually set only once.
- if (flags()->use_sigaltstack) SetAlternateSignalStack();
- MaybeInstallSigaction(SIGSEGV, ASAN_OnSIGSEGV);
- MaybeInstallSigaction(SIGBUS, ASAN_OnSIGSEGV);
+ // Access at a reasonable offset above SP, or slightly below it (to account
+ // for x86_64 redzone, ARM push of multiple registers, etc) is probably a
+ // stack overflow.
+ // We also check si_code to filter out SEGV caused by something else other
+ // then hitting the guard page or unmapped memory, like, for example,
+ // unaligned memory access.
+ if (addr + 128 > sp && addr < sp + 0xFFFF &&
+ (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR))
+ ReportStackOverflow(pc, sp, bp, context, addr);
+ else
+ ReportSIGSEGV(pc, sp, bp, context, addr);
}
// ---------------------- TSD ---------------- {{{1
@@ -125,4 +82,4 @@ void PlatformTSDDtor(void *tsd) {
}
} // namespace __asan
-#endif // SANITIZER_LINUX || SANITIZER_MAC
+#endif // SANITIZER_POSIX
diff --git a/libsanitizer/asan/asan_report.cc b/libsanitizer/asan/asan_report.cc
index 70c4b481a2f..d0a89b9677e 100644
--- a/libsanitizer/asan/asan_report.cc
+++ b/libsanitizer/asan/asan_report.cc
@@ -43,11 +43,9 @@ void AppendToErrorMessageBuffer(const char *buffer) {
}
// ---------------------- Decorator ------------------------------ {{{1
-class Decorator: private __sanitizer::AnsiColorDecorator {
+class Decorator: public __sanitizer::SanitizerCommonDecorator {
public:
- Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { }
- const char *Warning() { return Red(); }
- const char *EndWarning() { return Default(); }
+ Decorator() : SanitizerCommonDecorator() { }
const char *Access() { return Blue(); }
const char *EndAccess() { return Default(); }
const char *Location() { return Green(); }
@@ -89,68 +87,77 @@ class Decorator: private __sanitizer::AnsiColorDecorator {
// ---------------------- Helper functions ----------------------- {{{1
-static void PrintShadowByte(const char *before, u8 byte,
- const char *after = "\n") {
+static void PrintShadowByte(InternalScopedString *str, const char *before,
+ u8 byte, const char *after = "\n") {
Decorator d;
- Printf("%s%s%x%x%s%s", before,
- d.ShadowByte(byte), byte >> 4, byte & 15, d.EndShadowByte(), after);
+ str->append("%s%s%x%x%s%s", before, d.ShadowByte(byte), byte >> 4, byte & 15,
+ d.EndShadowByte(), after);
}
-static void PrintShadowBytes(const char *before, u8 *bytes,
- u8 *guilty, uptr n) {
+static void PrintShadowBytes(InternalScopedString *str, const char *before,
+ u8 *bytes, u8 *guilty, uptr n) {
Decorator d;
- if (before)
- Printf("%s%p:", before, bytes);
+ if (before) str->append("%s%p:", before, bytes);
for (uptr i = 0; i < n; i++) {
u8 *p = bytes + i;
- const char *before = p == guilty ? "[" :
- (p - 1 == guilty && i != 0) ? "" : " ";
+ const char *before =
+ p == guilty ? "[" : (p - 1 == guilty && i != 0) ? "" : " ";
const char *after = p == guilty ? "]" : "";
- PrintShadowByte(before, *p, after);
+ PrintShadowByte(str, before, *p, after);
}
- Printf("\n");
-}
-
-static void PrintLegend() {
- Printf("Shadow byte legend (one shadow byte represents %d "
- "application bytes):\n", (int)SHADOW_GRANULARITY);
- PrintShadowByte(" Addressable: ", 0);
- Printf(" Partially addressable: ");
- for (u8 i = 1; i < SHADOW_GRANULARITY; i++)
- PrintShadowByte("", i, " ");
- Printf("\n");
- PrintShadowByte(" Heap left redzone: ", kAsanHeapLeftRedzoneMagic);
- PrintShadowByte(" Heap right redzone: ", kAsanHeapRightRedzoneMagic);
- PrintShadowByte(" Freed heap region: ", kAsanHeapFreeMagic);
- PrintShadowByte(" Stack left redzone: ", kAsanStackLeftRedzoneMagic);
- PrintShadowByte(" Stack mid redzone: ", kAsanStackMidRedzoneMagic);
- PrintShadowByte(" Stack right redzone: ", kAsanStackRightRedzoneMagic);
- PrintShadowByte(" Stack partial redzone: ", kAsanStackPartialRedzoneMagic);
- PrintShadowByte(" Stack after return: ", kAsanStackAfterReturnMagic);
- PrintShadowByte(" Stack use after scope: ", kAsanStackUseAfterScopeMagic);
- PrintShadowByte(" Global redzone: ", kAsanGlobalRedzoneMagic);
- PrintShadowByte(" Global init order: ", kAsanInitializationOrderMagic);
- PrintShadowByte(" Poisoned by user: ", kAsanUserPoisonedMemoryMagic);
- PrintShadowByte(" Contiguous container OOB:",
+ str->append("\n");
+}
+
+static void PrintLegend(InternalScopedString *str) {
+ str->append(
+ "Shadow byte legend (one shadow byte represents %d "
+ "application bytes):\n",
+ (int)SHADOW_GRANULARITY);
+ PrintShadowByte(str, " Addressable: ", 0);
+ str->append(" Partially addressable: ");
+ for (u8 i = 1; i < SHADOW_GRANULARITY; i++) PrintShadowByte(str, "", i, " ");
+ str->append("\n");
+ PrintShadowByte(str, " Heap left redzone: ",
+ kAsanHeapLeftRedzoneMagic);
+ PrintShadowByte(str, " Heap right redzone: ",
+ kAsanHeapRightRedzoneMagic);
+ PrintShadowByte(str, " Freed heap region: ", kAsanHeapFreeMagic);
+ PrintShadowByte(str, " Stack left redzone: ",
+ kAsanStackLeftRedzoneMagic);
+ PrintShadowByte(str, " Stack mid redzone: ",
+ kAsanStackMidRedzoneMagic);
+ PrintShadowByte(str, " Stack right redzone: ",
+ kAsanStackRightRedzoneMagic);
+ PrintShadowByte(str, " Stack partial redzone: ",
+ kAsanStackPartialRedzoneMagic);
+ PrintShadowByte(str, " Stack after return: ",
+ kAsanStackAfterReturnMagic);
+ PrintShadowByte(str, " Stack use after scope: ",
+ kAsanStackUseAfterScopeMagic);
+ PrintShadowByte(str, " Global redzone: ", kAsanGlobalRedzoneMagic);
+ PrintShadowByte(str, " Global init order: ",
+ kAsanInitializationOrderMagic);
+ PrintShadowByte(str, " Poisoned by user: ",
+ kAsanUserPoisonedMemoryMagic);
+ PrintShadowByte(str, " Container overflow: ",
kAsanContiguousContainerOOBMagic);
- PrintShadowByte(" ASan internal: ", kAsanInternalHeapMagic);
+ PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic);
}
static void PrintShadowMemoryForAddress(uptr addr) {
- if (!AddrIsInMem(addr))
- return;
+ if (!AddrIsInMem(addr)) return;
uptr shadow_addr = MemToShadow(addr);
const uptr n_bytes_per_row = 16;
uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
- Printf("Shadow bytes around the buggy address:\n");
+ InternalScopedString str(4096 * 8);
+ str.append("Shadow bytes around the buggy address:\n");
for (int i = -5; i <= 5; i++) {
const char *prefix = (i == 0) ? "=>" : " ";
- PrintShadowBytes(prefix,
- (u8*)(aligned_shadow + i * n_bytes_per_row),
- (u8*)shadow_addr, n_bytes_per_row);
+ PrintShadowBytes(&str, prefix, (u8 *)(aligned_shadow + i * n_bytes_per_row),
+ (u8 *)shadow_addr, n_bytes_per_row);
}
- if (flags()->print_legend)
- PrintLegend();
+ if (flags()->print_legend) PrintLegend(&str);
+ Printf("%s", str.data());
}
static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
@@ -182,20 +189,25 @@ static bool IsASCII(unsigned char c) {
static const char *MaybeDemangleGlobalName(const char *name) {
// We can spoil names of globals with C linkage, so use an heuristic
// approach to check if the name should be demangled.
- return (name[0] == '_' && name[1] == 'Z')
- ? Symbolizer::Get()->Demangle(name)
- : name;
+ bool should_demangle = false;
+ if (name[0] == '_' && name[1] == 'Z')
+ should_demangle = true;
+ else if (SANITIZER_WINDOWS && name[0] == '\01' && name[1] == '?')
+ should_demangle = true;
+
+ return should_demangle ? Symbolizer::Get()->Demangle(name) : name;
}
// Check if the global is a zero-terminated ASCII string. If so, print it.
-static void PrintGlobalNameIfASCII(const __asan_global &g) {
+static void PrintGlobalNameIfASCII(InternalScopedString *str,
+ const __asan_global &g) {
for (uptr p = g.beg; p < g.beg + g.size - 1; p++) {
unsigned char c = *(unsigned char*)p;
if (c == '\0' || !IsASCII(c)) return;
}
if (*(char*)(g.beg + g.size - 1) != '\0') return;
- Printf(" '%s' is ascii string '%s'\n",
- MaybeDemangleGlobalName(g.name), (char*)g.beg);
+ str->append(" '%s' is ascii string '%s'\n", MaybeDemangleGlobalName(g.name),
+ (char *)g.beg);
}
bool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
@@ -203,23 +215,26 @@ bool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
static const uptr kMinimalDistanceFromAnotherGlobal = 64;
if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false;
if (addr >= g.beg + g.size_with_redzone) return false;
+ InternalScopedString str(4096);
Decorator d;
- Printf("%s", d.Location());
+ str.append("%s", d.Location());
if (addr < g.beg) {
- Printf("%p is located %zd bytes to the left", (void*)addr, g.beg - addr);
+ str.append("%p is located %zd bytes to the left", (void *)addr,
+ g.beg - addr);
} else if (addr + size > g.beg + g.size) {
if (addr < g.beg + g.size)
addr = g.beg + g.size;
- Printf("%p is located %zd bytes to the right", (void*)addr,
- addr - (g.beg + g.size));
+ str.append("%p is located %zd bytes to the right", (void *)addr,
+ addr - (g.beg + g.size));
} else {
// Can it happen?
- Printf("%p is located %zd bytes inside", (void*)addr, addr - g.beg);
+ str.append("%p is located %zd bytes inside", (void *)addr, addr - g.beg);
}
- Printf(" of global variable '%s' from '%s' (0x%zx) of size %zu\n",
+ str.append(" of global variable '%s' from '%s' (0x%zx) of size %zu\n",
MaybeDemangleGlobalName(g.name), g.module_name, g.beg, g.size);
- Printf("%s", d.EndLocation());
- PrintGlobalNameIfASCII(g);
+ str.append("%s", d.EndLocation());
+ PrintGlobalNameIfASCII(&str, g);
+ Printf("%s", str.data());
return true;
}
@@ -288,16 +303,18 @@ void PrintAccessAndVarIntersection(const char *var_name,
addr - prev_var_end >= var_beg - addr_end)
pos_descr = "underflows";
}
- Printf(" [%zd, %zd) '%s'", var_beg, var_beg + var_size, var_name);
+ InternalScopedString str(1024);
+ str.append(" [%zd, %zd) '%s'", var_beg, var_beg + var_size, var_name);
if (pos_descr) {
Decorator d;
// FIXME: we may want to also print the size of the access here,
// but in case of accesses generated by memset it may be confusing.
- Printf("%s <== Memory access at offset %zd %s this variable%s\n",
- d.Location(), addr, pos_descr, d.EndLocation());
+ str.append("%s <== Memory access at offset %zd %s this variable%s\n",
+ d.Location(), addr, pos_descr, d.EndLocation());
} else {
- Printf("\n");
+ str.append("\n");
}
+ Printf("%s", str.data());
}
struct StackVarDescr {
@@ -346,7 +363,7 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) {
alloca_stack.trace[0] = frame_pc + 16;
alloca_stack.size = 1;
Printf("%s", d.EndLocation());
- PrintStack(&alloca_stack);
+ alloca_stack.Print();
// Report the number of stack objects.
char *p;
uptr n_objects = (uptr)internal_simple_strtoll(frame_descr, &p, 10);
@@ -394,24 +411,26 @@ static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr,
uptr access_size) {
sptr offset;
Decorator d;
- Printf("%s", d.Location());
+ InternalScopedString str(4096);
+ str.append("%s", d.Location());
if (chunk.AddrIsAtLeft(addr, access_size, &offset)) {
- Printf("%p is located %zd bytes to the left of", (void*)addr, offset);
+ str.append("%p is located %zd bytes to the left of", (void *)addr, offset);
} else if (chunk.AddrIsAtRight(addr, access_size, &offset)) {
if (offset < 0) {
addr -= offset;
offset = 0;
}
- Printf("%p is located %zd bytes to the right of", (void*)addr, offset);
+ str.append("%p is located %zd bytes to the right of", (void *)addr, offset);
} else if (chunk.AddrIsInside(addr, access_size, &offset)) {
- Printf("%p is located %zd bytes inside of", (void*)addr, offset);
+ str.append("%p is located %zd bytes inside of", (void*)addr, offset);
} else {
- Printf("%p is located somewhere around (this is AddressSanitizer bug!)",
- (void*)addr);
+ str.append("%p is located somewhere around (this is AddressSanitizer bug!)",
+ (void *)addr);
}
- Printf(" %zu-byte region [%p,%p)\n", chunk.UsedSize(),
- (void*)(chunk.Beg()), (void*)(chunk.End()));
- Printf("%s", d.EndLocation());
+ str.append(" %zu-byte region [%p,%p)\n", chunk.UsedSize(),
+ (void *)(chunk.Beg()), (void *)(chunk.End()));
+ str.append("%s", d.EndLocation());
+ Printf("%s", str.data());
}
void DescribeHeapAddress(uptr addr, uptr access_size) {
@@ -439,7 +458,7 @@ void DescribeHeapAddress(uptr addr, uptr access_size) {
d.EndAllocation());
StackTrace free_stack;
chunk.GetFreeStack(&free_stack);
- PrintStack(&free_stack);
+ free_stack.Print();
Printf("%spreviously allocated by thread T%d%s here:%s\n",
d.Allocation(), alloc_thread->tid,
ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
@@ -450,7 +469,7 @@ void DescribeHeapAddress(uptr addr, uptr access_size) {
ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
d.EndAllocation());
}
- PrintStack(&alloc_stack);
+ alloc_stack.Print();
DescribeThread(GetCurrentThread());
if (free_thread)
DescribeThread(free_thread);
@@ -481,15 +500,16 @@ void DescribeThread(AsanThreadContext *context) {
}
context->announced = true;
char tname[128];
- Printf("Thread T%d%s", context->tid,
- ThreadNameWithParenthesis(context->tid, tname, sizeof(tname)));
- Printf(" created by T%d%s here:\n",
- context->parent_tid,
- ThreadNameWithParenthesis(context->parent_tid,
- tname, sizeof(tname)));
+ InternalScopedString str(1024);
+ str.append("Thread T%d%s", context->tid,
+ ThreadNameWithParenthesis(context->tid, tname, sizeof(tname)));
+ str.append(
+ " created by T%d%s here:\n", context->parent_tid,
+ ThreadNameWithParenthesis(context->parent_tid, tname, sizeof(tname)));
+ Printf("%s", str.data());
uptr stack_size;
const uptr *stack_trace = StackDepotGet(context->stack_id, &stack_size);
- PrintStack(stack_trace, stack_size);
+ StackTrace::PrintStack(stack_trace, stack_size);
// Recursively described parent thread if needed.
if (flags()->print_full_thread_history) {
AsanThreadContext *parent_context =
@@ -539,6 +559,8 @@ class ScopedInErrorReport {
NORETURN ~ScopedInErrorReport() {
// Make sure the current thread is announced.
DescribeThread(GetCurrentThread());
+ // We may want to grab this lock again when printing stats.
+ asanThreadRegistry().Unlock();
// Print memory stats.
if (flags()->print_stats)
__asan_print_accumulated_stats();
@@ -550,17 +572,33 @@ class ScopedInErrorReport {
}
};
-void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
+void ReportStackOverflow(uptr pc, uptr sp, uptr bp, void *context, uptr addr) {
ScopedInErrorReport in_report;
Decorator d;
Printf("%s", d.Warning());
- Report("ERROR: AddressSanitizer: SEGV on unknown address %p"
- " (pc %p sp %p bp %p T%d)\n",
- (void*)addr, (void*)pc, (void*)sp, (void*)bp,
- GetCurrentTidOrInvalid());
+ Report(
+ "ERROR: AddressSanitizer: stack-overflow on address %p"
+ " (pc %p sp %p bp %p T%d)\n",
+ (void *)addr, (void *)pc, (void *)sp, (void *)bp,
+ GetCurrentTidOrInvalid());
Printf("%s", d.EndWarning());
- GET_STACK_TRACE_FATAL(pc, bp);
- PrintStack(&stack);
+ GET_STACK_TRACE_SIGNAL(pc, bp, context);
+ stack.Print();
+ ReportErrorSummary("stack-overflow", &stack);
+}
+
+void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, void *context, uptr addr) {
+ ScopedInErrorReport in_report;
+ Decorator d;
+ Printf("%s", d.Warning());
+ Report(
+ "ERROR: AddressSanitizer: SEGV on unknown address %p"
+ " (pc %p sp %p bp %p T%d)\n",
+ (void *)addr, (void *)pc, (void *)sp, (void *)bp,
+ GetCurrentTidOrInvalid());
+ Printf("%s", d.EndWarning());
+ GET_STACK_TRACE_SIGNAL(pc, bp, context);
+ stack.Print();
Printf("AddressSanitizer can not provide additional info.\n");
ReportErrorSummary("SEGV", &stack);
}
@@ -578,7 +616,7 @@ void ReportDoubleFree(uptr addr, StackTrace *free_stack) {
Printf("%s", d.EndWarning());
CHECK_GT(free_stack->size, 0);
GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
- PrintStack(&stack);
+ stack.Print();
DescribeHeapAddress(addr, 1);
ReportErrorSummary("double-free", &stack);
}
@@ -595,7 +633,7 @@ void ReportFreeNotMalloced(uptr addr, StackTrace *free_stack) {
Printf("%s", d.EndWarning());
CHECK_GT(free_stack->size, 0);
GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
- PrintStack(&stack);
+ stack.Print();
DescribeHeapAddress(addr, 1);
ReportErrorSummary("bad-free", &stack);
}
@@ -616,7 +654,7 @@ void ReportAllocTypeMismatch(uptr addr, StackTrace *free_stack,
Printf("%s", d.EndWarning());
CHECK_GT(free_stack->size, 0);
GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
- PrintStack(&stack);
+ stack.Print();
DescribeHeapAddress(addr, 1);
ReportErrorSummary("alloc-dealloc-mismatch", &stack);
Report("HINT: if you don't care about these warnings you may set "
@@ -631,7 +669,7 @@ void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
"malloc_usable_size() for pointer which is "
"not owned: %p\n", addr);
Printf("%s", d.EndWarning());
- PrintStack(stack);
+ stack->Print();
DescribeHeapAddress(addr, 1);
ReportErrorSummary("bad-malloc_usable_size", stack);
}
@@ -644,7 +682,7 @@ void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
"__asan_get_allocated_size() for pointer which is "
"not owned: %p\n", addr);
Printf("%s", d.EndWarning());
- PrintStack(stack);
+ stack->Print();
DescribeHeapAddress(addr, 1);
ReportErrorSummary("bad-__asan_get_allocated_size", stack);
}
@@ -661,12 +699,81 @@ void ReportStringFunctionMemoryRangesOverlap(
"memory ranges [%p,%p) and [%p, %p) overlap\n", \
bug_type, offset1, offset1 + length1, offset2, offset2 + length2);
Printf("%s", d.EndWarning());
- PrintStack(stack);
+ stack->Print();
DescribeAddress((uptr)offset1, length1);
DescribeAddress((uptr)offset2, length2);
ReportErrorSummary(bug_type, stack);
}
+void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
+ StackTrace *stack) {
+ ScopedInErrorReport in_report;
+ Decorator d;
+ const char *bug_type = "negative-size-param";
+ Printf("%s", d.Warning());
+ Report("ERROR: AddressSanitizer: %s: (size=%zd)\n", bug_type, size);
+ Printf("%s", d.EndWarning());
+ stack->Print();
+ DescribeAddress(offset, size);
+ ReportErrorSummary(bug_type, stack);
+}
+
+void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
+ uptr old_mid, uptr new_mid,
+ StackTrace *stack) {
+ ScopedInErrorReport in_report;
+ Report("ERROR: AddressSanitizer: bad parameters to "
+ "__sanitizer_annotate_contiguous_container:\n"
+ " beg : %p\n"
+ " end : %p\n"
+ " old_mid : %p\n"
+ " new_mid : %p\n",
+ beg, end, old_mid, new_mid);
+ stack->Print();
+ ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack);
+}
+
+void ReportODRViolation(const __asan_global *g1, const __asan_global *g2) {
+ ScopedInErrorReport in_report;
+ Decorator d;
+ Printf("%s", d.Warning());
+ Report("ERROR: AddressSanitizer: odr-violation (%p):\n", g1->beg);
+ Printf("%s", d.EndWarning());
+ Printf(" [1] size=%zd %s %s\n", g1->size, g1->name, g1->module_name);
+ Printf(" [2] size=%zd %s %s\n", g2->size, g2->name, g2->module_name);
+ Report("HINT: if you don't care about these warnings you may set "
+ "ASAN_OPTIONS=detect_odr_violation=0\n");
+ ReportErrorSummary("odr-violation", g1->module_name, 0, g1->name);
+}
+
+// ----------------------- CheckForInvalidPointerPair ----------- {{{1
+static NOINLINE void
+ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp, uptr a1, uptr a2) {
+ ScopedInErrorReport in_report;
+ Decorator d;
+ Printf("%s", d.Warning());
+ Report("ERROR: AddressSanitizer: invalid-pointer-pair: %p %p\n", a1, a2);
+ Printf("%s", d.EndWarning());
+ GET_STACK_TRACE_FATAL(pc, bp);
+ stack.Print();
+ DescribeAddress(a1, 1);
+ DescribeAddress(a2, 1);
+ ReportErrorSummary("invalid-pointer-pair", &stack);
+}
+
+static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) {
+ if (!flags()->detect_invalid_pointer_pairs) return;
+ uptr a1 = reinterpret_cast<uptr>(p1);
+ uptr a2 = reinterpret_cast<uptr>(p2);
+ AsanChunkView chunk1 = FindHeapChunkByAddress(a1);
+ AsanChunkView chunk2 = FindHeapChunkByAddress(a2);
+ bool valid1 = chunk1.IsValid();
+ bool valid2 = chunk2.IsValid();
+ if ((valid1 != valid2) || (valid1 && valid2 && !chunk1.Eq(chunk2))) {
+ GET_CALLER_PC_BP_SP; \
+ return ReportInvalidPointerPair(pc, bp, sp, a1, a2);
+ }
+}
// ----------------------- Mac-specific reports ----------------- {{{1
void WarnMacFreeUnallocated(
@@ -676,7 +783,7 @@ void WarnMacFreeUnallocated(
"AddressSanitizer is ignoring this error on Mac OS now.\n",
addr);
PrintZoneForPointer(addr, zone_ptr, zone_name);
- PrintStack(stack);
+ stack->Print();
DescribeHeapAddress(addr, 1);
}
@@ -687,7 +794,7 @@ void ReportMacMzReallocUnknown(
"This is an unrecoverable problem, exiting now.\n",
addr);
PrintZoneForPointer(addr, zone_ptr, zone_name);
- PrintStack(stack);
+ stack->Print();
DescribeHeapAddress(addr, 1);
}
@@ -698,7 +805,7 @@ void ReportMacCfReallocUnknown(
"This is an unrecoverable problem, exiting now.\n",
addr);
PrintZoneForPointer(addr, zone_ptr, zone_name);
- PrintStack(stack);
+ stack->Print();
DescribeHeapAddress(addr, 1);
}
@@ -707,8 +814,8 @@ void ReportMacCfReallocUnknown(
// --------------------------- Interface --------------------- {{{1
using namespace __asan; // NOLINT
-void __asan_report_error(uptr pc, uptr bp, uptr sp,
- uptr addr, bool is_write, uptr access_size) {
+void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
+ uptr access_size) {
ScopedInErrorReport in_report;
// Determine the error type.
@@ -774,7 +881,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp,
d.EndAccess());
GET_STACK_TRACE_FATAL(pc, bp);
- PrintStack(&stack);
+ stack.Print();
DescribeAddress(addr, access_size);
ReportErrorSummary(bug_descr, &stack);
@@ -786,7 +893,7 @@ void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
if (callback) {
error_message_buffer_size = 1 << 16;
error_message_buffer =
- (char*)MmapOrDie(error_message_buffer_size, __FUNCTION__);
+ (char*)MmapOrDie(error_message_buffer_size, __func__);
error_message_buffer_pos = 0;
}
}
@@ -795,6 +902,17 @@ void __asan_describe_address(uptr addr) {
DescribeAddress(addr, 1);
}
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_ptr_sub(void *a, void *b) {
+ CheckForInvalidPointerPair(a, b);
+}
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_ptr_cmp(void *a, void *b) {
+ CheckForInvalidPointerPair(a, b);
+}
+} // extern "C"
+
#if !SANITIZER_SUPPORTS_WEAK_HOOKS
// Provide default implementation of __asan_on_error that does nothing
// and may be overriden by user.
diff --git a/libsanitizer/asan/asan_report.h b/libsanitizer/asan/asan_report.h
index e4c756e557f..d9a0bca6423 100644
--- a/libsanitizer/asan/asan_report.h
+++ b/libsanitizer/asan/asan_report.h
@@ -30,7 +30,10 @@ void DescribeAddress(uptr addr, uptr access_size);
void DescribeThread(AsanThreadContext *context);
// Different kinds of error reports.
-void NORETURN ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr);
+void NORETURN
+ ReportStackOverflow(uptr pc, uptr sp, uptr bp, void *context, uptr addr);
+void NORETURN
+ ReportSIGSEGV(uptr pc, uptr sp, uptr bp, void *context, uptr addr);
void NORETURN ReportDoubleFree(uptr addr, StackTrace *free_stack);
void NORETURN ReportFreeNotMalloced(uptr addr, StackTrace *free_stack);
void NORETURN ReportAllocTypeMismatch(uptr addr, StackTrace *free_stack,
@@ -43,6 +46,14 @@ void NORETURN ReportAsanGetAllocatedSizeNotOwned(uptr addr,
void NORETURN ReportStringFunctionMemoryRangesOverlap(
const char *function, const char *offset1, uptr length1,
const char *offset2, uptr length2, StackTrace *stack);
+void NORETURN
+ReportStringFunctionSizeOverflow(uptr offset, uptr size, StackTrace *stack);
+void NORETURN
+ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, uptr old_mid,
+ uptr new_mid, StackTrace *stack);
+
+void NORETURN
+ReportODRViolation(const __asan_global *g1, const __asan_global *g2);
// Mac-specific errors and warnings.
void WarnMacFreeUnallocated(
diff --git a/libsanitizer/asan/asan_rtl.cc b/libsanitizer/asan/asan_rtl.cc
index 537d40612aa..00b4b95868e 100644
--- a/libsanitizer/asan/asan_rtl.cc
+++ b/libsanitizer/asan/asan_rtl.cc
@@ -9,6 +9,7 @@
//
// Main file of the ASan run-time library.
//===----------------------------------------------------------------------===//
+#include "asan_activation.h"
#include "asan_allocator.h"
#include "asan_interceptors.h"
#include "asan_interface_internal.h"
@@ -26,6 +27,7 @@
#include "lsan/lsan_common.h"
int __asan_option_detect_stack_use_after_return; // Global interface symbol.
+uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan.
namespace __asan {
@@ -49,7 +51,7 @@ static void AsanDie() {
UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
}
}
- if (flags()->coverage)
+ if (common_flags()->coverage)
__sanitizer_cov_dump();
if (death_callback)
death_callback();
@@ -60,8 +62,8 @@ static void AsanDie() {
static void AsanCheckFailed(const char *file, int line, const char *cond,
u64 v1, u64 v2) {
- Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n",
- file, line, cond, (uptr)v1, (uptr)v2);
+ Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n", file,
+ line, cond, (uptr)v1, (uptr)v2);
// FIXME: check for infinite recursion without a thread-local counter here.
PRINT_CURRENT_STACK();
Die();
@@ -76,7 +78,7 @@ static const char *MaybeCallAsanDefaultOptions() {
return (&__asan_default_options) ? __asan_default_options() : "";
}
-static const char *MaybeUseAsanDefaultOptionsCompileDefiniton() {
+static const char *MaybeUseAsanDefaultOptionsCompileDefinition() {
#ifdef ASAN_DEFAULT_OPTIONS
// Stringize the macro value.
# define ASAN_STRINGIZE(x) #x
@@ -91,56 +93,154 @@ static void ParseFlagsFromString(Flags *f, const char *str) {
CommonFlags *cf = common_flags();
ParseCommonFlagsFromString(cf, str);
CHECK((uptr)cf->malloc_context_size <= kStackTraceMax);
-
- ParseFlag(str, &f->quarantine_size, "quarantine_size");
- ParseFlag(str, &f->redzone, "redzone");
+ // Please write meaningful flag descriptions when adding new flags.
+ ParseFlag(str, &f->quarantine_size, "quarantine_size",
+ "Size (in bytes) of quarantine used to detect use-after-free "
+ "errors. Lower value may reduce memory usage but increase the "
+ "chance of false negatives.");
+ ParseFlag(str, &f->redzone, "redzone",
+ "Minimal size (in bytes) of redzones around heap objects. "
+ "Requirement: redzone >= 16, is a power of two.");
+ ParseFlag(str, &f->max_redzone, "max_redzone",
+ "Maximal size (in bytes) of redzones around heap objects.");
CHECK_GE(f->redzone, 16);
+ CHECK_GE(f->max_redzone, f->redzone);
+ CHECK_LE(f->max_redzone, 2048);
CHECK(IsPowerOfTwo(f->redzone));
-
- ParseFlag(str, &f->debug, "debug");
- ParseFlag(str, &f->report_globals, "report_globals");
- ParseFlag(str, &f->check_initialization_order, "check_initialization_order");
-
- ParseFlag(str, &f->replace_str, "replace_str");
- ParseFlag(str, &f->replace_intrin, "replace_intrin");
- ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free");
+ CHECK(IsPowerOfTwo(f->max_redzone));
+
+ ParseFlag(str, &f->debug, "debug",
+ "If set, prints some debugging information and does additional checks.");
+ ParseFlag(str, &f->report_globals, "report_globals",
+ "Controls the way to handle globals (0 - don't detect buffer overflow on "
+ "globals, 1 - detect buffer overflow, 2 - print data about registered "
+ "globals).");
+
+ ParseFlag(str, &f->check_initialization_order,
+ "check_initialization_order",
+ "If set, attempts to catch initialization order issues.");
+
+ ParseFlag(str, &f->replace_str, "replace_str",
+ "If set, uses custom wrappers and replacements for libc string functions "
+ "to find more errors.");
+
+ ParseFlag(str, &f->replace_intrin, "replace_intrin",
+ "If set, uses custom wrappers for memset/memcpy/memmove intinsics.");
+ ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free",
+ "Ignore invalid free() calls to work around some bugs. Used on OS X "
+ "only.");
ParseFlag(str, &f->detect_stack_use_after_return,
- "detect_stack_use_after_return");
- ParseFlag(str, &f->uar_stack_size_log, "uar_stack_size_log");
- ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size");
- ParseFlag(str, &f->malloc_fill_byte, "malloc_fill_byte");
- ParseFlag(str, &f->exitcode, "exitcode");
- ParseFlag(str, &f->allow_user_poisoning, "allow_user_poisoning");
- ParseFlag(str, &f->sleep_before_dying, "sleep_before_dying");
- ParseFlag(str, &f->handle_segv, "handle_segv");
- ParseFlag(str, &f->allow_user_segv_handler, "allow_user_segv_handler");
- ParseFlag(str, &f->use_sigaltstack, "use_sigaltstack");
- ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size");
- ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit");
- ParseFlag(str, &f->abort_on_error, "abort_on_error");
- ParseFlag(str, &f->print_stats, "print_stats");
- ParseFlag(str, &f->print_legend, "print_legend");
- ParseFlag(str, &f->atexit, "atexit");
- ParseFlag(str, &f->coverage, "coverage");
- ParseFlag(str, &f->disable_core, "disable_core");
- ParseFlag(str, &f->allow_reexec, "allow_reexec");
- ParseFlag(str, &f->print_full_thread_history, "print_full_thread_history");
- ParseFlag(str, &f->poison_heap, "poison_heap");
- ParseFlag(str, &f->poison_partial, "poison_partial");
- ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch");
- ParseFlag(str, &f->strict_memcmp, "strict_memcmp");
- ParseFlag(str, &f->strict_init_order, "strict_init_order");
+ "detect_stack_use_after_return",
+ "Enables stack-use-after-return checking at run-time.");
+ ParseFlag(str, &f->min_uar_stack_size_log, "min_uar_stack_size_log",
+ "Minimum fake stack size log.");
+ ParseFlag(str, &f->max_uar_stack_size_log, "max_uar_stack_size_log",
+ "Maximum fake stack size log.");
+ ParseFlag(str, &f->uar_noreserve, "uar_noreserve",
+ "Use mmap with 'norserve' flag to allocate fake stack.");
+ ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size",
+ "ASan allocator flag. max_malloc_fill_size is the maximal amount of "
+ "bytes that will be filled with malloc_fill_byte on malloc.");
+ ParseFlag(str, &f->malloc_fill_byte, "malloc_fill_byte",
+ "Value used to fill the newly allocated memory.");
+ ParseFlag(str, &f->exitcode, "exitcode",
+ "Override the program exit status if the tool found an error.");
+ ParseFlag(str, &f->allow_user_poisoning, "allow_user_poisoning",
+ "If set, user may manually mark memory regions as poisoned or "
+ "unpoisoned.");
+ ParseFlag(str, &f->sleep_before_dying, "sleep_before_dying",
+ "Number of seconds to sleep between printing an error report and "
+ "terminating the program. Useful for debugging purposes (e.g. when one "
+ "needs to attach gdb).");
+
+ ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size",
+ "Allows the users to work around the bug in Nvidia drivers prior to "
+ "295.*.");
+
+ ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit",
+ "If set, explicitly unmaps the (huge) shadow at exit.");
+ ParseFlag(str, &f->abort_on_error, "abort_on_error",
+ "If set, the tool calls abort() instead of _exit() after printing the "
+ "error report.");
+ ParseFlag(str, &f->print_stats, "print_stats",
+ "Print various statistics after printing an error message or if "
+ "atexit=1.");
+ ParseFlag(str, &f->print_legend, "print_legend",
+ "Print the legend for the shadow bytes.");
+ ParseFlag(str, &f->atexit, "atexit",
+ "If set, prints ASan exit stats even after program terminates "
+ "successfully.");
+
+ ParseFlag(str, &f->disable_core, "disable_core",
+ "Disable core dumping. By default, disable_core=1 on 64-bit to avoid "
+ "dumping a 16T+ core file. "
+ "Ignored on OSes that don't dump core by default.");
+
+ ParseFlag(str, &f->allow_reexec, "allow_reexec",
+ "Allow the tool to re-exec the program. This may interfere badly with "
+ "the debugger.");
+
+ ParseFlag(str, &f->print_full_thread_history,
+ "print_full_thread_history",
+ "If set, prints thread creation stacks for the threads involved in the "
+ "report and their ancestors up to the main thread.");
+
+ ParseFlag(str, &f->poison_heap, "poison_heap",
+ "Poison (or not) the heap memory on [de]allocation. Zero value is useful "
+ "for benchmarking the allocator or instrumentator.");
+
+ ParseFlag(str, &f->poison_partial, "poison_partial",
+ "If true, poison partially addressable 8-byte aligned words "
+ "(default=true). This flag affects heap and global buffers, but not "
+ "stack buffers.");
+
+ ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch",
+ "Report errors on malloc/delete, new/free, new/delete[], etc.");
+ ParseFlag(str, &f->strict_memcmp, "strict_memcmp",
+ "If true, assume that memcmp(p1, p2, n) always reads n bytes before "
+ "comparing p1 and p2.");
+
+ ParseFlag(str, &f->strict_init_order, "strict_init_order",
+ "If true, assume that dynamic initializers can never access globals from "
+ "other modules, even if the latter are already initialized.");
+
+ ParseFlag(str, &f->start_deactivated, "start_deactivated",
+ "If true, ASan tweaks a bunch of other flags (quarantine, redzone, heap "
+ "poisoning) to reduce memory consumption as much as possible, and "
+ "restores them to original values when the first instrumented module is "
+ "loaded into the process. This is mainly intended to be used on "
+ "Android. ");
+
+ ParseFlag(str, &f->detect_invalid_pointer_pairs,
+ "detect_invalid_pointer_pairs",
+ "If non-zero, try to detect operations like <, <=, >, >= and - on "
+ "invalid pointer pairs (e.g. when pointers belong to different objects). "
+ "The bigger the value the harder we try.");
+
+ ParseFlag(str, &f->detect_container_overflow,
+ "detect_container_overflow",
+ "If true, honor the container overflow annotations. "
+ "See https://code.google.com/p/address-sanitizer/wiki/ContainerOverflow");
+
+ ParseFlag(str, &f->detect_odr_violation, "detect_odr_violation",
+ "If >=2, detect violation of One-Definition-Rule (ODR); "
+ "If ==1, detect ODR-violation only if the two variables "
+ "have different sizes");
}
void InitializeFlags(Flags *f, const char *env) {
CommonFlags *cf = common_flags();
SetCommonFlagsDefaults(cf);
+ cf->detect_leaks = CAN_SANITIZE_LEAKS;
cf->external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH");
cf->malloc_context_size = kDefaultMallocContextSize;
+ cf->intercept_tls_get_addr = true;
+ cf->coverage = false;
internal_memset(f, 0, sizeof(*f));
f->quarantine_size = (ASAN_LOW_MEMORY) ? 1UL << 26 : 1UL << 28;
f->redzone = 16;
+ f->max_redzone = 2048;
f->debug = false;
f->report_globals = 1;
f->check_initialization_order = false;
@@ -148,53 +248,55 @@ void InitializeFlags(Flags *f, const char *env) {
f->replace_intrin = true;
f->mac_ignore_invalid_free = false;
f->detect_stack_use_after_return = false; // Also needs the compiler flag.
- f->uar_stack_size_log = 0;
+ f->min_uar_stack_size_log = 16; // We can't do smaller anyway.
+ f->max_uar_stack_size_log = 20; // 1Mb per size class, i.e. ~11Mb per thread.
+ f->uar_noreserve = false;
f->max_malloc_fill_size = 0x1000; // By default, fill only the first 4K.
f->malloc_fill_byte = 0xbe;
f->exitcode = ASAN_DEFAULT_FAILURE_EXITCODE;
f->allow_user_poisoning = true;
f->sleep_before_dying = 0;
- f->handle_segv = ASAN_NEEDS_SEGV;
- f->allow_user_segv_handler = false;
- f->use_sigaltstack = false;
f->check_malloc_usable_size = true;
f->unmap_shadow_on_exit = false;
f->abort_on_error = false;
f->print_stats = false;
f->print_legend = true;
f->atexit = false;
- f->coverage = false;
f->disable_core = (SANITIZER_WORDSIZE == 64);
f->allow_reexec = true;
f->print_full_thread_history = true;
f->poison_heap = true;
f->poison_partial = true;
// Turn off alloc/dealloc mismatch checker on Mac and Windows for now.
+ // https://code.google.com/p/address-sanitizer/issues/detail?id=131
+ // https://code.google.com/p/address-sanitizer/issues/detail?id=309
// TODO(glider,timurrrr): Fix known issues and enable this back.
f->alloc_dealloc_mismatch = (SANITIZER_MAC == 0) && (SANITIZER_WINDOWS == 0);
f->strict_memcmp = true;
f->strict_init_order = false;
+ f->start_deactivated = false;
+ f->detect_invalid_pointer_pairs = 0;
+ f->detect_container_overflow = true;
// Override from compile definition.
- ParseFlagsFromString(f, MaybeUseAsanDefaultOptionsCompileDefiniton());
+ ParseFlagsFromString(f, MaybeUseAsanDefaultOptionsCompileDefinition());
// Override from user-specified string.
ParseFlagsFromString(f, MaybeCallAsanDefaultOptions());
- if (cf->verbosity) {
- Report("Using the defaults from __asan_default_options: %s\n",
- MaybeCallAsanDefaultOptions());
- }
+ VReport(1, "Using the defaults from __asan_default_options: %s\n",
+ MaybeCallAsanDefaultOptions());
// Override from command line.
ParseFlagsFromString(f, env);
+ if (common_flags()->help) {
+ PrintFlagDescriptions();
+ }
-#if !CAN_SANITIZE_LEAKS
- if (cf->detect_leaks) {
+ if (!CAN_SANITIZE_LEAKS && cf->detect_leaks) {
Report("%s: detect_leaks is not supported on this platform.\n",
SanitizerToolName);
cf->detect_leaks = false;
}
-#endif
// Make "strict_init_order" imply "check_initialization_order".
// TODO(samsonov): Use a single runtime flag for an init-order checker.
@@ -203,6 +305,17 @@ void InitializeFlags(Flags *f, const char *env) {
}
}
+// Parse flags that may change between startup and activation.
+// On Android they come from a system property.
+// On other platforms this is no-op.
+void ParseExtraActivationFlags() {
+ char buf[100];
+ GetExtraActivationFlags(buf, sizeof(buf));
+ ParseFlagsFromString(flags(), buf);
+ if (buf[0] != '\0')
+ VReport(1, "Extra activation flags: %s\n", buf);
+}
+
// -------------------------- Globals --------------------- {{{1
int asan_inited;
bool asan_init_is_running;
@@ -224,6 +337,7 @@ static void ReserveShadowMemoryRange(uptr beg, uptr end) {
CHECK_EQ((beg % GetPageSizeCached()), 0);
CHECK_EQ(((end + 1) % GetPageSizeCached()), 0);
uptr size = end - beg + 1;
+ DecreaseTotalMmap(size); // Don't count the shadow against mmap_limit_mb.
void *res = MmapFixedNoReserve(beg, size);
if (res != (void*)beg) {
Report("ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
@@ -269,6 +383,53 @@ void __asan_report_ ## type ## _n(uptr addr, uptr size) { \
ASAN_REPORT_ERROR_N(load, false)
ASAN_REPORT_ERROR_N(store, true)
+#define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size) \
+ extern "C" NOINLINE INTERFACE_ATTRIBUTE void __asan_##type##size(uptr addr); \
+ void __asan_##type##size(uptr addr) { \
+ uptr sp = MEM_TO_SHADOW(addr); \
+ uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \
+ : *reinterpret_cast<u16 *>(sp); \
+ if (UNLIKELY(s)) { \
+ if (UNLIKELY(size >= SHADOW_GRANULARITY || \
+ ((s8)((addr & (SHADOW_GRANULARITY - 1)) + size - 1)) >= \
+ (s8)s)) { \
+ if (__asan_test_only_reported_buggy_pointer) { \
+ *__asan_test_only_reported_buggy_pointer = addr; \
+ } else { \
+ GET_CALLER_PC_BP_SP; \
+ __asan_report_error(pc, bp, sp, addr, is_write, size); \
+ } \
+ } \
+ } \
+ }
+
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1)
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 2)
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 4)
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 8)
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 16)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 1)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 2)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 4)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 8)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16)
+
+extern "C"
+NOINLINE INTERFACE_ATTRIBUTE void __asan_loadN(uptr addr, uptr size) {
+ if (__asan_region_is_poisoned(addr, size)) {
+ GET_CALLER_PC_BP_SP;
+ __asan_report_error(pc, bp, sp, addr, false, size);
+ }
+}
+
+extern "C"
+NOINLINE INTERFACE_ATTRIBUTE void __asan_storeN(uptr addr, uptr size) {
+ if (__asan_region_is_poisoned(addr, size)) {
+ GET_CALLER_PC_BP_SP;
+ __asan_report_error(pc, bp, sp, addr, true, size);
+ }
+}
+
// Force the linker to keep the symbols for various ASan interface functions.
// We want to keep those in the executable in order to let the instrumented
// dynamic libraries access the symbol even if it is not used by the executable
@@ -372,7 +533,8 @@ static void PrintAddressSpaceLayout() {
(void*)MEM_TO_SHADOW(kMidShadowEnd));
}
Printf("\n");
- Printf("red_zone=%zu\n", (uptr)flags()->redzone);
+ Printf("redzone=%zu\n", (uptr)flags()->redzone);
+ Printf("max_redzone=%zu\n", (uptr)flags()->max_redzone);
Printf("quarantine_size=%zuM\n", (uptr)flags()->quarantine_size >> 20);
Printf("malloc_context_size=%zu\n",
(uptr)common_flags()->malloc_context_size);
@@ -387,59 +549,17 @@ static void PrintAddressSpaceLayout() {
kHighShadowBeg > kMidMemEnd);
}
-} // namespace __asan
-
-// ---------------------- Interface ---------------- {{{1
-using namespace __asan; // NOLINT
-
-#if !SANITIZER_SUPPORTS_WEAK_HOOKS
-extern "C" {
-SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
-const char* __asan_default_options() { return ""; }
-} // extern "C"
-#endif
-
-int NOINLINE __asan_set_error_exit_code(int exit_code) {
- int old = flags()->exitcode;
- flags()->exitcode = exit_code;
- return old;
-}
-
-void NOINLINE __asan_handle_no_return() {
- int local_stack;
- AsanThread *curr_thread = GetCurrentThread();
- CHECK(curr_thread);
- uptr PageSize = GetPageSizeCached();
- uptr top = curr_thread->stack_top();
- uptr bottom = ((uptr)&local_stack - PageSize) & ~(PageSize-1);
- static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M
- if (top - bottom > kMaxExpectedCleanupSize) {
- static bool reported_warning = false;
- if (reported_warning)
- return;
- reported_warning = true;
- Report("WARNING: ASan is ignoring requested __asan_handle_no_return: "
- "stack top: %p; bottom %p; size: %p (%zd)\n"
- "False positive error reports may follow\n"
- "For details see "
- "http://code.google.com/p/address-sanitizer/issues/detail?id=189\n",
- top, bottom, top - bottom, top - bottom);
- return;
- }
- PoisonShadow(bottom, top - bottom, 0);
- if (curr_thread->has_fake_stack())
- curr_thread->fake_stack()->HandleNoReturn();
-}
-
-void NOINLINE __asan_set_death_callback(void (*callback)(void)) {
- death_callback = callback;
-}
-
-void __asan_init() {
- if (asan_inited) return;
+static void AsanInitInternal() {
+ if (LIKELY(asan_inited)) return;
SanitizerToolName = "AddressSanitizer";
CHECK(!asan_init_is_running && "ASan init calls itself!");
asan_init_is_running = true;
+
+ // Initialize flags. This must be done early, because most of the
+ // initialization steps look at flags().
+ const char *options = GetEnv("ASAN_OPTIONS");
+ InitializeFlags(flags(), options);
+
InitializeHighMemEnd();
// Make sure we are not statically linked.
@@ -450,18 +570,21 @@ void __asan_init() {
SetCheckFailedCallback(AsanCheckFailed);
SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
- // Initialize flags. This must be done early, because most of the
- // initialization steps look at flags().
- const char *options = GetEnv("ASAN_OPTIONS");
- InitializeFlags(flags(), options);
+ if (!flags()->start_deactivated)
+ ParseExtraActivationFlags();
+
__sanitizer_set_report_path(common_flags()->log_path);
__asan_option_detect_stack_use_after_return =
flags()->detect_stack_use_after_return;
+ CHECK_LE(flags()->min_uar_stack_size_log, flags()->max_uar_stack_size_log);
- if (common_flags()->verbosity && options) {
- Report("Parsed ASAN_OPTIONS: %s\n", options);
+ if (options) {
+ VReport(1, "Parsed ASAN_OPTIONS: %s\n", options);
}
+ if (flags()->start_deactivated)
+ AsanStartDeactivated();
+
// Re-exec ourselves if we need to set additional env or command line args.
MaybeReexec();
@@ -471,7 +594,6 @@ void __asan_init() {
InitializeAsanInterceptors();
ReplaceSystemMalloc();
- ReplaceOperatorsNewAndDelete();
uptr shadow_start = kLowShadowBeg;
if (kLowShadowBeg)
@@ -501,6 +623,7 @@ void __asan_init() {
ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
// protect the gap.
ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
+ CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1);
} else if (kMidMemBeg &&
MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {
@@ -523,18 +646,13 @@ void __asan_init() {
}
AsanTSDInit(PlatformTSDDtor);
- InstallSignalHandlers();
+ InstallDeadlySignalHandlers(AsanOnSIGSEGV);
// Allocator should be initialized before starting external symbolizer, as
// fork() on Mac locks the allocator.
InitializeAllocator();
- // Start symbolizer process if necessary.
- if (common_flags()->symbolize) {
- Symbolizer::Init(common_flags()->external_symbolizer_path);
- } else {
- Symbolizer::Disable();
- }
+ Symbolizer::Init(common_flags()->external_symbolizer_path);
// On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
// should be set to 1 prior to initializing the threads.
@@ -544,8 +662,10 @@ void __asan_init() {
if (flags()->atexit)
Atexit(asan_atexit);
- if (flags()->coverage)
+ if (common_flags()->coverage) {
+ __sanitizer_cov_init();
Atexit(__sanitizer_cov_dump);
+ }
// interceptors
InitTlsSize();
@@ -559,6 +679,7 @@ void __asan_init() {
SetCurrentThread(main_thread);
main_thread->ThreadStart(internal_getpid());
force_interface_symbols(); // no-op.
+ SanitizerInitializeUnwinder();
#if CAN_SANITIZE_LEAKS
__lsan::InitCommonLsan();
@@ -567,7 +688,84 @@ void __asan_init() {
}
#endif // CAN_SANITIZE_LEAKS
- if (common_flags()->verbosity) {
- Report("AddressSanitizer Init done\n");
+ VReport(1, "AddressSanitizer Init done\n");
+}
+
+// Initialize as requested from some part of ASan runtime library (interceptors,
+// allocator, etc).
+void AsanInitFromRtl() {
+ AsanInitInternal();
+}
+
+#if ASAN_DYNAMIC
+// Initialize runtime in case it's LD_PRELOAD-ed into unsanitized executable
+// (and thus normal initializer from .preinit_array haven't run).
+
+class AsanInitializer {
+public: // NOLINT
+ AsanInitializer() {
+ AsanCheckIncompatibleRT();
+ AsanCheckDynamicRTPrereqs();
+ if (UNLIKELY(!asan_inited))
+ __asan_init();
}
+};
+
+static AsanInitializer asan_initializer;
+#endif // ASAN_DYNAMIC
+
+} // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan; // NOLINT
+
+#if !SANITIZER_SUPPORTS_WEAK_HOOKS
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+const char* __asan_default_options() { return ""; }
+} // extern "C"
+#endif
+
+int NOINLINE __asan_set_error_exit_code(int exit_code) {
+ int old = flags()->exitcode;
+ flags()->exitcode = exit_code;
+ return old;
+}
+
+void NOINLINE __asan_handle_no_return() {
+ int local_stack;
+ AsanThread *curr_thread = GetCurrentThread();
+ CHECK(curr_thread);
+ uptr PageSize = GetPageSizeCached();
+ uptr top = curr_thread->stack_top();
+ uptr bottom = ((uptr)&local_stack - PageSize) & ~(PageSize-1);
+ static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M
+ if (top - bottom > kMaxExpectedCleanupSize) {
+ static bool reported_warning = false;
+ if (reported_warning)
+ return;
+ reported_warning = true;
+ Report("WARNING: ASan is ignoring requested __asan_handle_no_return: "
+ "stack top: %p; bottom %p; size: %p (%zd)\n"
+ "False positive error reports may follow\n"
+ "For details see "
+ "http://code.google.com/p/address-sanitizer/issues/detail?id=189\n",
+ top, bottom, top - bottom, top - bottom);
+ return;
+ }
+ PoisonShadow(bottom, top - bottom, 0);
+ if (curr_thread->has_fake_stack())
+ curr_thread->fake_stack()->HandleNoReturn();
+}
+
+void NOINLINE __asan_set_death_callback(void (*callback)(void)) {
+ death_callback = callback;
+}
+
+// Initialize as requested from instrumented application code.
+// We use this call as a trigger to wake up ASan from deactivated state.
+void __asan_init() {
+ AsanCheckIncompatibleRT();
+ AsanActivate();
+ AsanInitInternal();
}
diff --git a/libsanitizer/asan/asan_stack.cc b/libsanitizer/asan/asan_stack.cc
index 24cccbd196e..96178e8247b 100644
--- a/libsanitizer/asan/asan_stack.cc
+++ b/libsanitizer/asan/asan_stack.cc
@@ -10,40 +10,10 @@
// Code for ASan stack trace.
//===----------------------------------------------------------------------===//
#include "asan_internal.h"
-#include "asan_flags.h"
#include "asan_stack.h"
-#include "sanitizer_common/sanitizer_flags.h"
-
-namespace __asan {
-
-static bool MaybeCallAsanSymbolize(const void *pc, char *out_buffer,
- int out_size) {
- return (&__asan_symbolize) ? __asan_symbolize(pc, out_buffer, out_size)
- : false;
-}
-
-void PrintStack(const uptr *trace, uptr size) {
- StackTrace::PrintStack(trace, size, MaybeCallAsanSymbolize);
-}
-
-void PrintStack(StackTrace *stack) {
- PrintStack(stack->trace, stack->size);
-}
-
-} // namespace __asan
// ------------------ Interface -------------- {{{1
-// Provide default implementation of __asan_symbolize that does nothing
-// and may be overriden by user if he wants to use his own symbolization.
-// ASan on Windows has its own implementation of this.
-#if !SANITIZER_WINDOWS && !SANITIZER_SUPPORTS_WEAK_HOOKS
-SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE
-bool __asan_symbolize(const void *pc, char *out_buffer, int out_size) {
- return false;
-}
-#endif
-
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
void __sanitizer_print_stack_trace() {
diff --git a/libsanitizer/asan/asan_stack.h b/libsanitizer/asan/asan_stack.h
index df7a9805f92..d31c0afa83b 100644
--- a/libsanitizer/asan/asan_stack.h
+++ b/libsanitizer/asan/asan_stack.h
@@ -19,49 +19,62 @@
namespace __asan {
-void PrintStack(StackTrace *stack);
-void PrintStack(const uptr *trace, uptr size);
-
-} // namespace __asan
-
// Get the stack trace with the given pc and bp.
// The pc will be in the position 0 of the resulting stack trace.
// The bp may refer to the current frame or to the caller's frame.
+ALWAYS_INLINE
+void GetStackTraceWithPcBpAndContext(StackTrace *stack, uptr max_depth, uptr pc,
+ uptr bp, void *context, bool fast) {
#if SANITIZER_WINDOWS
-#define GET_STACK_TRACE_WITH_PC_AND_BP(max_s, pc, bp, fast) \
- StackTrace stack; \
- stack.Unwind(max_s, pc, bp, 0, 0, fast)
+ stack->Unwind(max_depth, pc, bp, context, 0, 0, fast);
#else
-#define GET_STACK_TRACE_WITH_PC_AND_BP(max_s, pc, bp, fast) \
- StackTrace stack; \
- { \
- AsanThread *t; \
- stack.size = 0; \
- if (asan_inited) { \
- if ((t = GetCurrentThread()) && !t->isUnwinding()) { \
- uptr stack_top = t->stack_top(); \
- uptr stack_bottom = t->stack_bottom(); \
- ScopedUnwinding unwind_scope(t); \
- stack.Unwind(max_s, pc, bp, stack_top, stack_bottom, fast); \
- } else if (t == 0 && !fast) { \
- /* If GetCurrentThread() has failed, try to do slow unwind anyways. */ \
- stack.Unwind(max_s, pc, bp, 0, 0, false); \
- } \
- } \
+ AsanThread *t;
+ stack->size = 0;
+ if (LIKELY(asan_inited)) {
+ if ((t = GetCurrentThread()) && !t->isUnwinding()) {
+ uptr stack_top = t->stack_top();
+ uptr stack_bottom = t->stack_bottom();
+ ScopedUnwinding unwind_scope(t);
+ stack->Unwind(max_depth, pc, bp, context, stack_top, stack_bottom, fast);
+ } else if (t == 0 && !fast) {
+ /* If GetCurrentThread() has failed, try to do slow unwind anyways. */
+ stack->Unwind(max_depth, pc, bp, context, 0, 0, false);
+ }
}
#endif // SANITIZER_WINDOWS
+}
+
+} // namespace __asan
// NOTE: A Rule of thumb is to retrieve stack trace in the interceptors
// as early as possible (in functions exposed to the user), as we generally
// don't want stack trace to contain functions from ASan internals.
-#define GET_STACK_TRACE(max_size, fast) \
- GET_STACK_TRACE_WITH_PC_AND_BP(max_size, \
- StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), fast)
+#define GET_STACK_TRACE(max_size, fast) \
+ StackTrace stack; \
+ if (max_size <= 2) { \
+ stack.size = max_size; \
+ if (max_size > 0) { \
+ stack.top_frame_bp = GET_CURRENT_FRAME(); \
+ stack.trace[0] = StackTrace::GetCurrentPc(); \
+ if (max_size > 1) \
+ stack.trace[1] = GET_CALLER_PC(); \
+ } \
+ } else { \
+ GetStackTraceWithPcBpAndContext(&stack, max_size, \
+ StackTrace::GetCurrentPc(), \
+ GET_CURRENT_FRAME(), 0, fast); \
+ }
-#define GET_STACK_TRACE_FATAL(pc, bp) \
- GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp, \
- common_flags()->fast_unwind_on_fatal)
+#define GET_STACK_TRACE_FATAL(pc, bp) \
+ StackTrace stack; \
+ GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, 0, \
+ common_flags()->fast_unwind_on_fatal)
+
+#define GET_STACK_TRACE_SIGNAL(pc, bp, context) \
+ StackTrace stack; \
+ GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context, \
+ common_flags()->fast_unwind_on_fatal)
#define GET_STACK_TRACE_FATAL_HERE \
GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal)
@@ -78,7 +91,7 @@ void PrintStack(const uptr *trace, uptr size);
#define PRINT_CURRENT_STACK() \
{ \
GET_STACK_TRACE_FATAL_HERE; \
- PrintStack(&stack); \
+ stack.Print(); \
}
#endif // ASAN_STACK_H
diff --git a/libsanitizer/asan/asan_thread.cc b/libsanitizer/asan/asan_thread.cc
index 5a9c2dddffb..df85858a67b 100644
--- a/libsanitizer/asan/asan_thread.cc
+++ b/libsanitizer/asan/asan_thread.cc
@@ -18,6 +18,7 @@
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
#include "lsan/lsan_common.h"
namespace __asan {
@@ -76,7 +77,7 @@ AsanThread *AsanThread::Create(thread_callback_t start_routine,
void *arg) {
uptr PageSize = GetPageSizeCached();
uptr size = RoundUpTo(sizeof(AsanThread), PageSize);
- AsanThread *thread = (AsanThread*)MmapOrDie(size, __FUNCTION__);
+ AsanThread *thread = (AsanThread*)MmapOrDie(size, __func__);
thread->start_routine_ = start_routine;
thread->arg_ = arg;
@@ -85,28 +86,27 @@ AsanThread *AsanThread::Create(thread_callback_t start_routine,
void AsanThread::TSDDtor(void *tsd) {
AsanThreadContext *context = (AsanThreadContext*)tsd;
- if (common_flags()->verbosity >= 1)
- Report("T%d TSDDtor\n", context->tid);
+ VReport(1, "T%d TSDDtor\n", context->tid);
if (context->thread)
context->thread->Destroy();
}
void AsanThread::Destroy() {
- if (common_flags()->verbosity >= 1) {
- Report("T%d exited\n", tid());
- }
+ int tid = this->tid();
+ VReport(1, "T%d exited\n", tid);
malloc_storage().CommitBack();
- if (flags()->use_sigaltstack) UnsetAlternateSignalStack();
- asanThreadRegistry().FinishThread(tid());
+ if (common_flags()->use_sigaltstack) UnsetAlternateSignalStack();
+ asanThreadRegistry().FinishThread(tid);
FlushToDeadThreadStats(&stats_);
// We also clear the shadow on thread destruction because
// some code may still be executing in later TSD destructors
// and we don't want it to have any poisoned stack.
ClearShadowForThreadStackAndTLS();
- DeleteFakeStack();
+ DeleteFakeStack(tid);
uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached());
UnmapOrDie(this, size);
+ DTLS_Destroy();
}
// We want to create the FakeStack lazyly on the first use, but not eralier
@@ -121,13 +121,16 @@ FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() {
// 1 -- being initialized
// ptr -- initialized
// This CAS checks if the state was 0 and if so changes it to state 1,
- // if that was successfull, it initilizes the pointer.
+ // if that was successful, it initializes the pointer.
if (atomic_compare_exchange_strong(
reinterpret_cast<atomic_uintptr_t *>(&fake_stack_), &old_val, 1UL,
memory_order_relaxed)) {
uptr stack_size_log = Log2(RoundUpToPowerOfTwo(stack_size));
- if (flags()->uar_stack_size_log)
- stack_size_log = static_cast<uptr>(flags()->uar_stack_size_log);
+ CHECK_LE(flags()->min_uar_stack_size_log, flags()->max_uar_stack_size_log);
+ stack_size_log =
+ Min(stack_size_log, static_cast<uptr>(flags()->max_uar_stack_size_log));
+ stack_size_log =
+ Max(stack_size_log, static_cast<uptr>(flags()->min_uar_stack_size_log));
fake_stack_ = FakeStack::Create(stack_size_log);
SetTLSFakeStack(fake_stack_);
return fake_stack_;
@@ -140,12 +143,10 @@ void AsanThread::Init() {
CHECK(AddrIsInMem(stack_bottom_));
CHECK(AddrIsInMem(stack_top_ - 1));
ClearShadowForThreadStackAndTLS();
- if (common_flags()->verbosity >= 1) {
- int local = 0;
- Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n",
- tid(), (void*)stack_bottom_, (void*)stack_top_,
- stack_top_ - stack_bottom_, &local);
- }
+ int local = 0;
+ VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(),
+ (void *)stack_bottom_, (void *)stack_top_, stack_top_ - stack_bottom_,
+ &local);
fake_stack_ = 0; // Will be initialized lazily if needed.
AsanPlatformThreadInit();
}
@@ -153,7 +154,7 @@ void AsanThread::Init() {
thread_return_t AsanThread::ThreadStart(uptr os_id) {
Init();
asanThreadRegistry().StartThread(tid(), os_id, 0);
- if (flags()->use_sigaltstack) SetAlternateSignalStack();
+ if (common_flags()->use_sigaltstack) SetAlternateSignalStack();
if (!start_routine_) {
// start_routine_ == 0 if we're on the main thread or on one of the
@@ -265,10 +266,8 @@ AsanThread *GetCurrentThread() {
void SetCurrentThread(AsanThread *t) {
CHECK(t->context());
- if (common_flags()->verbosity >= 2) {
- Report("SetCurrentThread: %p for thread %p\n",
- t->context(), (void*)GetThreadSelf());
- }
+ VReport(2, "SetCurrentThread: %p for thread %p\n", t->context(),
+ (void *)GetThreadSelf());
// Make sure we do not reset the current AsanThread.
CHECK_EQ(0, AsanTSDGet());
AsanTSDSet(t->context());
diff --git a/libsanitizer/asan/asan_thread.h b/libsanitizer/asan/asan_thread.h
index 5a917fa9a3d..33242efabaa 100644
--- a/libsanitizer/asan/asan_thread.h
+++ b/libsanitizer/asan/asan_thread.h
@@ -15,7 +15,6 @@
#include "asan_allocator.h"
#include "asan_internal.h"
#include "asan_fake_stack.h"
-#include "asan_stack.h"
#include "asan_stats.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
@@ -76,12 +75,12 @@ class AsanThread {
return addr >= stack_bottom_ && addr < stack_top_;
}
- void DeleteFakeStack() {
+ void DeleteFakeStack(int tid) {
if (!fake_stack_) return;
FakeStack *t = fake_stack_;
fake_stack_ = 0;
SetTLSFakeStack(0);
- t->Destroy();
+ t->Destroy(tid);
}
bool has_fake_stack() {
diff --git a/libsanitizer/asan/asan_win.cc b/libsanitizer/asan/asan_win.cc
index 8ffa58faa37..03d45e3839b 100644
--- a/libsanitizer/asan/asan_win.cc
+++ b/libsanitizer/asan/asan_win.cc
@@ -33,11 +33,6 @@ extern "C" {
namespace __asan {
-// ---------------------- Stacktraces, symbols, etc. ---------------- {{{1
-static BlockingMutex dbghelp_lock(LINKER_INITIALIZED);
-static bool dbghelp_initialized = false;
-#pragma comment(lib, "dbghelp.lib")
-
// ---------------------- TSD ---------------- {{{1
static bool tsd_key_inited = false;
@@ -73,17 +68,9 @@ void *AsanDoesNotSupportStaticLinkage() {
return 0;
}
-void SetAlternateSignalStack() {
- // FIXME: Decide what to do on Windows.
-}
+void AsanCheckDynamicRTPrereqs() { UNIMPLEMENTED(); }
-void UnsetAlternateSignalStack() {
- // FIXME: Decide what to do on Windows.
-}
-
-void InstallSignalHandlers() {
- // FIXME: Decide what to do on Windows.
-}
+void AsanCheckIncompatibleRT() {}
void AsanPlatformThreadInit() {
// Nothing here for now.
@@ -93,54 +80,10 @@ void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
UNIMPLEMENTED();
}
-} // namespace __asan
-
-// ---------------------- Interface ---------------- {{{1
-using namespace __asan; // NOLINT
-
-extern "C" {
-SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
-bool __asan_symbolize(const void *addr, char *out_buffer, int buffer_size) {
- BlockingMutexLock lock(&dbghelp_lock);
- if (!dbghelp_initialized) {
- SymSetOptions(SYMOPT_DEFERRED_LOADS |
- SYMOPT_UNDNAME |
- SYMOPT_LOAD_LINES);
- CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE));
- // FIXME: We don't call SymCleanup() on exit yet - should we?
- dbghelp_initialized = true;
- }
-
- // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
- char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)];
- PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
- symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
- symbol->MaxNameLen = MAX_SYM_NAME;
- DWORD64 offset = 0;
- BOOL got_objname = SymFromAddr(GetCurrentProcess(),
- (DWORD64)addr, &offset, symbol);
- if (!got_objname)
- return false;
-
- DWORD unused;
- IMAGEHLP_LINE64 info;
- info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
- BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(),
- (DWORD64)addr, &unused, &info);
- int written = 0;
- out_buffer[0] = '\0';
- // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too.
- if (got_fileline) {
- written += internal_snprintf(out_buffer + written, buffer_size - written,
- " %s %s:%d", symbol->Name,
- info.FileName, info.LineNumber);
- } else {
- written += internal_snprintf(out_buffer + written, buffer_size - written,
- " %s+0x%p", symbol->Name, offset);
- }
- return true;
+void AsanOnSIGSEGV(int, void *siginfo, void *context) {
+ UNIMPLEMENTED();
}
-} // extern "C"
+} // namespace __asan
#endif // _WIN32
diff --git a/libsanitizer/include/sanitizer/asan_interface.h b/libsanitizer/include/sanitizer/asan_interface.h
index 0016339e486..bf4c4789536 100644
--- a/libsanitizer/include/sanitizer/asan_interface.h
+++ b/libsanitizer/include/sanitizer/asan_interface.h
@@ -48,9 +48,10 @@ extern "C" {
((void)(addr), (void)(size))
#endif
- // Returns true iff addr is poisoned (i.e. 1-byte read/write access to this
+ // Returns 1 if addr is poisoned (i.e. 1-byte read/write access to this
// address will result in error report from AddressSanitizer).
- bool __asan_address_is_poisoned(void const volatile *addr);
+ // Otherwise returns 0.
+ int __asan_address_is_poisoned(void const volatile *addr);
// If at least on byte in [beg, beg+size) is poisoned, return the address
// of the first such byte. Otherwise return 0.
@@ -63,7 +64,7 @@ extern "C" {
// However it is still a part of the interface because users may want to
// set a breakpoint on this function in a debugger.
void __asan_report_error(void *pc, void *bp, void *sp,
- void *addr, bool is_write, size_t access_size);
+ void *addr, int is_write, size_t access_size);
// Sets the exit code to use when reporting an error.
// Returns the old value.
@@ -80,22 +81,14 @@ extern "C" {
// the program crashes before ASan report is printed.
void __asan_on_error();
- // User may provide its own implementation for symbolization function.
- // It should print the description of instruction at address "pc" to
- // "out_buffer". Description should be at most "out_size" bytes long.
- // User-specified function should return true if symbolization was
- // successful.
- bool __asan_symbolize(const void *pc, char *out_buffer,
- int out_size);
-
// Returns the estimated number of bytes that will be reserved by allocator
// for request of "size" bytes. If ASan allocator can't allocate that much
// memory, returns the maximal possible allocation size, otherwise returns
// "size".
size_t __asan_get_estimated_allocated_size(size_t size);
- // Returns true if p was returned by the ASan allocator and
- // is not yet freed.
- bool __asan_get_ownership(const void *p);
+ // Returns 1 if p was returned by the ASan allocator and is not yet freed.
+ // Otherwise returns 0.
+ int __asan_get_ownership(const void *p);
// Returns the number of bytes reserved for the pointer p.
// Requires (get_ownership(p) == true) or (p == 0).
size_t __asan_get_allocated_size(const void *p);
@@ -128,6 +121,24 @@ extern "C" {
// deallocation of "ptr".
void __asan_malloc_hook(void *ptr, size_t size);
void __asan_free_hook(void *ptr);
+
+ // The following 2 functions facilitate garbage collection in presence of
+ // asan's fake stack.
+
+ // Returns an opaque handler to be used later in __asan_addr_is_in_fake_stack.
+ // Returns NULL if the current thread does not have a fake stack.
+ void *__asan_get_current_fake_stack();
+
+ // If fake_stack is non-NULL and addr belongs to a fake frame in
+ // fake_stack, returns the address on real stack that corresponds to
+ // the fake frame and sets beg/end to the boundaries of this fake frame.
+ // Otherwise returns NULL and does not touch beg/end.
+ // If beg/end are NULL, they are not touched.
+ // This function may be called from a thread other than the owner of
+ // fake_stack, but the owner thread need to be alive.
+ void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg,
+ void **end);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/libsanitizer/include/sanitizer/common_interface_defs.h b/libsanitizer/include/sanitizer/common_interface_defs.h
index db8b3b543e3..44870a039b4 100644
--- a/libsanitizer/include/sanitizer/common_interface_defs.h
+++ b/libsanitizer/include/sanitizer/common_interface_defs.h
@@ -22,13 +22,28 @@
#ifdef __cplusplus
extern "C" {
#endif
+ // Arguments for __sanitizer_sandbox_on_notify() below.
+ typedef struct {
+ // Enable sandbox support in sanitizer coverage.
+ int coverage_sandboxed;
+ // File descriptor to write coverage data to. If -1 is passed, a file will
+ // be pre-opened by __sanitizer_sandobx_on_notify(). This field has no
+ // effect if coverage_sandboxed == 0.
+ intptr_t coverage_fd;
+ // If non-zero, split the coverage data into well-formed blocks. This is
+ // useful when coverage_fd is a socket descriptor. Each block will contain
+ // a header, allowing data from multiple processes to be sent over the same
+ // socket.
+ unsigned int coverage_max_block_size;
+ } __sanitizer_sandbox_arguments;
+
// Tell the tools to write their reports to "path.<pid>" instead of stderr.
void __sanitizer_set_report_path(const char *path);
// Notify the tools that the sandbox is going to be turned on. The reserved
// parameter will be used in the future to hold a structure with functions
// that the tools may call to bypass the sandbox.
- void __sanitizer_sandbox_on_notify(void *reserved);
+ void __sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args);
// This function is called by the tool when it has just finished reporting
// an error. 'error_summary' is a one-line string that summarizes
@@ -45,6 +60,8 @@ extern "C" {
void __sanitizer_unaligned_store32(void *p, uint32_t x);
void __sanitizer_unaligned_store64(void *p, uint64_t x);
+ // Initialize coverage.
+ void __sanitizer_cov_init();
// Record and dump coverage info.
void __sanitizer_cov_dump();
@@ -54,7 +71,7 @@ extern "C" {
// in a contiguous region of memory. The container owns the region of memory
// [beg, end); the memory [beg, mid) is used to store the current elements
// and the memory [mid, end) is reserved for future elements;
- // end <= mid <= end. For example, in "std::vector<> v"
+ // beg <= mid <= end. For example, in "std::vector<> v"
// beg = &v[0];
// end = beg + v.capacity() * sizeof(v[0]);
// mid = beg + v.size() * sizeof(v[0]);
@@ -82,6 +99,14 @@ extern "C" {
const void *end,
const void *old_mid,
const void *new_mid);
+ // Returns true if the contiguous container [beg, end) ir properly poisoned
+ // (e.g. with __sanitizer_annotate_contiguous_container), i.e. if
+ // - [beg, mid) is addressable,
+ // - [mid, end) is unaddressable.
+ // Full verification requires O(end-beg) time; this function tries to avoid
+ // such complexity by touching only parts of the container around beg/mid/end.
+ int __sanitizer_verify_contiguous_container(const void *beg, const void *mid,
+ const void *end);
// Print the stack trace leading to this call. Useful for debugging user code.
void __sanitizer_print_stack_trace();
diff --git a/libsanitizer/include/sanitizer/dfsan_interface.h b/libsanitizer/include/sanitizer/dfsan_interface.h
index dd938483d18..c1b160205a7 100644
--- a/libsanitizer/include/sanitizer/dfsan_interface.h
+++ b/libsanitizer/include/sanitizer/dfsan_interface.h
@@ -37,6 +37,9 @@ struct dfsan_label_info {
void *userdata;
};
+/// Signature of the callback argument to dfsan_set_write_callback().
+typedef void (*dfsan_write_callback_t)(int fd, const void *buf, size_t count);
+
/// Computes the union of \c l1 and \c l2, possibly creating a union label in
/// the process.
dfsan_label dfsan_union(dfsan_label l1, dfsan_label l2);
@@ -72,6 +75,14 @@ int dfsan_has_label(dfsan_label label, dfsan_label elem);
/// that label, else returns 0.
dfsan_label dfsan_has_label_with_desc(dfsan_label label, const char *desc);
+/// Returns the number of labels allocated.
+size_t dfsan_get_label_count(void);
+
+/// Sets a callback to be invoked on calls to write(). The callback is invoked
+/// before the write is done. The write is not guaranteed to succeed when the
+/// callback executes. Pass in NULL to remove any callback.
+void dfsan_set_write_callback(dfsan_write_callback_t labeled_write_callback);
+
#ifdef __cplusplus
} // extern "C"
diff --git a/libsanitizer/include/sanitizer/lsan_interface.h b/libsanitizer/include/sanitizer/lsan_interface.h
index ec9c730eee3..95e79245ec0 100644
--- a/libsanitizer/include/sanitizer/lsan_interface.h
+++ b/libsanitizer/include/sanitizer/lsan_interface.h
@@ -21,13 +21,24 @@ extern "C" {
// be treated as non-leaks. Disable/enable pairs may be nested.
void __lsan_disable();
void __lsan_enable();
+
// The heap object into which p points will be treated as a non-leak.
void __lsan_ignore_object(const void *p);
- // The user may optionally provide this function to disallow leak checking
- // for the program it is linked into (if the return value is non-zero). This
- // function must be defined as returning a constant value; any behavior beyond
- // that is unsupported.
- int __lsan_is_turned_off();
+
+ // Memory regions registered through this interface will be treated as sources
+ // of live pointers during leak checking. Useful if you store pointers in
+ // mapped memory.
+ // Points of note:
+ // - __lsan_unregister_root_region() must be called with the same pointer and
+ // size that have earlier been passed to __lsan_register_root_region()
+ // - LSan will skip any inaccessible memory when scanning a root region. E.g.,
+ // if you map memory within a larger region that you have mprotect'ed, you can
+ // register the entire large region.
+ // - the implementation is not optimized for performance. This interface is
+ // intended to be used for a small number of relatively static regions.
+ void __lsan_register_root_region(const void *p, size_t size);
+ void __lsan_unregister_root_region(const void *p, size_t size);
+
// Calling this function makes LSan enter the leak checking phase immediately.
// Use this if normal end-of-process leak checking happens too late (e.g. if
// you have intentional memory leaks in your shutdown code). Calling this
@@ -35,6 +46,16 @@ extern "C" {
// most once per process. This function will terminate the process if there
// are memory leaks and the exit_code flag is non-zero.
void __lsan_do_leak_check();
+
+ // The user may optionally provide this function to disallow leak checking
+ // for the program it is linked into (if the return value is non-zero). This
+ // function must be defined as returning a constant value; any behavior beyond
+ // that is unsupported.
+ int __lsan_is_turned_off();
+
+ // This function may be optionally provided by the user and should return
+ // a string containing LSan suppressions.
+ const char *__lsan_default_suppressions();
#ifdef __cplusplus
} // extern "C"
diff --git a/libsanitizer/include/sanitizer/msan_interface.h b/libsanitizer/include/sanitizer/msan_interface.h
index f531cf347c9..68e510f19bd 100644
--- a/libsanitizer/include/sanitizer/msan_interface.h
+++ b/libsanitizer/include/sanitizer/msan_interface.h
@@ -17,13 +17,10 @@
#ifdef __cplusplus
extern "C" {
#endif
-
-#if __has_feature(memory_sanitizer)
/* Returns a string describing a stack origin.
Return NULL if the origin is invalid, or is not a stack origin. */
const char *__msan_get_origin_descr_if_stack(uint32_t id);
-
/* Set raw origin for the memory range. */
void __msan_set_origin(const volatile void *a, size_t size, uint32_t origin);
@@ -39,6 +36,10 @@ extern "C" {
/* Make memory region fully initialized (without changing its contents). */
void __msan_unpoison(const volatile void *a, size_t size);
+ /* Make a null-terminated string fully initialized (without changing its
+ contents). */
+ void __msan_unpoison_string(const volatile char *a);
+
/* Make memory region fully uninitialized (without changing its contents). */
void __msan_poison(const volatile void *a, size_t size);
@@ -51,6 +52,10 @@ extern "C" {
memory range, or -1 if the whole range is good. */
intptr_t __msan_test_shadow(const volatile void *x, size_t size);
+ /* Checks that memory range is fully initialized, and reports an error if it
+ * is not. */
+ void __msan_check_mem_is_initialized(const volatile void *x, size_t size);
+
/* Set exit code when error(s) were detected.
Value of 0 means don't change the program exit code. */
void __msan_set_exit_code(int exit_code);
@@ -67,13 +72,13 @@ extern "C" {
modules that were compiled without the corresponding compiler flag. */
void __msan_set_keep_going(int keep_going);
- /* Print shadow and origin for the memory range to stdout in a human-readable
+ /* Print shadow and origin for the memory range to stderr in a human-readable
format. */
void __msan_print_shadow(const volatile void *x, size_t size);
- /* Print current function arguments shadow and origin to stdout in a
+ /* Print shadow for the memory range to stderr in a minimalistic
human-readable format. */
- void __msan_print_param_shadow();
+ void __msan_dump_shadow(const volatile void *x, size_t size);
/* Returns true if running under a dynamic tool (DynamoRio-based). */
int __msan_has_dynamic_component();
@@ -86,6 +91,9 @@ extern "C" {
a string containing Msan runtime options. See msan_flags.h for details. */
const char* __msan_default_options();
+ // Sets the callback to be called right before death on error.
+ // Passing 0 will unset the callback.
+ void __msan_set_death_callback(void (*callback)(void));
/***********************************/
/* Allocator statistics interface. */
@@ -132,27 +140,6 @@ extern "C" {
deallocation of "ptr". */
void __msan_malloc_hook(const volatile void *ptr, size_t size);
void __msan_free_hook(const volatile void *ptr);
-
-#else // __has_feature(memory_sanitizer)
-
-#define __msan_get_origin_descr_if_stack(id) ((const char*)0)
-#define __msan_set_origin(a, size, origin)
-#define __msan_get_origin(a) ((uint32_t)-1)
-#define __msan_get_track_origins() (0)
-#define __msan_get_umr_origin() ((uint32_t)-1)
-#define __msan_unpoison(a, size)
-#define __msan_poison(a, size)
-#define __msan_partial_poison(data, shadow, size)
-#define __msan_test_shadow(x, size) ((intptr_t)-1)
-#define __msan_set_exit_code(exit_code)
-#define __msan_set_expect_umr(expect_umr)
-#define __msan_print_shadow(x, size)
-#define __msan_print_param_shadow()
-#define __msan_has_dynamic_component() (0)
-#define __msan_allocated_memory(data, size)
-
-#endif // __has_feature(memory_sanitizer)
-
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/libsanitizer/tsan/tsan_interface_atomic.h b/libsanitizer/include/sanitizer/tsan_interface_atomic.h
index c500614acc4..d19c9109416 100644
--- a/libsanitizer/tsan/tsan_interface_atomic.h
+++ b/libsanitizer/include/sanitizer/tsan_interface_atomic.h
@@ -7,14 +7,11 @@
//
// This file is a part of ThreadSanitizer (TSan), a race detector.
//
+// Public interface header for TSan atomics.
//===----------------------------------------------------------------------===//
#ifndef TSAN_INTERFACE_ATOMIC_H
#define TSAN_INTERFACE_ATOMIC_H
-#ifndef INTERFACE_ATTRIBUTE
-# define INTERFACE_ATTRIBUTE __attribute__((visibility("default")))
-#endif
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -23,14 +20,12 @@ typedef char __tsan_atomic8;
typedef short __tsan_atomic16; // NOLINT
typedef int __tsan_atomic32;
typedef long __tsan_atomic64; // NOLINT
-
#if defined(__SIZEOF_INT128__) \
|| (__clang_major__ * 100 + __clang_minor__ >= 302)
__extension__ typedef __int128 __tsan_atomic128;
-#define __TSAN_HAS_INT128 1
+# define __TSAN_HAS_INT128 1
#else
-typedef char __tsan_atomic128;
-#define __TSAN_HAS_INT128 0
+# define __TSAN_HAS_INT128 0
#endif
// Part of ABI, do not change.
@@ -45,159 +40,181 @@ typedef enum {
} __tsan_memory_order;
__tsan_atomic8 __tsan_atomic8_load(const volatile __tsan_atomic8 *a,
- __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_load(const volatile __tsan_atomic16 *a,
- __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_load(const volatile __tsan_atomic32 *a,
- __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
__tsan_atomic64 __tsan_atomic64_load(const volatile __tsan_atomic64 *a,
- __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
__tsan_atomic128 __tsan_atomic128_load(const volatile __tsan_atomic128 *a,
- __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
+#endif
void __tsan_atomic8_store(volatile __tsan_atomic8 *a, __tsan_atomic8 v,
- __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
void __tsan_atomic16_store(volatile __tsan_atomic16 *a, __tsan_atomic16 v,
- __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
void __tsan_atomic32_store(volatile __tsan_atomic32 *a, __tsan_atomic32 v,
- __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
void __tsan_atomic64_store(volatile __tsan_atomic64 *a, __tsan_atomic64 v,
- __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
void __tsan_atomic128_store(volatile __tsan_atomic128 *a, __tsan_atomic128 v,
- __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo);
+#endif
__tsan_atomic8 __tsan_atomic8_exchange(volatile __tsan_atomic8 *a,
- __tsan_atomic8 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 v, __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_exchange(volatile __tsan_atomic16 *a,
- __tsan_atomic16 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 v, __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_exchange(volatile __tsan_atomic32 *a,
- __tsan_atomic32 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 v, __tsan_memory_order mo);
__tsan_atomic64 __tsan_atomic64_exchange(volatile __tsan_atomic64 *a,
- __tsan_atomic64 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic64 v, __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
__tsan_atomic128 __tsan_atomic128_exchange(volatile __tsan_atomic128 *a,
- __tsan_atomic128 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic128 v, __tsan_memory_order mo);
+#endif
__tsan_atomic8 __tsan_atomic8_fetch_add(volatile __tsan_atomic8 *a,
- __tsan_atomic8 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 v, __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_fetch_add(volatile __tsan_atomic16 *a,
- __tsan_atomic16 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 v, __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_fetch_add(volatile __tsan_atomic32 *a,
- __tsan_atomic32 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 v, __tsan_memory_order mo);
__tsan_atomic64 __tsan_atomic64_fetch_add(volatile __tsan_atomic64 *a,
- __tsan_atomic64 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic64 v, __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
__tsan_atomic128 __tsan_atomic128_fetch_add(volatile __tsan_atomic128 *a,
- __tsan_atomic128 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic128 v, __tsan_memory_order mo);
+#endif
__tsan_atomic8 __tsan_atomic8_fetch_sub(volatile __tsan_atomic8 *a,
- __tsan_atomic8 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 v, __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_fetch_sub(volatile __tsan_atomic16 *a,
- __tsan_atomic16 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 v, __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_fetch_sub(volatile __tsan_atomic32 *a,
- __tsan_atomic32 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 v, __tsan_memory_order mo);
__tsan_atomic64 __tsan_atomic64_fetch_sub(volatile __tsan_atomic64 *a,
- __tsan_atomic64 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic64 v, __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
__tsan_atomic128 __tsan_atomic128_fetch_sub(volatile __tsan_atomic128 *a,
- __tsan_atomic128 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic128 v, __tsan_memory_order mo);
+#endif
__tsan_atomic8 __tsan_atomic8_fetch_and(volatile __tsan_atomic8 *a,
- __tsan_atomic8 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 v, __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_fetch_and(volatile __tsan_atomic16 *a,
- __tsan_atomic16 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 v, __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_fetch_and(volatile __tsan_atomic32 *a,
- __tsan_atomic32 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 v, __tsan_memory_order mo);
__tsan_atomic64 __tsan_atomic64_fetch_and(volatile __tsan_atomic64 *a,
- __tsan_atomic64 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic64 v, __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
__tsan_atomic128 __tsan_atomic128_fetch_and(volatile __tsan_atomic128 *a,
- __tsan_atomic128 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic128 v, __tsan_memory_order mo);
+#endif
__tsan_atomic8 __tsan_atomic8_fetch_or(volatile __tsan_atomic8 *a,
- __tsan_atomic8 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 v, __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_fetch_or(volatile __tsan_atomic16 *a,
- __tsan_atomic16 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 v, __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_fetch_or(volatile __tsan_atomic32 *a,
- __tsan_atomic32 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 v, __tsan_memory_order mo);
__tsan_atomic64 __tsan_atomic64_fetch_or(volatile __tsan_atomic64 *a,
- __tsan_atomic64 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic64 v, __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
__tsan_atomic128 __tsan_atomic128_fetch_or(volatile __tsan_atomic128 *a,
- __tsan_atomic128 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic128 v, __tsan_memory_order mo);
+#endif
__tsan_atomic8 __tsan_atomic8_fetch_xor(volatile __tsan_atomic8 *a,
- __tsan_atomic8 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 v, __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_fetch_xor(volatile __tsan_atomic16 *a,
- __tsan_atomic16 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 v, __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_fetch_xor(volatile __tsan_atomic32 *a,
- __tsan_atomic32 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 v, __tsan_memory_order mo);
__tsan_atomic64 __tsan_atomic64_fetch_xor(volatile __tsan_atomic64 *a,
- __tsan_atomic64 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic64 v, __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
__tsan_atomic128 __tsan_atomic128_fetch_xor(volatile __tsan_atomic128 *a,
- __tsan_atomic128 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic128 v, __tsan_memory_order mo);
+#endif
__tsan_atomic8 __tsan_atomic8_fetch_nand(volatile __tsan_atomic8 *a,
- __tsan_atomic8 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic8 v, __tsan_memory_order mo);
__tsan_atomic16 __tsan_atomic16_fetch_nand(volatile __tsan_atomic16 *a,
- __tsan_atomic16 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic16 v, __tsan_memory_order mo);
__tsan_atomic32 __tsan_atomic32_fetch_nand(volatile __tsan_atomic32 *a,
- __tsan_atomic32 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic32 v, __tsan_memory_order mo);
__tsan_atomic64 __tsan_atomic64_fetch_nand(volatile __tsan_atomic64 *a,
- __tsan_atomic64 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic64 v, __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
__tsan_atomic128 __tsan_atomic128_fetch_nand(volatile __tsan_atomic128 *a,
- __tsan_atomic128 v, __tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+ __tsan_atomic128 v, __tsan_memory_order mo);
+#endif
int __tsan_atomic8_compare_exchange_weak(volatile __tsan_atomic8 *a,
__tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo,
- __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order fail_mo);
int __tsan_atomic16_compare_exchange_weak(volatile __tsan_atomic16 *a,
__tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo,
- __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order fail_mo);
int __tsan_atomic32_compare_exchange_weak(volatile __tsan_atomic32 *a,
__tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo,
- __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order fail_mo);
int __tsan_atomic64_compare_exchange_weak(volatile __tsan_atomic64 *a,
__tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo,
- __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order fail_mo);
+#if __TSAN_HAS_INT128
int __tsan_atomic128_compare_exchange_weak(volatile __tsan_atomic128 *a,
__tsan_atomic128 *c, __tsan_atomic128 v, __tsan_memory_order mo,
- __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order fail_mo);
+#endif
int __tsan_atomic8_compare_exchange_strong(volatile __tsan_atomic8 *a,
__tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo,
- __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order fail_mo);
int __tsan_atomic16_compare_exchange_strong(volatile __tsan_atomic16 *a,
__tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo,
- __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order fail_mo);
int __tsan_atomic32_compare_exchange_strong(volatile __tsan_atomic32 *a,
__tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo,
- __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order fail_mo);
int __tsan_atomic64_compare_exchange_strong(volatile __tsan_atomic64 *a,
__tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo,
- __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order fail_mo);
+#if __TSAN_HAS_INT128
int __tsan_atomic128_compare_exchange_strong(volatile __tsan_atomic128 *a,
__tsan_atomic128 *c, __tsan_atomic128 v, __tsan_memory_order mo,
- __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order fail_mo);
+#endif
__tsan_atomic8 __tsan_atomic8_compare_exchange_val(
volatile __tsan_atomic8 *a, __tsan_atomic8 c, __tsan_atomic8 v,
- __tsan_memory_order mo, __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo, __tsan_memory_order fail_mo);
__tsan_atomic16 __tsan_atomic16_compare_exchange_val(
volatile __tsan_atomic16 *a, __tsan_atomic16 c, __tsan_atomic16 v,
- __tsan_memory_order mo, __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo, __tsan_memory_order fail_mo);
__tsan_atomic32 __tsan_atomic32_compare_exchange_val(
volatile __tsan_atomic32 *a, __tsan_atomic32 c, __tsan_atomic32 v,
- __tsan_memory_order mo, __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo, __tsan_memory_order fail_mo);
__tsan_atomic64 __tsan_atomic64_compare_exchange_val(
volatile __tsan_atomic64 *a, __tsan_atomic64 c, __tsan_atomic64 v,
- __tsan_memory_order mo, __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo, __tsan_memory_order fail_mo);
+#if __TSAN_HAS_INT128
__tsan_atomic128 __tsan_atomic128_compare_exchange_val(
volatile __tsan_atomic128 *a, __tsan_atomic128 c, __tsan_atomic128 v,
- __tsan_memory_order mo, __tsan_memory_order fail_mo) INTERFACE_ATTRIBUTE;
+ __tsan_memory_order mo, __tsan_memory_order fail_mo);
+#endif
-void __tsan_atomic_thread_fence(__tsan_memory_order mo) INTERFACE_ATTRIBUTE;
-void __tsan_atomic_signal_fence(__tsan_memory_order mo) INTERFACE_ATTRIBUTE;
+void __tsan_atomic_thread_fence(__tsan_memory_order mo);
+void __tsan_atomic_signal_fence(__tsan_memory_order mo);
#ifdef __cplusplus
} // extern "C"
#endif
-#undef INTERFACE_ATTRIBUTE
-
-#endif // #ifndef TSAN_INTERFACE_ATOMIC_H
+#endif // TSAN_INTERFACE_ATOMIC_H
diff --git a/libsanitizer/interception/interception.h b/libsanitizer/interception/interception.h
index 7393f4c26be..51505e1baa2 100644
--- a/libsanitizer/interception/interception.h
+++ b/libsanitizer/interception/interception.h
@@ -13,7 +13,8 @@
#ifndef INTERCEPTION_H
#define INTERCEPTION_H
-#if !defined(__linux__) && !defined(__APPLE__) && !defined(_WIN32)
+#if !defined(__linux__) && !defined(__FreeBSD__) && \
+ !defined(__APPLE__) && !defined(_WIN32)
# error "Interception doesn't work on this operating system."
#endif
@@ -233,11 +234,11 @@ typedef unsigned long uptr; // NOLINT
#define INCLUDED_FROM_INTERCEPTION_LIB
-#if defined(__linux__)
+#if defined(__linux__) || defined(__FreeBSD__)
# include "interception_linux.h"
-# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX(func)
+# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
# define INTERCEPT_FUNCTION_VER(func, symver) \
- INTERCEPT_FUNCTION_VER_LINUX(func, symver)
+ INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver)
#elif defined(__APPLE__)
# include "interception_mac.h"
# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_MAC(func)
diff --git a/libsanitizer/interception/interception_linux.cc b/libsanitizer/interception/interception_linux.cc
index 0a8df474ab4..0a8305b0bf8 100644
--- a/libsanitizer/interception/interception_linux.cc
+++ b/libsanitizer/interception/interception_linux.cc
@@ -10,10 +10,10 @@
// Linux-specific interception methods.
//===----------------------------------------------------------------------===//
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
#include "interception.h"
-#include <dlfcn.h> // for dlsym
+#include <dlfcn.h> // for dlsym() and dlvsym()
namespace __interception {
bool GetRealFunctionAddress(const char *func_name, uptr *func_addr,
@@ -31,4 +31,4 @@ void *GetFuncAddrVer(const char *func_name, const char *ver) {
} // namespace __interception
-#endif // __linux__
+#endif // __linux__ || __FreeBSD__
diff --git a/libsanitizer/interception/interception_linux.h b/libsanitizer/interception/interception_linux.h
index 5ab24db438e..e2cc4c19dff 100644
--- a/libsanitizer/interception/interception_linux.h
+++ b/libsanitizer/interception/interception_linux.h
@@ -10,7 +10,7 @@
// Linux-specific interception methods.
//===----------------------------------------------------------------------===//
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
#if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
# error "interception_linux.h should be included from interception library only"
@@ -26,20 +26,20 @@ bool GetRealFunctionAddress(const char *func_name, uptr *func_addr,
void *GetFuncAddrVer(const char *func_name, const char *ver);
} // namespace __interception
-#define INTERCEPT_FUNCTION_LINUX(func) \
- ::__interception::GetRealFunctionAddress( \
- #func, (::__interception::uptr*)&REAL(func), \
- (::__interception::uptr)&(func), \
- (::__interception::uptr)&WRAP(func))
+#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \
+ ::__interception::GetRealFunctionAddress( \
+ #func, (::__interception::uptr *)&__interception::PTR_TO_REAL(func), \
+ (::__interception::uptr) & (func), \
+ (::__interception::uptr) & WRAP(func))
#if !defined(__ANDROID__) // android does not have dlvsym
-# define INTERCEPT_FUNCTION_VER_LINUX(func, symver) \
+# define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
::__interception::real_##func = (func##_f)(unsigned long) \
::__interception::GetFuncAddrVer(#func, symver)
#else
-# define INTERCEPT_FUNCTION_VER_LINUX(func, symver) \
- INTERCEPT_FUNCTION_LINUX(func)
+# define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
+ INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
#endif // !defined(__ANDROID__)
#endif // INTERCEPTION_LINUX_H
-#endif // __linux__
+#endif // __linux__ || __FreeBSD__
diff --git a/libsanitizer/interception/interception_type_test.cc b/libsanitizer/interception/interception_type_test.cc
index f664eeeb04f..6ba45e26dda 100644
--- a/libsanitizer/interception/interception_type_test.cc
+++ b/libsanitizer/interception/interception_type_test.cc
@@ -17,13 +17,13 @@
#include <stddef.h>
#include <stdint.h>
-COMPILER_CHECK(sizeof(SIZE_T) == sizeof(size_t));
-COMPILER_CHECK(sizeof(SSIZE_T) == sizeof(ssize_t));
-COMPILER_CHECK(sizeof(PTRDIFF_T) == sizeof(ptrdiff_t));
-COMPILER_CHECK(sizeof(INTMAX_T) == sizeof(intmax_t));
+COMPILER_CHECK(sizeof(::SIZE_T) == sizeof(size_t));
+COMPILER_CHECK(sizeof(::SSIZE_T) == sizeof(ssize_t));
+COMPILER_CHECK(sizeof(::PTRDIFF_T) == sizeof(ptrdiff_t));
+COMPILER_CHECK(sizeof(::INTMAX_T) == sizeof(intmax_t));
#ifndef __APPLE__
-COMPILER_CHECK(sizeof(OFF64_T) == sizeof(off64_t));
+COMPILER_CHECK(sizeof(::OFF64_T) == sizeof(off64_t));
#endif
// The following are the cases when pread (and friends) is used instead of
@@ -31,7 +31,7 @@ COMPILER_CHECK(sizeof(OFF64_T) == sizeof(off64_t));
// rest (they depend on _FILE_OFFSET_BITS setting when building an application).
# if defined(__ANDROID__) || !defined _FILE_OFFSET_BITS || \
_FILE_OFFSET_BITS != 64
-COMPILER_CHECK(sizeof(OFF_T) == sizeof(off_t));
+COMPILER_CHECK(sizeof(::OFF_T) == sizeof(off_t));
# endif
#endif
diff --git a/libsanitizer/interception/interception_win.cc b/libsanitizer/interception/interception_win.cc
index 443bdce1859..9cd71751839 100644
--- a/libsanitizer/interception/interception_win.cc
+++ b/libsanitizer/interception/interception_win.cc
@@ -54,91 +54,136 @@ static void WriteJumpInstruction(char *jmp_from, char *to) {
*(ptrdiff_t*)(jmp_from + 1) = offset;
}
-bool OverrideFunction(uptr old_func, uptr new_func, uptr *orig_old_func) {
-#ifdef _WIN64
-# error OverrideFunction was not tested on x64
-#endif
- // Basic idea:
- // We write 5 bytes (jmp-to-new_func) at the beginning of the 'old_func'
- // to override it. We want to be able to execute the original 'old_func' from
- // the wrapper, so we need to keep the leading 5+ bytes ('head') of the
- // original instructions somewhere with a "jmp old_func+head".
- // We call these 'head'+5 bytes of instructions a "trampoline".
-
+static char *GetMemoryForTrampoline(size_t size) {
// Trampolines are allocated from a common pool.
const int POOL_SIZE = 1024;
static char *pool = NULL;
static size_t pool_used = 0;
- if (pool == NULL) {
- pool = (char*)VirtualAlloc(NULL, POOL_SIZE,
- MEM_RESERVE | MEM_COMMIT,
- PAGE_EXECUTE_READWRITE);
- // FIXME: set PAGE_EXECUTE_READ access after setting all interceptors?
- if (pool == NULL)
- return false;
+ if (!pool) {
+ pool = (char *)VirtualAlloc(NULL, POOL_SIZE, MEM_RESERVE | MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE);
+ // FIXME: Might want to apply PAGE_EXECUTE_READ access after all the
+ // interceptors are in place.
+ if (!pool)
+ return NULL;
_memset(pool, 0xCC /* int 3 */, POOL_SIZE);
}
- char* old_bytes = (char*)old_func;
- char* trampoline = pool + pool_used;
+ if (pool_used + size > POOL_SIZE)
+ return NULL;
- // Find out the number of bytes of the instructions we need to copy to the
- // island and store it in 'head'.
- size_t head = 0;
- while (head < 5) {
- switch (old_bytes[head]) {
+ char *ret = pool + pool_used;
+ pool_used += size;
+ return ret;
+}
+
+// Returns 0 on error.
+static size_t RoundUpToInstrBoundary(size_t size, char *code) {
+ size_t cursor = 0;
+ while (cursor < size) {
+ switch (code[cursor]) {
+ case '\x51': // push ecx
+ case '\x52': // push edx
+ case '\x53': // push ebx
+ case '\x54': // push esp
case '\x55': // push ebp
case '\x56': // push esi
case '\x57': // push edi
- head++;
+ case '\x5D': // pop ebp
+ cursor++;
+ continue;
+ case '\x6A': // 6A XX = push XX
+ cursor += 2;
+ continue;
+ case '\xE9': // E9 XX YY ZZ WW = jmp WWZZYYXX
+ cursor += 5;
continue;
}
- switch (*(unsigned short*)(old_bytes + head)) { // NOLINT
+ switch (*(unsigned short*)(code + cursor)) { // NOLINT
case 0xFF8B: // 8B FF = mov edi, edi
case 0xEC8B: // 8B EC = mov ebp, esp
case 0xC033: // 33 C0 = xor eax, eax
- head += 2;
+ cursor += 2;
continue;
+ case 0x458B: // 8B 45 XX = mov eax, dword ptr [ebp+XXh]
+ case 0x5D8B: // 8B 5D XX = mov ebx, dword ptr [ebp+XXh]
case 0xEC83: // 83 EC XX = sub esp, XX
- head += 3;
+ cursor += 3;
continue;
case 0xC1F7: // F7 C1 XX YY ZZ WW = test ecx, WWZZYYXX
- head += 6;
+ cursor += 6;
+ continue;
+ case 0x3D83: // 83 3D XX YY ZZ WW TT = cmp TT, WWZZYYXX
+ cursor += 7;
continue;
}
- switch (0x00FFFFFF & *(unsigned int*)(old_bytes + head)) {
+ switch (0x00FFFFFF & *(unsigned int*)(code + cursor)) {
case 0x24448A: // 8A 44 24 XX = mov eal, dword ptr [esp+XXh]
case 0x244C8B: // 8B 4C 24 XX = mov ecx, dword ptr [esp+XXh]
case 0x24548B: // 8B 54 24 XX = mov edx, dword ptr [esp+XXh]
+ case 0x24748B: // 8B 74 24 XX = mov esi, dword ptr [esp+XXh]
case 0x247C8B: // 8B 7C 24 XX = mov edi, dword ptr [esp+XXh]
- head += 4;
+ cursor += 4;
continue;
}
// Unknown instruction!
- return false;
+ // FIXME: Unknown instruction failures might happen when we add a new
+ // interceptor or a new compiler version. In either case, they should result
+ // in visible and readable error messages. However, merely calling abort()
+ // or __debugbreak() leads to an infinite recursion in CheckFailed.
+ // Do we have a good way to abort with an error message here?
+ return 0;
}
- if (pool_used + head + 5 > POOL_SIZE)
- return false;
+ return cursor;
+}
+
+bool OverrideFunction(uptr old_func, uptr new_func, uptr *orig_old_func) {
+#ifdef _WIN64
+#error OverrideFunction is not yet supported on x64
+#endif
+ // Function overriding works basically like this:
+ // We write "jmp <new_func>" (5 bytes) at the beginning of the 'old_func'
+ // to override it.
+ // We might want to be able to execute the original 'old_func' from the
+ // wrapper, in this case we need to keep the leading 5+ bytes ('head')
+ // of the original code somewhere with a "jmp <old_func+head>".
+ // We call these 'head'+5 bytes of instructions a "trampoline".
+ char *old_bytes = (char *)old_func;
+
+ // We'll need at least 5 bytes for a 'jmp'.
+ size_t head = 5;
+ if (orig_old_func) {
+ // Find out the number of bytes of the instructions we need to copy
+ // to the trampoline and store it in 'head'.
+ head = RoundUpToInstrBoundary(head, old_bytes);
+ if (!head)
+ return false;
+
+ // Put the needed instructions into the trampoline bytes.
+ char *trampoline = GetMemoryForTrampoline(head + 5);
+ if (!trampoline)
+ return false;
+ _memcpy(trampoline, old_bytes, head);
+ WriteJumpInstruction(trampoline + head, old_bytes + head);
+ *orig_old_func = (uptr)trampoline;
+ }
- // Now put the "jump to trampoline" instruction into the original code.
+ // Now put the "jmp <new_func>" instruction at the original code location.
+ // We should preserve the EXECUTE flag as some of our own code might be
+ // located in the same page (sic!). FIXME: might consider putting the
+ // __interception code into a separate section or something?
DWORD old_prot, unused_prot;
- if (!VirtualProtect((void*)old_func, head, PAGE_EXECUTE_READWRITE,
+ if (!VirtualProtect((void *)old_bytes, head, PAGE_EXECUTE_READWRITE,
&old_prot))
return false;
- // Put the needed instructions into the trampoline bytes.
- _memcpy(trampoline, old_bytes, head);
- WriteJumpInstruction(trampoline + head, old_bytes + head);
- *orig_old_func = (uptr)trampoline;
- pool_used += head + 5;
-
- // Intercept the 'old_func'.
- WriteJumpInstruction(old_bytes, (char*)new_func);
+ WriteJumpInstruction(old_bytes, (char *)new_func);
_memset(old_bytes + 5, 0xCC /* int 3 */, head - 5);
- if (!VirtualProtect((void*)old_func, head, old_prot, &unused_prot))
+ // Restore the original permissions.
+ if (!VirtualProtect((void *)old_bytes, head, old_prot, &unused_prot))
return false; // not clear if this failure bothers us.
return true;
diff --git a/libsanitizer/lsan/lsan.cc b/libsanitizer/lsan/lsan.cc
index 270979a78e7..c1481f5fb97 100644
--- a/libsanitizer/lsan/lsan.cc
+++ b/libsanitizer/lsan/lsan.cc
@@ -33,6 +33,11 @@ static void InitializeCommonFlags() {
ParseCommonFlagsFromString(cf, GetEnv("LSAN_OPTIONS"));
}
+///// Interface to the common LSan module. /////
+bool WordIsPoisoned(uptr addr) {
+ return false;
+}
+
} // namespace __lsan
using namespace __lsan; // NOLINT
@@ -53,12 +58,7 @@ extern "C" void __lsan_init() {
ThreadStart(tid, GetTid());
SetCurrentThread(tid);
- // Start symbolizer process if necessary.
- if (common_flags()->symbolize) {
- Symbolizer::Init(common_flags()->external_symbolizer_path);
- } else {
- Symbolizer::Disable();
- }
+ Symbolizer::Init(common_flags()->external_symbolizer_path);
InitCommonLsan();
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
diff --git a/libsanitizer/lsan/lsan_allocator.cc b/libsanitizer/lsan/lsan_allocator.cc
index ce47dfcd215..3e81ebef2a7 100644
--- a/libsanitizer/lsan/lsan_allocator.cc
+++ b/libsanitizer/lsan/lsan_allocator.cc
@@ -141,7 +141,11 @@ uptr PointsIntoChunk(void* p) {
if (addr < chunk) return 0;
ChunkMetadata *m = Metadata(reinterpret_cast<void *>(chunk));
CHECK(m);
- if (m->allocated && addr < chunk + m->requested_size)
+ if (!m->allocated)
+ return 0;
+ if (addr < chunk + m->requested_size)
+ return chunk;
+ if (IsSpecialCaseOfOperatorNew0(chunk, m->requested_size, addr))
return chunk;
return 0;
}
diff --git a/libsanitizer/lsan/lsan_common.cc b/libsanitizer/lsan/lsan_common.cc
index bbc5b5f0378..78afa7706d6 100644
--- a/libsanitizer/lsan/lsan_common.cc
+++ b/libsanitizer/lsan/lsan_common.cc
@@ -15,6 +15,7 @@
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "sanitizer_common/sanitizer_stoptheworld.h"
@@ -24,7 +25,8 @@
#if CAN_SANITIZE_LEAKS
namespace __lsan {
-// This mutex is used to prevent races between DoLeakCheck and IgnoreObject.
+// This mutex is used to prevent races between DoLeakCheck and IgnoreObject, and
+// also to protect the global list of root regions.
BlockingMutex global_mutex(LINKER_INITIALIZED);
THREADLOCAL int disable_counter;
@@ -39,42 +41,56 @@ static void InitializeFlags() {
f->resolution = 0;
f->max_leaks = 0;
f->exitcode = 23;
+ f->print_suppressions = true;
f->suppressions="";
f->use_registers = true;
f->use_globals = true;
f->use_stacks = true;
f->use_tls = true;
+ f->use_root_regions = true;
f->use_unaligned = false;
- f->verbosity = 0;
+ f->use_poisoned = false;
f->log_pointers = false;
f->log_threads = false;
const char *options = GetEnv("LSAN_OPTIONS");
if (options) {
- ParseFlag(options, &f->use_registers, "use_registers");
- ParseFlag(options, &f->use_globals, "use_globals");
- ParseFlag(options, &f->use_stacks, "use_stacks");
- ParseFlag(options, &f->use_tls, "use_tls");
- ParseFlag(options, &f->use_unaligned, "use_unaligned");
- ParseFlag(options, &f->report_objects, "report_objects");
- ParseFlag(options, &f->resolution, "resolution");
+ ParseFlag(options, &f->use_registers, "use_registers", "");
+ ParseFlag(options, &f->use_globals, "use_globals", "");
+ ParseFlag(options, &f->use_stacks, "use_stacks", "");
+ ParseFlag(options, &f->use_tls, "use_tls", "");
+ ParseFlag(options, &f->use_root_regions, "use_root_regions", "");
+ ParseFlag(options, &f->use_unaligned, "use_unaligned", "");
+ ParseFlag(options, &f->use_poisoned, "use_poisoned", "");
+ ParseFlag(options, &f->report_objects, "report_objects", "");
+ ParseFlag(options, &f->resolution, "resolution", "");
CHECK_GE(&f->resolution, 0);
- ParseFlag(options, &f->max_leaks, "max_leaks");
+ ParseFlag(options, &f->max_leaks, "max_leaks", "");
CHECK_GE(&f->max_leaks, 0);
- ParseFlag(options, &f->verbosity, "verbosity");
- ParseFlag(options, &f->log_pointers, "log_pointers");
- ParseFlag(options, &f->log_threads, "log_threads");
- ParseFlag(options, &f->exitcode, "exitcode");
- ParseFlag(options, &f->suppressions, "suppressions");
+ ParseFlag(options, &f->log_pointers, "log_pointers", "");
+ ParseFlag(options, &f->log_threads, "log_threads", "");
+ ParseFlag(options, &f->exitcode, "exitcode", "");
+ ParseFlag(options, &f->print_suppressions, "print_suppressions", "");
+ ParseFlag(options, &f->suppressions, "suppressions", "");
}
}
+#define LOG_POINTERS(...) \
+ do { \
+ if (flags()->log_pointers) Report(__VA_ARGS__); \
+ } while (0);
+
+#define LOG_THREADS(...) \
+ do { \
+ if (flags()->log_threads) Report(__VA_ARGS__); \
+ } while (0);
+
SuppressionContext *suppression_ctx;
void InitializeSuppressions() {
CHECK(!suppression_ctx);
- ALIGNED(64) static char placeholder_[sizeof(SuppressionContext)];
- suppression_ctx = new(placeholder_) SuppressionContext;
+ ALIGNED(64) static char placeholder[sizeof(SuppressionContext)];
+ suppression_ctx = new(placeholder) SuppressionContext;
char *suppressions_from_file;
uptr buffer_size;
if (ReadFileToBuffer(flags()->suppressions, &suppressions_from_file,
@@ -89,8 +105,22 @@ void InitializeSuppressions() {
suppression_ctx->Parse(__lsan_default_suppressions());
}
+struct RootRegion {
+ const void *begin;
+ uptr size;
+};
+
+InternalMmapVector<RootRegion> *root_regions;
+
+void InitializeRootRegions() {
+ CHECK(!root_regions);
+ ALIGNED(64) static char placeholder[sizeof(InternalMmapVector<RootRegion>)];
+ root_regions = new(placeholder) InternalMmapVector<RootRegion>(1);
+}
+
void InitCommonLsan() {
InitializeFlags();
+ InitializeRootRegions();
if (common_flags()->detect_leaks) {
// Initialization which can fail or print warnings should only be done if
// LSan is actually enabled.
@@ -130,8 +160,7 @@ void ScanRangeForPointers(uptr begin, uptr end,
Frontier *frontier,
const char *region_type, ChunkTag tag) {
const uptr alignment = flags()->pointer_alignment();
- if (flags()->log_pointers)
- Report("Scanning %s range %p-%p.\n", region_type, begin, end);
+ LOG_POINTERS("Scanning %s range %p-%p.\n", region_type, begin, end);
uptr pp = begin;
if (pp % alignment)
pp = pp + alignment - pp % alignment;
@@ -146,10 +175,19 @@ void ScanRangeForPointers(uptr begin, uptr end,
// Reachable beats ignored beats leaked.
if (m.tag() == kReachable) continue;
if (m.tag() == kIgnored && tag != kReachable) continue;
+
+ // Do this check relatively late so we can log only the interesting cases.
+ if (!flags()->use_poisoned && WordIsPoisoned(pp)) {
+ LOG_POINTERS(
+ "%p is poisoned: ignoring %p pointing into chunk %p-%p of size "
+ "%zu.\n",
+ pp, p, chunk, chunk + m.requested_size(), m.requested_size());
+ continue;
+ }
+
m.set_tag(tag);
- if (flags()->log_pointers)
- Report("%p: found %p pointing into chunk %p-%p of size %zu.\n", pp, p,
- chunk, chunk + m.requested_size(), m.requested_size());
+ LOG_POINTERS("%p: found %p pointing into chunk %p-%p of size %zu.\n", pp, p,
+ chunk, chunk + m.requested_size(), m.requested_size());
if (frontier)
frontier->push_back(chunk);
}
@@ -168,7 +206,7 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
uptr registers_end = registers_begin + registers.size();
for (uptr i = 0; i < suspended_threads.thread_count(); i++) {
uptr os_id = static_cast<uptr>(suspended_threads.GetThreadID(i));
- if (flags()->log_threads) Report("Processing thread %d.\n", os_id);
+ LOG_THREADS("Processing thread %d.\n", os_id);
uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end;
bool thread_found = GetThreadRangesLocked(os_id, &stack_begin, &stack_end,
&tls_begin, &tls_end,
@@ -176,8 +214,7 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
if (!thread_found) {
// If a thread can't be found in the thread registry, it's probably in the
// process of destruction. Log this event and move on.
- if (flags()->log_threads)
- Report("Thread %d not found in registry.\n", os_id);
+ LOG_THREADS("Thread %d not found in registry.\n", os_id);
continue;
}
uptr sp;
@@ -194,14 +231,12 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
"REGISTERS", kReachable);
if (flags()->use_stacks) {
- if (flags()->log_threads)
- Report("Stack at %p-%p, SP = %p.\n", stack_begin, stack_end, sp);
+ LOG_THREADS("Stack at %p-%p (SP = %p).\n", stack_begin, stack_end, sp);
if (sp < stack_begin || sp >= stack_end) {
// SP is outside the recorded stack range (e.g. the thread is running a
// signal handler on alternate stack). Again, consider the entire stack
// range to be reachable.
- if (flags()->log_threads)
- Report("WARNING: stack pointer not in stack range.\n");
+ LOG_THREADS("WARNING: stack pointer not in stack range.\n");
} else {
// Shrink the stack range to ignore out-of-scope values.
stack_begin = sp;
@@ -212,7 +247,7 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
}
if (flags()->use_tls) {
- if (flags()->log_threads) Report("TLS at %p-%p.\n", tls_begin, tls_end);
+ LOG_THREADS("TLS at %p-%p.\n", tls_begin, tls_end);
if (cache_begin == cache_end) {
ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable);
} else {
@@ -230,6 +265,37 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
}
}
+static void ProcessRootRegion(Frontier *frontier, uptr root_begin,
+ uptr root_end) {
+ MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+ uptr begin, end, prot;
+ while (proc_maps.Next(&begin, &end,
+ /*offset*/ 0, /*filename*/ 0, /*filename_size*/ 0,
+ &prot)) {
+ uptr intersection_begin = Max(root_begin, begin);
+ uptr intersection_end = Min(end, root_end);
+ if (intersection_begin >= intersection_end) continue;
+ bool is_readable = prot & MemoryMappingLayout::kProtectionRead;
+ LOG_POINTERS("Root region %p-%p intersects with mapped region %p-%p (%s)\n",
+ root_begin, root_end, begin, end,
+ is_readable ? "readable" : "unreadable");
+ if (is_readable)
+ ScanRangeForPointers(intersection_begin, intersection_end, frontier,
+ "ROOT", kReachable);
+ }
+}
+
+// Scans root regions for heap pointers.
+static void ProcessRootRegions(Frontier *frontier) {
+ if (!flags()->use_root_regions) return;
+ CHECK(root_regions);
+ for (uptr i = 0; i < root_regions->size(); i++) {
+ RootRegion region = (*root_regions)[i];
+ uptr begin_addr = reinterpret_cast<uptr>(region.begin);
+ ProcessRootRegion(frontier, begin_addr, begin_addr + region.size);
+ }
+}
+
static void FloodFillTag(Frontier *frontier, ChunkTag tag) {
while (frontier->size()) {
uptr next_chunk = frontier->back();
@@ -264,30 +330,27 @@ static void CollectIgnoredCb(uptr chunk, void *arg) {
// Sets the appropriate tag on each chunk.
static void ClassifyAllChunks(SuspendedThreadsList const &suspended_threads) {
// Holds the flood fill frontier.
- Frontier frontier(GetPageSizeCached());
+ Frontier frontier(1);
- if (flags()->use_globals)
- ProcessGlobalRegions(&frontier);
+ ProcessGlobalRegions(&frontier);
ProcessThreads(suspended_threads, &frontier);
+ ProcessRootRegions(&frontier);
FloodFillTag(&frontier, kReachable);
// The check here is relatively expensive, so we do this in a separate flood
// fill. That way we can skip the check for chunks that are reachable
// otherwise.
- if (flags()->log_pointers)
- Report("Processing platform-specific allocations.\n");
+ LOG_POINTERS("Processing platform-specific allocations.\n");
ProcessPlatformSpecificAllocations(&frontier);
FloodFillTag(&frontier, kReachable);
- if (flags()->log_pointers)
- Report("Scanning ignored chunks.\n");
+ LOG_POINTERS("Scanning ignored chunks.\n");
CHECK_EQ(0, frontier.size());
ForEachChunk(CollectIgnoredCb, &frontier);
FloodFillTag(&frontier, kIgnored);
// Iterate over leaked chunks and mark those that are reachable from other
// leaked chunks.
- if (flags()->log_pointers)
- Report("Scanning leaked chunks.\n");
+ LOG_POINTERS("Scanning leaked chunks.\n");
ForEachChunk(MarkIndirectlyLeakedCb, 0 /* arg */);
}
@@ -298,7 +361,8 @@ static void PrintStackTraceById(u32 stack_trace_id) {
StackTrace::PrintStack(trace, size);
}
-// ForEachChunk callback. Aggregates unreachable chunks into a LeakReport.
+// ForEachChunk callback. Aggregates information about unreachable chunks into
+// a LeakReport.
static void CollectLeaksCb(uptr chunk, void *arg) {
CHECK(arg);
LeakReport *leak_report = reinterpret_cast<LeakReport *>(arg);
@@ -307,26 +371,17 @@ static void CollectLeaksCb(uptr chunk, void *arg) {
if (!m.allocated()) return;
if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) {
uptr resolution = flags()->resolution;
+ u32 stack_trace_id = 0;
if (resolution > 0) {
uptr size = 0;
const uptr *trace = StackDepotGet(m.stack_trace_id(), &size);
size = Min(size, resolution);
- leak_report->Add(StackDepotPut(trace, size), m.requested_size(), m.tag());
+ stack_trace_id = StackDepotPut(trace, size);
} else {
- leak_report->Add(m.stack_trace_id(), m.requested_size(), m.tag());
+ stack_trace_id = m.stack_trace_id();
}
- }
-}
-
-// ForEachChunkCallback. Prints addresses of unreachable chunks.
-static void PrintLeakedCb(uptr chunk, void *arg) {
- chunk = GetUserBegin(chunk);
- LsanMetadata m(chunk);
- if (!m.allocated()) return;
- if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) {
- Printf("%s leaked %zu byte object at %p.\n",
- m.tag() == kDirectlyLeaked ? "Directly" : "Indirectly",
- m.requested_size(), chunk);
+ leak_report->AddLeakedChunk(chunk, stack_trace_id, m.requested_size(),
+ m.tag());
}
}
@@ -345,12 +400,6 @@ static void PrintMatchedSuppressions() {
Printf("%s\n\n", line);
}
-static void PrintLeaked() {
- Printf("\n");
- Printf("Reporting individual objects:\n");
- ForEachChunk(PrintLeakedCb, 0 /* arg */);
-}
-
struct DoLeakCheckParam {
bool success;
LeakReport leak_report;
@@ -361,11 +410,8 @@ static void DoLeakCheckCallback(const SuspendedThreadsList &suspended_threads,
DoLeakCheckParam *param = reinterpret_cast<DoLeakCheckParam *>(arg);
CHECK(param);
CHECK(!param->success);
- CHECK(param->leak_report.IsEmpty());
ClassifyAllChunks(suspended_threads);
ForEachChunk(CollectLeaksCb, &param->leak_report);
- if (!param->leak_report.IsEmpty() && flags()->report_objects)
- PrintLeaked();
param->success = true;
}
@@ -376,7 +422,7 @@ void DoLeakCheck() {
if (already_done) return;
already_done = true;
if (&__lsan_is_turned_off && __lsan_is_turned_off())
- return;
+ return;
DoLeakCheckParam param;
param.success = false;
@@ -390,8 +436,9 @@ void DoLeakCheck() {
Report("LeakSanitizer has encountered a fatal error.\n");
Die();
}
- uptr have_unsuppressed = param.leak_report.ApplySuppressions();
- if (have_unsuppressed) {
+ param.leak_report.ApplySuppressions();
+ uptr unsuppressed_count = param.leak_report.UnsuppressedLeakCount();
+ if (unsuppressed_count > 0) {
Decorator d;
Printf("\n"
"================================================================="
@@ -399,27 +446,37 @@ void DoLeakCheck() {
Printf("%s", d.Error());
Report("ERROR: LeakSanitizer: detected memory leaks\n");
Printf("%s", d.End());
- param.leak_report.PrintLargest(flags()->max_leaks);
+ param.leak_report.ReportTopLeaks(flags()->max_leaks);
}
- if (have_unsuppressed || (flags()->verbosity >= 1)) {
+ if (flags()->print_suppressions)
PrintMatchedSuppressions();
+ if (unsuppressed_count > 0) {
param.leak_report.PrintSummary();
+ if (flags()->exitcode)
+ internal__exit(flags()->exitcode);
}
- if (have_unsuppressed && flags()->exitcode)
- internal__exit(flags()->exitcode);
}
static Suppression *GetSuppressionForAddr(uptr addr) {
+ Suppression *s;
+
+ // Suppress by module name.
+ const char *module_name;
+ uptr module_offset;
+ if (Symbolizer::Get()->GetModuleNameAndOffsetForPC(addr, &module_name,
+ &module_offset) &&
+ suppression_ctx->Match(module_name, SuppressionLeak, &s))
+ return s;
+
+ // Suppress by file or function name.
static const uptr kMaxAddrFrames = 16;
InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
for (uptr i = 0; i < kMaxAddrFrames; i++) new (&addr_frames[i]) AddressInfo();
- uptr addr_frames_num = Symbolizer::Get()->SymbolizeCode(
+ uptr addr_frames_num = Symbolizer::Get()->SymbolizePC(
addr, addr_frames.data(), kMaxAddrFrames);
for (uptr i = 0; i < addr_frames_num; i++) {
- Suppression* s;
if (suppression_ctx->Match(addr_frames[i].function, SuppressionLeak, &s) ||
- suppression_ctx->Match(addr_frames[i].file, SuppressionLeak, &s) ||
- suppression_ctx->Match(addr_frames[i].module, SuppressionLeak, &s))
+ suppression_ctx->Match(addr_frames[i].file, SuppressionLeak, &s))
return s;
}
return 0;
@@ -439,26 +496,35 @@ static Suppression *GetSuppressionForStack(u32 stack_trace_id) {
///// LeakReport implementation. /////
// A hard limit on the number of distinct leaks, to avoid quadratic complexity
-// in LeakReport::Add(). We don't expect to ever see this many leaks in
-// real-world applications.
+// in LeakReport::AddLeakedChunk(). We don't expect to ever see this many leaks
+// in real-world applications.
// FIXME: Get rid of this limit by changing the implementation of LeakReport to
// use a hash table.
const uptr kMaxLeaksConsidered = 5000;
-void LeakReport::Add(u32 stack_trace_id, uptr leaked_size, ChunkTag tag) {
+void LeakReport::AddLeakedChunk(uptr chunk, u32 stack_trace_id,
+ uptr leaked_size, ChunkTag tag) {
CHECK(tag == kDirectlyLeaked || tag == kIndirectlyLeaked);
bool is_directly_leaked = (tag == kDirectlyLeaked);
- for (uptr i = 0; i < leaks_.size(); i++)
+ uptr i;
+ for (i = 0; i < leaks_.size(); i++) {
if (leaks_[i].stack_trace_id == stack_trace_id &&
leaks_[i].is_directly_leaked == is_directly_leaked) {
leaks_[i].hit_count++;
leaks_[i].total_size += leaked_size;
- return;
+ break;
}
- if (leaks_.size() == kMaxLeaksConsidered) return;
- Leak leak = { /* hit_count */ 1, leaked_size, stack_trace_id,
- is_directly_leaked, /* is_suppressed */ false };
- leaks_.push_back(leak);
+ }
+ if (i == leaks_.size()) {
+ if (leaks_.size() == kMaxLeaksConsidered) return;
+ Leak leak = { next_id_++, /* hit_count */ 1, leaked_size, stack_trace_id,
+ is_directly_leaked, /* is_suppressed */ false };
+ leaks_.push_back(leak);
+ }
+ if (flags()->report_objects) {
+ LeakedObject obj = {leaks_[i].id, chunk, leaked_size};
+ leaked_objects_.push_back(obj);
+ }
}
static bool LeakComparator(const Leak &leak1, const Leak &leak2) {
@@ -468,7 +534,7 @@ static bool LeakComparator(const Leak &leak1, const Leak &leak2) {
return leak1.is_directly_leaked;
}
-void LeakReport::PrintLargest(uptr num_leaks_to_print) {
+void LeakReport::ReportTopLeaks(uptr num_leaks_to_report) {
CHECK(leaks_.size() <= kMaxLeaksConsidered);
Printf("\n");
if (leaks_.size() == kMaxLeaksConsidered)
@@ -476,31 +542,49 @@ void LeakReport::PrintLargest(uptr num_leaks_to_print) {
"reported.\n",
kMaxLeaksConsidered);
- uptr unsuppressed_count = 0;
- for (uptr i = 0; i < leaks_.size(); i++)
- if (!leaks_[i].is_suppressed) unsuppressed_count++;
- if (num_leaks_to_print > 0 && num_leaks_to_print < unsuppressed_count)
- Printf("The %zu largest leak(s):\n", num_leaks_to_print);
+ uptr unsuppressed_count = UnsuppressedLeakCount();
+ if (num_leaks_to_report > 0 && num_leaks_to_report < unsuppressed_count)
+ Printf("The %zu top leak(s):\n", num_leaks_to_report);
InternalSort(&leaks_, leaks_.size(), LeakComparator);
- uptr leaks_printed = 0;
- Decorator d;
+ uptr leaks_reported = 0;
for (uptr i = 0; i < leaks_.size(); i++) {
if (leaks_[i].is_suppressed) continue;
- Printf("%s", d.Leak());
- Printf("%s leak of %zu byte(s) in %zu object(s) allocated from:\n",
- leaks_[i].is_directly_leaked ? "Direct" : "Indirect",
- leaks_[i].total_size, leaks_[i].hit_count);
- Printf("%s", d.End());
- PrintStackTraceById(leaks_[i].stack_trace_id);
- leaks_printed++;
- if (leaks_printed == num_leaks_to_print) break;
+ PrintReportForLeak(i);
+ leaks_reported++;
+ if (leaks_reported == num_leaks_to_report) break;
}
- if (leaks_printed < unsuppressed_count) {
- uptr remaining = unsuppressed_count - leaks_printed;
+ if (leaks_reported < unsuppressed_count) {
+ uptr remaining = unsuppressed_count - leaks_reported;
Printf("Omitting %zu more leak(s).\n", remaining);
}
}
+void LeakReport::PrintReportForLeak(uptr index) {
+ Decorator d;
+ Printf("%s", d.Leak());
+ Printf("%s leak of %zu byte(s) in %zu object(s) allocated from:\n",
+ leaks_[index].is_directly_leaked ? "Direct" : "Indirect",
+ leaks_[index].total_size, leaks_[index].hit_count);
+ Printf("%s", d.End());
+
+ PrintStackTraceById(leaks_[index].stack_trace_id);
+
+ if (flags()->report_objects) {
+ Printf("Objects leaked above:\n");
+ PrintLeakedObjectsForLeak(index);
+ Printf("\n");
+ }
+}
+
+void LeakReport::PrintLeakedObjectsForLeak(uptr index) {
+ u32 leak_id = leaks_[index].id;
+ for (uptr j = 0; j < leaked_objects_.size(); j++) {
+ if (leaked_objects_[j].leak_id == leak_id)
+ Printf("%p (%zu bytes)\n", leaked_objects_[j].addr,
+ leaked_objects_[j].size);
+ }
+}
+
void LeakReport::PrintSummary() {
CHECK(leaks_.size() <= kMaxLeaksConsidered);
uptr bytes = 0, allocations = 0;
@@ -516,20 +600,24 @@ void LeakReport::PrintSummary() {
ReportErrorSummary(summary.data());
}
-uptr LeakReport::ApplySuppressions() {
- uptr unsuppressed_count = 0;
+void LeakReport::ApplySuppressions() {
for (uptr i = 0; i < leaks_.size(); i++) {
Suppression *s = GetSuppressionForStack(leaks_[i].stack_trace_id);
if (s) {
s->weight += leaks_[i].total_size;
s->hit_count += leaks_[i].hit_count;
leaks_[i].is_suppressed = true;
- } else {
- unsuppressed_count++;
}
}
- return unsuppressed_count;
}
+
+uptr LeakReport::UnsuppressedLeakCount() {
+ uptr result = 0;
+ for (uptr i = 0; i < leaks_.size(); i++)
+ if (!leaks_[i].is_suppressed) result++;
+ return result;
+}
+
} // namespace __lsan
#endif // CAN_SANITIZE_LEAKS
@@ -545,13 +633,51 @@ void __lsan_ignore_object(const void *p) {
// locked.
BlockingMutexLock l(&global_mutex);
IgnoreObjectResult res = IgnoreObjectLocked(p);
- if (res == kIgnoreObjectInvalid && flags()->verbosity >= 2)
- Report("__lsan_ignore_object(): no heap object found at %p", p);
- if (res == kIgnoreObjectAlreadyIgnored && flags()->verbosity >= 2)
- Report("__lsan_ignore_object(): "
+ if (res == kIgnoreObjectInvalid)
+ VReport(1, "__lsan_ignore_object(): no heap object found at %p", p);
+ if (res == kIgnoreObjectAlreadyIgnored)
+ VReport(1, "__lsan_ignore_object(): "
"heap object at %p is already being ignored\n", p);
- if (res == kIgnoreObjectSuccess && flags()->verbosity >= 3)
- Report("__lsan_ignore_object(): ignoring heap object at %p\n", p);
+ if (res == kIgnoreObjectSuccess)
+ VReport(1, "__lsan_ignore_object(): ignoring heap object at %p\n", p);
+#endif // CAN_SANITIZE_LEAKS
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __lsan_register_root_region(const void *begin, uptr size) {
+#if CAN_SANITIZE_LEAKS
+ BlockingMutexLock l(&global_mutex);
+ CHECK(root_regions);
+ RootRegion region = {begin, size};
+ root_regions->push_back(region);
+ VReport(1, "Registered root region at %p of size %llu\n", begin, size);
+#endif // CAN_SANITIZE_LEAKS
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __lsan_unregister_root_region(const void *begin, uptr size) {
+#if CAN_SANITIZE_LEAKS
+ BlockingMutexLock l(&global_mutex);
+ CHECK(root_regions);
+ bool removed = false;
+ for (uptr i = 0; i < root_regions->size(); i++) {
+ RootRegion region = (*root_regions)[i];
+ if (region.begin == begin && region.size == size) {
+ removed = true;
+ uptr last_index = root_regions->size() - 1;
+ (*root_regions)[i] = (*root_regions)[last_index];
+ root_regions->pop_back();
+ VReport(1, "Unregistered root region at %p of size %llu\n", begin, size);
+ break;
+ }
+ }
+ if (!removed) {
+ Report(
+ "__lsan_unregister_root_region(): region at %p of size %llu has not "
+ "been registered.\n",
+ begin, size);
+ Die();
+ }
#endif // CAN_SANITIZE_LEAKS
}
diff --git a/libsanitizer/lsan/lsan_common.h b/libsanitizer/lsan/lsan_common.h
index 5d9b4eb62e1..0c84d414be2 100644
--- a/libsanitizer/lsan/lsan_common.h
+++ b/libsanitizer/lsan/lsan_common.h
@@ -19,7 +19,7 @@
#include "sanitizer_common/sanitizer_platform.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
-#if SANITIZER_LINUX && defined(__x86_64__)
+#if SANITIZER_LINUX && defined(__x86_64__) && (SANITIZER_WORDSIZE == 64)
#define CAN_SANITIZE_LEAKS 1
#else
#define CAN_SANITIZE_LEAKS 0
@@ -49,6 +49,8 @@ struct Flags {
int max_leaks;
// If nonzero kill the process with this exit code upon finding leaks.
int exitcode;
+ // Print matched suppressions after leak checking.
+ bool print_suppressions;
// Suppressions file name.
const char* suppressions;
@@ -61,12 +63,13 @@ struct Flags {
bool use_registers;
// TLS and thread-specific storage.
bool use_tls;
+ // Regions added via __lsan_register_root_region().
+ bool use_root_regions;
// Consider unaligned pointers valid.
bool use_unaligned;
-
- // User-visible verbosity.
- int verbosity;
+ // Consider pointers found in poisoned memory to be valid.
+ bool use_poisoned;
// Debug logging.
bool log_pointers;
@@ -77,6 +80,7 @@ extern Flags lsan_flags;
inline Flags *flags() { return &lsan_flags; }
struct Leak {
+ u32 id;
uptr hit_count;
uptr total_size;
u32 stack_trace_id;
@@ -84,17 +88,31 @@ struct Leak {
bool is_suppressed;
};
+struct LeakedObject {
+ u32 leak_id;
+ uptr addr;
+ uptr size;
+};
+
// Aggregates leaks by stack trace prefix.
class LeakReport {
public:
- LeakReport() : leaks_(1) {}
- void Add(u32 stack_trace_id, uptr leaked_size, ChunkTag tag);
- void PrintLargest(uptr max_leaks);
+ LeakReport() : next_id_(0), leaks_(1), leaked_objects_(1) {}
+ void AddLeakedChunk(uptr chunk, u32 stack_trace_id, uptr leaked_size,
+ ChunkTag tag);
+ void ReportTopLeaks(uptr max_leaks);
void PrintSummary();
- bool IsEmpty() { return leaks_.size() == 0; }
- uptr ApplySuppressions();
+ void ApplySuppressions();
+ uptr UnsuppressedLeakCount();
+
+
private:
+ void PrintReportForLeak(uptr index);
+ void PrintLeakedObjectsForLeak(uptr index);
+
+ u32 next_id_;
InternalMmapVector<Leak> leaks_;
+ InternalMmapVector<LeakedObject> leaked_objects_;
};
typedef InternalMmapVector<uptr> Frontier;
@@ -119,6 +137,15 @@ void InitCommonLsan();
void DoLeakCheck();
bool DisabledInThisThread();
+// Special case for "new T[0]" where T is a type with DTOR.
+// new T[0] will allocate one word for the array size (0) and store a pointer
+// to the end of allocated chunk.
+inline bool IsSpecialCaseOfOperatorNew0(uptr chunk_beg, uptr chunk_size,
+ uptr addr) {
+ return chunk_size == sizeof(uptr) && chunk_beg + chunk_size == addr &&
+ *reinterpret_cast<uptr *>(chunk_beg) == 0;
+}
+
// The following must be implemented in the parent tool.
void ForEachChunk(ForEachChunkCallback callback, void *arg);
@@ -127,6 +154,8 @@ void GetAllocatorGlobalRange(uptr *begin, uptr *end);
// Wrappers for allocator's ForceLock()/ForceUnlock().
void LockAllocator();
void UnlockAllocator();
+// Returns true if [addr, addr + sizeof(void *)) is poisoned.
+bool WordIsPoisoned(uptr addr);
// Wrappers for ThreadRegistry access.
void LockThreadRegistry();
void UnlockThreadRegistry();
diff --git a/libsanitizer/lsan/lsan_common_linux.cc b/libsanitizer/lsan/lsan_common_linux.cc
index 80d2459a9ad..c318fbc4c3b 100644
--- a/libsanitizer/lsan/lsan_common_linux.cc
+++ b/libsanitizer/lsan/lsan_common_linux.cc
@@ -17,6 +17,7 @@
#include <link.h>
#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_linux.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
@@ -41,11 +42,11 @@ void InitializePlatformSpecificModules() {
return;
}
if (num_matches == 0)
- Report("LeakSanitizer: Dynamic linker not found. "
- "TLS will not be handled correctly.\n");
+ VReport(1, "LeakSanitizer: Dynamic linker not found. "
+ "TLS will not be handled correctly.\n");
else if (num_matches > 1)
- Report("LeakSanitizer: Multiple modules match \"%s\". "
- "TLS will not be handled correctly.\n", kLinkerName);
+ VReport(1, "LeakSanitizer: Multiple modules match \"%s\". "
+ "TLS will not be handled correctly.\n", kLinkerName);
linker = 0;
}
@@ -81,6 +82,7 @@ static int ProcessGlobalRegionsCallback(struct dl_phdr_info *info, size_t size,
// Scans global variables for heap pointers.
void ProcessGlobalRegions(Frontier *frontier) {
+ if (!flags()->use_globals) return;
// FIXME: dl_iterate_phdr acquires a linker lock, so we run a risk of
// deadlocking by running this under StopTheWorld. However, the lock is
// reentrant, so we should be able to fix this by acquiring the lock before
@@ -127,6 +129,21 @@ static void ProcessPlatformSpecificAllocationsCb(uptr chunk, void *arg) {
// Handles dynamically allocated TLS blocks by treating all chunks allocated
// from ld-linux.so as reachable.
+// Dynamic TLS blocks contain the TLS variables of dynamically loaded modules.
+// They are allocated with a __libc_memalign() call in allocate_and_init()
+// (elf/dl-tls.c). Glibc won't tell us the address ranges occupied by those
+// blocks, but we can make sure they come from our own allocator by intercepting
+// __libc_memalign(). On top of that, there is no easy way to reach them. Their
+// addresses are stored in a dynamically allocated array (the DTV) which is
+// referenced from the static TLS. Unfortunately, we can't just rely on the DTV
+// being reachable from the static TLS, and the dynamic TLS being reachable from
+// the DTV. This is because the initial DTV is allocated before our interception
+// mechanism kicks in, and thus we don't recognize it as allocated memory. We
+// can't special-case it either, since we don't know its size.
+// Our solution is to include in the root set all allocations made from
+// ld-linux.so (which is where allocate_and_init() is implemented). This is
+// guaranteed to include all dynamic TLS blocks (and possibly other allocations
+// which we don't care about).
void ProcessPlatformSpecificAllocations(Frontier *frontier) {
if (!flags()->use_tls) return;
if (!linker) return;
diff --git a/libsanitizer/lsan/lsan_interceptors.cc b/libsanitizer/lsan/lsan_interceptors.cc
index 1940902ef83..dfaad325672 100644
--- a/libsanitizer/lsan/lsan_interceptors.cc
+++ b/libsanitizer/lsan/lsan_interceptors.cc
@@ -10,11 +10,11 @@
//
//===----------------------------------------------------------------------===//
-#include "interception/interception.h"
#include "sanitizer_common/sanitizer_allocator.h"
#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_interception.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_linux.h"
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
@@ -32,19 +32,19 @@ int pthread_key_create(unsigned *key, void (*destructor)(void* v));
int pthread_setspecific(unsigned key, const void *v);
}
-#define GET_STACK_TRACE \
- StackTrace stack; \
- { \
- uptr stack_top = 0, stack_bottom = 0; \
- ThreadContext *t; \
- bool fast = common_flags()->fast_unwind_on_malloc; \
- if (fast && (t = CurrentThreadContext())) { \
- stack_top = t->stack_end(); \
- stack_bottom = t->stack_begin(); \
- } \
- stack.Unwind(__sanitizer::common_flags()->malloc_context_size, \
- StackTrace::GetCurrentPc(), \
- GET_CURRENT_FRAME(), stack_top, stack_bottom, fast); \
+#define GET_STACK_TRACE \
+ StackTrace stack; \
+ { \
+ uptr stack_top = 0, stack_bottom = 0; \
+ ThreadContext *t; \
+ bool fast = common_flags()->fast_unwind_on_malloc; \
+ if (fast && (t = CurrentThreadContext())) { \
+ stack_top = t->stack_end(); \
+ stack_bottom = t->stack_begin(); \
+ } \
+ stack.Unwind(__sanitizer::common_flags()->malloc_context_size, \
+ StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), 0, \
+ stack_top, stack_bottom, fast); \
}
#define ENSURE_LSAN_INITED do { \
@@ -150,7 +150,7 @@ INTERCEPTOR(void*, pvalloc, uptr size) {
return Allocate(stack, size, GetPageSizeCached(), kAlwaysClearMemory);
}
-INTERCEPTOR(void, cfree, void *p) ALIAS("free");
+INTERCEPTOR(void, cfree, void *p) ALIAS(WRAPPER_NAME(free));
#define OPERATOR_NEW_BODY \
ENSURE_LSAN_INITED; \
@@ -171,9 +171,9 @@ void *operator new[](uptr size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
Deallocate(ptr);
INTERCEPTOR_ATTRIBUTE
-void operator delete(void *ptr) { OPERATOR_DELETE_BODY; }
+void operator delete(void *ptr) throw() { OPERATOR_DELETE_BODY; }
INTERCEPTOR_ATTRIBUTE
-void operator delete[](void *ptr) { OPERATOR_DELETE_BODY; }
+void operator delete[](void *ptr) throw() { OPERATOR_DELETE_BODY; }
INTERCEPTOR_ATTRIBUTE
void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
INTERCEPTOR_ATTRIBUTE
@@ -183,7 +183,8 @@ void operator delete[](void *ptr, std::nothrow_t const &) {
// We need this to intercept the __libc_memalign calls that are used to
// allocate dynamic TLS space in ld-linux.so.
-INTERCEPTOR(void *, __libc_memalign, uptr align, uptr s) ALIAS("memalign");
+INTERCEPTOR(void *, __libc_memalign, uptr align, uptr s)
+ ALIAS(WRAPPER_NAME(memalign));
///// Thread initialization and finalization. /////
@@ -236,7 +237,7 @@ INTERCEPTOR(int, pthread_create, void *th, void *attr,
pthread_attr_init(&myattr);
attr = &myattr;
}
- AdjustStackSizeLinux(attr);
+ AdjustStackSize(attr);
int detached = 0;
pthread_attr_getdetachstate(attr, &detached);
ThreadParam p;
diff --git a/libsanitizer/sanitizer_common/Makefile.am b/libsanitizer/sanitizer_common/Makefile.am
index 8e9038dc8cf..089c6936e2a 100644
--- a/libsanitizer/sanitizer_common/Makefile.am
+++ b/libsanitizer/sanitizer_common/Makefile.am
@@ -22,6 +22,8 @@ sanitizer_common_files = \
sanitizer_common.cc \
sanitizer_common_libcdep.cc \
sanitizer_coverage.cc \
+ sanitizer_deadlock_detector1.cc \
+ sanitizer_deadlock_detector2.cc \
sanitizer_flags.cc \
sanitizer_libc.cc \
sanitizer_libignore.cc \
@@ -30,20 +32,23 @@ sanitizer_common_files = \
sanitizer_mac.cc \
sanitizer_platform_limits_linux.cc \
sanitizer_platform_limits_posix.cc \
- sanitizer_posix_libcdep.cc \
sanitizer_posix.cc \
+ sanitizer_posix_libcdep.cc \
sanitizer_printf.cc \
+ sanitizer_procmaps_linux.cc \
+ sanitizer_procmaps_mac.cc \
sanitizer_stackdepot.cc \
sanitizer_stacktrace.cc \
sanitizer_stacktrace_libcdep.cc \
sanitizer_stoptheworld_linux_libcdep.cc \
sanitizer_suppressions.cc \
- sanitizer_symbolizer_posix_libcdep.cc \
- sanitizer_symbolizer_win.cc \
sanitizer_symbolizer.cc \
sanitizer_symbolizer_libbacktrace.cc \
sanitizer_symbolizer_libcdep.cc \
+ sanitizer_symbolizer_posix_libcdep.cc \
+ sanitizer_symbolizer_win.cc \
sanitizer_thread_registry.cc \
+ sanitizer_tls_get_addr.cc \
sanitizer_win.cc
libsanitizer_common_la_SOURCES = $(sanitizer_common_files)
diff --git a/libsanitizer/sanitizer_common/Makefile.in b/libsanitizer/sanitizer_common/Makefile.in
index e9fd115e976..1ea631590c0 100644
--- a/libsanitizer/sanitizer_common/Makefile.in
+++ b/libsanitizer/sanitizer_common/Makefile.in
@@ -65,19 +65,23 @@ LTLIBRARIES = $(noinst_LTLIBRARIES)
libsanitizer_common_la_LIBADD =
am__objects_1 = sanitizer_allocator.lo sanitizer_common.lo \
sanitizer_common_libcdep.lo sanitizer_coverage.lo \
- sanitizer_flags.lo sanitizer_libc.lo sanitizer_libignore.lo \
- sanitizer_linux.lo sanitizer_linux_libcdep.lo sanitizer_mac.lo \
+ sanitizer_deadlock_detector1.lo \
+ sanitizer_deadlock_detector2.lo sanitizer_flags.lo \
+ sanitizer_libc.lo sanitizer_libignore.lo sanitizer_linux.lo \
+ sanitizer_linux_libcdep.lo sanitizer_mac.lo \
sanitizer_platform_limits_linux.lo \
- sanitizer_platform_limits_posix.lo sanitizer_posix_libcdep.lo \
- sanitizer_posix.lo sanitizer_printf.lo sanitizer_stackdepot.lo \
- sanitizer_stacktrace.lo sanitizer_stacktrace_libcdep.lo \
+ sanitizer_platform_limits_posix.lo sanitizer_posix.lo \
+ sanitizer_posix_libcdep.lo sanitizer_printf.lo \
+ sanitizer_procmaps_linux.lo sanitizer_procmaps_mac.lo \
+ sanitizer_stackdepot.lo sanitizer_stacktrace.lo \
+ sanitizer_stacktrace_libcdep.lo \
sanitizer_stoptheworld_linux_libcdep.lo \
- sanitizer_suppressions.lo \
- sanitizer_symbolizer_posix_libcdep.lo \
- sanitizer_symbolizer_win.lo sanitizer_symbolizer.lo \
+ sanitizer_suppressions.lo sanitizer_symbolizer.lo \
sanitizer_symbolizer_libbacktrace.lo \
- sanitizer_symbolizer_libcdep.lo sanitizer_thread_registry.lo \
- sanitizer_win.lo
+ sanitizer_symbolizer_libcdep.lo \
+ sanitizer_symbolizer_posix_libcdep.lo \
+ sanitizer_symbolizer_win.lo sanitizer_thread_registry.lo \
+ sanitizer_tls_get_addr.lo sanitizer_win.lo
am_libsanitizer_common_la_OBJECTS = $(am__objects_1)
libsanitizer_common_la_OBJECTS = $(am_libsanitizer_common_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
@@ -253,6 +257,8 @@ sanitizer_common_files = \
sanitizer_common.cc \
sanitizer_common_libcdep.cc \
sanitizer_coverage.cc \
+ sanitizer_deadlock_detector1.cc \
+ sanitizer_deadlock_detector2.cc \
sanitizer_flags.cc \
sanitizer_libc.cc \
sanitizer_libignore.cc \
@@ -261,20 +267,23 @@ sanitizer_common_files = \
sanitizer_mac.cc \
sanitizer_platform_limits_linux.cc \
sanitizer_platform_limits_posix.cc \
- sanitizer_posix_libcdep.cc \
sanitizer_posix.cc \
+ sanitizer_posix_libcdep.cc \
sanitizer_printf.cc \
+ sanitizer_procmaps_linux.cc \
+ sanitizer_procmaps_mac.cc \
sanitizer_stackdepot.cc \
sanitizer_stacktrace.cc \
sanitizer_stacktrace_libcdep.cc \
sanitizer_stoptheworld_linux_libcdep.cc \
sanitizer_suppressions.cc \
- sanitizer_symbolizer_posix_libcdep.cc \
- sanitizer_symbolizer_win.cc \
sanitizer_symbolizer.cc \
sanitizer_symbolizer_libbacktrace.cc \
sanitizer_symbolizer_libcdep.cc \
+ sanitizer_symbolizer_posix_libcdep.cc \
+ sanitizer_symbolizer_win.cc \
sanitizer_thread_registry.cc \
+ sanitizer_tls_get_addr.cc \
sanitizer_win.cc
libsanitizer_common_la_SOURCES = $(sanitizer_common_files)
@@ -374,6 +383,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_common.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_common_libcdep.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_coverage.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_deadlock_detector1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_deadlock_detector2.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_flags.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_libc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_libignore.Plo@am__quote@
@@ -385,6 +396,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_posix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_posix_libcdep.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_printf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_procmaps_linux.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_procmaps_mac.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_stackdepot.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_stacktrace.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_stacktrace_libcdep.Plo@am__quote@
@@ -396,6 +409,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_symbolizer_posix_libcdep.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_symbolizer_win.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_thread_registry.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_tls_get_addr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_win.Plo@am__quote@
.cc.o:
diff --git a/libsanitizer/sanitizer_common/sanitizer_addrhashmap.h b/libsanitizer/sanitizer_common/sanitizer_addrhashmap.h
new file mode 100644
index 00000000000..9e15d51c66c
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_addrhashmap.h
@@ -0,0 +1,340 @@
+//===-- sanitizer_addrhashmap.h ---------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Concurrent uptr->T hashmap.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ADDRHASHMAP_H
+#define SANITIZER_ADDRHASHMAP_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_mutex.h"
+#include "sanitizer_atomic.h"
+#include "sanitizer_allocator_internal.h"
+
+namespace __sanitizer {
+
+// Concurrent uptr->T hashmap.
+// T must be a POD type, kSize is preferably a prime but can be any number.
+// Usage example:
+//
+// typedef AddrHashMap<uptr, 11> Map;
+// Map m;
+// {
+// Map::Handle h(&m, addr);
+// use h.operator->() to access the data
+// if h.created() then the element was just created, and the current thread
+// has exclusive access to it
+// otherwise the current thread has only read access to the data
+// }
+// {
+// Map::Handle h(&m, addr, true);
+// this will remove the data from the map in Handle dtor
+// the current thread has exclusive access to the data
+// if !h.exists() then the element never existed
+// }
+template<typename T, uptr kSize>
+class AddrHashMap {
+ private:
+ struct Cell {
+ atomic_uintptr_t addr;
+ T val;
+ };
+
+ struct AddBucket {
+ uptr cap;
+ uptr size;
+ Cell cells[1]; // variable len
+ };
+
+ static const uptr kBucketSize = 3;
+
+ struct Bucket {
+ RWMutex mtx;
+ atomic_uintptr_t add;
+ Cell cells[kBucketSize];
+ };
+
+ public:
+ AddrHashMap();
+
+ class Handle {
+ public:
+ Handle(AddrHashMap<T, kSize> *map, uptr addr);
+ Handle(AddrHashMap<T, kSize> *map, uptr addr, bool remove);
+ Handle(AddrHashMap<T, kSize> *map, uptr addr, bool remove, bool create);
+
+ ~Handle();
+ T *operator->();
+ bool created() const;
+ bool exists() const;
+
+ private:
+ friend AddrHashMap<T, kSize>;
+ AddrHashMap<T, kSize> *map_;
+ Bucket *bucket_;
+ Cell *cell_;
+ uptr addr_;
+ uptr addidx_;
+ bool created_;
+ bool remove_;
+ bool create_;
+ };
+
+ private:
+ friend class Handle;
+ Bucket *table_;
+
+ void acquire(Handle *h);
+ void release(Handle *h);
+ uptr calcHash(uptr addr);
+};
+
+template<typename T, uptr kSize>
+AddrHashMap<T, kSize>::Handle::Handle(AddrHashMap<T, kSize> *map, uptr addr) {
+ map_ = map;
+ addr_ = addr;
+ remove_ = false;
+ create_ = true;
+ map_->acquire(this);
+}
+
+template<typename T, uptr kSize>
+AddrHashMap<T, kSize>::Handle::Handle(AddrHashMap<T, kSize> *map, uptr addr,
+ bool remove) {
+ map_ = map;
+ addr_ = addr;
+ remove_ = remove;
+ create_ = true;
+ map_->acquire(this);
+}
+
+template<typename T, uptr kSize>
+AddrHashMap<T, kSize>::Handle::Handle(AddrHashMap<T, kSize> *map, uptr addr,
+ bool remove, bool create) {
+ map_ = map;
+ addr_ = addr;
+ remove_ = remove;
+ create_ = create;
+ map_->acquire(this);
+}
+
+template<typename T, uptr kSize>
+AddrHashMap<T, kSize>::Handle::~Handle() {
+ map_->release(this);
+}
+
+template <typename T, uptr kSize>
+T *AddrHashMap<T, kSize>::Handle::operator->() {
+ return &cell_->val;
+}
+
+template<typename T, uptr kSize>
+bool AddrHashMap<T, kSize>::Handle::created() const {
+ return created_;
+}
+
+template<typename T, uptr kSize>
+bool AddrHashMap<T, kSize>::Handle::exists() const {
+ return cell_ != 0;
+}
+
+template<typename T, uptr kSize>
+AddrHashMap<T, kSize>::AddrHashMap() {
+ table_ = (Bucket*)MmapOrDie(kSize * sizeof(table_[0]), "AddrHashMap");
+}
+
+template<typename T, uptr kSize>
+void AddrHashMap<T, kSize>::acquire(Handle *h) {
+ uptr addr = h->addr_;
+ uptr hash = calcHash(addr);
+ Bucket *b = &table_[hash];
+
+ h->created_ = false;
+ h->addidx_ = -1U;
+ h->bucket_ = b;
+ h->cell_ = 0;
+
+ // If we want to remove the element, we need exclusive access to the bucket,
+ // so skip the lock-free phase.
+ if (h->remove_)
+ goto locked;
+
+ retry:
+ // First try to find an existing element w/o read mutex.
+ CHECK(!h->remove_);
+ // Check the embed cells.
+ for (uptr i = 0; i < kBucketSize; i++) {
+ Cell *c = &b->cells[i];
+ uptr addr1 = atomic_load(&c->addr, memory_order_acquire);
+ if (addr1 == addr) {
+ h->cell_ = c;
+ return;
+ }
+ }
+
+ // Check the add cells with read lock.
+ if (atomic_load(&b->add, memory_order_relaxed)) {
+ b->mtx.ReadLock();
+ AddBucket *add = (AddBucket*)atomic_load(&b->add, memory_order_relaxed);
+ for (uptr i = 0; i < add->size; i++) {
+ Cell *c = &add->cells[i];
+ uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
+ if (addr1 == addr) {
+ h->addidx_ = i;
+ h->cell_ = c;
+ return;
+ }
+ }
+ b->mtx.ReadUnlock();
+ }
+
+ locked:
+ // Re-check existence under write lock.
+ // Embed cells.
+ b->mtx.Lock();
+ for (uptr i = 0; i < kBucketSize; i++) {
+ Cell *c = &b->cells[i];
+ uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
+ if (addr1 == addr) {
+ if (h->remove_) {
+ h->cell_ = c;
+ return;
+ }
+ b->mtx.Unlock();
+ goto retry;
+ }
+ }
+
+ // Add cells.
+ AddBucket *add = (AddBucket*)atomic_load(&b->add, memory_order_relaxed);
+ if (add) {
+ for (uptr i = 0; i < add->size; i++) {
+ Cell *c = &add->cells[i];
+ uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
+ if (addr1 == addr) {
+ if (h->remove_) {
+ h->addidx_ = i;
+ h->cell_ = c;
+ return;
+ }
+ b->mtx.Unlock();
+ goto retry;
+ }
+ }
+ }
+
+ // The element does not exist, no need to create it if we want to remove.
+ if (h->remove_ || !h->create_) {
+ b->mtx.Unlock();
+ return;
+ }
+
+ // Now try to create it under the mutex.
+ h->created_ = true;
+ // See if we have a free embed cell.
+ for (uptr i = 0; i < kBucketSize; i++) {
+ Cell *c = &b->cells[i];
+ uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
+ if (addr1 == 0) {
+ h->cell_ = c;
+ return;
+ }
+ }
+
+ // Store in the add cells.
+ if (add == 0) {
+ // Allocate a new add array.
+ const uptr kInitSize = 64;
+ add = (AddBucket*)InternalAlloc(kInitSize);
+ internal_memset(add, 0, kInitSize);
+ add->cap = (kInitSize - sizeof(*add)) / sizeof(add->cells[0]) + 1;
+ add->size = 0;
+ atomic_store(&b->add, (uptr)add, memory_order_relaxed);
+ }
+ if (add->size == add->cap) {
+ // Grow existing add array.
+ uptr oldsize = sizeof(*add) + (add->cap - 1) * sizeof(add->cells[0]);
+ uptr newsize = oldsize * 2;
+ AddBucket *add1 = (AddBucket*)InternalAlloc(newsize);
+ internal_memset(add1, 0, newsize);
+ add1->cap = (newsize - sizeof(*add)) / sizeof(add->cells[0]) + 1;
+ add1->size = add->size;
+ internal_memcpy(add1->cells, add->cells, add->size * sizeof(add->cells[0]));
+ InternalFree(add);
+ atomic_store(&b->add, (uptr)add1, memory_order_relaxed);
+ add = add1;
+ }
+ // Store.
+ uptr i = add->size++;
+ Cell *c = &add->cells[i];
+ CHECK_EQ(atomic_load(&c->addr, memory_order_relaxed), 0);
+ h->addidx_ = i;
+ h->cell_ = c;
+}
+
+template<typename T, uptr kSize>
+void AddrHashMap<T, kSize>::release(Handle *h) {
+ if (h->cell_ == 0)
+ return;
+ Bucket *b = h->bucket_;
+ Cell *c = h->cell_;
+ uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
+ if (h->created_) {
+ // Denote completion of insertion.
+ CHECK_EQ(addr1, 0);
+ // After the following store, the element becomes available
+ // for lock-free reads.
+ atomic_store(&c->addr, h->addr_, memory_order_release);
+ b->mtx.Unlock();
+ } else if (h->remove_) {
+ // Denote that the cell is empty now.
+ CHECK_EQ(addr1, h->addr_);
+ atomic_store(&c->addr, 0, memory_order_release);
+ // See if we need to compact the bucket.
+ AddBucket *add = (AddBucket*)atomic_load(&b->add, memory_order_relaxed);
+ if (h->addidx_ == -1U) {
+ // Removed from embed array, move an add element into the freed cell.
+ if (add && add->size != 0) {
+ uptr last = --add->size;
+ Cell *c1 = &add->cells[last];
+ c->val = c1->val;
+ uptr addr1 = atomic_load(&c1->addr, memory_order_relaxed);
+ atomic_store(&c->addr, addr1, memory_order_release);
+ atomic_store(&c1->addr, 0, memory_order_release);
+ }
+ } else {
+ // Removed from add array, compact it.
+ uptr last = --add->size;
+ Cell *c1 = &add->cells[last];
+ if (c != c1) {
+ *c = *c1;
+ atomic_store(&c1->addr, 0, memory_order_relaxed);
+ }
+ }
+ if (add && add->size == 0) {
+ // FIXME(dvyukov): free add?
+ }
+ b->mtx.Unlock();
+ } else {
+ CHECK_EQ(addr1, h->addr_);
+ if (h->addidx_ != -1U)
+ b->mtx.ReadUnlock();
+ }
+}
+
+template<typename T, uptr kSize>
+uptr AddrHashMap<T, kSize>::calcHash(uptr addr) {
+ addr += addr << 10;
+ addr ^= addr >> 6;
+ return addr % kSize;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_ADDRHASHMAP_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_allocator.cc b/libsanitizer/sanitizer_common/sanitizer_allocator.cc
index 9d38e9429ac..f4e3af1b06a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_allocator.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_allocator.cc
@@ -17,7 +17,7 @@
namespace __sanitizer {
// ThreadSanitizer for Go uses libc malloc/free.
-#if defined(SANITIZER_GO)
+#if defined(SANITIZER_GO) || defined(SANITIZER_USE_MALLOC)
# if SANITIZER_LINUX && !SANITIZER_ANDROID
extern "C" void *__libc_malloc(uptr size);
extern "C" void __libc_free(void *ptr);
@@ -115,7 +115,7 @@ void *LowLevelAllocator::Allocate(uptr size) {
if (allocated_end_ - allocated_current_ < (sptr)size) {
uptr size_to_allocate = Max(size, GetPageSizeCached());
allocated_current_ =
- (char*)MmapOrDie(size_to_allocate, __FUNCTION__);
+ (char*)MmapOrDie(size_to_allocate, __func__);
allocated_end_ = allocated_current_ + size_to_allocate;
if (low_level_alloc_callback) {
low_level_alloc_callback((uptr)allocated_current_,
diff --git a/libsanitizer/sanitizer_common/sanitizer_allocator.h b/libsanitizer/sanitizer_common/sanitizer_allocator.h
index 8ba825f14ec..99be09ba9ba 100644
--- a/libsanitizer/sanitizer_common/sanitizer_allocator.h
+++ b/libsanitizer/sanitizer_common/sanitizer_allocator.h
@@ -196,14 +196,12 @@ template<class SizeClassAllocator> struct SizeClassAllocatorLocalCache;
// Memory allocator statistics
enum AllocatorStat {
- AllocatorStatMalloced,
- AllocatorStatFreed,
- AllocatorStatMmapped,
- AllocatorStatUnmapped,
+ AllocatorStatAllocated,
+ AllocatorStatMapped,
AllocatorStatCount
};
-typedef u64 AllocatorStatCounters[AllocatorStatCount];
+typedef uptr AllocatorStatCounters[AllocatorStatCount];
// Per-thread stats, live in per-thread cache.
class AllocatorStats {
@@ -212,16 +210,21 @@ class AllocatorStats {
internal_memset(this, 0, sizeof(*this));
}
- void Add(AllocatorStat i, u64 v) {
+ void Add(AllocatorStat i, uptr v) {
v += atomic_load(&stats_[i], memory_order_relaxed);
atomic_store(&stats_[i], v, memory_order_relaxed);
}
- void Set(AllocatorStat i, u64 v) {
+ void Sub(AllocatorStat i, uptr v) {
+ v = atomic_load(&stats_[i], memory_order_relaxed) - v;
atomic_store(&stats_[i], v, memory_order_relaxed);
}
- u64 Get(AllocatorStat i) const {
+ void Set(AllocatorStat i, uptr v) {
+ atomic_store(&stats_[i], v, memory_order_relaxed);
+ }
+
+ uptr Get(AllocatorStat i) const {
return atomic_load(&stats_[i], memory_order_relaxed);
}
@@ -229,7 +232,7 @@ class AllocatorStats {
friend class AllocatorGlobalStats;
AllocatorStats *next_;
AllocatorStats *prev_;
- atomic_uint64_t stats_[AllocatorStatCount];
+ atomic_uintptr_t stats_[AllocatorStatCount];
};
// Global stats, used for aggregation and querying.
@@ -258,7 +261,7 @@ class AllocatorGlobalStats : public AllocatorStats {
}
void Get(AllocatorStatCounters s) const {
- internal_memset(s, 0, AllocatorStatCount * sizeof(u64));
+ internal_memset(s, 0, AllocatorStatCount * sizeof(uptr));
SpinMutexLock l(&mu_);
const AllocatorStats *stats = this;
for (;;) {
@@ -268,6 +271,9 @@ class AllocatorGlobalStats : public AllocatorStats {
if (stats == this)
break;
}
+ // All stats must be positive.
+ for (int i = 0; i < AllocatorStatCount; i++)
+ s[i] = ((sptr)s[i]) > 0 ? s[i] : 1;
}
private:
@@ -520,7 +526,7 @@ class SizeClassAllocator64 {
map_size += kUserMapSize;
CHECK_GE(region->mapped_user + map_size, end_idx);
MapWithCallback(region_beg + region->mapped_user, map_size);
- stat->Add(AllocatorStatMmapped, map_size);
+ stat->Add(AllocatorStatMapped, map_size);
region->mapped_user += map_size;
}
uptr total_count = (region->mapped_user - beg_idx - size)
@@ -839,7 +845,7 @@ class SizeClassAllocator32 {
uptr res = reinterpret_cast<uptr>(MmapAlignedOrDie(kRegionSize, kRegionSize,
"SizeClassAllocator32"));
MapUnmapCallback().OnMap(res, kRegionSize);
- stat->Add(AllocatorStatMmapped, kRegionSize);
+ stat->Add(AllocatorStatMapped, kRegionSize);
CHECK_EQ(0U, (res & (kRegionSize - 1)));
possible_regions.set(ComputeRegionId(res), static_cast<u8>(class_id));
return res;
@@ -905,7 +911,7 @@ struct SizeClassAllocatorLocalCache {
void *Allocate(SizeClassAllocator *allocator, uptr class_id) {
CHECK_NE(class_id, 0UL);
CHECK_LT(class_id, kNumClasses);
- stats_.Add(AllocatorStatMalloced, SizeClassMap::Size(class_id));
+ stats_.Add(AllocatorStatAllocated, SizeClassMap::Size(class_id));
PerClass *c = &per_class_[class_id];
if (UNLIKELY(c->count == 0))
Refill(allocator, class_id);
@@ -920,7 +926,7 @@ struct SizeClassAllocatorLocalCache {
// If the first allocator call on a new thread is a deallocation, then
// max_count will be zero, leading to check failure.
InitCache();
- stats_.Add(AllocatorStatFreed, SizeClassMap::Size(class_id));
+ stats_.Sub(AllocatorStatAllocated, SizeClassMap::Size(class_id));
PerClass *c = &per_class_[class_id];
CHECK_NE(c->max_count, 0UL);
if (UNLIKELY(c->count == c->max_count))
@@ -1031,8 +1037,8 @@ class LargeMmapAllocator {
stats.currently_allocated += map_size;
stats.max_allocated = Max(stats.max_allocated, stats.currently_allocated);
stats.by_size_log[size_log]++;
- stat->Add(AllocatorStatMalloced, map_size);
- stat->Add(AllocatorStatMmapped, map_size);
+ stat->Add(AllocatorStatAllocated, map_size);
+ stat->Add(AllocatorStatMapped, map_size);
}
return reinterpret_cast<void*>(res);
}
@@ -1050,8 +1056,8 @@ class LargeMmapAllocator {
chunks_sorted_ = false;
stats.n_frees++;
stats.currently_allocated -= h->map_size;
- stat->Add(AllocatorStatFreed, h->map_size);
- stat->Add(AllocatorStatUnmapped, h->map_size);
+ stat->Sub(AllocatorStatAllocated, h->map_size);
+ stat->Sub(AllocatorStatMapped, h->map_size);
}
MapUnmapCallback().OnUnmap(h->map_beg, h->map_size);
UnmapOrDie(reinterpret_cast<void*>(h->map_beg), h->map_size);
diff --git a/libsanitizer/sanitizer_common/sanitizer_allocator_internal.h b/libsanitizer/sanitizer_common/sanitizer_allocator_internal.h
index efdb89e3682..74e4402f736 100644
--- a/libsanitizer/sanitizer_common/sanitizer_allocator_internal.h
+++ b/libsanitizer/sanitizer_common/sanitizer_allocator_internal.h
@@ -22,14 +22,13 @@ namespace __sanitizer {
typedef CompactSizeClassMap InternalSizeClassMap;
static const uptr kInternalAllocatorSpace = 0;
+static const u64 kInternalAllocatorSize = SANITIZER_MMAP_RANGE_SIZE;
#if SANITIZER_WORDSIZE == 32
-static const u64 kInternalAllocatorSize = (1ULL << 32);
static const uptr kInternalAllocatorRegionSizeLog = 20;
static const uptr kInternalAllocatorNumRegions =
kInternalAllocatorSize >> kInternalAllocatorRegionSizeLog;
typedef FlatByteMap<kInternalAllocatorNumRegions> ByteMap;
#else
-static const u64 kInternalAllocatorSize = (1ULL << 47);
static const uptr kInternalAllocatorRegionSizeLog = 24;
static const uptr kInternalAllocatorNumRegions =
kInternalAllocatorSize >> kInternalAllocatorRegionSizeLog;
@@ -46,10 +45,10 @@ typedef SizeClassAllocatorLocalCache<PrimaryInternalAllocator>
// LargeMmapAllocator.
struct CrashOnMapUnmap {
void OnMap(uptr p, uptr size) const {
- RAW_CHECK_MSG(0, "Unexpected mmap in InternalAllocator!");
+ RAW_CHECK_MSG(0, "Unexpected mmap in InternalAllocator!\n");
}
void OnUnmap(uptr p, uptr size) const {
- RAW_CHECK_MSG(0, "Unexpected munmap in InternalAllocator!");
+ RAW_CHECK_MSG(0, "Unexpected munmap in InternalAllocator!\n");
}
};
diff --git a/libsanitizer/sanitizer_common/sanitizer_atomic.h b/libsanitizer/sanitizer_common/sanitizer_atomic.h
index f2bf23588a4..6387664f63b 100644
--- a/libsanitizer/sanitizer_common/sanitizer_atomic.h
+++ b/libsanitizer/sanitizer_common/sanitizer_atomic.h
@@ -42,7 +42,8 @@ struct atomic_uint32_t {
struct atomic_uint64_t {
typedef u64 Type;
- volatile Type val_dont_use;
+ // On 32-bit platforms u64 is not necessary aligned on 8 bytes.
+ volatile ALIGNED(8) Type val_dont_use;
};
struct atomic_uintptr_t {
diff --git a/libsanitizer/sanitizer_common/sanitizer_atomic_clang.h b/libsanitizer/sanitizer_common/sanitizer_atomic_clang.h
index 88819e32a73..c600999e67a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_atomic_clang.h
+++ b/libsanitizer/sanitizer_common/sanitizer_atomic_clang.h
@@ -13,8 +13,26 @@
#ifndef SANITIZER_ATOMIC_CLANG_H
#define SANITIZER_ATOMIC_CLANG_H
+#if defined(__i386__) || defined(__x86_64__)
+# include "sanitizer_atomic_clang_x86.h"
+#else
+# include "sanitizer_atomic_clang_other.h"
+#endif
+
namespace __sanitizer {
+// We would like to just use compiler builtin atomic operations
+// for loads and stores, but they are mostly broken in clang:
+// - they lead to vastly inefficient code generation
+// (http://llvm.org/bugs/show_bug.cgi?id=17281)
+// - 64-bit atomic operations are not implemented on x86_32
+// (http://llvm.org/bugs/show_bug.cgi?id=15034)
+// - they are not implemented on ARM
+// error: undefined reference to '__atomic_load_4'
+
+// See http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
+// for mappings of the memory model to different processors.
+
INLINE void atomic_signal_fence(memory_order) {
__asm__ __volatile__("" ::: "memory");
}
@@ -23,59 +41,6 @@ INLINE void atomic_thread_fence(memory_order) {
__sync_synchronize();
}
-INLINE void proc_yield(int cnt) {
- __asm__ __volatile__("" ::: "memory");
-#if defined(__i386__) || defined(__x86_64__)
- for (int i = 0; i < cnt; i++)
- __asm__ __volatile__("pause");
-#endif
- __asm__ __volatile__("" ::: "memory");
-}
-
-template<typename T>
-INLINE typename T::Type atomic_load(
- const volatile T *a, memory_order mo) {
- DCHECK(mo & (memory_order_relaxed | memory_order_consume
- | memory_order_acquire | memory_order_seq_cst));
- DCHECK(!((uptr)a % sizeof(*a)));
- typename T::Type v;
- // FIXME:
- // 64-bit atomic operations are not atomic on 32-bit platforms.
- // The implementation lacks necessary memory fences on ARM/PPC.
- // We would like to use compiler builtin atomic operations,
- // but they are mostly broken:
- // - they lead to vastly inefficient code generation
- // (http://llvm.org/bugs/show_bug.cgi?id=17281)
- // - 64-bit atomic operations are not implemented on x86_32
- // (http://llvm.org/bugs/show_bug.cgi?id=15034)
- // - they are not implemented on ARM
- // error: undefined reference to '__atomic_load_4'
- if (mo == memory_order_relaxed) {
- v = a->val_dont_use;
- } else {
- atomic_signal_fence(memory_order_seq_cst);
- v = a->val_dont_use;
- atomic_signal_fence(memory_order_seq_cst);
- }
- return v;
-}
-
-template<typename T>
-INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
- DCHECK(mo & (memory_order_relaxed | memory_order_release
- | memory_order_seq_cst));
- DCHECK(!((uptr)a % sizeof(*a)));
- if (mo == memory_order_relaxed) {
- a->val_dont_use = v;
- } else {
- atomic_signal_fence(memory_order_seq_cst);
- a->val_dont_use = v;
- atomic_signal_fence(memory_order_seq_cst);
- }
- if (mo == memory_order_seq_cst)
- atomic_thread_fence(memory_order_seq_cst);
-}
-
template<typename T>
INLINE typename T::Type atomic_fetch_add(volatile T *a,
typename T::Type v, memory_order mo) {
diff --git a/libsanitizer/sanitizer_common/sanitizer_atomic_clang_other.h b/libsanitizer/sanitizer_common/sanitizer_atomic_clang_other.h
new file mode 100644
index 00000000000..c66c0992e1b
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_atomic_clang_other.h
@@ -0,0 +1,95 @@
+//===-- sanitizer_atomic_clang_other.h --------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+// Not intended for direct inclusion. Include sanitizer_atomic.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ATOMIC_CLANG_OTHER_H
+#define SANITIZER_ATOMIC_CLANG_OTHER_H
+
+namespace __sanitizer {
+
+INLINE void proc_yield(int cnt) {
+ __asm__ __volatile__("" ::: "memory");
+}
+
+template<typename T>
+INLINE typename T::Type atomic_load(
+ const volatile T *a, memory_order mo) {
+ DCHECK(mo & (memory_order_relaxed | memory_order_consume
+ | memory_order_acquire | memory_order_seq_cst));
+ DCHECK(!((uptr)a % sizeof(*a)));
+ typename T::Type v;
+
+ if (sizeof(*a) < 8 || sizeof(void*) == 8) {
+ // Assume that aligned loads are atomic.
+ if (mo == memory_order_relaxed) {
+ v = a->val_dont_use;
+ } else if (mo == memory_order_consume) {
+ // Assume that processor respects data dependencies
+ // (and that compiler won't break them).
+ __asm__ __volatile__("" ::: "memory");
+ v = a->val_dont_use;
+ __asm__ __volatile__("" ::: "memory");
+ } else if (mo == memory_order_acquire) {
+ __asm__ __volatile__("" ::: "memory");
+ v = a->val_dont_use;
+ __sync_synchronize();
+ } else { // seq_cst
+ // E.g. on POWER we need a hw fence even before the store.
+ __sync_synchronize();
+ v = a->val_dont_use;
+ __sync_synchronize();
+ }
+ } else {
+ // 64-bit load on 32-bit platform.
+ // Gross, but simple and reliable.
+ // Assume that it is not in read-only memory.
+ v = __sync_fetch_and_add(
+ const_cast<typename T::Type volatile *>(&a->val_dont_use), 0);
+ }
+ return v;
+}
+
+template<typename T>
+INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
+ DCHECK(mo & (memory_order_relaxed | memory_order_release
+ | memory_order_seq_cst));
+ DCHECK(!((uptr)a % sizeof(*a)));
+
+ if (sizeof(*a) < 8 || sizeof(void*) == 8) {
+ // Assume that aligned loads are atomic.
+ if (mo == memory_order_relaxed) {
+ a->val_dont_use = v;
+ } else if (mo == memory_order_release) {
+ __sync_synchronize();
+ a->val_dont_use = v;
+ __asm__ __volatile__("" ::: "memory");
+ } else { // seq_cst
+ __sync_synchronize();
+ a->val_dont_use = v;
+ __sync_synchronize();
+ }
+ } else {
+ // 64-bit store on 32-bit platform.
+ // Gross, but simple and reliable.
+ typename T::Type cmp = a->val_dont_use;
+ typename T::Type cur;
+ for (;;) {
+ cur = __sync_val_compare_and_swap(&a->val_dont_use, cmp, v);
+ if (cmp == v)
+ break;
+ cmp = cur;
+ }
+ }
+}
+
+} // namespace __sanitizer
+
+#endif // #ifndef SANITIZER_ATOMIC_CLANG_OTHER_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_atomic_clang_x86.h b/libsanitizer/sanitizer_common/sanitizer_atomic_clang_x86.h
new file mode 100644
index 00000000000..5df210eca79
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_atomic_clang_x86.h
@@ -0,0 +1,114 @@
+//===-- sanitizer_atomic_clang_x86.h ----------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+// Not intended for direct inclusion. Include sanitizer_atomic.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ATOMIC_CLANG_X86_H
+#define SANITIZER_ATOMIC_CLANG_X86_H
+
+namespace __sanitizer {
+
+INLINE void proc_yield(int cnt) {
+ __asm__ __volatile__("" ::: "memory");
+ for (int i = 0; i < cnt; i++)
+ __asm__ __volatile__("pause");
+ __asm__ __volatile__("" ::: "memory");
+}
+
+template<typename T>
+INLINE typename T::Type atomic_load(
+ const volatile T *a, memory_order mo) {
+ DCHECK(mo & (memory_order_relaxed | memory_order_consume
+ | memory_order_acquire | memory_order_seq_cst));
+ DCHECK(!((uptr)a % sizeof(*a)));
+ typename T::Type v;
+
+ if (sizeof(*a) < 8 || sizeof(void*) == 8) {
+ // Assume that aligned loads are atomic.
+ if (mo == memory_order_relaxed) {
+ v = a->val_dont_use;
+ } else if (mo == memory_order_consume) {
+ // Assume that processor respects data dependencies
+ // (and that compiler won't break them).
+ __asm__ __volatile__("" ::: "memory");
+ v = a->val_dont_use;
+ __asm__ __volatile__("" ::: "memory");
+ } else if (mo == memory_order_acquire) {
+ __asm__ __volatile__("" ::: "memory");
+ v = a->val_dont_use;
+ // On x86 loads are implicitly acquire.
+ __asm__ __volatile__("" ::: "memory");
+ } else { // seq_cst
+ // On x86 plain MOV is enough for seq_cst store.
+ __asm__ __volatile__("" ::: "memory");
+ v = a->val_dont_use;
+ __asm__ __volatile__("" ::: "memory");
+ }
+ } else {
+ // 64-bit load on 32-bit platform.
+ __asm__ __volatile__(
+ "movq %1, %%mm0;" // Use mmx reg for 64-bit atomic moves
+ "movq %%mm0, %0;" // (ptr could be read-only)
+ "emms;" // Empty mmx state/Reset FP regs
+ : "=m" (v)
+ : "m" (a->val_dont_use)
+ : // mark the FP stack and mmx registers as clobbered
+ "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)",
+#ifdef __MMX__
+ "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
+#endif // #ifdef __MMX__
+ "memory");
+ }
+ return v;
+}
+
+template<typename T>
+INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
+ DCHECK(mo & (memory_order_relaxed | memory_order_release
+ | memory_order_seq_cst));
+ DCHECK(!((uptr)a % sizeof(*a)));
+
+ if (sizeof(*a) < 8 || sizeof(void*) == 8) {
+ // Assume that aligned loads are atomic.
+ if (mo == memory_order_relaxed) {
+ a->val_dont_use = v;
+ } else if (mo == memory_order_release) {
+ // On x86 stores are implicitly release.
+ __asm__ __volatile__("" ::: "memory");
+ a->val_dont_use = v;
+ __asm__ __volatile__("" ::: "memory");
+ } else { // seq_cst
+ // On x86 stores are implicitly release.
+ __asm__ __volatile__("" ::: "memory");
+ a->val_dont_use = v;
+ __sync_synchronize();
+ }
+ } else {
+ // 64-bit store on 32-bit platform.
+ __asm__ __volatile__(
+ "movq %1, %%mm0;" // Use mmx reg for 64-bit atomic moves
+ "movq %%mm0, %0;"
+ "emms;" // Empty mmx state/Reset FP regs
+ : "=m" (a->val_dont_use)
+ : "m" (v)
+ : // mark the FP stack and mmx registers as clobbered
+ "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)",
+#ifdef __MMX__
+ "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
+#endif // #ifdef __MMX__
+ "memory");
+ if (mo == memory_order_seq_cst)
+ __sync_synchronize();
+ }
+}
+
+} // namespace __sanitizer
+
+#endif // #ifndef SANITIZER_ATOMIC_CLANG_X86_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_atomic_msvc.h b/libsanitizer/sanitizer_common/sanitizer_atomic_msvc.h
index dac7c19199b..7e18fa38748 100644
--- a/libsanitizer/sanitizer_common/sanitizer_atomic_msvc.h
+++ b/libsanitizer/sanitizer_common/sanitizer_atomic_msvc.h
@@ -22,8 +22,20 @@ extern "C" void _mm_pause();
extern "C" long _InterlockedExchangeAdd( // NOLINT
long volatile * Addend, long Value); // NOLINT
#pragma intrinsic(_InterlockedExchangeAdd)
+extern "C" short _InterlockedCompareExchange16( // NOLINT
+ short volatile *Destination, // NOLINT
+ short Exchange, short Comparand); // NOLINT
+#pragma intrinsic(_InterlockedCompareExchange16)
+extern "C"
+long long _InterlockedCompareExchange64( // NOLINT
+ long long volatile *Destination, // NOLINT
+ long long Exchange, long long Comparand); // NOLINT
+#pragma intrinsic(_InterlockedCompareExchange64)
#ifdef _WIN64
+extern "C" long long _InterlockedExchangeAdd64( // NOLINT
+ long long volatile * Addend, long long Value); // NOLINT
+#pragma intrinsic(_InterlockedExchangeAdd64)
extern "C" void *_InterlockedCompareExchangePointer(
void *volatile *Destination,
void *Exchange, void *Comparand);
@@ -106,6 +118,40 @@ INLINE u32 atomic_fetch_add(volatile atomic_uint32_t *a,
(volatile long*)&a->val_dont_use, (long)v); // NOLINT
}
+INLINE uptr atomic_fetch_add(volatile atomic_uintptr_t *a,
+ uptr v, memory_order mo) {
+ (void)mo;
+ DCHECK(!((uptr)a % sizeof(*a)));
+#ifdef _WIN64
+ return (uptr)_InterlockedExchangeAdd64(
+ (volatile long long*)&a->val_dont_use, (long long)v); // NOLINT
+#else
+ return (uptr)_InterlockedExchangeAdd(
+ (volatile long*)&a->val_dont_use, (long)v); // NOLINT
+#endif
+}
+
+INLINE u32 atomic_fetch_sub(volatile atomic_uint32_t *a,
+ u32 v, memory_order mo) {
+ (void)mo;
+ DCHECK(!((uptr)a % sizeof(*a)));
+ return (u32)_InterlockedExchangeAdd(
+ (volatile long*)&a->val_dont_use, -(long)v); // NOLINT
+}
+
+INLINE uptr atomic_fetch_sub(volatile atomic_uintptr_t *a,
+ uptr v, memory_order mo) {
+ (void)mo;
+ DCHECK(!((uptr)a % sizeof(*a)));
+#ifdef _WIN64
+ return (uptr)_InterlockedExchangeAdd64(
+ (volatile long long*)&a->val_dont_use, -(long long)v); // NOLINT
+#else
+ return (uptr)_InterlockedExchangeAdd(
+ (volatile long*)&a->val_dont_use, -(long)v); // NOLINT
+#endif
+}
+
INLINE u8 atomic_exchange(volatile atomic_uint8_t *a,
u8 v, memory_order mo) {
(void)mo;
@@ -166,6 +212,45 @@ INLINE bool atomic_compare_exchange_strong(volatile atomic_uintptr_t *a,
return false;
}
+INLINE bool atomic_compare_exchange_strong(volatile atomic_uint16_t *a,
+ u16 *cmp,
+ u16 xchg,
+ memory_order mo) {
+ u16 cmpv = *cmp;
+ u16 prev = (u16)_InterlockedCompareExchange16(
+ (volatile short*)&a->val_dont_use, (short)xchg, (short)cmpv);
+ if (prev == cmpv)
+ return true;
+ *cmp = prev;
+ return false;
+}
+
+INLINE bool atomic_compare_exchange_strong(volatile atomic_uint32_t *a,
+ u32 *cmp,
+ u32 xchg,
+ memory_order mo) {
+ u32 cmpv = *cmp;
+ u32 prev = (u32)_InterlockedCompareExchange(
+ (volatile long*)&a->val_dont_use, (long)xchg, (long)cmpv);
+ if (prev == cmpv)
+ return true;
+ *cmp = prev;
+ return false;
+}
+
+INLINE bool atomic_compare_exchange_strong(volatile atomic_uint64_t *a,
+ u64 *cmp,
+ u64 xchg,
+ memory_order mo) {
+ u64 cmpv = *cmp;
+ u64 prev = (u64)_InterlockedCompareExchange64(
+ (volatile long long*)&a->val_dont_use, (long long)xchg, (long long)cmpv);
+ if (prev == cmpv)
+ return true;
+ *cmp = prev;
+ return false;
+}
+
template<typename T>
INLINE bool atomic_compare_exchange_weak(volatile T *a,
typename T::Type *cmp,
diff --git a/libsanitizer/sanitizer_common/sanitizer_bitvector.h b/libsanitizer/sanitizer_common/sanitizer_bitvector.h
new file mode 100644
index 00000000000..bb2872facde
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_bitvector.h
@@ -0,0 +1,349 @@
+//===-- sanitizer_bitvector.h -----------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Specializer BitVector implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_BITVECTOR_H
+#define SANITIZER_BITVECTOR_H
+
+#include "sanitizer_common.h"
+
+namespace __sanitizer {
+
+// Fixed size bit vector based on a single basic integer.
+template <class basic_int_t = uptr>
+class BasicBitVector {
+ public:
+ enum SizeEnum { kSize = sizeof(basic_int_t) * 8 };
+
+ uptr size() const { return kSize; }
+ // No CTOR.
+ void clear() { bits_ = 0; }
+ void setAll() { bits_ = ~(basic_int_t)0; }
+ bool empty() const { return bits_ == 0; }
+
+ // Returns true if the bit has changed from 0 to 1.
+ bool setBit(uptr idx) {
+ basic_int_t old = bits_;
+ bits_ |= mask(idx);
+ return bits_ != old;
+ }
+
+ // Returns true if the bit has changed from 1 to 0.
+ bool clearBit(uptr idx) {
+ basic_int_t old = bits_;
+ bits_ &= ~mask(idx);
+ return bits_ != old;
+ }
+
+ bool getBit(uptr idx) const { return (bits_ & mask(idx)) != 0; }
+
+ uptr getAndClearFirstOne() {
+ CHECK(!empty());
+ uptr idx = LeastSignificantSetBitIndex(bits_);
+ clearBit(idx);
+ return idx;
+ }
+
+ // Do "this |= v" and return whether new bits have been added.
+ bool setUnion(const BasicBitVector &v) {
+ basic_int_t old = bits_;
+ bits_ |= v.bits_;
+ return bits_ != old;
+ }
+
+ // Do "this &= v" and return whether any bits have been removed.
+ bool setIntersection(const BasicBitVector &v) {
+ basic_int_t old = bits_;
+ bits_ &= v.bits_;
+ return bits_ != old;
+ }
+
+ // Do "this &= ~v" and return whether any bits have been removed.
+ bool setDifference(const BasicBitVector &v) {
+ basic_int_t old = bits_;
+ bits_ &= ~v.bits_;
+ return bits_ != old;
+ }
+
+ void copyFrom(const BasicBitVector &v) { bits_ = v.bits_; }
+
+ // Returns true if 'this' intersects with 'v'.
+ bool intersectsWith(const BasicBitVector &v) const {
+ return (bits_ & v.bits_) != 0;
+ }
+
+ // for (BasicBitVector<>::Iterator it(bv); it.hasNext();) {
+ // uptr idx = it.next();
+ // use(idx);
+ // }
+ class Iterator {
+ public:
+ Iterator() { }
+ explicit Iterator(const BasicBitVector &bv) : bv_(bv) {}
+ bool hasNext() const { return !bv_.empty(); }
+ uptr next() { return bv_.getAndClearFirstOne(); }
+ void clear() { bv_.clear(); }
+ private:
+ BasicBitVector bv_;
+ };
+
+ private:
+ basic_int_t mask(uptr idx) const {
+ CHECK_LT(idx, size());
+ return (basic_int_t)1UL << idx;
+ }
+ basic_int_t bits_;
+};
+
+// Fixed size bit vector of (kLevel1Size*BV::kSize**2) bits.
+// The implementation is optimized for better performance on
+// sparse bit vectors, i.e. the those with few set bits.
+template <uptr kLevel1Size = 1, class BV = BasicBitVector<> >
+class TwoLevelBitVector {
+ // This is essentially a 2-level bit vector.
+ // Set bit in the first level BV indicates that there are set bits
+ // in the corresponding BV of the second level.
+ // This structure allows O(kLevel1Size) time for clear() and empty(),
+ // as well fast handling of sparse BVs.
+ public:
+ enum SizeEnum { kSize = BV::kSize * BV::kSize * kLevel1Size };
+ // No CTOR.
+
+ uptr size() const { return kSize; }
+
+ void clear() {
+ for (uptr i = 0; i < kLevel1Size; i++)
+ l1_[i].clear();
+ }
+
+ void setAll() {
+ for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
+ l1_[i0].setAll();
+ for (uptr i1 = 0; i1 < BV::kSize; i1++)
+ l2_[i0][i1].setAll();
+ }
+ }
+
+ bool empty() const {
+ for (uptr i = 0; i < kLevel1Size; i++)
+ if (!l1_[i].empty())
+ return false;
+ return true;
+ }
+
+ // Returns true if the bit has changed from 0 to 1.
+ bool setBit(uptr idx) {
+ check(idx);
+ uptr i0 = idx0(idx);
+ uptr i1 = idx1(idx);
+ uptr i2 = idx2(idx);
+ if (!l1_[i0].getBit(i1)) {
+ l1_[i0].setBit(i1);
+ l2_[i0][i1].clear();
+ }
+ bool res = l2_[i0][i1].setBit(i2);
+ // Printf("%s: %zd => %zd %zd %zd; %d\n", __func__,
+ // idx, i0, i1, i2, res);
+ return res;
+ }
+
+ bool clearBit(uptr idx) {
+ check(idx);
+ uptr i0 = idx0(idx);
+ uptr i1 = idx1(idx);
+ uptr i2 = idx2(idx);
+ bool res = false;
+ if (l1_[i0].getBit(i1)) {
+ res = l2_[i0][i1].clearBit(i2);
+ if (l2_[i0][i1].empty())
+ l1_[i0].clearBit(i1);
+ }
+ return res;
+ }
+
+ bool getBit(uptr idx) const {
+ check(idx);
+ uptr i0 = idx0(idx);
+ uptr i1 = idx1(idx);
+ uptr i2 = idx2(idx);
+ // Printf("%s: %zd => %zd %zd %zd\n", __func__, idx, i0, i1, i2);
+ return l1_[i0].getBit(i1) && l2_[i0][i1].getBit(i2);
+ }
+
+ uptr getAndClearFirstOne() {
+ for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
+ if (l1_[i0].empty()) continue;
+ uptr i1 = l1_[i0].getAndClearFirstOne();
+ uptr i2 = l2_[i0][i1].getAndClearFirstOne();
+ if (!l2_[i0][i1].empty())
+ l1_[i0].setBit(i1);
+ uptr res = i0 * BV::kSize * BV::kSize + i1 * BV::kSize + i2;
+ // Printf("getAndClearFirstOne: %zd %zd %zd => %zd\n", i0, i1, i2, res);
+ return res;
+ }
+ CHECK(0);
+ return 0;
+ }
+
+ // Do "this |= v" and return whether new bits have been added.
+ bool setUnion(const TwoLevelBitVector &v) {
+ bool res = false;
+ for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
+ BV t = v.l1_[i0];
+ while (!t.empty()) {
+ uptr i1 = t.getAndClearFirstOne();
+ if (l1_[i0].setBit(i1))
+ l2_[i0][i1].clear();
+ if (l2_[i0][i1].setUnion(v.l2_[i0][i1]))
+ res = true;
+ }
+ }
+ return res;
+ }
+
+ // Do "this &= v" and return whether any bits have been removed.
+ bool setIntersection(const TwoLevelBitVector &v) {
+ bool res = false;
+ for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
+ if (l1_[i0].setIntersection(v.l1_[i0]))
+ res = true;
+ if (!l1_[i0].empty()) {
+ BV t = l1_[i0];
+ while (!t.empty()) {
+ uptr i1 = t.getAndClearFirstOne();
+ if (l2_[i0][i1].setIntersection(v.l2_[i0][i1]))
+ res = true;
+ if (l2_[i0][i1].empty())
+ l1_[i0].clearBit(i1);
+ }
+ }
+ }
+ return res;
+ }
+
+ // Do "this &= ~v" and return whether any bits have been removed.
+ bool setDifference(const TwoLevelBitVector &v) {
+ bool res = false;
+ for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
+ BV t = l1_[i0];
+ t.setIntersection(v.l1_[i0]);
+ while (!t.empty()) {
+ uptr i1 = t.getAndClearFirstOne();
+ if (l2_[i0][i1].setDifference(v.l2_[i0][i1]))
+ res = true;
+ if (l2_[i0][i1].empty())
+ l1_[i0].clearBit(i1);
+ }
+ }
+ return res;
+ }
+
+ void copyFrom(const TwoLevelBitVector &v) {
+ clear();
+ setUnion(v);
+ }
+
+ // Returns true if 'this' intersects with 'v'.
+ bool intersectsWith(const TwoLevelBitVector &v) const {
+ for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
+ BV t = l1_[i0];
+ t.setIntersection(v.l1_[i0]);
+ while (!t.empty()) {
+ uptr i1 = t.getAndClearFirstOne();
+ if (!v.l1_[i0].getBit(i1)) continue;
+ if (l2_[i0][i1].intersectsWith(v.l2_[i0][i1]))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // for (TwoLevelBitVector<>::Iterator it(bv); it.hasNext();) {
+ // uptr idx = it.next();
+ // use(idx);
+ // }
+ class Iterator {
+ public:
+ Iterator() { }
+ explicit Iterator(const TwoLevelBitVector &bv) : bv_(bv), i0_(0), i1_(0) {
+ it1_.clear();
+ it2_.clear();
+ }
+
+ bool hasNext() const {
+ if (it1_.hasNext()) return true;
+ for (uptr i = i0_; i < kLevel1Size; i++)
+ if (!bv_.l1_[i].empty()) return true;
+ return false;
+ }
+
+ uptr next() {
+ // Printf("++++: %zd %zd; %d %d; size %zd\n", i0_, i1_, it1_.hasNext(),
+ // it2_.hasNext(), kSize);
+ if (!it1_.hasNext() && !it2_.hasNext()) {
+ for (; i0_ < kLevel1Size; i0_++) {
+ if (bv_.l1_[i0_].empty()) continue;
+ it1_ = typename BV::Iterator(bv_.l1_[i0_]);
+ // Printf("+i0: %zd %zd; %d %d; size %zd\n", i0_, i1_, it1_.hasNext(),
+ // it2_.hasNext(), kSize);
+ break;
+ }
+ }
+ if (!it2_.hasNext()) {
+ CHECK(it1_.hasNext());
+ i1_ = it1_.next();
+ it2_ = typename BV::Iterator(bv_.l2_[i0_][i1_]);
+ // Printf("++i1: %zd %zd; %d %d; size %zd\n", i0_, i1_, it1_.hasNext(),
+ // it2_.hasNext(), kSize);
+ }
+ CHECK(it2_.hasNext());
+ uptr i2 = it2_.next();
+ uptr res = i0_ * BV::kSize * BV::kSize + i1_ * BV::kSize + i2;
+ // Printf("+ret: %zd %zd; %d %d; size %zd; res: %zd\n", i0_, i1_,
+ // it1_.hasNext(), it2_.hasNext(), kSize, res);
+ if (!it1_.hasNext() && !it2_.hasNext())
+ i0_++;
+ return res;
+ }
+
+ private:
+ const TwoLevelBitVector &bv_;
+ uptr i0_, i1_;
+ typename BV::Iterator it1_, it2_;
+ };
+
+ private:
+ void check(uptr idx) const { CHECK_LE(idx, size()); }
+
+ uptr idx0(uptr idx) const {
+ uptr res = idx / (BV::kSize * BV::kSize);
+ CHECK_LE(res, kLevel1Size);
+ return res;
+ }
+
+ uptr idx1(uptr idx) const {
+ uptr res = (idx / BV::kSize) % BV::kSize;
+ CHECK_LE(res, BV::kSize);
+ return res;
+ }
+
+ uptr idx2(uptr idx) const {
+ uptr res = idx % BV::kSize;
+ CHECK_LE(res, BV::kSize);
+ return res;
+ }
+
+ BV l1_[kLevel1Size];
+ BV l2_[kLevel1Size][BV::kSize];
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_BITVECTOR_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_bvgraph.h b/libsanitizer/sanitizer_common/sanitizer_bvgraph.h
new file mode 100644
index 00000000000..6ef0e81e044
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_bvgraph.h
@@ -0,0 +1,163 @@
+//===-- sanitizer_bvgraph.h -------------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer runtime.
+// BVGraph -- a directed graph.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_BVGRAPH_H
+#define SANITIZER_BVGRAPH_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_bitvector.h"
+
+namespace __sanitizer {
+
+// Directed graph of fixed size implemented as an array of bit vectors.
+// Not thread-safe, all accesses should be protected by an external lock.
+template<class BV>
+class BVGraph {
+ public:
+ enum SizeEnum { kSize = BV::kSize };
+ uptr size() const { return kSize; }
+ // No CTOR.
+ void clear() {
+ for (uptr i = 0; i < size(); i++)
+ v[i].clear();
+ }
+
+ bool empty() const {
+ for (uptr i = 0; i < size(); i++)
+ if (!v[i].empty())
+ return false;
+ return true;
+ }
+
+ // Returns true if a new edge was added.
+ bool addEdge(uptr from, uptr to) {
+ check(from, to);
+ return v[from].setBit(to);
+ }
+
+ // Returns true if at least one new edge was added.
+ uptr addEdges(const BV &from, uptr to, uptr added_edges[],
+ uptr max_added_edges) {
+ uptr res = 0;
+ t1.copyFrom(from);
+ while (!t1.empty()) {
+ uptr node = t1.getAndClearFirstOne();
+ if (v[node].setBit(to))
+ if (res < max_added_edges)
+ added_edges[res++] = node;
+ }
+ return res;
+ }
+
+ // *EXPERIMENTAL*
+ // Returns true if an edge from=>to exist.
+ // This function does not use any global state except for 'this' itself,
+ // and thus can be called from different threads w/o locking.
+ // This would be racy.
+ // FIXME: investigate how much we can prove about this race being "benign".
+ bool hasEdge(uptr from, uptr to) { return v[from].getBit(to); }
+
+ // Returns true if the edge from=>to was removed.
+ bool removeEdge(uptr from, uptr to) {
+ return v[from].clearBit(to);
+ }
+
+ // Returns true if at least one edge *=>to was removed.
+ bool removeEdgesTo(const BV &to) {
+ bool res = 0;
+ for (uptr from = 0; from < size(); from++) {
+ if (v[from].setDifference(to))
+ res = true;
+ }
+ return res;
+ }
+
+ // Returns true if at least one edge from=>* was removed.
+ bool removeEdgesFrom(const BV &from) {
+ bool res = false;
+ t1.copyFrom(from);
+ while (!t1.empty()) {
+ uptr idx = t1.getAndClearFirstOne();
+ if (!v[idx].empty()) {
+ v[idx].clear();
+ res = true;
+ }
+ }
+ return res;
+ }
+
+ void removeEdgesFrom(uptr from) {
+ return v[from].clear();
+ }
+
+ bool hasEdge(uptr from, uptr to) const {
+ check(from, to);
+ return v[from].getBit(to);
+ }
+
+ // Returns true if there is a path from the node 'from'
+ // to any of the nodes in 'targets'.
+ bool isReachable(uptr from, const BV &targets) {
+ BV &to_visit = t1,
+ &visited = t2;
+ to_visit.copyFrom(v[from]);
+ visited.clear();
+ visited.setBit(from);
+ while (!to_visit.empty()) {
+ uptr idx = to_visit.getAndClearFirstOne();
+ if (visited.setBit(idx))
+ to_visit.setUnion(v[idx]);
+ }
+ return targets.intersectsWith(visited);
+ }
+
+ // Finds a path from 'from' to one of the nodes in 'target',
+ // stores up to 'path_size' items of the path into 'path',
+ // returns the path length, or 0 if there is no path of size 'path_size'.
+ uptr findPath(uptr from, const BV &targets, uptr *path, uptr path_size) {
+ if (path_size == 0)
+ return 0;
+ path[0] = from;
+ if (targets.getBit(from))
+ return 1;
+ // The function is recursive, so we don't want to create BV on stack.
+ // Instead of a getAndClearFirstOne loop we use the slower iterator.
+ for (typename BV::Iterator it(v[from]); it.hasNext(); ) {
+ uptr idx = it.next();
+ if (uptr res = findPath(idx, targets, path + 1, path_size - 1))
+ return res + 1;
+ }
+ return 0;
+ }
+
+ // Same as findPath, but finds a shortest path.
+ uptr findShortestPath(uptr from, const BV &targets, uptr *path,
+ uptr path_size) {
+ for (uptr p = 1; p <= path_size; p++)
+ if (findPath(from, targets, path, p) == p)
+ return p;
+ return 0;
+ }
+
+ private:
+ void check(uptr idx1, uptr idx2) const {
+ CHECK_LT(idx1, size());
+ CHECK_LT(idx2, size());
+ }
+ BV v[kSize];
+ // Keep temporary vectors here since we can not create large objects on stack.
+ BV t1, t2;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_BVGRAPH_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_common.cc b/libsanitizer/sanitizer_common/sanitizer_common.cc
index 0d93527aa5e..e76d4d558a1 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_common.cc
@@ -91,7 +91,7 @@ uptr ReadFileToBuffer(const char *file_name, char **buff,
if (internal_iserror(openrv)) return 0;
fd_t fd = openrv;
UnmapOrDie(*buff, *buff_size);
- *buff = (char*)MmapOrDie(size, __FUNCTION__);
+ *buff = (char*)MmapOrDie(size, __func__);
*buff_size = size;
// Read up to one page at a time.
read_len = 0;
@@ -200,11 +200,11 @@ void ReportErrorSummary(const char *error_type, StackTrace *stack) {
return;
AddressInfo ai;
#if !SANITIZER_GO
- if (stack->size > 0 && Symbolizer::Get()->IsAvailable()) {
+ if (stack->size > 0 && Symbolizer::Get()->CanReturnFileLineInfo()) {
// Currently, we include the first stack frame into the report summary.
// Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
- Symbolizer::Get()->SymbolizeCode(pc, &ai, 1);
+ Symbolizer::Get()->SymbolizePC(pc, &ai, 1);
}
#endif
ReportErrorSummary(error_type, ai.file, ai.line, ai.function);
@@ -242,6 +242,30 @@ char *StripModuleName(const char *module) {
return internal_strdup(short_module_name);
}
+static atomic_uintptr_t g_total_mmaped;
+
+void IncreaseTotalMmap(uptr size) {
+ if (!common_flags()->mmap_limit_mb) return;
+ uptr total_mmaped =
+ atomic_fetch_add(&g_total_mmaped, size, memory_order_relaxed) + size;
+ if ((total_mmaped >> 20) > common_flags()->mmap_limit_mb) {
+ // Since for now mmap_limit_mb is not a user-facing flag, just CHECK.
+ uptr mmap_limit_mb = common_flags()->mmap_limit_mb;
+ common_flags()->mmap_limit_mb = 0; // Allow mmap in CHECK.
+ RAW_CHECK(total_mmaped >> 20 < mmap_limit_mb);
+ }
+}
+
+void DecreaseTotalMmap(uptr size) {
+ if (!common_flags()->mmap_limit_mb) return;
+ atomic_fetch_sub(&g_total_mmaped, size, memory_order_relaxed);
+}
+
+static void (*sandboxing_callback)();
+void SetSandboxingCallback(void (*f)()) {
+ sandboxing_callback = f;
+}
+
} // namespace __sanitizer
using namespace __sanitizer; // NOLINT
@@ -274,9 +298,11 @@ void __sanitizer_set_report_path(const char *path) {
}
}
-void NOINLINE __sanitizer_sandbox_on_notify(void *reserved) {
- (void)reserved;
- PrepareForSandboxing();
+void NOINLINE
+__sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args) {
+ PrepareForSandboxing(args);
+ if (sandboxing_callback)
+ sandboxing_callback();
}
void __sanitizer_report_error_summary(const char *error_summary) {
diff --git a/libsanitizer/sanitizer_common/sanitizer_common.h b/libsanitizer/sanitizer_common/sanitizer_common.h
index 07d1b63db58..93317132c49 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common.h
+++ b/libsanitizer/sanitizer_common/sanitizer_common.h
@@ -17,6 +17,7 @@
#include "sanitizer_internal_defs.h"
#include "sanitizer_libc.h"
#include "sanitizer_mutex.h"
+#include "sanitizer_flags.h"
namespace __sanitizer {
struct StackTrace;
@@ -26,13 +27,15 @@ const uptr kWordSize = SANITIZER_WORDSIZE / 8;
const uptr kWordSizeInBits = 8 * kWordSize;
#if defined(__powerpc__) || defined(__powerpc64__)
-const uptr kCacheLineSize = 128;
+ const uptr kCacheLineSize = 128;
#else
-const uptr kCacheLineSize = 64;
+ const uptr kCacheLineSize = 64;
#endif
const uptr kMaxPathLength = 512;
+const uptr kMaxThreadStackSize = 1 << 30; // 1Gb
+
extern const char *SanitizerToolName; // Can be changed by the tool.
uptr GetPageSize();
@@ -51,6 +54,7 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
void *MmapOrDie(uptr size, const char *mem_type);
void UnmapOrDie(void *addr, uptr size);
void *MmapFixedNoReserve(uptr fixed_addr, uptr size);
+void *MmapNoReserveOrDie(uptr size, const char *mem_type);
void *MmapFixedOrDie(uptr fixed_addr, uptr size);
void *Mprotect(uptr fixed_addr, uptr size);
// Map aligned chunk of address space; size and alignment are powers of two.
@@ -58,6 +62,8 @@ void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type);
// Used to check if we can map shadow memory to a fixed location.
bool MemoryRangeIsAvailable(uptr range_start, uptr range_end);
void FlushUnneededShadowMemory(uptr addr, uptr size);
+void IncreaseTotalMmap(uptr size);
+void DecreaseTotalMmap(uptr size);
// InternalScopedBuffer can be used instead of large stack arrays to
// keep frame size low.
@@ -123,9 +129,18 @@ void RawWrite(const char *buffer);
bool PrintsToTty();
// Caching version of PrintsToTty(). Not thread-safe.
bool PrintsToTtyCached();
+bool ColorizeReports();
void Printf(const char *format, ...);
void Report(const char *format, ...);
void SetPrintfAndReportCallback(void (*callback)(const char *));
+#define VReport(level, ...) \
+ do { \
+ if ((uptr)common_flags()->verbosity >= (level)) Report(__VA_ARGS__); \
+ } while (0)
+#define VPrintf(level, ...) \
+ do { \
+ if ((uptr)common_flags()->verbosity >= (level)) Printf(__VA_ARGS__); \
+ } while (0)
// Can be used to prevent mixing error reports from different sanitizers.
extern StaticSpinMutex CommonSanitizerReportMutex;
@@ -169,7 +184,10 @@ u32 GetUid();
void ReExec();
bool StackSizeIsUnlimited();
void SetStackSizeLimitInBytes(uptr limit);
-void PrepareForSandboxing();
+void AdjustStackSize(void *attr);
+void PrepareForSandboxing(__sanitizer_sandbox_arguments *args);
+void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args);
+void SetSandboxingCallback(void (*f)());
void InitTlsSize();
uptr GetTlsSize();
@@ -206,6 +224,14 @@ typedef void (*CheckFailedCallbackType)(const char *, int, const char *,
u64, u64);
void SetCheckFailedCallback(CheckFailedCallbackType callback);
+// Functions related to signal handling.
+typedef void (*SignalHandlerType)(int, void *, void *);
+bool IsDeadlySignal(int signum);
+void InstallDeadlySignalHandlers(SignalHandlerType handler);
+// Alternative signal stack (POSIX-only).
+void SetAlternateSignalStack();
+void UnsetAlternateSignalStack();
+
// We don't want a summary too long.
const int kMaxSummaryLength = 1024;
// Construct a one-line string:
@@ -243,6 +269,19 @@ INLINE uptr MostSignificantSetBitIndex(uptr x) {
return up;
}
+INLINE uptr LeastSignificantSetBitIndex(uptr x) {
+ CHECK_NE(x, 0U);
+ unsigned long up; // NOLINT
+#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
+ up = __builtin_ctzl(x);
+#elif defined(_WIN64)
+ _BitScanForward64(&up, x);
+#else
+ _BitScanForward(&up, x);
+#endif
+ return up;
+}
+
INLINE bool IsPowerOfTwo(uptr x) {
return (x & (x - 1)) == 0;
}
@@ -307,12 +346,6 @@ INLINE int ToLower(int c) {
return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
}
-#if SANITIZER_WORDSIZE == 64
-# define FIRST_32_SECOND_64(a, b) (b)
-#else
-# define FIRST_32_SECOND_64(a, b) (a)
-#endif
-
// A low-level vector based on mmap. May incur a significant memory overhead for
// small vectors.
// WARNING: The current implementation supports only POD types.
@@ -477,6 +510,33 @@ const uptr kPthreadDestructorIterations = 0;
// Callback type for iterating over a set of memory ranges.
typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg);
+
+#if (SANITIZER_FREEBSD || SANITIZER_LINUX) && !defined(SANITIZER_GO)
+extern uptr indirect_call_wrapper;
+void SetIndirectCallWrapper(uptr wrapper);
+
+template <typename F>
+F IndirectExternCall(F f) {
+ typedef F (*WrapF)(F);
+ return indirect_call_wrapper ? ((WrapF)indirect_call_wrapper)(f) : f;
+}
+#else
+INLINE void SetIndirectCallWrapper(uptr wrapper) {}
+template <typename F>
+F IndirectExternCall(F f) {
+ return f;
+}
+#endif
+
+#if SANITIZER_ANDROID
+void AndroidLogWrite(const char *buffer);
+void GetExtraActivationFlags(char *buf, uptr size);
+void SanitizerInitializeUnwinder();
+#else
+INLINE void AndroidLogWrite(const char *buffer_unused) {}
+INLINE void GetExtraActivationFlags(char *buf, uptr size) { *buf = '\0'; }
+INLINE void SanitizerInitializeUnwinder() {}
+#endif
} // namespace __sanitizer
inline void *operator new(__sanitizer::operator_new_size_type size,
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
index e301dc17bd3..f758c1a6c52 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
@@ -26,7 +26,10 @@
// COMMON_INTERCEPTOR_HANDLE_RECVMSG
//===----------------------------------------------------------------------===//
#include "interception/interception.h"
+#include "sanitizer_addrhashmap.h"
+#include "sanitizer_placement_new.h"
#include "sanitizer_platform_interceptors.h"
+#include "sanitizer_tls_get_addr.h"
#include <stdarg.h>
@@ -35,7 +38,11 @@
#endif // _WIN32
#ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE
-#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, p, size) {}
+#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(p, size) {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_UNPOISON_PARAM
+#define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) {}
#endif
#ifndef COMMON_INTERCEPTOR_FD_ACCESS
@@ -58,14 +65,70 @@
#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) ((void)(msg))
#endif
+#ifndef COMMON_INTERCEPTOR_FILE_OPEN
+#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_FILE_CLOSE
+#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) {}
+#endif
+
+struct FileMetadata {
+ // For open_memstream().
+ char **addr;
+ SIZE_T *size;
+};
+
+struct CommonInterceptorMetadata {
+ enum {
+ CIMT_INVALID = 0,
+ CIMT_FILE
+ } type;
+ union {
+ FileMetadata file;
+ };
+};
+
+typedef AddrHashMap<CommonInterceptorMetadata, 31051> MetadataHashMap;
+
+static MetadataHashMap *interceptor_metadata_map;
+
+#if SI_NOT_WINDOWS
+UNUSED static void SetInterceptorMetadata(__sanitizer_FILE *addr,
+ const FileMetadata &file) {
+ MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr);
+ CHECK(h.created());
+ h->type = CommonInterceptorMetadata::CIMT_FILE;
+ h->file = file;
+}
+
+UNUSED static const FileMetadata *GetInterceptorMetadata(
+ __sanitizer_FILE *addr) {
+ MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr,
+ /* remove */ false,
+ /* create */ false);
+ if (h.exists()) {
+ CHECK(!h.created());
+ CHECK(h->type == CommonInterceptorMetadata::CIMT_FILE);
+ return &h->file;
+ } else {
+ return 0;
+ }
+}
+
+UNUSED static void DeleteInterceptorMetadata(void *addr) {
+ MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr, true);
+ CHECK(h.exists());
+}
+#endif // SI_NOT_WINDOWS
+
#if SANITIZER_INTERCEPT_TEXTDOMAIN
INTERCEPTOR(char*, textdomain, const char *domainname) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, textdomain, domainname);
char* domain = REAL(textdomain)(domainname);
if (domain) {
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, domain,
- REAL(strlen)(domain) + 1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, REAL(strlen)(domain) + 1);
}
return domain;
}
@@ -160,6 +223,34 @@ INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T n) {
#define INIT_STRNCASECMP
#endif
+#if SANITIZER_INTERCEPT_MEMCHR
+INTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, memchr, s, c, n);
+ void *res = REAL(memchr)(s, c, n);
+ uptr len = res ? (char*)res - (char*)s + 1 : n;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, len);
+ return res;
+}
+
+#define INIT_MEMCHR COMMON_INTERCEPT_FUNCTION(memchr)
+#else
+#define INIT_MEMCHR
+#endif
+
+#if SANITIZER_INTERCEPT_MEMRCHR
+INTERCEPTOR(void*, memrchr, const void *s, int c, SIZE_T n) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, memrchr, s, c, n);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, n);
+ return REAL(memrchr)(s, c, n);
+}
+
+#define INIT_MEMRCHR COMMON_INTERCEPT_FUNCTION(memrchr)
+#else
+#define INIT_MEMRCHR
+#endif
+
#if SANITIZER_INTERCEPT_FREXP
INTERCEPTOR(double, frexp, double x, int *exp) {
void *ctx;
@@ -449,7 +540,7 @@ static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
if (tm->tm_zone) {
// Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone
// can point to shared memory and tsan would report a data race.
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, tm->tm_zone,
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(tm->tm_zone,
REAL(strlen(tm->tm_zone)) + 1);
}
}
@@ -533,6 +624,20 @@ INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
}
return res;
}
+INTERCEPTOR(long, mktime, __sanitizer_tm *tm) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, mktime, tm);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_sec, sizeof(tm->tm_sec));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_min, sizeof(tm->tm_min));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_hour, sizeof(tm->tm_hour));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mday, sizeof(tm->tm_mday));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mon, sizeof(tm->tm_mon));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_year, sizeof(tm->tm_year));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_isdst, sizeof(tm->tm_isdst));
+ long res = REAL(mktime)(tm);
+ if (res != -1) unpoison_tm(ctx, tm);
+ return res;
+}
#define INIT_LOCALTIME_AND_FRIENDS \
COMMON_INTERCEPT_FUNCTION(localtime); \
COMMON_INTERCEPT_FUNCTION(localtime_r); \
@@ -541,7 +646,8 @@ INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
COMMON_INTERCEPT_FUNCTION(ctime); \
COMMON_INTERCEPT_FUNCTION(ctime_r); \
COMMON_INTERCEPT_FUNCTION(asctime); \
- COMMON_INTERCEPT_FUNCTION(asctime_r);
+ COMMON_INTERCEPT_FUNCTION(asctime_r); \
+ COMMON_INTERCEPT_FUNCTION(mktime);
#else
#define INIT_LOCALTIME_AND_FRIENDS
#endif // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
@@ -567,9 +673,23 @@ INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) {
#define INIT_STRPTIME
#endif
-#if SANITIZER_INTERCEPT_SCANF
+#if SANITIZER_INTERCEPT_SCANF || SANITIZER_INTERCEPT_PRINTF
+#include "sanitizer_common_interceptors_format.inc"
-#include "sanitizer_common_interceptors_scanf.inc"
+#define FORMAT_INTERCEPTOR_IMPL(name, vname, ...) \
+ { \
+ void *ctx; \
+ va_list ap; \
+ va_start(ap, format); \
+ COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__, ap); \
+ int res = WRAP(vname)(__VA_ARGS__, ap); \
+ va_end(ap); \
+ return res; \
+ }
+
+#endif
+
+#if SANITIZER_INTERCEPT_SCANF
#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...) \
{ \
@@ -605,35 +725,24 @@ INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
#endif // SANITIZER_INTERCEPT_ISOC99_SCANF
-#define SCANF_INTERCEPTOR_IMPL(name, vname, ...) \
- { \
- void *ctx; \
- va_list ap; \
- va_start(ap, format); \
- COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__, ap); \
- int res = vname(__VA_ARGS__, ap); \
- va_end(ap); \
- return res; \
- }
-
INTERCEPTOR(int, scanf, const char *format, ...)
-SCANF_INTERCEPTOR_IMPL(scanf, vscanf, format)
+FORMAT_INTERCEPTOR_IMPL(scanf, vscanf, format)
INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
-SCANF_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
+FORMAT_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
-SCANF_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
+FORMAT_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
#if SANITIZER_INTERCEPT_ISOC99_SCANF
INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
-SCANF_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
+FORMAT_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
-SCANF_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
+FORMAT_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
-SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
+FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
#endif
#endif
@@ -662,6 +771,171 @@ SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
#define INIT_ISOC99_SCANF
#endif
+#if SANITIZER_INTERCEPT_PRINTF
+
+#define VPRINTF_INTERCEPTOR_ENTER(vname, ...) \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__); \
+ va_list aq; \
+ va_copy(aq, ap);
+
+#define VPRINTF_INTERCEPTOR_RETURN() \
+ va_end(aq);
+
+#define VPRINTF_INTERCEPTOR_IMPL(vname, ...) \
+ { \
+ VPRINTF_INTERCEPTOR_ENTER(vname, __VA_ARGS__); \
+ if (common_flags()->check_printf) \
+ printf_common(ctx, format, aq); \
+ int res = REAL(vname)(__VA_ARGS__); \
+ VPRINTF_INTERCEPTOR_RETURN(); \
+ return res; \
+ }
+
+#define VSPRINTF_INTERCEPTOR_IMPL(vname, str, ...) \
+ { \
+ VPRINTF_INTERCEPTOR_ENTER(vname, str, __VA_ARGS__) \
+ if (common_flags()->check_printf) { \
+ printf_common(ctx, format, aq); \
+ } \
+ int res = REAL(vname)(str, __VA_ARGS__); \
+ if (res >= 0) { \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, res + 1); \
+ } \
+ VPRINTF_INTERCEPTOR_RETURN(); \
+ return res; \
+ }
+
+#define VSNPRINTF_INTERCEPTOR_IMPL(vname, str, size, ...) \
+ { \
+ VPRINTF_INTERCEPTOR_ENTER(vname, str, size, __VA_ARGS__) \
+ if (common_flags()->check_printf) { \
+ printf_common(ctx, format, aq); \
+ } \
+ int res = REAL(vname)(str, size, __VA_ARGS__); \
+ if (res >= 0) { \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, Min(size, (SIZE_T)(res + 1))); \
+ } \
+ VPRINTF_INTERCEPTOR_RETURN(); \
+ return res; \
+ }
+
+#define VASPRINTF_INTERCEPTOR_IMPL(vname, strp, ...) \
+ { \
+ VPRINTF_INTERCEPTOR_ENTER(vname, strp, __VA_ARGS__) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, strp, sizeof(char *)); \
+ if (common_flags()->check_printf) { \
+ printf_common(ctx, format, aq); \
+ } \
+ int res = REAL(vname)(strp, __VA_ARGS__); \
+ if (res >= 0) { \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *strp, res + 1); \
+ } \
+ VPRINTF_INTERCEPTOR_RETURN(); \
+ return res; \
+ }
+
+INTERCEPTOR(int, vprintf, const char *format, va_list ap)
+VPRINTF_INTERCEPTOR_IMPL(vprintf, format, ap)
+
+INTERCEPTOR(int, vfprintf, __sanitizer_FILE *stream, const char *format,
+ va_list ap)
+VPRINTF_INTERCEPTOR_IMPL(vfprintf, stream, format, ap)
+
+INTERCEPTOR(int, vsnprintf, char *str, SIZE_T size, const char *format,
+ va_list ap)
+VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap)
+
+INTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap)
+VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)
+
+INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap)
+VASPRINTF_INTERCEPTOR_IMPL(vasprintf, strp, format, ap)
+
+#if SANITIZER_INTERCEPT_ISOC99_PRINTF
+INTERCEPTOR(int, __isoc99_vprintf, const char *format, va_list ap)
+VPRINTF_INTERCEPTOR_IMPL(__isoc99_vprintf, format, ap)
+
+INTERCEPTOR(int, __isoc99_vfprintf, __sanitizer_FILE *stream,
+ const char *format, va_list ap)
+VPRINTF_INTERCEPTOR_IMPL(__isoc99_vfprintf, stream, format, ap)
+
+INTERCEPTOR(int, __isoc99_vsnprintf, char *str, SIZE_T size, const char *format,
+ va_list ap)
+VSNPRINTF_INTERCEPTOR_IMPL(__isoc99_vsnprintf, str, size, format, ap)
+
+INTERCEPTOR(int, __isoc99_vsprintf, char *str, const char *format,
+ va_list ap)
+VSPRINTF_INTERCEPTOR_IMPL(__isoc99_vsprintf, str, format,
+ ap)
+
+#endif // SANITIZER_INTERCEPT_ISOC99_PRINTF
+
+INTERCEPTOR(int, printf, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(printf, vprintf, format)
+
+INTERCEPTOR(int, fprintf, __sanitizer_FILE *stream, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(fprintf, vfprintf, stream, format)
+
+INTERCEPTOR(int, sprintf, char *str, const char *format, ...) // NOLINT
+FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format) // NOLINT
+
+INTERCEPTOR(int, snprintf, char *str, SIZE_T size, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(snprintf, vsnprintf, str, size, format)
+
+INTERCEPTOR(int, asprintf, char **strp, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(asprintf, vasprintf, strp, format)
+
+#if SANITIZER_INTERCEPT_ISOC99_PRINTF
+INTERCEPTOR(int, __isoc99_printf, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(__isoc99_printf, __isoc99_vprintf, format)
+
+INTERCEPTOR(int, __isoc99_fprintf, __sanitizer_FILE *stream, const char *format,
+ ...)
+FORMAT_INTERCEPTOR_IMPL(__isoc99_fprintf, __isoc99_vfprintf, stream, format)
+
+INTERCEPTOR(int, __isoc99_sprintf, char *str, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(__isoc99_sprintf, __isoc99_vsprintf, str, format)
+
+INTERCEPTOR(int, __isoc99_snprintf, char *str, SIZE_T size,
+ const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size,
+ format)
+
+#endif // SANITIZER_INTERCEPT_ISOC99_PRINTF
+
+#endif // SANITIZER_INTERCEPT_PRINTF
+
+#if SANITIZER_INTERCEPT_PRINTF
+#define INIT_PRINTF \
+ COMMON_INTERCEPT_FUNCTION(printf); \
+ COMMON_INTERCEPT_FUNCTION(sprintf); \
+ COMMON_INTERCEPT_FUNCTION(snprintf); \
+ COMMON_INTERCEPT_FUNCTION(asprintf); \
+ COMMON_INTERCEPT_FUNCTION(fprintf); \
+ COMMON_INTERCEPT_FUNCTION(vprintf); \
+ COMMON_INTERCEPT_FUNCTION(vsprintf); \
+ COMMON_INTERCEPT_FUNCTION(vsnprintf); \
+ COMMON_INTERCEPT_FUNCTION(vasprintf); \
+ COMMON_INTERCEPT_FUNCTION(vfprintf);
+#else
+#define INIT_PRINTF
+#endif
+
+#if SANITIZER_INTERCEPT_ISOC99_PRINTF
+#define INIT_ISOC99_PRINTF \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_printf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_sprintf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_snprintf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_fprintf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_vprintf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_vsprintf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_vsnprintf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_vfprintf);
+#else
+#define INIT_ISOC99_PRINTF
+#endif
+
#if SANITIZER_INTERCEPT_IOCTL
#include "sanitizer_common_interceptors_ioctl.inc"
INTERCEPTOR(int, ioctl, int d, unsigned request, void *arg) {
@@ -675,7 +949,14 @@ INTERCEPTOR(int, ioctl, int d, unsigned request, void *arg) {
if (!common_flags()->handle_ioctl) return REAL(ioctl)(d, request, arg);
const ioctl_desc *desc = ioctl_lookup(request);
- if (!desc) Printf("WARNING: unknown ioctl %x\n", request);
+ ioctl_desc decoded_desc;
+ if (!desc) {
+ VPrintf(2, "Decoding unknown ioctl 0x%x\n", request);
+ if (!ioctl_decode(request, &decoded_desc))
+ Printf("WARNING: failed decoding unknown ioctl 0x%x\n", request);
+ else
+ desc = &decoded_desc;
+ }
if (desc) ioctl_common_pre(ctx, desc, d, request, arg);
int res = REAL(ioctl)(d, request, arg);
@@ -690,35 +971,85 @@ INTERCEPTOR(int, ioctl, int d, unsigned request, void *arg) {
#define INIT_IOCTL
#endif
+#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS || \
+ SANITIZER_INTERCEPT_GETPWENT || SANITIZER_INTERCEPT_FGETPWENT
+static void unpoison_passwd(void *ctx, __sanitizer_passwd *pwd) {
+ if (pwd) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, sizeof(*pwd));
+ if (pwd->pw_name)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_name,
+ REAL(strlen)(pwd->pw_name) + 1);
+ if (pwd->pw_passwd)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_passwd,
+ REAL(strlen)(pwd->pw_passwd) + 1);
+#if !SANITIZER_ANDROID
+ if (pwd->pw_gecos)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_gecos,
+ REAL(strlen)(pwd->pw_gecos) + 1);
+#endif
+#if SANITIZER_MAC
+ if (pwd->pw_class)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_class,
+ REAL(strlen)(pwd->pw_class) + 1);
+#endif
+ if (pwd->pw_dir)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_dir,
+ REAL(strlen)(pwd->pw_dir) + 1);
+ if (pwd->pw_shell)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_shell,
+ REAL(strlen)(pwd->pw_shell) + 1);
+ }
+}
+
+static void unpoison_group(void *ctx, __sanitizer_group *grp) {
+ if (grp) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, sizeof(*grp));
+ if (grp->gr_name)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_name,
+ REAL(strlen)(grp->gr_name) + 1);
+ if (grp->gr_passwd)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_passwd,
+ REAL(strlen)(grp->gr_passwd) + 1);
+ char **p = grp->gr_mem;
+ for (; *p; ++p) {
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*p, REAL(strlen)(*p) + 1);
+ }
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_mem,
+ (p - grp->gr_mem + 1) * sizeof(*p));
+ }
+}
+#endif // SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS ||
+ // SANITIZER_INTERCEPT_GETPWENT || SANITIZER_INTERCEPT_FGETPWENT
+
#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
-INTERCEPTOR(void *, getpwnam, const char *name) {
+INTERCEPTOR(__sanitizer_passwd *, getpwnam, const char *name) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
- void *res = REAL(getpwnam)(name);
- if (res != 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_passwd_sz);
+ __sanitizer_passwd *res = REAL(getpwnam)(name);
+ if (res != 0) unpoison_passwd(ctx, res);
return res;
}
-INTERCEPTOR(void *, getpwuid, u32 uid) {
+INTERCEPTOR(__sanitizer_passwd *, getpwuid, u32 uid) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
- void *res = REAL(getpwuid)(uid);
- if (res != 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_passwd_sz);
+ __sanitizer_passwd *res = REAL(getpwuid)(uid);
+ if (res != 0) unpoison_passwd(ctx, res);
return res;
}
-INTERCEPTOR(void *, getgrnam, const char *name) {
+INTERCEPTOR(__sanitizer_group *, getgrnam, const char *name) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
- void *res = REAL(getgrnam)(name);
- if (res != 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_group_sz);
+ __sanitizer_group *res = REAL(getgrnam)(name);
+ if (res != 0) unpoison_group(ctx, res);
return res;
}
-INTERCEPTOR(void *, getgrgid, u32 gid) {
+INTERCEPTOR(__sanitizer_group *, getgrgid, u32 gid) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid);
- void *res = REAL(getgrgid)(gid);
- if (res != 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_group_sz);
+ __sanitizer_group *res = REAL(getgrgid)(gid);
+ if (res != 0) unpoison_group(ctx, res);
return res;
}
#define INIT_GETPWNAM_AND_FRIENDS \
@@ -731,50 +1062,54 @@ INTERCEPTOR(void *, getgrgid, u32 gid) {
#endif
#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
-INTERCEPTOR(int, getpwnam_r, const char *name, void *pwd, char *buf,
- SIZE_T buflen, void **result) {
+INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd,
+ char *buf, SIZE_T buflen, __sanitizer_passwd **result) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
if (!res) {
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, struct_passwd_sz);
+ if (result && *result) unpoison_passwd(ctx, *result);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
}
+ if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
return res;
}
-INTERCEPTOR(int, getpwuid_r, u32 uid, void *pwd, char *buf, SIZE_T buflen,
- void **result) {
+INTERCEPTOR(int, getpwuid_r, u32 uid, __sanitizer_passwd *pwd, char *buf,
+ SIZE_T buflen, __sanitizer_passwd **result) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
if (!res) {
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, struct_passwd_sz);
+ if (result && *result) unpoison_passwd(ctx, *result);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
}
+ if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
return res;
}
-INTERCEPTOR(int, getgrnam_r, const char *name, void *grp, char *buf,
- SIZE_T buflen, void **result) {
+INTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp,
+ char *buf, SIZE_T buflen, __sanitizer_group **result) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
if (!res) {
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, struct_group_sz);
+ if (result && *result) unpoison_group(ctx, *result);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
}
+ if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
return res;
}
-INTERCEPTOR(int, getgrgid_r, u32 gid, void *grp, char *buf, SIZE_T buflen,
- void **result) {
+INTERCEPTOR(int, getgrgid_r, u32 gid, __sanitizer_group *grp, char *buf,
+ SIZE_T buflen, __sanitizer_group **result) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
if (!res) {
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, struct_group_sz);
+ if (result && *result) unpoison_group(ctx, *result);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
}
+ if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
return res;
}
#define INIT_GETPWNAM_R_AND_FRIENDS \
@@ -786,6 +1121,141 @@ INTERCEPTOR(int, getgrgid_r, u32 gid, void *grp, char *buf, SIZE_T buflen,
#define INIT_GETPWNAM_R_AND_FRIENDS
#endif
+#if SANITIZER_INTERCEPT_GETPWENT
+INTERCEPTOR(__sanitizer_passwd *, getpwent, int dummy) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpwent, dummy);
+ __sanitizer_passwd *res = REAL(getpwent)(dummy);
+ if (res != 0) unpoison_passwd(ctx, res);
+ return res;
+}
+INTERCEPTOR(__sanitizer_group *, getgrent, int dummy) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgrent, dummy);
+ __sanitizer_group *res = REAL(getgrent)(dummy);
+ if (res != 0) unpoison_group(ctx, res);;
+ return res;
+}
+#define INIT_GETPWENT \
+ COMMON_INTERCEPT_FUNCTION(getpwent); \
+ COMMON_INTERCEPT_FUNCTION(getgrent);
+#else
+#define INIT_GETPWENT
+#endif
+
+#if SANITIZER_INTERCEPT_FGETPWENT
+INTERCEPTOR(__sanitizer_passwd *, fgetpwent, void *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent, fp);
+ __sanitizer_passwd *res = REAL(fgetpwent)(fp);
+ if (res != 0) unpoison_passwd(ctx, res);
+ return res;
+}
+INTERCEPTOR(__sanitizer_group *, fgetgrent, void *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent, fp);
+ __sanitizer_group *res = REAL(fgetgrent)(fp);
+ if (res != 0) unpoison_group(ctx, res);
+ return res;
+}
+#define INIT_FGETPWENT \
+ COMMON_INTERCEPT_FUNCTION(fgetpwent); \
+ COMMON_INTERCEPT_FUNCTION(fgetgrent);
+#else
+#define INIT_FGETPWENT
+#endif
+
+#if SANITIZER_INTERCEPT_GETPWENT_R
+INTERCEPTOR(int, getpwent_r, __sanitizer_passwd *pwbuf, char *buf,
+ SIZE_T buflen, __sanitizer_passwd **pwbufp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpwent_r, pwbuf, buf, buflen, pwbufp);
+ int res = REAL(getpwent_r)(pwbuf, buf, buflen, pwbufp);
+ if (!res) {
+ if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
+ }
+ if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
+ return res;
+}
+INTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf,
+ SIZE_T buflen, __sanitizer_passwd **pwbufp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp);
+ int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp);
+ if (!res) {
+ if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
+ }
+ if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
+ return res;
+}
+INTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen,
+ __sanitizer_group **pwbufp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp);
+ int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp);
+ if (!res) {
+ if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
+ }
+ if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
+ return res;
+}
+INTERCEPTOR(int, fgetgrent_r, void *fp, __sanitizer_group *pwbuf, char *buf,
+ SIZE_T buflen, __sanitizer_group **pwbufp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent_r, fp, pwbuf, buf, buflen, pwbufp);
+ int res = REAL(fgetgrent_r)(fp, pwbuf, buf, buflen, pwbufp);
+ if (!res) {
+ if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
+ }
+ if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
+ return res;
+}
+#define INIT_GETPWENT_R \
+ COMMON_INTERCEPT_FUNCTION(getpwent_r); \
+ COMMON_INTERCEPT_FUNCTION(fgetpwent_r); \
+ COMMON_INTERCEPT_FUNCTION(getgrent_r); \
+ COMMON_INTERCEPT_FUNCTION(fgetgrent_r);
+#else
+#define INIT_GETPWENT_R
+#endif
+
+#if SANITIZER_INTERCEPT_SETPWENT
+// The only thing these interceptors do is disable any nested interceptors.
+// These functions may open nss modules and call uninstrumented functions from
+// them, and we don't want things like strlen() to trigger.
+INTERCEPTOR(void, setpwent, int dummy) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, setpwent, dummy);
+ REAL(setpwent)(dummy);
+}
+INTERCEPTOR(void, endpwent, int dummy) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, endpwent, dummy);
+ REAL(endpwent)(dummy);
+}
+INTERCEPTOR(void, setgrent, int dummy) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, setgrent, dummy);
+ REAL(setgrent)(dummy);
+}
+INTERCEPTOR(void, endgrent, int dummy) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, endgrent, dummy);
+ REAL(endgrent)(dummy);
+}
+#define INIT_SETPWENT \
+ COMMON_INTERCEPT_FUNCTION(setpwent); \
+ COMMON_INTERCEPT_FUNCTION(endpwent); \
+ COMMON_INTERCEPT_FUNCTION(setgrent); \
+ COMMON_INTERCEPT_FUNCTION(endgrent);
+#else
+#define INIT_SETPWENT
+#endif
+
#if SANITIZER_INTERCEPT_CLOCK_GETTIME
INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
void *ctx;
@@ -861,34 +1331,33 @@ static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
}
static THREADLOCAL __sanitizer_glob_t *pglob_copy;
-static THREADLOCAL void *glob_ctx;
static void wrapped_gl_closedir(void *dir) {
- COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
- pglob_copy->gl_closedir(dir);
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
+ IndirectExternCall(pglob_copy->gl_closedir)(dir);
}
static void *wrapped_gl_readdir(void *dir) {
- COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
- return pglob_copy->gl_readdir(dir);
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
+ return IndirectExternCall(pglob_copy->gl_readdir)(dir);
}
static void *wrapped_gl_opendir(const char *s) {
- COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
- COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
- return pglob_copy->gl_opendir(s);
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
+ return IndirectExternCall(pglob_copy->gl_opendir)(s);
}
static int wrapped_gl_lstat(const char *s, void *st) {
- COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2);
- COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
- return pglob_copy->gl_lstat(s, st);
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
+ return IndirectExternCall(pglob_copy->gl_lstat)(s, st);
}
static int wrapped_gl_stat(const char *s, void *st) {
- COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2);
- COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
- return pglob_copy->gl_stat(s, st);
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
+ return IndirectExternCall(pglob_copy->gl_stat)(s, st);
}
INTERCEPTOR(int, glob, const char *pattern, int flags,
@@ -907,7 +1376,6 @@ INTERCEPTOR(int, glob, const char *pattern, int flags,
Swap(pglob->gl_lstat, glob_copy.gl_lstat);
Swap(pglob->gl_stat, glob_copy.gl_stat);
pglob_copy = &glob_copy;
- glob_ctx = ctx;
}
int res = REAL(glob)(pattern, flags, errfunc, pglob);
if (flags & glob_altdirfunc) {
@@ -918,7 +1386,6 @@ INTERCEPTOR(int, glob, const char *pattern, int flags,
Swap(pglob->gl_stat, glob_copy.gl_stat);
}
pglob_copy = 0;
- glob_ctx = 0;
if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
return res;
}
@@ -939,7 +1406,6 @@ INTERCEPTOR(int, glob64, const char *pattern, int flags,
Swap(pglob->gl_lstat, glob_copy.gl_lstat);
Swap(pglob->gl_stat, glob_copy.gl_stat);
pglob_copy = &glob_copy;
- glob_ctx = ctx;
}
int res = REAL(glob64)(pattern, flags, errfunc, pglob);
if (flags & glob_altdirfunc) {
@@ -950,7 +1416,6 @@ INTERCEPTOR(int, glob64, const char *pattern, int flags,
Swap(pglob->gl_stat, glob_copy.gl_stat);
}
pglob_copy = 0;
- glob_ctx = 0;
if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
return res;
}
@@ -1000,6 +1465,19 @@ INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
}
return res;
}
+#if SANITIZER_ANDROID
+INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __wait4, pid, status, options, rusage);
+ int res = REAL(__wait4)(pid, status, options, rusage);
+ if (res != -1) {
+ if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
+ if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
+ }
+ return res;
+}
+#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(__wait4);
+#else
INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
@@ -1010,14 +1488,16 @@ INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
}
return res;
}
+#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(wait4);
+#endif // SANITIZER_ANDROID
#define INIT_WAIT \
COMMON_INTERCEPT_FUNCTION(wait); \
COMMON_INTERCEPT_FUNCTION(waitid); \
COMMON_INTERCEPT_FUNCTION(waitpid); \
- COMMON_INTERCEPT_FUNCTION(wait3); \
- COMMON_INTERCEPT_FUNCTION(wait4);
+ COMMON_INTERCEPT_FUNCTION(wait3);
#else
#define INIT_WAIT
+#define INIT_WAIT4
#endif
#if SANITIZER_INTERCEPT_INET
@@ -1227,14 +1707,12 @@ INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
h_errnop);
int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
- if (res == 0) {
- if (result) {
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
- if (*result) write_hostent(ctx, *result);
- }
- if (h_errnop)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
+ if (result) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (res == 0 && *result) write_hostent(ctx, *result);
}
+ if (h_errnop)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
return res;
}
@@ -1247,14 +1725,12 @@ INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
h_errnop);
- if (res == 0) {
- if (result) {
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
- if (*result) write_hostent(ctx, *result);
- }
- if (h_errnop)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
+ if (result) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (res == 0 && *result) write_hostent(ctx, *result);
}
+ if (h_errnop)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
return res;
}
@@ -1265,14 +1741,12 @@ INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
h_errnop);
int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
- if (res == 0) {
- if (result) {
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
- if (*result) write_hostent(ctx, *result);
- }
- if (h_errnop)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
+ if (result) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (res == 0 && *result) write_hostent(ctx, *result);
}
+ if (h_errnop)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
return res;
}
@@ -1284,14 +1758,12 @@ INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
result, h_errnop);
int res =
REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
- if (res == 0) {
- if (result) {
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
- if (*result) write_hostent(ctx, *result);
- }
- if (h_errnop)
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
+ if (result) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (res == 0 && *result) write_hostent(ctx, *result);
}
+ if (h_errnop)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
return res;
}
#define INIT_GETHOSTBYNAME_R \
@@ -1834,7 +2306,7 @@ INTERCEPTOR(char *, strerror, int errnum) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
char *res = REAL(strerror)(errnum);
- if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
return res;
}
#define INIT_STRERROR COMMON_INTERCEPT_FUNCTION(strerror);
@@ -1890,24 +2362,23 @@ typedef int (*scandir_filter_f)(const struct __sanitizer_dirent *);
typedef int (*scandir_compar_f)(const struct __sanitizer_dirent **,
const struct __sanitizer_dirent **);
-static THREADLOCAL void *scandir_ctx;
static THREADLOCAL scandir_filter_f scandir_filter;
static THREADLOCAL scandir_compar_f scandir_compar;
static int wrapped_scandir_filter(const struct __sanitizer_dirent *dir) {
- COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir_ctx, 1);
- COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, dir, dir->d_reclen);
- return scandir_filter(dir);
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
+ return IndirectExternCall(scandir_filter)(dir);
}
static int wrapped_scandir_compar(const struct __sanitizer_dirent **a,
const struct __sanitizer_dirent **b) {
- COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir_ctx, 2);
- COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, a, sizeof(*a));
- COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, *a, (*a)->d_reclen);
- COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, b, sizeof(*b));
- COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, *b, (*b)->d_reclen);
- return scandir_compar(a, b);
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
+ return IndirectExternCall(scandir_compar)(a, b);
}
INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
@@ -1915,13 +2386,10 @@ INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar);
if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
- CHECK_EQ(0, scandir_ctx);
- scandir_ctx = ctx;
scandir_filter = filter;
scandir_compar = compar;
int res = REAL(scandir)(dirp, namelist, filter ? wrapped_scandir_filter : 0,
compar ? wrapped_scandir_compar : 0);
- scandir_ctx = 0;
scandir_filter = 0;
scandir_compar = 0;
if (namelist && res > 0) {
@@ -1943,24 +2411,23 @@ typedef int (*scandir64_filter_f)(const struct __sanitizer_dirent64 *);
typedef int (*scandir64_compar_f)(const struct __sanitizer_dirent64 **,
const struct __sanitizer_dirent64 **);
-static THREADLOCAL void *scandir64_ctx;
static THREADLOCAL scandir64_filter_f scandir64_filter;
static THREADLOCAL scandir64_compar_f scandir64_compar;
static int wrapped_scandir64_filter(const struct __sanitizer_dirent64 *dir) {
- COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir64_ctx, 1);
- COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, dir, dir->d_reclen);
- return scandir64_filter(dir);
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
+ return IndirectExternCall(scandir64_filter)(dir);
}
static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a,
const struct __sanitizer_dirent64 **b) {
- COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir64_ctx, 2);
- COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, a, sizeof(*a));
- COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, *a, (*a)->d_reclen);
- COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, b, sizeof(*b));
- COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, *b, (*b)->d_reclen);
- return scandir64_compar(a, b);
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
+ return IndirectExternCall(scandir64_compar)(a, b);
}
INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
@@ -1968,14 +2435,11 @@ INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar);
if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
- CHECK_EQ(0, scandir64_ctx);
- scandir64_ctx = ctx;
scandir64_filter = filter;
scandir64_compar = compar;
int res =
REAL(scandir64)(dirp, namelist, filter ? wrapped_scandir64_filter : 0,
compar ? wrapped_scandir64_compar : 0);
- scandir64_ctx = 0;
scandir64_filter = 0;
scandir64_compar = 0;
if (namelist && res > 0) {
@@ -2243,53 +2707,6 @@ INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
#define INIT_PTHREAD_MUTEX_UNLOCK
#endif
-#if SANITIZER_INTERCEPT_PTHREAD_COND
-INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
- void *ctx;
- COMMON_INTERCEPTOR_ENTER(ctx, pthread_cond_wait, c, m);
- COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, c, pthread_cond_t_sz);
- int res = REAL(pthread_cond_wait)(c, m);
- COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m);
- return res;
-}
-
-INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
- void *ctx;
- COMMON_INTERCEPTOR_ENTER(ctx, pthread_cond_init, c, a);
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, c, pthread_cond_t_sz);
- return REAL(pthread_cond_init)(c, a);
-}
-
-INTERCEPTOR(int, pthread_cond_signal, void *c) {
- void *ctx;
- COMMON_INTERCEPTOR_ENTER(ctx, pthread_cond_signal, c);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, c, pthread_cond_t_sz);
- return REAL(pthread_cond_signal)(c);
-}
-
-INTERCEPTOR(int, pthread_cond_broadcast, void *c) {
- void *ctx;
- COMMON_INTERCEPTOR_ENTER(ctx, pthread_cond_broadcast, c);
- COMMON_INTERCEPTOR_READ_RANGE(ctx, c, pthread_cond_t_sz);
- return REAL(pthread_cond_broadcast)(c);
-}
-
-#define INIT_PTHREAD_COND_WAIT \
- INTERCEPT_FUNCTION_VER(pthread_cond_wait, "GLIBC_2.3.2")
-#define INIT_PTHREAD_COND_INIT \
- INTERCEPT_FUNCTION_VER(pthread_cond_init, "GLIBC_2.3.2")
-#define INIT_PTHREAD_COND_SIGNAL \
- INTERCEPT_FUNCTION_VER(pthread_cond_signal, "GLIBC_2.3.2")
-#define INIT_PTHREAD_COND_BROADCAST \
- INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, "GLIBC_2.3.2")
-#else
-#define INIT_PTHREAD_COND_WAIT
-#define INIT_PTHREAD_COND_INIT
-#define INIT_PTHREAD_COND_SIGNAL
-#define INIT_PTHREAD_COND_BROADCAST
-#endif
-
#if SANITIZER_INTERCEPT_GETMNTENT || SANITIZER_INTERCEPT_GETMNTENT_R
static void write_mntent(void *ctx, __sanitizer_mntent *mnt) {
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt, sizeof(*mnt));
@@ -2446,7 +2863,7 @@ INTERCEPTOR(char *, ether_ntoa, __sanitizer_ether_addr *addr) {
COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa, addr);
if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
char *res = REAL(ether_ntoa)(addr);
- if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
return res;
}
INTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) {
@@ -2454,7 +2871,7 @@ INTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) {
COMMON_INTERCEPTOR_ENTER(ctx, ether_aton, buf);
if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
__sanitizer_ether_addr *res = REAL(ether_aton)(buf);
- if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, res, sizeof(*res));
+ if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, sizeof(*res));
return res;
}
INTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) {
@@ -2592,9 +3009,13 @@ INTERCEPTOR(int, pthread_attr_getstack, void *attr, void **addr, SIZE_T *size) {
// We may need to call the real pthread_attr_getstack from the run-time
// in sanitizer_common, but we don't want to include the interception headers
// there. So, just define this function here.
-int __sanitizer_pthread_attr_getstack(void *attr, void **addr, SIZE_T *size) {
+namespace __sanitizer {
+extern "C" {
+int real_pthread_attr_getstack(void *attr, void **addr, SIZE_T *size) {
return REAL(pthread_attr_getstack)(attr, addr, size);
}
+} // extern "C"
+} // namespace __sanitizer
#define INIT_PTHREAD_ATTR_GET \
COMMON_INTERCEPT_FUNCTION(pthread_attr_getdetachstate); \
@@ -2644,7 +3065,7 @@ INTERCEPTOR(char *, tmpnam, char *s) {
if (s)
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
else
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
}
return res;
}
@@ -2673,7 +3094,7 @@ INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, REAL(strlen)(dir) + 1);
if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, REAL(strlen)(pfx) + 1);
char *res = REAL(tempnam)(dir, pfx);
- if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
return res;
}
#define INIT_TEMPNAM COMMON_INTERCEPT_FUNCTION(tempnam);
@@ -2836,6 +3257,18 @@ INTERCEPTOR(int, lrand48_r, void *buffer, long *result) {
#define INIT_DRAND48_R
#endif
+#if SANITIZER_INTERCEPT_RAND_R
+INTERCEPTOR(int, rand_r, unsigned *seedp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, rand_r, seedp);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, seedp, sizeof(*seedp));
+ return REAL(rand_r)(seedp);
+}
+#define INIT_RAND_R COMMON_INTERCEPT_FUNCTION(rand_r);
+#else
+#define INIT_RAND_R
+#endif
+
#if SANITIZER_INTERCEPT_GETLINE
INTERCEPTOR(SSIZE_T, getline, char **lineptr, SIZE_T *n, void *stream) {
void *ctx;
@@ -2906,117 +3339,840 @@ INTERCEPTOR(__sanitizer_clock_t, times, void *tms) {
#define INIT_TIMES
#endif
-#define SANITIZER_COMMON_INTERCEPTORS_INIT \
- INIT_TEXTDOMAIN; \
- INIT_STRCMP; \
- INIT_STRNCMP; \
- INIT_STRCASECMP; \
- INIT_STRNCASECMP; \
- INIT_READ; \
- INIT_PREAD; \
- INIT_PREAD64; \
- INIT_READV; \
- INIT_PREADV; \
- INIT_PREADV64; \
- INIT_WRITE; \
- INIT_PWRITE; \
- INIT_PWRITE64; \
- INIT_WRITEV; \
- INIT_PWRITEV; \
- INIT_PWRITEV64; \
- INIT_PRCTL; \
- INIT_LOCALTIME_AND_FRIENDS; \
- INIT_STRPTIME; \
- INIT_SCANF; \
- INIT_ISOC99_SCANF; \
- INIT_FREXP; \
- INIT_FREXPF_FREXPL; \
- INIT_GETPWNAM_AND_FRIENDS; \
- INIT_GETPWNAM_R_AND_FRIENDS; \
- INIT_CLOCK_GETTIME; \
- INIT_GETITIMER; \
- INIT_TIME; \
- INIT_GLOB; \
- INIT_WAIT; \
- INIT_INET; \
- INIT_PTHREAD_GETSCHEDPARAM; \
- INIT_GETADDRINFO; \
- INIT_GETNAMEINFO; \
- INIT_GETSOCKNAME; \
- INIT_GETHOSTBYNAME; \
- INIT_GETHOSTBYNAME_R; \
- INIT_GETSOCKOPT; \
- INIT_ACCEPT; \
- INIT_ACCEPT4; \
- INIT_MODF; \
- INIT_RECVMSG; \
- INIT_GETPEERNAME; \
- INIT_IOCTL; \
- INIT_INET_ATON; \
- INIT_SYSINFO; \
- INIT_READDIR; \
- INIT_READDIR64; \
- INIT_PTRACE; \
- INIT_SETLOCALE; \
- INIT_GETCWD; \
- INIT_GET_CURRENT_DIR_NAME; \
- INIT_STRTOIMAX; \
- INIT_MBSTOWCS; \
- INIT_MBSNRTOWCS; \
- INIT_WCSTOMBS; \
- INIT_WCSNRTOMBS; \
- INIT_TCGETATTR; \
- INIT_REALPATH; \
- INIT_CANONICALIZE_FILE_NAME; \
- INIT_CONFSTR; \
- INIT_SCHED_GETAFFINITY; \
- INIT_STRERROR; \
- INIT_STRERROR_R; \
- INIT_XPG_STRERROR_R; \
- INIT_SCANDIR; \
- INIT_SCANDIR64; \
- INIT_GETGROUPS; \
- INIT_POLL; \
- INIT_PPOLL; \
- INIT_WORDEXP; \
- INIT_SIGWAIT; \
- INIT_SIGWAITINFO; \
- INIT_SIGTIMEDWAIT; \
- INIT_SIGSETOPS; \
- INIT_SIGPENDING; \
- INIT_SIGPROCMASK; \
- INIT_BACKTRACE; \
- INIT__EXIT; \
- INIT_PTHREAD_MUTEX_LOCK; \
- INIT_PTHREAD_MUTEX_UNLOCK; \
- INIT_PTHREAD_COND_WAIT; \
- INIT_PTHREAD_COND_INIT; \
- INIT_PTHREAD_COND_SIGNAL; \
- INIT_PTHREAD_COND_BROADCAST; \
- INIT_GETMNTENT; \
- INIT_GETMNTENT_R; \
- INIT_STATFS; \
- INIT_STATFS64; \
- INIT_STATVFS; \
- INIT_STATVFS64; \
- INIT_INITGROUPS; \
- INIT_ETHER; \
- INIT_ETHER_R; \
- INIT_SHMCTL; \
- INIT_RANDOM_R; \
- INIT_PTHREAD_ATTR_GET; \
- INIT_PTHREAD_ATTR_GETINHERITSCHED; \
- INIT_PTHREAD_ATTR_GETAFFINITY_NP; \
- INIT_TMPNAM; \
- INIT_TMPNAM_R; \
- INIT_TEMPNAM; \
- INIT_PTHREAD_SETNAME_NP; \
- INIT_SINCOS; \
- INIT_REMQUO; \
- INIT_LGAMMA; \
- INIT_LGAMMA_R; \
- INIT_DRAND48_R; \
- INIT_GETLINE; \
- INIT_ICONV; \
- INIT_TIMES; \
-/**/
+#if SANITIZER_INTERCEPT_TLS_GET_ADDR
+#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr)
+INTERCEPTOR(void *, __tls_get_addr, void *arg) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr, arg);
+ void *res = REAL(__tls_get_addr)(arg);
+ DTLS_on_tls_get_addr(arg, res);
+ return res;
+}
+#else
+#define INIT_TLS_GET_ADDR
+#endif
+
+#if SANITIZER_INTERCEPT_LISTXATTR
+INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, listxattr, path, list, size);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ SSIZE_T res = REAL(listxattr)(path, list, size);
+ // Here and below, size == 0 is a special case where nothing is written to the
+ // buffer, and res contains the desired buffer size.
+ if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
+ return res;
+}
+INTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, llistxattr, path, list, size);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ SSIZE_T res = REAL(llistxattr)(path, list, size);
+ if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
+ return res;
+}
+INTERCEPTOR(SSIZE_T, flistxattr, int fd, char *list, SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, flistxattr, fd, list, size);
+ SSIZE_T res = REAL(flistxattr)(fd, list, size);
+ if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
+ return res;
+}
+#define INIT_LISTXATTR \
+ COMMON_INTERCEPT_FUNCTION(listxattr); \
+ COMMON_INTERCEPT_FUNCTION(llistxattr); \
+ COMMON_INTERCEPT_FUNCTION(flistxattr);
+#else
+#define INIT_LISTXATTR
+#endif
+
+#if SANITIZER_INTERCEPT_GETXATTR
+INTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value,
+ SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getxattr, path, name, value, size);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ SSIZE_T res = REAL(getxattr)(path, name, value, size);
+ if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
+ return res;
+}
+INTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value,
+ SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, lgetxattr, path, name, value, size);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ SSIZE_T res = REAL(lgetxattr)(path, name, value, size);
+ if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
+ return res;
+}
+INTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value,
+ SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fgetxattr, fd, name, value, size);
+ if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ SSIZE_T res = REAL(fgetxattr)(fd, name, value, size);
+ if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
+ return res;
+}
+#define INIT_GETXATTR \
+ COMMON_INTERCEPT_FUNCTION(getxattr); \
+ COMMON_INTERCEPT_FUNCTION(lgetxattr); \
+ COMMON_INTERCEPT_FUNCTION(fgetxattr);
+#else
+#define INIT_GETXATTR
+#endif
+
+#if SANITIZER_INTERCEPT_GETRESID
+INTERCEPTOR(int, getresuid, void *ruid, void *euid, void *suid) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getresuid, ruid, euid, suid);
+ int res = REAL(getresuid)(ruid, euid, suid);
+ if (res >= 0) {
+ if (ruid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ruid, uid_t_sz);
+ if (euid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, euid, uid_t_sz);
+ if (suid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, suid, uid_t_sz);
+ }
+ return res;
+}
+INTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getresgid, rgid, egid, sgid);
+ int res = REAL(getresgid)(rgid, egid, sgid);
+ if (res >= 0) {
+ if (rgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rgid, gid_t_sz);
+ if (egid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, egid, gid_t_sz);
+ if (sgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sgid, gid_t_sz);
+ }
+ return res;
+}
+#define INIT_GETRESID \
+ COMMON_INTERCEPT_FUNCTION(getresuid); \
+ COMMON_INTERCEPT_FUNCTION(getresgid);
+#else
+#define INIT_GETRESID
+#endif
+
+#if SANITIZER_INTERCEPT_GETIFADDRS
+// As long as getifaddrs()/freeifaddrs() use calloc()/free(), we don't need to
+// intercept freeifaddrs(). If that ceases to be the case, we might need to
+// intercept it to poison the memory again.
+INTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **ifap) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getifaddrs, ifap);
+ int res = REAL(getifaddrs)(ifap);
+ if (res == 0 && ifap) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifap, sizeof(void *));
+ __sanitizer_ifaddrs *p = *ifap;
+ while (p) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(__sanitizer_ifaddrs));
+ if (p->ifa_name)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_name,
+ REAL(strlen)(p->ifa_name) + 1);
+ if (p->ifa_addr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_addr, struct_sockaddr_sz);
+ if (p->ifa_netmask)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_netmask, struct_sockaddr_sz);
+ // On Linux this is a union, but the other member also points to a
+ // struct sockaddr, so the following is sufficient.
+ if (p->ifa_dstaddr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_dstaddr, struct_sockaddr_sz);
+ // FIXME(smatveev): Unpoison p->ifa_data as well.
+ p = p->ifa_next;
+ }
+ }
+ return res;
+}
+#define INIT_GETIFADDRS \
+ COMMON_INTERCEPT_FUNCTION(getifaddrs);
+#else
+#define INIT_GETIFADDRS
+#endif
+
+#if SANITIZER_INTERCEPT_IF_INDEXTONAME
+INTERCEPTOR(char *, if_indextoname, unsigned int ifindex, char* ifname) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, if_indextoname, ifindex, ifname);
+ char *res = REAL(if_indextoname)(ifindex, ifname);
+ if (res && ifname)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
+ return res;
+}
+INTERCEPTOR(unsigned int, if_nametoindex, const char* ifname) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, if_nametoindex, ifname);
+ if (ifname)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
+ return REAL(if_nametoindex)(ifname);
+}
+#define INIT_IF_INDEXTONAME \
+ COMMON_INTERCEPT_FUNCTION(if_indextoname); \
+ COMMON_INTERCEPT_FUNCTION(if_nametoindex);
+#else
+#define INIT_IF_INDEXTONAME
+#endif
+
+#if SANITIZER_INTERCEPT_CAPGET
+INTERCEPTOR(int, capget, void *hdrp, void *datap) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, capget, hdrp, datap);
+ if (hdrp)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
+ int res = REAL(capget)(hdrp, datap);
+ if (res == 0 && datap)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datap, __user_cap_data_struct_sz);
+ // We can also return -1 and write to hdrp->version if the version passed in
+ // hdrp->version is unsupported. But that's not a trivial condition to check,
+ // and anyway COMMON_INTERCEPTOR_READ_RANGE protects us to some extent.
+ return res;
+}
+INTERCEPTOR(int, capset, void *hdrp, const void *datap) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, capset, hdrp, datap);
+ if (hdrp)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
+ if (datap)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, datap, __user_cap_data_struct_sz);
+ return REAL(capset)(hdrp, datap);
+}
+#define INIT_CAPGET \
+ COMMON_INTERCEPT_FUNCTION(capget); \
+ COMMON_INTERCEPT_FUNCTION(capset);
+#else
+#define INIT_CAPGET
+#endif
+
+#if SANITIZER_INTERCEPT_AEABI_MEM
+DECLARE_REAL_AND_INTERCEPTOR(void *, memmove, void *, const void *, uptr);
+DECLARE_REAL_AND_INTERCEPTOR(void *, memcpy, void *, const void *, uptr);
+DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *, int, uptr);
+
+INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, uptr size) {
+ return WRAP(memmove)(to, from, size);
+}
+INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) {
+ return WRAP(memmove)(to, from, size);
+}
+INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) {
+ return WRAP(memmove)(to, from, size);
+}
+INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) {
+ return WRAP(memcpy)(to, from, size);
+}
+INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) {
+ return WRAP(memcpy)(to, from, size);
+}
+INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) {
+ return WRAP(memcpy)(to, from, size);
+}
+// Note the argument order.
+INTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) {
+ return WRAP(memset)(block, c, size);
+}
+INTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) {
+ return WRAP(memset)(block, c, size);
+}
+INTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) {
+ return WRAP(memset)(block, c, size);
+}
+INTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) {
+ return WRAP(memset)(block, 0, size);
+}
+INTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) {
+ return WRAP(memset)(block, 0, size);
+}
+INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
+ return WRAP(memset)(block, 0, size);
+}
+#define INIT_AEABI_MEM \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memmove); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memmove4); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memmove8); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy4); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy8); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memset); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memset4); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memset8); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memclr); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memclr4); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memclr8);
+#else
+#define INIT_AEABI_MEM
+#endif // SANITIZER_INTERCEPT_AEABI_MEM
+
+#if SANITIZER_INTERCEPT___BZERO
+DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *, int, uptr);
+
+INTERCEPTOR(void *, __bzero, void *block, uptr size) {
+ return WRAP(memset)(block, 0, size);
+}
+#define INIT___BZERO COMMON_INTERCEPT_FUNCTION(__bzero);
+#else
+#define INIT___BZERO
+#endif // SANITIZER_INTERCEPT___BZERO
+
+#if SANITIZER_INTERCEPT_FTIME
+INTERCEPTOR(int, ftime, __sanitizer_timeb *tp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ftime, tp);
+ int res = REAL(ftime)(tp);
+ if (tp)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, sizeof(*tp));
+ return res;
+}
+#define INIT_FTIME COMMON_INTERCEPT_FUNCTION(ftime);
+#else
+#define INIT_FTIME
+#endif // SANITIZER_INTERCEPT_FTIME
+
+#if SANITIZER_INTERCEPT_XDR
+INTERCEPTOR(void, xdrmem_create, __sanitizer_XDR *xdrs, uptr addr,
+ unsigned size, int op) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, xdrmem_create, xdrs, addr, size, op);
+ REAL(xdrmem_create)(xdrs, addr, size, op);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
+ if (op == __sanitizer_XDR_ENCODE) {
+ // It's not obvious how much data individual xdr_ routines write.
+ // Simply unpoison the entire target buffer in advance.
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (void *)addr, size);
+ }
+}
+
+INTERCEPTOR(void, xdrstdio_create, __sanitizer_XDR *xdrs, void *file, int op) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, xdrstdio_create, xdrs, file, op);
+ REAL(xdrstdio_create)(xdrs, file, op);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
+}
+
+#define XDR_INTERCEPTOR(F, T) \
+ INTERCEPTOR(int, F, __sanitizer_XDR *xdrs, T *p) { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, F, xdrs, p); \
+ if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p)); \
+ int res = REAL(F)(xdrs, p); \
+ if (res && p && xdrs->x_op == __sanitizer_XDR_DECODE) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); \
+ return res; \
+ }
+
+XDR_INTERCEPTOR(xdr_short, short)
+XDR_INTERCEPTOR(xdr_u_short, unsigned short)
+XDR_INTERCEPTOR(xdr_int, int)
+XDR_INTERCEPTOR(xdr_u_int, unsigned)
+XDR_INTERCEPTOR(xdr_long, long)
+XDR_INTERCEPTOR(xdr_u_long, unsigned long)
+XDR_INTERCEPTOR(xdr_hyper, long long)
+XDR_INTERCEPTOR(xdr_u_hyper, unsigned long long)
+XDR_INTERCEPTOR(xdr_longlong_t, long long)
+XDR_INTERCEPTOR(xdr_u_longlong_t, unsigned long long)
+XDR_INTERCEPTOR(xdr_int8_t, u8)
+XDR_INTERCEPTOR(xdr_uint8_t, u8)
+XDR_INTERCEPTOR(xdr_int16_t, u16)
+XDR_INTERCEPTOR(xdr_uint16_t, u16)
+XDR_INTERCEPTOR(xdr_int32_t, u32)
+XDR_INTERCEPTOR(xdr_uint32_t, u32)
+XDR_INTERCEPTOR(xdr_int64_t, u64)
+XDR_INTERCEPTOR(xdr_uint64_t, u64)
+XDR_INTERCEPTOR(xdr_quad_t, long long)
+XDR_INTERCEPTOR(xdr_u_quad_t, unsigned long long)
+XDR_INTERCEPTOR(xdr_bool, bool)
+XDR_INTERCEPTOR(xdr_enum, int)
+XDR_INTERCEPTOR(xdr_char, char)
+XDR_INTERCEPTOR(xdr_u_char, unsigned char)
+XDR_INTERCEPTOR(xdr_float, float)
+XDR_INTERCEPTOR(xdr_double, double)
+
+// FIXME: intercept xdr_array, opaque, union, vector, reference, pointer,
+// wrapstring, sizeof
+
+INTERCEPTOR(int, xdr_bytes, __sanitizer_XDR *xdrs, char **p, unsigned *sizep,
+ unsigned maxsize) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, xdr_bytes, xdrs, p, sizep, maxsize);
+ if (p && sizep && xdrs->x_op == __sanitizer_XDR_ENCODE) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sizep, sizeof(*sizep));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, *sizep);
+ }
+ int res = REAL(xdr_bytes)(xdrs, p, sizep, maxsize);
+ if (p && sizep && xdrs->x_op == __sanitizer_XDR_DECODE) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizep, sizeof(*sizep));
+ if (res && *p && *sizep) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, *sizep);
+ }
+ return res;
+}
+
+INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p,
+ unsigned maxsize) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, xdr_string, xdrs, p, maxsize);
+ if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
+ }
+ int res = REAL(xdr_string)(xdrs, p, maxsize);
+ if (p && xdrs->x_op == __sanitizer_XDR_DECODE) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
+ if (res && *p)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
+ }
+ return res;
+}
+
+#define INIT_XDR \
+ COMMON_INTERCEPT_FUNCTION(xdrmem_create); \
+ COMMON_INTERCEPT_FUNCTION(xdrstdio_create); \
+ COMMON_INTERCEPT_FUNCTION(xdr_short); \
+ COMMON_INTERCEPT_FUNCTION(xdr_u_short); \
+ COMMON_INTERCEPT_FUNCTION(xdr_int); \
+ COMMON_INTERCEPT_FUNCTION(xdr_u_int); \
+ COMMON_INTERCEPT_FUNCTION(xdr_long); \
+ COMMON_INTERCEPT_FUNCTION(xdr_u_long); \
+ COMMON_INTERCEPT_FUNCTION(xdr_hyper); \
+ COMMON_INTERCEPT_FUNCTION(xdr_u_hyper); \
+ COMMON_INTERCEPT_FUNCTION(xdr_longlong_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_u_longlong_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_int8_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_uint8_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_int16_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_uint16_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_int32_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_uint32_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_int64_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_uint64_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_quad_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_u_quad_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_bool); \
+ COMMON_INTERCEPT_FUNCTION(xdr_enum); \
+ COMMON_INTERCEPT_FUNCTION(xdr_char); \
+ COMMON_INTERCEPT_FUNCTION(xdr_u_char); \
+ COMMON_INTERCEPT_FUNCTION(xdr_float); \
+ COMMON_INTERCEPT_FUNCTION(xdr_double); \
+ COMMON_INTERCEPT_FUNCTION(xdr_bytes); \
+ COMMON_INTERCEPT_FUNCTION(xdr_string);
+#else
+#define INIT_XDR
+#endif // SANITIZER_INTERCEPT_XDR
+
+#if SANITIZER_INTERCEPT_TSEARCH
+INTERCEPTOR(void *, tsearch, void *key, void **rootp,
+ int (*compar)(const void *, const void *)) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, tsearch, key, rootp, compar);
+ void *res = REAL(tsearch)(key, rootp, compar);
+ if (res && *(void **)res == key)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(void *));
+ return res;
+}
+#define INIT_TSEARCH COMMON_INTERCEPT_FUNCTION(tsearch);
+#else
+#define INIT_TSEARCH
+#endif
+
+#if SANITIZER_INTERCEPT_LIBIO_INTERNALS || SANITIZER_INTERCEPT_FOPEN || \
+ SANITIZER_INTERCEPT_OPEN_MEMSTREAM
+void unpoison_file(__sanitizer_FILE *fp) {
+#if SANITIZER_HAS_STRUCT_FILE
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp, sizeof(*fp));
+ if (fp->_IO_read_base && fp->_IO_read_base < fp->_IO_read_end)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_read_base,
+ fp->_IO_read_end - fp->_IO_read_base);
+#endif // SANITIZER_HAS_STRUCT_FILE
+}
+#endif
+
+#if SANITIZER_INTERCEPT_LIBIO_INTERNALS
+// These guys are called when a .c source is built with -O2.
+INTERCEPTOR(int, __uflow, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __uflow, fp);
+ int res = REAL(__uflow)(fp);
+ unpoison_file(fp);
+ return res;
+}
+INTERCEPTOR(int, __underflow, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __underflow, fp);
+ int res = REAL(__underflow)(fp);
+ unpoison_file(fp);
+ return res;
+}
+INTERCEPTOR(int, __overflow, __sanitizer_FILE *fp, int ch) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __overflow, fp, ch);
+ int res = REAL(__overflow)(fp, ch);
+ unpoison_file(fp);
+ return res;
+}
+INTERCEPTOR(int, __wuflow, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __wuflow, fp);
+ int res = REAL(__wuflow)(fp);
+ unpoison_file(fp);
+ return res;
+}
+INTERCEPTOR(int, __wunderflow, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __wunderflow, fp);
+ int res = REAL(__wunderflow)(fp);
+ unpoison_file(fp);
+ return res;
+}
+INTERCEPTOR(int, __woverflow, __sanitizer_FILE *fp, int ch) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __woverflow, fp, ch);
+ int res = REAL(__woverflow)(fp, ch);
+ unpoison_file(fp);
+ return res;
+}
+#define INIT_LIBIO_INTERNALS \
+ COMMON_INTERCEPT_FUNCTION(__uflow); \
+ COMMON_INTERCEPT_FUNCTION(__underflow); \
+ COMMON_INTERCEPT_FUNCTION(__overflow); \
+ COMMON_INTERCEPT_FUNCTION(__wuflow); \
+ COMMON_INTERCEPT_FUNCTION(__wunderflow); \
+ COMMON_INTERCEPT_FUNCTION(__woverflow);
+#else
+#define INIT_LIBIO_INTERNALS
+#endif
+
+#if SANITIZER_INTERCEPT_FOPEN
+INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fopen, path, mode);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
+ __sanitizer_FILE *res = REAL(fopen)(path, mode);
+ COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
+ if (res) unpoison_file(res);
+ return res;
+}
+INTERCEPTOR(__sanitizer_FILE *, fdopen, int fd, const char *mode) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fdopen, fd, mode);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
+ __sanitizer_FILE *res = REAL(fdopen)(fd, mode);
+ if (res) unpoison_file(res);
+ return res;
+}
+INTERCEPTOR(__sanitizer_FILE *, freopen, const char *path, const char *mode,
+ __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, freopen, path, mode, fp);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
+ COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
+ __sanitizer_FILE *res = REAL(freopen)(path, mode, fp);
+ COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
+ if (res) unpoison_file(res);
+ return res;
+}
+#define INIT_FOPEN \
+ COMMON_INTERCEPT_FUNCTION(fopen); \
+ COMMON_INTERCEPT_FUNCTION(fdopen); \
+ COMMON_INTERCEPT_FUNCTION(freopen);
+#else
+#define INIT_FOPEN
+#endif
+
+#if SANITIZER_INTERCEPT_FOPEN64
+INTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fopen64, path, mode);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
+ __sanitizer_FILE *res = REAL(fopen64)(path, mode);
+ COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
+ if (res) unpoison_file(res);
+ return res;
+}
+INTERCEPTOR(__sanitizer_FILE *, freopen64, const char *path, const char *mode,
+ __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, freopen64, path, mode, fp);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
+ COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
+ __sanitizer_FILE *res = REAL(freopen64)(path, mode, fp);
+ COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
+ if (res) unpoison_file(res);
+ return res;
+}
+#define INIT_FOPEN64 \
+ COMMON_INTERCEPT_FUNCTION(fopen64); \
+ COMMON_INTERCEPT_FUNCTION(freopen64);
+#else
+#define INIT_FOPEN64
+#endif
+
+#if SANITIZER_INTERCEPT_OPEN_MEMSTREAM
+INTERCEPTOR(__sanitizer_FILE *, open_memstream, char **ptr, SIZE_T *sizeloc) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, open_memstream, ptr, sizeloc);
+ __sanitizer_FILE *res = REAL(open_memstream)(ptr, sizeloc);
+ if (res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
+ unpoison_file(res);
+ FileMetadata file = {ptr, sizeloc};
+ SetInterceptorMetadata(res, file);
+ }
+ return res;
+}
+INTERCEPTOR(__sanitizer_FILE *, open_wmemstream, wchar_t **ptr,
+ SIZE_T *sizeloc) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, open_wmemstream, ptr, sizeloc);
+ __sanitizer_FILE *res = REAL(open_wmemstream)(ptr, sizeloc);
+ if (res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
+ unpoison_file(res);
+ FileMetadata file = {(char **)ptr, sizeloc};
+ SetInterceptorMetadata(res, file);
+ }
+ return res;
+}
+INTERCEPTOR(__sanitizer_FILE *, fmemopen, void *buf, SIZE_T size,
+ const char *mode) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fmemopen, buf, size, mode);
+ __sanitizer_FILE *res = REAL(fmemopen)(buf, size, mode);
+ if (res) unpoison_file(res);
+ return res;
+}
+#define INIT_OPEN_MEMSTREAM \
+ COMMON_INTERCEPT_FUNCTION(open_memstream); \
+ COMMON_INTERCEPT_FUNCTION(open_wmemstream); \
+ COMMON_INTERCEPT_FUNCTION(fmemopen);
+#else
+#define INIT_OPEN_MEMSTREAM
+#endif
+
+#if SANITIZER_INTERCEPT_OBSTACK
+static void initialize_obstack(__sanitizer_obstack *obstack) {
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack, sizeof(*obstack));
+ if (obstack->chunk)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack->chunk,
+ sizeof(*obstack->chunk));
+}
+
+INTERCEPTOR(int, _obstack_begin_1, __sanitizer_obstack *obstack, int sz,
+ int align, void *(*alloc_fn)(uptr arg, uptr sz),
+ void (*free_fn)(uptr arg, void *p)) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin_1, obstack, sz, align, alloc_fn,
+ free_fn);
+ int res = REAL(_obstack_begin_1)(obstack, sz, align, alloc_fn, free_fn);
+ if (res) initialize_obstack(obstack);
+ return res;
+}
+INTERCEPTOR(int, _obstack_begin, __sanitizer_obstack *obstack, int sz,
+ int align, void *(*alloc_fn)(uptr sz), void (*free_fn)(void *p)) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin, obstack, sz, align, alloc_fn,
+ free_fn);
+ int res = REAL(_obstack_begin)(obstack, sz, align, alloc_fn, free_fn);
+ if (res) initialize_obstack(obstack);
+ return res;
+}
+INTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack, int length) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, _obstack_newchunk, obstack, length);
+ REAL(_obstack_newchunk)(obstack, length);
+ if (obstack->chunk)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(
+ obstack->chunk, obstack->next_free - (char *)obstack->chunk);
+}
+#define INIT_OBSTACK \
+ COMMON_INTERCEPT_FUNCTION(_obstack_begin_1); \
+ COMMON_INTERCEPT_FUNCTION(_obstack_begin); \
+ COMMON_INTERCEPT_FUNCTION(_obstack_newchunk);
+#else
+#define INIT_OBSTACK
+#endif
+
+#if SANITIZER_INTERCEPT_FFLUSH
+INTERCEPTOR(int, fflush, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fflush, fp);
+ int res = REAL(fflush)(fp);
+ // FIXME: handle fp == NULL
+ if (fp) {
+ const FileMetadata *m = GetInterceptorMetadata(fp);
+ if (m) COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
+ }
+ return res;
+}
+#define INIT_FFLUSH COMMON_INTERCEPT_FUNCTION(fflush);
+#else
+#define INIT_FFLUSH
+#endif
+
+#if SANITIZER_INTERCEPT_FCLOSE
+INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fclose, fp);
+ if (fp) {
+ COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
+ const FileMetadata *m = GetInterceptorMetadata(fp);
+ if (m) {
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
+ DeleteInterceptorMetadata(fp);
+ }
+ }
+ return REAL(fclose)(fp);
+}
+#define INIT_FCLOSE COMMON_INTERCEPT_FUNCTION(fclose);
+#else
+#define INIT_FCLOSE
+#endif
+
+static void InitializeCommonInterceptors() {
+ static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
+ interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap();
+
+ INIT_TEXTDOMAIN;
+ INIT_STRCMP;
+ INIT_STRNCMP;
+ INIT_STRCASECMP;
+ INIT_STRNCASECMP;
+ INIT_MEMCHR;
+ INIT_MEMRCHR;
+ INIT_READ;
+ INIT_PREAD;
+ INIT_PREAD64;
+ INIT_READV;
+ INIT_PREADV;
+ INIT_PREADV64;
+ INIT_WRITE;
+ INIT_PWRITE;
+ INIT_PWRITE64;
+ INIT_WRITEV;
+ INIT_PWRITEV;
+ INIT_PWRITEV64;
+ INIT_PRCTL;
+ INIT_LOCALTIME_AND_FRIENDS;
+ INIT_STRPTIME;
+ INIT_SCANF;
+ INIT_ISOC99_SCANF;
+ INIT_PRINTF;
+ INIT_ISOC99_PRINTF;
+ INIT_FREXP;
+ INIT_FREXPF_FREXPL;
+ INIT_GETPWNAM_AND_FRIENDS;
+ INIT_GETPWNAM_R_AND_FRIENDS;
+ INIT_GETPWENT;
+ INIT_FGETPWENT;
+ INIT_GETPWENT_R;
+ INIT_SETPWENT;
+ INIT_CLOCK_GETTIME;
+ INIT_GETITIMER;
+ INIT_TIME;
+ INIT_GLOB;
+ INIT_WAIT;
+ INIT_WAIT4;
+ INIT_INET;
+ INIT_PTHREAD_GETSCHEDPARAM;
+ INIT_GETADDRINFO;
+ INIT_GETNAMEINFO;
+ INIT_GETSOCKNAME;
+ INIT_GETHOSTBYNAME;
+ INIT_GETHOSTBYNAME_R;
+ INIT_GETSOCKOPT;
+ INIT_ACCEPT;
+ INIT_ACCEPT4;
+ INIT_MODF;
+ INIT_RECVMSG;
+ INIT_GETPEERNAME;
+ INIT_IOCTL;
+ INIT_INET_ATON;
+ INIT_SYSINFO;
+ INIT_READDIR;
+ INIT_READDIR64;
+ INIT_PTRACE;
+ INIT_SETLOCALE;
+ INIT_GETCWD;
+ INIT_GET_CURRENT_DIR_NAME;
+ INIT_STRTOIMAX;
+ INIT_MBSTOWCS;
+ INIT_MBSNRTOWCS;
+ INIT_WCSTOMBS;
+ INIT_WCSNRTOMBS;
+ INIT_TCGETATTR;
+ INIT_REALPATH;
+ INIT_CANONICALIZE_FILE_NAME;
+ INIT_CONFSTR;
+ INIT_SCHED_GETAFFINITY;
+ INIT_STRERROR;
+ INIT_STRERROR_R;
+ INIT_XPG_STRERROR_R;
+ INIT_SCANDIR;
+ INIT_SCANDIR64;
+ INIT_GETGROUPS;
+ INIT_POLL;
+ INIT_PPOLL;
+ INIT_WORDEXP;
+ INIT_SIGWAIT;
+ INIT_SIGWAITINFO;
+ INIT_SIGTIMEDWAIT;
+ INIT_SIGSETOPS;
+ INIT_SIGPENDING;
+ INIT_SIGPROCMASK;
+ INIT_BACKTRACE;
+ INIT__EXIT;
+ INIT_PTHREAD_MUTEX_LOCK;
+ INIT_PTHREAD_MUTEX_UNLOCK;
+ INIT_GETMNTENT;
+ INIT_GETMNTENT_R;
+ INIT_STATFS;
+ INIT_STATFS64;
+ INIT_STATVFS;
+ INIT_STATVFS64;
+ INIT_INITGROUPS;
+ INIT_ETHER;
+ INIT_ETHER_R;
+ INIT_SHMCTL;
+ INIT_RANDOM_R;
+ INIT_PTHREAD_ATTR_GET;
+ INIT_PTHREAD_ATTR_GETINHERITSCHED;
+ INIT_PTHREAD_ATTR_GETAFFINITY_NP;
+ INIT_TMPNAM;
+ INIT_TMPNAM_R;
+ INIT_TEMPNAM;
+ INIT_PTHREAD_SETNAME_NP;
+ INIT_SINCOS;
+ INIT_REMQUO;
+ INIT_LGAMMA;
+ INIT_LGAMMA_R;
+ INIT_DRAND48_R;
+ INIT_RAND_R;
+ INIT_GETLINE;
+ INIT_ICONV;
+ INIT_TIMES;
+ INIT_TLS_GET_ADDR;
+ INIT_LISTXATTR;
+ INIT_GETXATTR;
+ INIT_GETRESID;
+ INIT_GETIFADDRS;
+ INIT_IF_INDEXTONAME;
+ INIT_CAPGET;
+ INIT_AEABI_MEM;
+ INIT___BZERO;
+ INIT_FTIME;
+ INIT_XDR;
+ INIT_TSEARCH;
+ INIT_LIBIO_INTERNALS;
+ INIT_FOPEN;
+ INIT_FOPEN64;
+ INIT_OPEN_MEMSTREAM;
+ INIT_OBSTACK;
+ INIT_FFLUSH;
+ INIT_FCLOSE;
+}
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc
new file mode 100644
index 00000000000..dfc4ac6b556
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc
@@ -0,0 +1,554 @@
+//===-- sanitizer_common_interceptors_format.inc ----------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Scanf/printf implementation for use in *Sanitizer interceptors.
+// Follows http://pubs.opengroup.org/onlinepubs/9699919799/functions/fscanf.html
+// and http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
+// with a few common GNU extensions.
+//
+//===----------------------------------------------------------------------===//
+#include <stdarg.h>
+
+static const char *parse_number(const char *p, int *out) {
+ *out = internal_atoll(p);
+ while (*p >= '0' && *p <= '9')
+ ++p;
+ return p;
+}
+
+static const char *maybe_parse_param_index(const char *p, int *out) {
+ // n$
+ if (*p >= '0' && *p <= '9') {
+ int number;
+ const char *q = parse_number(p, &number);
+ CHECK(q);
+ if (*q == '$') {
+ *out = number;
+ p = q + 1;
+ }
+ }
+
+ // Otherwise, do not change p. This will be re-parsed later as the field
+ // width.
+ return p;
+}
+
+static bool char_is_one_of(char c, const char *s) {
+ return !!internal_strchr(s, c);
+}
+
+static const char *maybe_parse_length_modifier(const char *p, char ll[2]) {
+ if (char_is_one_of(*p, "jztLq")) {
+ ll[0] = *p;
+ ++p;
+ } else if (*p == 'h') {
+ ll[0] = 'h';
+ ++p;
+ if (*p == 'h') {
+ ll[1] = 'h';
+ ++p;
+ }
+ } else if (*p == 'l') {
+ ll[0] = 'l';
+ ++p;
+ if (*p == 'l') {
+ ll[1] = 'l';
+ ++p;
+ }
+ }
+ return p;
+}
+
+// Returns true if the character is an integer conversion specifier.
+static bool format_is_integer_conv(char c) {
+ return char_is_one_of(c, "diouxXn");
+}
+
+// Returns true if the character is an floating point conversion specifier.
+static bool format_is_float_conv(char c) {
+ return char_is_one_of(c, "aAeEfFgG");
+}
+
+// Returns string output character size for string-like conversions,
+// or 0 if the conversion is invalid.
+static int format_get_char_size(char convSpecifier,
+ const char lengthModifier[2]) {
+ if (char_is_one_of(convSpecifier, "CS")) {
+ return sizeof(wchar_t);
+ }
+
+ if (char_is_one_of(convSpecifier, "cs[")) {
+ if (lengthModifier[0] == 'l' && lengthModifier[1] == '\0')
+ return sizeof(wchar_t);
+ else if (lengthModifier[0] == '\0')
+ return sizeof(char);
+ }
+
+ return 0;
+}
+
+enum FormatStoreSize {
+ // Store size not known in advance; can be calculated as wcslen() of the
+ // destination buffer.
+ FSS_WCSLEN = -2,
+ // Store size not known in advance; can be calculated as strlen() of the
+ // destination buffer.
+ FSS_STRLEN = -1,
+ // Invalid conversion specifier.
+ FSS_INVALID = 0
+};
+
+// Returns the memory size of a format directive (if >0), or a value of
+// FormatStoreSize.
+static int format_get_value_size(char convSpecifier,
+ const char lengthModifier[2],
+ bool promote_float) {
+ if (format_is_integer_conv(convSpecifier)) {
+ switch (lengthModifier[0]) {
+ case 'h':
+ return lengthModifier[1] == 'h' ? sizeof(char) : sizeof(short);
+ case 'l':
+ return lengthModifier[1] == 'l' ? sizeof(long long) : sizeof(long);
+ case 'q':
+ return sizeof(long long);
+ case 'L':
+ return sizeof(long long);
+ case 'j':
+ return sizeof(INTMAX_T);
+ case 'z':
+ return sizeof(SIZE_T);
+ case 't':
+ return sizeof(PTRDIFF_T);
+ case 0:
+ return sizeof(int);
+ default:
+ return FSS_INVALID;
+ }
+ }
+
+ if (format_is_float_conv(convSpecifier)) {
+ switch (lengthModifier[0]) {
+ case 'L':
+ case 'q':
+ return sizeof(long double);
+ case 'l':
+ return lengthModifier[1] == 'l' ? sizeof(long double)
+ : sizeof(double);
+ case 0:
+ // Printf promotes floats to doubles but scanf does not
+ return promote_float ? sizeof(double) : sizeof(float);
+ default:
+ return FSS_INVALID;
+ }
+ }
+
+ if (convSpecifier == 'p') {
+ if (lengthModifier[0] != 0)
+ return FSS_INVALID;
+ return sizeof(void *);
+ }
+
+ return FSS_INVALID;
+}
+
+struct ScanfDirective {
+ int argIdx; // argument index, or -1 if not specified ("%n$")
+ int fieldWidth;
+ const char *begin;
+ const char *end;
+ bool suppressed; // suppress assignment ("*")
+ bool allocate; // allocate space ("m")
+ char lengthModifier[2];
+ char convSpecifier;
+ bool maybeGnuMalloc;
+};
+
+// Parse scanf format string. If a valid directive in encountered, it is
+// returned in dir. This function returns the pointer to the first
+// unprocessed character, or 0 in case of error.
+// In case of the end-of-string, a pointer to the closing \0 is returned.
+static const char *scanf_parse_next(const char *p, bool allowGnuMalloc,
+ ScanfDirective *dir) {
+ internal_memset(dir, 0, sizeof(*dir));
+ dir->argIdx = -1;
+
+ while (*p) {
+ if (*p != '%') {
+ ++p;
+ continue;
+ }
+ dir->begin = p;
+ ++p;
+ // %%
+ if (*p == '%') {
+ ++p;
+ continue;
+ }
+ if (*p == '\0') {
+ return 0;
+ }
+ // %n$
+ p = maybe_parse_param_index(p, &dir->argIdx);
+ CHECK(p);
+ // *
+ if (*p == '*') {
+ dir->suppressed = true;
+ ++p;
+ }
+ // Field width
+ if (*p >= '0' && *p <= '9') {
+ p = parse_number(p, &dir->fieldWidth);
+ CHECK(p);
+ if (dir->fieldWidth <= 0) // Width if at all must be non-zero
+ return 0;
+ }
+ // m
+ if (*p == 'm') {
+ dir->allocate = true;
+ ++p;
+ }
+ // Length modifier.
+ p = maybe_parse_length_modifier(p, dir->lengthModifier);
+ // Conversion specifier.
+ dir->convSpecifier = *p++;
+ // Consume %[...] expression.
+ if (dir->convSpecifier == '[') {
+ if (*p == '^')
+ ++p;
+ if (*p == ']')
+ ++p;
+ while (*p && *p != ']')
+ ++p;
+ if (*p == 0)
+ return 0; // unexpected end of string
+ // Consume the closing ']'.
+ ++p;
+ }
+ // This is unfortunately ambiguous between old GNU extension
+ // of %as, %aS and %a[...] and newer POSIX %a followed by
+ // letters s, S or [.
+ if (allowGnuMalloc && dir->convSpecifier == 'a' &&
+ !dir->lengthModifier[0]) {
+ if (*p == 's' || *p == 'S') {
+ dir->maybeGnuMalloc = true;
+ ++p;
+ } else if (*p == '[') {
+ // Watch for %a[h-j%d], if % appears in the
+ // [...] range, then we need to give up, we don't know
+ // if scanf will parse it as POSIX %a [h-j %d ] or
+ // GNU allocation of string with range dh-j plus %.
+ const char *q = p + 1;
+ if (*q == '^')
+ ++q;
+ if (*q == ']')
+ ++q;
+ while (*q && *q != ']' && *q != '%')
+ ++q;
+ if (*q == 0 || *q == '%')
+ return 0;
+ p = q + 1; // Consume the closing ']'.
+ dir->maybeGnuMalloc = true;
+ }
+ }
+ dir->end = p;
+ break;
+ }
+ return p;
+}
+
+static int scanf_get_value_size(ScanfDirective *dir) {
+ if (dir->allocate) {
+ if (!char_is_one_of(dir->convSpecifier, "cCsS["))
+ return FSS_INVALID;
+ return sizeof(char *);
+ }
+
+ if (dir->maybeGnuMalloc) {
+ if (dir->convSpecifier != 'a' || dir->lengthModifier[0])
+ return FSS_INVALID;
+ // This is ambiguous, so check the smaller size of char * (if it is
+ // a GNU extension of %as, %aS or %a[...]) and float (if it is
+ // POSIX %a followed by s, S or [ letters).
+ return sizeof(char *) < sizeof(float) ? sizeof(char *) : sizeof(float);
+ }
+
+ if (char_is_one_of(dir->convSpecifier, "cCsS[")) {
+ bool needsTerminator = char_is_one_of(dir->convSpecifier, "sS[");
+ unsigned charSize =
+ format_get_char_size(dir->convSpecifier, dir->lengthModifier);
+ if (charSize == 0)
+ return FSS_INVALID;
+ if (dir->fieldWidth == 0) {
+ if (!needsTerminator)
+ return charSize;
+ return (charSize == sizeof(char)) ? FSS_STRLEN : FSS_WCSLEN;
+ }
+ return (dir->fieldWidth + needsTerminator) * charSize;
+ }
+
+ return format_get_value_size(dir->convSpecifier, dir->lengthModifier, false);
+}
+
+// Common part of *scanf interceptors.
+// Process format string and va_list, and report all store ranges.
+// Stops when "consuming" n_inputs input items.
+static void scanf_common(void *ctx, int n_inputs, bool allowGnuMalloc,
+ const char *format, va_list aq) {
+ CHECK_GT(n_inputs, 0);
+ const char *p = format;
+
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, format, internal_strlen(format) + 1);
+
+ while (*p) {
+ ScanfDirective dir;
+ p = scanf_parse_next(p, allowGnuMalloc, &dir);
+ if (!p)
+ break;
+ if (dir.convSpecifier == 0) {
+ // This can only happen at the end of the format string.
+ CHECK_EQ(*p, 0);
+ break;
+ }
+ // Here the directive is valid. Do what it says.
+ if (dir.argIdx != -1) {
+ // Unsupported.
+ break;
+ }
+ if (dir.suppressed)
+ continue;
+ int size = scanf_get_value_size(&dir);
+ if (size == FSS_INVALID) {
+ Report("WARNING: unexpected format specifier in scanf interceptor: "
+ "%.*s\n", dir.end - dir.begin, dir.begin);
+ break;
+ }
+ void *argp = va_arg(aq, void *);
+ if (dir.convSpecifier != 'n')
+ --n_inputs;
+ if (n_inputs < 0)
+ break;
+ if (size == FSS_STRLEN) {
+ size = internal_strlen((const char *)argp) + 1;
+ } else if (size == FSS_WCSLEN) {
+ // FIXME: actually use wcslen() to calculate it.
+ size = 0;
+ }
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, argp, size);
+ }
+}
+
+#if SANITIZER_INTERCEPT_PRINTF
+
+struct PrintfDirective {
+ int fieldWidth;
+ int fieldPrecision;
+ int argIdx; // width argument index, or -1 if not specified ("%*n$")
+ int precisionIdx; // precision argument index, or -1 if not specified (".*n$")
+ const char *begin;
+ const char *end;
+ bool starredWidth;
+ bool starredPrecision;
+ char lengthModifier[2];
+ char convSpecifier;
+};
+
+static const char *maybe_parse_number(const char *p, int *out) {
+ if (*p >= '0' && *p <= '9')
+ p = parse_number(p, out);
+ return p;
+}
+
+static const char *maybe_parse_number_or_star(const char *p, int *out,
+ bool *star) {
+ if (*p == '*') {
+ *star = true;
+ ++p;
+ } else {
+ *star = false;
+ p = maybe_parse_number(p, out);
+ }
+ return p;
+}
+
+// Parse printf format string. Same as scanf_parse_next.
+static const char *printf_parse_next(const char *p, PrintfDirective *dir) {
+ internal_memset(dir, 0, sizeof(*dir));
+ dir->argIdx = -1;
+ dir->precisionIdx = -1;
+
+ while (*p) {
+ if (*p != '%') {
+ ++p;
+ continue;
+ }
+ dir->begin = p;
+ ++p;
+ // %%
+ if (*p == '%') {
+ ++p;
+ continue;
+ }
+ if (*p == '\0') {
+ return 0;
+ }
+ // %n$
+ p = maybe_parse_param_index(p, &dir->precisionIdx);
+ CHECK(p);
+ // Flags
+ while (char_is_one_of(*p, "'-+ #0")) {
+ ++p;
+ }
+ // Field width
+ p = maybe_parse_number_or_star(p, &dir->fieldWidth,
+ &dir->starredWidth);
+ if (!p)
+ return 0;
+ // Precision
+ if (*p == '.') {
+ ++p;
+ // Actual precision is optional (surprise!)
+ p = maybe_parse_number_or_star(p, &dir->fieldPrecision,
+ &dir->starredPrecision);
+ if (!p)
+ return 0;
+ // m$
+ if (dir->starredPrecision) {
+ p = maybe_parse_param_index(p, &dir->precisionIdx);
+ CHECK(p);
+ }
+ }
+ // Length modifier.
+ p = maybe_parse_length_modifier(p, dir->lengthModifier);
+ // Conversion specifier.
+ dir->convSpecifier = *p++;
+ dir->end = p;
+ break;
+ }
+ return p;
+}
+
+static int printf_get_value_size(PrintfDirective *dir) {
+ if (dir->convSpecifier == 'm') {
+ return sizeof(char *);
+ }
+
+ if (char_is_one_of(dir->convSpecifier, "cCsS")) {
+ unsigned charSize =
+ format_get_char_size(dir->convSpecifier, dir->lengthModifier);
+ if (charSize == 0)
+ return FSS_INVALID;
+ if (char_is_one_of(dir->convSpecifier, "sS")) {
+ return (charSize == sizeof(char)) ? FSS_STRLEN : FSS_WCSLEN;
+ }
+ return charSize;
+ }
+
+ return format_get_value_size(dir->convSpecifier, dir->lengthModifier, true);
+}
+
+#define SKIP_SCALAR_ARG(aq, convSpecifier, size) \
+ do { \
+ if (format_is_float_conv(convSpecifier)) { \
+ switch (size) { \
+ case 8: \
+ va_arg(*aq, double); \
+ break; \
+ case 16: \
+ va_arg(*aq, long double); \
+ break; \
+ default: \
+ Report("WARNING: unexpected floating-point arg size" \
+ " in printf interceptor: %d\n", size); \
+ return; \
+ } \
+ } else { \
+ switch (size) { \
+ case 1: \
+ case 2: \
+ case 4: \
+ va_arg(*aq, u32); \
+ break; \
+ case 8: \
+ va_arg(*aq, u64); \
+ break; \
+ default: \
+ Report("WARNING: unexpected arg size" \
+ " in printf interceptor: %d\n", size); \
+ return; \
+ } \
+ } \
+ } while (0)
+
+// Common part of *printf interceptors.
+// Process format string and va_list, and report all load ranges.
+static void printf_common(void *ctx, const char *format, va_list aq) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, format, internal_strlen(format) + 1);
+
+ const char *p = format;
+
+ while (*p) {
+ PrintfDirective dir;
+ p = printf_parse_next(p, &dir);
+ if (!p)
+ break;
+ if (dir.convSpecifier == 0) {
+ // This can only happen at the end of the format string.
+ CHECK_EQ(*p, 0);
+ break;
+ }
+ // Here the directive is valid. Do what it says.
+ if (dir.argIdx != -1 || dir.precisionIdx != -1) {
+ // Unsupported.
+ break;
+ }
+ if (dir.starredWidth) {
+ // Dynamic width
+ SKIP_SCALAR_ARG(&aq, 'd', sizeof(int));
+ }
+ if (dir.starredPrecision) {
+ // Dynamic precision
+ SKIP_SCALAR_ARG(&aq, 'd', sizeof(int));
+ }
+ int size = printf_get_value_size(&dir);
+ if (size == FSS_INVALID) {
+ Report("WARNING: unexpected format specifier in printf "
+ "interceptor: %.*s\n", dir.end - dir.begin, dir.begin);
+ break;
+ }
+ if (dir.convSpecifier == 'n') {
+ void *argp = va_arg(aq, void *);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, argp, size);
+ continue;
+ } else if (size == FSS_STRLEN) {
+ if (void *argp = va_arg(aq, void *)) {
+ if (dir.starredPrecision) {
+ // FIXME: properly support starred precision for strings.
+ size = 0;
+ } else if (dir.fieldPrecision > 0) {
+ // Won't read more than "precision" symbols.
+ size = internal_strnlen((const char *)argp, dir.fieldPrecision);
+ if (size < dir.fieldPrecision) size++;
+ } else {
+ // Whole string will be accessed.
+ size = internal_strlen((const char *)argp) + 1;
+ }
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, size);
+ }
+ } else if (size == FSS_WCSLEN) {
+ if (void *argp = va_arg(aq, void *)) {
+ // FIXME: Properly support wide-character strings (via wcsrtombs).
+ size = 0;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, size);
+ }
+ } else {
+ // Skip non-pointer args
+ SKIP_SCALAR_ARG(&aq, dir.convSpecifier, size);
+ }
+ }
+}
+
+#endif // SANITIZER_INTERCEPT_PRINTF
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
index ac8cdae5b81..96d171a92f5 100755
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
@@ -12,14 +12,18 @@
struct ioctl_desc {
unsigned req;
- // FIXME: support read+write arguments. Those are currently marked as WRITE.
+ // FIXME: support read+write arguments. Currently READWRITE and WRITE do the
+ // same thing.
+ // XXX: The declarations below may use WRITE instead of READWRITE, unless
+ // explicitly noted.
enum {
NONE,
READ,
WRITE,
+ READWRITE,
CUSTOM
- } type : 2;
- unsigned size : 30;
+ } type : 3;
+ unsigned size : 29;
const char* name;
};
@@ -487,11 +491,15 @@ static void ioctl_init() {
// Handle the most evil ioctls that encode argument value as part of request id.
static unsigned ioctl_request_fixup(unsigned req) {
#if SANITIZER_LINUX
- if ((req & ~0x3fff001fU) == IOCTL_EVIOCGBIT)
+ // Strip size and event number.
+ const unsigned kEviocgbitMask =
+ (IOC_SIZEMASK << IOC_SIZESHIFT) | EVIOC_EV_MAX;
+ if ((req & ~kEviocgbitMask) == IOCTL_EVIOCGBIT)
return IOCTL_EVIOCGBIT;
- if ((req & ~0x3fU) == IOCTL_EVIOCGABS)
+ // Strip absolute axis number.
+ if ((req & ~EVIOC_ABS_MAX) == IOCTL_EVIOCGABS)
return IOCTL_EVIOCGABS;
- if ((req & ~0x3fU) == IOCTL_EVIOCSABS)
+ if ((req & ~EVIOC_ABS_MAX) == IOCTL_EVIOCSABS)
return IOCTL_EVIOCSABS;
#endif
return req;
@@ -513,24 +521,56 @@ static const ioctl_desc *ioctl_table_lookup(unsigned req) {
return 0;
}
+static bool ioctl_decode(unsigned req, ioctl_desc *desc) {
+ CHECK(desc);
+ desc->req = req;
+ desc->name = "<DECODED_IOCTL>";
+ desc->size = IOC_SIZE(req);
+ // Sanity check.
+ if (desc->size > 1024) return false;
+ unsigned dir = IOC_DIR(req);
+ switch (dir) {
+ case IOC_NONE:
+ desc->type = ioctl_desc::NONE;
+ break;
+ case IOC_READ | IOC_WRITE:
+ desc->type = ioctl_desc::READWRITE;
+ break;
+ case IOC_READ:
+ desc->type = ioctl_desc::WRITE;
+ break;
+ case IOC_WRITE:
+ desc->type = ioctl_desc::READ;
+ break;
+ default:
+ return false;
+ }
+ if (desc->type != IOC_NONE && desc->size == 0) return false;
+ char id = IOC_TYPE(req);
+ // Sanity check.
+ if (!(id >= 'a' && id <= 'z') && !(id >= 'A' && id <= 'Z')) return false;
+ return true;
+}
+
static const ioctl_desc *ioctl_lookup(unsigned req) {
req = ioctl_request_fixup(req);
const ioctl_desc *desc = ioctl_table_lookup(req);
if (desc) return desc;
// Try stripping access size from the request id.
- desc = ioctl_table_lookup(req & ~0x3fff0000U);
+ desc = ioctl_table_lookup(req & ~(IOC_SIZEMASK << IOC_SIZESHIFT));
// Sanity check: requests that encode access size are either read or write and
// have size of 0 in the table.
if (desc && desc->size == 0 &&
- (desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READ))
+ (desc->type == ioctl_desc::READWRITE || desc->type == ioctl_desc::WRITE ||
+ desc->type == ioctl_desc::READ))
return desc;
return 0;
}
static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d,
unsigned request, void *arg) {
- if (desc->type == ioctl_desc::READ) {
+ if (desc->type == ioctl_desc::READ || desc->type == ioctl_desc::READWRITE) {
unsigned size = desc->size ? desc->size : IOC_SIZE(request);
COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size);
}
@@ -548,7 +588,7 @@ static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d,
static void ioctl_common_post(void *ctx, const ioctl_desc *desc, int res, int d,
unsigned request, void *arg) {
- if (desc->type == ioctl_desc::WRITE) {
+ if (desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READWRITE) {
// FIXME: add verbose output
unsigned size = desc->size ? desc->size : IOC_SIZE(request);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size);
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_scanf.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_scanf.inc
deleted file mode 100644
index 2660dada2be..00000000000
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_scanf.inc
+++ /dev/null
@@ -1,309 +0,0 @@
-//===-- sanitizer_common_interceptors_scanf.inc -----------------*- C++ -*-===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Scanf implementation for use in *Sanitizer interceptors.
-// Follows http://pubs.opengroup.org/onlinepubs/9699919799/functions/fscanf.html
-// with a few common GNU extensions.
-//
-//===----------------------------------------------------------------------===//
-#include <stdarg.h>
-
-struct ScanfDirective {
- int argIdx; // argument index, or -1 of not specified ("%n$")
- int fieldWidth;
- bool suppressed; // suppress assignment ("*")
- bool allocate; // allocate space ("m")
- char lengthModifier[2];
- char convSpecifier;
- bool maybeGnuMalloc;
-};
-
-static const char *parse_number(const char *p, int *out) {
- *out = internal_atoll(p);
- while (*p >= '0' && *p <= '9')
- ++p;
- return p;
-}
-
-static bool char_is_one_of(char c, const char *s) {
- return !!internal_strchr(s, c);
-}
-
-// Parse scanf format string. If a valid directive in encountered, it is
-// returned in dir. This function returns the pointer to the first
-// unprocessed character, or 0 in case of error.
-// In case of the end-of-string, a pointer to the closing \0 is returned.
-static const char *scanf_parse_next(const char *p, bool allowGnuMalloc,
- ScanfDirective *dir) {
- internal_memset(dir, 0, sizeof(*dir));
- dir->argIdx = -1;
-
- while (*p) {
- if (*p != '%') {
- ++p;
- continue;
- }
- ++p;
- // %%
- if (*p == '%') {
- ++p;
- continue;
- }
- if (*p == '\0') {
- return 0;
- }
- // %n$
- if (*p >= '0' && *p <= '9') {
- int number;
- const char *q = parse_number(p, &number);
- if (*q == '$') {
- dir->argIdx = number;
- p = q + 1;
- }
- // Otherwise, do not change p. This will be re-parsed later as the field
- // width.
- }
- // *
- if (*p == '*') {
- dir->suppressed = true;
- ++p;
- }
- // Field width.
- if (*p >= '0' && *p <= '9') {
- p = parse_number(p, &dir->fieldWidth);
- if (dir->fieldWidth <= 0)
- return 0;
- }
- // m
- if (*p == 'm') {
- dir->allocate = true;
- ++p;
- }
- // Length modifier.
- if (char_is_one_of(*p, "jztLq")) {
- dir->lengthModifier[0] = *p;
- ++p;
- } else if (*p == 'h') {
- dir->lengthModifier[0] = 'h';
- ++p;
- if (*p == 'h') {
- dir->lengthModifier[1] = 'h';
- ++p;
- }
- } else if (*p == 'l') {
- dir->lengthModifier[0] = 'l';
- ++p;
- if (*p == 'l') {
- dir->lengthModifier[1] = 'l';
- ++p;
- }
- }
- // Conversion specifier.
- dir->convSpecifier = *p++;
- // Consume %[...] expression.
- if (dir->convSpecifier == '[') {
- if (*p == '^')
- ++p;
- if (*p == ']')
- ++p;
- while (*p && *p != ']')
- ++p;
- if (*p == 0)
- return 0; // unexpected end of string
- // Consume the closing ']'.
- ++p;
- }
- // This is unfortunately ambiguous between old GNU extension
- // of %as, %aS and %a[...] and newer POSIX %a followed by
- // letters s, S or [.
- if (allowGnuMalloc && dir->convSpecifier == 'a' &&
- !dir->lengthModifier[0]) {
- if (*p == 's' || *p == 'S') {
- dir->maybeGnuMalloc = true;
- ++p;
- } else if (*p == '[') {
- // Watch for %a[h-j%d], if % appears in the
- // [...] range, then we need to give up, we don't know
- // if scanf will parse it as POSIX %a [h-j %d ] or
- // GNU allocation of string with range dh-j plus %.
- const char *q = p + 1;
- if (*q == '^')
- ++q;
- if (*q == ']')
- ++q;
- while (*q && *q != ']' && *q != '%')
- ++q;
- if (*q == 0 || *q == '%')
- return 0;
- p = q + 1; // Consume the closing ']'.
- dir->maybeGnuMalloc = true;
- }
- }
- break;
- }
- return p;
-}
-
-// Returns true if the character is an integer conversion specifier.
-static bool scanf_is_integer_conv(char c) {
- return char_is_one_of(c, "diouxXn");
-}
-
-// Returns true if the character is an floating point conversion specifier.
-static bool scanf_is_float_conv(char c) {
- return char_is_one_of(c, "aAeEfFgG");
-}
-
-// Returns string output character size for string-like conversions,
-// or 0 if the conversion is invalid.
-static int scanf_get_char_size(ScanfDirective *dir) {
- if (char_is_one_of(dir->convSpecifier, "CS")) {
- // wchar_t
- return 0;
- }
-
- if (char_is_one_of(dir->convSpecifier, "cs[")) {
- if (dir->lengthModifier[0] == 'l')
- // wchar_t
- return 0;
- else if (dir->lengthModifier[0] == 0)
- return sizeof(char);
- else
- return 0;
- }
-
- return 0;
-}
-
-enum ScanfStoreSize {
- // Store size not known in advance; can be calculated as strlen() of the
- // destination buffer.
- SSS_STRLEN = -1,
- // Invalid conversion specifier.
- SSS_INVALID = 0
-};
-
-// Returns the store size of a scanf directive (if >0), or a value of
-// ScanfStoreSize.
-static int scanf_get_store_size(ScanfDirective *dir) {
- if (dir->allocate) {
- if (!char_is_one_of(dir->convSpecifier, "cCsS["))
- return SSS_INVALID;
- return sizeof(char *);
- }
-
- if (dir->maybeGnuMalloc) {
- if (dir->convSpecifier != 'a' || dir->lengthModifier[0])
- return SSS_INVALID;
- // This is ambiguous, so check the smaller size of char * (if it is
- // a GNU extension of %as, %aS or %a[...]) and float (if it is
- // POSIX %a followed by s, S or [ letters).
- return sizeof(char *) < sizeof(float) ? sizeof(char *) : sizeof(float);
- }
-
- if (scanf_is_integer_conv(dir->convSpecifier)) {
- switch (dir->lengthModifier[0]) {
- case 'h':
- return dir->lengthModifier[1] == 'h' ? sizeof(char) : sizeof(short);
- case 'l':
- return dir->lengthModifier[1] == 'l' ? sizeof(long long) : sizeof(long);
- case 'L':
- return sizeof(long long);
- case 'j':
- return sizeof(INTMAX_T);
- case 'z':
- return sizeof(SIZE_T);
- case 't':
- return sizeof(PTRDIFF_T);
- case 0:
- return sizeof(int);
- default:
- return SSS_INVALID;
- }
- }
-
- if (scanf_is_float_conv(dir->convSpecifier)) {
- switch (dir->lengthModifier[0]) {
- case 'L':
- case 'q':
- return sizeof(long double);
- case 'l':
- return dir->lengthModifier[1] == 'l' ? sizeof(long double)
- : sizeof(double);
- case 0:
- return sizeof(float);
- default:
- return SSS_INVALID;
- }
- }
-
- if (char_is_one_of(dir->convSpecifier, "sS[")) {
- unsigned charSize = scanf_get_char_size(dir);
- if (charSize == 0)
- return SSS_INVALID;
- if (dir->fieldWidth == 0)
- return SSS_STRLEN;
- return (dir->fieldWidth + 1) * charSize;
- }
-
- if (char_is_one_of(dir->convSpecifier, "cC")) {
- unsigned charSize = scanf_get_char_size(dir);
- if (charSize == 0)
- return SSS_INVALID;
- if (dir->fieldWidth == 0)
- return charSize;
- return dir->fieldWidth * charSize;
- }
-
- if (dir->convSpecifier == 'p') {
- if (dir->lengthModifier[1] != 0)
- return SSS_INVALID;
- return sizeof(void *);
- }
-
- return SSS_INVALID;
-}
-
-// Common part of *scanf interceptors.
-// Process format string and va_list, and report all store ranges.
-// Stops when "consuming" n_inputs input items.
-static void scanf_common(void *ctx, int n_inputs, bool allowGnuMalloc,
- const char *format, va_list aq) {
- CHECK_GT(n_inputs, 0);
- const char *p = format;
-
- while (*p) {
- ScanfDirective dir;
- p = scanf_parse_next(p, allowGnuMalloc, &dir);
- if (!p)
- break;
- if (dir.convSpecifier == 0) {
- // This can only happen at the end of the format string.
- CHECK_EQ(*p, 0);
- break;
- }
- // Here the directive is valid. Do what it says.
- if (dir.argIdx != -1) {
- // Unsupported.
- break;
- }
- if (dir.suppressed)
- continue;
- int size = scanf_get_store_size(&dir);
- if (size == SSS_INVALID)
- break;
- void *argp = va_arg(aq, void *);
- if (dir.convSpecifier != 'n')
- --n_inputs;
- if (n_inputs < 0)
- break;
- if (size == SSS_STRLEN) {
- size = internal_strlen((const char *)argp) + 1;
- }
- COMMON_INTERCEPTOR_WRITE_RANGE(ctx, argp, size);
- }
-}
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cc
index 215a61deab6..d8330630b5f 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cc
@@ -10,6 +10,7 @@
//===----------------------------------------------------------------------===//
#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
namespace __sanitizer {
@@ -32,4 +33,10 @@ bool PrintsToTtyCached() {
}
return prints_to_tty;
}
+
+bool ColorizeReports() {
+ const char *flag = common_flags()->color;
+ return internal_strcmp(flag, "always") == 0 ||
+ (internal_strcmp(flag, "auto") == 0 && PrintsToTtyCached());
+}
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc
index 75f7d1d1e89..6be2f51b80a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc
@@ -232,6 +232,7 @@ POST_SYSCALL(settimeofday)(long res, void *tv, void *tz) {
}
}
+#if !SANITIZER_ANDROID
PRE_SYSCALL(adjtimex)(void *txc_p) {}
POST_SYSCALL(adjtimex)(long res, void *txc_p) {
@@ -239,6 +240,7 @@ POST_SYSCALL(adjtimex)(long res, void *txc_p) {
if (txc_p) POST_WRITE(txc_p, struct_timex_sz);
}
}
+#endif
PRE_SYSCALL(times)(void *tbuf) {}
@@ -384,24 +386,21 @@ PRE_SYSCALL(acct)(const void *name) {
POST_SYSCALL(acct)(long res, const void *name) {}
-PRE_SYSCALL(capget)(void *header, void *dataptr) {}
+PRE_SYSCALL(capget)(void *header, void *dataptr) {
+ if (header) PRE_READ(header, __user_cap_header_struct_sz);
+}
POST_SYSCALL(capget)(long res, void *header, void *dataptr) {
- if (res >= 0) {
- if (header) POST_WRITE(header, __user_cap_header_struct_sz);
+ if (res >= 0)
if (dataptr) POST_WRITE(dataptr, __user_cap_data_struct_sz);
- }
}
PRE_SYSCALL(capset)(void *header, const void *data) {
+ if (header) PRE_READ(header, __user_cap_header_struct_sz);
if (data) PRE_READ(data, __user_cap_data_struct_sz);
}
-POST_SYSCALL(capset)(long res, void *header, const void *data) {
- if (res >= 0) {
- if (header) POST_WRITE(header, __user_cap_header_struct_sz);
- }
-}
+POST_SYSCALL(capset)(long res, void *header, const void *data) {}
PRE_SYSCALL(personality)(long personality) {}
@@ -494,6 +493,7 @@ POST_SYSCALL(clock_gettime)(long res, long which_clock, void *tp) {
}
}
+#if !SANITIZER_ANDROID
PRE_SYSCALL(clock_adjtime)(long which_clock, void *tx) {}
POST_SYSCALL(clock_adjtime)(long res, long which_clock, void *tx) {
@@ -501,6 +501,7 @@ POST_SYSCALL(clock_adjtime)(long res, long which_clock, void *tx) {
if (tx) POST_WRITE(tx, struct_timex_sz);
}
}
+#endif
PRE_SYSCALL(clock_getres)(long which_clock, void *tp) {}
@@ -918,6 +919,7 @@ POST_SYSCALL(newfstat)(long res, long fd, void *statbuf) {
}
}
+#if !SANITIZER_ANDROID
PRE_SYSCALL(ustat)(long dev, void *ubuf) {}
POST_SYSCALL(ustat)(long res, long dev, void *ubuf) {
@@ -925,6 +927,7 @@ POST_SYSCALL(ustat)(long res, long dev, void *ubuf) {
if (ubuf) POST_WRITE(ubuf, struct_ustat_sz);
}
}
+#endif // !SANITIZER_ANDROID
PRE_SYSCALL(stat64)(const void *filename, void *statbuf) {
if (filename)
@@ -1002,8 +1005,8 @@ PRE_SYSCALL(getxattr)(const void *path, const void *name, void *value,
POST_SYSCALL(getxattr)(long res, const void *path, const void *name,
void *value, long size) {
- if (res >= 0) {
- if (value) POST_WRITE(value, size);
+ if (size && res > 0) {
+ if (value) POST_WRITE(value, res);
}
}
@@ -1017,8 +1020,8 @@ PRE_SYSCALL(lgetxattr)(const void *path, const void *name, void *value,
POST_SYSCALL(lgetxattr)(long res, const void *path, const void *name,
void *value, long size) {
- if (res >= 0) {
- if (value) POST_WRITE(value, size);
+ if (size && res > 0) {
+ if (value) POST_WRITE(value, res);
}
}
@@ -1029,8 +1032,8 @@ PRE_SYSCALL(fgetxattr)(long fd, const void *name, void *value, long size) {
POST_SYSCALL(fgetxattr)(long res, long fd, const void *name, void *value,
long size) {
- if (res >= 0) {
- if (value) POST_WRITE(value, size);
+ if (size && res > 0) {
+ if (value) POST_WRITE(value, res);
}
}
@@ -1040,8 +1043,8 @@ PRE_SYSCALL(listxattr)(const void *path, void *list, long size) {
}
POST_SYSCALL(listxattr)(long res, const void *path, void *list, long size) {
- if (res >= 0) {
- if (list) POST_WRITE(list, size);
+ if (size && res > 0) {
+ if (list) POST_WRITE(list, res);
}
}
@@ -1051,16 +1054,16 @@ PRE_SYSCALL(llistxattr)(const void *path, void *list, long size) {
}
POST_SYSCALL(llistxattr)(long res, const void *path, void *list, long size) {
- if (res >= 0) {
- if (list) POST_WRITE(list, size);
+ if (size && res > 0) {
+ if (list) POST_WRITE(list, res);
}
}
PRE_SYSCALL(flistxattr)(long fd, void *list, long size) {}
POST_SYSCALL(flistxattr)(long res, long fd, void *list, long size) {
- if (res >= 0) {
- if (list) POST_WRITE(list, size);
+ if (size && res > 0) {
+ if (list) POST_WRITE(list, res);
}
}
@@ -2080,6 +2083,7 @@ POST_SYSCALL(msgrcv)(long res, long msqid, void *msgp, long msgsz, long msgtyp,
}
}
+#if !SANITIZER_ANDROID
PRE_SYSCALL(msgctl)(long msqid, long cmd, void *buf) {}
POST_SYSCALL(msgctl)(long res, long msqid, long cmd, void *buf) {
@@ -2087,6 +2091,7 @@ POST_SYSCALL(msgctl)(long res, long msqid, long cmd, void *buf) {
if (buf) POST_WRITE(buf, struct_msqid_ds_sz);
}
}
+#endif
PRE_SYSCALL(semget)(long key, long nsems, long semflg) {}
diff --git a/libsanitizer/sanitizer_common/sanitizer_coverage.cc b/libsanitizer/sanitizer_common/sanitizer_coverage.cc
index e87b76c0081..b88e9e7ed0a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_coverage.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_coverage.cc
@@ -9,15 +9,15 @@
// This file implements run-time support for a poor man's coverage tool.
//
// Compiler instrumentation:
-// For every function F the compiler injects the following code:
+// For every interesting basic block the compiler injects the following code:
// if (*Guard) {
-// __sanitizer_cov(&F);
+// __sanitizer_cov();
// *Guard = 1;
// }
-// It's fine to call __sanitizer_cov more than once for a given function.
+// It's fine to call __sanitizer_cov more than once for a given block.
//
// Run-time:
-// - __sanitizer_cov(pc): record that we've executed a given PC.
+// - __sanitizer_cov(): record that we've executed the PC (GET_CALLER_PC).
// - __sanitizer_cov_dump: dump the coverage data to disk.
// For every module of the current process that has coverage data
// this will create a file module_name.PID.sancov. The file format is simple:
@@ -35,40 +35,103 @@
#include "sanitizer_libc.h"
#include "sanitizer_mutex.h"
#include "sanitizer_procmaps.h"
+#include "sanitizer_stacktrace.h"
#include "sanitizer_flags.h"
-struct CovData {
- BlockingMutex mu;
- InternalMmapVector<uptr> v;
-};
+atomic_uint32_t dump_once_guard; // Ensure that CovDump runs only once.
+
+// pc_array is the array containing the covered PCs.
+// To make the pc_array thread- and async-signal-safe it has to be large enough.
+// 128M counters "ought to be enough for anybody" (4M on 32-bit).
+// pc_array is allocated with MmapNoReserveOrDie and so it uses only as
+// much RAM as it really needs.
+static const uptr kPcArraySize = FIRST_32_SECOND_64(1 << 22, 1 << 27);
+static uptr *pc_array;
+static atomic_uintptr_t pc_array_index;
-static uptr cov_data_placeholder[sizeof(CovData) / sizeof(uptr)];
-COMPILER_CHECK(sizeof(cov_data_placeholder) >= sizeof(CovData));
-static CovData *cov_data = reinterpret_cast<CovData*>(cov_data_placeholder);
+static bool cov_sandboxed = false;
+static int cov_fd = kInvalidFd;
+static unsigned int cov_max_block_size = 0;
namespace __sanitizer {
// Simply add the pc into the vector under lock. If the function is called more
// than once for a given PC it will be inserted multiple times, which is fine.
static void CovAdd(uptr pc) {
- BlockingMutexLock lock(&cov_data->mu);
- cov_data->v.push_back(pc);
+ if (!pc_array) return;
+ uptr idx = atomic_fetch_add(&pc_array_index, 1, memory_order_relaxed);
+ CHECK_LT(idx, kPcArraySize);
+ pc_array[idx] = pc;
+}
+
+void CovInit() {
+ pc_array = reinterpret_cast<uptr *>(
+ MmapNoReserveOrDie(sizeof(uptr) * kPcArraySize, "CovInit"));
}
static inline bool CompareLess(const uptr &a, const uptr &b) {
return a < b;
}
+// Block layout for packed file format: header, followed by module name (no
+// trailing zero), followed by data blob.
+struct CovHeader {
+ int pid;
+ unsigned int module_name_length;
+ unsigned int data_length;
+};
+
+static void CovWritePacked(int pid, const char *module, const void *blob,
+ unsigned int blob_size) {
+ CHECK_GE(cov_fd, 0);
+ unsigned module_name_length = internal_strlen(module);
+ CovHeader header = {pid, module_name_length, blob_size};
+
+ if (cov_max_block_size == 0) {
+ // Writing to a file. Just go ahead.
+ internal_write(cov_fd, &header, sizeof(header));
+ internal_write(cov_fd, module, module_name_length);
+ internal_write(cov_fd, blob, blob_size);
+ } else {
+ // Writing to a socket. We want to split the data into appropriately sized
+ // blocks.
+ InternalScopedBuffer<char> block(cov_max_block_size);
+ CHECK_EQ((uptr)block.data(), (uptr)(CovHeader *)block.data());
+ uptr header_size_with_module = sizeof(header) + module_name_length;
+ CHECK_LT(header_size_with_module, cov_max_block_size);
+ unsigned int max_payload_size =
+ cov_max_block_size - header_size_with_module;
+ char *block_pos = block.data();
+ internal_memcpy(block_pos, &header, sizeof(header));
+ block_pos += sizeof(header);
+ internal_memcpy(block_pos, module, module_name_length);
+ block_pos += module_name_length;
+ char *block_data_begin = block_pos;
+ char *blob_pos = (char *)blob;
+ while (blob_size > 0) {
+ unsigned int payload_size = Min(blob_size, max_payload_size);
+ blob_size -= payload_size;
+ internal_memcpy(block_data_begin, blob_pos, payload_size);
+ blob_pos += payload_size;
+ ((CovHeader *)block.data())->data_length = payload_size;
+ internal_write(cov_fd, block.data(),
+ header_size_with_module + payload_size);
+ }
+ }
+}
+
// Dump the coverage on disk.
-void CovDump() {
+static void CovDump() {
+ if (!common_flags()->coverage) return;
#if !SANITIZER_WINDOWS
- BlockingMutexLock lock(&cov_data->mu);
- InternalMmapVector<uptr> &v = cov_data->v;
- InternalSort(&v, v.size(), CompareLess);
- InternalMmapVector<u32> offsets(v.size());
- const uptr *vb = v.data();
- const uptr *ve = vb + v.size();
- MemoryMappingLayout proc_maps(/*cache_enabled*/false);
+ if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed))
+ return;
+ uptr size = atomic_load(&pc_array_index, memory_order_relaxed);
+ InternalSort(&pc_array, size, CompareLess);
+ InternalMmapVector<u32> offsets(size);
+ const uptr *vb = pc_array;
+ const uptr *ve = vb + size;
+ MemoryMappingLayout proc_maps(/*cache_enabled*/true);
uptr mb, me, off, prot;
InternalScopedBuffer<char> module(4096);
InternalScopedBuffer<char> path(4096 * 2);
@@ -77,8 +140,9 @@ void CovDump() {
i++) {
if ((prot & MemoryMappingLayout::kProtectionExecute) == 0)
continue;
+ while (vb < ve && *vb < mb) vb++;
if (vb >= ve) break;
- if (mb <= *vb && *vb < me) {
+ if (*vb < me) {
offsets.clear();
const uptr *old_vb = vb;
CHECK_LE(off, *vb);
@@ -88,24 +152,63 @@ void CovDump() {
offsets.push_back(static_cast<u32>(diff));
}
char *module_name = StripModuleName(module.data());
- internal_snprintf((char *)path.data(), path.size(), "%s.%zd.sancov",
- module_name, internal_getpid());
+ if (cov_sandboxed) {
+ CovWritePacked(internal_getpid(), module_name, offsets.data(),
+ offsets.size() * sizeof(u32));
+ VReport(1, " CovDump: %zd PCs written to packed file\n", vb - old_vb);
+ } else {
+ // One file per module per process.
+ internal_snprintf((char *)path.data(), path.size(), "%s.%zd.sancov",
+ module_name, internal_getpid());
+ uptr fd = OpenFile(path.data(), true);
+ if (internal_iserror(fd)) {
+ Report(" CovDump: failed to open %s for writing\n", path.data());
+ } else {
+ internal_write(fd, offsets.data(), offsets.size() * sizeof(u32));
+ internal_close(fd);
+ VReport(1, " CovDump: %s: %zd PCs written\n", path.data(),
+ vb - old_vb);
+ }
+ }
InternalFree(module_name);
- uptr fd = OpenFile(path.data(), true);
- internal_write(fd, offsets.data(), offsets.size() * sizeof(u32));
- internal_close(fd);
- if (common_flags()->verbosity)
- Report(" CovDump: %s: %zd PCs written\n", path.data(), vb - old_vb);
}
}
+ if (cov_fd >= 0)
+ internal_close(cov_fd);
#endif // !SANITIZER_WINDOWS
}
+static void OpenPackedFileForWriting() {
+ CHECK(cov_fd == kInvalidFd);
+ InternalScopedBuffer<char> path(1024);
+ internal_snprintf((char *)path.data(), path.size(), "%zd.sancov.packed",
+ internal_getpid());
+ uptr fd = OpenFile(path.data(), true);
+ if (internal_iserror(fd)) {
+ Report(" Coverage: failed to open %s for writing\n", path.data());
+ Die();
+ }
+ cov_fd = fd;
+}
+
+void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
+ if (!args) return;
+ if (!common_flags()->coverage) return;
+ cov_sandboxed = args->coverage_sandboxed;
+ if (!cov_sandboxed) return;
+ cov_fd = args->coverage_fd;
+ cov_max_block_size = args->coverage_max_block_size;
+ if (cov_fd < 0)
+ // Pre-open the file now. The sandbox won't allow us to do it later.
+ OpenPackedFileForWriting();
+}
+
} // namespace __sanitizer
extern "C" {
-SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov(void *pc) {
- CovAdd(reinterpret_cast<uptr>(pc));
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov() {
+ CovAdd(StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()));
}
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { CovDump(); }
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init() { CovInit(); }
} // extern "C"
diff --git a/libsanitizer/sanitizer_common/sanitizer_deadlock_detector.h b/libsanitizer/sanitizer_common/sanitizer_deadlock_detector.h
new file mode 100644
index 00000000000..949c486a14a
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_deadlock_detector.h
@@ -0,0 +1,410 @@
+//===-- sanitizer_deadlock_detector.h ---------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer runtime.
+// The deadlock detector maintains a directed graph of lock acquisitions.
+// When a lock event happens, the detector checks if the locks already held by
+// the current thread are reachable from the newly acquired lock.
+//
+// The detector can handle only a fixed amount of simultaneously live locks
+// (a lock is alive if it has been locked at least once and has not been
+// destroyed). When the maximal number of locks is reached the entire graph
+// is flushed and the new lock epoch is started. The node ids from the old
+// epochs can not be used with any of the detector methods except for
+// nodeBelongsToCurrentEpoch().
+//
+// FIXME: this is work in progress, nothing really works yet.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_DEADLOCK_DETECTOR_H
+#define SANITIZER_DEADLOCK_DETECTOR_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_bvgraph.h"
+
+namespace __sanitizer {
+
+// Thread-local state for DeadlockDetector.
+// It contains the locks currently held by the owning thread.
+template <class BV>
+class DeadlockDetectorTLS {
+ public:
+ // No CTOR.
+ void clear() {
+ bv_.clear();
+ epoch_ = 0;
+ n_recursive_locks = 0;
+ n_all_locks_ = 0;
+ }
+
+ bool empty() const { return bv_.empty(); }
+
+ void ensureCurrentEpoch(uptr current_epoch) {
+ if (epoch_ == current_epoch) return;
+ bv_.clear();
+ epoch_ = current_epoch;
+ }
+
+ uptr getEpoch() const { return epoch_; }
+
+ // Returns true if this is the first (non-recursive) acquisition of this lock.
+ bool addLock(uptr lock_id, uptr current_epoch, u32 stk) {
+ // Printf("addLock: %zx %zx stk %u\n", lock_id, current_epoch, stk);
+ CHECK_EQ(epoch_, current_epoch);
+ if (!bv_.setBit(lock_id)) {
+ // The lock is already held by this thread, it must be recursive.
+ CHECK_LT(n_recursive_locks, ARRAY_SIZE(recursive_locks));
+ recursive_locks[n_recursive_locks++] = lock_id;
+ return false;
+ }
+ CHECK_LT(n_all_locks_, ARRAY_SIZE(all_locks_with_contexts_));
+ // lock_id < BV::kSize, can cast to a smaller int.
+ u32 lock_id_short = static_cast<u32>(lock_id);
+ LockWithContext l = {lock_id_short, stk};
+ all_locks_with_contexts_[n_all_locks_++] = l;
+ return true;
+ }
+
+ void removeLock(uptr lock_id) {
+ if (n_recursive_locks) {
+ for (sptr i = n_recursive_locks - 1; i >= 0; i--) {
+ if (recursive_locks[i] == lock_id) {
+ n_recursive_locks--;
+ Swap(recursive_locks[i], recursive_locks[n_recursive_locks]);
+ return;
+ }
+ }
+ }
+ // Printf("remLock: %zx %zx\n", lock_id, epoch_);
+ CHECK(bv_.clearBit(lock_id));
+ if (n_all_locks_) {
+ for (sptr i = n_all_locks_ - 1; i >= 0; i--) {
+ if (all_locks_with_contexts_[i].lock == static_cast<u32>(lock_id)) {
+ Swap(all_locks_with_contexts_[i],
+ all_locks_with_contexts_[n_all_locks_ - 1]);
+ n_all_locks_--;
+ break;
+ }
+ }
+ }
+ }
+
+ u32 findLockContext(uptr lock_id) {
+ for (uptr i = 0; i < n_all_locks_; i++)
+ if (all_locks_with_contexts_[i].lock == static_cast<u32>(lock_id))
+ return all_locks_with_contexts_[i].stk;
+ return 0;
+ }
+
+ const BV &getLocks(uptr current_epoch) const {
+ CHECK_EQ(epoch_, current_epoch);
+ return bv_;
+ }
+
+ uptr getNumLocks() const { return n_all_locks_; }
+ uptr getLock(uptr idx) const { return all_locks_with_contexts_[idx].lock; }
+
+ private:
+ BV bv_;
+ uptr epoch_;
+ uptr recursive_locks[64];
+ uptr n_recursive_locks;
+ struct LockWithContext {
+ u32 lock;
+ u32 stk;
+ };
+ LockWithContext all_locks_with_contexts_[64];
+ uptr n_all_locks_;
+};
+
+// DeadlockDetector.
+// For deadlock detection to work we need one global DeadlockDetector object
+// and one DeadlockDetectorTLS object per evey thread.
+// This class is not thread safe, all concurrent accesses should be guarded
+// by an external lock.
+// Most of the methods of this class are not thread-safe (i.e. should
+// be protected by an external lock) unless explicitly told otherwise.
+template <class BV>
+class DeadlockDetector {
+ public:
+ typedef BV BitVector;
+
+ uptr size() const { return g_.size(); }
+
+ // No CTOR.
+ void clear() {
+ current_epoch_ = 0;
+ available_nodes_.clear();
+ recycled_nodes_.clear();
+ g_.clear();
+ n_edges_ = 0;
+ }
+
+ // Allocate new deadlock detector node.
+ // If we are out of available nodes first try to recycle some.
+ // If there is nothing to recycle, flush the graph and increment the epoch.
+ // Associate 'data' (opaque user's object) with the new node.
+ uptr newNode(uptr data) {
+ if (!available_nodes_.empty())
+ return getAvailableNode(data);
+ if (!recycled_nodes_.empty()) {
+ // Printf("recycling: n_edges_ %zd\n", n_edges_);
+ for (sptr i = n_edges_ - 1; i >= 0; i--) {
+ if (recycled_nodes_.getBit(edges_[i].from) ||
+ recycled_nodes_.getBit(edges_[i].to)) {
+ Swap(edges_[i], edges_[n_edges_ - 1]);
+ n_edges_--;
+ }
+ }
+ CHECK(available_nodes_.empty());
+ // removeEdgesFrom was called in removeNode.
+ g_.removeEdgesTo(recycled_nodes_);
+ available_nodes_.setUnion(recycled_nodes_);
+ recycled_nodes_.clear();
+ return getAvailableNode(data);
+ }
+ // We are out of vacant nodes. Flush and increment the current_epoch_.
+ current_epoch_ += size();
+ recycled_nodes_.clear();
+ available_nodes_.setAll();
+ g_.clear();
+ return getAvailableNode(data);
+ }
+
+ // Get data associated with the node created by newNode().
+ uptr getData(uptr node) const { return data_[nodeToIndex(node)]; }
+
+ bool nodeBelongsToCurrentEpoch(uptr node) {
+ return node && (node / size() * size()) == current_epoch_;
+ }
+
+ void removeNode(uptr node) {
+ uptr idx = nodeToIndex(node);
+ CHECK(!available_nodes_.getBit(idx));
+ CHECK(recycled_nodes_.setBit(idx));
+ g_.removeEdgesFrom(idx);
+ }
+
+ void ensureCurrentEpoch(DeadlockDetectorTLS<BV> *dtls) {
+ dtls->ensureCurrentEpoch(current_epoch_);
+ }
+
+ // Returns true if there is a cycle in the graph after this lock event.
+ // Ideally should be called before the lock is acquired so that we can
+ // report a deadlock before a real deadlock happens.
+ bool onLockBefore(DeadlockDetectorTLS<BV> *dtls, uptr cur_node) {
+ ensureCurrentEpoch(dtls);
+ uptr cur_idx = nodeToIndex(cur_node);
+ return g_.isReachable(cur_idx, dtls->getLocks(current_epoch_));
+ }
+
+ u32 findLockContext(DeadlockDetectorTLS<BV> *dtls, uptr node) {
+ return dtls->findLockContext(nodeToIndex(node));
+ }
+
+ // Add cur_node to the set of locks held currently by dtls.
+ void onLockAfter(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk = 0) {
+ ensureCurrentEpoch(dtls);
+ uptr cur_idx = nodeToIndex(cur_node);
+ dtls->addLock(cur_idx, current_epoch_, stk);
+ }
+
+ // Experimental *racy* fast path function.
+ // Returns true if all edges from the currently held locks to cur_node exist.
+ bool hasAllEdges(DeadlockDetectorTLS<BV> *dtls, uptr cur_node) {
+ uptr local_epoch = dtls->getEpoch();
+ // Read from current_epoch_ is racy.
+ if (cur_node && local_epoch == current_epoch_ &&
+ local_epoch == nodeToEpoch(cur_node)) {
+ uptr cur_idx = nodeToIndexUnchecked(cur_node);
+ for (uptr i = 0, n = dtls->getNumLocks(); i < n; i++) {
+ if (!g_.hasEdge(dtls->getLock(i), cur_idx))
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ // Adds edges from currently held locks to cur_node,
+ // returns the number of added edges, and puts the sources of added edges
+ // into added_edges[].
+ // Should be called before onLockAfter.
+ uptr addEdges(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk,
+ int unique_tid) {
+ ensureCurrentEpoch(dtls);
+ uptr cur_idx = nodeToIndex(cur_node);
+ uptr added_edges[40];
+ uptr n_added_edges = g_.addEdges(dtls->getLocks(current_epoch_), cur_idx,
+ added_edges, ARRAY_SIZE(added_edges));
+ for (uptr i = 0; i < n_added_edges; i++) {
+ if (n_edges_ < ARRAY_SIZE(edges_)) {
+ Edge e = {(u16)added_edges[i], (u16)cur_idx,
+ dtls->findLockContext(added_edges[i]), stk,
+ unique_tid};
+ edges_[n_edges_++] = e;
+ }
+ // Printf("Edge%zd: %u %zd=>%zd in T%d\n",
+ // n_edges_, stk, added_edges[i], cur_idx, unique_tid);
+ }
+ return n_added_edges;
+ }
+
+ bool findEdge(uptr from_node, uptr to_node, u32 *stk_from, u32 *stk_to,
+ int *unique_tid) {
+ uptr from_idx = nodeToIndex(from_node);
+ uptr to_idx = nodeToIndex(to_node);
+ for (uptr i = 0; i < n_edges_; i++) {
+ if (edges_[i].from == from_idx && edges_[i].to == to_idx) {
+ *stk_from = edges_[i].stk_from;
+ *stk_to = edges_[i].stk_to;
+ *unique_tid = edges_[i].unique_tid;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Test-only function. Handles the before/after lock events,
+ // returns true if there is a cycle.
+ bool onLock(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk = 0) {
+ ensureCurrentEpoch(dtls);
+ bool is_reachable = !isHeld(dtls, cur_node) && onLockBefore(dtls, cur_node);
+ addEdges(dtls, cur_node, stk, 0);
+ onLockAfter(dtls, cur_node, stk);
+ return is_reachable;
+ }
+
+ // Handles the try_lock event, returns false.
+ // When a try_lock event happens (i.e. a try_lock call succeeds) we need
+ // to add this lock to the currently held locks, but we should not try to
+ // change the lock graph or to detect a cycle. We may want to investigate
+ // whether a more aggressive strategy is possible for try_lock.
+ bool onTryLock(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk = 0) {
+ ensureCurrentEpoch(dtls);
+ uptr cur_idx = nodeToIndex(cur_node);
+ dtls->addLock(cur_idx, current_epoch_, stk);
+ return false;
+ }
+
+ // Returns true iff dtls is empty (no locks are currently held) and we can
+ // add the node to the currently held locks w/o chanding the global state.
+ // This operation is thread-safe as it only touches the dtls.
+ bool onFirstLock(DeadlockDetectorTLS<BV> *dtls, uptr node, u32 stk = 0) {
+ if (!dtls->empty()) return false;
+ if (dtls->getEpoch() && dtls->getEpoch() == nodeToEpoch(node)) {
+ dtls->addLock(nodeToIndexUnchecked(node), nodeToEpoch(node), stk);
+ return true;
+ }
+ return false;
+ }
+
+ // Finds a path between the lock 'cur_node' (currently not held in dtls)
+ // and some currently held lock, returns the length of the path
+ // or 0 on failure.
+ uptr findPathToLock(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, uptr *path,
+ uptr path_size) {
+ tmp_bv_.copyFrom(dtls->getLocks(current_epoch_));
+ uptr idx = nodeToIndex(cur_node);
+ CHECK(!tmp_bv_.getBit(idx));
+ uptr res = g_.findShortestPath(idx, tmp_bv_, path, path_size);
+ for (uptr i = 0; i < res; i++)
+ path[i] = indexToNode(path[i]);
+ if (res)
+ CHECK_EQ(path[0], cur_node);
+ return res;
+ }
+
+ // Handle the unlock event.
+ // This operation is thread-safe as it only touches the dtls.
+ void onUnlock(DeadlockDetectorTLS<BV> *dtls, uptr node) {
+ if (dtls->getEpoch() == nodeToEpoch(node))
+ dtls->removeLock(nodeToIndexUnchecked(node));
+ }
+
+ // Tries to handle the lock event w/o writing to global state.
+ // Returns true on success.
+ // This operation is thread-safe as it only touches the dtls
+ // (modulo racy nature of hasAllEdges).
+ bool onLockFast(DeadlockDetectorTLS<BV> *dtls, uptr node, u32 stk = 0) {
+ if (hasAllEdges(dtls, node)) {
+ dtls->addLock(nodeToIndexUnchecked(node), nodeToEpoch(node), stk);
+ return true;
+ }
+ return false;
+ }
+
+ bool isHeld(DeadlockDetectorTLS<BV> *dtls, uptr node) const {
+ return dtls->getLocks(current_epoch_).getBit(nodeToIndex(node));
+ }
+
+ uptr testOnlyGetEpoch() const { return current_epoch_; }
+ bool testOnlyHasEdge(uptr l1, uptr l2) {
+ return g_.hasEdge(nodeToIndex(l1), nodeToIndex(l2));
+ }
+ // idx1 and idx2 are raw indices to g_, not lock IDs.
+ bool testOnlyHasEdgeRaw(uptr idx1, uptr idx2) {
+ return g_.hasEdge(idx1, idx2);
+ }
+
+ void Print() {
+ for (uptr from = 0; from < size(); from++)
+ for (uptr to = 0; to < size(); to++)
+ if (g_.hasEdge(from, to))
+ Printf(" %zx => %zx\n", from, to);
+ }
+
+ private:
+ void check_idx(uptr idx) const { CHECK_LT(idx, size()); }
+
+ void check_node(uptr node) const {
+ CHECK_GE(node, size());
+ CHECK_EQ(current_epoch_, nodeToEpoch(node));
+ }
+
+ uptr indexToNode(uptr idx) const {
+ check_idx(idx);
+ return idx + current_epoch_;
+ }
+
+ uptr nodeToIndexUnchecked(uptr node) const { return node % size(); }
+
+ uptr nodeToIndex(uptr node) const {
+ check_node(node);
+ return nodeToIndexUnchecked(node);
+ }
+
+ uptr nodeToEpoch(uptr node) const { return node / size() * size(); }
+
+ uptr getAvailableNode(uptr data) {
+ uptr idx = available_nodes_.getAndClearFirstOne();
+ data_[idx] = data;
+ return indexToNode(idx);
+ }
+
+ struct Edge {
+ u16 from;
+ u16 to;
+ u32 stk_from;
+ u32 stk_to;
+ int unique_tid;
+ };
+
+ uptr current_epoch_;
+ BV available_nodes_;
+ BV recycled_nodes_;
+ BV tmp_bv_;
+ BVGraph<BV> g_;
+ uptr data_[BV::kSize];
+ Edge edges_[BV::kSize * 32];
+ uptr n_edges_;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_DEADLOCK_DETECTOR_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_deadlock_detector1.cc b/libsanitizer/sanitizer_common/sanitizer_deadlock_detector1.cc
new file mode 100644
index 00000000000..fc6f5dcfbb4
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_deadlock_detector1.cc
@@ -0,0 +1,187 @@
+//===-- sanitizer_deadlock_detector1.cc -----------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Deadlock detector implementation based on NxN adjacency bit matrix.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_deadlock_detector_interface.h"
+#include "sanitizer_deadlock_detector.h"
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_mutex.h"
+
+#if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1
+
+namespace __sanitizer {
+
+typedef TwoLevelBitVector<> DDBV; // DeadlockDetector's bit vector.
+
+struct DDPhysicalThread {
+};
+
+struct DDLogicalThread {
+ u64 ctx;
+ DeadlockDetectorTLS<DDBV> dd;
+ DDReport rep;
+ bool report_pending;
+};
+
+struct DD : public DDetector {
+ SpinMutex mtx;
+ DeadlockDetector<DDBV> dd;
+ DDFlags flags;
+
+ explicit DD(const DDFlags *flags);
+
+ DDPhysicalThread* CreatePhysicalThread();
+ void DestroyPhysicalThread(DDPhysicalThread *pt);
+
+ DDLogicalThread* CreateLogicalThread(u64 ctx);
+ void DestroyLogicalThread(DDLogicalThread *lt);
+
+ void MutexInit(DDCallback *cb, DDMutex *m);
+ void MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock);
+ void MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock, bool trylock);
+ void MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock);
+ void MutexDestroy(DDCallback *cb, DDMutex *m);
+
+ DDReport *GetReport(DDCallback *cb);
+
+ void MutexEnsureID(DDLogicalThread *lt, DDMutex *m);
+ void ReportDeadlock(DDCallback *cb, DDMutex *m);
+};
+
+DDetector *DDetector::Create(const DDFlags *flags) {
+ (void)flags;
+ void *mem = MmapOrDie(sizeof(DD), "deadlock detector");
+ return new(mem) DD(flags);
+}
+
+DD::DD(const DDFlags *flags)
+ : flags(*flags) {
+ dd.clear();
+}
+
+DDPhysicalThread* DD::CreatePhysicalThread() {
+ return 0;
+}
+
+void DD::DestroyPhysicalThread(DDPhysicalThread *pt) {
+}
+
+DDLogicalThread* DD::CreateLogicalThread(u64 ctx) {
+ DDLogicalThread *lt = (DDLogicalThread*)InternalAlloc(sizeof(*lt));
+ lt->ctx = ctx;
+ lt->dd.clear();
+ lt->report_pending = false;
+ return lt;
+}
+
+void DD::DestroyLogicalThread(DDLogicalThread *lt) {
+ lt->~DDLogicalThread();
+ InternalFree(lt);
+}
+
+void DD::MutexInit(DDCallback *cb, DDMutex *m) {
+ m->id = 0;
+ m->stk = cb->Unwind();
+}
+
+void DD::MutexEnsureID(DDLogicalThread *lt, DDMutex *m) {
+ if (!dd.nodeBelongsToCurrentEpoch(m->id))
+ m->id = dd.newNode(reinterpret_cast<uptr>(m));
+ dd.ensureCurrentEpoch(&lt->dd);
+}
+
+void DD::MutexBeforeLock(DDCallback *cb,
+ DDMutex *m, bool wlock) {
+ DDLogicalThread *lt = cb->lt;
+ if (lt->dd.empty()) return; // This will be the first lock held by lt.
+ if (dd.hasAllEdges(&lt->dd, m->id)) return; // We already have all edges.
+ SpinMutexLock lk(&mtx);
+ MutexEnsureID(lt, m);
+ if (dd.isHeld(&lt->dd, m->id))
+ return; // FIXME: allow this only for recursive locks.
+ if (dd.onLockBefore(&lt->dd, m->id)) {
+ // Actually add this edge now so that we have all the stack traces.
+ dd.addEdges(&lt->dd, m->id, cb->Unwind(), cb->UniqueTid());
+ ReportDeadlock(cb, m);
+ }
+}
+
+void DD::ReportDeadlock(DDCallback *cb, DDMutex *m) {
+ DDLogicalThread *lt = cb->lt;
+ uptr path[10];
+ uptr len = dd.findPathToLock(&lt->dd, m->id, path, ARRAY_SIZE(path));
+ CHECK_GT(len, 0U); // Hm.. cycle of 10 locks? I'd like to see that.
+ CHECK_EQ(m->id, path[0]);
+ lt->report_pending = true;
+ DDReport *rep = &lt->rep;
+ rep->n = len;
+ for (uptr i = 0; i < len; i++) {
+ uptr from = path[i];
+ uptr to = path[(i + 1) % len];
+ DDMutex *m0 = (DDMutex*)dd.getData(from);
+ DDMutex *m1 = (DDMutex*)dd.getData(to);
+
+ u32 stk_from = -1U, stk_to = -1U;
+ int unique_tid = 0;
+ dd.findEdge(from, to, &stk_from, &stk_to, &unique_tid);
+ // Printf("Edge: %zd=>%zd: %u/%u T%d\n", from, to, stk_from, stk_to,
+ // unique_tid);
+ rep->loop[i].thr_ctx = unique_tid;
+ rep->loop[i].mtx_ctx0 = m0->ctx;
+ rep->loop[i].mtx_ctx1 = m1->ctx;
+ rep->loop[i].stk[0] = stk_to;
+ rep->loop[i].stk[1] = stk_from;
+ }
+}
+
+void DD::MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock, bool trylock) {
+ DDLogicalThread *lt = cb->lt;
+ u32 stk = 0;
+ if (flags.second_deadlock_stack)
+ stk = cb->Unwind();
+ // Printf("T%p MutexLock: %zx stk %u\n", lt, m->id, stk);
+ if (dd.onFirstLock(&lt->dd, m->id, stk))
+ return;
+ if (dd.onLockFast(&lt->dd, m->id, stk))
+ return;
+
+ SpinMutexLock lk(&mtx);
+ MutexEnsureID(lt, m);
+ if (wlock) // Only a recursive rlock may be held.
+ CHECK(!dd.isHeld(&lt->dd, m->id));
+ if (!trylock)
+ dd.addEdges(&lt->dd, m->id, stk ? stk : cb->Unwind(), cb->UniqueTid());
+ dd.onLockAfter(&lt->dd, m->id, stk);
+}
+
+void DD::MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {
+ // Printf("T%p MutexUnLock: %zx\n", cb->lt, m->id);
+ dd.onUnlock(&cb->lt->dd, m->id);
+}
+
+void DD::MutexDestroy(DDCallback *cb,
+ DDMutex *m) {
+ if (!m->id) return;
+ SpinMutexLock lk(&mtx);
+ if (dd.nodeBelongsToCurrentEpoch(m->id))
+ dd.removeNode(m->id);
+ m->id = 0;
+}
+
+DDReport *DD::GetReport(DDCallback *cb) {
+ if (!cb->lt->report_pending)
+ return 0;
+ cb->lt->report_pending = false;
+ return &cb->lt->rep;
+}
+
+} // namespace __sanitizer
+#endif // #if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1
diff --git a/libsanitizer/sanitizer_common/sanitizer_deadlock_detector2.cc b/libsanitizer/sanitizer_common/sanitizer_deadlock_detector2.cc
new file mode 100644
index 00000000000..f4d46d99736
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_deadlock_detector2.cc
@@ -0,0 +1,427 @@
+//===-- sanitizer_deadlock_detector2.cc -----------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Deadlock detector implementation based on adjacency lists.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_deadlock_detector_interface.h"
+#include "sanitizer_common.h"
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_mutex.h"
+
+#if SANITIZER_DEADLOCK_DETECTOR_VERSION == 2
+
+namespace __sanitizer {
+
+const int kMaxNesting = 64;
+const u32 kNoId = -1;
+const u32 kEndId = -2;
+const int kMaxLink = 8;
+const int kL1Size = 1024;
+const int kL2Size = 1024;
+const int kMaxMutex = kL1Size * kL2Size;
+
+struct Id {
+ u32 id;
+ u32 seq;
+
+ explicit Id(u32 id = 0, u32 seq = 0)
+ : id(id)
+ , seq(seq) {
+ }
+};
+
+struct Link {
+ u32 id;
+ u32 seq;
+ u32 tid;
+ u32 stk0;
+ u32 stk1;
+
+ explicit Link(u32 id = 0, u32 seq = 0, u32 tid = 0, u32 s0 = 0, u32 s1 = 0)
+ : id(id)
+ , seq(seq)
+ , tid(tid)
+ , stk0(s0)
+ , stk1(s1) {
+ }
+};
+
+struct DDPhysicalThread {
+ DDReport rep;
+ bool report_pending;
+ bool visited[kMaxMutex];
+ Link pending[kMaxMutex];
+ Link path[kMaxMutex];
+};
+
+struct ThreadMutex {
+ u32 id;
+ u32 stk;
+};
+
+struct DDLogicalThread {
+ u64 ctx;
+ ThreadMutex locked[kMaxNesting];
+ int nlocked;
+};
+
+struct Mutex {
+ StaticSpinMutex mtx;
+ u32 seq;
+ int nlink;
+ Link link[kMaxLink];
+};
+
+struct DD : public DDetector {
+ explicit DD(const DDFlags *flags);
+
+ DDPhysicalThread* CreatePhysicalThread();
+ void DestroyPhysicalThread(DDPhysicalThread *pt);
+
+ DDLogicalThread* CreateLogicalThread(u64 ctx);
+ void DestroyLogicalThread(DDLogicalThread *lt);
+
+ void MutexInit(DDCallback *cb, DDMutex *m);
+ void MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock);
+ void MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock,
+ bool trylock);
+ void MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock);
+ void MutexDestroy(DDCallback *cb, DDMutex *m);
+
+ DDReport *GetReport(DDCallback *cb);
+
+ void CycleCheck(DDPhysicalThread *pt, DDLogicalThread *lt, DDMutex *mtx);
+ void Report(DDPhysicalThread *pt, DDLogicalThread *lt, int npath);
+ u32 allocateId(DDCallback *cb);
+ Mutex *getMutex(u32 id);
+ u32 getMutexId(Mutex *m);
+
+ DDFlags flags;
+
+ Mutex* mutex[kL1Size];
+
+ SpinMutex mtx;
+ InternalMmapVector<u32> free_id;
+ int id_gen;
+};
+
+DDetector *DDetector::Create(const DDFlags *flags) {
+ (void)flags;
+ void *mem = MmapOrDie(sizeof(DD), "deadlock detector");
+ return new(mem) DD(flags);
+}
+
+DD::DD(const DDFlags *flags)
+ : flags(*flags)
+ , free_id(1024) {
+ id_gen = 0;
+}
+
+DDPhysicalThread* DD::CreatePhysicalThread() {
+ DDPhysicalThread *pt = (DDPhysicalThread*)MmapOrDie(sizeof(DDPhysicalThread),
+ "deadlock detector (physical thread)");
+ return pt;
+}
+
+void DD::DestroyPhysicalThread(DDPhysicalThread *pt) {
+ pt->~DDPhysicalThread();
+ UnmapOrDie(pt, sizeof(DDPhysicalThread));
+}
+
+DDLogicalThread* DD::CreateLogicalThread(u64 ctx) {
+ DDLogicalThread *lt = (DDLogicalThread*)InternalAlloc(
+ sizeof(DDLogicalThread));
+ lt->ctx = ctx;
+ lt->nlocked = 0;
+ return lt;
+}
+
+void DD::DestroyLogicalThread(DDLogicalThread *lt) {
+ lt->~DDLogicalThread();
+ InternalFree(lt);
+}
+
+void DD::MutexInit(DDCallback *cb, DDMutex *m) {
+ VPrintf(2, "#%llu: DD::MutexInit(%p)\n", cb->lt->ctx, m);
+ m->id = kNoId;
+ m->recursion = 0;
+ atomic_store(&m->owner, 0, memory_order_relaxed);
+}
+
+Mutex *DD::getMutex(u32 id) {
+ return &mutex[id / kL2Size][id % kL2Size];
+}
+
+u32 DD::getMutexId(Mutex *m) {
+ for (int i = 0; i < kL1Size; i++) {
+ Mutex *tab = mutex[i];
+ if (tab == 0)
+ break;
+ if (m >= tab && m < tab + kL2Size)
+ return i * kL2Size + (m - tab);
+ }
+ return -1;
+}
+
+u32 DD::allocateId(DDCallback *cb) {
+ u32 id = -1;
+ SpinMutexLock l(&mtx);
+ if (free_id.size() > 0) {
+ id = free_id.back();
+ free_id.pop_back();
+ } else {
+ CHECK_LT(id_gen, kMaxMutex);
+ if ((id_gen % kL2Size) == 0) {
+ mutex[id_gen / kL2Size] = (Mutex*)MmapOrDie(kL2Size * sizeof(Mutex),
+ "deadlock detector (mutex table)");
+ }
+ id = id_gen++;
+ }
+ CHECK_LE(id, kMaxMutex);
+ VPrintf(3, "#%llu: DD::allocateId assign id %d\n",
+ cb->lt->ctx, id);
+ return id;
+}
+
+void DD::MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) {
+ VPrintf(2, "#%llu: DD::MutexBeforeLock(%p, wlock=%d) nlocked=%d\n",
+ cb->lt->ctx, m, wlock, cb->lt->nlocked);
+ DDPhysicalThread *pt = cb->pt;
+ DDLogicalThread *lt = cb->lt;
+
+ uptr owner = atomic_load(&m->owner, memory_order_relaxed);
+ if (owner == (uptr)cb->lt) {
+ VPrintf(3, "#%llu: DD::MutexBeforeLock recursive\n",
+ cb->lt->ctx);
+ return;
+ }
+
+ CHECK_LE(lt->nlocked, kMaxNesting);
+
+ // FIXME(dvyukov): don't allocate id if lt->nlocked == 0?
+ if (m->id == kNoId)
+ m->id = allocateId(cb);
+
+ ThreadMutex *tm = &lt->locked[lt->nlocked++];
+ tm->id = m->id;
+ if (flags.second_deadlock_stack)
+ tm->stk = cb->Unwind();
+ if (lt->nlocked == 1) {
+ VPrintf(3, "#%llu: DD::MutexBeforeLock first mutex\n",
+ cb->lt->ctx);
+ return;
+ }
+
+ bool added = false;
+ Mutex *mtx = getMutex(m->id);
+ for (int i = 0; i < lt->nlocked - 1; i++) {
+ u32 id1 = lt->locked[i].id;
+ u32 stk1 = lt->locked[i].stk;
+ Mutex *mtx1 = getMutex(id1);
+ SpinMutexLock l(&mtx1->mtx);
+ if (mtx1->nlink == kMaxLink) {
+ // FIXME(dvyukov): check stale links
+ continue;
+ }
+ int li = 0;
+ for (; li < mtx1->nlink; li++) {
+ Link *link = &mtx1->link[li];
+ if (link->id == m->id) {
+ if (link->seq != mtx->seq) {
+ link->seq = mtx->seq;
+ link->tid = lt->ctx;
+ link->stk0 = stk1;
+ link->stk1 = cb->Unwind();
+ added = true;
+ VPrintf(3, "#%llu: DD::MutexBeforeLock added %d->%d link\n",
+ cb->lt->ctx, getMutexId(mtx1), m->id);
+ }
+ break;
+ }
+ }
+ if (li == mtx1->nlink) {
+ // FIXME(dvyukov): check stale links
+ Link *link = &mtx1->link[mtx1->nlink++];
+ link->id = m->id;
+ link->seq = mtx->seq;
+ link->tid = lt->ctx;
+ link->stk0 = stk1;
+ link->stk1 = cb->Unwind();
+ added = true;
+ VPrintf(3, "#%llu: DD::MutexBeforeLock added %d->%d link\n",
+ cb->lt->ctx, getMutexId(mtx1), m->id);
+ }
+ }
+
+ if (!added || mtx->nlink == 0) {
+ VPrintf(3, "#%llu: DD::MutexBeforeLock don't check\n",
+ cb->lt->ctx);
+ return;
+ }
+
+ CycleCheck(pt, lt, m);
+}
+
+void DD::MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock,
+ bool trylock) {
+ VPrintf(2, "#%llu: DD::MutexAfterLock(%p, wlock=%d, try=%d) nlocked=%d\n",
+ cb->lt->ctx, m, wlock, trylock, cb->lt->nlocked);
+ DDLogicalThread *lt = cb->lt;
+
+ uptr owner = atomic_load(&m->owner, memory_order_relaxed);
+ if (owner == (uptr)cb->lt) {
+ VPrintf(3, "#%llu: DD::MutexAfterLock recursive\n", cb->lt->ctx);
+ CHECK(wlock);
+ m->recursion++;
+ return;
+ }
+ CHECK_EQ(owner, 0);
+ if (wlock) {
+ VPrintf(3, "#%llu: DD::MutexAfterLock set owner\n", cb->lt->ctx);
+ CHECK_EQ(m->recursion, 0);
+ m->recursion = 1;
+ atomic_store(&m->owner, (uptr)cb->lt, memory_order_relaxed);
+ }
+
+ if (!trylock)
+ return;
+
+ CHECK_LE(lt->nlocked, kMaxNesting);
+ if (m->id == kNoId)
+ m->id = allocateId(cb);
+ ThreadMutex *tm = &lt->locked[lt->nlocked++];
+ tm->id = m->id;
+ if (flags.second_deadlock_stack)
+ tm->stk = cb->Unwind();
+}
+
+void DD::MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {
+ VPrintf(2, "#%llu: DD::MutexBeforeUnlock(%p, wlock=%d) nlocked=%d\n",
+ cb->lt->ctx, m, wlock, cb->lt->nlocked);
+ DDLogicalThread *lt = cb->lt;
+
+ uptr owner = atomic_load(&m->owner, memory_order_relaxed);
+ if (owner == (uptr)cb->lt) {
+ VPrintf(3, "#%llu: DD::MutexBeforeUnlock recursive\n", cb->lt->ctx);
+ if (--m->recursion > 0)
+ return;
+ VPrintf(3, "#%llu: DD::MutexBeforeUnlock reset owner\n", cb->lt->ctx);
+ atomic_store(&m->owner, 0, memory_order_relaxed);
+ }
+ CHECK_NE(m->id, kNoId);
+ int last = lt->nlocked - 1;
+ for (int i = last; i >= 0; i--) {
+ if (cb->lt->locked[i].id == m->id) {
+ lt->locked[i] = lt->locked[last];
+ lt->nlocked--;
+ break;
+ }
+ }
+}
+
+void DD::MutexDestroy(DDCallback *cb, DDMutex *m) {
+ VPrintf(2, "#%llu: DD::MutexDestroy(%p)\n",
+ cb->lt->ctx, m);
+ DDLogicalThread *lt = cb->lt;
+
+ if (m->id == kNoId)
+ return;
+
+ // Remove the mutex from lt->locked if there.
+ int last = lt->nlocked - 1;
+ for (int i = last; i >= 0; i--) {
+ if (lt->locked[i].id == m->id) {
+ lt->locked[i] = lt->locked[last];
+ lt->nlocked--;
+ break;
+ }
+ }
+
+ // Clear and invalidate the mutex descriptor.
+ {
+ Mutex *mtx = getMutex(m->id);
+ SpinMutexLock l(&mtx->mtx);
+ mtx->seq++;
+ mtx->nlink = 0;
+ }
+
+ // Return id to cache.
+ {
+ SpinMutexLock l(&mtx);
+ free_id.push_back(m->id);
+ }
+}
+
+void DD::CycleCheck(DDPhysicalThread *pt, DDLogicalThread *lt,
+ DDMutex *m) {
+ internal_memset(pt->visited, 0, sizeof(pt->visited));
+ int npath = 0;
+ int npending = 0;
+ {
+ Mutex *mtx = getMutex(m->id);
+ SpinMutexLock l(&mtx->mtx);
+ for (int li = 0; li < mtx->nlink; li++)
+ pt->pending[npending++] = mtx->link[li];
+ }
+ while (npending > 0) {
+ Link link = pt->pending[--npending];
+ if (link.id == kEndId) {
+ npath--;
+ continue;
+ }
+ if (pt->visited[link.id])
+ continue;
+ Mutex *mtx1 = getMutex(link.id);
+ SpinMutexLock l(&mtx1->mtx);
+ if (mtx1->seq != link.seq)
+ continue;
+ pt->visited[link.id] = true;
+ if (mtx1->nlink == 0)
+ continue;
+ pt->path[npath++] = link;
+ pt->pending[npending++] = Link(kEndId);
+ if (link.id == m->id)
+ return Report(pt, lt, npath); // Bingo!
+ for (int li = 0; li < mtx1->nlink; li++) {
+ Link *link1 = &mtx1->link[li];
+ // Mutex *mtx2 = getMutex(link->id);
+ // FIXME(dvyukov): fast seq check
+ // FIXME(dvyukov): fast nlink != 0 check
+ // FIXME(dvyukov): fast pending check?
+ // FIXME(dvyukov): npending can be larger than kMaxMutex
+ pt->pending[npending++] = *link1;
+ }
+ }
+}
+
+void DD::Report(DDPhysicalThread *pt, DDLogicalThread *lt, int npath) {
+ DDReport *rep = &pt->rep;
+ rep->n = npath;
+ for (int i = 0; i < npath; i++) {
+ Link *link = &pt->path[i];
+ Link *link0 = &pt->path[i ? i - 1 : npath - 1];
+ rep->loop[i].thr_ctx = link->tid;
+ rep->loop[i].mtx_ctx0 = link0->id;
+ rep->loop[i].mtx_ctx1 = link->id;
+ rep->loop[i].stk[0] = flags.second_deadlock_stack ? link->stk0 : 0;
+ rep->loop[i].stk[1] = link->stk1;
+ }
+ pt->report_pending = true;
+}
+
+DDReport *DD::GetReport(DDCallback *cb) {
+ if (!cb->pt->report_pending)
+ return 0;
+ cb->pt->report_pending = false;
+ return &cb->pt->rep;
+}
+
+} // namespace __sanitizer
+#endif // #if SANITIZER_DEADLOCK_DETECTOR_VERSION == 2
diff --git a/libsanitizer/sanitizer_common/sanitizer_deadlock_detector_interface.h b/libsanitizer/sanitizer_common/sanitizer_deadlock_detector_interface.h
new file mode 100644
index 00000000000..59d8d93fe13
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_deadlock_detector_interface.h
@@ -0,0 +1,91 @@
+//===-- sanitizer_deadlock_detector_interface.h -----------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer runtime.
+// Abstract deadlock detector interface.
+// FIXME: this is work in progress, nothing really works yet.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_DEADLOCK_DETECTOR_INTERFACE_H
+#define SANITIZER_DEADLOCK_DETECTOR_INTERFACE_H
+
+#ifndef SANITIZER_DEADLOCK_DETECTOR_VERSION
+# define SANITIZER_DEADLOCK_DETECTOR_VERSION 1
+#endif
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_atomic.h"
+
+namespace __sanitizer {
+
+// dd - deadlock detector.
+// lt - logical (user) thread.
+// pt - physical (OS) thread.
+
+struct DDPhysicalThread;
+struct DDLogicalThread;
+
+struct DDMutex {
+#if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1
+ uptr id;
+ u32 stk; // creation stack
+#elif SANITIZER_DEADLOCK_DETECTOR_VERSION == 2
+ u32 id;
+ u32 recursion;
+ atomic_uintptr_t owner;
+#else
+# error "BAD SANITIZER_DEADLOCK_DETECTOR_VERSION"
+#endif
+ u64 ctx;
+};
+
+struct DDFlags {
+ bool second_deadlock_stack;
+};
+
+struct DDReport {
+ enum { kMaxLoopSize = 8 };
+ int n; // number of entries in loop
+ struct {
+ u64 thr_ctx; // user thread context
+ u64 mtx_ctx0; // user mutex context, start of the edge
+ u64 mtx_ctx1; // user mutex context, end of the edge
+ u32 stk[2]; // stack ids for the edge
+ } loop[kMaxLoopSize];
+};
+
+struct DDCallback {
+ DDPhysicalThread *pt;
+ DDLogicalThread *lt;
+
+ virtual u32 Unwind() { return 0; }
+ virtual int UniqueTid() { return 0; }
+};
+
+struct DDetector {
+ static DDetector *Create(const DDFlags *flags);
+
+ virtual DDPhysicalThread* CreatePhysicalThread() { return 0; }
+ virtual void DestroyPhysicalThread(DDPhysicalThread *pt) {}
+
+ virtual DDLogicalThread* CreateLogicalThread(u64 ctx) { return 0; }
+ virtual void DestroyLogicalThread(DDLogicalThread *lt) {}
+
+ virtual void MutexInit(DDCallback *cb, DDMutex *m) {}
+ virtual void MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) {}
+ virtual void MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock,
+ bool trylock) {}
+ virtual void MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {}
+ virtual void MutexDestroy(DDCallback *cb, DDMutex *m) {}
+
+ virtual DDReport *GetReport(DDCallback *cb) { return 0; }
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_DEADLOCK_DETECTOR_INTERFACE_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_flags.cc b/libsanitizer/sanitizer_common/sanitizer_flags.cc
index 90bb57dff98..e90d79e4360 100644
--- a/libsanitizer/sanitizer_common/sanitizer_flags.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_flags.cc
@@ -13,12 +13,24 @@
#include "sanitizer_common.h"
#include "sanitizer_libc.h"
+#include "sanitizer_list.h"
namespace __sanitizer {
+CommonFlags common_flags_dont_use;
+
+struct FlagDescription {
+ const char *name;
+ const char *description;
+ FlagDescription *next;
+};
+
+IntrusiveList<FlagDescription> flag_descriptions;
+
void SetCommonFlagsDefaults(CommonFlags *f) {
f->symbolize = true;
f->external_symbolizer_path = 0;
+ f->allow_addr2line = false;
f->strip_path_prefix = "";
f->fast_unwind_on_fatal = false;
f->fast_unwind_on_malloc = true;
@@ -26,26 +38,96 @@ void SetCommonFlagsDefaults(CommonFlags *f) {
f->malloc_context_size = 1;
f->log_path = "stderr";
f->verbosity = 0;
- f->detect_leaks = false;
+ f->detect_leaks = true;
f->leak_check_at_exit = true;
f->allocator_may_return_null = false;
f->print_summary = true;
+ f->check_printf = true;
+ // TODO(glider): tools may want to set different defaults for handle_segv.
+ f->handle_segv = SANITIZER_NEEDS_SEGV;
+ f->allow_user_segv_handler = false;
+ f->use_sigaltstack = true;
+ f->detect_deadlocks = false;
+ f->clear_shadow_mmap_threshold = 64 * 1024;
+ f->color = "auto";
+ f->legacy_pthread_cond = false;
+ f->intercept_tls_get_addr = false;
+ f->coverage = false;
+ f->full_address_space = false;
}
void ParseCommonFlagsFromString(CommonFlags *f, const char *str) {
- ParseFlag(str, &f->symbolize, "symbolize");
- ParseFlag(str, &f->external_symbolizer_path, "external_symbolizer_path");
- ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");
- ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal");
- ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc");
- ParseFlag(str, &f->handle_ioctl, "handle_ioctl");
- ParseFlag(str, &f->malloc_context_size, "malloc_context_size");
- ParseFlag(str, &f->log_path, "log_path");
- ParseFlag(str, &f->verbosity, "verbosity");
- ParseFlag(str, &f->detect_leaks, "detect_leaks");
- ParseFlag(str, &f->leak_check_at_exit, "leak_check_at_exit");
- ParseFlag(str, &f->allocator_may_return_null, "allocator_may_return_null");
- ParseFlag(str, &f->print_summary, "print_summary");
+ ParseFlag(str, &f->symbolize, "symbolize",
+ "If set, use the online symbolizer from common sanitizer runtime to turn "
+ "virtual addresses to file/line locations.");
+ ParseFlag(str, &f->external_symbolizer_path, "external_symbolizer_path",
+ "Path to external symbolizer. If empty, the tool will search $PATH for "
+ "the symbolizer.");
+ ParseFlag(str, &f->allow_addr2line, "allow_addr2line",
+ "If set, allows online symbolizer to run addr2line binary to symbolize "
+ "stack traces (addr2line will only be used if llvm-symbolizer binary is "
+ "unavailable.");
+ ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix",
+ "Strips this prefix from file paths in error reports.");
+ ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal",
+ "If available, use the fast frame-pointer-based unwinder on fatal "
+ "errors.");
+ ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc",
+ "If available, use the fast frame-pointer-based unwinder on "
+ "malloc/free.");
+ ParseFlag(str, &f->handle_ioctl, "handle_ioctl",
+ "Intercept and handle ioctl requests.");
+ ParseFlag(str, &f->malloc_context_size, "malloc_context_size",
+ "Max number of stack frames kept for each allocation/deallocation.");
+ ParseFlag(str, &f->log_path, "log_path",
+ "Write logs to \"log_path.pid\". The special values are \"stdout\" and "
+ "\"stderr\". The default is \"stderr\".");
+ ParseFlag(str, &f->verbosity, "verbosity",
+ "Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).");
+ ParseFlag(str, &f->detect_leaks, "detect_leaks",
+ "Enable memory leak detection.");
+ ParseFlag(str, &f->leak_check_at_exit, "leak_check_at_exit",
+ "Invoke leak checking in an atexit handler. Has no effect if "
+ "detect_leaks=false, or if __lsan_do_leak_check() is called before the "
+ "handler has a chance to run.");
+ ParseFlag(str, &f->allocator_may_return_null, "allocator_may_return_null",
+ "If false, the allocator will crash instead of returning 0 on "
+ "out-of-memory.");
+ ParseFlag(str, &f->print_summary, "print_summary",
+ "If false, disable printing error summaries in addition to error "
+ "reports.");
+ ParseFlag(str, &f->check_printf, "check_printf",
+ "Check printf arguments.");
+ ParseFlag(str, &f->handle_segv, "handle_segv",
+ "If set, registers the tool's custom SEGV handler (both SIGBUS and "
+ "SIGSEGV on OSX).");
+ ParseFlag(str, &f->allow_user_segv_handler, "allow_user_segv_handler",
+ "If set, allows user to register a SEGV handler even if the tool "
+ "registers one.");
+ ParseFlag(str, &f->use_sigaltstack, "use_sigaltstack",
+ "If set, uses alternate stack for signal handling.");
+ ParseFlag(str, &f->detect_deadlocks, "detect_deadlocks",
+ "If set, deadlock detection is enabled.");
+ ParseFlag(str, &f->clear_shadow_mmap_threshold,
+ "clear_shadow_mmap_threshold",
+ "Large shadow regions are zero-filled using mmap(NORESERVE) instead of "
+ "memset(). This is the threshold size in bytes.");
+ ParseFlag(str, &f->color, "color",
+ "Colorize reports: (always|never|auto).");
+ ParseFlag(str, &f->legacy_pthread_cond, "legacy_pthread_cond",
+ "Enables support for dynamic libraries linked with libpthread 2.2.5.");
+ ParseFlag(str, &f->intercept_tls_get_addr, "intercept_tls_get_addr",
+ "Intercept __tls_get_addr.");
+ ParseFlag(str, &f->help, "help", "Print the flag descriptions.");
+ ParseFlag(str, &f->mmap_limit_mb, "mmap_limit_mb",
+ "Limit the amount of mmap-ed memory (excluding shadow) in Mb; "
+ "not a user-facing flag, used mosly for testing the tools");
+ ParseFlag(str, &f->coverage, "coverage",
+ "If set, coverage information will be dumped at program shutdown (if the "
+ "coverage instrumentation was enabled at compile time).");
+ ParseFlag(str, &f->full_address_space, "full_address_space",
+ "Sanitize complete address space; "
+ "by default kernel area on 32-bit platforms will not be sanitized");
// Do a sanity check for certain flags.
if (f->malloc_context_size < 1)
@@ -100,9 +182,40 @@ static bool StartsWith(const char *flag, int flag_length, const char *value) {
(0 == internal_strncmp(flag, value, value_length));
}
-void ParseFlag(const char *env, bool *flag, const char *name) {
+static LowLevelAllocator allocator_for_flags;
+
+// The linear scan is suboptimal, but the number of flags is relatively small.
+bool FlagInDescriptionList(const char *name) {
+ IntrusiveList<FlagDescription>::Iterator it(&flag_descriptions);
+ while (it.hasNext()) {
+ if (!internal_strcmp(it.next()->name, name)) return true;
+ }
+ return false;
+}
+
+void AddFlagDescription(const char *name, const char *description) {
+ if (FlagInDescriptionList(name)) return;
+ FlagDescription *new_description = new(allocator_for_flags) FlagDescription;
+ new_description->name = name;
+ new_description->description = description;
+ flag_descriptions.push_back(new_description);
+}
+
+// TODO(glider): put the descriptions inside CommonFlags.
+void PrintFlagDescriptions() {
+ IntrusiveList<FlagDescription>::Iterator it(&flag_descriptions);
+ Printf("Available flags for %s:\n", SanitizerToolName);
+ while (it.hasNext()) {
+ FlagDescription *descr = it.next();
+ Printf("\t%s\n\t\t- %s\n", descr->name, descr->description);
+ }
+}
+
+void ParseFlag(const char *env, bool *flag,
+ const char *name, const char *descr) {
const char *value;
int value_length;
+ AddFlagDescription(name, descr);
if (!GetFlagValue(env, name, &value, &value_length))
return;
if (StartsWith(value, value_length, "0") ||
@@ -115,19 +228,31 @@ void ParseFlag(const char *env, bool *flag, const char *name) {
*flag = true;
}
-void ParseFlag(const char *env, int *flag, const char *name) {
+void ParseFlag(const char *env, int *flag,
+ const char *name, const char *descr) {
const char *value;
int value_length;
+ AddFlagDescription(name, descr);
if (!GetFlagValue(env, name, &value, &value_length))
return;
*flag = static_cast<int>(internal_atoll(value));
}
-static LowLevelAllocator allocator_for_flags;
+void ParseFlag(const char *env, uptr *flag,
+ const char *name, const char *descr) {
+ const char *value;
+ int value_length;
+ AddFlagDescription(name, descr);
+ if (!GetFlagValue(env, name, &value, &value_length))
+ return;
+ *flag = static_cast<uptr>(internal_atoll(value));
+}
-void ParseFlag(const char *env, const char **flag, const char *name) {
+void ParseFlag(const char *env, const char **flag,
+ const char *name, const char *descr) {
const char *value;
int value_length;
+ AddFlagDescription(name, descr);
if (!GetFlagValue(env, name, &value, &value_length))
return;
// Copy the flag value. Don't use locks here, as flags are parsed at
diff --git a/libsanitizer/sanitizer_common/sanitizer_flags.h b/libsanitizer/sanitizer_common/sanitizer_flags.h
index 46ec0928193..107b6776b3a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_flags.h
+++ b/libsanitizer/sanitizer_common/sanitizer_flags.h
@@ -16,51 +16,53 @@
namespace __sanitizer {
-void ParseFlag(const char *env, bool *flag, const char *name);
-void ParseFlag(const char *env, int *flag, const char *name);
-void ParseFlag(const char *env, const char **flag, const char *name);
+void ParseFlag(const char *env, bool *flag,
+ const char *name, const char *descr);
+void ParseFlag(const char *env, int *flag,
+ const char *name, const char *descr);
+void ParseFlag(const char *env, uptr *flag,
+ const char *name, const char *descr);
+void ParseFlag(const char *env, const char **flag,
+ const char *name, const char *descr);
struct CommonFlags {
- // If set, use the online symbolizer from common sanitizer runtime.
bool symbolize;
- // Path to external symbolizer. If it is NULL, symbolizer will be looked for
- // in PATH. If it is empty, external symbolizer will not be started.
const char *external_symbolizer_path;
- // Strips this prefix from file paths in error reports.
+ bool allow_addr2line;
const char *strip_path_prefix;
- // Use fast (frame-pointer-based) unwinder on fatal errors (if available).
bool fast_unwind_on_fatal;
- // Use fast (frame-pointer-based) unwinder on malloc/free (if available).
bool fast_unwind_on_malloc;
- // Intercept and handle ioctl requests.
bool handle_ioctl;
- // Max number of stack frames kept for each allocation/deallocation.
int malloc_context_size;
- // Write logs to "log_path.pid".
- // The special values are "stdout" and "stderr".
- // The default is "stderr".
const char *log_path;
- // Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).
int verbosity;
- // Enable memory leak detection.
bool detect_leaks;
- // Invoke leak checking in an atexit handler. Has no effect if
- // detect_leaks=false, or if __lsan_do_leak_check() is called before the
- // handler has a chance to run.
bool leak_check_at_exit;
- // If false, the allocator will crash instead of returning 0 on out-of-memory.
bool allocator_may_return_null;
- // If false, disable printing error summaries in addition to error reports.
bool print_summary;
+ bool check_printf;
+ bool handle_segv;
+ bool allow_user_segv_handler;
+ bool use_sigaltstack;
+ bool detect_deadlocks;
+ uptr clear_shadow_mmap_threshold;
+ const char *color;
+ bool legacy_pthread_cond;
+ bool intercept_tls_get_addr;
+ bool help;
+ uptr mmap_limit_mb;
+ bool coverage;
+ bool full_address_space;
};
inline CommonFlags *common_flags() {
- static CommonFlags f;
- return &f;
+ extern CommonFlags common_flags_dont_use;
+ return &common_flags_dont_use;
}
void SetCommonFlagsDefaults(CommonFlags *f);
void ParseCommonFlagsFromString(CommonFlags *f, const char *str);
+void PrintFlagDescriptions();
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_interception.h b/libsanitizer/sanitizer_common/sanitizer_interception.h
new file mode 100644
index 00000000000..2346fa859b1
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_interception.h
@@ -0,0 +1,23 @@
+//===-- sanitizer_interception.h --------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Common macro definitions for interceptors.
+// Always use this headers instead of interception/interception.h.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_INTERCEPTION_H
+#define SANITIZER_INTERCEPTION_H
+
+#include "interception/interception.h"
+#include "sanitizer_common.h"
+
+#if SANITIZER_LINUX && !defined(SANITIZER_GO)
+#undef REAL
+#define REAL(x) IndirectExternCall(__interception::PTR_TO_REAL(x))
+#endif
+
+#endif // SANITIZER_INTERCEPTION_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
index 0dab7c2f6c7..a925d306b61 100644
--- a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
+++ b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
@@ -32,10 +32,9 @@
# define SANITIZER_SUPPORTS_WEAK_HOOKS 0
#endif
-#if __LP64__ || defined(_WIN64)
-# define SANITIZER_WORDSIZE 64
-#else
-# define SANITIZER_WORDSIZE 32
+// If set, the tool will install its own SEGV signal handler.
+#ifndef SANITIZER_NEEDS_SEGV
+# define SANITIZER_NEEDS_SEGV 1
#endif
// GCC does not understand __has_feature
@@ -57,7 +56,7 @@ typedef unsigned long uptr; // NOLINT
typedef signed long sptr; // NOLINT
#endif // defined(_WIN64)
#if defined(__x86_64__)
-// Since x32 uses ILP32 data model in 64-bit hardware mode, we must use
+// Since x32 uses ILP32 data model in 64-bit hardware mode, we must use
// 64-bit pointer to unwind stack frame.
typedef unsigned long long uhwptr; // NOLINT
#else
@@ -97,11 +96,15 @@ extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
void __sanitizer_set_report_path(const char *path);
- // Notify the tools that the sandbox is going to be turned on. The reserved
- // parameter will be used in the future to hold a structure with functions
- // that the tools may call to bypass the sandbox.
- SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
- void __sanitizer_sandbox_on_notify(void *reserved);
+ typedef struct {
+ int coverage_sandboxed;
+ __sanitizer::sptr coverage_fd;
+ unsigned int coverage_max_block_size;
+ } __sanitizer_sandbox_arguments;
+
+ // Notify the tools that the sandbox is going to be turned on.
+ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+ __sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args);
// This function is called by the tool when it has just finished reporting
// an error. 'error_summary' is a one-line string that summarizes
@@ -110,12 +113,16 @@ extern "C" {
void __sanitizer_report_error_summary(const char *error_summary);
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump();
- SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov(void *pc);
+ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init();
+ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov();
SANITIZER_INTERFACE_ATTRIBUTE
void __sanitizer_annotate_contiguous_container(const void *beg,
const void *end,
const void *old_mid,
const void *new_mid);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ int __sanitizer_verify_contiguous_container(const void *beg, const void *mid,
+ const void *end);
} // extern "C"
@@ -141,8 +148,6 @@ using namespace __sanitizer; // NOLINT
# define NOTHROW
# define LIKELY(x) (x)
# define UNLIKELY(x) (x)
-# define UNUSED
-# define USED
# define PREFETCH(x) /* _mm_prefetch(x, _MM_HINT_NTA) */
#else // _MSC_VER
# define ALWAYS_INLINE inline __attribute__((always_inline))
@@ -157,8 +162,6 @@ using namespace __sanitizer; // NOLINT
# define NOTHROW throw()
# define LIKELY(x) __builtin_expect(!!(x), 1)
# define UNLIKELY(x) __builtin_expect(!!(x), 0)
-# define UNUSED __attribute__((unused))
-# define USED __attribute__((used))
# if defined(__i386__) || defined(__x86_64__)
// __builtin_prefetch(x) generates prefetchnt0 on x86
# define PREFETCH(x) __asm__("prefetchnta (%0)" : : "r" (x))
@@ -167,6 +170,14 @@ using namespace __sanitizer; // NOLINT
# endif
#endif // _MSC_VER
+#if !defined(_MSC_VER) || defined(__clang__)
+# define UNUSED __attribute__((unused))
+# define USED __attribute__((used))
+#else
+# define UNUSED
+# define USED
+#endif
+
// Unaligned versions of basic types.
typedef ALIGNED(1) u16 uu16;
typedef ALIGNED(1) u32 uu32;
@@ -197,7 +208,7 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
// Check macro
#define RAW_CHECK_MSG(expr, msg) do { \
- if (!(expr)) { \
+ if (UNLIKELY(!(expr))) { \
RawWrite(msg); \
Die(); \
} \
@@ -209,7 +220,7 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
do { \
__sanitizer::u64 v1 = (u64)(c1); \
__sanitizer::u64 v2 = (u64)(c2); \
- if (!(v1 op v2)) \
+ if (UNLIKELY(!(v1 op v2))) \
__sanitizer::CheckFailed(__FILE__, __LINE__, \
"(" #c1 ") " #op " (" #c2 ")", v1, v2); \
} while (false) \
diff --git a/libsanitizer/sanitizer_common/sanitizer_libc.cc b/libsanitizer/sanitizer_common/sanitizer_libc.cc
index 53c87555092..c13a66d88cd 100644
--- a/libsanitizer/sanitizer_common/sanitizer_libc.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_libc.cc
@@ -16,7 +16,7 @@ namespace __sanitizer {
// Make the compiler think that something is going on there.
static inline void break_optimization(void *arg) {
-#if SANITIZER_WINDOWS
+#if _MSC_VER
// FIXME: make sure this is actually enough.
__asm;
#else
diff --git a/libsanitizer/sanitizer_common/sanitizer_libc.h b/libsanitizer/sanitizer_common/sanitizer_libc.h
index ae23bc45e9d..fd03b791c58 100644
--- a/libsanitizer/sanitizer_common/sanitizer_libc.h
+++ b/libsanitizer/sanitizer_common/sanitizer_libc.h
@@ -89,12 +89,16 @@ uptr internal_waitpid(int pid, int *status, int options);
uptr internal_getpid();
uptr internal_getppid();
+int internal_fork();
+
// Threading
uptr internal_sched_yield();
// Error handling
bool internal_iserror(uptr retval, int *rverrno = 0);
+int internal_sigaction(int signum, const void *act, void *oldact);
+
} // namespace __sanitizer
#endif // SANITIZER_LIBC_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_libignore.cc b/libsanitizer/sanitizer_common/sanitizer_libignore.cc
index 310e811df1d..c88550dec8d 100644
--- a/libsanitizer/sanitizer_common/sanitizer_libignore.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_libignore.cc
@@ -74,9 +74,10 @@ void LibIgnore::OnLibraryLoaded(const char *name) {
loaded = true;
if (lib->loaded)
continue;
- if (common_flags()->verbosity)
- Report("Matched called_from_lib suppression '%s' against library"
- " '%s'\n", lib->templ, module.data());
+ VReport(1,
+ "Matched called_from_lib suppression '%s' against library"
+ " '%s'\n",
+ lib->templ, module.data());
lib->loaded = true;
lib->name = internal_strdup(module.data());
const uptr idx = atomic_load(&loaded_count_, memory_order_relaxed);
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_linux.cc
index 69c9c1063f0..faa85acd696 100644
--- a/libsanitizer/sanitizer_common/sanitizer_linux.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_linux.cc
@@ -11,9 +11,10 @@
//===----------------------------------------------------------------------===//
#include "sanitizer_platform.h"
-#if SANITIZER_LINUX
+#if SANITIZER_FREEBSD || SANITIZER_LINUX
#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_libc.h"
#include "sanitizer_linux.h"
@@ -23,7 +24,10 @@
#include "sanitizer_stacktrace.h"
#include "sanitizer_symbolizer.h"
+#if !SANITIZER_FREEBSD
#include <asm/param.h>
+#endif
+
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
@@ -42,10 +46,25 @@
#include <unistd.h>
#include <unwind.h>
+#if SANITIZER_FREEBSD
+#include <machine/atomic.h>
+extern "C" {
+// <sys/umtx.h> must be included after <errno.h> and <sys/types.h> on
+// FreeBSD 9.2 and 10.0.
+#include <sys/umtx.h>
+}
+#endif // SANITIZER_FREEBSD
+
#if !SANITIZER_ANDROID
#include <sys/signal.h>
#endif
+#if SANITIZER_ANDROID
+#include <android/log.h>
+#include <sys/system_properties.h>
+#endif
+
+#if SANITIZER_LINUX
// <linux/time.h>
struct kernel_timeval {
long tv_sec;
@@ -55,11 +74,12 @@ struct kernel_timeval {
// <linux/futex.h> is broken on some linux distributions.
const int FUTEX_WAIT = 0;
const int FUTEX_WAKE = 1;
+#endif // SANITIZER_LINUX
-// Are we using 32-bit or 64-bit syscalls?
+// Are we using 32-bit or 64-bit Linux syscalls?
// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
// but it still needs to use 64-bit syscalls.
-#if defined(__x86_64__) || SANITIZER_WORDSIZE == 64
+#if SANITIZER_LINUX && (defined(__x86_64__) || SANITIZER_WORDSIZE == 64)
# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
#else
# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
@@ -67,7 +87,7 @@ const int FUTEX_WAKE = 1;
namespace __sanitizer {
-#ifdef __x86_64__
+#if SANITIZER_LINUX && defined(__x86_64__)
#include "sanitizer_syscall_linux_x86_64.inc"
#else
#include "sanitizer_syscall_generic.inc"
@@ -76,28 +96,38 @@ namespace __sanitizer {
// --------------- sanitizer_libc.h
uptr internal_mmap(void *addr, uptr length, int prot, int flags,
int fd, u64 offset) {
-#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
- return internal_syscall(__NR_mmap, (uptr)addr, length, prot, flags, fd,
+#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
+ return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,
offset);
#else
- return internal_syscall(__NR_mmap2, addr, length, prot, flags, fd, offset);
+ return internal_syscall(SYSCALL(mmap2), addr, length, prot, flags, fd,
+ offset);
#endif
}
uptr internal_munmap(void *addr, uptr length) {
- return internal_syscall(__NR_munmap, (uptr)addr, length);
+ return internal_syscall(SYSCALL(munmap), (uptr)addr, length);
}
uptr internal_close(fd_t fd) {
- return internal_syscall(__NR_close, fd);
+ return internal_syscall(SYSCALL(close), fd);
}
uptr internal_open(const char *filename, int flags) {
- return internal_syscall(__NR_open, (uptr)filename, flags);
+#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+ return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags);
+#else
+ return internal_syscall(SYSCALL(open), (uptr)filename, flags);
+#endif
}
uptr internal_open(const char *filename, int flags, u32 mode) {
- return internal_syscall(__NR_open, (uptr)filename, flags, mode);
+#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+ return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags,
+ mode);
+#else
+ return internal_syscall(SYSCALL(open), (uptr)filename, flags, mode);
+#endif
}
uptr OpenFile(const char *filename, bool write) {
@@ -107,17 +137,19 @@ uptr OpenFile(const char *filename, bool write) {
uptr internal_read(fd_t fd, void *buf, uptr count) {
sptr res;
- HANDLE_EINTR(res, (sptr)internal_syscall(__NR_read, fd, (uptr)buf, count));
+ HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf,
+ count));
return res;
}
uptr internal_write(fd_t fd, const void *buf, uptr count) {
sptr res;
- HANDLE_EINTR(res, (sptr)internal_syscall(__NR_write, fd, (uptr)buf, count));
+ HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(write), fd, (uptr)buf,
+ count));
return res;
}
-#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS
+#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS && !SANITIZER_FREEBSD
static void stat64_to_stat(struct stat64 *in, struct stat *out) {
internal_memset(out, 0, sizeof(*out));
out->st_dev = in->st_dev;
@@ -138,33 +170,43 @@ static void stat64_to_stat(struct stat64 *in, struct stat *out) {
#endif
uptr internal_stat(const char *path, void *buf) {
-#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
- return internal_syscall(__NR_stat, (uptr)path, (uptr)buf);
+#if SANITIZER_FREEBSD
+ return internal_syscall(SYSCALL(stat), path, buf);
+#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+ return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path,
+ (uptr)buf, 0);
+#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
+ return internal_syscall(SYSCALL(stat), (uptr)path, (uptr)buf);
#else
struct stat64 buf64;
- int res = internal_syscall(__NR_stat64, path, &buf64);
+ int res = internal_syscall(SYSCALL(stat64), path, &buf64);
stat64_to_stat(&buf64, (struct stat *)buf);
return res;
#endif
}
uptr internal_lstat(const char *path, void *buf) {
-#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
- return internal_syscall(__NR_lstat, (uptr)path, (uptr)buf);
+#if SANITIZER_FREEBSD
+ return internal_syscall(SYSCALL(lstat), path, buf);
+#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+ return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path,
+ (uptr)buf, AT_SYMLINK_NOFOLLOW);
+#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
+ return internal_syscall(SYSCALL(lstat), (uptr)path, (uptr)buf);
#else
struct stat64 buf64;
- int res = internal_syscall(__NR_lstat64, path, &buf64);
+ int res = internal_syscall(SYSCALL(lstat64), path, &buf64);
stat64_to_stat(&buf64, (struct stat *)buf);
return res;
#endif
}
uptr internal_fstat(fd_t fd, void *buf) {
-#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
- return internal_syscall(__NR_fstat, fd, (uptr)buf);
+#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
+ return internal_syscall(SYSCALL(fstat), fd, (uptr)buf);
#else
struct stat64 buf64;
- int res = internal_syscall(__NR_fstat64, fd, &buf64);
+ int res = internal_syscall(SYSCALL(fstat64), fd, &buf64);
stat64_to_stat(&buf64, (struct stat *)buf);
return res;
#endif
@@ -178,48 +220,80 @@ uptr internal_filesize(fd_t fd) {
}
uptr internal_dup2(int oldfd, int newfd) {
- return internal_syscall(__NR_dup2, oldfd, newfd);
+#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+ return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0);
+#else
+ return internal_syscall(SYSCALL(dup2), oldfd, newfd);
+#endif
}
uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
- return internal_syscall(__NR_readlink, (uptr)path, (uptr)buf, bufsize);
+#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+ return internal_syscall(SYSCALL(readlinkat), AT_FDCWD,
+ (uptr)path, (uptr)buf, bufsize);
+#else
+ return internal_syscall(SYSCALL(readlink), (uptr)path, (uptr)buf, bufsize);
+#endif
}
uptr internal_unlink(const char *path) {
- return internal_syscall(__NR_unlink, (uptr)path);
+#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+ return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0);
+#else
+ return internal_syscall(SYSCALL(unlink), (uptr)path);
+#endif
}
uptr internal_sched_yield() {
- return internal_syscall(__NR_sched_yield);
+ return internal_syscall(SYSCALL(sched_yield));
}
void internal__exit(int exitcode) {
- internal_syscall(__NR_exit_group, exitcode);
+#if SANITIZER_FREEBSD
+ internal_syscall(SYSCALL(exit), exitcode);
+#else
+ internal_syscall(SYSCALL(exit_group), exitcode);
+#endif
Die(); // Unreachable.
}
uptr internal_execve(const char *filename, char *const argv[],
char *const envp[]) {
- return internal_syscall(__NR_execve, (uptr)filename, (uptr)argv, (uptr)envp);
+ return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv,
+ (uptr)envp);
}
// ----------------- sanitizer_common.h
bool FileExists(const char *filename) {
+#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+ struct stat st;
+ if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0))
+ return false;
+#else
struct stat st;
if (internal_stat(filename, &st))
return false;
// Sanity check: filename is a regular file.
return S_ISREG(st.st_mode);
+#endif
}
uptr GetTid() {
- return internal_syscall(__NR_gettid);
+#if SANITIZER_FREEBSD
+ return (uptr)pthread_self();
+#else
+ return internal_syscall(SYSCALL(gettid));
+#endif
}
u64 NanoTime() {
+#if SANITIZER_FREEBSD
+ timeval tv;
+#else
kernel_timeval tv;
+#endif
internal_memset(&tv, 0, sizeof(tv));
- internal_syscall(__NR_gettimeofday, (uptr)&tv, 0);
+ internal_syscall(SYSCALL(gettimeofday), (uptr)&tv, 0);
return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
}
@@ -303,7 +377,18 @@ void ReExec() {
Die();
}
-void PrepareForSandboxing() {
+// Stub implementation of GetThreadStackAndTls for Go.
+#if SANITIZER_GO
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+ uptr *tls_addr, uptr *tls_size) {
+ *stk_addr = 0;
+ *stk_size = 0;
+ *tls_addr = 0;
+ *tls_size = 0;
+}
+#endif // SANITIZER_GO
+
+void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
// Some kinds of sandboxes may forbid filesystem access, so we won't be able
// to read the file mappings from /proc/self/maps. Luckily, neither the
// process will be able to load additional libraries, so it's fine to use the
@@ -313,216 +398,10 @@ void PrepareForSandboxing() {
#if !SANITIZER_GO
if (Symbolizer *sym = Symbolizer::GetOrNull())
sym->PrepareForSandboxing();
+ CovPrepareForSandboxing(args);
#endif
}
-// ----------------- sanitizer_procmaps.h
-// Linker initialized.
-ProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_;
-StaticSpinMutex MemoryMappingLayout::cache_lock_; // Linker initialized.
-
-MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
- proc_self_maps_.len =
- ReadFileToBuffer("/proc/self/maps", &proc_self_maps_.data,
- &proc_self_maps_.mmaped_size, 1 << 26);
- if (cache_enabled) {
- if (proc_self_maps_.mmaped_size == 0) {
- LoadFromCache();
- CHECK_GT(proc_self_maps_.len, 0);
- }
- } else {
- CHECK_GT(proc_self_maps_.mmaped_size, 0);
- }
- Reset();
- // FIXME: in the future we may want to cache the mappings on demand only.
- if (cache_enabled)
- CacheMemoryMappings();
-}
-
-MemoryMappingLayout::~MemoryMappingLayout() {
- // Only unmap the buffer if it is different from the cached one. Otherwise
- // it will be unmapped when the cache is refreshed.
- if (proc_self_maps_.data != cached_proc_self_maps_.data) {
- UnmapOrDie(proc_self_maps_.data, proc_self_maps_.mmaped_size);
- }
-}
-
-void MemoryMappingLayout::Reset() {
- current_ = proc_self_maps_.data;
-}
-
-// static
-void MemoryMappingLayout::CacheMemoryMappings() {
- SpinMutexLock l(&cache_lock_);
- // Don't invalidate the cache if the mappings are unavailable.
- ProcSelfMapsBuff old_proc_self_maps;
- old_proc_self_maps = cached_proc_self_maps_;
- cached_proc_self_maps_.len =
- ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_.data,
- &cached_proc_self_maps_.mmaped_size, 1 << 26);
- if (cached_proc_self_maps_.mmaped_size == 0) {
- cached_proc_self_maps_ = old_proc_self_maps;
- } else {
- if (old_proc_self_maps.mmaped_size) {
- UnmapOrDie(old_proc_self_maps.data,
- old_proc_self_maps.mmaped_size);
- }
- }
-}
-
-void MemoryMappingLayout::LoadFromCache() {
- SpinMutexLock l(&cache_lock_);
- if (cached_proc_self_maps_.data) {
- proc_self_maps_ = cached_proc_self_maps_;
- }
-}
-
-// Parse a hex value in str and update str.
-static uptr ParseHex(char **str) {
- uptr x = 0;
- char *s;
- for (s = *str; ; s++) {
- char c = *s;
- uptr v = 0;
- if (c >= '0' && c <= '9')
- v = c - '0';
- else if (c >= 'a' && c <= 'f')
- v = c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- v = c - 'A' + 10;
- else
- break;
- x = x * 16 + v;
- }
- *str = s;
- return x;
-}
-
-static bool IsOneOf(char c, char c1, char c2) {
- return c == c1 || c == c2;
-}
-
-static bool IsDecimal(char c) {
- return c >= '0' && c <= '9';
-}
-
-static bool IsHex(char c) {
- return (c >= '0' && c <= '9')
- || (c >= 'a' && c <= 'f');
-}
-
-static uptr ReadHex(const char *p) {
- uptr v = 0;
- for (; IsHex(p[0]); p++) {
- if (p[0] >= '0' && p[0] <= '9')
- v = v * 16 + p[0] - '0';
- else
- v = v * 16 + p[0] - 'a' + 10;
- }
- return v;
-}
-
-static uptr ReadDecimal(const char *p) {
- uptr v = 0;
- for (; IsDecimal(p[0]); p++)
- v = v * 10 + p[0] - '0';
- return v;
-}
-
-
-bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
- char filename[], uptr filename_size,
- uptr *protection) {
- char *last = proc_self_maps_.data + proc_self_maps_.len;
- if (current_ >= last) return false;
- uptr dummy;
- if (!start) start = &dummy;
- if (!end) end = &dummy;
- if (!offset) offset = &dummy;
- char *next_line = (char*)internal_memchr(current_, '\n', last - current_);
- if (next_line == 0)
- next_line = last;
- // Example: 08048000-08056000 r-xp 00000000 03:0c 64593 /foo/bar
- *start = ParseHex(&current_);
- CHECK_EQ(*current_++, '-');
- *end = ParseHex(&current_);
- CHECK_EQ(*current_++, ' ');
- uptr local_protection = 0;
- CHECK(IsOneOf(*current_, '-', 'r'));
- if (*current_++ == 'r')
- local_protection |= kProtectionRead;
- CHECK(IsOneOf(*current_, '-', 'w'));
- if (*current_++ == 'w')
- local_protection |= kProtectionWrite;
- CHECK(IsOneOf(*current_, '-', 'x'));
- if (*current_++ == 'x')
- local_protection |= kProtectionExecute;
- CHECK(IsOneOf(*current_, 's', 'p'));
- if (*current_++ == 's')
- local_protection |= kProtectionShared;
- if (protection) {
- *protection = local_protection;
- }
- CHECK_EQ(*current_++, ' ');
- *offset = ParseHex(&current_);
- CHECK_EQ(*current_++, ' ');
- ParseHex(&current_);
- CHECK_EQ(*current_++, ':');
- ParseHex(&current_);
- CHECK_EQ(*current_++, ' ');
- while (IsDecimal(*current_))
- current_++;
- // Qemu may lack the trailing space.
- // http://code.google.com/p/address-sanitizer/issues/detail?id=160
- // CHECK_EQ(*current_++, ' ');
- // Skip spaces.
- while (current_ < next_line && *current_ == ' ')
- current_++;
- // Fill in the filename.
- uptr i = 0;
- while (current_ < next_line) {
- if (filename && i < filename_size - 1)
- filename[i++] = *current_;
- current_++;
- }
- if (filename && i < filename_size)
- filename[i] = 0;
- current_ = next_line + 1;
- return true;
-}
-
-// Gets the object name and the offset by walking MemoryMappingLayout.
-bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
- char filename[],
- uptr filename_size,
- uptr *protection) {
- return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
- protection);
-}
-
-void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) {
- char *smaps = 0;
- uptr smaps_cap = 0;
- uptr smaps_len = ReadFileToBuffer("/proc/self/smaps",
- &smaps, &smaps_cap, 64<<20);
- uptr start = 0;
- bool file = false;
- const char *pos = smaps;
- while (pos < smaps + smaps_len) {
- if (IsHex(pos[0])) {
- start = ReadHex(pos);
- for (; *pos != '/' && *pos > '\n'; pos++) {}
- file = *pos == '/';
- } else if (internal_strncmp(pos, "Rss:", 4) == 0) {
- for (; *pos < '0' || *pos > '9'; pos++) {}
- uptr rss = ReadDecimal(pos) * 1024;
- cb(start, rss, file, stats, stats_size);
- }
- while (*pos++ != '\n') {}
- }
- UnmapOrDie(smaps, smaps_cap);
-}
-
enum MutexState {
MtxUnlocked = 0,
MtxLocked = 1,
@@ -541,16 +420,26 @@ void BlockingMutex::Lock() {
atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
return;
- while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked)
- internal_syscall(__NR_futex, (uptr)m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
+ while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
+#if SANITIZER_FREEBSD
+ _umtx_op(m, UMTX_OP_WAIT_UINT, MtxSleeping, 0, 0);
+#else
+ internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
+#endif
+ }
}
void BlockingMutex::Unlock() {
atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed);
CHECK_NE(v, MtxUnlocked);
- if (v == MtxSleeping)
- internal_syscall(__NR_futex, (uptr)m, FUTEX_WAKE, 1, 0, 0, 0);
+ if (v == MtxSleeping) {
+#if SANITIZER_FREEBSD
+ _umtx_op(m, UMTX_OP_WAKE, 1, 0, 0);
+#else
+ internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAKE, 1, 0, 0, 0);
+#endif
+ }
}
void BlockingMutex::CheckLocked() {
@@ -563,71 +452,133 @@ void BlockingMutex::CheckLocked() {
// Note that getdents64 uses a different structure format. We only provide the
// 32-bit syscall here.
struct linux_dirent {
+#if SANITIZER_X32
+ u64 d_ino;
+ u64 d_off;
+#else
unsigned long d_ino;
unsigned long d_off;
+#endif
unsigned short d_reclen;
char d_name[256];
};
// Syscall wrappers.
uptr internal_ptrace(int request, int pid, void *addr, void *data) {
- return internal_syscall(__NR_ptrace, request, pid, (uptr)addr, (uptr)data);
+ return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr,
+ (uptr)data);
}
uptr internal_waitpid(int pid, int *status, int options) {
- return internal_syscall(__NR_wait4, pid, (uptr)status, options,
+ return internal_syscall(SYSCALL(wait4), pid, (uptr)status, options,
0 /* rusage */);
}
uptr internal_getpid() {
- return internal_syscall(__NR_getpid);
+ return internal_syscall(SYSCALL(getpid));
}
uptr internal_getppid() {
- return internal_syscall(__NR_getppid);
+ return internal_syscall(SYSCALL(getppid));
}
uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
- return internal_syscall(__NR_getdents, fd, (uptr)dirp, count);
+#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+ return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count);
+#else
+ return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count);
+#endif
}
uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
- return internal_syscall(__NR_lseek, fd, offset, whence);
+ return internal_syscall(SYSCALL(lseek), fd, offset, whence);
}
+#if SANITIZER_LINUX
uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
- return internal_syscall(__NR_prctl, option, arg2, arg3, arg4, arg5);
+ return internal_syscall(SYSCALL(prctl), option, arg2, arg3, arg4, arg5);
}
+#endif
uptr internal_sigaltstack(const struct sigaltstack *ss,
struct sigaltstack *oss) {
- return internal_syscall(__NR_sigaltstack, (uptr)ss, (uptr)oss);
+ return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss);
}
-uptr internal_sigaction(int signum, const __sanitizer_kernel_sigaction_t *act,
- __sanitizer_kernel_sigaction_t *oldact) {
- return internal_syscall(__NR_rt_sigaction, signum, act, oldact,
- sizeof(__sanitizer_kernel_sigset_t));
+int internal_fork() {
+ return internal_syscall(SYSCALL(fork));
}
-uptr internal_sigprocmask(int how, __sanitizer_kernel_sigset_t *set,
- __sanitizer_kernel_sigset_t *oldset) {
- return internal_syscall(__NR_rt_sigprocmask, (uptr)how, &set->sig[0],
- &oldset->sig[0], sizeof(__sanitizer_kernel_sigset_t));
+#if SANITIZER_LINUX
+// Doesn't set sa_restorer, use with caution (see below).
+int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
+ __sanitizer_kernel_sigaction_t k_act, k_oldact;
+ internal_memset(&k_act, 0, sizeof(__sanitizer_kernel_sigaction_t));
+ internal_memset(&k_oldact, 0, sizeof(__sanitizer_kernel_sigaction_t));
+ const __sanitizer_sigaction *u_act = (__sanitizer_sigaction *)act;
+ __sanitizer_sigaction *u_oldact = (__sanitizer_sigaction *)oldact;
+ if (u_act) {
+ k_act.handler = u_act->handler;
+ k_act.sigaction = u_act->sigaction;
+ internal_memcpy(&k_act.sa_mask, &u_act->sa_mask,
+ sizeof(__sanitizer_kernel_sigset_t));
+ k_act.sa_flags = u_act->sa_flags;
+ // FIXME: most often sa_restorer is unset, however the kernel requires it
+ // to point to a valid signal restorer that calls the rt_sigreturn syscall.
+ // If sa_restorer passed to the kernel is NULL, the program may crash upon
+ // signal delivery or fail to unwind the stack in the signal handler.
+ // libc implementation of sigaction() passes its own restorer to
+ // rt_sigaction, so we need to do the same (we'll need to reimplement the
+ // restorers; for x86_64 the restorer address can be obtained from
+ // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact).
+ k_act.sa_restorer = u_act->sa_restorer;
+ }
+
+ uptr result = internal_syscall(SYSCALL(rt_sigaction), (uptr)signum,
+ (uptr)(u_act ? &k_act : NULL),
+ (uptr)(u_oldact ? &k_oldact : NULL),
+ (uptr)sizeof(__sanitizer_kernel_sigset_t));
+
+ if ((result == 0) && u_oldact) {
+ u_oldact->handler = k_oldact.handler;
+ u_oldact->sigaction = k_oldact.sigaction;
+ internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask,
+ sizeof(__sanitizer_kernel_sigset_t));
+ u_oldact->sa_flags = k_oldact.sa_flags;
+ u_oldact->sa_restorer = k_oldact.sa_restorer;
+ }
+ return result;
}
+#endif // SANITIZER_LINUX
-void internal_sigfillset(__sanitizer_kernel_sigset_t *set) {
+uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
+ __sanitizer_sigset_t *oldset) {
+#if SANITIZER_FREEBSD
+ return internal_syscall(SYSCALL(sigprocmask), how, set, oldset);
+#else
+ __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
+ __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset;
+ return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how,
+ (uptr)&k_set->sig[0], (uptr)&k_oldset->sig[0],
+ sizeof(__sanitizer_kernel_sigset_t));
+#endif
+}
+
+void internal_sigfillset(__sanitizer_sigset_t *set) {
internal_memset(set, 0xff, sizeof(*set));
}
-void internal_sigdelset(__sanitizer_kernel_sigset_t *set, int signum) {
+#if SANITIZER_LINUX
+void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
signum -= 1;
CHECK_GE(signum, 0);
CHECK_LT(signum, sizeof(*set) * 8);
- const uptr idx = signum / (sizeof(set->sig[0]) * 8);
- const uptr bit = signum % (sizeof(set->sig[0]) * 8);
- set->sig[idx] &= ~(1 << bit);
+ __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
+ const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);
+ const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
+ k_set->sig[idx] &= ~(1 << bit);
}
+#endif // SANITIZER_LINUX
// ThreadLister implementation.
ThreadLister::ThreadLister(int pid)
@@ -698,7 +649,7 @@ bool ThreadLister::GetDirectoryEntries() {
}
uptr GetPageSize() {
-#if defined(__x86_64__) || defined(__i386__)
+#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__))
return EXEC_PAGESIZE;
#else
return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy.
@@ -753,8 +704,10 @@ bool LibraryNameIs(const char *full_name, const char *base_name) {
#if !SANITIZER_ANDROID
// Call cb for each region mapped by map.
void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
+#if !SANITIZER_FREEBSD
typedef ElfW(Phdr) Elf_Phdr;
typedef ElfW(Ehdr) Elf_Ehdr;
+#endif // !SANITIZER_FREEBSD
char *base = (char *)map->l_addr;
Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
char *phdrs = base + ehdr->e_phoff;
@@ -788,7 +741,7 @@ void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
}
#endif
-#if defined(__x86_64__)
+#if defined(__x86_64__) && SANITIZER_LINUX
// We cannot use glibc's clone wrapper, because it messes with the child
// task's TLS. It writes the PID and TID of the child task to its thread
// descriptor, but in our case the child task shares the thread descriptor with
@@ -807,7 +760,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
register void *r8 __asm__("r8") = newtls;
register int *r10 __asm__("r10") = child_tidptr;
__asm__ __volatile__(
- /* %rax = syscall(%rax = __NR_clone,
+ /* %rax = syscall(%rax = SYSCALL(clone),
* %rdi = flags,
* %rsi = child_stack,
* %rdx = parent_tidptr,
@@ -841,7 +794,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
/* Return to parent. */
"1:\n"
: "=a" (res)
- : "a"(__NR_clone), "i"(__NR_exit),
+ : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
"S"(child_stack),
"D"(flags),
"d"(parent_tidptr),
@@ -850,7 +803,38 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
: "rsp", "memory", "r11", "rcx");
return res;
}
-#endif // defined(__x86_64__)
+#endif // defined(__x86_64__) && SANITIZER_LINUX
+
+#if SANITIZER_ANDROID
+// This thing is not, strictly speaking, async signal safe, but it does not seem
+// to cause any issues. Alternative is writing to log devices directly, but
+// their location and message format might change in the future, so we'd really
+// like to avoid that.
+void AndroidLogWrite(const char *buffer) {
+ char *copy = internal_strdup(buffer);
+ char *p = copy;
+ char *q;
+ // __android_log_write has an implicit message length limit.
+ // Print one line at a time.
+ do {
+ q = internal_strchr(p, '\n');
+ if (q) *q = '\0';
+ __android_log_write(ANDROID_LOG_INFO, NULL, p);
+ if (q) p = q + 1;
+ } while (q);
+ InternalFree(copy);
+}
+
+void GetExtraActivationFlags(char *buf, uptr size) {
+ CHECK(size > PROP_VALUE_MAX);
+ __system_property_get("asan.options", buf);
+}
+#endif
+
+bool IsDeadlySignal(int signum) {
+ return (signum == SIGSEGV) && common_flags()->handle_segv;
+}
+
} // namespace __sanitizer
-#endif // SANITIZER_LINUX
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.h b/libsanitizer/sanitizer_common/sanitizer_linux.h
index 6422df142e7..086834c3a2f 100644
--- a/libsanitizer/sanitizer_common/sanitizer_linux.h
+++ b/libsanitizer/sanitizer_common/sanitizer_linux.h
@@ -12,7 +12,7 @@
#define SANITIZER_LINUX_H
#include "sanitizer_platform.h"
-#if SANITIZER_LINUX
+#if SANITIZER_FREEBSD || SANITIZER_LINUX
#include "sanitizer_common.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_platform_limits_posix.h"
@@ -27,20 +27,25 @@ struct linux_dirent;
// Syscall wrappers.
uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count);
-uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5);
uptr internal_sigaltstack(const struct sigaltstack* ss,
struct sigaltstack* oss);
-uptr internal_sigaction(int signum, const __sanitizer_kernel_sigaction_t *act,
- __sanitizer_kernel_sigaction_t *oldact);
-uptr internal_sigprocmask(int how, __sanitizer_kernel_sigset_t *set,
- __sanitizer_kernel_sigset_t *oldset);
-void internal_sigfillset(__sanitizer_kernel_sigset_t *set);
-void internal_sigdelset(__sanitizer_kernel_sigset_t *set, int signum);
+uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
+ __sanitizer_sigset_t *oldset);
+void internal_sigfillset(__sanitizer_sigset_t *set);
-#ifdef __x86_64__
+// Linux-only syscalls.
+#if SANITIZER_LINUX
+uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5);
+// Used only by sanitizer_stoptheworld. Signal handlers that are actually used
+// (like the process-wide error reporting SEGV handler) must use
+// internal_sigaction instead.
+int internal_sigaction_norestorer(int signum, const void *act, void *oldact);
+void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
+#if defined(__x86_64__)
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
int *parent_tidptr, void *newtls, int *child_tidptr);
#endif
+#endif // SANITIZER_LINUX
// This class reads thread IDs from /proc/<pid>/task using only syscalls.
class ThreadLister {
@@ -64,8 +69,6 @@ class ThreadLister {
int bytes_read_;
};
-void AdjustStackSizeLinux(void *attr);
-
// Exposed for testing.
uptr ThreadDescriptorSize();
uptr ThreadSelf();
@@ -84,5 +87,5 @@ void CacheBinaryName();
void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr));
} // namespace __sanitizer
-#endif // SANITIZER_LINUX
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
#endif // SANITIZER_LINUX_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
index c9eb435be91..e754b26e693 100644
--- a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
@@ -11,7 +11,7 @@
//===----------------------------------------------------------------------===//
#include "sanitizer_platform.h"
-#if SANITIZER_LINUX
+#if SANITIZER_FREEBSD || SANITIZER_LINUX
#include "sanitizer_common.h"
#include "sanitizer_flags.h"
@@ -23,27 +23,53 @@
#include <dlfcn.h>
#include <pthread.h>
-#include <sys/prctl.h>
+#include <signal.h>
#include <sys/resource.h>
+#if SANITIZER_FREEBSD
+#define _GNU_SOURCE // to declare _Unwind_Backtrace() from <unwind.h>
+#endif
#include <unwind.h>
+#if SANITIZER_FREEBSD
+#include <pthread_np.h>
+#define pthread_getattr_np pthread_attr_get_np
+#endif
+
+#if SANITIZER_LINUX
+#include <sys/prctl.h>
+#endif
+
#if !SANITIZER_ANDROID
#include <elf.h>
#include <link.h>
#include <unistd.h>
#endif
+namespace __sanitizer {
+
// This function is defined elsewhere if we intercepted pthread_attr_getstack.
-SANITIZER_WEAK_ATTRIBUTE
-int __sanitizer_pthread_attr_getstack(void *attr, void **addr, size_t *size) {
- return pthread_attr_getstack((pthread_attr_t*)attr, addr, size);
+extern "C" {
+SANITIZER_WEAK_ATTRIBUTE int
+real_pthread_attr_getstack(void *attr, void **addr, size_t *size);
+} // extern "C"
+
+static int my_pthread_attr_getstack(void *attr, void **addr, size_t *size) {
+ if (real_pthread_attr_getstack)
+ return real_pthread_attr_getstack((pthread_attr_t *)attr, addr, size);
+ return pthread_attr_getstack((pthread_attr_t *)attr, addr, size);
}
-namespace __sanitizer {
+SANITIZER_WEAK_ATTRIBUTE int
+real_sigaction(int signum, const void *act, void *oldact);
+
+int internal_sigaction(int signum, const void *act, void *oldact) {
+ if (real_sigaction)
+ return real_sigaction(signum, act, oldact);
+ return sigaction(signum, (struct sigaction *)act, (struct sigaction *)oldact);
+}
void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
uptr *stack_bottom) {
- static const uptr kMaxThreadStackSize = 1 << 30; // 1Gb
CHECK(stack_top);
CHECK(stack_bottom);
if (at_initialization) {
@@ -77,10 +103,11 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
return;
}
pthread_attr_t attr;
+ pthread_attr_init(&attr);
CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
uptr stacksize = 0;
void *stackaddr = 0;
- __sanitizer_pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize);
+ my_pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize);
pthread_attr_destroy(&attr);
CHECK_LE(stacksize, kMaxThreadStackSize); // Sanity check.
@@ -88,8 +115,6 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
*stack_bottom = (uptr)stackaddr;
}
-// Does not compile for Go because dlsym() requires -ldl
-#ifndef SANITIZER_GO
bool SetEnv(const char *name, const char *value) {
void *f = dlsym(RTLD_NEXT, "setenv");
if (f == 0)
@@ -98,9 +123,8 @@ bool SetEnv(const char *name, const char *value) {
setenv_ft setenv_f;
CHECK_EQ(sizeof(setenv_f), sizeof(f));
internal_memcpy(&setenv_f, &f, sizeof(f));
- return setenv_f(name, value, 1) == 0;
+ return IndirectExternCall(setenv_f)(name, value, 1) == 0;
}
-#endif
bool SanitizerSetThreadName(const char *name) {
#ifdef PR_SET_NAME
@@ -123,8 +147,52 @@ bool SanitizerGetThreadName(char *name, int max_len) {
#endif
}
-#ifndef SANITIZER_GO
//------------------------- SlowUnwindStack -----------------------------------
+
+typedef struct {
+ uptr absolute_pc;
+ uptr stack_top;
+ uptr stack_size;
+} backtrace_frame_t;
+
+extern "C" {
+typedef void *(*acquire_my_map_info_list_func)();
+typedef void (*release_my_map_info_list_func)(void *map);
+typedef sptr (*unwind_backtrace_signal_arch_func)(
+ void *siginfo, void *sigcontext, void *map_info_list,
+ backtrace_frame_t *backtrace, uptr ignore_depth, uptr max_depth);
+acquire_my_map_info_list_func acquire_my_map_info_list;
+release_my_map_info_list_func release_my_map_info_list;
+unwind_backtrace_signal_arch_func unwind_backtrace_signal_arch;
+} // extern "C"
+
+#if SANITIZER_ANDROID
+void SanitizerInitializeUnwinder() {
+ void *p = dlopen("libcorkscrew.so", RTLD_LAZY);
+ if (!p) {
+ VReport(1,
+ "Failed to open libcorkscrew.so. You may see broken stack traces "
+ "in SEGV reports.");
+ return;
+ }
+ acquire_my_map_info_list =
+ (acquire_my_map_info_list_func)(uptr)dlsym(p, "acquire_my_map_info_list");
+ release_my_map_info_list =
+ (release_my_map_info_list_func)(uptr)dlsym(p, "release_my_map_info_list");
+ unwind_backtrace_signal_arch = (unwind_backtrace_signal_arch_func)(uptr)dlsym(
+ p, "unwind_backtrace_signal_arch");
+ if (!acquire_my_map_info_list || !release_my_map_info_list ||
+ !unwind_backtrace_signal_arch) {
+ VReport(1,
+ "Failed to find one of the required symbols in libcorkscrew.so. "
+ "You may see broken stack traces in SEGV reports.");
+ acquire_my_map_info_list = NULL;
+ unwind_backtrace_signal_arch = NULL;
+ release_my_map_info_list = NULL;
+ }
+}
+#endif
+
#ifdef __arm__
#define UNWIND_STOP _URC_END_OF_STACK
#define UNWIND_CONTINUE _URC_NO_REASON
@@ -161,9 +229,8 @@ _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
}
void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
+ CHECK_GE(max_depth, 2);
size = 0;
- if (max_depth == 0)
- return;
UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)};
_Unwind_Backtrace(Unwind_Trace, &arg);
// We need to pop a few frames so that pc is on top.
@@ -175,9 +242,35 @@ void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
trace[0] = pc;
}
-#endif // !SANITIZER_GO
+void StackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
+ uptr max_depth) {
+ CHECK_GE(max_depth, 2);
+ if (!unwind_backtrace_signal_arch) {
+ SlowUnwindStack(pc, max_depth);
+ return;
+ }
+
+ void *map = acquire_my_map_info_list();
+ CHECK(map);
+ InternalScopedBuffer<backtrace_frame_t> frames(kStackTraceMax);
+ // siginfo argument appears to be unused.
+ sptr res = unwind_backtrace_signal_arch(/* siginfo */ NULL, context, map,
+ frames.data(),
+ /* ignore_depth */ 0, max_depth);
+ release_my_map_info_list(map);
+ if (res < 0) return;
+ CHECK_LE((uptr)res, kStackTraceMax);
+
+ size = 0;
+ // +2 compensate for libcorkscrew unwinder returning addresses of call
+ // instructions instead of raw return addresses.
+ for (sptr i = 0; i < res; ++i)
+ trace[size++] = frames[i].absolute_pc + 2;
+}
+#if !SANITIZER_FREEBSD
static uptr g_tls_size;
+#endif
#ifdef __i386__
# define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall))
@@ -186,7 +279,7 @@ static uptr g_tls_size;
#endif
void InitTlsSize() {
-#if !defined(SANITIZER_GO) && !SANITIZER_ANDROID
+#if !SANITIZER_FREEBSD && !SANITIZER_ANDROID
typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION;
get_tls_func get_tls;
void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
@@ -196,16 +289,12 @@ void InitTlsSize() {
CHECK_NE(get_tls, 0);
size_t tls_size = 0;
size_t tls_align = 0;
- get_tls(&tls_size, &tls_align);
+ IndirectExternCall(get_tls)(&tls_size, &tls_align);
g_tls_size = tls_size;
-#endif
-}
-
-uptr GetTlsSize() {
- return g_tls_size;
+#endif // !SANITIZER_FREEBSD && !SANITIZER_ANDROID
}
-#if defined(__x86_64__) || defined(__i386__)
+#if (defined(__x86_64__) || defined(__i386__)) && SANITIZER_LINUX
// sizeof(struct thread) from glibc.
static atomic_uintptr_t kThreadDescriptorSize;
@@ -221,7 +310,9 @@ uptr ThreadDescriptorSize() {
int minor = internal_simple_strtoll(buf + 8, &end, 10);
if (end != buf + 8 && (*end == '\0' || *end == '.')) {
/* sizeof(struct thread) values from various glibc versions. */
- if (minor <= 3)
+ if (SANITIZER_X32)
+ val = 1728; // Assume only one particular version for x32.
+ else if (minor <= 3)
val = FIRST_32_SECOND_64(1104, 1696);
else if (minor == 4)
val = FIRST_32_SECOND_64(1120, 1728);
@@ -253,27 +344,79 @@ uptr ThreadSelfOffset() {
uptr ThreadSelf() {
uptr descr_addr;
-#ifdef __i386__
+# if defined(__i386__)
asm("mov %%gs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset));
-#else
+# elif defined(__x86_64__)
asm("mov %%fs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset));
-#endif
+# else
+# error "unsupported CPU arch"
+# endif
return descr_addr;
}
-#endif // defined(__x86_64__) || defined(__i386__)
+#endif // (defined(__x86_64__) || defined(__i386__)) && SANITIZER_LINUX
+
+#if SANITIZER_FREEBSD
+static void **ThreadSelfSegbase() {
+ void **segbase = 0;
+# if defined(__i386__)
+ // sysarch(I386_GET_GSBASE, segbase);
+ __asm __volatile("mov %%gs:0, %0" : "=r" (segbase));
+# elif defined(__x86_64__)
+ // sysarch(AMD64_GET_FSBASE, segbase);
+ __asm __volatile("movq %%fs:0, %0" : "=r" (segbase));
+# else
+# error "unsupported CPU arch for FreeBSD platform"
+# endif
+ return segbase;
+}
-void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
- uptr *tls_addr, uptr *tls_size) {
-#ifndef SANITIZER_GO
-#if defined(__x86_64__) || defined(__i386__)
- *tls_addr = ThreadSelf();
- *tls_size = GetTlsSize();
- *tls_addr -= *tls_size;
- *tls_addr += ThreadDescriptorSize();
+uptr ThreadSelf() {
+ return (uptr)ThreadSelfSegbase()[2];
+}
+#endif // SANITIZER_FREEBSD
+
+static void GetTls(uptr *addr, uptr *size) {
+#if SANITIZER_LINUX
+# if defined(__x86_64__) || defined(__i386__)
+ *addr = ThreadSelf();
+ *size = GetTlsSize();
+ *addr -= *size;
+ *addr += ThreadDescriptorSize();
+# else
+ *addr = 0;
+ *size = 0;
+# endif
+#elif SANITIZER_FREEBSD
+ void** segbase = ThreadSelfSegbase();
+ *addr = 0;
+ *size = 0;
+ if (segbase != 0) {
+ // tcbalign = 16
+ // tls_size = round(tls_static_space, tcbalign);
+ // dtv = segbase[1];
+ // dtv[2] = segbase - tls_static_space;
+ void **dtv = (void**) segbase[1];
+ *addr = (uptr) dtv[2];
+ *size = (*addr == 0) ? 0 : ((uptr) segbase[0] - (uptr) dtv[2]);
+ }
+#else
+# error "Unknown OS"
+#endif
+}
+
+uptr GetTlsSize() {
+#if SANITIZER_FREEBSD
+ uptr addr, size;
+ GetTls(&addr, &size);
+ return size;
#else
- *tls_addr = 0;
- *tls_size = 0;
+ return g_tls_size;
#endif
+}
+
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+ uptr *tls_addr, uptr *tls_size) {
+ GetTls(tls_addr, tls_size);
uptr stack_top, stack_bottom;
GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
@@ -289,19 +432,13 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
*tls_addr = *stk_addr + *stk_size;
}
}
-#else // SANITIZER_GO
- *stk_addr = 0;
- *stk_size = 0;
- *tls_addr = 0;
- *tls_size = 0;
-#endif // SANITIZER_GO
}
-void AdjustStackSizeLinux(void *attr_) {
+void AdjustStackSize(void *attr_) {
pthread_attr_t *attr = (pthread_attr_t *)attr_;
uptr stackaddr = 0;
size_t stacksize = 0;
- __sanitizer_pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize);
+ my_pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize);
// GLibC will return (0 - stacksize) as the stack address in the case when
// stacksize is set, but stackaddr is not.
bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0);
@@ -309,10 +446,11 @@ void AdjustStackSizeLinux(void *attr_) {
const uptr minstacksize = GetTlsSize() + 128*1024;
if (stacksize < minstacksize) {
if (!stack_set) {
- if (common_flags()->verbosity && stacksize != 0)
- Printf("Sanitizer: increasing stacksize %zu->%zu\n", stacksize,
- minstacksize);
- pthread_attr_setstacksize(attr, minstacksize);
+ if (stacksize != 0) {
+ VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize,
+ minstacksize);
+ pthread_attr_setstacksize(attr, minstacksize);
+ }
} else {
Printf("Sanitizer: pre-allocated stack size is insufficient: "
"%zu < %zu\n", stacksize, minstacksize);
@@ -324,10 +462,13 @@ void AdjustStackSizeLinux(void *attr_) {
#if SANITIZER_ANDROID
uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
string_predicate_t filter) {
- return 0;
+ MemoryMappingLayout memory_mapping(false);
+ return memory_mapping.DumpListOfModules(modules, max_modules, filter);
}
#else // SANITIZER_ANDROID
+# if !SANITIZER_FREEBSD
typedef ElfW(Phdr) Elf_Phdr;
+# endif
struct DlIteratePhdrData {
LoadedModule *modules;
@@ -378,6 +519,14 @@ uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
}
#endif // SANITIZER_ANDROID
+uptr indirect_call_wrapper;
+
+void SetIndirectCallWrapper(uptr wrapper) {
+ CHECK(!indirect_call_wrapper);
+ CHECK(wrapper);
+ indirect_call_wrapper = wrapper;
+}
+
} // namespace __sanitizer
-#endif // SANITIZER_LINUX
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
diff --git a/libsanitizer/sanitizer_common/sanitizer_list.h b/libsanitizer/sanitizer_common/sanitizer_list.h
index 9692e01b8e0..b72c548e385 100644
--- a/libsanitizer/sanitizer_common/sanitizer_list.h
+++ b/libsanitizer/sanitizer_common/sanitizer_list.h
@@ -24,6 +24,8 @@ namespace __sanitizer {
// non-zero-initialized objects before using.
template<class Item>
struct IntrusiveList {
+ friend class Iterator;
+
void clear() {
first_ = last_ = 0;
size_ = 0;
@@ -111,6 +113,21 @@ struct IntrusiveList {
}
}
+ class Iterator {
+ public:
+ explicit Iterator(IntrusiveList<Item> *list)
+ : list_(list), current_(list->first_) { }
+ Item *next() {
+ Item *ret = current_;
+ if (current_) current_ = current_->next;
+ return ret;
+ }
+ bool hasNext() const { return current_ != 0; }
+ private:
+ IntrusiveList<Item> *list_;
+ Item *current_;
+ };
+
// private, don't use directly.
uptr size_;
Item *first_;
diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.cc b/libsanitizer/sanitizer_common/sanitizer_mac.cc
index 288e31ca078..6deba53d3e8 100644
--- a/libsanitizer/sanitizer_common/sanitizer_mac.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_mac.cc
@@ -5,9 +5,8 @@
//
//===----------------------------------------------------------------------===//
//
-// This file is shared between AddressSanitizer and ThreadSanitizer
-// run-time libraries and implements mac-specific functions from
-// sanitizer_libc.h.
+// This file is shared between various sanitizers' runtime libraries and
+// implements OSX-specific functions.
//===----------------------------------------------------------------------===//
#include "sanitizer_platform.h"
@@ -21,20 +20,22 @@
#include <stdio.h>
#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_libc.h"
+#include "sanitizer_mac.h"
#include "sanitizer_placement_new.h"
#include "sanitizer_procmaps.h"
#include <crt_externs.h> // for _NSGetEnviron
#include <fcntl.h>
-#include <mach-o/dyld.h>
-#include <mach-o/loader.h>
#include <pthread.h>
#include <sched.h>
+#include <signal.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>
+#include <sys/sysctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <libkern/OSAtomic.h>
@@ -118,6 +119,16 @@ uptr internal_getpid() {
return getpid();
}
+int internal_sigaction(int signum, const void *act, void *oldact) {
+ return sigaction(signum,
+ (struct sigaction *)act, (struct sigaction *)oldact);
+}
+
+int internal_fork() {
+ // TODO(glider): this may call user's pthread_atfork() handlers which is bad.
+ return fork();
+}
+
// ----------------- sanitizer_common.h
bool FileExists(const char *filename) {
struct stat st;
@@ -136,6 +147,20 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
CHECK(stack_top);
CHECK(stack_bottom);
uptr stacksize = pthread_get_stacksize_np(pthread_self());
+ // pthread_get_stacksize_np() returns an incorrect stack size for the main
+ // thread on Mavericks. See
+ // https://code.google.com/p/address-sanitizer/issues/detail?id=261
+ if ((GetMacosVersion() == MACOS_VERSION_MAVERICKS) && at_initialization &&
+ stacksize == (1 << 19)) {
+ struct rlimit rl;
+ CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
+ // Most often rl.rlim_cur will be the desired 8M.
+ if (rl.rlim_cur < kMaxThreadStackSize) {
+ stacksize = rl.rlim_cur;
+ } else {
+ stacksize = kMaxThreadStackSize;
+ }
+ }
void *stackaddr = pthread_get_stackaddr_np(pthread_self());
*stack_top = (uptr)stackaddr;
*stack_bottom = *stack_top - stacksize;
@@ -169,7 +194,8 @@ void ReExec() {
UNIMPLEMENTED();
}
-void PrepareForSandboxing() {
+void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
+ (void)args;
// Nothing here for now.
}
@@ -177,148 +203,6 @@ uptr GetPageSize() {
return sysconf(_SC_PAGESIZE);
}
-// ----------------- sanitizer_procmaps.h
-
-MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
- Reset();
-}
-
-MemoryMappingLayout::~MemoryMappingLayout() {
-}
-
-// More information about Mach-O headers can be found in mach-o/loader.h
-// Each Mach-O image has a header (mach_header or mach_header_64) starting with
-// a magic number, and a list of linker load commands directly following the
-// header.
-// A load command is at least two 32-bit words: the command type and the
-// command size in bytes. We're interested only in segment load commands
-// (LC_SEGMENT and LC_SEGMENT_64), which tell that a part of the file is mapped
-// into the task's address space.
-// The |vmaddr|, |vmsize| and |fileoff| fields of segment_command or
-// segment_command_64 correspond to the memory address, memory size and the
-// file offset of the current memory segment.
-// Because these fields are taken from the images as is, one needs to add
-// _dyld_get_image_vmaddr_slide() to get the actual addresses at runtime.
-
-void MemoryMappingLayout::Reset() {
- // Count down from the top.
- // TODO(glider): as per man 3 dyld, iterating over the headers with
- // _dyld_image_count is thread-unsafe. We need to register callbacks for
- // adding and removing images which will invalidate the MemoryMappingLayout
- // state.
- current_image_ = _dyld_image_count();
- current_load_cmd_count_ = -1;
- current_load_cmd_addr_ = 0;
- current_magic_ = 0;
- current_filetype_ = 0;
-}
-
-// static
-void MemoryMappingLayout::CacheMemoryMappings() {
- // No-op on Mac for now.
-}
-
-void MemoryMappingLayout::LoadFromCache() {
- // No-op on Mac for now.
-}
-
-// Next and NextSegmentLoad were inspired by base/sysinfo.cc in
-// Google Perftools, http://code.google.com/p/google-perftools.
-
-// NextSegmentLoad scans the current image for the next segment load command
-// and returns the start and end addresses and file offset of the corresponding
-// segment.
-// Note that the segment addresses are not necessarily sorted.
-template<u32 kLCSegment, typename SegmentCommand>
-bool MemoryMappingLayout::NextSegmentLoad(
- uptr *start, uptr *end, uptr *offset,
- char filename[], uptr filename_size, uptr *protection) {
- if (protection)
- UNIMPLEMENTED();
- const char* lc = current_load_cmd_addr_;
- current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize;
- if (((const load_command *)lc)->cmd == kLCSegment) {
- const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_);
- const SegmentCommand* sc = (const SegmentCommand *)lc;
- if (start) *start = sc->vmaddr + dlloff;
- if (end) *end = sc->vmaddr + sc->vmsize + dlloff;
- if (offset) {
- if (current_filetype_ == /*MH_EXECUTE*/ 0x2) {
- *offset = sc->vmaddr;
- } else {
- *offset = sc->fileoff;
- }
- }
- if (filename) {
- internal_strncpy(filename, _dyld_get_image_name(current_image_),
- filename_size);
- }
- return true;
- }
- return false;
-}
-
-bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
- char filename[], uptr filename_size,
- uptr *protection) {
- for (; current_image_ >= 0; current_image_--) {
- const mach_header* hdr = _dyld_get_image_header(current_image_);
- if (!hdr) continue;
- if (current_load_cmd_count_ < 0) {
- // Set up for this image;
- current_load_cmd_count_ = hdr->ncmds;
- current_magic_ = hdr->magic;
- current_filetype_ = hdr->filetype;
- switch (current_magic_) {
-#ifdef MH_MAGIC_64
- case MH_MAGIC_64: {
- current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header_64);
- break;
- }
-#endif
- case MH_MAGIC: {
- current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header);
- break;
- }
- default: {
- continue;
- }
- }
- }
-
- for (; current_load_cmd_count_ >= 0; current_load_cmd_count_--) {
- switch (current_magic_) {
- // current_magic_ may be only one of MH_MAGIC, MH_MAGIC_64.
-#ifdef MH_MAGIC_64
- case MH_MAGIC_64: {
- if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
- start, end, offset, filename, filename_size, protection))
- return true;
- break;
- }
-#endif
- case MH_MAGIC: {
- if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
- start, end, offset, filename, filename_size, protection))
- return true;
- break;
- }
- }
- }
- // If we get here, no more load_cmd's in this image talk about
- // segments. Go on to the next image.
- }
- return false;
-}
-
-bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
- char filename[],
- uptr filename_size,
- uptr *protection) {
- return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
- protection);
-}
-
BlockingMutex::BlockingMutex(LinkerInitialized) {
// We assume that OS_SPINLOCK_INIT is zero
}
@@ -377,32 +261,49 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
string_predicate_t filter) {
MemoryMappingLayout memory_mapping(false);
- memory_mapping.Reset();
- uptr cur_beg, cur_end, cur_offset;
- InternalScopedBuffer<char> module_name(kMaxPathLength);
- uptr n_modules = 0;
- for (uptr i = 0;
- n_modules < max_modules &&
- memory_mapping.Next(&cur_beg, &cur_end, &cur_offset,
- module_name.data(), module_name.size(), 0);
- i++) {
- const char *cur_name = module_name.data();
- if (cur_name[0] == '\0')
- continue;
- if (filter && !filter(cur_name))
- continue;
- LoadedModule *cur_module = 0;
- if (n_modules > 0 &&
- 0 == internal_strcmp(cur_name, modules[n_modules - 1].full_name())) {
- cur_module = &modules[n_modules - 1];
- } else {
- void *mem = &modules[n_modules];
- cur_module = new(mem) LoadedModule(cur_name, cur_beg);
- n_modules++;
+ return memory_mapping.DumpListOfModules(modules, max_modules, filter);
+}
+
+bool IsDeadlySignal(int signum) {
+ return (signum == SIGSEGV || signum == SIGBUS) && common_flags()->handle_segv;
+}
+
+MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED;
+
+MacosVersion GetMacosVersionInternal() {
+ int mib[2] = { CTL_KERN, KERN_OSRELEASE };
+ char version[100];
+ uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]);
+ for (uptr i = 0; i < maxlen; i++) version[i] = '\0';
+ // Get the version length.
+ CHECK_NE(sysctl(mib, 2, 0, &len, 0, 0), -1);
+ CHECK_LT(len, maxlen);
+ CHECK_NE(sysctl(mib, 2, version, &len, 0, 0), -1);
+ switch (version[0]) {
+ case '9': return MACOS_VERSION_LEOPARD;
+ case '1': {
+ switch (version[1]) {
+ case '0': return MACOS_VERSION_SNOW_LEOPARD;
+ case '1': return MACOS_VERSION_LION;
+ case '2': return MACOS_VERSION_MOUNTAIN_LION;
+ case '3': return MACOS_VERSION_MAVERICKS;
+ default: return MACOS_VERSION_UNKNOWN;
+ }
}
- cur_module->addAddressRange(cur_beg, cur_end);
+ default: return MACOS_VERSION_UNKNOWN;
+ }
+}
+
+MacosVersion GetMacosVersion() {
+ atomic_uint32_t *cache =
+ reinterpret_cast<atomic_uint32_t*>(&cached_macos_version);
+ MacosVersion result =
+ static_cast<MacosVersion>(atomic_load(cache, memory_order_acquire));
+ if (result == MACOS_VERSION_UNINITIALIZED) {
+ result = GetMacosVersionInternal();
+ atomic_store(cache, result, memory_order_release);
}
- return n_modules;
+ return result;
}
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.h b/libsanitizer/sanitizer_common/sanitizer_mac.h
new file mode 100644
index 00000000000..63055297fef
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_mac.h
@@ -0,0 +1,34 @@
+//===-- sanitizer_mac.h -----------------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between various sanitizers' runtime libraries and
+// provides definitions for OSX-specific functions.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_MAC_H
+#define SANITIZER_MAC_H
+
+#include "sanitizer_platform.h"
+#if SANITIZER_MAC
+
+namespace __sanitizer {
+
+enum MacosVersion {
+ MACOS_VERSION_UNINITIALIZED = 0,
+ MACOS_VERSION_UNKNOWN,
+ MACOS_VERSION_LEOPARD,
+ MACOS_VERSION_SNOW_LEOPARD,
+ MACOS_VERSION_LION,
+ MACOS_VERSION_MOUNTAIN_LION,
+ MACOS_VERSION_MAVERICKS
+};
+
+MacosVersion GetMacosVersion();
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_MAC
+#endif // SANITIZER_MAC_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_mutex.h b/libsanitizer/sanitizer_common/sanitizer_mutex.h
index d78f43edaae..adc3add6008 100644
--- a/libsanitizer/sanitizer_common/sanitizer_mutex.h
+++ b/libsanitizer/sanitizer_common/sanitizer_mutex.h
@@ -81,6 +81,88 @@ class BlockingMutex {
uptr owner_; // for debugging
};
+// Reader-writer spin mutex.
+class RWMutex {
+ public:
+ RWMutex() {
+ atomic_store(&state_, kUnlocked, memory_order_relaxed);
+ }
+
+ ~RWMutex() {
+ CHECK_EQ(atomic_load(&state_, memory_order_relaxed), kUnlocked);
+ }
+
+ void Lock() {
+ u32 cmp = kUnlocked;
+ if (atomic_compare_exchange_strong(&state_, &cmp, kWriteLock,
+ memory_order_acquire))
+ return;
+ LockSlow();
+ }
+
+ void Unlock() {
+ u32 prev = atomic_fetch_sub(&state_, kWriteLock, memory_order_release);
+ DCHECK_NE(prev & kWriteLock, 0);
+ (void)prev;
+ }
+
+ void ReadLock() {
+ u32 prev = atomic_fetch_add(&state_, kReadLock, memory_order_acquire);
+ if ((prev & kWriteLock) == 0)
+ return;
+ ReadLockSlow();
+ }
+
+ void ReadUnlock() {
+ u32 prev = atomic_fetch_sub(&state_, kReadLock, memory_order_release);
+ DCHECK_EQ(prev & kWriteLock, 0);
+ DCHECK_GT(prev & ~kWriteLock, 0);
+ (void)prev;
+ }
+
+ void CheckLocked() {
+ CHECK_NE(atomic_load(&state_, memory_order_relaxed), kUnlocked);
+ }
+
+ private:
+ atomic_uint32_t state_;
+
+ enum {
+ kUnlocked = 0,
+ kWriteLock = 1,
+ kReadLock = 2
+ };
+
+ void NOINLINE LockSlow() {
+ for (int i = 0;; i++) {
+ if (i < 10)
+ proc_yield(10);
+ else
+ internal_sched_yield();
+ u32 cmp = atomic_load(&state_, memory_order_relaxed);
+ if (cmp == kUnlocked &&
+ atomic_compare_exchange_weak(&state_, &cmp, kWriteLock,
+ memory_order_acquire))
+ return;
+ }
+ }
+
+ void NOINLINE ReadLockSlow() {
+ for (int i = 0;; i++) {
+ if (i < 10)
+ proc_yield(10);
+ else
+ internal_sched_yield();
+ u32 prev = atomic_load(&state_, memory_order_acquire);
+ if ((prev & kWriteLock) == 0)
+ return;
+ }
+ }
+
+ RWMutex(const RWMutex&);
+ void operator = (const RWMutex&);
+};
+
template<typename MutexType>
class GenericScopedLock {
public:
@@ -121,6 +203,8 @@ class GenericScopedReadLock {
typedef GenericScopedLock<StaticSpinMutex> SpinMutexLock;
typedef GenericScopedLock<BlockingMutex> BlockingMutexLock;
+typedef GenericScopedLock<RWMutex> RWMutexLock;
+typedef GenericScopedReadLock<RWMutex> RWMutexReadLock;
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform.h b/libsanitizer/sanitizer_common/sanitizer_platform.h
index 7693fe7ff17..14594d5ce55 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform.h
@@ -11,7 +11,8 @@
#ifndef SANITIZER_PLATFORM_H
#define SANITIZER_PLATFORM_H
-#if !defined(__linux__) && !defined(__APPLE__) && !defined(_WIN32)
+#if !defined(__linux__) && !defined(__FreeBSD__) && \
+ !defined(__APPLE__) && !defined(_WIN32)
# error "This operating system is not supported"
#endif
@@ -21,6 +22,12 @@
# define SANITIZER_LINUX 0
#endif
+#if defined(__FreeBSD__)
+# define SANITIZER_FREEBSD 1
+#else
+# define SANITIZER_FREEBSD 0
+#endif
+
#if defined(__APPLE__)
# define SANITIZER_MAC 1
# include <TargetConditionals.h>
@@ -46,6 +53,58 @@
# define SANITIZER_ANDROID 0
#endif
-#define SANITIZER_POSIX (SANITIZER_LINUX || SANITIZER_MAC)
+#define SANITIZER_POSIX (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC)
+
+#if __LP64__ || defined(_WIN64)
+# define SANITIZER_WORDSIZE 64
+#else
+# define SANITIZER_WORDSIZE 32
+#endif
+
+#if SANITIZER_WORDSIZE == 64
+# define FIRST_32_SECOND_64(a, b) (b)
+#else
+# define FIRST_32_SECOND_64(a, b) (a)
+#endif
+
+#if defined(__x86_64__) && !defined(_LP64)
+# define SANITIZER_X32 1
+#else
+# define SANITIZER_X32 0
+#endif
+
+// By default we allow to use SizeClassAllocator64 on 64-bit platform.
+// But in some cases (e.g. AArch64's 39-bit address space) SizeClassAllocator64
+// does not work well and we need to fallback to SizeClassAllocator32.
+// For such platforms build this code with -DSANITIZER_CAN_USE_ALLOCATOR64=0 or
+// change the definition of SANITIZER_CAN_USE_ALLOCATOR64 here.
+#ifndef SANITIZER_CAN_USE_ALLOCATOR64
+# if defined(__aarch64__)
+# define SANITIZER_CAN_USE_ALLOCATOR64 0
+# else
+# define SANITIZER_CAN_USE_ALLOCATOR64 (SANITIZER_WORDSIZE == 64)
+# endif
+#endif
+
+// The range of addresses which can be returned my mmap.
+// FIXME: this value should be different on different platforms,
+// e.g. on AArch64 it is most likely (1ULL << 39). Larger values will still work
+// but will consume more memory for TwoLevelByteMap.
+#if defined(__aarch64__)
+# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 39)
+#else
+# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
+#endif
+
+// The AArch64 linux port uses the canonical syscall set as mandated by
+// the upstream linux community for all new ports. Other ports may still
+// use legacy syscalls.
+#ifndef SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+# if defined(__aarch64__) && SANITIZER_LINUX
+# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1
+# else
+# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0
+# endif
+#endif
#endif // SANITIZER_PLATFORM_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
index f37d84b041d..92bbc005106 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
@@ -45,14 +45,16 @@
# define SI_IOS 0
#endif
-# define SANITIZER_INTERCEPT_STRCMP 1
-# define SANITIZER_INTERCEPT_TEXTDOMAIN SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_STRCASECMP SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_STRCMP 1
+#define SANITIZER_INTERCEPT_TEXTDOMAIN SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_STRCASECMP SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_MEMCHR 1
+#define SANITIZER_INTERCEPT_MEMRCHR SI_LINUX
-# define SANITIZER_INTERCEPT_READ SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_PREAD SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_WRITE SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_PWRITE SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_READ SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_PREAD SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_WRITE SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_PWRITE SI_NOT_WINDOWS
#define SANITIZER_INTERCEPT_PREAD64 SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_PWRITE64 SI_LINUX_NOT_ANDROID
@@ -65,109 +67,139 @@
#define SANITIZER_INTERCEPT_PREADV64 SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_PWRITEV64 SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_PRCTL SI_LINUX
-
-# define SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_STRPTIME SI_NOT_WINDOWS
-
-# define SANITIZER_INTERCEPT_SCANF SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_ISOC99_SCANF SI_LINUX
-
-# define SANITIZER_INTERCEPT_FREXP 1
-# define SANITIZER_INTERCEPT_FREXPF_FREXPL SI_NOT_WINDOWS
-
-# define SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS \
- SI_MAC || SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_CLOCK_GETTIME SI_LINUX
-# define SANITIZER_INTERCEPT_GETITIMER SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_TIME SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_GLOB SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_WAIT SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_INET SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_GETADDRINFO SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_GETNAMEINFO SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_GETSOCKNAME SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_GETHOSTBYNAME SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_GETHOSTBYNAME_R SI_LINUX
-# define SANITIZER_INTERCEPT_GETSOCKOPT SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_ACCEPT SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_ACCEPT4 SI_LINUX
-# define SANITIZER_INTERCEPT_MODF SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_RECVMSG SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_GETPEERNAME SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_IOCTL SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_INET_ATON SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_SYSINFO SI_LINUX
-# define SANITIZER_INTERCEPT_READDIR SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_READDIR64 SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_PTRACE SI_LINUX_NOT_ANDROID && \
- (defined(__i386) || defined (__x86_64)) // NOLINT
-# define SANITIZER_INTERCEPT_SETLOCALE SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_GETCWD SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME SI_LINUX
-# define SANITIZER_INTERCEPT_STRTOIMAX SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_MBSTOWCS SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_MBSNRTOWCS SI_MAC || SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_WCSTOMBS SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_WCSNRTOMBS SI_MAC || SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_TCGETATTR SI_LINUX
-# define SANITIZER_INTERCEPT_REALPATH SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_CONFSTR SI_MAC || SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_SCHED_GETAFFINITY SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_STRERROR SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_STRERROR_R SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_XPG_STRERROR_R SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_SCANDIR SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_SCANDIR64 SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_GETGROUPS SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_POLL SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_PPOLL SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_WORDEXP SI_MAC || SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_SIGWAIT SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_SIGWAITINFO SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_SIGTIMEDWAIT SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_SIGSETOPS SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_SIGPENDING SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_SIGPROCMASK SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_BACKTRACE SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_GETMNTENT SI_LINUX
-# define SANITIZER_INTERCEPT_GETMNTENT_R SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_STATFS SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_STATFS64 \
- (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_STATVFS SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_STATVFS64 SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_INITGROUPS SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_ETHER SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_ETHER_R SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_SHMCTL \
- (SI_LINUX_NOT_ANDROID && SANITIZER_WORDSIZE == 64)
-# define SANITIZER_INTERCEPT_RANDOM_R SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED \
- SI_MAC || SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_TMPNAM SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_TMPNAM_R SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_TEMPNAM SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_SINCOS SI_LINUX
-# define SANITIZER_INTERCEPT_REMQUO SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_LGAMMA SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_LGAMMA_R SI_LINUX
-# define SANITIZER_INTERCEPT_DRAND48_R SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_ICONV SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_TIMES SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_PRCTL SI_LINUX
-// FIXME: getline seems to be available on OSX 10.7
-# define SANITIZER_INTERCEPT_GETLINE SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_STRPTIME SI_NOT_WINDOWS
+
+#define SANITIZER_INTERCEPT_SCANF SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_ISOC99_SCANF SI_LINUX
+
+#ifndef SANITIZER_INTERCEPT_PRINTF
+# define SANITIZER_INTERCEPT_PRINTF SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_ISOC99_PRINTF SI_LINUX
+#endif
-# define SANITIZER_INTERCEPT__EXIT SI_LINUX
+#define SANITIZER_INTERCEPT_FREXP 1
+#define SANITIZER_INTERCEPT_FREXPF_FREXPL SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_PHTREAD_MUTEX SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_PTHREAD_COND SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS \
+ SI_MAC || SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_GETPWENT SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_FGETPWENT SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_GETPWENT_R SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_SETPWENT SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_CLOCK_GETTIME SI_LINUX
+#define SANITIZER_INTERCEPT_GETITIMER SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_TIME SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_GLOB SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_WAIT SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_INET SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_GETADDRINFO SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_GETNAMEINFO SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_GETSOCKNAME SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_GETHOSTBYNAME SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_GETHOSTBYNAME_R SI_LINUX
+#define SANITIZER_INTERCEPT_GETSOCKOPT SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_ACCEPT SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_ACCEPT4 SI_LINUX
+#define SANITIZER_INTERCEPT_MODF SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_RECVMSG SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_GETPEERNAME SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_IOCTL SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_INET_ATON SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_SYSINFO SI_LINUX
+#define SANITIZER_INTERCEPT_READDIR SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_READDIR64 SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_PTRACE SI_LINUX_NOT_ANDROID && \
+ (defined(__i386) || defined (__x86_64)) // NOLINT
+#define SANITIZER_INTERCEPT_SETLOCALE SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_GETCWD SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME SI_LINUX
+#define SANITIZER_INTERCEPT_STRTOIMAX SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_MBSTOWCS SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_MBSNRTOWCS SI_MAC || SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_WCSTOMBS SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_WCSNRTOMBS SI_MAC || SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_TCGETATTR SI_LINUX
+#define SANITIZER_INTERCEPT_REALPATH SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_CONFSTR SI_MAC || SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_SCHED_GETAFFINITY SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_STRERROR SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_STRERROR_R SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_XPG_STRERROR_R SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_SCANDIR SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_SCANDIR64 SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_GETGROUPS SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_POLL SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_PPOLL SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_WORDEXP (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_SIGWAIT SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_SIGWAITINFO SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_SIGTIMEDWAIT SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_SIGSETOPS SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_SIGPENDING SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_SIGPROCMASK SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_BACKTRACE SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_GETMNTENT SI_LINUX
+#define SANITIZER_INTERCEPT_GETMNTENT_R SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_STATFS SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_STATFS64 \
+ (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_STATVFS SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_STATVFS64 SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_INITGROUPS SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_ETHER SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_ETHER_R SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_SHMCTL \
+ (SI_LINUX_NOT_ANDROID && SANITIZER_WORDSIZE == 64)
+#define SANITIZER_INTERCEPT_RANDOM_R SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED \
+ SI_MAC || SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_TMPNAM SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_TMPNAM_R SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_TEMPNAM SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_SINCOS SI_LINUX
+#define SANITIZER_INTERCEPT_REMQUO SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_LGAMMA SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_LGAMMA_R SI_LINUX
+#define SANITIZER_INTERCEPT_DRAND48_R SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_RAND_R SI_MAC || SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_ICONV SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_TIMES SI_NOT_WINDOWS
+
+// FIXME: getline seems to be available on OSX 10.7
+#define SANITIZER_INTERCEPT_GETLINE SI_LINUX_NOT_ANDROID
+
+#define SANITIZER_INTERCEPT__EXIT SI_LINUX
+
+#define SANITIZER_INTERCEPT_PHTREAD_MUTEX SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP SI_LINUX_NOT_ANDROID
+
+#define SANITIZER_INTERCEPT_TLS_GET_ADDR SI_LINUX_NOT_ANDROID
+
+#define SANITIZER_INTERCEPT_LISTXATTR SI_LINUX
+#define SANITIZER_INTERCEPT_GETXATTR SI_LINUX
+#define SANITIZER_INTERCEPT_GETRESID SI_LINUX
+#define SANITIZER_INTERCEPT_GETIFADDRS SI_LINUX_NOT_ANDROID || SI_MAC
+#define SANITIZER_INTERCEPT_IF_INDEXTONAME SI_LINUX_NOT_ANDROID || SI_MAC
+#define SANITIZER_INTERCEPT_CAPGET SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_AEABI_MEM SI_LINUX && defined(__arm__)
+#define SANITIZER_INTERCEPT___BZERO SI_MAC
+#define SANITIZER_INTERCEPT_FTIME SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_XDR SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_TSEARCH SI_LINUX_NOT_ANDROID || SI_MAC
+#define SANITIZER_INTERCEPT_LIBIO_INTERNALS SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_FOPEN SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_FOPEN64 SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_OPEN_MEMSTREAM SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_OBSTACK SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_FFLUSH SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_FCLOSE SI_NOT_WINDOWS
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc
index bc37df0df49..76ee9001b7d 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc
@@ -62,7 +62,7 @@ namespace __sanitizer {
unsigned struct_statfs64_sz = sizeof(struct statfs64);
} // namespace __sanitizer
-#if !defined(__powerpc64__) && !defined(__x86_64__)
+#if !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__aarch64__)
COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat));
#endif
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc
index 196eb3b3c64..a93d38d8aac 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc
@@ -12,10 +12,7 @@
#include "sanitizer_platform.h"
-#if SANITIZER_LINUX || SANITIZER_MAC
-
-#include "sanitizer_internal_defs.h"
-#include "sanitizer_platform_limits_posix.h"
+#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC
#include <arpa/inet.h>
#include <dirent.h>
@@ -31,10 +28,12 @@
#include <pwd.h>
#include <signal.h>
#include <stddef.h>
+#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
+#include <sys/timeb.h>
#include <sys/times.h>
#include <sys/types.h>
#include <sys/utsname.h>
@@ -42,12 +41,14 @@
#include <time.h>
#include <wchar.h>
+#if !SANITIZER_ANDROID
+#include <sys/mount.h>
+#endif
+
#if SANITIZER_LINUX
+#include <malloc.h>
#include <mntent.h>
#include <netinet/ether.h>
-#include <utime.h>
-#include <sys/mount.h>
-#include <sys/ptrace.h>
#include <sys/sysinfo.h>
#include <sys/vt.h>
#include <linux/cdrom.h>
@@ -62,18 +63,63 @@
#include <linux/posix_types.h>
#endif
+#if SANITIZER_FREEBSD
+# include <sys/mount.h>
+# include <sys/sockio.h>
+# include <sys/socket.h>
+# include <sys/filio.h>
+# include <sys/signal.h>
+# include <sys/timespec.h>
+# include <sys/timex.h>
+# include <sys/mqueue.h>
+# include <sys/msg.h>
+# include <sys/ipc.h>
+# include <sys/msg.h>
+# include <sys/statvfs.h>
+# include <sys/soundcard.h>
+# include <sys/mtio.h>
+# include <sys/consio.h>
+# include <sys/kbio.h>
+# include <sys/link_elf.h>
+# include <netinet/ip_mroute.h>
+# include <netinet/in.h>
+# include <netinet/ip_compat.h>
+# include <net/ethernet.h>
+# include <net/ppp_defs.h>
+# include <glob.h>
+# include <term.h>
+
+#define _KERNEL // to declare 'shminfo' structure
+# include <sys/shm.h>
+#undef _KERNEL
+
+#undef INLINE // to avoid clashes with sanitizers' definitions
+#endif
+
+#if SANITIZER_FREEBSD || SANITIZER_IOS
+#undef IOC_DIRMASK
+#endif
+
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
+# include <utime.h>
+# include <sys/ptrace.h>
+#endif
+
#if !SANITIZER_ANDROID
+#include <ifaddrs.h>
#include <sys/ucontext.h>
#include <wordexp.h>
#endif
#if SANITIZER_LINUX && !SANITIZER_ANDROID
#include <glob.h>
+#include <obstack.h>
#include <mqueue.h>
#include <net/if_ppp.h>
#include <netax25/ax25.h>
#include <netipx/ipx.h>
#include <netrom/netrom.h>
+#include <rpc/xdr.h>
#include <scsi/scsi.h>
#include <sys/mtio.h>
#include <sys/kd.h>
@@ -92,7 +138,6 @@
#include <linux/serial.h>
#include <sys/msg.h>
#include <sys/ipc.h>
-#include <sys/shm.h>
#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
#if SANITIZER_ANDROID
@@ -112,16 +157,19 @@
#if SANITIZER_MAC
#include <net/ethernet.h>
#include <sys/filio.h>
-#include <sys/mount.h>
#include <sys/sockio.h>
#endif
+// Include these after system headers to avoid name clashes and ambiguities.
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_platform_limits_posix.h"
+
namespace __sanitizer {
unsigned struct_utsname_sz = sizeof(struct utsname);
unsigned struct_stat_sz = sizeof(struct stat);
-#if !SANITIZER_IOS
+#if !SANITIZER_IOS && !SANITIZER_FREEBSD
unsigned struct_stat64_sz = sizeof(struct stat64);
-#endif // !SANITIZER_IOS
+#endif // !SANITIZER_IOS && !SANITIZER_FREEBSD
unsigned struct_rusage_sz = sizeof(struct rusage);
unsigned struct_tm_sz = sizeof(struct tm);
unsigned struct_passwd_sz = sizeof(struct passwd);
@@ -134,6 +182,7 @@ namespace __sanitizer {
unsigned pid_t_sz = sizeof(pid_t);
unsigned timeval_sz = sizeof(timeval);
unsigned uid_t_sz = sizeof(uid_t);
+ unsigned gid_t_sz = sizeof(gid_t);
unsigned mbstate_t_sz = sizeof(mbstate_t);
unsigned sigset_t_sz = sizeof(sigset_t);
unsigned struct_timezone_sz = sizeof(struct timezone);
@@ -147,33 +196,40 @@ namespace __sanitizer {
#endif // SANITIZER_MAC && !SANITIZER_IOS
#if !SANITIZER_ANDROID
+ unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
unsigned ucontext_t_sz = sizeof(ucontext_t);
#endif // !SANITIZER_ANDROID
#if SANITIZER_LINUX
- unsigned struct_rlimit_sz = sizeof(struct rlimit);
unsigned struct_epoll_event_sz = sizeof(struct epoll_event);
unsigned struct_sysinfo_sz = sizeof(struct sysinfo);
- unsigned struct_timespec_sz = sizeof(struct timespec);
unsigned __user_cap_header_struct_sz =
sizeof(struct __user_cap_header_struct);
unsigned __user_cap_data_struct_sz = sizeof(struct __user_cap_data_struct);
- unsigned struct_utimbuf_sz = sizeof(struct utimbuf);
unsigned struct_new_utsname_sz = sizeof(struct new_utsname);
unsigned struct_old_utsname_sz = sizeof(struct old_utsname);
unsigned struct_oldold_utsname_sz = sizeof(struct oldold_utsname);
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
+ unsigned struct_rlimit_sz = sizeof(struct rlimit);
+ unsigned struct_timespec_sz = sizeof(struct timespec);
+ unsigned struct_utimbuf_sz = sizeof(struct utimbuf);
unsigned struct_itimerspec_sz = sizeof(struct itimerspec);
- unsigned struct_ustat_sz = sizeof(struct ustat);
-#endif // SANITIZER_LINUX
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD
#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ unsigned struct_ustat_sz = sizeof(struct ustat);
unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
+ unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+
+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
unsigned struct_timex_sz = sizeof(struct timex);
unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds);
unsigned struct_mq_attr_sz = sizeof(struct mq_attr);
unsigned struct_statvfs_sz = sizeof(struct statvfs);
- unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
-#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+#endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
uptr sig_ign = (uptr)SIG_IGN;
uptr sig_dfl = (uptr)SIG_DFL;
@@ -184,15 +240,17 @@ namespace __sanitizer {
#endif
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
unsigned struct_shminfo_sz = sizeof(struct shminfo);
unsigned struct_shm_info_sz = sizeof(struct shm_info);
int shmctl_ipc_stat = (int)IPC_STAT;
int shmctl_ipc_info = (int)IPC_INFO;
int shmctl_shm_info = (int)SHM_INFO;
- int shmctl_shm_stat = (int)SHM_INFO;
+ int shmctl_shm_stat = (int)SHM_STAT;
#endif
+ int map_fixed = MAP_FIXED;
+
int af_inet = (int)AF_INET;
int af_inet6 = (int)AF_INET6;
@@ -205,13 +263,13 @@ namespace __sanitizer {
return 0;
}
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
int glob_nomatch = GLOB_NOMATCH;
int glob_altdirfunc = GLOB_ALTDIRFUNC;
#endif
#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
- (defined(__i386) || defined (__x86_64)) // NOLINT
+ (defined(__i386) || defined(__x86_64))
unsigned struct_user_regs_struct_sz = sizeof(struct user_regs_struct);
unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpregs_struct);
#ifdef __x86_64
@@ -229,15 +287,21 @@ namespace __sanitizer {
int ptrace_setfpregs = PTRACE_SETFPREGS;
int ptrace_getfpxregs = PTRACE_GETFPXREGS;
int ptrace_setfpxregs = PTRACE_SETFPXREGS;
+#if (defined(PTRACE_GETSIGINFO) && defined(PTRACE_SETSIGINFO)) || \
+ (defined(PT_GETSIGINFO) && defined(PT_SETSIGINFO))
int ptrace_getsiginfo = PTRACE_GETSIGINFO;
int ptrace_setsiginfo = PTRACE_SETSIGINFO;
+#else
+ int ptrace_getsiginfo = -1;
+ int ptrace_setsiginfo = -1;
+#endif // PTRACE_GETSIGINFO/PTRACE_SETSIGINFO
#if defined(PTRACE_GETREGSET) && defined(PTRACE_SETREGSET)
int ptrace_getregset = PTRACE_GETREGSET;
int ptrace_setregset = PTRACE_SETREGSET;
#else
int ptrace_getregset = -1;
int ptrace_setregset = -1;
-#endif
+#endif // PTRACE_GETREGSET/PTRACE_SETREGSET
#endif
unsigned path_max = PATH_MAX;
@@ -257,15 +321,6 @@ namespace __sanitizer {
unsigned struct_cdrom_tocentry_sz = sizeof(struct cdrom_tocentry);
unsigned struct_cdrom_tochdr_sz = sizeof(struct cdrom_tochdr);
unsigned struct_cdrom_volctrl_sz = sizeof(struct cdrom_volctrl);
-#if SOUND_VERSION >= 0x040000
- unsigned struct_copr_buffer_sz = 0;
- unsigned struct_copr_debug_buf_sz = 0;
- unsigned struct_copr_msg_sz = 0;
-#else
- unsigned struct_copr_buffer_sz = sizeof(struct copr_buffer);
- unsigned struct_copr_debug_buf_sz = sizeof(struct copr_debug_buf);
- unsigned struct_copr_msg_sz = sizeof(struct copr_msg);
-#endif
unsigned struct_ff_effect_sz = sizeof(struct ff_effect);
unsigned struct_floppy_drive_params_sz = sizeof(struct floppy_drive_params);
unsigned struct_floppy_drive_struct_sz = sizeof(struct floppy_drive_struct);
@@ -279,23 +334,34 @@ namespace __sanitizer {
unsigned struct_hd_geometry_sz = sizeof(struct hd_geometry);
unsigned struct_input_absinfo_sz = sizeof(struct input_absinfo);
unsigned struct_input_id_sz = sizeof(struct input_id);
+ unsigned struct_mtpos_sz = sizeof(struct mtpos);
+ unsigned struct_termio_sz = sizeof(struct termio);
+ unsigned struct_vt_consize_sz = sizeof(struct vt_consize);
+ unsigned struct_vt_sizes_sz = sizeof(struct vt_sizes);
+ unsigned struct_vt_stat_sz = sizeof(struct vt_stat);
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
+#if SOUND_VERSION >= 0x040000
+ unsigned struct_copr_buffer_sz = 0;
+ unsigned struct_copr_debug_buf_sz = 0;
+ unsigned struct_copr_msg_sz = 0;
+#else
+ unsigned struct_copr_buffer_sz = sizeof(struct copr_buffer);
+ unsigned struct_copr_debug_buf_sz = sizeof(struct copr_debug_buf);
+ unsigned struct_copr_msg_sz = sizeof(struct copr_msg);
+#endif
unsigned struct_midi_info_sz = sizeof(struct midi_info);
unsigned struct_mtget_sz = sizeof(struct mtget);
unsigned struct_mtop_sz = sizeof(struct mtop);
- unsigned struct_mtpos_sz = sizeof(struct mtpos);
unsigned struct_rtentry_sz = sizeof(struct rtentry);
unsigned struct_sbi_instrument_sz = sizeof(struct sbi_instrument);
unsigned struct_seq_event_rec_sz = sizeof(struct seq_event_rec);
unsigned struct_synth_info_sz = sizeof(struct synth_info);
- unsigned struct_termio_sz = sizeof(struct termio);
- unsigned struct_vt_consize_sz = sizeof(struct vt_consize);
unsigned struct_vt_mode_sz = sizeof(struct vt_mode);
- unsigned struct_vt_sizes_sz = sizeof(struct vt_sizes);
- unsigned struct_vt_stat_sz = sizeof(struct vt_stat);
-#endif
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD
#if SANITIZER_LINUX && !SANITIZER_ANDROID
- unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info);
unsigned struct_ax25_parms_struct_sz = sizeof(struct ax25_parms_struct);
unsigned struct_cyclades_monitor_sz = sizeof(struct cyclades_monitor);
#if EV_VERSION > (0x010000)
@@ -310,7 +376,6 @@ namespace __sanitizer {
unsigned struct_kbsentry_sz = sizeof(struct kbsentry);
unsigned struct_mtconfiginfo_sz = sizeof(struct mtconfiginfo);
unsigned struct_nr_parms_struct_sz = sizeof(struct nr_parms_struct);
- unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
unsigned struct_scc_modem_sz = sizeof(struct scc_modem);
unsigned struct_scc_stat_sz = sizeof(struct scc_stat);
unsigned struct_serial_multiport_struct_sz
@@ -319,7 +384,12 @@ namespace __sanitizer {
unsigned struct_sockaddr_ax25_sz = sizeof(struct sockaddr_ax25);
unsigned struct_unimapdesc_sz = sizeof(struct unimapdesc);
unsigned struct_unimapinit_sz = sizeof(struct unimapinit);
-#endif
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+
+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
+ unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info);
+ unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
+#endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
#if !SANITIZER_ANDROID && !SANITIZER_MAC
unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
@@ -372,10 +442,11 @@ namespace __sanitizer {
unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
unsigned IOCTL_TIOCSTI = TIOCSTI;
unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
-#if (SANITIZER_LINUX && !SANITIZER_ANDROID)
+#if ((SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID)
unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT;
unsigned IOCTL_SIOCGETVIFCNT = SIOCGETVIFCNT;
#endif
+
#if SANITIZER_LINUX
unsigned IOCTL_EVIOCGABS = EVIOCGABS(0);
unsigned IOCTL_EVIOCGBIT = EVIOCGBIT(0, 0);
@@ -466,9 +537,7 @@ namespace __sanitizer {
unsigned IOCTL_HDIO_SET_MULTCOUNT = HDIO_SET_MULTCOUNT;
unsigned IOCTL_HDIO_SET_NOWERR = HDIO_SET_NOWERR;
unsigned IOCTL_HDIO_SET_UNMASKINTR = HDIO_SET_UNMASKINTR;
- unsigned IOCTL_MTIOCGET = MTIOCGET;
unsigned IOCTL_MTIOCPOS = MTIOCPOS;
- unsigned IOCTL_MTIOCTOP = MTIOCTOP;
unsigned IOCTL_PPPIOCGASYNCMAP = PPPIOCGASYNCMAP;
unsigned IOCTL_PPPIOCGDEBUG = PPPIOCGDEBUG;
unsigned IOCTL_PPPIOCGFLAGS = PPPIOCGFLAGS;
@@ -480,9 +549,7 @@ namespace __sanitizer {
unsigned IOCTL_PPPIOCSMAXCID = PPPIOCSMAXCID;
unsigned IOCTL_PPPIOCSMRU = PPPIOCSMRU;
unsigned IOCTL_PPPIOCSXASYNCMAP = PPPIOCSXASYNCMAP;
- unsigned IOCTL_SIOCADDRT = SIOCADDRT;
unsigned IOCTL_SIOCDARP = SIOCDARP;
- unsigned IOCTL_SIOCDELRT = SIOCDELRT;
unsigned IOCTL_SIOCDRARP = SIOCDRARP;
unsigned IOCTL_SIOCGARP = SIOCGARP;
unsigned IOCTL_SIOCGIFENCAP = SIOCGIFENCAP;
@@ -501,7 +568,7 @@ namespace __sanitizer {
unsigned IOCTL_SIOCSIFMEM = SIOCSIFMEM;
unsigned IOCTL_SIOCSIFSLAVE = SIOCSIFSLAVE;
unsigned IOCTL_SIOCSRARP = SIOCSRARP;
-#if SOUND_VERSION >= 0x040000
+# if SOUND_VERSION >= 0x040000
unsigned IOCTL_SNDCTL_COPR_HALT = IOCTL_NOT_PRESENT;
unsigned IOCTL_SNDCTL_COPR_LOAD = IOCTL_NOT_PRESENT;
unsigned IOCTL_SNDCTL_COPR_RCODE = IOCTL_NOT_PRESENT;
@@ -518,7 +585,7 @@ namespace __sanitizer {
unsigned IOCTL_SOUND_PCM_READ_RATE = IOCTL_NOT_PRESENT;
unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS = IOCTL_NOT_PRESENT;
unsigned IOCTL_SOUND_PCM_WRITE_FILTER = IOCTL_NOT_PRESENT;
-#else
+# else // SOUND_VERSION
unsigned IOCTL_SNDCTL_COPR_HALT = SNDCTL_COPR_HALT;
unsigned IOCTL_SNDCTL_COPR_LOAD = SNDCTL_COPR_LOAD;
unsigned IOCTL_SNDCTL_COPR_RCODE = SNDCTL_COPR_RCODE;
@@ -535,7 +602,41 @@ namespace __sanitizer {
unsigned IOCTL_SOUND_PCM_READ_RATE = SOUND_PCM_READ_RATE;
unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS = SOUND_PCM_WRITE_CHANNELS;
unsigned IOCTL_SOUND_PCM_WRITE_FILTER = SOUND_PCM_WRITE_FILTER;
-#endif
+#endif // SOUND_VERSION
+ unsigned IOCTL_TCFLSH = TCFLSH;
+ unsigned IOCTL_TCGETA = TCGETA;
+ unsigned IOCTL_TCGETS = TCGETS;
+ unsigned IOCTL_TCSBRK = TCSBRK;
+ unsigned IOCTL_TCSBRKP = TCSBRKP;
+ unsigned IOCTL_TCSETA = TCSETA;
+ unsigned IOCTL_TCSETAF = TCSETAF;
+ unsigned IOCTL_TCSETAW = TCSETAW;
+ unsigned IOCTL_TCSETS = TCSETS;
+ unsigned IOCTL_TCSETSF = TCSETSF;
+ unsigned IOCTL_TCSETSW = TCSETSW;
+ unsigned IOCTL_TCXONC = TCXONC;
+ unsigned IOCTL_TIOCGLCKTRMIOS = TIOCGLCKTRMIOS;
+ unsigned IOCTL_TIOCGSOFTCAR = TIOCGSOFTCAR;
+ unsigned IOCTL_TIOCINQ = TIOCINQ;
+ unsigned IOCTL_TIOCLINUX = TIOCLINUX;
+ unsigned IOCTL_TIOCSERCONFIG = TIOCSERCONFIG;
+ unsigned IOCTL_TIOCSERGETLSR = TIOCSERGETLSR;
+ unsigned IOCTL_TIOCSERGWILD = TIOCSERGWILD;
+ unsigned IOCTL_TIOCSERSWILD = TIOCSERSWILD;
+ unsigned IOCTL_TIOCSLCKTRMIOS = TIOCSLCKTRMIOS;
+ unsigned IOCTL_TIOCSSOFTCAR = TIOCSSOFTCAR;
+ unsigned IOCTL_VT_DISALLOCATE = VT_DISALLOCATE;
+ unsigned IOCTL_VT_GETSTATE = VT_GETSTATE;
+ unsigned IOCTL_VT_RESIZE = VT_RESIZE;
+ unsigned IOCTL_VT_RESIZEX = VT_RESIZEX;
+ unsigned IOCTL_VT_SENDSIG = VT_SENDSIG;
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
+ unsigned IOCTL_MTIOCGET = MTIOCGET;
+ unsigned IOCTL_MTIOCTOP = MTIOCTOP;
+ unsigned IOCTL_SIOCADDRT = SIOCADDRT;
+ unsigned IOCTL_SIOCDELRT = SIOCDELRT;
unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE = SNDCTL_DSP_GETBLKSIZE;
unsigned IOCTL_SNDCTL_DSP_GETFMTS = SNDCTL_DSP_GETFMTS;
unsigned IOCTL_SNDCTL_DSP_NONBLOCK = SNDCTL_DSP_NONBLOCK;
@@ -620,40 +721,14 @@ namespace __sanitizer {
unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH = SOUND_MIXER_WRITE_SYNTH;
unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE = SOUND_MIXER_WRITE_TREBLE;
unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME = SOUND_MIXER_WRITE_VOLUME;
- unsigned IOCTL_TCFLSH = TCFLSH;
- unsigned IOCTL_TCGETA = TCGETA;
- unsigned IOCTL_TCGETS = TCGETS;
- unsigned IOCTL_TCSBRK = TCSBRK;
- unsigned IOCTL_TCSBRKP = TCSBRKP;
- unsigned IOCTL_TCSETA = TCSETA;
- unsigned IOCTL_TCSETAF = TCSETAF;
- unsigned IOCTL_TCSETAW = TCSETAW;
- unsigned IOCTL_TCSETS = TCSETS;
- unsigned IOCTL_TCSETSF = TCSETSF;
- unsigned IOCTL_TCSETSW = TCSETSW;
- unsigned IOCTL_TCXONC = TCXONC;
- unsigned IOCTL_TIOCGLCKTRMIOS = TIOCGLCKTRMIOS;
- unsigned IOCTL_TIOCGSOFTCAR = TIOCGSOFTCAR;
- unsigned IOCTL_TIOCINQ = TIOCINQ;
- unsigned IOCTL_TIOCLINUX = TIOCLINUX;
- unsigned IOCTL_TIOCSERCONFIG = TIOCSERCONFIG;
- unsigned IOCTL_TIOCSERGETLSR = TIOCSERGETLSR;
- unsigned IOCTL_TIOCSERGWILD = TIOCSERGWILD;
- unsigned IOCTL_TIOCSERSWILD = TIOCSERSWILD;
- unsigned IOCTL_TIOCSLCKTRMIOS = TIOCSLCKTRMIOS;
- unsigned IOCTL_TIOCSSOFTCAR = TIOCSSOFTCAR;
unsigned IOCTL_VT_ACTIVATE = VT_ACTIVATE;
- unsigned IOCTL_VT_DISALLOCATE = VT_DISALLOCATE;
unsigned IOCTL_VT_GETMODE = VT_GETMODE;
- unsigned IOCTL_VT_GETSTATE = VT_GETSTATE;
unsigned IOCTL_VT_OPENQRY = VT_OPENQRY;
unsigned IOCTL_VT_RELDISP = VT_RELDISP;
- unsigned IOCTL_VT_RESIZE = VT_RESIZE;
- unsigned IOCTL_VT_RESIZEX = VT_RESIZEX;
- unsigned IOCTL_VT_SENDSIG = VT_SENDSIG;
unsigned IOCTL_VT_SETMODE = VT_SETMODE;
unsigned IOCTL_VT_WAITACTIVE = VT_WAITACTIVE;
-#endif
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD
+
#if SANITIZER_LINUX && !SANITIZER_ANDROID
unsigned IOCTL_CYGETDEFTHRESH = CYGETDEFTHRESH;
unsigned IOCTL_CYGETDEFTIMEOUT = CYGETDEFTIMEOUT;
@@ -685,37 +760,25 @@ namespace __sanitizer {
unsigned IOCTL_FS_IOC_SETVERSION = FS_IOC_SETVERSION;
unsigned IOCTL_GIO_CMAP = GIO_CMAP;
unsigned IOCTL_GIO_FONT = GIO_FONT;
- unsigned IOCTL_GIO_SCRNMAP = GIO_SCRNMAP;
unsigned IOCTL_GIO_UNIMAP = GIO_UNIMAP;
unsigned IOCTL_GIO_UNISCRNMAP = GIO_UNISCRNMAP;
unsigned IOCTL_KDADDIO = KDADDIO;
unsigned IOCTL_KDDELIO = KDDELIO;
- unsigned IOCTL_KDDISABIO = KDDISABIO;
- unsigned IOCTL_KDENABIO = KDENABIO;
unsigned IOCTL_KDGETKEYCODE = KDGETKEYCODE;
- unsigned IOCTL_KDGETLED = KDGETLED;
- unsigned IOCTL_KDGETMODE = KDGETMODE;
unsigned IOCTL_KDGKBDIACR = KDGKBDIACR;
unsigned IOCTL_KDGKBENT = KDGKBENT;
unsigned IOCTL_KDGKBLED = KDGKBLED;
unsigned IOCTL_KDGKBMETA = KDGKBMETA;
- unsigned IOCTL_KDGKBMODE = KDGKBMODE;
unsigned IOCTL_KDGKBSENT = KDGKBSENT;
- unsigned IOCTL_KDGKBTYPE = KDGKBTYPE;
unsigned IOCTL_KDMAPDISP = KDMAPDISP;
- unsigned IOCTL_KDMKTONE = KDMKTONE;
unsigned IOCTL_KDSETKEYCODE = KDSETKEYCODE;
- unsigned IOCTL_KDSETLED = KDSETLED;
- unsigned IOCTL_KDSETMODE = KDSETMODE;
unsigned IOCTL_KDSIGACCEPT = KDSIGACCEPT;
unsigned IOCTL_KDSKBDIACR = KDSKBDIACR;
unsigned IOCTL_KDSKBENT = KDSKBENT;
unsigned IOCTL_KDSKBLED = KDSKBLED;
unsigned IOCTL_KDSKBMETA = KDSKBMETA;
- unsigned IOCTL_KDSKBMODE = KDSKBMODE;
unsigned IOCTL_KDSKBSENT = KDSKBSENT;
unsigned IOCTL_KDUNMAPDISP = KDUNMAPDISP;
- unsigned IOCTL_KIOCSOUND = KIOCSOUND;
unsigned IOCTL_LPABORT = LPABORT;
unsigned IOCTL_LPABORTOPEN = LPABORTOPEN;
unsigned IOCTL_LPCAREFUL = LPCAREFUL;
@@ -730,7 +793,6 @@ namespace __sanitizer {
unsigned IOCTL_MTIOCSETCONFIG = MTIOCSETCONFIG;
unsigned IOCTL_PIO_CMAP = PIO_CMAP;
unsigned IOCTL_PIO_FONT = PIO_FONT;
- unsigned IOCTL_PIO_SCRNMAP = PIO_SCRNMAP;
unsigned IOCTL_PIO_UNIMAP = PIO_UNIMAP;
unsigned IOCTL_PIO_UNIMAPCLR = PIO_UNIMAPCLR;
unsigned IOCTL_PIO_UNISCRNMAP = PIO_UNISCRNMAP;
@@ -752,20 +814,40 @@ namespace __sanitizer {
unsigned IOCTL_SIOCNRGETPARMS = SIOCNRGETPARMS;
unsigned IOCTL_SIOCNRRTCTL = SIOCNRRTCTL;
unsigned IOCTL_SIOCNRSETPARMS = SIOCNRSETPARMS;
- unsigned IOCTL_SNDCTL_DSP_GETISPACE = SNDCTL_DSP_GETISPACE;
- unsigned IOCTL_SNDCTL_DSP_GETOSPACE = SNDCTL_DSP_GETOSPACE;
unsigned IOCTL_TIOCGSERIAL = TIOCGSERIAL;
unsigned IOCTL_TIOCSERGETMULTI = TIOCSERGETMULTI;
unsigned IOCTL_TIOCSERSETMULTI = TIOCSERSETMULTI;
unsigned IOCTL_TIOCSSERIAL = TIOCSSERIAL;
-#endif
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
+ unsigned IOCTL_GIO_SCRNMAP = GIO_SCRNMAP;
+ unsigned IOCTL_KDDISABIO = KDDISABIO;
+ unsigned IOCTL_KDENABIO = KDENABIO;
+ unsigned IOCTL_KDGETLED = KDGETLED;
+ unsigned IOCTL_KDGETMODE = KDGETMODE;
+ unsigned IOCTL_KDGKBMODE = KDGKBMODE;
+ unsigned IOCTL_KDGKBTYPE = KDGKBTYPE;
+ unsigned IOCTL_KDMKTONE = KDMKTONE;
+ unsigned IOCTL_KDSETLED = KDSETLED;
+ unsigned IOCTL_KDSETMODE = KDSETMODE;
+ unsigned IOCTL_KDSKBMODE = KDSKBMODE;
+ unsigned IOCTL_KIOCSOUND = KIOCSOUND;
+ unsigned IOCTL_PIO_SCRNMAP = PIO_SCRNMAP;
+ unsigned IOCTL_SNDCTL_DSP_GETISPACE = SNDCTL_DSP_GETISPACE;
+ unsigned IOCTL_SNDCTL_DSP_GETOSPACE = SNDCTL_DSP_GETOSPACE;
+#endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
+
+ const int errno_EINVAL = EINVAL;
// EOWNERDEAD is not present in some older platforms.
#if defined(EOWNERDEAD)
- extern const int errno_EOWNERDEAD = EOWNERDEAD;
+ const int errno_EOWNERDEAD = EOWNERDEAD;
#else
- extern const int errno_EOWNERDEAD = -1;
+ const int errno_EOWNERDEAD = -1;
#endif
+
+ const int si_SEGV_MAPERR = SEGV_MAPERR;
+ const int si_SEGV_ACCERR = SEGV_ACCERR;
} // namespace __sanitizer
COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
@@ -774,6 +856,31 @@ COMPILER_CHECK(sizeof(socklen_t) == sizeof(unsigned));
CHECK_TYPE_SIZE(pthread_key_t);
#if SANITIZER_LINUX
+// FIXME: We define those on Linux and Mac, but only check on Linux.
+COMPILER_CHECK(IOC_NRBITS == _IOC_NRBITS);
+COMPILER_CHECK(IOC_TYPEBITS == _IOC_TYPEBITS);
+COMPILER_CHECK(IOC_SIZEBITS == _IOC_SIZEBITS);
+COMPILER_CHECK(IOC_DIRBITS == _IOC_DIRBITS);
+COMPILER_CHECK(IOC_NRMASK == _IOC_NRMASK);
+COMPILER_CHECK(IOC_TYPEMASK == _IOC_TYPEMASK);
+COMPILER_CHECK(IOC_SIZEMASK == _IOC_SIZEMASK);
+COMPILER_CHECK(IOC_DIRMASK == _IOC_DIRMASK);
+COMPILER_CHECK(IOC_NRSHIFT == _IOC_NRSHIFT);
+COMPILER_CHECK(IOC_TYPESHIFT == _IOC_TYPESHIFT);
+COMPILER_CHECK(IOC_SIZESHIFT == _IOC_SIZESHIFT);
+COMPILER_CHECK(IOC_DIRSHIFT == _IOC_DIRSHIFT);
+COMPILER_CHECK(IOC_NONE == _IOC_NONE);
+COMPILER_CHECK(IOC_WRITE == _IOC_WRITE);
+COMPILER_CHECK(IOC_READ == _IOC_READ);
+COMPILER_CHECK(EVIOC_ABS_MAX == ABS_MAX);
+COMPILER_CHECK(EVIOC_EV_MAX == EV_MAX);
+COMPILER_CHECK(IOC_SIZE(0x12345678) == _IOC_SIZE(0x12345678));
+COMPILER_CHECK(IOC_DIR(0x12345678) == _IOC_DIR(0x12345678));
+COMPILER_CHECK(IOC_NR(0x12345678) == _IOC_NR(0x12345678));
+COMPILER_CHECK(IOC_TYPE(0x12345678) == _IOC_TYPE(0x12345678));
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
// There are more undocumented fields in dl_phdr_info that we are not interested
// in.
COMPILER_CHECK(sizeof(__sanitizer_dl_phdr_info) <= sizeof(dl_phdr_info));
@@ -781,11 +888,9 @@ CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_addr);
CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_name);
CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr);
CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum);
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD
-COMPILER_CHECK(IOC_SIZE(0x12345678) == _IOC_SIZE(0x12345678));
-#endif
-
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
CHECK_TYPE_SIZE(glob_t);
CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc);
CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv);
@@ -837,6 +942,8 @@ COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
CHECK_SIZE_AND_OFFSET(dirent, d_ino);
#if SANITIZER_MAC
CHECK_SIZE_AND_OFFSET(dirent, d_seekoff);
+#elif SANITIZER_FREEBSD
+// There is no 'd_off' field on FreeBSD.
#else
CHECK_SIZE_AND_OFFSET(dirent, d_off);
#endif
@@ -921,15 +1028,20 @@ CHECK_SIZE_AND_OFFSET(mntent, mnt_passno);
CHECK_TYPE_SIZE(ether_addr);
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
CHECK_TYPE_SIZE(ipc_perm);
+# if SANITIZER_FREEBSD
+CHECK_SIZE_AND_OFFSET(ipc_perm, key);
+CHECK_SIZE_AND_OFFSET(ipc_perm, seq);
+# else
CHECK_SIZE_AND_OFFSET(ipc_perm, __key);
+CHECK_SIZE_AND_OFFSET(ipc_perm, __seq);
+# endif
CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
-CHECK_SIZE_AND_OFFSET(ipc_perm, __seq);
CHECK_TYPE_SIZE(shmid_ds);
CHECK_SIZE_AND_OFFSET(shmid_ds, shm_perm);
@@ -944,4 +1056,108 @@ CHECK_SIZE_AND_OFFSET(shmid_ds, shm_nattch);
CHECK_TYPE_SIZE(clock_t);
-#endif // SANITIZER_LINUX || SANITIZER_MAC
+#if !SANITIZER_ANDROID
+CHECK_TYPE_SIZE(ifaddrs);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_addr);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_netmask);
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
+// Compare against the union, because we can't reach into the union in a
+// compliant way.
+#ifdef ifa_dstaddr
+#undef ifa_dstaddr
+#endif
+# if SANITIZER_FREEBSD
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr);
+# else
+COMPILER_CHECK(sizeof(((__sanitizer_ifaddrs *)NULL)->ifa_dstaddr) ==
+ sizeof(((ifaddrs *)NULL)->ifa_ifu));
+COMPILER_CHECK(offsetof(__sanitizer_ifaddrs, ifa_dstaddr) ==
+ offsetof(ifaddrs, ifa_ifu));
+# endif // SANITIZER_FREEBSD
+#else
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr);
+#endif // SANITIZER_LINUX
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data);
+#endif
+
+#if SANITIZER_LINUX
+COMPILER_CHECK(sizeof(__sanitizer_mallinfo) == sizeof(struct mallinfo));
+#endif
+
+CHECK_TYPE_SIZE(timeb);
+CHECK_SIZE_AND_OFFSET(timeb, time);
+CHECK_SIZE_AND_OFFSET(timeb, millitm);
+CHECK_SIZE_AND_OFFSET(timeb, timezone);
+CHECK_SIZE_AND_OFFSET(timeb, dstflag);
+
+CHECK_TYPE_SIZE(passwd);
+CHECK_SIZE_AND_OFFSET(passwd, pw_name);
+CHECK_SIZE_AND_OFFSET(passwd, pw_passwd);
+CHECK_SIZE_AND_OFFSET(passwd, pw_uid);
+CHECK_SIZE_AND_OFFSET(passwd, pw_gid);
+CHECK_SIZE_AND_OFFSET(passwd, pw_dir);
+CHECK_SIZE_AND_OFFSET(passwd, pw_shell);
+
+#if !SANITIZER_ANDROID
+CHECK_SIZE_AND_OFFSET(passwd, pw_gecos);
+#endif
+
+#if SANITIZER_MAC
+CHECK_SIZE_AND_OFFSET(passwd, pw_change);
+CHECK_SIZE_AND_OFFSET(passwd, pw_expire);
+CHECK_SIZE_AND_OFFSET(passwd, pw_class);
+#endif
+
+
+CHECK_TYPE_SIZE(group);
+CHECK_SIZE_AND_OFFSET(group, gr_name);
+CHECK_SIZE_AND_OFFSET(group, gr_passwd);
+CHECK_SIZE_AND_OFFSET(group, gr_gid);
+CHECK_SIZE_AND_OFFSET(group, gr_mem);
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+CHECK_TYPE_SIZE(XDR);
+CHECK_SIZE_AND_OFFSET(XDR, x_op);
+CHECK_SIZE_AND_OFFSET(XDR, x_ops);
+CHECK_SIZE_AND_OFFSET(XDR, x_public);
+CHECK_SIZE_AND_OFFSET(XDR, x_private);
+CHECK_SIZE_AND_OFFSET(XDR, x_base);
+CHECK_SIZE_AND_OFFSET(XDR, x_handy);
+COMPILER_CHECK(__sanitizer_XDR_ENCODE == XDR_ENCODE);
+COMPILER_CHECK(__sanitizer_XDR_DECODE == XDR_DECODE);
+COMPILER_CHECK(__sanitizer_XDR_FREE == XDR_FREE);
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+COMPILER_CHECK(sizeof(__sanitizer_FILE) <= sizeof(FILE));
+CHECK_SIZE_AND_OFFSET(FILE, _flags);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_read_ptr);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_read_end);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_read_base);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_write_ptr);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_write_end);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_write_base);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_buf_base);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_buf_end);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_save_base);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_backup_base);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_save_end);
+CHECK_SIZE_AND_OFFSET(FILE, _markers);
+CHECK_SIZE_AND_OFFSET(FILE, _chain);
+CHECK_SIZE_AND_OFFSET(FILE, _fileno);
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+COMPILER_CHECK(sizeof(__sanitizer__obstack_chunk) <= sizeof(_obstack_chunk));
+CHECK_SIZE_AND_OFFSET(_obstack_chunk, limit);
+CHECK_SIZE_AND_OFFSET(_obstack_chunk, prev);
+CHECK_TYPE_SIZE(obstack);
+CHECK_SIZE_AND_OFFSET(obstack, chunk_size);
+CHECK_SIZE_AND_OFFSET(obstack, chunk);
+CHECK_SIZE_AND_OFFSET(obstack, object_base);
+CHECK_SIZE_AND_OFFSET(obstack, next_free);
+#endif
+
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
index be6e6cf1c3f..dece2d3cbdd 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -19,12 +19,10 @@
namespace __sanitizer {
extern unsigned struct_utsname_sz;
extern unsigned struct_stat_sz;
-#if !SANITIZER_IOS
+#if !SANITIZER_FREEBSD && !SANITIZER_IOS
extern unsigned struct_stat64_sz;
#endif
extern unsigned struct_rusage_sz;
- extern unsigned struct_passwd_sz;
- extern unsigned struct_group_sz;
extern unsigned siginfo_t_sz;
extern unsigned struct_itimerval_sz;
extern unsigned pthread_t_sz;
@@ -32,6 +30,7 @@ namespace __sanitizer {
extern unsigned pid_t_sz;
extern unsigned timeval_sz;
extern unsigned uid_t_sz;
+ extern unsigned gid_t_sz;
extern unsigned mbstate_t_sz;
extern unsigned struct_timezone_sz;
extern unsigned struct_tms_sz;
@@ -40,6 +39,7 @@ namespace __sanitizer {
extern unsigned struct_sched_param_sz;
extern unsigned struct_statfs_sz;
extern unsigned struct_statfs64_sz;
+ extern unsigned struct_sockaddr_sz;
#if !SANITIZER_ANDROID
extern unsigned ucontext_t_sz;
@@ -48,23 +48,21 @@ namespace __sanitizer {
#if SANITIZER_LINUX
#if defined(__x86_64__)
- const unsigned struct___old_kernel_stat_sz = 32;
const unsigned struct_kernel_stat_sz = 144;
const unsigned struct_kernel_stat64_sz = 0;
#elif defined(__i386__)
- const unsigned struct___old_kernel_stat_sz = 32;
const unsigned struct_kernel_stat_sz = 64;
const unsigned struct_kernel_stat64_sz = 96;
#elif defined(__arm__)
- const unsigned struct___old_kernel_stat_sz = 32;
const unsigned struct_kernel_stat_sz = 64;
const unsigned struct_kernel_stat64_sz = 104;
+#elif defined(__aarch64__)
+ const unsigned struct_kernel_stat_sz = 128;
+ const unsigned struct_kernel_stat64_sz = 104;
#elif defined(__powerpc__) && !defined(__powerpc64__)
- const unsigned struct___old_kernel_stat_sz = 32;
const unsigned struct_kernel_stat_sz = 72;
const unsigned struct_kernel_stat64_sz = 104;
#elif defined(__powerpc64__)
- const unsigned struct___old_kernel_stat_sz = 0;
const unsigned struct_kernel_stat_sz = 144;
const unsigned struct_kernel_stat64_sz = 104;
#endif
@@ -74,23 +72,28 @@ namespace __sanitizer {
// More fields that vary with the kernel version.
};
- extern unsigned struct_utimbuf_sz;
+ extern unsigned struct_epoll_event_sz;
+ extern unsigned struct_sysinfo_sz;
+ extern unsigned __user_cap_header_struct_sz;
+ extern unsigned __user_cap_data_struct_sz;
extern unsigned struct_new_utsname_sz;
extern unsigned struct_old_utsname_sz;
extern unsigned struct_oldold_utsname_sz;
- extern unsigned struct_msqid_ds_sz;
- extern unsigned struct_mq_attr_sz;
- extern unsigned struct_timex_sz;
- extern unsigned struct_ustat_sz;
+
+ const unsigned struct_kexec_segment_sz = 4 * sizeof(unsigned long);
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
+
+#if defined(__powerpc64__)
+ const unsigned struct___old_kernel_stat_sz = 0;
+#else
+ const unsigned struct___old_kernel_stat_sz = 32;
+#endif
extern unsigned struct_rlimit_sz;
- extern unsigned struct_epoll_event_sz;
- extern unsigned struct_sysinfo_sz;
+ extern unsigned struct_utimbuf_sz;
extern unsigned struct_timespec_sz;
- extern unsigned __user_cap_header_struct_sz;
- extern unsigned __user_cap_data_struct_sz;
- const unsigned old_sigset_t_sz = sizeof(unsigned long);
- const unsigned struct_kexec_segment_sz = 4 * sizeof(unsigned long);
struct __sanitizer_iocb {
u64 aio_data;
@@ -127,11 +130,23 @@ namespace __sanitizer {
uptr newlen;
unsigned long ___unused[4];
};
-#endif // SANITIZER_LINUX
+
+ const unsigned old_sigset_t_sz = sizeof(unsigned long);
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD
+
+#if SANITIZER_ANDROID
+ struct __sanitizer_mallinfo {
+ uptr v[10];
+ };
+#endif
#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ struct __sanitizer_mallinfo {
+ int v[10];
+ };
+
+ extern unsigned struct_ustat_sz;
extern unsigned struct_rlimit64_sz;
- extern unsigned struct_statvfs_sz;
extern unsigned struct_statvfs64_sz;
struct __sanitizer_ipc_perm {
@@ -200,19 +215,121 @@ namespace __sanitizer {
uptr __unused5;
#endif
};
- #endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+#elif SANITIZER_FREEBSD
+ struct __sanitizer_ipc_perm {
+ unsigned int cuid;
+ unsigned int cgid;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned short mode;
+ unsigned short seq;
+ long key;
+ };
+
+ struct __sanitizer_shmid_ds {
+ __sanitizer_ipc_perm shm_perm;
+ unsigned long shm_segsz;
+ unsigned int shm_lpid;
+ unsigned int shm_cpid;
+ int shm_nattch;
+ unsigned long shm_atime;
+ unsigned long shm_dtime;
+ unsigned long shm_ctime;
+ };
+#endif
+
+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
+ extern unsigned struct_msqid_ds_sz;
+ extern unsigned struct_mq_attr_sz;
+ extern unsigned struct_timex_sz;
+ extern unsigned struct_statvfs_sz;
+#endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
struct __sanitizer_iovec {
- void *iov_base;
+ void *iov_base;
uptr iov_len;
};
+#if !SANITIZER_ANDROID
+ struct __sanitizer_ifaddrs {
+ struct __sanitizer_ifaddrs *ifa_next;
+ char *ifa_name;
+ unsigned int ifa_flags;
+ void *ifa_addr; // (struct sockaddr *)
+ void *ifa_netmask; // (struct sockaddr *)
+ // This is a union on Linux.
+# ifdef ifa_dstaddr
+# undef ifa_dstaddr
+# endif
+ void *ifa_dstaddr; // (struct sockaddr *)
+ void *ifa_data;
+ };
+#endif // !SANITIZER_ANDROID
+
#if SANITIZER_MAC
typedef unsigned long __sanitizer_pthread_key_t;
#else
typedef unsigned __sanitizer_pthread_key_t;
#endif
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+
+ struct __sanitizer_XDR {
+ int x_op;
+ void *x_ops;
+ uptr x_public;
+ uptr x_private;
+ uptr x_base;
+ unsigned x_handy;
+ };
+
+ const int __sanitizer_XDR_ENCODE = 0;
+ const int __sanitizer_XDR_DECODE = 1;
+ const int __sanitizer_XDR_FREE = 2;
+#endif
+
+ struct __sanitizer_passwd {
+ char *pw_name;
+ char *pw_passwd;
+ int pw_uid;
+ int pw_gid;
+#if SANITIZER_MAC || SANITIZER_FREEBSD
+ long pw_change;
+ char *pw_class;
+#endif
+#if !SANITIZER_ANDROID
+ char *pw_gecos;
+#endif
+ char *pw_dir;
+ char *pw_shell;
+#if SANITIZER_MAC || SANITIZER_FREEBSD
+ long pw_expire;
+#endif
+#if SANITIZER_FREEBSD
+ int pw_fields;
+#endif
+ };
+
+ struct __sanitizer_group {
+ char *gr_name;
+ char *gr_passwd;
+ int gr_gid;
+ char **gr_mem;
+ };
+
+#if defined(__x86_64__) && !defined(_LP64)
+ typedef long long __sanitizer_time_t;
+#else
+ typedef long __sanitizer_time_t;
+#endif
+
+ struct __sanitizer_timeb {
+ __sanitizer_time_t time;
+ unsigned short millitm;
+ short timezone;
+ short dstflag;
+ };
+
struct __sanitizer_ether_addr {
u8 octet[6];
};
@@ -242,7 +359,7 @@ namespace __sanitizer {
};
#endif
-#if SANITIZER_ANDROID || SANITIZER_MAC
+#if SANITIZER_ANDROID || SANITIZER_MAC || SANITIZER_FREEBSD
struct __sanitizer_msghdr {
void *msg_name;
unsigned msg_namelen;
@@ -281,6 +398,12 @@ namespace __sanitizer {
unsigned short d_reclen;
// more fields that we don't care about
};
+#elif SANITIZER_FREEBSD
+ struct __sanitizer_dirent {
+ unsigned int d_fileno;
+ unsigned short d_reclen;
+ // more fields that we don't care about
+ };
#elif SANITIZER_ANDROID || defined(__x86_64__)
struct __sanitizer_dirent {
unsigned long long d_ino;
@@ -306,13 +429,16 @@ namespace __sanitizer {
};
#endif
-#if defined(__x86_64__) && !defined(_LP64)
+// 'clock_t' is 32 bits wide on x64 FreeBSD
+#if SANITIZER_FREEBSD
+ typedef int __sanitizer_clock_t;
+#elif defined(__x86_64__) && !defined(_LP64)
typedef long long __sanitizer_clock_t;
#else
typedef long __sanitizer_clock_t;
#endif
-#if SANITIZER_LINUX
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
#if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__)
typedef unsigned __sanitizer___kernel_uid_t;
typedef unsigned __sanitizer___kernel_gid_t;
@@ -326,7 +452,7 @@ namespace __sanitizer {
typedef long __sanitizer___kernel_off_t;
#endif
-#if defined(__powerpc__)
+#if defined(__powerpc__) || defined(__aarch64__)
typedef unsigned int __sanitizer___kernel_old_uid_t;
typedef unsigned int __sanitizer___kernel_old_gid_t;
#else
@@ -357,28 +483,44 @@ namespace __sanitizer {
// The size is determined by looking at sizeof of real sigset_t on linux.
uptr val[128 / sizeof(uptr)];
};
+#elif SANITIZER_FREEBSD
+ struct __sanitizer_sigset_t {
+ // uint32_t * 4
+ unsigned int __bits[4];
+ };
#endif
+ // Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
struct __sanitizer_sigaction {
union {
- void (*sa_handler)(int sig);
- void (*sa_sigaction)(int sig, void *siginfo, void *uctx);
+ void (*sigaction)(int sig, void *siginfo, void *uctx);
+ void (*handler)(int sig);
};
+#if SANITIZER_FREEBSD
+ int sa_flags;
+ __sanitizer_sigset_t sa_mask;
+#else
__sanitizer_sigset_t sa_mask;
int sa_flags;
+#endif
#if SANITIZER_LINUX
void (*sa_restorer)();
#endif
};
+#if SANITIZER_FREEBSD
+ typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t;
+#else
struct __sanitizer_kernel_sigset_t {
u8 sig[8];
};
+#endif
+ // Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
struct __sanitizer_kernel_sigaction_t {
union {
- void (*sigaction)(int signo, void *info, void *ctx);
void (*handler)(int signo);
+ void (*sigaction)(int signo, void *info, void *ctx);
};
unsigned long sa_flags;
void (*sa_restorer)(void);
@@ -397,7 +539,7 @@ namespace __sanitizer {
extern int af_inet6;
uptr __sanitizer_in_addr_sz(int af);
-#if SANITIZER_LINUX
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
struct __sanitizer_dl_phdr_info {
uptr dlpi_addr;
const char *dlpi_name;
@@ -411,7 +553,7 @@ namespace __sanitizer {
int ai_family;
int ai_socktype;
int ai_protocol;
-#if SANITIZER_ANDROID || SANITIZER_MAC
+#if SANITIZER_ANDROID || SANITIZER_MAC || SANITIZER_FREEBSD
unsigned ai_addrlen;
char *ai_canonname;
void *ai_addr;
@@ -437,13 +579,14 @@ namespace __sanitizer {
short revents;
};
-#if SANITIZER_ANDROID || SANITIZER_MAC
+#if SANITIZER_ANDROID || SANITIZER_MAC || SANITIZER_FREEBSD
typedef unsigned __sanitizer_nfds_t;
#else
typedef unsigned long __sanitizer_nfds_t;
#endif
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#if !SANITIZER_ANDROID
+# if SANITIZER_LINUX
struct __sanitizer_glob_t {
uptr gl_pathc;
char **gl_pathv;
@@ -456,10 +599,27 @@ namespace __sanitizer {
int (*gl_lstat)(const char *, void *);
int (*gl_stat)(const char *, void *);
};
+# elif SANITIZER_FREEBSD
+ struct __sanitizer_glob_t {
+ uptr gl_pathc;
+ uptr gl_matchc;
+ uptr gl_offs;
+ int gl_flags;
+ char **gl_pathv;
+ int (*gl_errfunc)(const char*, int);
+ void (*gl_closedir)(void *dirp);
+ struct dirent *(*gl_readdir)(void *dirp);
+ void *(*gl_opendir)(const char*);
+ int (*gl_lstat)(const char*, void* /* struct stat* */);
+ int (*gl_stat)(const char*, void* /* struct stat* */);
+ };
+# endif // SANITIZER_FREEBSD
+# if SANITIZER_LINUX || SANITIZER_FREEBSD
extern int glob_nomatch;
extern int glob_altdirfunc;
-#endif
+# endif
+#endif // !SANITIZER_ANDROID
extern unsigned path_max;
@@ -467,10 +627,38 @@ namespace __sanitizer {
uptr we_wordc;
char **we_wordv;
uptr we_offs;
+#if SANITIZER_FREEBSD
+ char *we_strings;
+ uptr we_nbytes;
+#endif
};
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ struct __sanitizer_FILE {
+ int _flags;
+ char *_IO_read_ptr;
+ char *_IO_read_end;
+ char *_IO_read_base;
+ char *_IO_write_base;
+ char *_IO_write_ptr;
+ char *_IO_write_end;
+ char *_IO_buf_base;
+ char *_IO_buf_end;
+ char *_IO_save_base;
+ char *_IO_backup_base;
+ char *_IO_save_end;
+ void *_markers;
+ __sanitizer_FILE *_chain;
+ int _fileno;
+ };
+# define SANITIZER_HAS_STRUCT_FILE 1
+#else
+ typedef void __sanitizer_FILE;
+# define SANITIZER_HAS_STRUCT_FILE 0
+#endif
+
#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
- (defined(__i386) || defined (__x86_64)) // NOLINT
+ (defined(__i386) || defined(__x86_64))
extern unsigned struct_user_regs_struct_sz;
extern unsigned struct_user_fpregs_struct_sz;
extern unsigned struct_user_fpxregs_struct_sz;
@@ -490,7 +678,7 @@ namespace __sanitizer {
extern int ptrace_setregset;
#endif
-#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
extern unsigned struct_shminfo_sz;
extern unsigned struct_shm_info_sz;
extern int shmctl_ipc_stat;
@@ -499,6 +687,8 @@ namespace __sanitizer {
extern int shmctl_shm_stat;
#endif
+ extern int map_fixed;
+
// ioctl arguments
struct __sanitizer_ifconf {
int ifc_len;
@@ -511,7 +701,54 @@ namespace __sanitizer {
};
#endif
-#define IOC_SIZE(nr) (((nr) >> 16) & 0x3fff)
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+struct __sanitizer__obstack_chunk {
+ char *limit;
+ struct __sanitizer__obstack_chunk *prev;
+};
+
+struct __sanitizer_obstack {
+ long chunk_size;
+ struct __sanitizer__obstack_chunk *chunk;
+ char *object_base;
+ char *next_free;
+ uptr more_fields[7];
+};
+#endif
+
+#define IOC_NRBITS 8
+#define IOC_TYPEBITS 8
+#if defined(__powerpc__) || defined(__powerpc64__)
+#define IOC_SIZEBITS 13
+#define IOC_DIRBITS 3
+#define IOC_NONE 1U
+#define IOC_WRITE 4U
+#define IOC_READ 2U
+#else
+#define IOC_SIZEBITS 14
+#define IOC_DIRBITS 2
+#define IOC_NONE 0U
+#define IOC_WRITE 1U
+#define IOC_READ 2U
+#endif
+#define IOC_NRMASK ((1 << IOC_NRBITS) - 1)
+#define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1)
+#define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1)
+#if defined(IOC_DIRMASK)
+#undef IOC_DIRMASK
+#endif
+#define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1)
+#define IOC_NRSHIFT 0
+#define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS)
+#define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS)
+#define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS)
+#define EVIOC_EV_MAX 0x1f
+#define EVIOC_ABS_MAX 0x3f
+
+#define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
+#define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
+#define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
+#define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
extern unsigned struct_arpreq_sz;
extern unsigned struct_ifreq_sz;
@@ -527,9 +764,6 @@ namespace __sanitizer {
extern unsigned struct_cdrom_tocentry_sz;
extern unsigned struct_cdrom_tochdr_sz;
extern unsigned struct_cdrom_volctrl_sz;
- extern unsigned struct_copr_buffer_sz;
- extern unsigned struct_copr_debug_buf_sz;
- extern unsigned struct_copr_msg_sz;
extern unsigned struct_ff_effect_sz;
extern unsigned struct_floppy_drive_params_sz;
extern unsigned struct_floppy_drive_struct_sz;
@@ -543,23 +777,28 @@ namespace __sanitizer {
extern unsigned struct_hd_geometry_sz;
extern unsigned struct_input_absinfo_sz;
extern unsigned struct_input_id_sz;
+ extern unsigned struct_mtpos_sz;
+ extern unsigned struct_termio_sz;
+ extern unsigned struct_vt_consize_sz;
+ extern unsigned struct_vt_sizes_sz;
+ extern unsigned struct_vt_stat_sz;
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
+ extern unsigned struct_copr_buffer_sz;
+ extern unsigned struct_copr_debug_buf_sz;
+ extern unsigned struct_copr_msg_sz;
extern unsigned struct_midi_info_sz;
extern unsigned struct_mtget_sz;
extern unsigned struct_mtop_sz;
- extern unsigned struct_mtpos_sz;
extern unsigned struct_rtentry_sz;
extern unsigned struct_sbi_instrument_sz;
extern unsigned struct_seq_event_rec_sz;
extern unsigned struct_synth_info_sz;
- extern unsigned struct_termio_sz;
- extern unsigned struct_vt_consize_sz;
extern unsigned struct_vt_mode_sz;
- extern unsigned struct_vt_sizes_sz;
- extern unsigned struct_vt_stat_sz;
-#endif
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD
#if SANITIZER_LINUX && !SANITIZER_ANDROID
- extern unsigned struct_audio_buf_info_sz;
extern unsigned struct_ax25_parms_struct_sz;
extern unsigned struct_cyclades_monitor_sz;
extern unsigned struct_input_keymap_entry_sz;
@@ -570,7 +809,6 @@ namespace __sanitizer {
extern unsigned struct_kbsentry_sz;
extern unsigned struct_mtconfiginfo_sz;
extern unsigned struct_nr_parms_struct_sz;
- extern unsigned struct_ppp_stats_sz;
extern unsigned struct_scc_modem_sz;
extern unsigned struct_scc_stat_sz;
extern unsigned struct_serial_multiport_struct_sz;
@@ -578,7 +816,12 @@ namespace __sanitizer {
extern unsigned struct_sockaddr_ax25_sz;
extern unsigned struct_unimapdesc_sz;
extern unsigned struct_unimapinit_sz;
-#endif
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+
+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
+ extern unsigned struct_audio_buf_info_sz;
+ extern unsigned struct_ppp_stats_sz;
+#endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
#if !SANITIZER_ANDROID && !SANITIZER_MAC
extern unsigned struct_sioc_sg_req_sz;
@@ -635,7 +878,7 @@ namespace __sanitizer {
extern unsigned IOCTL_TIOCSPGRP;
extern unsigned IOCTL_TIOCSTI;
extern unsigned IOCTL_TIOCSWINSZ;
-#if (SANITIZER_LINUX && !SANITIZER_ANDROID)
+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
extern unsigned IOCTL_SIOCGETSGCNT;
extern unsigned IOCTL_SIOCGETVIFCNT;
#endif
@@ -729,9 +972,7 @@ namespace __sanitizer {
extern unsigned IOCTL_HDIO_SET_MULTCOUNT;
extern unsigned IOCTL_HDIO_SET_NOWERR;
extern unsigned IOCTL_HDIO_SET_UNMASKINTR;
- extern unsigned IOCTL_MTIOCGET;
extern unsigned IOCTL_MTIOCPOS;
- extern unsigned IOCTL_MTIOCTOP;
extern unsigned IOCTL_PPPIOCGASYNCMAP;
extern unsigned IOCTL_PPPIOCGDEBUG;
extern unsigned IOCTL_PPPIOCGFLAGS;
@@ -743,9 +984,7 @@ namespace __sanitizer {
extern unsigned IOCTL_PPPIOCSMAXCID;
extern unsigned IOCTL_PPPIOCSMRU;
extern unsigned IOCTL_PPPIOCSXASYNCMAP;
- extern unsigned IOCTL_SIOCADDRT;
extern unsigned IOCTL_SIOCDARP;
- extern unsigned IOCTL_SIOCDELRT;
extern unsigned IOCTL_SIOCDRARP;
extern unsigned IOCTL_SIOCGARP;
extern unsigned IOCTL_SIOCGIFENCAP;
@@ -774,6 +1013,39 @@ namespace __sanitizer {
extern unsigned IOCTL_SNDCTL_COPR_SENDMSG;
extern unsigned IOCTL_SNDCTL_COPR_WCODE;
extern unsigned IOCTL_SNDCTL_COPR_WDATA;
+ extern unsigned IOCTL_TCFLSH;
+ extern unsigned IOCTL_TCGETA;
+ extern unsigned IOCTL_TCGETS;
+ extern unsigned IOCTL_TCSBRK;
+ extern unsigned IOCTL_TCSBRKP;
+ extern unsigned IOCTL_TCSETA;
+ extern unsigned IOCTL_TCSETAF;
+ extern unsigned IOCTL_TCSETAW;
+ extern unsigned IOCTL_TCSETS;
+ extern unsigned IOCTL_TCSETSF;
+ extern unsigned IOCTL_TCSETSW;
+ extern unsigned IOCTL_TCXONC;
+ extern unsigned IOCTL_TIOCGLCKTRMIOS;
+ extern unsigned IOCTL_TIOCGSOFTCAR;
+ extern unsigned IOCTL_TIOCINQ;
+ extern unsigned IOCTL_TIOCLINUX;
+ extern unsigned IOCTL_TIOCSERCONFIG;
+ extern unsigned IOCTL_TIOCSERGETLSR;
+ extern unsigned IOCTL_TIOCSERGWILD;
+ extern unsigned IOCTL_TIOCSERSWILD;
+ extern unsigned IOCTL_TIOCSLCKTRMIOS;
+ extern unsigned IOCTL_TIOCSSOFTCAR;
+ extern unsigned IOCTL_VT_DISALLOCATE;
+ extern unsigned IOCTL_VT_GETSTATE;
+ extern unsigned IOCTL_VT_RESIZE;
+ extern unsigned IOCTL_VT_RESIZEX;
+ extern unsigned IOCTL_VT_SENDSIG;
+#endif // SANITIZER_LINUX
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
+ extern unsigned IOCTL_MTIOCGET;
+ extern unsigned IOCTL_MTIOCTOP;
+ extern unsigned IOCTL_SIOCADDRT;
+ extern unsigned IOCTL_SIOCDELRT;
extern unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE;
extern unsigned IOCTL_SNDCTL_DSP_GETFMTS;
extern unsigned IOCTL_SNDCTL_DSP_NONBLOCK;
@@ -864,40 +1136,14 @@ namespace __sanitizer {
extern unsigned IOCTL_SOUND_PCM_READ_RATE;
extern unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS;
extern unsigned IOCTL_SOUND_PCM_WRITE_FILTER;
- extern unsigned IOCTL_TCFLSH;
- extern unsigned IOCTL_TCGETA;
- extern unsigned IOCTL_TCGETS;
- extern unsigned IOCTL_TCSBRK;
- extern unsigned IOCTL_TCSBRKP;
- extern unsigned IOCTL_TCSETA;
- extern unsigned IOCTL_TCSETAF;
- extern unsigned IOCTL_TCSETAW;
- extern unsigned IOCTL_TCSETS;
- extern unsigned IOCTL_TCSETSF;
- extern unsigned IOCTL_TCSETSW;
- extern unsigned IOCTL_TCXONC;
- extern unsigned IOCTL_TIOCGLCKTRMIOS;
- extern unsigned IOCTL_TIOCGSOFTCAR;
- extern unsigned IOCTL_TIOCINQ;
- extern unsigned IOCTL_TIOCLINUX;
- extern unsigned IOCTL_TIOCSERCONFIG;
- extern unsigned IOCTL_TIOCSERGETLSR;
- extern unsigned IOCTL_TIOCSERGWILD;
- extern unsigned IOCTL_TIOCSERSWILD;
- extern unsigned IOCTL_TIOCSLCKTRMIOS;
- extern unsigned IOCTL_TIOCSSOFTCAR;
extern unsigned IOCTL_VT_ACTIVATE;
- extern unsigned IOCTL_VT_DISALLOCATE;
extern unsigned IOCTL_VT_GETMODE;
- extern unsigned IOCTL_VT_GETSTATE;
extern unsigned IOCTL_VT_OPENQRY;
extern unsigned IOCTL_VT_RELDISP;
- extern unsigned IOCTL_VT_RESIZE;
- extern unsigned IOCTL_VT_RESIZEX;
- extern unsigned IOCTL_VT_SENDSIG;
extern unsigned IOCTL_VT_SETMODE;
extern unsigned IOCTL_VT_WAITACTIVE;
-#endif
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD
+
#if SANITIZER_LINUX && !SANITIZER_ANDROID
extern unsigned IOCTL_CYGETDEFTHRESH;
extern unsigned IOCTL_CYGETDEFTIMEOUT;
@@ -923,37 +1169,25 @@ namespace __sanitizer {
extern unsigned IOCTL_FS_IOC_SETVERSION;
extern unsigned IOCTL_GIO_CMAP;
extern unsigned IOCTL_GIO_FONT;
- extern unsigned IOCTL_GIO_SCRNMAP;
extern unsigned IOCTL_GIO_UNIMAP;
extern unsigned IOCTL_GIO_UNISCRNMAP;
extern unsigned IOCTL_KDADDIO;
extern unsigned IOCTL_KDDELIO;
- extern unsigned IOCTL_KDDISABIO;
- extern unsigned IOCTL_KDENABIO;
extern unsigned IOCTL_KDGETKEYCODE;
- extern unsigned IOCTL_KDGETLED;
- extern unsigned IOCTL_KDGETMODE;
extern unsigned IOCTL_KDGKBDIACR;
extern unsigned IOCTL_KDGKBENT;
extern unsigned IOCTL_KDGKBLED;
extern unsigned IOCTL_KDGKBMETA;
- extern unsigned IOCTL_KDGKBMODE;
extern unsigned IOCTL_KDGKBSENT;
- extern unsigned IOCTL_KDGKBTYPE;
extern unsigned IOCTL_KDMAPDISP;
- extern unsigned IOCTL_KDMKTONE;
extern unsigned IOCTL_KDSETKEYCODE;
- extern unsigned IOCTL_KDSETLED;
- extern unsigned IOCTL_KDSETMODE;
extern unsigned IOCTL_KDSIGACCEPT;
extern unsigned IOCTL_KDSKBDIACR;
extern unsigned IOCTL_KDSKBENT;
extern unsigned IOCTL_KDSKBLED;
extern unsigned IOCTL_KDSKBMETA;
- extern unsigned IOCTL_KDSKBMODE;
extern unsigned IOCTL_KDSKBSENT;
extern unsigned IOCTL_KDUNMAPDISP;
- extern unsigned IOCTL_KIOCSOUND;
extern unsigned IOCTL_LPABORT;
extern unsigned IOCTL_LPABORTOPEN;
extern unsigned IOCTL_LPCAREFUL;
@@ -968,7 +1202,6 @@ namespace __sanitizer {
extern unsigned IOCTL_MTIOCSETCONFIG;
extern unsigned IOCTL_PIO_CMAP;
extern unsigned IOCTL_PIO_FONT;
- extern unsigned IOCTL_PIO_SCRNMAP;
extern unsigned IOCTL_PIO_UNIMAP;
extern unsigned IOCTL_PIO_UNIMAPCLR;
extern unsigned IOCTL_PIO_UNISCRNMAP;
@@ -996,9 +1229,29 @@ namespace __sanitizer {
extern unsigned IOCTL_TIOCSERGETMULTI;
extern unsigned IOCTL_TIOCSERSETMULTI;
extern unsigned IOCTL_TIOCSSERIAL;
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+
+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
+ extern unsigned IOCTL_GIO_SCRNMAP;
+ extern unsigned IOCTL_KDDISABIO;
+ extern unsigned IOCTL_KDENABIO;
+ extern unsigned IOCTL_KDGETLED;
+ extern unsigned IOCTL_KDGETMODE;
+ extern unsigned IOCTL_KDGKBMODE;
+ extern unsigned IOCTL_KDGKBTYPE;
+ extern unsigned IOCTL_KDMKTONE;
+ extern unsigned IOCTL_KDSETLED;
+ extern unsigned IOCTL_KDSETMODE;
+ extern unsigned IOCTL_KDSKBMODE;
+ extern unsigned IOCTL_KIOCSOUND;
+ extern unsigned IOCTL_PIO_SCRNMAP;
#endif
+ extern const int errno_EINVAL;
extern const int errno_EOWNERDEAD;
+
+ extern const int si_SEGV_MAPERR;
+ extern const int si_SEGV_ACCERR;
} // namespace __sanitizer
#define CHECK_TYPE_SIZE(TYPE) \
diff --git a/libsanitizer/sanitizer_common/sanitizer_posix.cc b/libsanitizer/sanitizer_common/sanitizer_posix.cc
index ef5cb0b03b8..e24d5ed5031 100644
--- a/libsanitizer/sanitizer_common/sanitizer_posix.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_posix.cc
@@ -11,7 +11,7 @@
//===----------------------------------------------------------------------===//
#include "sanitizer_platform.h"
-#if SANITIZER_LINUX || SANITIZER_MAC
+#if SANITIZER_POSIX
#include "sanitizer_common.h"
#include "sanitizer_libc.h"
@@ -20,6 +20,14 @@
#include <sys/mman.h>
+#if SANITIZER_LINUX
+#include <sys/utsname.h>
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#include <sys/personality.h>
+#endif
+
namespace __sanitizer {
// ------------- sanitizer_common.h
@@ -27,21 +35,65 @@ uptr GetMmapGranularity() {
return GetPageSize();
}
+#if SANITIZER_WORDSIZE == 32
+// Take care of unusable kernel area in top gigabyte.
+static uptr GetKernelAreaSize() {
+#if SANITIZER_LINUX
+ const uptr gbyte = 1UL << 30;
+
+ // Firstly check if there are writable segments
+ // mapped to top gigabyte (e.g. stack).
+ MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+ uptr end, prot;
+ while (proc_maps.Next(/*start*/0, &end,
+ /*offset*/0, /*filename*/0,
+ /*filename_size*/0, &prot)) {
+ if ((end >= 3 * gbyte)
+ && (prot & MemoryMappingLayout::kProtectionWrite) != 0)
+ return 0;
+ }
+
+#if !SANITIZER_ANDROID
+ // Even if nothing is mapped, top Gb may still be accessible
+ // if we are running on 64-bit kernel.
+ // Uname may report misleading results if personality type
+ // is modified (e.g. under schroot) so check this as well.
+ struct utsname uname_info;
+ int pers = personality(0xffffffffUL);
+ if (!(pers & PER_MASK)
+ && uname(&uname_info) == 0
+ && internal_strstr(uname_info.machine, "64"))
+ return 0;
+#endif // SANITIZER_ANDROID
+
+ // Top gigabyte is reserved for kernel.
+ return gbyte;
+#else
+ return 0;
+#endif // SANITIZER_LINUX
+}
+#endif // SANITIZER_WORDSIZE == 32
+
uptr GetMaxVirtualAddress() {
#if SANITIZER_WORDSIZE == 64
# if defined(__powerpc64__)
// On PowerPC64 we have two different address space layouts: 44- and 46-bit.
- // We somehow need to figure our which one we are using now and choose
+ // We somehow need to figure out which one we are using now and choose
// one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.
// Note that with 'ulimit -s unlimited' the stack is moved away from the top
// of the address space, so simply checking the stack address is not enough.
return (1ULL << 44) - 1; // 0x00000fffffffffffUL
+# elif defined(__aarch64__)
+ return (1ULL << 39) - 1;
# else
return (1ULL << 47) - 1; // 0x00007fffffffffffUL;
# endif
#else // SANITIZER_WORDSIZE == 32
- // FIXME: We can probably lower this on Android?
- return (1ULL << 32) - 1; // 0xffffffff;
+ uptr res = (1ULL << 32) - 1; // 0xffffffff;
+ if (!common_flags()->full_address_space)
+ res -= GetKernelAreaSize();
+ CHECK_LT(reinterpret_cast<uptr>(&res), res);
+ return res;
#endif // SANITIZER_WORDSIZE
}
@@ -60,11 +112,13 @@ void *MmapOrDie(uptr size, const char *mem_type) {
Die();
}
recursion_count++;
- Report("ERROR: %s failed to allocate 0x%zx (%zd) bytes of %s: %d\n",
+ Report("ERROR: %s failed to "
+ "allocate 0x%zx (%zd) bytes of %s (errno: %d)\n",
SanitizerToolName, size, size, mem_type, reserrno);
DumpProcessMap();
CHECK("unable to mmap" && 0);
}
+ IncreaseTotalMmap(size);
return (void *)res;
}
@@ -76,6 +130,25 @@ void UnmapOrDie(void *addr, uptr size) {
SanitizerToolName, size, size, addr);
CHECK("unable to unmap" && 0);
}
+ DecreaseTotalMmap(size);
+}
+
+void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
+ uptr PageSize = GetPageSizeCached();
+ uptr p = internal_mmap(0,
+ RoundUpTo(size, PageSize),
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
+ -1, 0);
+ int reserrno;
+ if (internal_iserror(p, &reserrno)) {
+ Report("ERROR: %s failed to "
+ "allocate noreserve 0x%zx (%zd) bytes for '%s' (errno: %d)\n",
+ SanitizerToolName, size, size, mem_type, reserrno);
+ CHECK("unable to mmap" && 0);
+ }
+ IncreaseTotalMmap(size);
+ return (void *)p;
}
void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
@@ -87,9 +160,10 @@ void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
-1, 0);
int reserrno;
if (internal_iserror(p, &reserrno))
- Report("ERROR: "
- "%s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n",
+ Report("ERROR: %s failed to "
+ "allocate 0x%zx (%zd) bytes at address %zx (errno: %d)\n",
SanitizerToolName, size, size, fixed_addr, reserrno);
+ IncreaseTotalMmap(size);
return (void *)p;
}
@@ -102,11 +176,12 @@ void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
-1, 0);
int reserrno;
if (internal_iserror(p, &reserrno)) {
- Report("ERROR:"
- " %s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n",
+ Report("ERROR: %s failed to "
+ "allocate 0x%zx (%zd) bytes at address %zx (errno: %d)\n",
SanitizerToolName, size, size, fixed_addr, reserrno);
CHECK("unable to mmap" && 0);
}
+ IncreaseTotalMmap(size);
return (void *)p;
}
@@ -157,7 +232,7 @@ void DumpProcessMap() {
MemoryMappingLayout proc_maps(/*cache_enabled*/true);
uptr start, end;
const sptr kBufSize = 4095;
- char *filename = (char*)MmapOrDie(kBufSize, __FUNCTION__);
+ char *filename = (char*)MmapOrDie(kBufSize, __func__);
Report("Process memory map follows:\n");
while (proc_maps.Next(&start, &end, /* file_offset */0,
filename, kBufSize, /* protection */0)) {
@@ -204,7 +279,7 @@ void MaybeOpenReportFile() {
if (report_fd_pid == pid) return;
InternalScopedBuffer<char> report_path_full(4096);
internal_snprintf(report_path_full.data(), report_path_full.size(),
- "%s.%d", report_path_prefix, pid);
+ "%s.%zu", report_path_prefix, pid);
uptr openrv = OpenFile(report_path_full.data(), true);
if (internal_iserror(openrv)) {
report_fd = kStderrFd;
@@ -248,4 +323,4 @@ bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end) {
} // namespace __sanitizer
-#endif // SANITIZER_LINUX || SANITIZER_MAC
+#endif // SANITIZER_POSIX
diff --git a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cc
index ae782ac39cb..8e3a96f01e4 100644
--- a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cc
@@ -12,12 +12,15 @@
#include "sanitizer_platform.h"
-#if SANITIZER_LINUX || SANITIZER_MAC
+#if SANITIZER_POSIX
#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_platform_limits_posix.h"
#include "sanitizer_stacktrace.h"
#include <errno.h>
#include <pthread.h>
+#include <signal.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/resource.h>
@@ -49,7 +52,7 @@ void DisableCoreDumper() {
bool StackSizeIsUnlimited() {
struct rlimit rlim;
CHECK_EQ(0, getrlimit(RLIMIT_STACK, &rlim));
- return (rlim.rlim_cur == (uptr)-1);
+ return ((uptr)rlim.rlim_cur == (uptr)-1);
}
void SetStackSizeLimitInBytes(uptr limit) {
@@ -87,6 +90,59 @@ int internal_isatty(fd_t fd) {
return isatty(fd);
}
+#ifndef SANITIZER_GO
+// TODO(glider): different tools may require different altstack size.
+static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough.
+
+void SetAlternateSignalStack() {
+ stack_t altstack, oldstack;
+ CHECK_EQ(0, sigaltstack(0, &oldstack));
+ // If the alternate stack is already in place, do nothing.
+ // Android always sets an alternate stack, but it's too small for us.
+ if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) return;
+ // TODO(glider): the mapped stack should have the MAP_STACK flag in the
+ // future. It is not required by man 2 sigaltstack now (they're using
+ // malloc()).
+ void* base = MmapOrDie(kAltStackSize, __func__);
+ altstack.ss_sp = (char*) base;
+ altstack.ss_flags = 0;
+ altstack.ss_size = kAltStackSize;
+ CHECK_EQ(0, sigaltstack(&altstack, 0));
+}
+
+void UnsetAlternateSignalStack() {
+ stack_t altstack, oldstack;
+ altstack.ss_sp = 0;
+ altstack.ss_flags = SS_DISABLE;
+ altstack.ss_size = kAltStackSize; // Some sane value required on Darwin.
+ CHECK_EQ(0, sigaltstack(&altstack, &oldstack));
+ UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
+}
+
+typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
+static void MaybeInstallSigaction(int signum,
+ SignalHandlerType handler) {
+ if (!IsDeadlySignal(signum))
+ return;
+ struct sigaction sigact;
+ internal_memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_sigaction = (sa_sigaction_t)handler;
+ sigact.sa_flags = SA_SIGINFO;
+ if (common_flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;
+ CHECK_EQ(0, internal_sigaction(signum, &sigact, 0));
+ VReport(1, "Installed the sigaction for signal %d\n", signum);
+}
+
+void InstallDeadlySignalHandlers(SignalHandlerType handler) {
+ // Set the alternate signal stack for the main thread.
+ // This will cause SetAlternateSignalStack to be called twice, but the stack
+ // will be actually set only once.
+ if (common_flags()->use_sigaltstack) SetAlternateSignalStack();
+ MaybeInstallSigaction(SIGSEGV, handler);
+ MaybeInstallSigaction(SIGBUS, handler);
+}
+#endif // SANITIZER_GO
+
} // namespace __sanitizer
-#endif
+#endif // SANITIZER_POSIX
diff --git a/libsanitizer/sanitizer_common/sanitizer_printf.cc b/libsanitizer/sanitizer_common/sanitizer_printf.cc
index 08951c7e247..4fc26308ee4 100644
--- a/libsanitizer/sanitizer_common/sanitizer_printf.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_printf.cc
@@ -14,6 +14,7 @@
#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
#include "sanitizer_libc.h"
#include <stdio.h>
@@ -92,11 +93,14 @@ static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num,
minimal_num_length, pad_with_zero, negative);
}
-static int AppendString(char **buff, const char *buff_end, const char *s) {
+static int AppendString(char **buff, const char *buff_end, int precision,
+ const char *s) {
if (s == 0)
s = "<null>";
int result = 0;
for (; *s; s++) {
+ if (precision >= 0 && result >= precision)
+ break;
result += AppendChar(buff, buff_end, *s);
}
return result;
@@ -104,7 +108,7 @@ static int AppendString(char **buff, const char *buff_end, const char *s) {
static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) {
int result = 0;
- result += AppendString(buff, buff_end, "0x");
+ result += AppendString(buff, buff_end, -1, "0x");
result += AppendUnsigned(buff, buff_end, ptr_value, 16,
(SANITIZER_WORDSIZE == 64) ? 12 : 8, true);
return result;
@@ -113,7 +117,7 @@ static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) {
int VSNPrintf(char *buff, int buff_length,
const char *format, va_list args) {
static const char *kPrintfFormatsHelp =
- "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x}; %p; %s; %c\n";
+ "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x}; %p; %(\\.\\*)?s; %c\n";
RAW_CHECK(format);
RAW_CHECK(buff_length > 0);
const char *buff_end = &buff[buff_length - 1];
@@ -133,6 +137,12 @@ int VSNPrintf(char *buff, int buff_length,
width = width * 10 + *cur++ - '0';
}
}
+ bool have_precision = (cur[0] == '.' && cur[1] == '*');
+ int precision = -1;
+ if (have_precision) {
+ cur += 2;
+ precision = va_arg(args, int);
+ }
bool have_z = (*cur == 'z');
cur += have_z;
bool have_ll = !have_z && (cur[0] == 'l' && cur[1] == 'l');
@@ -140,6 +150,8 @@ int VSNPrintf(char *buff, int buff_length,
s64 dval;
u64 uval;
bool have_flags = have_width | have_z | have_ll;
+ // Only %s supports precision for now
+ CHECK(!(precision >= 0 && *cur != 's'));
switch (*cur) {
case 'd': {
dval = have_ll ? va_arg(args, s64)
@@ -165,7 +177,7 @@ int VSNPrintf(char *buff, int buff_length,
}
case 's': {
RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
- result += AppendString(&buff, buff_end, va_arg(args, char*));
+ result += AppendString(&buff, buff_end, precision, va_arg(args, char*));
break;
}
case 'c': {
@@ -258,6 +270,7 @@ static void SharedPrintfCode(bool append_pid, const char *format,
break;
}
RawWrite(buffer);
+ AndroidLogWrite(buffer);
CallPrintfAndReportCallback(buffer);
// If we had mapped any memory, clean up.
if (buffer != local_buffer)
@@ -265,6 +278,7 @@ static void SharedPrintfCode(bool append_pid, const char *format,
va_end(args2);
}
+FORMAT(1, 2)
void Printf(const char *format, ...) {
va_list args;
va_start(args, format);
@@ -273,6 +287,7 @@ void Printf(const char *format, ...) {
}
// Like Printf, but prints the current PID before the output string.
+FORMAT(1, 2)
void Report(const char *format, ...) {
va_list args;
va_start(args, format);
@@ -284,6 +299,7 @@ void Report(const char *format, ...) {
// Returns the number of symbols that should have been written to buffer
// (not including trailing '\0'). Thus, the string is truncated
// iff return value is not less than "length".
+FORMAT(3, 4)
int internal_snprintf(char *buffer, uptr length, const char *format, ...) {
va_list args;
va_start(args, format);
@@ -292,6 +308,7 @@ int internal_snprintf(char *buffer, uptr length, const char *format, ...) {
return needed_length;
}
+FORMAT(2, 3)
void InternalScopedString::append(const char *format, ...) {
CHECK_LT(length_, size());
va_list args;
@@ -299,6 +316,7 @@ void InternalScopedString::append(const char *format, ...) {
VSNPrintf(data() + length_, size() - length_, format, args);
va_end(args);
length_ += internal_strlen(data() + length_);
+ CHECK_LT(length_, size());
}
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_procmaps.h b/libsanitizer/sanitizer_common/sanitizer_procmaps.h
index 87887f6b74b..d140c47fda9 100644
--- a/libsanitizer/sanitizer_common/sanitizer_procmaps.h
+++ b/libsanitizer/sanitizer_common/sanitizer_procmaps.h
@@ -12,49 +12,35 @@
#ifndef SANITIZER_PROCMAPS_H
#define SANITIZER_PROCMAPS_H
+#include "sanitizer_common.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_mutex.h"
namespace __sanitizer {
-#if SANITIZER_WINDOWS
-class MemoryMappingLayout {
- public:
- explicit MemoryMappingLayout(bool cache_enabled) {
- (void)cache_enabled;
- }
- bool GetObjectNameAndOffset(uptr addr, uptr *offset,
- char filename[], uptr filename_size,
- uptr *protection) {
- UNIMPLEMENTED();
- }
-};
-
-#else // SANITIZER_WINDOWS
-#if SANITIZER_LINUX
+#if SANITIZER_FREEBSD || SANITIZER_LINUX
struct ProcSelfMapsBuff {
char *data;
uptr mmaped_size;
uptr len;
};
-#endif // SANITIZER_LINUX
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
class MemoryMappingLayout {
public:
explicit MemoryMappingLayout(bool cache_enabled);
+ ~MemoryMappingLayout();
bool Next(uptr *start, uptr *end, uptr *offset,
char filename[], uptr filename_size, uptr *protection);
void Reset();
- // Gets the object file name and the offset in that object for a given
- // address 'addr'. Returns true on success.
- bool GetObjectNameAndOffset(uptr addr, uptr *offset,
- char filename[], uptr filename_size,
- uptr *protection);
// In some cases, e.g. when running under a sandbox on Linux, ASan is unable
// to obtain the memory mappings. It should fall back to pre-cached data
// instead of aborting.
static void CacheMemoryMappings();
- ~MemoryMappingLayout();
+
+ // Stores the list of mapped objects into an array.
+ uptr DumpListOfModules(LoadedModule *modules, uptr max_modules,
+ string_predicate_t filter);
// Memory protection masks.
static const uptr kProtectionRead = 1;
@@ -64,39 +50,10 @@ class MemoryMappingLayout {
private:
void LoadFromCache();
- // Default implementation of GetObjectNameAndOffset.
- // Quite slow, because it iterates through the whole process map for each
- // lookup.
- bool IterateForObjectNameAndOffset(uptr addr, uptr *offset,
- char filename[], uptr filename_size,
- uptr *protection) {
- Reset();
- uptr start, end, file_offset;
- for (int i = 0; Next(&start, &end, &file_offset, filename, filename_size,
- protection);
- i++) {
- if (addr >= start && addr < end) {
- // Don't subtract 'start' for the first entry:
- // * If a binary is compiled w/o -pie, then the first entry in
- // process maps is likely the binary itself (all dynamic libs
- // are mapped higher in address space). For such a binary,
- // instruction offset in binary coincides with the actual
- // instruction address in virtual memory (as code section
- // is mapped to a fixed memory range).
- // * If a binary is compiled with -pie, all the modules are
- // mapped high at address space (in particular, higher than
- // shadow memory of the tool), so the module can't be the
- // first entry.
- *offset = (addr - (i ? start : 0)) + file_offset;
- return true;
- }
- }
- if (filename_size)
- filename[0] = '\0';
- return false;
- }
-# if SANITIZER_LINUX
+ // FIXME: Hide implementation details for different platforms in
+ // platform-specific files.
+# if SANITIZER_FREEBSD || SANITIZER_LINUX
ProcSelfMapsBuff proc_self_maps_;
char *current_;
@@ -127,8 +84,6 @@ void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size);
// Returns code range for the specified module.
bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end);
-#endif // SANITIZER_WINDOWS
-
} // namespace __sanitizer
#endif // SANITIZER_PROCMAPS_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_procmaps_linux.cc b/libsanitizer/sanitizer_common/sanitizer_procmaps_linux.cc
new file mode 100644
index 00000000000..20a074a799f
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_procmaps_linux.cc
@@ -0,0 +1,302 @@
+//===-- sanitizer_procmaps_linux.cc ---------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Information about the process mappings (Linux-specific parts).
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_FREEBSD || SANITIZER_LINUX
+#include "sanitizer_common.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_procmaps.h"
+
+#if SANITIZER_FREEBSD
+#include <unistd.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#endif
+
+namespace __sanitizer {
+
+// Linker initialized.
+ProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_;
+StaticSpinMutex MemoryMappingLayout::cache_lock_; // Linker initialized.
+
+static void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
+#if SANITIZER_FREEBSD
+ const int Mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid() };
+ size_t Size = 0;
+ int Err = sysctl(Mib, 4, NULL, &Size, NULL, 0);
+ CHECK_EQ(Err, 0);
+ CHECK_GT(Size, 0);
+
+ size_t MmapedSize = Size * 4 / 3;
+ void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()");
+ Size = MmapedSize;
+ Err = sysctl(Mib, 4, VmMap, &Size, NULL, 0);
+ CHECK_EQ(Err, 0);
+
+ proc_maps->data = (char*)VmMap;
+ proc_maps->mmaped_size = MmapedSize;
+ proc_maps->len = Size;
+#else
+ proc_maps->len = ReadFileToBuffer("/proc/self/maps", &proc_maps->data,
+ &proc_maps->mmaped_size, 1 << 26);
+#endif
+}
+
+MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
+ ReadProcMaps(&proc_self_maps_);
+ if (cache_enabled) {
+ if (proc_self_maps_.mmaped_size == 0) {
+ LoadFromCache();
+ CHECK_GT(proc_self_maps_.len, 0);
+ }
+ } else {
+ CHECK_GT(proc_self_maps_.mmaped_size, 0);
+ }
+ Reset();
+ // FIXME: in the future we may want to cache the mappings on demand only.
+ if (cache_enabled)
+ CacheMemoryMappings();
+}
+
+MemoryMappingLayout::~MemoryMappingLayout() {
+ // Only unmap the buffer if it is different from the cached one. Otherwise
+ // it will be unmapped when the cache is refreshed.
+ if (proc_self_maps_.data != cached_proc_self_maps_.data) {
+ UnmapOrDie(proc_self_maps_.data, proc_self_maps_.mmaped_size);
+ }
+}
+
+void MemoryMappingLayout::Reset() {
+ current_ = proc_self_maps_.data;
+}
+
+// static
+void MemoryMappingLayout::CacheMemoryMappings() {
+ SpinMutexLock l(&cache_lock_);
+ // Don't invalidate the cache if the mappings are unavailable.
+ ProcSelfMapsBuff old_proc_self_maps;
+ old_proc_self_maps = cached_proc_self_maps_;
+ ReadProcMaps(&cached_proc_self_maps_);
+ if (cached_proc_self_maps_.mmaped_size == 0) {
+ cached_proc_self_maps_ = old_proc_self_maps;
+ } else {
+ if (old_proc_self_maps.mmaped_size) {
+ UnmapOrDie(old_proc_self_maps.data,
+ old_proc_self_maps.mmaped_size);
+ }
+ }
+}
+
+void MemoryMappingLayout::LoadFromCache() {
+ SpinMutexLock l(&cache_lock_);
+ if (cached_proc_self_maps_.data) {
+ proc_self_maps_ = cached_proc_self_maps_;
+ }
+}
+
+#if !SANITIZER_FREEBSD
+// Parse a hex value in str and update str.
+static uptr ParseHex(char **str) {
+ uptr x = 0;
+ char *s;
+ for (s = *str; ; s++) {
+ char c = *s;
+ uptr v = 0;
+ if (c >= '0' && c <= '9')
+ v = c - '0';
+ else if (c >= 'a' && c <= 'f')
+ v = c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ v = c - 'A' + 10;
+ else
+ break;
+ x = x * 16 + v;
+ }
+ *str = s;
+ return x;
+}
+
+static bool IsOneOf(char c, char c1, char c2) {
+ return c == c1 || c == c2;
+}
+#endif
+
+static bool IsDecimal(char c) {
+ return c >= '0' && c <= '9';
+}
+
+static bool IsHex(char c) {
+ return (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'f');
+}
+
+static uptr ReadHex(const char *p) {
+ uptr v = 0;
+ for (; IsHex(p[0]); p++) {
+ if (p[0] >= '0' && p[0] <= '9')
+ v = v * 16 + p[0] - '0';
+ else
+ v = v * 16 + p[0] - 'a' + 10;
+ }
+ return v;
+}
+
+static uptr ReadDecimal(const char *p) {
+ uptr v = 0;
+ for (; IsDecimal(p[0]); p++)
+ v = v * 10 + p[0] - '0';
+ return v;
+}
+
+bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
+ char filename[], uptr filename_size,
+ uptr *protection) {
+ char *last = proc_self_maps_.data + proc_self_maps_.len;
+ if (current_ >= last) return false;
+ uptr dummy;
+ if (!start) start = &dummy;
+ if (!end) end = &dummy;
+ if (!offset) offset = &dummy;
+ if (!protection) protection = &dummy;
+#if SANITIZER_FREEBSD
+ struct kinfo_vmentry *VmEntry = (struct kinfo_vmentry*)current_;
+
+ *start = (uptr)VmEntry->kve_start;
+ *end = (uptr)VmEntry->kve_end;
+ *offset = (uptr)VmEntry->kve_offset;
+
+ *protection = 0;
+ if ((VmEntry->kve_protection & KVME_PROT_READ) != 0)
+ *protection |= kProtectionRead;
+ if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0)
+ *protection |= kProtectionWrite;
+ if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0)
+ *protection |= kProtectionExecute;
+
+ if (filename != NULL && filename_size > 0) {
+ internal_snprintf(filename,
+ Min(filename_size, (uptr)PATH_MAX),
+ "%s", VmEntry->kve_path);
+ }
+
+ current_ += VmEntry->kve_structsize;
+#else // !SANITIZER_FREEBSD
+ char *next_line = (char*)internal_memchr(current_, '\n', last - current_);
+ if (next_line == 0)
+ next_line = last;
+ // Example: 08048000-08056000 r-xp 00000000 03:0c 64593 /foo/bar
+ *start = ParseHex(&current_);
+ CHECK_EQ(*current_++, '-');
+ *end = ParseHex(&current_);
+ CHECK_EQ(*current_++, ' ');
+ CHECK(IsOneOf(*current_, '-', 'r'));
+ *protection = 0;
+ if (*current_++ == 'r')
+ *protection |= kProtectionRead;
+ CHECK(IsOneOf(*current_, '-', 'w'));
+ if (*current_++ == 'w')
+ *protection |= kProtectionWrite;
+ CHECK(IsOneOf(*current_, '-', 'x'));
+ if (*current_++ == 'x')
+ *protection |= kProtectionExecute;
+ CHECK(IsOneOf(*current_, 's', 'p'));
+ if (*current_++ == 's')
+ *protection |= kProtectionShared;
+ CHECK_EQ(*current_++, ' ');
+ *offset = ParseHex(&current_);
+ CHECK_EQ(*current_++, ' ');
+ ParseHex(&current_);
+ CHECK_EQ(*current_++, ':');
+ ParseHex(&current_);
+ CHECK_EQ(*current_++, ' ');
+ while (IsDecimal(*current_))
+ current_++;
+ // Qemu may lack the trailing space.
+ // http://code.google.com/p/address-sanitizer/issues/detail?id=160
+ // CHECK_EQ(*current_++, ' ');
+ // Skip spaces.
+ while (current_ < next_line && *current_ == ' ')
+ current_++;
+ // Fill in the filename.
+ uptr i = 0;
+ while (current_ < next_line) {
+ if (filename && i < filename_size - 1)
+ filename[i++] = *current_;
+ current_++;
+ }
+ if (filename && i < filename_size)
+ filename[i] = 0;
+ current_ = next_line + 1;
+#endif // !SANITIZER_FREEBSD
+ return true;
+}
+
+uptr MemoryMappingLayout::DumpListOfModules(LoadedModule *modules,
+ uptr max_modules,
+ string_predicate_t filter) {
+ Reset();
+ uptr cur_beg, cur_end, cur_offset;
+ InternalScopedBuffer<char> module_name(kMaxPathLength);
+ uptr n_modules = 0;
+ for (uptr i = 0; n_modules < max_modules &&
+ Next(&cur_beg, &cur_end, &cur_offset, module_name.data(),
+ module_name.size(), 0);
+ i++) {
+ const char *cur_name = module_name.data();
+ if (cur_name[0] == '\0')
+ continue;
+ if (filter && !filter(cur_name))
+ continue;
+ void *mem = &modules[n_modules];
+ // Don't subtract 'cur_beg' from the first entry:
+ // * If a binary is compiled w/o -pie, then the first entry in
+ // process maps is likely the binary itself (all dynamic libs
+ // are mapped higher in address space). For such a binary,
+ // instruction offset in binary coincides with the actual
+ // instruction address in virtual memory (as code section
+ // is mapped to a fixed memory range).
+ // * If a binary is compiled with -pie, all the modules are
+ // mapped high at address space (in particular, higher than
+ // shadow memory of the tool), so the module can't be the
+ // first entry.
+ uptr base_address = (i ? cur_beg : 0) - cur_offset;
+ LoadedModule *cur_module = new(mem) LoadedModule(cur_name, base_address);
+ cur_module->addAddressRange(cur_beg, cur_end);
+ n_modules++;
+ }
+ return n_modules;
+}
+
+void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) {
+ char *smaps = 0;
+ uptr smaps_cap = 0;
+ uptr smaps_len = ReadFileToBuffer("/proc/self/smaps",
+ &smaps, &smaps_cap, 64<<20);
+ uptr start = 0;
+ bool file = false;
+ const char *pos = smaps;
+ while (pos < smaps + smaps_len) {
+ if (IsHex(pos[0])) {
+ start = ReadHex(pos);
+ for (; *pos != '/' && *pos > '\n'; pos++) {}
+ file = *pos == '/';
+ } else if (internal_strncmp(pos, "Rss:", 4) == 0) {
+ for (; *pos < '0' || *pos > '9'; pos++) {}
+ uptr rss = ReadDecimal(pos) * 1024;
+ cb(start, rss, file, stats, stats_size);
+ }
+ while (*pos++ != '\n') {}
+ }
+ UnmapOrDie(smaps, smaps_cap);
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
diff --git a/libsanitizer/sanitizer_common/sanitizer_procmaps_mac.cc b/libsanitizer/sanitizer_common/sanitizer_procmaps_mac.cc
new file mode 100644
index 00000000000..c6853068346
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_procmaps_mac.cc
@@ -0,0 +1,186 @@
+//===-- sanitizer_procmaps_mac.cc -----------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Information about the process mappings (Mac-specific parts).
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_MAC
+#include "sanitizer_common.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_procmaps.h"
+
+#include <mach-o/dyld.h>
+#include <mach-o/loader.h>
+
+namespace __sanitizer {
+
+MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
+ Reset();
+}
+
+MemoryMappingLayout::~MemoryMappingLayout() {
+}
+
+// More information about Mach-O headers can be found in mach-o/loader.h
+// Each Mach-O image has a header (mach_header or mach_header_64) starting with
+// a magic number, and a list of linker load commands directly following the
+// header.
+// A load command is at least two 32-bit words: the command type and the
+// command size in bytes. We're interested only in segment load commands
+// (LC_SEGMENT and LC_SEGMENT_64), which tell that a part of the file is mapped
+// into the task's address space.
+// The |vmaddr|, |vmsize| and |fileoff| fields of segment_command or
+// segment_command_64 correspond to the memory address, memory size and the
+// file offset of the current memory segment.
+// Because these fields are taken from the images as is, one needs to add
+// _dyld_get_image_vmaddr_slide() to get the actual addresses at runtime.
+
+void MemoryMappingLayout::Reset() {
+ // Count down from the top.
+ // TODO(glider): as per man 3 dyld, iterating over the headers with
+ // _dyld_image_count is thread-unsafe. We need to register callbacks for
+ // adding and removing images which will invalidate the MemoryMappingLayout
+ // state.
+ current_image_ = _dyld_image_count();
+ current_load_cmd_count_ = -1;
+ current_load_cmd_addr_ = 0;
+ current_magic_ = 0;
+ current_filetype_ = 0;
+}
+
+// static
+void MemoryMappingLayout::CacheMemoryMappings() {
+ // No-op on Mac for now.
+}
+
+void MemoryMappingLayout::LoadFromCache() {
+ // No-op on Mac for now.
+}
+
+// Next and NextSegmentLoad were inspired by base/sysinfo.cc in
+// Google Perftools, http://code.google.com/p/google-perftools.
+
+// NextSegmentLoad scans the current image for the next segment load command
+// and returns the start and end addresses and file offset of the corresponding
+// segment.
+// Note that the segment addresses are not necessarily sorted.
+template<u32 kLCSegment, typename SegmentCommand>
+bool MemoryMappingLayout::NextSegmentLoad(
+ uptr *start, uptr *end, uptr *offset,
+ char filename[], uptr filename_size, uptr *protection) {
+ if (protection)
+ UNIMPLEMENTED();
+ const char* lc = current_load_cmd_addr_;
+ current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize;
+ if (((const load_command *)lc)->cmd == kLCSegment) {
+ const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_);
+ const SegmentCommand* sc = (const SegmentCommand *)lc;
+ if (start) *start = sc->vmaddr + dlloff;
+ if (end) *end = sc->vmaddr + sc->vmsize + dlloff;
+ if (offset) {
+ if (current_filetype_ == /*MH_EXECUTE*/ 0x2) {
+ *offset = sc->vmaddr;
+ } else {
+ *offset = sc->fileoff;
+ }
+ }
+ if (filename) {
+ internal_strncpy(filename, _dyld_get_image_name(current_image_),
+ filename_size);
+ }
+ return true;
+ }
+ return false;
+}
+
+bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
+ char filename[], uptr filename_size,
+ uptr *protection) {
+ for (; current_image_ >= 0; current_image_--) {
+ const mach_header* hdr = _dyld_get_image_header(current_image_);
+ if (!hdr) continue;
+ if (current_load_cmd_count_ < 0) {
+ // Set up for this image;
+ current_load_cmd_count_ = hdr->ncmds;
+ current_magic_ = hdr->magic;
+ current_filetype_ = hdr->filetype;
+ switch (current_magic_) {
+#ifdef MH_MAGIC_64
+ case MH_MAGIC_64: {
+ current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header_64);
+ break;
+ }
+#endif
+ case MH_MAGIC: {
+ current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header);
+ break;
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+
+ for (; current_load_cmd_count_ >= 0; current_load_cmd_count_--) {
+ switch (current_magic_) {
+ // current_magic_ may be only one of MH_MAGIC, MH_MAGIC_64.
+#ifdef MH_MAGIC_64
+ case MH_MAGIC_64: {
+ if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
+ start, end, offset, filename, filename_size, protection))
+ return true;
+ break;
+ }
+#endif
+ case MH_MAGIC: {
+ if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
+ start, end, offset, filename, filename_size, protection))
+ return true;
+ break;
+ }
+ }
+ }
+ // If we get here, no more load_cmd's in this image talk about
+ // segments. Go on to the next image.
+ }
+ return false;
+}
+
+uptr MemoryMappingLayout::DumpListOfModules(LoadedModule *modules,
+ uptr max_modules,
+ string_predicate_t filter) {
+ Reset();
+ uptr cur_beg, cur_end;
+ InternalScopedBuffer<char> module_name(kMaxPathLength);
+ uptr n_modules = 0;
+ for (uptr i = 0; n_modules < max_modules &&
+ Next(&cur_beg, &cur_end, 0, module_name.data(),
+ module_name.size(), 0);
+ i++) {
+ const char *cur_name = module_name.data();
+ if (cur_name[0] == '\0')
+ continue;
+ if (filter && !filter(cur_name))
+ continue;
+ LoadedModule *cur_module = 0;
+ if (n_modules > 0 &&
+ 0 == internal_strcmp(cur_name, modules[n_modules - 1].full_name())) {
+ cur_module = &modules[n_modules - 1];
+ } else {
+ void *mem = &modules[n_modules];
+ cur_module = new(mem) LoadedModule(cur_name, cur_beg);
+ n_modules++;
+ }
+ cur_module->addAddressRange(cur_beg, cur_end);
+ }
+ return n_modules;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_MAC
diff --git a/libsanitizer/sanitizer_common/sanitizer_report_decorator.h b/libsanitizer/sanitizer_common/sanitizer_report_decorator.h
index c6e79ad0c7c..c8510585111 100644
--- a/libsanitizer/sanitizer_common/sanitizer_report_decorator.h
+++ b/libsanitizer/sanitizer_common/sanitizer_report_decorator.h
@@ -15,6 +15,8 @@
#ifndef SANITIZER_REPORT_DECORATOR_H
#define SANITIZER_REPORT_DECORATOR_H
+#include "sanitizer_common.h"
+
namespace __sanitizer {
class AnsiColorDecorator {
// FIXME: This is not portable. It assumes the special strings are printed to
@@ -34,6 +36,15 @@ class AnsiColorDecorator {
private:
bool ansi_;
};
+
+class SanitizerCommonDecorator: protected AnsiColorDecorator {
+ public:
+ SanitizerCommonDecorator()
+ : __sanitizer::AnsiColorDecorator(ColorizeReports()) { }
+ const char *Warning() { return Red(); }
+ const char *EndWarning() { return Default(); }
+};
+
} // namespace __sanitizer
#endif // SANITIZER_REPORT_DECORATOR_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
index 3a9e902537a..244ac36f5f8 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
@@ -11,18 +11,15 @@
#include "sanitizer_common.h"
#include "sanitizer_flags.h"
-#include "sanitizer_procmaps.h"
#include "sanitizer_stacktrace.h"
-#include "sanitizer_symbolizer.h"
namespace __sanitizer {
uptr StackTrace::GetPreviousInstructionPc(uptr pc) {
-#ifdef __arm__
+#if defined(__arm__)
// Cancel Thumb bit.
pc = pc & (~1);
-#endif
-#if defined(__powerpc__) || defined(__powerpc64__)
+#elif defined(__powerpc__) || defined(__powerpc64__)
// PCs are always 4 byte aligned.
return pc - 4;
#elif defined(__sparc__)
@@ -32,87 +29,6 @@ uptr StackTrace::GetPreviousInstructionPc(uptr pc) {
#endif
}
-static void PrintStackFramePrefix(InternalScopedString *buffer, uptr frame_num,
- uptr pc) {
- buffer->append(" #%zu 0x%zx", frame_num, pc);
-}
-
-void StackTrace::PrintStack(const uptr *addr, uptr size,
- SymbolizeCallback symbolize_callback) {
- if (addr == 0 || size == 0) {
- Printf(" <empty stack>\n\n");
- return;
- }
- MemoryMappingLayout proc_maps(/*cache_enabled*/true);
- InternalScopedBuffer<char> buff(GetPageSizeCached() * 2);
- InternalScopedBuffer<AddressInfo> addr_frames(64);
- InternalScopedString frame_desc(GetPageSizeCached() * 2);
- uptr frame_num = 0;
- for (uptr i = 0; i < size && addr[i]; i++) {
- // PCs in stack traces are actually the return addresses, that is,
- // addresses of the next instructions after the call.
- uptr pc = GetPreviousInstructionPc(addr[i]);
- uptr addr_frames_num = 0; // The number of stack frames for current
- // instruction address.
- if (symbolize_callback) {
- if (symbolize_callback((void*)pc, buff.data(), buff.size())) {
- addr_frames_num = 1;
- frame_desc.clear();
- PrintStackFramePrefix(&frame_desc, frame_num, pc);
- // We can't know anything about the string returned by external
- // symbolizer, but if it starts with filename, try to strip path prefix
- // from it.
- frame_desc.append(
- " %s",
- StripPathPrefix(buff.data(), common_flags()->strip_path_prefix));
- Printf("%s\n", frame_desc.data());
- frame_num++;
- }
- }
- if (common_flags()->symbolize && addr_frames_num == 0) {
- // Use our own (online) symbolizer, if necessary.
- if (Symbolizer *sym = Symbolizer::GetOrNull())
- addr_frames_num =
- sym->SymbolizeCode(pc, addr_frames.data(), addr_frames.size());
- for (uptr j = 0; j < addr_frames_num; j++) {
- AddressInfo &info = addr_frames[j];
- frame_desc.clear();
- PrintStackFramePrefix(&frame_desc, frame_num, pc);
- if (info.function) {
- frame_desc.append(" in %s", info.function);
- }
- if (info.file) {
- frame_desc.append(" ");
- PrintSourceLocation(&frame_desc, info.file, info.line, info.column);
- } else if (info.module) {
- frame_desc.append(" ");
- PrintModuleAndOffset(&frame_desc, info.module, info.module_offset);
- }
- Printf("%s\n", frame_desc.data());
- frame_num++;
- info.Clear();
- }
- }
- if (addr_frames_num == 0) {
- // If online symbolization failed, try to output at least module and
- // offset for instruction.
- frame_desc.clear();
- PrintStackFramePrefix(&frame_desc, frame_num, pc);
- uptr offset;
- if (proc_maps.GetObjectNameAndOffset(pc, &offset,
- buff.data(), buff.size(),
- /* protection */0)) {
- frame_desc.append(" ");
- PrintModuleAndOffset(&frame_desc, buff.data(), offset);
- }
- Printf("%s\n", frame_desc.data());
- frame_num++;
- }
- }
- // Always print a trailing empty line after stack trace.
- Printf("\n");
-}
-
uptr StackTrace::GetCurrentPc() {
return GET_CALLER_PC();
}
@@ -120,10 +36,7 @@ uptr StackTrace::GetCurrentPc() {
void StackTrace::FastUnwindStack(uptr pc, uptr bp,
uptr stack_top, uptr stack_bottom,
uptr max_depth) {
- if (max_depth == 0) {
- size = 0;
- return;
- }
+ CHECK_GE(max_depth, 2);
trace[0] = pc;
size = 1;
uhwptr *frame = (uhwptr *)bp;
@@ -144,22 +57,22 @@ void StackTrace::FastUnwindStack(uptr pc, uptr bp,
}
}
+static bool MatchPc(uptr cur_pc, uptr trace_pc, uptr threshold) {
+ return cur_pc - trace_pc <= threshold || trace_pc - cur_pc <= threshold;
+}
+
void StackTrace::PopStackFrames(uptr count) {
- CHECK(size >= count);
+ CHECK_LT(count, size);
size -= count;
- for (uptr i = 0; i < size; i++) {
+ for (uptr i = 0; i < size; ++i) {
trace[i] = trace[i + count];
}
}
-static bool MatchPc(uptr cur_pc, uptr trace_pc, uptr threshold) {
- return cur_pc - trace_pc <= threshold || trace_pc - cur_pc <= threshold;
-}
-
uptr StackTrace::LocatePcInTrace(uptr pc) {
// Use threshold to find PC in stack trace, as PC we want to unwind from may
// slightly differ from return address in the actual unwinded stack trace.
- const int kPcThreshold = 192;
+ const int kPcThreshold = 288;
for (uptr i = 0; i < size; ++i) {
if (MatchPc(pc, trace[i], kPcThreshold))
return i;
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.h b/libsanitizer/sanitizer_common/sanitizer_stacktrace.h
index d06db5ffa7a..f66857ed1fb 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.h
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.h
@@ -17,10 +17,9 @@ namespace __sanitizer {
static const uptr kStackTraceMax = 256;
-#if SANITIZER_LINUX && (defined(__arm__) || \
- defined(__powerpc__) || defined(__powerpc64__) || \
- defined(__sparc__) || \
- defined(__mips__))
+#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__powerpc__) || \
+ defined(__powerpc64__) || defined(__sparc__) || \
+ defined(__mips__))
# define SANITIZER_CAN_FAST_UNWIND 0
#elif SANITIZER_WINDOWS
# define SANITIZER_CAN_FAST_UNWIND 0
@@ -36,8 +35,10 @@ struct StackTrace {
uptr trace[kStackTraceMax];
// Prints a symbolized stacktrace, followed by an empty line.
- static void PrintStack(const uptr *addr, uptr size,
- SymbolizeCallback symbolize_callback = 0);
+ static void PrintStack(const uptr *addr, uptr size);
+ void Print() const {
+ PrintStack(trace, size);
+ }
void CopyFrom(const uptr *src, uptr src_size) {
top_frame_bp = 0;
@@ -56,7 +57,7 @@ struct StackTrace {
return request_fast_unwind;
}
- void Unwind(uptr max_depth, uptr pc, uptr bp, uptr stack_top,
+ void Unwind(uptr max_depth, uptr pc, uptr bp, void *context, uptr stack_top,
uptr stack_bottom, bool request_fast_unwind);
static uptr GetCurrentPc();
@@ -66,6 +67,8 @@ struct StackTrace {
void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom,
uptr max_depth);
void SlowUnwindStack(uptr pc, uptr max_depth);
+ void SlowUnwindStackWithContext(uptr pc, void *context,
+ uptr max_depth);
void PopStackFrames(uptr count);
uptr LocatePcInTrace(uptr pc);
};
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cc
index ea2f9d07771..c3c1045ee04 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cc
@@ -9,18 +9,80 @@
// run-time libraries.
//===----------------------------------------------------------------------===//
+#include "sanitizer_common.h"
#include "sanitizer_stacktrace.h"
+#include "sanitizer_symbolizer.h"
namespace __sanitizer {
-void StackTrace::Unwind(uptr max_depth, uptr pc, uptr bp, uptr stack_top,
- uptr stack_bottom, bool request_fast_unwind) {
- if (!WillUseFastUnwind(request_fast_unwind))
- SlowUnwindStack(pc, max_depth);
- else
- FastUnwindStack(pc, bp, stack_top, stack_bottom, max_depth);
+static void PrintStackFramePrefix(InternalScopedString *buffer, uptr frame_num,
+ uptr pc) {
+ buffer->append(" #%zu 0x%zx", frame_num, pc);
+}
- top_frame_bp = size ? bp : 0;
+void StackTrace::PrintStack(const uptr *addr, uptr size) {
+ if (addr == 0 || size == 0) {
+ Printf(" <empty stack>\n\n");
+ return;
+ }
+ InternalScopedBuffer<char> buff(GetPageSizeCached() * 2);
+ InternalScopedBuffer<AddressInfo> addr_frames(64);
+ InternalScopedString frame_desc(GetPageSizeCached() * 2);
+ uptr frame_num = 0;
+ for (uptr i = 0; i < size && addr[i]; i++) {
+ // PCs in stack traces are actually the return addresses, that is,
+ // addresses of the next instructions after the call.
+ uptr pc = GetPreviousInstructionPc(addr[i]);
+ uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC(
+ pc, addr_frames.data(), addr_frames.size());
+ for (uptr j = 0; j < addr_frames_num; j++) {
+ AddressInfo &info = addr_frames[j];
+ frame_desc.clear();
+ PrintStackFramePrefix(&frame_desc, frame_num, pc);
+ if (info.function) {
+ frame_desc.append(" in %s", info.function);
+ // Print offset in function if we don't know the source file.
+ if (!info.file && info.function_offset != AddressInfo::kUnknown)
+ frame_desc.append("+0x%zx", info.function_offset);
+ }
+ if (info.file) {
+ frame_desc.append(" ");
+ PrintSourceLocation(&frame_desc, info.file, info.line, info.column);
+ } else if (info.module) {
+ frame_desc.append(" ");
+ PrintModuleAndOffset(&frame_desc, info.module, info.module_offset);
+ }
+ Printf("%s\n", frame_desc.data());
+ frame_num++;
+ info.Clear();
+ }
+ }
+ // Always print a trailing empty line after stack trace.
+ Printf("\n");
+}
+
+void StackTrace::Unwind(uptr max_depth, uptr pc, uptr bp, void *context,
+ uptr stack_top, uptr stack_bottom,
+ bool request_fast_unwind) {
+ top_frame_bp = (max_depth > 0) ? bp : 0;
+ // Avoid doing any work for small max_depth.
+ if (max_depth == 0) {
+ size = 0;
+ return;
+ }
+ if (max_depth == 1) {
+ size = 1;
+ trace[0] = pc;
+ return;
+ }
+ if (!WillUseFastUnwind(request_fast_unwind)) {
+ if (context)
+ SlowUnwindStackWithContext(pc, context, max_depth);
+ else
+ SlowUnwindStack(pc, max_depth);
+ } else {
+ FastUnwindStack(pc, bp, stack_top, stack_bottom, max_depth);
+ }
}
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
index 6ee63ec3168..58812023674 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
@@ -98,12 +98,11 @@ bool ThreadSuspender::SuspendThread(SuspendedThreadID thread_id) {
&pterrno)) {
// Either the thread is dead, or something prevented us from attaching.
// Log this event and move on.
- if (common_flags()->verbosity)
- Report("Could not attach to thread %d (errno %d).\n", thread_id, pterrno);
+ VReport(1, "Could not attach to thread %d (errno %d).\n", thread_id,
+ pterrno);
return false;
} else {
- if (common_flags()->verbosity)
- Report("Attached to thread %d.\n", thread_id);
+ VReport(1, "Attached to thread %d.\n", thread_id);
// The thread is not guaranteed to stop before ptrace returns, so we must
// wait on it.
uptr waitpid_status;
@@ -112,9 +111,8 @@ bool ThreadSuspender::SuspendThread(SuspendedThreadID thread_id) {
if (internal_iserror(waitpid_status, &wperrno)) {
// Got a ECHILD error. I don't think this situation is possible, but it
// doesn't hurt to report it.
- if (common_flags()->verbosity)
- Report("Waiting on thread %d failed, detaching (errno %d).\n",
- thread_id, wperrno);
+ VReport(1, "Waiting on thread %d failed, detaching (errno %d).\n",
+ thread_id, wperrno);
internal_ptrace(PTRACE_DETACH, thread_id, NULL, NULL);
return false;
}
@@ -129,14 +127,12 @@ void ThreadSuspender::ResumeAllThreads() {
int pterrno;
if (!internal_iserror(internal_ptrace(PTRACE_DETACH, tid, NULL, NULL),
&pterrno)) {
- if (common_flags()->verbosity)
- Report("Detached from thread %d.\n", tid);
+ VReport(1, "Detached from thread %d.\n", tid);
} else {
// Either the thread is dead, or we are already detached.
// The latter case is possible, for instance, if this function was called
// from a signal handler.
- if (common_flags()->verbosity)
- Report("Could not detach from thread %d (errno %d).\n", tid, pterrno);
+ VReport(1, "Could not detach from thread %d (errno %d).\n", tid, pterrno);
}
}
}
@@ -248,18 +244,18 @@ static int TracerThread(void* argument) {
// the mask we inherited from the caller thread.
for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals);
signal_index++) {
- __sanitizer_kernel_sigaction_t new_sigaction;
+ __sanitizer_sigaction new_sigaction;
internal_memset(&new_sigaction, 0, sizeof(new_sigaction));
new_sigaction.sigaction = TracerThreadSignalHandler;
new_sigaction.sa_flags = SA_ONSTACK | SA_SIGINFO;
internal_sigfillset(&new_sigaction.sa_mask);
- internal_sigaction(kUnblockedSignals[signal_index], &new_sigaction, NULL);
+ internal_sigaction_norestorer(kUnblockedSignals[signal_index],
+ &new_sigaction, NULL);
}
int exit_code = 0;
if (!thread_suspender.SuspendAllThreads()) {
- if (common_flags()->verbosity)
- Report("Failed suspending threads.\n");
+ VReport(1, "Failed suspending threads.\n");
exit_code = 3;
} else {
tracer_thread_argument->callback(thread_suspender.suspended_threads_list(),
@@ -299,9 +295,9 @@ class ScopedStackSpaceWithGuard {
// We have a limitation on the stack frame size, so some stuff had to be moved
// into globals.
-static __sanitizer_kernel_sigset_t blocked_sigset;
-static __sanitizer_kernel_sigset_t old_sigset;
-static __sanitizer_kernel_sigaction_t old_sigactions
+static __sanitizer_sigset_t blocked_sigset;
+static __sanitizer_sigset_t old_sigset;
+static __sanitizer_sigaction old_sigactions
[ARRAY_SIZE(kUnblockedSignals)];
class StopTheWorldScope {
@@ -318,12 +314,12 @@ class StopTheWorldScope {
// Remove the signal from the set of blocked signals.
internal_sigdelset(&blocked_sigset, kUnblockedSignals[signal_index]);
// Install the default handler.
- __sanitizer_kernel_sigaction_t new_sigaction;
+ __sanitizer_sigaction new_sigaction;
internal_memset(&new_sigaction, 0, sizeof(new_sigaction));
new_sigaction.handler = SIG_DFL;
internal_sigfillset(&new_sigaction.sa_mask);
- internal_sigaction(kUnblockedSignals[signal_index], &new_sigaction,
- &old_sigactions[signal_index]);
+ internal_sigaction_norestorer(kUnblockedSignals[signal_index],
+ &new_sigaction, &old_sigactions[signal_index]);
}
int sigprocmask_status =
internal_sigprocmask(SIG_BLOCK, &blocked_sigset, &old_sigset);
@@ -344,8 +340,8 @@ class StopTheWorldScope {
// Restore the signal handlers.
for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals);
signal_index++) {
- internal_sigaction(kUnblockedSignals[signal_index],
- &old_sigactions[signal_index], NULL);
+ internal_sigaction_norestorer(kUnblockedSignals[signal_index],
+ &old_sigactions[signal_index], NULL);
}
internal_sigprocmask(SIG_SETMASK, &old_sigset, &old_sigset);
}
@@ -387,8 +383,7 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {
/* child_tidptr */);
int local_errno = 0;
if (internal_iserror(tracer_pid, &local_errno)) {
- if (common_flags()->verbosity)
- Report("Failed spawning a tracer thread (errno %d).\n", local_errno);
+ VReport(1, "Failed spawning a tracer thread (errno %d).\n", local_errno);
tracer_thread_argument.mutex.Unlock();
} else {
ScopedSetTracerPID scoped_set_tracer_pid(tracer_pid);
@@ -404,11 +399,9 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {
// At this point, any signal will either be blocked or kill us, so waitpid
// should never return (and set errno) while the tracer thread is alive.
uptr waitpid_status = internal_waitpid(tracer_pid, NULL, __WALL);
- if (internal_iserror(waitpid_status, &local_errno)) {
- if (common_flags()->verbosity)
- Report("Waiting on the tracer thread failed (errno %d).\n",
- local_errno);
- }
+ if (internal_iserror(waitpid_status, &local_errno))
+ VReport(1, "Waiting on the tracer thread failed (errno %d).\n",
+ local_errno);
}
}
@@ -449,9 +442,8 @@ int SuspendedThreadsList::GetRegistersAndSP(uptr index,
int pterrno;
if (internal_iserror(internal_ptrace(PTRACE_GETREGS, tid, NULL, &regs),
&pterrno)) {
- if (common_flags()->verbosity)
- Report("Could not get registers from thread %d (errno %d).\n",
- tid, pterrno);
+ VReport(1, "Could not get registers from thread %d (errno %d).\n", tid,
+ pterrno);
return -1;
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_suppressions.cc b/libsanitizer/sanitizer_common/sanitizer_suppressions.cc
index 14f13e62081..1766fb5a319 100644
--- a/libsanitizer/sanitizer_common/sanitizer_suppressions.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_suppressions.cc
@@ -18,8 +18,8 @@
namespace __sanitizer {
static const char *const kTypeStrings[SuppressionTypeCount] = {
- "none", "race", "mutex", "thread", "signal", "leak", "called_from_lib"
-};
+ "none", "race", "mutex", "thread",
+ "signal", "leak", "called_from_lib", "deadlock"};
bool TemplateMatch(char *templ, const char *str) {
if (str == 0 || str[0] == 0)
diff --git a/libsanitizer/sanitizer_common/sanitizer_suppressions.h b/libsanitizer/sanitizer_common/sanitizer_suppressions.h
index b4c719cb187..033ddc5f52a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_suppressions.h
+++ b/libsanitizer/sanitizer_common/sanitizer_suppressions.h
@@ -24,6 +24,7 @@ enum SuppressionType {
SuppressionSignal,
SuppressionLeak,
SuppressionLib,
+ SuppressionDeadlock,
SuppressionTypeCount
};
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer.h b/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
index af93de75081..05fc6a7cbb9 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
@@ -25,23 +25,30 @@ namespace __sanitizer {
struct AddressInfo {
uptr address;
+
char *module;
uptr module_offset;
+
+ static const uptr kUnknown = ~(uptr)0;
char *function;
+ uptr function_offset;
+
char *file;
int line;
int column;
AddressInfo() {
internal_memset(this, 0, sizeof(AddressInfo));
+ function_offset = kUnknown;
}
- // Deletes all strings and sets all fields to zero.
+ // Deletes all strings and resets all fields.
void Clear() {
InternalFree(module);
InternalFree(function);
InternalFree(file);
internal_memset(this, 0, sizeof(AddressInfo));
+ function_offset = kUnknown;
}
void FillAddressAndModuleInfo(uptr addr, const char *mod_name,
@@ -77,22 +84,20 @@ class Symbolizer {
/// reasons as this function will check $PATH for an external symbolizer. Not
/// thread safe.
static Symbolizer *Init(const char* path_to_external = 0);
- /// Initialize the symbolizer in a disabled state. Not thread safe.
- static Symbolizer *Disable();
// Fills at most "max_frames" elements of "frames" with descriptions
// for a given address (in all inlined functions). Returns the number
// of descriptions actually filled.
- virtual uptr SymbolizeCode(uptr address, AddressInfo *frames,
- uptr max_frames) {
+ virtual uptr SymbolizePC(uptr address, AddressInfo *frames, uptr max_frames) {
return 0;
}
virtual bool SymbolizeData(uptr address, DataInfo *info) {
return false;
}
- virtual bool IsAvailable() {
+ virtual bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
+ uptr *module_address) {
return false;
}
- virtual bool IsExternalAvailable() {
+ virtual bool CanReturnFileLineInfo() {
return false;
}
// Release internal caches (if any).
@@ -119,6 +124,8 @@ class Symbolizer {
/// Create a symbolizer and store it to symbolizer_ without checking if one
/// already exists. Not thread safe.
static Symbolizer *CreateAndStore(const char *path_to_external);
+ /// Initialize the symbolizer in a disabled state. Not thread safe.
+ static Symbolizer *Disable();
static Symbolizer *symbolizer_;
static StaticSpinMutex init_mu_;
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
index 3023002af47..86d32e529ec 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
@@ -35,7 +35,7 @@ namespace __sanitizer {
namespace {
-#if SANITIZER_CP_DEMANGLE
+# if SANITIZER_CP_DEMANGLE
struct CplusV3DemangleData {
char *buf;
uptr size, allocated;
@@ -62,13 +62,13 @@ static void CplusV3DemangleCallback(const char *s, size_t l, void *vdata) {
}
} // extern "C"
-char *CplusV3Demangle(const char *name, bool always_alloc) {
+char *CplusV3Demangle(const char *name) {
CplusV3DemangleData data;
data.buf = 0;
data.size = 0;
data.allocated = 0;
if (cplus_demangle_v3_callback(name, DMGL_PARAMS | DMGL_ANSI,
- CplusV3DemangleCallback, &data)) {
+ CplusV3DemangleCallback, &data)) {
if (data.size + 64 > data.allocated)
return data.buf;
char *buf = internal_strdup(data.buf);
@@ -77,17 +77,9 @@ char *CplusV3Demangle(const char *name, bool always_alloc) {
}
if (data.buf)
InternalFree(data.buf);
- if (always_alloc)
- return internal_strdup(name);
- return 0;
-}
-#else
-const char *CplusV3Demangle(const char *name, bool always_alloc) {
- if (always_alloc)
- return internal_strdup(name);
return 0;
}
-#endif
+# endif // SANITIZER_CP_DEMANGLE
struct SymbolizeCodeData {
AddressInfo *frames;
@@ -107,7 +99,7 @@ static int SymbolizeCodePCInfoCallback(void *vdata, uintptr_t addr,
info->Clear();
info->FillAddressAndModuleInfo(addr, cdata->module_name,
cdata->module_offset);
- info->function = CplusV3Demangle(function, true);
+ info->function = LibbacktraceSymbolizer::Demangle(function, true);
if (filename)
info->file = internal_strdup(filename);
info->line = lineno;
@@ -125,7 +117,7 @@ static void SymbolizeCodeCallback(void *vdata, uintptr_t addr,
info->Clear();
info->FillAddressAndModuleInfo(addr, cdata->module_name,
cdata->module_offset);
- info->function = CplusV3Demangle(symname, true);
+ info->function = LibbacktraceSymbolizer::Demangle(symname, true);
cdata->n_frames = 1;
}
}
@@ -134,7 +126,7 @@ static void SymbolizeDataCallback(void *vdata, uintptr_t, const char *symname,
uintptr_t symval, uintptr_t symsize) {
DataInfo *info = (DataInfo *)vdata;
if (symname && symval) {
- info->name = CplusV3Demangle(symname, true);
+ info->name = LibbacktraceSymbolizer::Demangle(symname, true);
info->start = symval;
info->size = symsize;
}
@@ -179,17 +171,6 @@ bool LibbacktraceSymbolizer::SymbolizeData(DataInfo *info) {
return true;
}
-const char *LibbacktraceSymbolizer::Demangle(const char *name) {
-#if SANITIZER_CP_DEMANGLE
- const char *demangled = CplusV3Demangle(name, false);
- if (demangled)
- return demangled;
- return name;
-#else
- return 0;
-#endif
-}
-
#else // SANITIZER_LIBBACKTRACE
LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
@@ -208,10 +189,16 @@ bool LibbacktraceSymbolizer::SymbolizeData(DataInfo *info) {
return false;
}
-const char *LibbacktraceSymbolizer::Demangle(const char *name) {
+#endif // SANITIZER_LIBBACKTRACE
+
+char *LibbacktraceSymbolizer::Demangle(const char *name, bool always_alloc) {
+#if SANITIZER_LIBBACKTRACE && SANITIZER_CP_DEMANGLE
+ if (char *demangled = CplusV3Demangle(name))
+ return demangled;
+#endif
+ if (always_alloc)
+ return internal_strdup(name);
return 0;
}
-#endif // SANITIZER_LIBBACKTRACE
-
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.h b/libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
index 05f0558c3d8..c7a83bfca92 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
@@ -1,4 +1,4 @@
-//===-- sanitizer_symbolizer_libbacktrace.h -------------------------------===//
+//===-- sanitizer_symbolizer_libbacktrace.h ---------------------*- C++ -*-===//
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
@@ -9,6 +9,8 @@
// run-time libraries.
// Header for libbacktrace symbolizer.
//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_SYMBOLIZER_LIBBACKTRACE_H
+#define SANITIZER_SYMBOLIZER_LIBBACKTRACE_H
#include "sanitizer_platform.h"
#include "sanitizer_common.h"
@@ -18,6 +20,10 @@
# define SANITIZER_LIBBACKTRACE 0
#endif
+#ifndef SANITIZER_CP_DEMANGLE
+# define SANITIZER_CP_DEMANGLE 0
+#endif
+
namespace __sanitizer {
class LibbacktraceSymbolizer {
@@ -29,7 +35,8 @@ class LibbacktraceSymbolizer {
bool SymbolizeData(DataInfo *info);
- const char *Demangle(const char *name);
+ // May return NULL if demangling failed.
+ static char *Demangle(const char *name, bool always_alloc = false);
private:
explicit LibbacktraceSymbolizer(void *state) : state_(state) {}
@@ -38,3 +45,4 @@ class LibbacktraceSymbolizer {
};
} // namespace __sanitizer
+#endif // SANITIZER_SYMBOLIZER_LIBBACKTRACE_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
index 7aead970382..161c21b3aad 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
@@ -14,6 +14,7 @@
#if SANITIZER_POSIX
#include "sanitizer_allocator_internal.h"
#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_linux.h"
#include "sanitizer_placement_new.h"
@@ -52,107 +53,6 @@ static const char *DemangleCXXABI(const char *name) {
return name;
}
-#if defined(__x86_64__)
-static const char* const kSymbolizerArch = "--default-arch=x86_64";
-#elif defined(__i386__)
-static const char* const kSymbolizerArch = "--default-arch=i386";
-#elif defined(__powerpc64__)
-static const char* const kSymbolizerArch = "--default-arch=powerpc64";
-#else
-static const char* const kSymbolizerArch = "--default-arch=unknown";
-#endif
-
-static const int kSymbolizerStartupTimeMillis = 10;
-
-// Creates external symbolizer connected via pipe, user should write
-// to output_fd and read from input_fd.
-static bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
- int *input_fd, int *output_fd) {
- if (!FileExists(path_to_symbolizer)) {
- Report("WARNING: invalid path to external symbolizer!\n");
- return false;
- }
-
- int *infd = NULL;
- int *outfd = NULL;
- // The client program may close its stdin and/or stdout and/or stderr
- // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
- // In this case the communication between the forked processes may be
- // broken if either the parent or the child tries to close or duplicate
- // these descriptors. The loop below produces two pairs of file
- // descriptors, each greater than 2 (stderr).
- int sock_pair[5][2];
- for (int i = 0; i < 5; i++) {
- if (pipe(sock_pair[i]) == -1) {
- for (int j = 0; j < i; j++) {
- internal_close(sock_pair[j][0]);
- internal_close(sock_pair[j][1]);
- }
- Report("WARNING: Can't create a socket pair to start "
- "external symbolizer (errno: %d)\n", errno);
- return false;
- } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) {
- if (infd == NULL) {
- infd = sock_pair[i];
- } else {
- outfd = sock_pair[i];
- for (int j = 0; j < i; j++) {
- if (sock_pair[j] == infd) continue;
- internal_close(sock_pair[j][0]);
- internal_close(sock_pair[j][1]);
- }
- break;
- }
- }
- }
- CHECK(infd);
- CHECK(outfd);
-
- int pid = fork();
- if (pid == -1) {
- // Fork() failed.
- internal_close(infd[0]);
- internal_close(infd[1]);
- internal_close(outfd[0]);
- internal_close(outfd[1]);
- Report("WARNING: failed to fork external symbolizer "
- " (errno: %d)\n", errno);
- return false;
- } else if (pid == 0) {
- // Child subprocess.
- internal_close(STDOUT_FILENO);
- internal_close(STDIN_FILENO);
- internal_dup2(outfd[0], STDIN_FILENO);
- internal_dup2(infd[1], STDOUT_FILENO);
- internal_close(outfd[0]);
- internal_close(outfd[1]);
- internal_close(infd[0]);
- internal_close(infd[1]);
- for (int fd = getdtablesize(); fd > 2; fd--)
- internal_close(fd);
- execl(path_to_symbolizer, path_to_symbolizer, kSymbolizerArch, (char*)0);
- internal__exit(1);
- }
-
- // Continue execution in parent process.
- internal_close(outfd[0]);
- internal_close(infd[1]);
- *input_fd = infd[0];
- *output_fd = outfd[1];
-
- // Check that symbolizer subprocess started successfully.
- int pid_status;
- SleepForMillis(kSymbolizerStartupTimeMillis);
- int exited_pid = waitpid(pid, &pid_status, WNOHANG);
- if (exited_pid != 0) {
- // Either waitpid failed, or child has already exited.
- Report("WARNING: external symbolizer didn't start up correctly!\n");
- return false;
- }
-
- return true;
-}
-
// Extracts the prefix of "str" that consists of any characters not
// present in "delims" string, and copies this prefix to "result", allocating
// space for it.
@@ -192,29 +92,30 @@ static const char *ExtractUptr(const char *str, const char *delims,
return ret;
}
-// ExternalSymbolizer encapsulates communication between the tool and
-// external symbolizer program, running in a different subprocess,
-// For now we assume the following protocol:
-// For each request of the form
-// <module_name> <module_offset>
-// passed to STDIN, external symbolizer prints to STDOUT response:
-// <function_name>
-// <file_name>:<line_number>:<column_number>
-// <function_name>
-// <file_name>:<line_number>:<column_number>
-// ...
-// <empty line>
-// ExternalSymbolizer may not be used from two threads simultaneously.
-class ExternalSymbolizer {
+class ExternalSymbolizerInterface {
+ public:
+ // Can't declare pure virtual functions in sanitizer runtimes:
+ // __cxa_pure_virtual might be unavailable.
+ virtual char *SendCommand(bool is_data, const char *module_name,
+ uptr module_offset) {
+ UNIMPLEMENTED();
+ }
+};
+
+// SymbolizerProcess encapsulates communication between the tool and
+// external symbolizer program, running in a different subprocess.
+// SymbolizerProcess may not be used from two threads simultaneously.
+class SymbolizerProcess : public ExternalSymbolizerInterface {
public:
- explicit ExternalSymbolizer(const char *path)
+ explicit SymbolizerProcess(const char *path)
: path_(path),
input_fd_(kInvalidFd),
output_fd_(kInvalidFd),
times_restarted_(0),
- failed_to_start_(false) {
+ failed_to_start_(false),
+ reported_invalid_path_(false) {
CHECK(path_);
- CHECK_NE(path[0], '\0');
+ CHECK_NE(path_[0], '\0');
}
char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
@@ -231,16 +132,13 @@ class ExternalSymbolizer {
return 0;
}
- void Flush() {
- }
-
private:
bool Restart() {
if (input_fd_ != kInvalidFd)
internal_close(input_fd_);
if (output_fd_ != kInvalidFd)
internal_close(output_fd_);
- return StartSymbolizerSubprocess(path_, &input_fd_, &output_fd_);
+ return StartSymbolizerSubprocess();
}
char *SendCommandImpl(bool is_data, const char *module_name,
@@ -248,8 +146,9 @@ class ExternalSymbolizer {
if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd)
return 0;
CHECK(module_name);
- internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n",
- is_data ? "DATA " : "", module_name, module_offset);
+ if (!RenderInputCommand(buffer_, kBufferSize, is_data, module_name,
+ module_offset))
+ return 0;
if (!writeToSymbolizer(buffer_, internal_strlen(buffer_)))
return 0;
if (!readFromSymbolizer(buffer_, kBufferSize))
@@ -263,7 +162,7 @@ class ExternalSymbolizer {
uptr read_len = 0;
while (true) {
uptr just_read = internal_read(input_fd_, buffer + read_len,
- max_length - read_len);
+ max_length - read_len - 1);
// We can't read 0 bytes, as we don't expect external symbolizer to close
// its stdout.
if (just_read == 0 || just_read == (uptr)-1) {
@@ -271,12 +170,10 @@ class ExternalSymbolizer {
return false;
}
read_len += just_read;
- // Empty line marks the end of symbolizer output.
- if (read_len >= 2 && buffer[read_len - 1] == '\n' &&
- buffer[read_len - 2] == '\n') {
+ if (ReachedEndOfOutput(buffer, read_len))
break;
- }
}
+ buffer[read_len] = '\0';
return true;
}
@@ -291,6 +188,110 @@ class ExternalSymbolizer {
return true;
}
+ bool StartSymbolizerSubprocess() {
+ if (!FileExists(path_)) {
+ if (!reported_invalid_path_) {
+ Report("WARNING: invalid path to external symbolizer!\n");
+ reported_invalid_path_ = true;
+ }
+ return false;
+ }
+
+ int *infd = NULL;
+ int *outfd = NULL;
+ // The client program may close its stdin and/or stdout and/or stderr
+ // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
+ // In this case the communication between the forked processes may be
+ // broken if either the parent or the child tries to close or duplicate
+ // these descriptors. The loop below produces two pairs of file
+ // descriptors, each greater than 2 (stderr).
+ int sock_pair[5][2];
+ for (int i = 0; i < 5; i++) {
+ if (pipe(sock_pair[i]) == -1) {
+ for (int j = 0; j < i; j++) {
+ internal_close(sock_pair[j][0]);
+ internal_close(sock_pair[j][1]);
+ }
+ Report("WARNING: Can't create a socket pair to start "
+ "external symbolizer (errno: %d)\n", errno);
+ return false;
+ } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) {
+ if (infd == NULL) {
+ infd = sock_pair[i];
+ } else {
+ outfd = sock_pair[i];
+ for (int j = 0; j < i; j++) {
+ if (sock_pair[j] == infd) continue;
+ internal_close(sock_pair[j][0]);
+ internal_close(sock_pair[j][1]);
+ }
+ break;
+ }
+ }
+ }
+ CHECK(infd);
+ CHECK(outfd);
+
+ // Real fork() may call user callbacks registered with pthread_atfork().
+ int pid = internal_fork();
+ if (pid == -1) {
+ // Fork() failed.
+ internal_close(infd[0]);
+ internal_close(infd[1]);
+ internal_close(outfd[0]);
+ internal_close(outfd[1]);
+ Report("WARNING: failed to fork external symbolizer "
+ " (errno: %d)\n", errno);
+ return false;
+ } else if (pid == 0) {
+ // Child subprocess.
+ internal_close(STDOUT_FILENO);
+ internal_close(STDIN_FILENO);
+ internal_dup2(outfd[0], STDIN_FILENO);
+ internal_dup2(infd[1], STDOUT_FILENO);
+ internal_close(outfd[0]);
+ internal_close(outfd[1]);
+ internal_close(infd[0]);
+ internal_close(infd[1]);
+ for (int fd = getdtablesize(); fd > 2; fd--)
+ internal_close(fd);
+ ExecuteWithDefaultArgs(path_);
+ internal__exit(1);
+ }
+
+ // Continue execution in parent process.
+ internal_close(outfd[0]);
+ internal_close(infd[1]);
+ input_fd_ = infd[0];
+ output_fd_ = outfd[1];
+
+ // Check that symbolizer subprocess started successfully.
+ int pid_status;
+ SleepForMillis(kSymbolizerStartupTimeMillis);
+ int exited_pid = waitpid(pid, &pid_status, WNOHANG);
+ if (exited_pid != 0) {
+ // Either waitpid failed, or child has already exited.
+ Report("WARNING: external symbolizer didn't start up correctly!\n");
+ return false;
+ }
+
+ return true;
+ }
+
+ virtual bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
+ const char *module_name,
+ uptr module_offset) const {
+ UNIMPLEMENTED();
+ }
+
+ virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const {
+ UNIMPLEMENTED();
+ }
+
+ virtual void ExecuteWithDefaultArgs(const char *path_to_binary) const {
+ UNIMPLEMENTED();
+ }
+
const char *path_;
int input_fd_;
int output_fd_;
@@ -299,8 +300,120 @@ class ExternalSymbolizer {
char buffer_[kBufferSize];
static const uptr kMaxTimesRestarted = 5;
+ static const int kSymbolizerStartupTimeMillis = 10;
uptr times_restarted_;
bool failed_to_start_;
+ bool reported_invalid_path_;
+};
+
+// For now we assume the following protocol:
+// For each request of the form
+// <module_name> <module_offset>
+// passed to STDIN, external symbolizer prints to STDOUT response:
+// <function_name>
+// <file_name>:<line_number>:<column_number>
+// <function_name>
+// <file_name>:<line_number>:<column_number>
+// ...
+// <empty line>
+class LLVMSymbolizerProcess : public SymbolizerProcess {
+ public:
+ explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {}
+
+ private:
+ bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
+ const char *module_name, uptr module_offset) const {
+ internal_snprintf(buffer, max_length, "%s\"%s\" 0x%zx\n",
+ is_data ? "DATA " : "", module_name, module_offset);
+ return true;
+ }
+
+ bool ReachedEndOfOutput(const char *buffer, uptr length) const {
+ // Empty line marks the end of llvm-symbolizer output.
+ return length >= 2 && buffer[length - 1] == '\n' &&
+ buffer[length - 2] == '\n';
+ }
+
+ void ExecuteWithDefaultArgs(const char *path_to_binary) const {
+#if defined(__x86_64__)
+ const char* const kSymbolizerArch = "--default-arch=x86_64";
+#elif defined(__i386__)
+ const char* const kSymbolizerArch = "--default-arch=i386";
+#elif defined(__powerpc64__)
+ const char* const kSymbolizerArch = "--default-arch=powerpc64";
+#else
+ const char* const kSymbolizerArch = "--default-arch=unknown";
+#endif
+ execl(path_to_binary, path_to_binary, kSymbolizerArch, (char *)0);
+ }
+};
+
+class Addr2LineProcess : public SymbolizerProcess {
+ public:
+ Addr2LineProcess(const char *path, const char *module_name)
+ : SymbolizerProcess(path), module_name_(internal_strdup(module_name)) {}
+
+ const char *module_name() const { return module_name_; }
+
+ private:
+ bool RenderInputCommand(char *buffer, uptr max_length, bool is_data,
+ const char *module_name, uptr module_offset) const {
+ if (is_data)
+ return false;
+ CHECK_EQ(0, internal_strcmp(module_name, module_name_));
+ internal_snprintf(buffer, max_length, "0x%zx\n", module_offset);
+ return true;
+ }
+
+ bool ReachedEndOfOutput(const char *buffer, uptr length) const {
+ // Output should consist of two lines.
+ int num_lines = 0;
+ for (uptr i = 0; i < length; ++i) {
+ if (buffer[i] == '\n')
+ num_lines++;
+ if (num_lines >= 2)
+ return true;
+ }
+ return false;
+ }
+
+ void ExecuteWithDefaultArgs(const char *path_to_binary) const {
+ execl(path_to_binary, path_to_binary, "-Cfe", module_name_, (char *)0);
+ }
+
+ const char *module_name_; // Owned, leaked.
+};
+
+class Addr2LinePool : public ExternalSymbolizerInterface {
+ public:
+ explicit Addr2LinePool(const char *addr2line_path,
+ LowLevelAllocator *allocator)
+ : addr2line_path_(addr2line_path), allocator_(allocator),
+ addr2line_pool_(16) {}
+
+ char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
+ if (is_data)
+ return 0;
+ Addr2LineProcess *addr2line = 0;
+ for (uptr i = 0; i < addr2line_pool_.size(); ++i) {
+ if (0 ==
+ internal_strcmp(module_name, addr2line_pool_[i]->module_name())) {
+ addr2line = addr2line_pool_[i];
+ break;
+ }
+ }
+ if (!addr2line) {
+ addr2line =
+ new(*allocator_) Addr2LineProcess(addr2line_path_, module_name);
+ addr2line_pool_.push_back(addr2line);
+ }
+ return addr2line->SendCommand(is_data, module_name, module_offset);
+ }
+
+ private:
+ const char *addr2line_path_;
+ LowLevelAllocator *allocator_;
+ InternalMmapVector<Addr2LineProcess*> addr2line_pool_;
};
#if SANITIZER_SUPPORTS_WEAK_HOOKS
@@ -384,7 +497,7 @@ class InternalSymbolizer {
class POSIXSymbolizer : public Symbolizer {
public:
- POSIXSymbolizer(ExternalSymbolizer *external_symbolizer,
+ POSIXSymbolizer(ExternalSymbolizerInterface *external_symbolizer,
InternalSymbolizer *internal_symbolizer,
LibbacktraceSymbolizer *libbacktrace_symbolizer)
: Symbolizer(),
@@ -392,15 +505,14 @@ class POSIXSymbolizer : public Symbolizer {
internal_symbolizer_(internal_symbolizer),
libbacktrace_symbolizer_(libbacktrace_symbolizer) {}
- uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames) {
+ uptr SymbolizePC(uptr addr, AddressInfo *frames, uptr max_frames) {
BlockingMutexLock l(&mu_);
if (max_frames == 0)
return 0;
- LoadedModule *module = FindModuleForAddress(addr);
- if (module == 0)
+ const char *module_name;
+ uptr module_offset;
+ if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset))
return 0;
- const char *module_name = module->full_name();
- uptr module_offset = addr - module->base_address();
// First, try to use libbacktrace symbolizer (if it's available).
if (libbacktrace_symbolizer_ != 0) {
mu_.CheckLocked();
@@ -472,6 +584,7 @@ class POSIXSymbolizer : public Symbolizer {
info->address = addr;
info->module = internal_strdup(module_name);
info->module_offset = module_offset;
+ // First, try to use libbacktrace symbolizer (if it's available).
if (libbacktrace_symbolizer_ != 0) {
mu_.CheckLocked();
if (libbacktrace_symbolizer_->SymbolizeData(info))
@@ -487,13 +600,15 @@ class POSIXSymbolizer : public Symbolizer {
return true;
}
- bool IsAvailable() {
- return internal_symbolizer_ != 0 || external_symbolizer_ != 0 ||
- libbacktrace_symbolizer_ != 0;
+ bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
+ uptr *module_address) {
+ BlockingMutexLock l(&mu_);
+ return FindModuleNameAndOffsetForAddress(pc, module_name, module_address);
}
- bool IsExternalAvailable() {
- return external_symbolizer_ != 0;
+ bool CanReturnFileLineInfo() {
+ return internal_symbolizer_ != 0 || external_symbolizer_ != 0 ||
+ libbacktrace_symbolizer_ != 0;
}
void Flush() {
@@ -502,8 +617,6 @@ class POSIXSymbolizer : public Symbolizer {
SymbolizerScope sym_scope(this);
internal_symbolizer_->Flush();
}
- if (external_symbolizer_ != 0)
- external_symbolizer_->Flush();
}
const char *Demangle(const char *name) {
@@ -511,13 +624,13 @@ class POSIXSymbolizer : public Symbolizer {
// Run hooks even if we don't use internal symbolizer, as cxxabi
// demangle may call system functions.
SymbolizerScope sym_scope(this);
- if (internal_symbolizer_ != 0)
- return internal_symbolizer_->Demangle(name);
+ // Try to use libbacktrace demangler (if available).
if (libbacktrace_symbolizer_ != 0) {
- const char *demangled = libbacktrace_symbolizer_->Demangle(name);
- if (demangled)
- return demangled;
+ if (const char *demangled = libbacktrace_symbolizer_->Demangle(name))
+ return demangled;
}
+ if (internal_symbolizer_ != 0)
+ return internal_symbolizer_->Demangle(name);
return DemangleCXXABI(name);
}
@@ -540,6 +653,7 @@ class POSIXSymbolizer : public Symbolizer {
}
// Otherwise, fall back to external symbolizer.
if (external_symbolizer_) {
+ SymbolizerScope sym_scope(this);
return external_symbolizer_->SendCommand(is_data, module_name,
module_offset);
}
@@ -555,8 +669,7 @@ class POSIXSymbolizer : public Symbolizer {
CHECK(modules_);
n_modules_ = GetListOfModules(modules_, kMaxNumberOfModuleContexts,
/* filter */ 0);
- // FIXME: Return this check when GetListOfModules is implemented on Mac.
- // CHECK_GT(n_modules_, 0);
+ CHECK_GT(n_modules_, 0);
CHECK_LT(n_modules_, kMaxNumberOfModuleContexts);
modules_fresh_ = true;
modules_were_reloaded = true;
@@ -577,6 +690,17 @@ class POSIXSymbolizer : public Symbolizer {
return 0;
}
+ bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name,
+ uptr *module_offset) {
+ mu_.CheckLocked();
+ LoadedModule *module = FindModuleForAddress(address);
+ if (module == 0)
+ return false;
+ *module_name = module->full_name();
+ *module_offset = address - module->base_address();
+ return true;
+ }
+
// 16K loaded modules should be enough for everyone.
static const uptr kMaxNumberOfModuleContexts = 1 << 14;
LoadedModule *modules_; // Array of module descriptions is leaked.
@@ -585,27 +709,41 @@ class POSIXSymbolizer : public Symbolizer {
bool modules_fresh_;
BlockingMutex mu_;
- ExternalSymbolizer *external_symbolizer_; // Leaked.
- InternalSymbolizer *const internal_symbolizer_; // Leaked.
- LibbacktraceSymbolizer *libbacktrace_symbolizer_; // Leaked.
+ ExternalSymbolizerInterface *external_symbolizer_; // Leaked.
+ InternalSymbolizer *const internal_symbolizer_; // Leaked.
+ LibbacktraceSymbolizer *libbacktrace_symbolizer_; // Leaked.
};
Symbolizer *Symbolizer::PlatformInit(const char *path_to_external) {
+ if (!common_flags()->symbolize) {
+ return new(symbolizer_allocator_) POSIXSymbolizer(0, 0, 0);
+ }
InternalSymbolizer* internal_symbolizer =
InternalSymbolizer::get(&symbolizer_allocator_);
- ExternalSymbolizer *external_symbolizer = 0;
+ ExternalSymbolizerInterface *external_symbolizer = 0;
LibbacktraceSymbolizer *libbacktrace_symbolizer = 0;
if (!internal_symbolizer) {
libbacktrace_symbolizer =
LibbacktraceSymbolizer::get(&symbolizer_allocator_);
if (!libbacktrace_symbolizer) {
- // Find path to llvm-symbolizer if it's not provided.
- if (!path_to_external)
- path_to_external = FindPathToBinary("llvm-symbolizer");
- if (path_to_external && path_to_external[0] != '\0')
- external_symbolizer = new(symbolizer_allocator_)
- ExternalSymbolizer(path_to_external);
+ if (path_to_external && path_to_external[0] == '\0') {
+ // External symbolizer is explicitly disabled. Do nothing.
+ } else {
+ // Find path to llvm-symbolizer if it's not provided.
+ if (!path_to_external)
+ path_to_external = FindPathToBinary("llvm-symbolizer");
+ if (path_to_external) {
+ external_symbolizer = new(symbolizer_allocator_)
+ LLVMSymbolizerProcess(path_to_external);
+ } else if (common_flags()->allow_addr2line) {
+ // If llvm-symbolizer is not found, try to use addr2line.
+ if (const char *addr2line_path = FindPathToBinary("addr2line")) {
+ external_symbolizer = new(symbolizer_allocator_)
+ Addr2LinePool(addr2line_path, &symbolizer_allocator_);
+ }
+ }
+ }
}
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc
index 446de8af293..c014c6af42b 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc
@@ -12,11 +12,96 @@
#include "sanitizer_platform.h"
#if SANITIZER_WINDOWS
+#include <windows.h>
+#include <dbghelp.h>
+#pragma comment(lib, "dbghelp.lib")
+
#include "sanitizer_symbolizer.h"
namespace __sanitizer {
-Symbolizer *Symbolizer::PlatformInit(const char *path_to_external) { return 0; }
+class WinSymbolizer : public Symbolizer {
+ public:
+ WinSymbolizer() : initialized_(false) {}
+
+ uptr SymbolizePC(uptr addr, AddressInfo *frames, uptr max_frames) {
+ if (max_frames == 0)
+ return 0;
+
+ BlockingMutexLock l(&dbghelp_mu_);
+ if (!initialized_) {
+ SymSetOptions(SYMOPT_DEFERRED_LOADS |
+ SYMOPT_UNDNAME |
+ SYMOPT_LOAD_LINES);
+ CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE));
+ // FIXME: We don't call SymCleanup() on exit yet - should we?
+ initialized_ = true;
+ }
+
+ // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
+ char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)];
+ PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
+ symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+ symbol->MaxNameLen = MAX_SYM_NAME;
+ DWORD64 offset = 0;
+ BOOL got_objname = SymFromAddr(GetCurrentProcess(),
+ (DWORD64)addr, &offset, symbol);
+ if (!got_objname)
+ return 0;
+
+ DWORD unused;
+ IMAGEHLP_LINE64 line_info;
+ line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+ BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)addr,
+ &unused, &line_info);
+ AddressInfo *info = &frames[0];
+ info->Clear();
+ info->function = internal_strdup(symbol->Name);
+ info->function_offset = (uptr)offset;
+ if (got_fileline) {
+ info->file = internal_strdup(line_info.FileName);
+ info->line = line_info.LineNumber;
+ }
+
+ IMAGEHLP_MODULE64 mod_info;
+ internal_memset(&mod_info, 0, sizeof(mod_info));
+ mod_info.SizeOfStruct = sizeof(mod_info);
+ if (SymGetModuleInfo64(GetCurrentProcess(), addr, &mod_info))
+ info->FillAddressAndModuleInfo(addr, mod_info.ImageName,
+ addr - (uptr)mod_info.BaseOfImage);
+ return 1;
+ }
+
+ bool CanReturnFileLineInfo() {
+ return true;
+ }
+
+ const char *Demangle(const char *name) {
+ CHECK(initialized_);
+ static char demangle_buffer[1000];
+ if (name[0] == '\01' &&
+ UnDecorateSymbolName(name + 1, demangle_buffer, sizeof(demangle_buffer),
+ UNDNAME_NAME_ONLY))
+ return demangle_buffer;
+ else
+ return name;
+ }
+
+ // FIXME: Implement GetModuleNameAndOffsetForPC().
+
+ private:
+ // All DbgHelp functions are single threaded, so we should use a mutex to
+ // serialize accesses.
+ BlockingMutex dbghelp_mu_;
+ bool initialized_;
+};
+
+Symbolizer *Symbolizer::PlatformInit(const char *path_to_external) {
+ static bool called_once = false;
+ CHECK(!called_once && "Shouldn't create more than one symbolizer");
+ called_once = true;
+ return new(symbolizer_allocator_) WinSymbolizer();
+}
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_syscall_generic.inc b/libsanitizer/sanitizer_common/sanitizer_syscall_generic.inc
index 6b2c915a3bc..7667b753a8b 100644
--- a/libsanitizer/sanitizer_common/sanitizer_syscall_generic.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_syscall_generic.inc
@@ -9,7 +9,17 @@
//
//===----------------------------------------------------------------------===//
-#define internal_syscall syscall
+#if SANITIZER_FREEBSD
+# define SYSCALL(name) SYS_ ## name
+#else
+# define SYSCALL(name) __NR_ ## name
+#endif
+
+#if SANITIZER_FREEBSD && defined(__x86_64__)
+# define internal_syscall __syscall
+# else
+# define internal_syscall syscall
+#endif
bool internal_iserror(uptr retval, int *rverrno) {
if (retval == (uptr)-1) {
diff --git a/libsanitizer/sanitizer_common/sanitizer_syscall_linux_x86_64.inc b/libsanitizer/sanitizer_common/sanitizer_syscall_linux_x86_64.inc
index 8810c7faa4b..b610d66be4f 100644
--- a/libsanitizer/sanitizer_common/sanitizer_syscall_linux_x86_64.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_syscall_linux_x86_64.inc
@@ -9,6 +9,8 @@
//
//===----------------------------------------------------------------------===//
+#define SYSCALL(name) __NR_ ## name
+
static uptr internal_syscall(u64 nr) {
u64 retval;
asm volatile("syscall" : "=a"(retval) : "a"(nr) : "rcx", "r11",
diff --git a/libsanitizer/sanitizer_common/sanitizer_thread_registry.cc b/libsanitizer/sanitizer_common/sanitizer_thread_registry.cc
index 666955f6c9a..0ad47561b8b 100644
--- a/libsanitizer/sanitizer_common/sanitizer_thread_registry.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_thread_registry.cc
@@ -15,8 +15,9 @@
namespace __sanitizer {
ThreadContextBase::ThreadContextBase(u32 tid)
- : tid(tid), unique_id(0), os_id(0), user_id(0), status(ThreadStatusInvalid),
- detached(false), reuse_count(0), parent_tid(0), next(0) {
+ : tid(tid), unique_id(0), reuse_count(), os_id(0), user_id(0),
+ status(ThreadStatusInvalid),
+ detached(false), parent_tid(0), next(0) {
name[0] = '\0';
}
@@ -76,7 +77,6 @@ void ThreadContextBase::SetCreated(uptr _user_id, u64 _unique_id,
void ThreadContextBase::Reset() {
status = ThreadStatusInvalid;
- reuse_count++;
SetName(0);
OnReset();
}
@@ -86,10 +86,11 @@ void ThreadContextBase::Reset() {
const u32 ThreadRegistry::kUnknownTid = ~0U;
ThreadRegistry::ThreadRegistry(ThreadContextFactory factory, u32 max_threads,
- u32 thread_quarantine_size)
+ u32 thread_quarantine_size, u32 max_reuse)
: context_factory_(factory),
max_threads_(max_threads),
thread_quarantine_size_(thread_quarantine_size),
+ max_reuse_(max_reuse),
mtx_(),
n_contexts_(0),
total_threads_(0),
@@ -128,8 +129,13 @@ u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,
tctx = context_factory_(tid);
threads_[tid] = tctx;
} else {
+#ifndef SANITIZER_GO
Report("%s: Thread limit (%u threads) exceeded. Dying.\n",
SanitizerToolName, max_threads_);
+#else
+ Printf("race: limit on %u simultaneously alive goroutines is exceeded,"
+ " dying\n", max_threads_);
+#endif
Die();
}
CHECK_NE(tctx, 0);
@@ -275,6 +281,9 @@ void ThreadRegistry::QuarantinePush(ThreadContextBase *tctx) {
dead_threads_.pop_front();
CHECK_EQ(tctx->status, ThreadStatusDead);
tctx->Reset();
+ tctx->reuse_count++;
+ if (max_reuse_ > 0 && tctx->reuse_count >= max_reuse_)
+ return;
invalid_threads_.push_back(tctx);
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_thread_registry.h b/libsanitizer/sanitizer_common/sanitizer_thread_registry.h
index 81c270945d3..2d7f9e90e0d 100644
--- a/libsanitizer/sanitizer_common/sanitizer_thread_registry.h
+++ b/libsanitizer/sanitizer_common/sanitizer_thread_registry.h
@@ -36,13 +36,13 @@ class ThreadContextBase {
const u32 tid; // Thread ID. Main thread should have tid = 0.
u64 unique_id; // Unique thread ID.
+ u32 reuse_count; // Number of times this tid was reused.
uptr os_id; // PID (used for reporting).
uptr user_id; // Some opaque user thread id (e.g. pthread_t).
char name[64]; // As annotated by user.
ThreadStatus status;
bool detached;
- int reuse_count;
u32 parent_tid;
ThreadContextBase *next; // For storing thread contexts in a list.
@@ -75,7 +75,7 @@ class ThreadRegistry {
static const u32 kUnknownTid;
ThreadRegistry(ThreadContextFactory factory, u32 max_threads,
- u32 thread_quarantine_size);
+ u32 thread_quarantine_size, u32 max_reuse = 0);
void GetNumberOfThreads(uptr *total = 0, uptr *running = 0, uptr *alive = 0);
uptr GetMaxAliveThreads();
@@ -117,6 +117,7 @@ class ThreadRegistry {
const ThreadContextFactory context_factory_;
const u32 max_threads_;
const u32 thread_quarantine_size_;
+ const u32 max_reuse_;
BlockingMutex mtx_;
diff --git a/libsanitizer/sanitizer_common/sanitizer_tls_get_addr.cc b/libsanitizer/sanitizer_common/sanitizer_tls_get_addr.cc
new file mode 100644
index 00000000000..1d6170f9157
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_tls_get_addr.cc
@@ -0,0 +1,129 @@
+//===-- sanitizer_tls_get_addr.cc -----------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Handle the __tls_get_addr call.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_tls_get_addr.h"
+
+#include "sanitizer_flags.h"
+#include "sanitizer_platform_interceptors.h"
+
+namespace __sanitizer {
+#if SANITIZER_INTERCEPT_TLS_GET_ADDR
+
+// The actual parameter that comes to __tls_get_addr
+// is a pointer to a struct with two words in it:
+struct TlsGetAddrParam {
+ uptr dso_id;
+ uptr offset;
+};
+
+// Glibc starting from 2.19 allocates tls using __signal_safe_memalign,
+// which has such header.
+struct Glibc_2_19_tls_header {
+ uptr size;
+ uptr start;
+};
+
+// This must be static TLS
+__attribute__((tls_model("initial-exec")))
+static __thread DTLS dtls;
+
+// Make sure we properly destroy the DTLS objects:
+// this counter should never get too large.
+static atomic_uintptr_t number_of_live_dtls;
+
+static const uptr kDestroyedThread = -1;
+
+static inline void DTLS_Deallocate(DTLS::DTV *dtv, uptr size) {
+ if (!size) return;
+ VPrintf(2, "__tls_get_addr: DTLS_Deallocate %p %zd\n", dtv, size);
+ UnmapOrDie(dtv, size * sizeof(DTLS::DTV));
+ atomic_fetch_sub(&number_of_live_dtls, 1, memory_order_relaxed);
+}
+
+static inline void DTLS_Resize(uptr new_size) {
+ if (dtls.dtv_size >= new_size) return;
+ new_size = RoundUpToPowerOfTwo(new_size);
+ new_size = Max(new_size, 4096UL / sizeof(DTLS::DTV));
+ DTLS::DTV *new_dtv =
+ (DTLS::DTV *)MmapOrDie(new_size * sizeof(DTLS::DTV), "DTLS_Resize");
+ uptr num_live_dtls =
+ atomic_fetch_add(&number_of_live_dtls, 1, memory_order_relaxed);
+ VPrintf(2, "__tls_get_addr: DTLS_Resize %p %zd\n", &dtls, num_live_dtls);
+ CHECK_LT(num_live_dtls, 1 << 20);
+ uptr old_dtv_size = dtls.dtv_size;
+ DTLS::DTV *old_dtv = dtls.dtv;
+ if (old_dtv_size)
+ internal_memcpy(new_dtv, dtls.dtv, dtls.dtv_size * sizeof(DTLS::DTV));
+ dtls.dtv = new_dtv;
+ dtls.dtv_size = new_size;
+ if (old_dtv_size)
+ DTLS_Deallocate(old_dtv, old_dtv_size);
+}
+
+void DTLS_Destroy() {
+ if (!common_flags()->intercept_tls_get_addr) return;
+ VPrintf(2, "__tls_get_addr: DTLS_Destroy %p %zd\n", &dtls, dtls.dtv_size);
+ uptr s = dtls.dtv_size;
+ dtls.dtv_size = kDestroyedThread; // Do this before unmap for AS-safety.
+ DTLS_Deallocate(dtls.dtv, s);
+}
+
+void DTLS_on_tls_get_addr(void *arg_void, void *res) {
+ if (!common_flags()->intercept_tls_get_addr) return;
+ TlsGetAddrParam *arg = reinterpret_cast<TlsGetAddrParam *>(arg_void);
+ uptr dso_id = arg->dso_id;
+ if (dtls.dtv_size == kDestroyedThread) return;
+ DTLS_Resize(dso_id + 1);
+ if (dtls.dtv[dso_id].beg)
+ return;
+ uptr tls_size = 0;
+ uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset;
+ VPrintf(2, "__tls_get_addr: %p {%p,%p} => %p; tls_beg: %p; sp: %p "
+ "num_live_dtls %zd\n",
+ arg, arg->dso_id, arg->offset, res, tls_beg, &tls_beg,
+ atomic_load(&number_of_live_dtls, memory_order_relaxed));
+ if (dtls.last_memalign_ptr == tls_beg) {
+ tls_size = dtls.last_memalign_size;
+ VPrintf(2, "__tls_get_addr: glibc <=2.18 suspected; tls={%p,%p}\n",
+ tls_beg, tls_size);
+ } else if ((tls_beg % 4096) == sizeof(Glibc_2_19_tls_header)) {
+ // We may want to check gnu_get_libc_version().
+ Glibc_2_19_tls_header *header = (Glibc_2_19_tls_header *)tls_beg - 1;
+ tls_size = header->size;
+ tls_beg = header->start;
+ VPrintf(2, "__tls_get_addr: glibc >=2.19 suspected; tls={%p %p}\n",
+ tls_beg, tls_size);
+ } else {
+ VPrintf(2, "__tls_get_addr: Can't guess glibc version\n");
+ // This may happen inside the DTOR of main thread, so just ignore it.
+ tls_size = 0;
+ }
+ dtls.dtv[dso_id].beg = tls_beg;
+ dtls.dtv[dso_id].size = tls_size;
+}
+
+void DTLS_on_libc_memalign(void *ptr, uptr size) {
+ if (!common_flags()->intercept_tls_get_addr) return;
+ VPrintf(2, "DTLS_on_libc_memalign: %p %p\n", ptr, size);
+ dtls.last_memalign_ptr = reinterpret_cast<uptr>(ptr);
+ dtls.last_memalign_size = size;
+}
+
+DTLS *DTLS_Get() { return &dtls; }
+
+#else
+void DTLS_on_libc_memalign(void *ptr, uptr size) {}
+void DTLS_on_tls_get_addr(void *arg, void *res) {}
+DTLS *DTLS_Get() { return 0; }
+void DTLS_Destroy() {}
+#endif // SANITIZER_INTERCEPT_TLS_GET_ADDR
+
+} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_tls_get_addr.h b/libsanitizer/sanitizer_common/sanitizer_tls_get_addr.h
new file mode 100644
index 00000000000..22a5e1c41c2
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_tls_get_addr.h
@@ -0,0 +1,56 @@
+//===-- sanitizer_tls_get_addr.h --------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Handle the __tls_get_addr call.
+//
+// All this magic is specific to glibc and is required to workaround
+// the lack of interface that would tell us about the Dynamic TLS (DTLS).
+// https://sourceware.org/bugzilla/show_bug.cgi?id=16291
+//
+// The matters get worse because the glibc implementation changed between
+// 2.18 and 2.19:
+// https://groups.google.com/forum/#!topic/address-sanitizer/BfwYD8HMxTM
+//
+// Before 2.19, every DTLS chunk is allocated with __libc_memalign,
+// which we intercept and thus know where is the DTLS.
+// Since 2.19, DTLS chunks are allocated with __signal_safe_memalign,
+// which is an internal function that wraps a mmap call, neither of which
+// we can intercept. Luckily, __signal_safe_memalign has a simple parseable
+// header which we can use.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_TLS_GET_ADDR_H
+#define SANITIZER_TLS_GET_ADDR_H
+
+#include "sanitizer_common.h"
+
+namespace __sanitizer {
+
+struct DTLS {
+ // Array of DTLS chunks for the current Thread.
+ // If beg == 0, the chunk is unused.
+ struct DTV {
+ uptr beg, size;
+ };
+
+ uptr dtv_size;
+ DTV *dtv; // dtv_size elements, allocated by MmapOrDie.
+
+ // Auxiliary fields, don't access them outside sanitizer_tls_get_addr.cc
+ uptr last_memalign_size;
+ uptr last_memalign_ptr;
+};
+
+void DTLS_on_tls_get_addr(void *arg, void *res);
+void DTLS_on_libc_memalign(void *ptr, uptr size);
+DTLS *DTLS_Get();
+void DTLS_Destroy(); // Make sure to call this before the thread is destroyed.
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_TLS_GET_ADDR_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_win.cc b/libsanitizer/sanitizer_common/sanitizer_win.cc
index c48274e3642..6065838cefe 100644
--- a/libsanitizer/sanitizer_common/sanitizer_win.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_win.cc
@@ -78,8 +78,9 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
void *MmapOrDie(uptr size, const char *mem_type) {
void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (rv == 0) {
- Report("ERROR: Failed to allocate 0x%zx (%zd) bytes of %s\n",
- size, size, mem_type);
+ Report("ERROR: %s failed to "
+ "allocate 0x%zx (%zd) bytes of %s (error code: %d)\n",
+ SanitizerToolName, size, size, mem_type, GetLastError());
CHECK("unable to mmap" && 0);
}
return rv;
@@ -87,8 +88,9 @@ void *MmapOrDie(uptr size, const char *mem_type) {
void UnmapOrDie(void *addr, uptr size) {
if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) {
- Report("ERROR: Failed to deallocate 0x%zx (%zd) bytes at address %p\n",
- size, size, addr);
+ Report("ERROR: %s failed to "
+ "deallocate 0x%zx (%zd) bytes at address %p (error code: %d)\n",
+ SanitizerToolName, size, size, addr, GetLastError());
CHECK("unable to unmap" && 0);
}
}
@@ -99,8 +101,9 @@ void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
void *p = VirtualAlloc((LPVOID)fixed_addr, size,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (p == 0)
- Report("ERROR: Failed to allocate 0x%zx (%zd) bytes at %p (%d)\n",
- size, size, fixed_addr, GetLastError());
+ Report("ERROR: %s failed to "
+ "allocate %p (%zd) bytes at %p (error code: %d)\n",
+ SanitizerToolName, size, size, fixed_addr, GetLastError());
return p;
}
@@ -108,6 +111,11 @@ void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
return MmapFixedNoReserve(fixed_addr, size);
}
+void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
+ // FIXME: make this really NoReserve?
+ return MmapOrDie(size, mem_type);
+}
+
void *Mprotect(uptr fixed_addr, uptr size) {
return VirtualAlloc((LPVOID)fixed_addr, size,
MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
@@ -175,14 +183,15 @@ void DumpProcessMap() {
}
void DisableCoreDumper() {
- UNIMPLEMENTED();
+ // Do nothing.
}
void ReExec() {
UNIMPLEMENTED();
}
-void PrepareForSandboxing() {
+void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
+ (void)args;
// Nothing here for now.
}
@@ -264,13 +273,48 @@ uptr internal_read(fd_t fd, void *buf, uptr count) {
uptr internal_write(fd_t fd, const void *buf, uptr count) {
if (fd != kStderrFd)
UNIMPLEMENTED();
- HANDLE err = GetStdHandle(STD_ERROR_HANDLE);
- if (err == 0)
- return 0; // FIXME: this might not work on some apps.
- DWORD ret;
- if (!WriteFile(err, buf, count, &ret, 0))
+
+ static HANDLE output_stream = 0;
+ // Abort immediately if we know printing is not possible.
+ if (output_stream == INVALID_HANDLE_VALUE)
return 0;
- return ret;
+
+ // If called for the first time, try to use stderr to output stuff,
+ // falling back to stdout if anything goes wrong.
+ bool fallback_to_stdout = false;
+ if (output_stream == 0) {
+ output_stream = GetStdHandle(STD_ERROR_HANDLE);
+ // We don't distinguish "no such handle" from error.
+ if (output_stream == 0)
+ output_stream = INVALID_HANDLE_VALUE;
+
+ if (output_stream == INVALID_HANDLE_VALUE) {
+ // Retry with stdout?
+ output_stream = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (output_stream == 0)
+ output_stream = INVALID_HANDLE_VALUE;
+ if (output_stream == INVALID_HANDLE_VALUE)
+ return 0;
+ } else {
+ // Successfully got an stderr handle. However, if WriteFile() fails,
+ // we can still try to fallback to stdout.
+ fallback_to_stdout = true;
+ }
+ }
+
+ DWORD ret;
+ if (WriteFile(output_stream, buf, count, &ret, 0))
+ return ret;
+
+ // Re-try with stdout if using a valid stderr handle fails.
+ if (fallback_to_stdout) {
+ output_stream = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (output_stream == 0)
+ output_stream = INVALID_HANDLE_VALUE;
+ if (output_stream != INVALID_HANDLE_VALUE)
+ return internal_write(fd, buf, count);
+ }
+ return 0;
}
uptr internal_stat(const char *path, void *buf) {
@@ -375,16 +419,25 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
}
void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
+ CHECK_GE(max_depth, 2);
// FIXME: CaptureStackBackTrace might be too slow for us.
// FIXME: Compare with StackWalk64.
// FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
size = CaptureStackBackTrace(2, Min(max_depth, kStackTraceMax),
(void**)trace, 0);
+ if (size == 0)
+ return;
+
// Skip the RTL frames by searching for the PC in the stacktrace.
uptr pc_location = LocatePcInTrace(pc);
PopStackFrames(pc_location);
}
+void StackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
+ uptr max_depth) {
+ UNREACHABLE("no signal context on windows");
+}
+
void MaybeOpenReportFile() {
// Windows doesn't have native fork, and we don't support Cygwin or other
// environments that try to fake it, so the initial report_fd will always be
@@ -392,8 +445,6 @@ void MaybeOpenReportFile() {
}
void RawWrite(const char *buffer) {
- static const char *kRawWriteError =
- "RawWrite can't output requested buffer!\n";
uptr length = (uptr)internal_strlen(buffer);
if (length != internal_write(report_fd, buffer, length)) {
// stderr may be closed, but we may be able to print to the debugger
@@ -403,6 +454,24 @@ void RawWrite(const char *buffer) {
}
}
+void SetAlternateSignalStack() {
+ // FIXME: Decide what to do on Windows.
+}
+
+void UnsetAlternateSignalStack() {
+ // FIXME: Decide what to do on Windows.
+}
+
+void InstallDeadlySignalHandlers(SignalHandlerType handler) {
+ (void)handler;
+ // FIXME: Decide what to do on Windows.
+}
+
+bool IsDeadlySignal(int signum) {
+ // FIXME: Decide what to do on Windows.
+ return false;
+}
+
} // namespace __sanitizer
#endif // _WIN32
diff --git a/libsanitizer/tsan/Makefile.am b/libsanitizer/tsan/Makefile.am
index 39ed2529c2c..5d98e215e05 100644
--- a/libsanitizer/tsan/Makefile.am
+++ b/libsanitizer/tsan/Makefile.am
@@ -11,32 +11,32 @@ ACLOCAL_AMFLAGS = -I m4
toolexeclib_LTLIBRARIES = libtsan.la
tsan_files = \
- tsan_clock.cc \
- tsan_interface_atomic.cc \
- tsan_mutex.cc \
- tsan_report.cc \
- tsan_rtl_thread.cc \
- tsan_symbolize.cc \
- tsan_flags.cc \
- tsan_interface.cc \
- tsan_platform_linux.cc \
- tsan_rtl.cc \
- tsan_stat.cc \
- tsan_sync.cc \
- tsan_ignoreset.cc \
- tsan_interceptors.cc \
- tsan_md5.cc \
- tsan_platform_mac.cc \
- tsan_rtl_mutex.cc \
- tsan_suppressions.cc \
- tsan_interface_ann.cc \
- tsan_mman.cc \
- tsan_rtl_report.cc \
+ tsan_clock.cc \
tsan_fd.cc \
- tsan_interface_java.cc \
- tsan_mutexset.cc \
- tsan_symbolize_addr2line_linux.cc \
- tsan_rtl_amd64.S
+ tsan_flags.cc \
+ tsan_ignoreset.cc \
+ tsan_interceptors.cc \
+ tsan_interface_ann.cc \
+ tsan_interface_atomic.cc \
+ tsan_interface.cc \
+ tsan_interface_java.cc \
+ tsan_md5.cc \
+ tsan_mman.cc \
+ tsan_mutex.cc \
+ tsan_mutexset.cc \
+ tsan_platform_linux.cc \
+ tsan_platform_mac.cc \
+ tsan_platform_windows.cc \
+ tsan_report.cc \
+ tsan_rtl.cc \
+ tsan_rtl_mutex.cc \
+ tsan_rtl_report.cc \
+ tsan_rtl_thread.cc \
+ tsan_stat.cc \
+ tsan_suppressions.cc \
+ tsan_symbolize.cc \
+ tsan_sync.cc \
+ tsan_rtl_amd64.S
libtsan_la_SOURCES = $(tsan_files)
libtsan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la
diff --git a/libsanitizer/tsan/Makefile.in b/libsanitizer/tsan/Makefile.in
index 01c27b9b7d4..068aaa87fe8 100644
--- a/libsanitizer/tsan/Makefile.in
+++ b/libsanitizer/tsan/Makefile.in
@@ -84,15 +84,15 @@ libtsan_la_DEPENDENCIES = \
$(top_builddir)/sanitizer_common/libsanitizer_common.la \
$(top_builddir)/interception/libinterception.la \
$(am__append_1) $(am__DEPENDENCIES_1)
-am__objects_1 = tsan_clock.lo tsan_interface_atomic.lo tsan_mutex.lo \
- tsan_report.lo tsan_rtl_thread.lo tsan_symbolize.lo \
- tsan_flags.lo tsan_interface.lo tsan_platform_linux.lo \
- tsan_rtl.lo tsan_stat.lo tsan_sync.lo tsan_ignoreset.lo \
- tsan_interceptors.lo tsan_md5.lo tsan_platform_mac.lo \
- tsan_rtl_mutex.lo tsan_suppressions.lo tsan_interface_ann.lo \
- tsan_mman.lo tsan_rtl_report.lo tsan_fd.lo \
- tsan_interface_java.lo tsan_mutexset.lo \
- tsan_symbolize_addr2line_linux.lo tsan_rtl_amd64.lo
+am__objects_1 = tsan_clock.lo tsan_fd.lo tsan_flags.lo \
+ tsan_ignoreset.lo tsan_interceptors.lo tsan_interface_ann.lo \
+ tsan_interface_atomic.lo tsan_interface.lo \
+ tsan_interface_java.lo tsan_md5.lo tsan_mman.lo tsan_mutex.lo \
+ tsan_mutexset.lo tsan_platform_linux.lo tsan_platform_mac.lo \
+ tsan_platform_windows.lo tsan_report.lo tsan_rtl.lo \
+ tsan_rtl_mutex.lo tsan_rtl_report.lo tsan_rtl_thread.lo \
+ tsan_stat.lo tsan_suppressions.lo tsan_symbolize.lo \
+ tsan_sync.lo tsan_rtl_amd64.lo
am_libtsan_la_OBJECTS = $(am__objects_1)
libtsan_la_OBJECTS = $(am_libtsan_la_OBJECTS)
libtsan_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
@@ -280,32 +280,32 @@ AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic \
ACLOCAL_AMFLAGS = -I m4
toolexeclib_LTLIBRARIES = libtsan.la
tsan_files = \
- tsan_clock.cc \
- tsan_interface_atomic.cc \
- tsan_mutex.cc \
- tsan_report.cc \
- tsan_rtl_thread.cc \
- tsan_symbolize.cc \
- tsan_flags.cc \
- tsan_interface.cc \
- tsan_platform_linux.cc \
- tsan_rtl.cc \
- tsan_stat.cc \
- tsan_sync.cc \
- tsan_ignoreset.cc \
- tsan_interceptors.cc \
- tsan_md5.cc \
- tsan_platform_mac.cc \
- tsan_rtl_mutex.cc \
- tsan_suppressions.cc \
- tsan_interface_ann.cc \
- tsan_mman.cc \
- tsan_rtl_report.cc \
+ tsan_clock.cc \
tsan_fd.cc \
- tsan_interface_java.cc \
- tsan_mutexset.cc \
- tsan_symbolize_addr2line_linux.cc \
- tsan_rtl_amd64.S
+ tsan_flags.cc \
+ tsan_ignoreset.cc \
+ tsan_interceptors.cc \
+ tsan_interface_ann.cc \
+ tsan_interface_atomic.cc \
+ tsan_interface.cc \
+ tsan_interface_java.cc \
+ tsan_md5.cc \
+ tsan_mman.cc \
+ tsan_mutex.cc \
+ tsan_mutexset.cc \
+ tsan_platform_linux.cc \
+ tsan_platform_mac.cc \
+ tsan_platform_windows.cc \
+ tsan_report.cc \
+ tsan_rtl.cc \
+ tsan_rtl_mutex.cc \
+ tsan_rtl_report.cc \
+ tsan_rtl_thread.cc \
+ tsan_stat.cc \
+ tsan_suppressions.cc \
+ tsan_symbolize.cc \
+ tsan_sync.cc \
+ tsan_rtl_amd64.S
libtsan_la_SOURCES = $(tsan_files)
libtsan_la_LIBADD = \
@@ -442,6 +442,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_mutexset.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_platform_linux.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_platform_mac.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_platform_windows.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_report.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_amd64.Plo@am__quote@
@@ -451,7 +452,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_stat.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_suppressions.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_symbolize.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_symbolize_addr2line_linux.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_sync.Plo@am__quote@
.S.o:
diff --git a/libsanitizer/tsan/tsan_clock.cc b/libsanitizer/tsan/tsan_clock.cc
index 5d45a5d15fb..b944cc50d54 100644
--- a/libsanitizer/tsan/tsan_clock.cc
+++ b/libsanitizer/tsan/tsan_clock.cc
@@ -11,99 +11,338 @@
#include "tsan_clock.h"
#include "tsan_rtl.h"
-// It's possible to optimize clock operations for some important cases
-// so that they are O(1). The cases include singletons, once's, local mutexes.
-// First, SyncClock must be re-implemented to allow indexing by tid.
-// It must not necessarily be a full vector clock, though. For example it may
-// be a multi-level table.
-// Then, each slot in SyncClock must contain a dirty bit (it's united with
-// the clock value, so no space increase). The acquire algorithm looks
-// as follows:
-// void acquire(thr, tid, thr_clock, sync_clock) {
-// if (!sync_clock[tid].dirty)
-// return; // No new info to acquire.
-// // This handles constant reads of singleton pointers and
-// // stop-flags.
-// acquire_impl(thr_clock, sync_clock); // As usual, O(N).
-// sync_clock[tid].dirty = false;
-// sync_clock.dirty_count--;
-// }
-// The release operation looks as follows:
-// void release(thr, tid, thr_clock, sync_clock) {
-// // thr->sync_cache is a simple fixed-size hash-based cache that holds
-// // several previous sync_clock's.
-// if (thr->sync_cache[sync_clock] >= thr->last_acquire_epoch) {
-// // The thread did no acquire operations since last release on this clock.
-// // So update only the thread's slot (other slots can't possibly change).
-// sync_clock[tid].clock = thr->epoch;
-// if (sync_clock.dirty_count == sync_clock.cnt
-// || (sync_clock.dirty_count == sync_clock.cnt - 1
-// && sync_clock[tid].dirty == false))
-// // All dirty flags are set, bail out.
-// return;
-// set all dirty bits, but preserve the thread's bit. // O(N)
-// update sync_clock.dirty_count;
-// return;
+// SyncClock and ThreadClock implement vector clocks for sync variables
+// (mutexes, atomic variables, file descriptors, etc) and threads, respectively.
+// ThreadClock contains fixed-size vector clock for maximum number of threads.
+// SyncClock contains growable vector clock for currently necessary number of
+// threads.
+// Together they implement very simple model of operations, namely:
+//
+// void ThreadClock::acquire(const SyncClock *src) {
+// for (int i = 0; i < kMaxThreads; i++)
+// clock[i] = max(clock[i], src->clock[i]);
+// }
+//
+// void ThreadClock::release(SyncClock *dst) const {
+// for (int i = 0; i < kMaxThreads; i++)
+// dst->clock[i] = max(dst->clock[i], clock[i]);
+// }
+//
+// void ThreadClock::ReleaseStore(SyncClock *dst) const {
+// for (int i = 0; i < kMaxThreads; i++)
+// dst->clock[i] = clock[i];
+// }
+//
+// void ThreadClock::acq_rel(SyncClock *dst) {
+// acquire(dst);
+// release(dst);
// }
-// release_impl(thr_clock, sync_clock); // As usual, O(N).
-// set all dirty bits, but preserve the thread's bit.
-// // The previous step is combined with release_impl(), so that
-// // we scan the arrays only once.
-// update sync_clock.dirty_count;
-// }
+//
+// Conformance to this model is extensively verified in tsan_clock_test.cc.
+// However, the implementation is significantly more complex. The complexity
+// allows to implement important classes of use cases in O(1) instead of O(N).
+//
+// The use cases are:
+// 1. Singleton/once atomic that has a single release-store operation followed
+// by zillions of acquire-loads (the acquire-load is O(1)).
+// 2. Thread-local mutex (both lock and unlock can be O(1)).
+// 3. Leaf mutex (unlock is O(1)).
+// 4. A mutex shared by 2 threads (both lock and unlock can be O(1)).
+// 5. An atomic with a single writer (writes can be O(1)).
+// The implementation dynamically adopts to workload. So if an atomic is in
+// read-only phase, these reads will be O(1); if it later switches to read/write
+// phase, the implementation will correctly handle that by switching to O(N).
+//
+// Thread-safety note: all const operations on SyncClock's are conducted under
+// a shared lock; all non-const operations on SyncClock's are conducted under
+// an exclusive lock; ThreadClock's are private to respective threads and so
+// do not need any protection.
+//
+// Description of ThreadClock state:
+// clk_ - fixed size vector clock.
+// nclk_ - effective size of the vector clock (the rest is zeros).
+// tid_ - index of the thread associated with he clock ("current thread").
+// last_acquire_ - current thread time when it acquired something from
+// other threads.
+//
+// Description of SyncClock state:
+// clk_ - variable size vector clock, low kClkBits hold timestamp,
+// the remaining bits hold "acquired" flag (the actual value is thread's
+// reused counter);
+// if acquried == thr->reused_, then the respective thread has already
+// acquired this clock (except possibly dirty_tids_).
+// dirty_tids_ - holds up to two indeces in the vector clock that other threads
+// need to acquire regardless of "acquired" flag value;
+// release_store_tid_ - denotes that the clock state is a result of
+// release-store operation by the thread with release_store_tid_ index.
+// release_store_reused_ - reuse count of release_store_tid_.
+
+// We don't have ThreadState in these methods, so this is an ugly hack that
+// works only in C++.
+#ifndef TSAN_GO
+# define CPP_STAT_INC(typ) StatInc(cur_thread(), typ)
+#else
+# define CPP_STAT_INC(typ) (void)0
+#endif
namespace __tsan {
-ThreadClock::ThreadClock() {
- nclk_ = 0;
- for (uptr i = 0; i < (uptr)kMaxTidInClock; i++)
- clk_[i] = 0;
+const unsigned kInvalidTid = (unsigned)-1;
+
+ThreadClock::ThreadClock(unsigned tid, unsigned reused)
+ : tid_(tid)
+ , reused_(reused + 1) { // 0 has special meaning
+ CHECK_LT(tid, kMaxTidInClock);
+ CHECK_EQ(reused_, ((u64)reused_ << kClkBits) >> kClkBits);
+ nclk_ = tid_ + 1;
+ last_acquire_ = 0;
+ internal_memset(clk_, 0, sizeof(clk_));
+ clk_[tid_].reused = reused_;
}
void ThreadClock::acquire(const SyncClock *src) {
DCHECK(nclk_ <= kMaxTid);
DCHECK(src->clk_.Size() <= kMaxTid);
+ CPP_STAT_INC(StatClockAcquire);
+ // Check if it's empty -> no need to do anything.
const uptr nclk = src->clk_.Size();
- if (nclk == 0)
+ if (nclk == 0) {
+ CPP_STAT_INC(StatClockAcquireEmpty);
return;
+ }
+
+ // Check if we've already acquired src after the last release operation on src
+ bool acquired = false;
+ if (nclk > tid_) {
+ CPP_STAT_INC(StatClockAcquireLarge);
+ if (src->clk_[tid_].reused == reused_) {
+ CPP_STAT_INC(StatClockAcquireRepeat);
+ for (unsigned i = 0; i < kDirtyTids; i++) {
+ unsigned tid = src->dirty_tids_[i];
+ if (tid != kInvalidTid) {
+ u64 epoch = src->clk_[tid].epoch;
+ if (clk_[tid].epoch < epoch) {
+ clk_[tid].epoch = epoch;
+ acquired = true;
+ }
+ }
+ }
+ if (acquired) {
+ CPP_STAT_INC(StatClockAcquiredSomething);
+ last_acquire_ = clk_[tid_].epoch;
+ }
+ return;
+ }
+ }
+
+ // O(N) acquire.
+ CPP_STAT_INC(StatClockAcquireFull);
nclk_ = max(nclk_, nclk);
for (uptr i = 0; i < nclk; i++) {
- if (clk_[i] < src->clk_[i])
- clk_[i] = src->clk_[i];
+ u64 epoch = src->clk_[i].epoch;
+ if (clk_[i].epoch < epoch) {
+ clk_[i].epoch = epoch;
+ acquired = true;
+ }
+ }
+
+ // Remember that this thread has acquired this clock.
+ if (nclk > tid_)
+ src->clk_[tid_].reused = reused_;
+
+ if (acquired) {
+ CPP_STAT_INC(StatClockAcquiredSomething);
+ last_acquire_ = clk_[tid_].epoch;
}
}
void ThreadClock::release(SyncClock *dst) const {
- DCHECK(nclk_ <= kMaxTid);
- DCHECK(dst->clk_.Size() <= kMaxTid);
+ DCHECK_LE(nclk_, kMaxTid);
+ DCHECK_LE(dst->clk_.Size(), kMaxTid);
- if (dst->clk_.Size() < nclk_)
+ if (dst->clk_.Size() == 0) {
+ // ReleaseStore will correctly set release_store_tid_,
+ // which can be important for future operations.
+ ReleaseStore(dst);
+ return;
+ }
+
+ CPP_STAT_INC(StatClockRelease);
+ // Check if we need to resize dst.
+ if (dst->clk_.Size() < nclk_) {
+ CPP_STAT_INC(StatClockReleaseResize);
dst->clk_.Resize(nclk_);
+ }
+
+ // Check if we had not acquired anything from other threads
+ // since the last release on dst. If so, we need to update
+ // only dst->clk_[tid_].
+ if (dst->clk_[tid_].epoch > last_acquire_) {
+ UpdateCurrentThread(dst);
+ if (dst->release_store_tid_ != tid_ ||
+ dst->release_store_reused_ != reused_)
+ dst->release_store_tid_ = kInvalidTid;
+ return;
+ }
+
+ // O(N) release.
+ CPP_STAT_INC(StatClockReleaseFull);
+ // First, remember whether we've acquired dst.
+ bool acquired = IsAlreadyAcquired(dst);
+ if (acquired)
+ CPP_STAT_INC(StatClockReleaseAcquired);
+ // Update dst->clk_.
for (uptr i = 0; i < nclk_; i++) {
- if (dst->clk_[i] < clk_[i])
- dst->clk_[i] = clk_[i];
+ dst->clk_[i].epoch = max(dst->clk_[i].epoch, clk_[i].epoch);
+ dst->clk_[i].reused = 0;
}
+ // Clear 'acquired' flag in the remaining elements.
+ if (nclk_ < dst->clk_.Size())
+ CPP_STAT_INC(StatClockReleaseClearTail);
+ for (uptr i = nclk_; i < dst->clk_.Size(); i++)
+ dst->clk_[i].reused = 0;
+ for (unsigned i = 0; i < kDirtyTids; i++)
+ dst->dirty_tids_[i] = kInvalidTid;
+ dst->release_store_tid_ = kInvalidTid;
+ dst->release_store_reused_ = 0;
+ // If we've acquired dst, remember this fact,
+ // so that we don't need to acquire it on next acquire.
+ if (acquired)
+ dst->clk_[tid_].reused = reused_;
}
void ThreadClock::ReleaseStore(SyncClock *dst) const {
DCHECK(nclk_ <= kMaxTid);
DCHECK(dst->clk_.Size() <= kMaxTid);
+ CPP_STAT_INC(StatClockStore);
- if (dst->clk_.Size() < nclk_)
+ // Check if we need to resize dst.
+ if (dst->clk_.Size() < nclk_) {
+ CPP_STAT_INC(StatClockStoreResize);
dst->clk_.Resize(nclk_);
- for (uptr i = 0; i < nclk_; i++)
- dst->clk_[i] = clk_[i];
- for (uptr i = nclk_; i < dst->clk_.Size(); i++)
- dst->clk_[i] = 0;
+ }
+
+ if (dst->release_store_tid_ == tid_ &&
+ dst->release_store_reused_ == reused_ &&
+ dst->clk_[tid_].epoch > last_acquire_) {
+ CPP_STAT_INC(StatClockStoreFast);
+ UpdateCurrentThread(dst);
+ return;
+ }
+
+ // O(N) release-store.
+ CPP_STAT_INC(StatClockStoreFull);
+ for (uptr i = 0; i < nclk_; i++) {
+ dst->clk_[i].epoch = clk_[i].epoch;
+ dst->clk_[i].reused = 0;
+ }
+ // Clear the tail of dst->clk_.
+ if (nclk_ < dst->clk_.Size()) {
+ internal_memset(&dst->clk_[nclk_], 0,
+ (dst->clk_.Size() - nclk_) * sizeof(dst->clk_[0]));
+ CPP_STAT_INC(StatClockStoreTail);
+ }
+ for (unsigned i = 0; i < kDirtyTids; i++)
+ dst->dirty_tids_[i] = kInvalidTid;
+ dst->release_store_tid_ = tid_;
+ dst->release_store_reused_ = reused_;
+ // Rememeber that we don't need to acquire it in future.
+ dst->clk_[tid_].reused = reused_;
}
void ThreadClock::acq_rel(SyncClock *dst) {
+ CPP_STAT_INC(StatClockAcquireRelease);
acquire(dst);
- release(dst);
+ ReleaseStore(dst);
+}
+
+// Updates only single element related to the current thread in dst->clk_.
+void ThreadClock::UpdateCurrentThread(SyncClock *dst) const {
+ // Update the threads time, but preserve 'acquired' flag.
+ dst->clk_[tid_].epoch = clk_[tid_].epoch;
+
+ for (unsigned i = 0; i < kDirtyTids; i++) {
+ if (dst->dirty_tids_[i] == tid_) {
+ CPP_STAT_INC(StatClockReleaseFast1);
+ return;
+ }
+ if (dst->dirty_tids_[i] == kInvalidTid) {
+ CPP_STAT_INC(StatClockReleaseFast2);
+ dst->dirty_tids_[i] = tid_;
+ return;
+ }
+ }
+ // Reset all 'acquired' flags, O(N).
+ CPP_STAT_INC(StatClockReleaseSlow);
+ for (uptr i = 0; i < dst->clk_.Size(); i++) {
+ dst->clk_[i].reused = 0;
+ }
+ for (unsigned i = 0; i < kDirtyTids; i++)
+ dst->dirty_tids_[i] = kInvalidTid;
+}
+
+// Checks whether the current threads has already acquired src.
+bool ThreadClock::IsAlreadyAcquired(const SyncClock *src) const {
+ if (src->clk_[tid_].reused != reused_)
+ return false;
+ for (unsigned i = 0; i < kDirtyTids; i++) {
+ unsigned tid = src->dirty_tids_[i];
+ if (tid != kInvalidTid) {
+ if (clk_[tid].epoch < src->clk_[tid].epoch)
+ return false;
+ }
+ }
+ return true;
+}
+
+// Sets a single element in the vector clock.
+// This function is called only from weird places like AcquireGlobal.
+void ThreadClock::set(unsigned tid, u64 v) {
+ DCHECK_LT(tid, kMaxTid);
+ DCHECK_GE(v, clk_[tid].epoch);
+ clk_[tid].epoch = v;
+ if (nclk_ <= tid)
+ nclk_ = tid + 1;
+ last_acquire_ = clk_[tid_].epoch;
+}
+
+void ThreadClock::DebugDump(int(*printf)(const char *s, ...)) {
+ printf("clock=[");
+ for (uptr i = 0; i < nclk_; i++)
+ printf("%s%llu", i == 0 ? "" : ",", clk_[i].epoch);
+ printf("] reused=[");
+ for (uptr i = 0; i < nclk_; i++)
+ printf("%s%llu", i == 0 ? "" : ",", clk_[i].reused);
+ printf("] tid=%u/%u last_acq=%llu",
+ tid_, reused_, last_acquire_);
}
SyncClock::SyncClock()
- : clk_(MBlockClock) {
+ : clk_(MBlockClock) {
+ release_store_tid_ = kInvalidTid;
+ release_store_reused_ = 0;
+ for (uptr i = 0; i < kDirtyTids; i++)
+ dirty_tids_[i] = kInvalidTid;
+}
+
+void SyncClock::Reset() {
+ clk_.Reset();
+ release_store_tid_ = kInvalidTid;
+ release_store_reused_ = 0;
+ for (uptr i = 0; i < kDirtyTids; i++)
+ dirty_tids_[i] = kInvalidTid;
+}
+
+void SyncClock::DebugDump(int(*printf)(const char *s, ...)) {
+ printf("clock=[");
+ for (uptr i = 0; i < clk_.Size(); i++)
+ printf("%s%llu", i == 0 ? "" : ",", clk_[i].epoch);
+ printf("] reused=[");
+ for (uptr i = 0; i < clk_.Size(); i++)
+ printf("%s%llu", i == 0 ? "" : ",", clk_[i].reused);
+ printf("] release_store_tid=%d/%d dirty_tids=%d/%d",
+ release_store_tid_, release_store_reused_,
+ dirty_tids_[0], dirty_tids_[1]);
}
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_clock.h b/libsanitizer/tsan/tsan_clock.h
index 8e4bf99ca89..2ce480b2d16 100644
--- a/libsanitizer/tsan/tsan_clock.h
+++ b/libsanitizer/tsan/tsan_clock.h
@@ -16,6 +16,11 @@
namespace __tsan {
+struct ClockElem {
+ u64 epoch : kClkBits;
+ u64 reused : 64 - kClkBits;
+};
+
// The clock that lives in sync variables (mutexes, atomics, etc).
class SyncClock {
public:
@@ -25,38 +30,43 @@ class SyncClock {
return clk_.Size();
}
- void Reset() {
- clk_.Reset();
+ u64 get(unsigned tid) const {
+ DCHECK_LT(tid, clk_.Size());
+ return clk_[tid].epoch;
}
+ void Reset();
+
+ void DebugDump(int(*printf)(const char *s, ...));
+
private:
- Vector<u64> clk_;
+ unsigned release_store_tid_;
+ unsigned release_store_reused_;
+ static const uptr kDirtyTids = 2;
+ unsigned dirty_tids_[kDirtyTids];
+ mutable Vector<ClockElem> clk_;
friend struct ThreadClock;
};
// The clock that lives in threads.
struct ThreadClock {
public:
- ThreadClock();
+ explicit ThreadClock(unsigned tid, unsigned reused = 0);
u64 get(unsigned tid) const {
DCHECK_LT(tid, kMaxTidInClock);
- return clk_[tid];
+ return clk_[tid].epoch;
}
- void set(unsigned tid, u64 v) {
- DCHECK_LT(tid, kMaxTid);
- DCHECK_GE(v, clk_[tid]);
- clk_[tid] = v;
- if (nclk_ <= tid)
- nclk_ = tid + 1;
+ void set(unsigned tid, u64 v);
+
+ void set(u64 v) {
+ DCHECK_GE(v, clk_[tid_].epoch);
+ clk_[tid_].epoch = v;
}
- void tick(unsigned tid) {
- DCHECK_LT(tid, kMaxTid);
- clk_[tid]++;
- if (nclk_ <= tid)
- nclk_ = tid + 1;
+ void tick() {
+ clk_[tid_].epoch++;
}
uptr size() const {
@@ -68,9 +78,19 @@ struct ThreadClock {
void acq_rel(SyncClock *dst);
void ReleaseStore(SyncClock *dst) const;
+ void DebugReset();
+ void DebugDump(int(*printf)(const char *s, ...));
+
private:
+ static const uptr kDirtyTids = SyncClock::kDirtyTids;
+ const unsigned tid_;
+ const unsigned reused_;
+ u64 last_acquire_;
uptr nclk_;
- u64 clk_[kMaxTidInClock];
+ ClockElem clk_[kMaxTidInClock];
+
+ bool IsAlreadyAcquired(const SyncClock *src) const;
+ void UpdateCurrentThread(SyncClock *dst) const;
};
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_defs.h b/libsanitizer/tsan/tsan_defs.h
index 3f20797ff4b..cc65ae8b4a3 100644
--- a/libsanitizer/tsan/tsan_defs.h
+++ b/libsanitizer/tsan/tsan_defs.h
@@ -39,6 +39,7 @@ const int kTidBits = 13;
const unsigned kMaxTid = 1 << kTidBits;
const unsigned kMaxTidInClock = kMaxTid * 2; // This includes msb 'freed' bit.
const int kClkBits = 42;
+const unsigned kMaxTidReuse = (1 << (64 - kClkBits)) - 1;
const uptr kShadowStackSize = 64 * 1024;
const uptr kTraceStackSize = 256;
@@ -63,6 +64,12 @@ const uptr kShadowSize = 8;
// Shadow memory is kShadowMultiplier times larger than user memory.
const uptr kShadowMultiplier = kShadowSize * kShadowCnt / kShadowCell;
+#if defined(TSAN_NO_HISTORY) && TSAN_NO_HISTORY
+const bool kCollectHistory = false;
+#else
+const bool kCollectHistory = true;
+#endif
+
#if defined(TSAN_COLLECT_STATS) && TSAN_COLLECT_STATS
const bool kCollectStats = true;
#else
diff --git a/libsanitizer/tsan/tsan_fd.cc b/libsanitizer/tsan/tsan_fd.cc
index b7ac3111c89..7d62ae4c5ff 100644
--- a/libsanitizer/tsan/tsan_fd.cc
+++ b/libsanitizer/tsan/tsan_fd.cc
@@ -63,7 +63,7 @@ static void unref(ThreadState *thr, uptr pc, FdSync *s) {
CHECK_NE(s, &fdctx.globsync);
CHECK_NE(s, &fdctx.filesync);
CHECK_NE(s, &fdctx.socksync);
- SyncVar *v = CTX()->synctab.GetAndRemove(thr, pc, (uptr)s);
+ SyncVar *v = ctx->synctab.GetAndRemove(thr, pc, (uptr)s);
if (v)
DestroyAndFree(v);
internal_free(s);
@@ -283,13 +283,13 @@ void FdSocketConnect(ThreadState *thr, uptr pc, int fd) {
init(thr, pc, fd, &fdctx.socksync);
}
-uptr File2addr(char *path) {
+uptr File2addr(const char *path) {
(void)path;
static u64 addr;
return (uptr)&addr;
}
-uptr Dir2addr(char *path) {
+uptr Dir2addr(const char *path) {
(void)path;
static u64 addr;
return (uptr)&addr;
diff --git a/libsanitizer/tsan/tsan_fd.h b/libsanitizer/tsan/tsan_fd.h
index 3306873223e..57ae62cfe8b 100644
--- a/libsanitizer/tsan/tsan_fd.h
+++ b/libsanitizer/tsan/tsan_fd.h
@@ -55,8 +55,8 @@ void FdSocketConnect(ThreadState *thr, uptr pc, int fd);
bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack);
void FdOnFork(ThreadState *thr, uptr pc);
-uptr File2addr(char *path);
-uptr Dir2addr(char *path);
+uptr File2addr(const char *path);
+uptr Dir2addr(const char *path);
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_flags.cc b/libsanitizer/tsan/tsan_flags.cc
index 158e24f8241..e241cb6cda4 100644
--- a/libsanitizer/tsan/tsan_flags.cc
+++ b/libsanitizer/tsan/tsan_flags.cc
@@ -18,17 +18,13 @@
namespace __tsan {
Flags *flags() {
- return &CTX()->flags;
+ return &ctx->flags;
}
// Can be overriden in frontend.
#ifdef TSAN_EXTERNAL_HOOKS
-void OverrideFlags(Flags *f);
extern "C" const char* __tsan_default_options();
#else
-void WEAK OverrideFlags(Flags *f) {
- (void)f;
-}
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
const char *WEAK __tsan_default_options() {
return "";
@@ -36,30 +32,35 @@ const char *WEAK __tsan_default_options() {
#endif
static void ParseFlags(Flags *f, const char *env) {
- ParseFlag(env, &f->enable_annotations, "enable_annotations");
- ParseFlag(env, &f->suppress_equal_stacks, "suppress_equal_stacks");
- ParseFlag(env, &f->suppress_equal_addresses, "suppress_equal_addresses");
- ParseFlag(env, &f->suppress_java, "suppress_java");
- ParseFlag(env, &f->report_bugs, "report_bugs");
- ParseFlag(env, &f->report_thread_leaks, "report_thread_leaks");
- ParseFlag(env, &f->report_destroy_locked, "report_destroy_locked");
- ParseFlag(env, &f->report_signal_unsafe, "report_signal_unsafe");
- ParseFlag(env, &f->report_atomic_races, "report_atomic_races");
- ParseFlag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics");
- ParseFlag(env, &f->suppressions, "suppressions");
- ParseFlag(env, &f->print_suppressions, "print_suppressions");
- ParseFlag(env, &f->print_benign, "print_benign");
- ParseFlag(env, &f->exitcode, "exitcode");
- ParseFlag(env, &f->halt_on_error, "halt_on_error");
- ParseFlag(env, &f->atexit_sleep_ms, "atexit_sleep_ms");
- ParseFlag(env, &f->profile_memory, "profile_memory");
- ParseFlag(env, &f->flush_memory_ms, "flush_memory_ms");
- ParseFlag(env, &f->flush_symbolizer_ms, "flush_symbolizer_ms");
- ParseFlag(env, &f->memory_limit_mb, "memory_limit_mb");
- ParseFlag(env, &f->stop_on_start, "stop_on_start");
- ParseFlag(env, &f->running_on_valgrind, "running_on_valgrind");
- ParseFlag(env, &f->history_size, "history_size");
- ParseFlag(env, &f->io_sync, "io_sync");
+ ParseFlag(env, &f->enable_annotations, "enable_annotations", "");
+ ParseFlag(env, &f->suppress_equal_stacks, "suppress_equal_stacks", "");
+ ParseFlag(env, &f->suppress_equal_addresses, "suppress_equal_addresses", "");
+ ParseFlag(env, &f->suppress_java, "suppress_java", "");
+ ParseFlag(env, &f->report_bugs, "report_bugs", "");
+ ParseFlag(env, &f->report_thread_leaks, "report_thread_leaks", "");
+ ParseFlag(env, &f->report_destroy_locked, "report_destroy_locked", "");
+ ParseFlag(env, &f->report_mutex_bugs, "report_mutex_bugs", "");
+ ParseFlag(env, &f->report_signal_unsafe, "report_signal_unsafe", "");
+ ParseFlag(env, &f->report_atomic_races, "report_atomic_races", "");
+ ParseFlag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics", "");
+ ParseFlag(env, &f->suppressions, "suppressions", "");
+ ParseFlag(env, &f->print_suppressions, "print_suppressions", "");
+ ParseFlag(env, &f->print_benign, "print_benign", "");
+ ParseFlag(env, &f->exitcode, "exitcode", "");
+ ParseFlag(env, &f->halt_on_error, "halt_on_error", "");
+ ParseFlag(env, &f->atexit_sleep_ms, "atexit_sleep_ms", "");
+ ParseFlag(env, &f->profile_memory, "profile_memory", "");
+ ParseFlag(env, &f->flush_memory_ms, "flush_memory_ms", "");
+ ParseFlag(env, &f->flush_symbolizer_ms, "flush_symbolizer_ms", "");
+ ParseFlag(env, &f->memory_limit_mb, "memory_limit_mb", "");
+ ParseFlag(env, &f->stop_on_start, "stop_on_start", "");
+ ParseFlag(env, &f->running_on_valgrind, "running_on_valgrind", "");
+ ParseFlag(env, &f->history_size, "history_size", "");
+ ParseFlag(env, &f->io_sync, "io_sync", "");
+ ParseFlag(env, &f->die_after_fork, "die_after_fork", "");
+
+ // DDFlags
+ ParseFlag(env, &f->second_deadlock_stack, "second_deadlock_stack", "");
}
void InitializeFlags(Flags *f, const char *env) {
@@ -73,6 +74,7 @@ void InitializeFlags(Flags *f, const char *env) {
f->report_bugs = true;
f->report_thread_leaks = true;
f->report_destroy_locked = true;
+ f->report_mutex_bugs = true;
f->report_signal_unsafe = true;
f->report_atomic_races = true;
f->force_seq_cst_atomics = false;
@@ -90,11 +92,16 @@ void InitializeFlags(Flags *f, const char *env) {
f->running_on_valgrind = false;
f->history_size = kGoMode ? 1 : 2; // There are a lot of goroutines in Go.
f->io_sync = 1;
+ f->die_after_fork = true;
+
+ // DDFlags
+ f->second_deadlock_stack = false;
SetCommonFlagsDefaults(f);
+ // Override some common flags defaults.
+ f->allow_addr2line = true;
// Let a frontend override.
- OverrideFlags(f);
ParseFlags(f, __tsan_default_options());
ParseCommonFlagsFromString(f, __tsan_default_options());
// Override from command line.
@@ -111,6 +118,8 @@ void InitializeFlags(Flags *f, const char *env) {
f->report_signal_unsafe = false;
}
+ if (f->help) PrintFlagDescriptions();
+
if (f->history_size < 0 || f->history_size > 7) {
Printf("ThreadSanitizer: incorrect value for history_size"
" (must be [0..7])\n");
diff --git a/libsanitizer/tsan/tsan_flags.h b/libsanitizer/tsan/tsan_flags.h
index 05d11a451c6..4bf459d5981 100644
--- a/libsanitizer/tsan/tsan_flags.h
+++ b/libsanitizer/tsan/tsan_flags.h
@@ -12,23 +12,18 @@
#ifndef TSAN_FLAGS_H
#define TSAN_FLAGS_H
-// ----------- ATTENTION -------------
-// ThreadSanitizer user may provide its implementation of weak
-// symbol __tsan::OverrideFlags(__tsan::Flags). Therefore, this
-// header may be included in the user code, and shouldn't include
-// other headers from TSan or common sanitizer runtime.
-
#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
namespace __tsan {
-struct Flags : CommonFlags {
+struct Flags : CommonFlags, DDFlags {
// Enable dynamic annotations, otherwise they are no-ops.
bool enable_annotations;
- // Supress a race report if we've already output another race report
+ // Suppress a race report if we've already output another race report
// with the same stack.
bool suppress_equal_stacks;
- // Supress a race report if we've already output another race report
+ // Suppress a race report if we've already output another race report
// on the same address.
bool suppress_equal_addresses;
// Suppress weird race reports that can be seen if JVM is embed
@@ -40,6 +35,8 @@ struct Flags : CommonFlags {
bool report_thread_leaks;
// Report destruction of a locked mutex?
bool report_destroy_locked;
+ // Report incorrect usages of mutexes and mutex annotations?
+ bool report_mutex_bugs;
// Report violations of async signal-safety
// (e.g. malloc() call from a signal handler).
bool report_signal_unsafe;
@@ -85,6 +82,8 @@ struct Flags : CommonFlags {
// 1 - reasonable level of synchronization (write->read)
// 2 - global synchronization of all IO operations
int io_sync;
+ // Die after multi-threaded fork if the child creates new threads.
+ bool die_after_fork;
};
Flags *flags();
diff --git a/libsanitizer/tsan/tsan_interceptors.cc b/libsanitizer/tsan/tsan_interceptors.cc
index 0574beb91df..19a3b7b0643 100644
--- a/libsanitizer/tsan/tsan_interceptors.cc
+++ b/libsanitizer/tsan/tsan_interceptors.cc
@@ -27,7 +27,7 @@
using namespace __tsan; // NOLINT
-const int kSigCount = 64;
+const int kSigCount = 65;
struct my_siginfo_t {
// The size is determined by looking at sizeof of real siginfo_t on linux.
@@ -51,6 +51,7 @@ extern "C" int pthread_sigmask(int how, const __sanitizer_sigset_t *set,
__sanitizer_sigset_t *oldset);
// REAL(sigfillset) defined in common interceptors.
DECLARE_REAL(int, sigfillset, __sanitizer_sigset_t *set)
+DECLARE_REAL(int, fflush, __sanitizer_FILE *fp)
extern "C" void *pthread_self();
extern "C" void _exit(int status);
extern "C" int *__errno_location();
@@ -60,6 +61,7 @@ extern "C" void *__libc_calloc(uptr size, uptr n);
extern "C" void *__libc_realloc(void *ptr, uptr size);
extern "C" void __libc_free(void *ptr);
extern "C" int mallopt(int param, int value);
+extern __sanitizer_FILE *stdout, *stderr;
const int PTHREAD_MUTEX_RECURSIVE = 1;
const int PTHREAD_MUTEX_RECURSIVE_NP = 1;
const int EINVAL = 22;
@@ -71,6 +73,7 @@ const int SIGABRT = 6;
const int SIGFPE = 8;
const int SIGSEGV = 11;
const int SIGPIPE = 13;
+const int SIGTERM = 15;
const int SIGBUS = 7;
const int SIGSYS = 31;
void *const MAP_FAILED = (void*)-1;
@@ -142,7 +145,6 @@ void InitializeLibIgnore() {
static SignalContext *SigCtx(ThreadState *thr) {
SignalContext *ctx = (SignalContext*)thr->signal_ctx;
if (ctx == 0 && thr->is_alive) {
- ScopedInRtl in_rtl;
ctx = (SignalContext*)MmapOrDie(sizeof(*ctx), "SignalContext");
MemoryResetRange(thr, (uptr)&SigCtx, (uptr)ctx, sizeof(*ctx));
thr->signal_ctx = ctx;
@@ -159,7 +161,6 @@ class ScopedInterceptor {
private:
ThreadState *const thr_;
const uptr pc_;
- const int in_rtl_;
bool in_ignored_lib_;
};
@@ -167,16 +168,12 @@ ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
uptr pc)
: thr_(thr)
, pc_(pc)
- , in_rtl_(thr->in_rtl)
, in_ignored_lib_(false) {
- if (thr_->in_rtl == 0) {
+ if (!thr_->ignore_interceptors) {
Initialize(thr);
FuncEntry(thr, pc);
- thr_->in_rtl++;
- DPrintf("#%d: intercept %s()\n", thr_->tid, fname);
- } else {
- thr_->in_rtl++;
}
+ DPrintf("#%d: intercept %s()\n", thr_->tid, fname);
if (!thr_->in_ignored_lib && libignore()->IsIgnored(pc)) {
in_ignored_lib_ = true;
thr_->in_ignored_lib = true;
@@ -189,18 +186,14 @@ ScopedInterceptor::~ScopedInterceptor() {
thr_->in_ignored_lib = false;
ThreadIgnoreEnd(thr_, pc_);
}
- thr_->in_rtl--;
- if (thr_->in_rtl == 0) {
- FuncExit(thr_);
+ if (!thr_->ignore_interceptors) {
ProcessPendingSignals(thr_);
+ FuncExit(thr_);
}
- CHECK_EQ(in_rtl_, thr_->in_rtl);
}
#define SCOPED_INTERCEPTOR_RAW(func, ...) \
ThreadState *thr = cur_thread(); \
- StatInc(thr, StatInterceptor); \
- StatInc(thr, StatInt_##func); \
const uptr caller_pc = GET_CALLER_PC(); \
ScopedInterceptor si(thr, #func, caller_pc); \
const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
@@ -210,15 +203,16 @@ ScopedInterceptor::~ScopedInterceptor() {
#define SCOPED_TSAN_INTERCEPTOR(func, ...) \
SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
if (REAL(func) == 0) { \
- Printf("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \
+ Report("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \
Die(); \
} \
- if (thr->in_rtl > 1 || thr->in_ignored_lib) \
+ if (thr->ignore_interceptors || thr->in_ignored_lib) \
return REAL(func)(__VA_ARGS__); \
/**/
#define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__)
#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
+#define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION_VER(func, ver)
#define BLOCK_REAL(name) (BlockingCall(thr), REAL(name))
@@ -233,6 +227,13 @@ struct BlockingCall {
}
SignalContext *ctx;
+
+ // When we are in a "blocking call", we process signals asynchronously
+ // (right when they arrive). In this context we do not expect to be
+ // executing any user/runtime code. The known interceptor sequence when
+ // this is not true is: pthread_join -> munmap(stack). It's fine
+ // to ignore munmap in this case -- we handle stack shadow separately.
+ ScopedIgnoreInterceptors ignore_interceptors;
};
TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) {
@@ -258,22 +259,14 @@ TSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) {
TSAN_INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
SCOPED_INTERCEPTOR_RAW(dlopen, filename, flag);
- // dlopen will execute global constructors, so it must be not in rtl.
- CHECK_EQ(thr->in_rtl, 1);
- thr->in_rtl = 0;
void *res = REAL(dlopen)(filename, flag);
- thr->in_rtl = 1;
libignore()->OnLibraryLoaded(filename);
return res;
}
TSAN_INTERCEPTOR(int, dlclose, void *handle) {
SCOPED_INTERCEPTOR_RAW(dlclose, handle);
- // dlclose will execute global destructors, so it must be not in rtl.
- CHECK_EQ(thr->in_rtl, 1);
- thr->in_rtl = 0;
int res = REAL(dlclose)(handle);
- thr->in_rtl = 1;
libignore()->OnLibraryUnloaded();
return res;
}
@@ -301,7 +294,6 @@ class AtExitContext {
}
void exit(ThreadState *thr, uptr pc) {
- CHECK_EQ(thr->in_rtl, 0);
for (;;) {
atexit_t f = 0;
void *arg = 0;
@@ -313,14 +305,12 @@ class AtExitContext {
f = stack_[pos_];
arg = args_[pos_];
is_on_exit = is_on_exits_[pos_];
- ScopedInRtl in_rtl;
Acquire(thr, pc, (uptr)this);
}
}
if (f == 0)
break;
DPrintf("#%d: executing atexit func %p\n", thr->tid, f);
- CHECK_EQ(thr->in_rtl, 0);
if (is_on_exit)
((void(*)(int status, void *arg))f)(0, arg);
else
@@ -342,7 +332,9 @@ static AtExitContext *atexit_ctx;
TSAN_INTERCEPTOR(int, atexit, void (*f)()) {
if (cur_thread()->in_symbolizer)
return 0;
- SCOPED_TSAN_INTERCEPTOR(atexit, f);
+ // We want to setup the atexit callback even if we are in ignored lib
+ // or after fork.
+ SCOPED_INTERCEPTOR_RAW(atexit, f);
return atexit_ctx->atexit(thr, pc, false, (void(*)())f, 0);
}
@@ -413,7 +405,6 @@ static void LongJmp(ThreadState *thr, uptr *env) {
// FIXME: put everything below into a common extern "C" block?
extern "C" void __tsan_setjmp(uptr sp, uptr mangled_sp) {
- ScopedInRtl in_rtl;
SetJmp(cur_thread(), sp, mangled_sp);
}
@@ -587,21 +578,21 @@ void *operator new[](__sanitizer::uptr size, std::nothrow_t const&) {
user_free(thr, pc, ptr);
SANITIZER_INTERFACE_ATTRIBUTE
-void operator delete(void *ptr);
-void operator delete(void *ptr) {
+void operator delete(void *ptr) throw();
+void operator delete(void *ptr) throw() {
OPERATOR_DELETE_BODY(_ZdlPv);
}
SANITIZER_INTERFACE_ATTRIBUTE
-void operator delete[](void *ptr);
-void operator delete[](void *ptr) {
- OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t);
+void operator delete[](void *ptr) throw();
+void operator delete[](void *ptr) throw() {
+ OPERATOR_DELETE_BODY(_ZdaPv);
}
SANITIZER_INTERFACE_ATTRIBUTE
void operator delete(void *ptr, std::nothrow_t const&);
void operator delete(void *ptr, std::nothrow_t const&) {
- OPERATOR_DELETE_BODY(_ZdaPv);
+ OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t);
}
SANITIZER_INTERFACE_ATTRIBUTE
@@ -643,20 +634,6 @@ TSAN_INTERCEPTOR(int, memcmp, const void *s1, const void *s2, uptr n) {
return res;
}
-TSAN_INTERCEPTOR(void*, memchr, void *s, int c, uptr n) {
- SCOPED_TSAN_INTERCEPTOR(memchr, s, c, n);
- void *res = REAL(memchr)(s, c, n);
- uptr len = res ? (char*)res - (char*)s + 1 : n;
- MemoryAccessRange(thr, pc, (uptr)s, len, false);
- return res;
-}
-
-TSAN_INTERCEPTOR(void*, memrchr, char *s, int c, uptr n) {
- SCOPED_TSAN_INTERCEPTOR(memrchr, s, c, n);
- MemoryAccessRange(thr, pc, (uptr)s, n, false);
- return REAL(memrchr)(s, c, n);
-}
-
TSAN_INTERCEPTOR(void*, memmove, void *dst, void *src, uptr n) {
SCOPED_TSAN_INTERCEPTOR(memmove, dst, src, n);
MemoryAccessRange(thr, pc, (uptr)dst, n, true);
@@ -827,7 +804,6 @@ static void thread_finalize(void *v) {
return;
}
{
- ScopedInRtl in_rtl;
ThreadState *thr = cur_thread();
ThreadFinish(thr);
SignalContext *sctx = thr->signal_ctx;
@@ -852,7 +828,8 @@ extern "C" void *__tsan_thread_start_func(void *arg) {
int tid = 0;
{
ThreadState *thr = cur_thread();
- ScopedInRtl in_rtl;
+ // Thread-local state is not initialized yet.
+ ScopedIgnoreInterceptors ignore;
if (pthread_setspecific(g_thread_finalize_key,
(void *)kPthreadDestructorIterations)) {
Printf("ThreadSanitizer: failed to set thread key\n");
@@ -862,7 +839,6 @@ extern "C" void *__tsan_thread_start_func(void *arg) {
pthread_yield();
atomic_store(&p->tid, 0, memory_order_release);
ThreadStart(thr, tid, GetTid());
- CHECK_EQ(thr->in_rtl, 1);
}
void *res = callback(param);
// Prevent the callback from being tail called,
@@ -875,6 +851,17 @@ extern "C" void *__tsan_thread_start_func(void *arg) {
TSAN_INTERCEPTOR(int, pthread_create,
void *th, void *attr, void *(*callback)(void*), void * param) {
SCOPED_INTERCEPTOR_RAW(pthread_create, th, attr, callback, param);
+ if (ctx->after_multithreaded_fork) {
+ if (flags()->die_after_fork) {
+ Report("ThreadSanitizer: starting new threads after multi-threaded "
+ "fork is not supported. Dying (set die_after_fork=0 to override)\n");
+ Die();
+ } else {
+ VPrintf(1, "ThreadSanitizer: starting new threads after multi-threaded "
+ "fork is not supported (pid %d). Continuing because of "
+ "die_after_fork=0, but you are on your own\n", internal_getpid());
+ }
+ }
__sanitizer_pthread_attr_t myattr;
if (attr == 0) {
pthread_attr_init(&myattr);
@@ -882,13 +869,20 @@ TSAN_INTERCEPTOR(int, pthread_create,
}
int detached = 0;
REAL(pthread_attr_getdetachstate)(attr, &detached);
- AdjustStackSizeLinux(attr);
+ AdjustStackSize(attr);
ThreadParam p;
p.callback = callback;
p.param = param;
atomic_store(&p.tid, 0, memory_order_relaxed);
- int res = REAL(pthread_create)(th, attr, __tsan_thread_start_func, &p);
+ int res = -1;
+ {
+ // Otherwise we see false positives in pthread stack manipulation.
+ ScopedIgnoreInterceptors ignore;
+ ThreadIgnoreBegin(thr, pc);
+ res = REAL(pthread_create)(th, attr, __tsan_thread_start_func, &p);
+ ThreadIgnoreEnd(thr, pc);
+ }
if (res == 0) {
int tid = ThreadCreate(thr, pc, *(uptr*)th, detached);
CHECK_NE(tid, 0);
@@ -904,7 +898,9 @@ TSAN_INTERCEPTOR(int, pthread_create,
TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret);
int tid = ThreadTid(thr, pc, (uptr)th);
+ ThreadIgnoreBegin(thr, pc);
int res = BLOCK_REAL(pthread_join)(th, ret);
+ ThreadIgnoreEnd(thr, pc);
if (res == 0) {
ThreadJoin(thr, pc, tid);
}
@@ -921,6 +917,122 @@ TSAN_INTERCEPTOR(int, pthread_detach, void *th) {
return res;
}
+// Problem:
+// NPTL implementation of pthread_cond has 2 versions (2.2.5 and 2.3.2).
+// pthread_cond_t has different size in the different versions.
+// If call new REAL functions for old pthread_cond_t, they will corrupt memory
+// after pthread_cond_t (old cond is smaller).
+// If we call old REAL functions for new pthread_cond_t, we will lose some
+// functionality (e.g. old functions do not support waiting against
+// CLOCK_REALTIME).
+// Proper handling would require to have 2 versions of interceptors as well.
+// But this is messy, in particular requires linker scripts when sanitizer
+// runtime is linked into a shared library.
+// Instead we assume we don't have dynamic libraries built against old
+// pthread (2.2.5 is dated by 2002). And provide legacy_pthread_cond flag
+// that allows to work with old libraries (but this mode does not support
+// some features, e.g. pthread_condattr_getpshared).
+static void *init_cond(void *c, bool force = false) {
+ // sizeof(pthread_cond_t) >= sizeof(uptr) in both versions.
+ // So we allocate additional memory on the side large enough to hold
+ // any pthread_cond_t object. Always call new REAL functions, but pass
+ // the aux object to them.
+ // Note: the code assumes that PTHREAD_COND_INITIALIZER initializes
+ // first word of pthread_cond_t to zero.
+ // It's all relevant only for linux.
+ if (!common_flags()->legacy_pthread_cond)
+ return c;
+ atomic_uintptr_t *p = (atomic_uintptr_t*)c;
+ uptr cond = atomic_load(p, memory_order_acquire);
+ if (!force && cond != 0)
+ return (void*)cond;
+ void *newcond = WRAP(malloc)(pthread_cond_t_sz);
+ internal_memset(newcond, 0, pthread_cond_t_sz);
+ if (atomic_compare_exchange_strong(p, &cond, (uptr)newcond,
+ memory_order_acq_rel))
+ return newcond;
+ WRAP(free)(newcond);
+ return (void*)cond;
+}
+
+struct CondMutexUnlockCtx {
+ ThreadState *thr;
+ uptr pc;
+ void *m;
+};
+
+static void cond_mutex_unlock(CondMutexUnlockCtx *arg) {
+ MutexLock(arg->thr, arg->pc, (uptr)arg->m);
+}
+
+INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
+ void *cond = init_cond(c, true);
+ SCOPED_TSAN_INTERCEPTOR(pthread_cond_init, cond, a);
+ MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), true);
+ return REAL(pthread_cond_init)(cond, a);
+}
+
+INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
+ void *cond = init_cond(c);
+ SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, cond, m);
+ MutexUnlock(thr, pc, (uptr)m);
+ MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
+ CondMutexUnlockCtx arg = {thr, pc, m};
+ // This ensures that we handle mutex lock even in case of pthread_cancel.
+ // See test/tsan/cond_cancel.cc.
+ int res = call_pthread_cancel_with_cleanup(
+ (int(*)(void *c, void *m, void *abstime))REAL(pthread_cond_wait),
+ cond, m, 0, (void(*)(void *arg))cond_mutex_unlock, &arg);
+ if (res == errno_EOWNERDEAD)
+ MutexRepair(thr, pc, (uptr)m);
+ MutexLock(thr, pc, (uptr)m);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) {
+ void *cond = init_cond(c);
+ SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, cond, m, abstime);
+ MutexUnlock(thr, pc, (uptr)m);
+ MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
+ CondMutexUnlockCtx arg = {thr, pc, m};
+ // This ensures that we handle mutex lock even in case of pthread_cancel.
+ // See test/tsan/cond_cancel.cc.
+ int res = call_pthread_cancel_with_cleanup(
+ REAL(pthread_cond_timedwait), cond, m, abstime,
+ (void(*)(void *arg))cond_mutex_unlock, &arg);
+ if (res == errno_EOWNERDEAD)
+ MutexRepair(thr, pc, (uptr)m);
+ MutexLock(thr, pc, (uptr)m);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_cond_signal, void *c) {
+ void *cond = init_cond(c);
+ SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal, cond);
+ MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
+ return REAL(pthread_cond_signal)(cond);
+}
+
+INTERCEPTOR(int, pthread_cond_broadcast, void *c) {
+ void *cond = init_cond(c);
+ SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast, cond);
+ MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
+ return REAL(pthread_cond_broadcast)(cond);
+}
+
+INTERCEPTOR(int, pthread_cond_destroy, void *c) {
+ void *cond = init_cond(c);
+ SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy, cond);
+ MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), true);
+ int res = REAL(pthread_cond_destroy)(cond);
+ if (common_flags()->legacy_pthread_cond) {
+ // Free our aux cond and zero the pointer to not leave dangling pointers.
+ WRAP(free)(cond);
+ atomic_store((atomic_uintptr_t*)c, 0, memory_order_relaxed);
+ }
+ return res;
+}
+
TSAN_INTERCEPTOR(int, pthread_mutex_init, void *m, void *a) {
SCOPED_TSAN_INTERCEPTOR(pthread_mutex_init, m, a);
int res = REAL(pthread_mutex_init)(m, a);
@@ -952,7 +1064,7 @@ TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) {
if (res == EOWNERDEAD)
MutexRepair(thr, pc, (uptr)m);
if (res == 0 || res == EOWNERDEAD)
- MutexLock(thr, pc, (uptr)m);
+ MutexLock(thr, pc, (uptr)m, /*rec=*/1, /*try_lock=*/true);
return res;
}
@@ -996,7 +1108,7 @@ TSAN_INTERCEPTOR(int, pthread_spin_trylock, void *m) {
SCOPED_TSAN_INTERCEPTOR(pthread_spin_trylock, m);
int res = REAL(pthread_spin_trylock)(m);
if (res == 0) {
- MutexLock(thr, pc, (uptr)m);
+ MutexLock(thr, pc, (uptr)m, /*rec=*/1, /*try_lock=*/true);
}
return res;
}
@@ -1039,7 +1151,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) {
SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_tryrdlock, m);
int res = REAL(pthread_rwlock_tryrdlock)(m);
if (res == 0) {
- MutexReadLock(thr, pc, (uptr)m);
+ MutexLock(thr, pc, (uptr)m, /*rec=*/1, /*try_lock=*/true);
}
return res;
}
@@ -1066,7 +1178,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) {
SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_trywrlock, m);
int res = REAL(pthread_rwlock_trywrlock)(m);
if (res == 0) {
- MutexLock(thr, pc, (uptr)m);
+ MutexLock(thr, pc, (uptr)m, /*rec=*/1, /*try_lock=*/true);
}
return res;
}
@@ -1087,23 +1199,6 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) {
return res;
}
-TSAN_INTERCEPTOR(int, pthread_cond_destroy, void *c) {
- SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy, c);
- MemoryWrite(thr, pc, (uptr)c, kSizeLog1);
- int res = REAL(pthread_cond_destroy)(c);
- return res;
-}
-
-TSAN_INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m,
- void *abstime) {
- SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, c, m, abstime);
- MutexUnlock(thr, pc, (uptr)m);
- MemoryRead(thr, pc, (uptr)c, kSizeLog1);
- int res = REAL(pthread_cond_timedwait)(c, m, abstime);
- MutexLock(thr, pc, (uptr)m);
- return res;
-}
-
TSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) {
SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count);
MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
@@ -1132,19 +1227,13 @@ TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) {
TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
SCOPED_INTERCEPTOR_RAW(pthread_once, o, f);
- // Using SCOPED_INTERCEPTOR_RAW, because if we are called from an ignored lib,
- // the user callback must be executed with thr->in_rtl == 0.
if (o == 0 || f == 0)
return EINVAL;
atomic_uint32_t *a = static_cast<atomic_uint32_t*>(o);
u32 v = atomic_load(a, memory_order_acquire);
if (v == 0 && atomic_compare_exchange_strong(a, &v, 1,
memory_order_relaxed)) {
- const int old_in_rtl = thr->in_rtl;
- thr->in_rtl = 0;
(*f)();
- CHECK_EQ(thr->in_rtl, 0);
- thr->in_rtl = old_in_rtl;
if (!thr->in_ignored_lib)
Release(thr, pc, (uptr)o);
atomic_store(a, 2, memory_order_release);
@@ -1509,10 +1598,9 @@ TSAN_INTERCEPTOR(int, unlink, char *path) {
return res;
}
-TSAN_INTERCEPTOR(void*, fopen, char *path, char *mode) {
- SCOPED_TSAN_INTERCEPTOR(fopen, path, mode);
- void *res = REAL(fopen)(path, mode);
- Acquire(thr, pc, File2addr(path));
+TSAN_INTERCEPTOR(void*, tmpfile, int fake) {
+ SCOPED_TSAN_INTERCEPTOR(tmpfile, fake);
+ void *res = REAL(tmpfile)(fake);
if (res) {
int fd = fileno_unlocked(res);
if (fd >= 0)
@@ -1521,15 +1609,9 @@ TSAN_INTERCEPTOR(void*, fopen, char *path, char *mode) {
return res;
}
-TSAN_INTERCEPTOR(void*, freopen, char *path, char *mode, void *stream) {
- SCOPED_TSAN_INTERCEPTOR(freopen, path, mode, stream);
- if (stream) {
- int fd = fileno_unlocked(stream);
- if (fd >= 0)
- FdClose(thr, pc, fd);
- }
- void *res = REAL(freopen)(path, mode, stream);
- Acquire(thr, pc, File2addr(path));
+TSAN_INTERCEPTOR(void*, tmpfile64, int fake) {
+ SCOPED_TSAN_INTERCEPTOR(tmpfile64, fake);
+ void *res = REAL(tmpfile64)(fake);
if (res) {
int fd = fileno_unlocked(res);
if (fd >= 0)
@@ -1538,19 +1620,6 @@ TSAN_INTERCEPTOR(void*, freopen, char *path, char *mode, void *stream) {
return res;
}
-TSAN_INTERCEPTOR(int, fclose, void *stream) {
- // libc file streams can call user-supplied functions, see fopencookie.
- {
- SCOPED_TSAN_INTERCEPTOR(fclose, stream);
- if (stream) {
- int fd = fileno_unlocked(stream);
- if (fd >= 0)
- FdClose(thr, pc, fd);
- }
- }
- return REAL(fclose)(stream);
-}
-
TSAN_INTERCEPTOR(uptr, fread, void *ptr, uptr size, uptr nmemb, void *f) {
// libc file streams can call user-supplied functions, see fopencookie.
{
@@ -1569,14 +1638,6 @@ TSAN_INTERCEPTOR(uptr, fwrite, const void *p, uptr size, uptr nmemb, void *f) {
return REAL(fwrite)(p, size, nmemb, f);
}
-TSAN_INTERCEPTOR(int, fflush, void *stream) {
- // libc file streams can call user-supplied functions, see fopencookie.
- {
- SCOPED_TSAN_INTERCEPTOR(fflush, stream);
- }
- return REAL(fflush)(stream);
-}
-
TSAN_INTERCEPTOR(void, abort, int fake) {
SCOPED_TSAN_INTERCEPTOR(abort, fake);
REAL(fflush)(0);
@@ -1626,30 +1687,106 @@ TSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) {
return res;
}
+namespace __tsan {
+
+static void CallUserSignalHandler(ThreadState *thr, bool sync, bool sigact,
+ int sig, my_siginfo_t *info, void *uctx) {
+ // Ensure that the handler does not spoil errno.
+ const int saved_errno = errno;
+ errno = 99;
+ // Need to remember pc before the call, because the handler can reset it.
+ uptr pc = sigact ?
+ (uptr)sigactions[sig].sa_sigaction :
+ (uptr)sigactions[sig].sa_handler;
+ pc += 1; // return address is expected, OutputReport() will undo this
+ if (sigact)
+ sigactions[sig].sa_sigaction(sig, info, uctx);
+ else
+ sigactions[sig].sa_handler(sig);
+ // We do not detect errno spoiling for SIGTERM,
+ // because some SIGTERM handlers do spoil errno but reraise SIGTERM,
+ // tsan reports false positive in such case.
+ // It's difficult to properly detect this situation (reraise),
+ // because in async signal processing case (when handler is called directly
+ // from rtl_generic_sighandler) we have not yet received the reraised
+ // signal; and it looks too fragile to intercept all ways to reraise a signal.
+ if (flags()->report_bugs && !sync && sig != SIGTERM && errno != 99) {
+ __tsan::StackTrace stack;
+ stack.ObtainCurrent(thr, pc);
+ ThreadRegistryLock l(ctx->thread_registry);
+ ScopedReport rep(ReportTypeErrnoInSignal);
+ if (!IsFiredSuppression(ctx, rep, stack)) {
+ rep.AddStack(&stack);
+ OutputReport(ctx, rep, rep.GetReport()->stacks[0]);
+ }
+ }
+ errno = saved_errno;
+}
+
+void ProcessPendingSignals(ThreadState *thr) {
+ SignalContext *sctx = SigCtx(thr);
+ if (sctx == 0 || sctx->pending_signal_count == 0 || thr->in_signal_handler)
+ return;
+ thr->in_signal_handler = true;
+ sctx->pending_signal_count = 0;
+ // These are too big for stack.
+ static THREADLOCAL __sanitizer_sigset_t emptyset, oldset;
+ REAL(sigfillset)(&emptyset);
+ pthread_sigmask(SIG_SETMASK, &emptyset, &oldset);
+ for (int sig = 0; sig < kSigCount; sig++) {
+ SignalDesc *signal = &sctx->pending_signals[sig];
+ if (signal->armed) {
+ signal->armed = false;
+ if (sigactions[sig].sa_handler != SIG_DFL
+ && sigactions[sig].sa_handler != SIG_IGN) {
+ CallUserSignalHandler(thr, false, signal->sigaction,
+ sig, &signal->siginfo, &signal->ctx);
+ }
+ }
+ }
+ pthread_sigmask(SIG_SETMASK, &oldset, 0);
+ CHECK_EQ(thr->in_signal_handler, true);
+ thr->in_signal_handler = false;
+}
+
+} // namespace __tsan
+
+static bool is_sync_signal(SignalContext *sctx, int sig) {
+ return sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
+ sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS ||
+ // If we are sending signal to ourselves, we must process it now.
+ (sctx && sig == sctx->int_signal_send);
+}
+
void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
my_siginfo_t *info, void *ctx) {
ThreadState *thr = cur_thread();
SignalContext *sctx = SigCtx(thr);
+ if (sig < 0 || sig >= kSigCount) {
+ VPrintf(1, "ThreadSanitizer: ignoring signal %d\n", sig);
+ return;
+ }
// Don't mess with synchronous signals.
- if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
- sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS ||
- // If we are sending signal to ourselves, we must process it now.
- (sctx && sig == sctx->int_signal_send) ||
+ const bool sync = is_sync_signal(sctx, sig);
+ if (sync ||
// If we are in blocking function, we can safely process it now
// (but check if we are in a recursive interceptor,
// i.e. pthread_join()->munmap()).
- (sctx && sctx->in_blocking_func == 1 && thr->in_rtl == 1)) {
- int in_rtl = thr->in_rtl;
- thr->in_rtl = 0;
+ (sctx && sctx->in_blocking_func == 1)) {
CHECK_EQ(thr->in_signal_handler, false);
thr->in_signal_handler = true;
- if (sigact)
- sigactions[sig].sa_sigaction(sig, info, ctx);
- else
- sigactions[sig].sa_handler(sig);
+ if (sctx && sctx->in_blocking_func == 1) {
+ // We ignore interceptors in blocking functions,
+ // temporary enbled them again while we are calling user function.
+ int const i = thr->ignore_interceptors;
+ thr->ignore_interceptors = 0;
+ CallUserSignalHandler(thr, sync, sigact, sig, info, ctx);
+ thr->ignore_interceptors = i;
+ } else {
+ CallUserSignalHandler(thr, sync, sigact, sig, info, ctx);
+ }
CHECK_EQ(thr->in_signal_handler, true);
thr->in_signal_handler = false;
- thr->in_rtl = in_rtl;
return;
}
@@ -1769,11 +1906,7 @@ TSAN_INTERCEPTOR(int, getaddrinfo, void *node, void *service,
// and can report false race between malloc and free
// inside of getaddrinfo. So ignore memory accesses.
ThreadIgnoreBegin(thr, pc);
- // getaddrinfo calls fopen, which can be intercepted by user.
- thr->in_rtl--;
- CHECK_EQ(thr->in_rtl, 0);
int res = REAL(getaddrinfo)(node, service, hints, rv);
- thr->in_rtl++;
ThreadIgnoreEnd(thr, pc);
return res;
}
@@ -1784,8 +1917,7 @@ static void MlockIsUnsupported() {
static atomic_uint8_t printed;
if (atomic_exchange(&printed, 1, memory_order_relaxed))
return;
- if (flags()->verbosity > 0)
- Printf("INFO: ThreadSanitizer ignores mlock/mlockall/munlock/munlockall\n");
+ VPrintf(1, "INFO: ThreadSanitizer ignores mlock/munlock[all]\n");
}
TSAN_INTERCEPTOR(int, mlock, const void *addr, uptr len) {
@@ -1809,17 +1941,42 @@ TSAN_INTERCEPTOR(int, munlockall, void) {
}
TSAN_INTERCEPTOR(int, fork, int fake) {
+ if (cur_thread()->in_symbolizer)
+ return REAL(fork)(fake);
SCOPED_INTERCEPTOR_RAW(fork, fake);
+ ForkBefore(thr, pc);
int pid = REAL(fork)(fake);
if (pid == 0) {
// child
+ ForkChildAfter(thr, pc);
FdOnFork(thr, pc);
} else if (pid > 0) {
// parent
+ ForkParentAfter(thr, pc);
+ } else {
+ // error
+ ForkParentAfter(thr, pc);
}
return pid;
}
+TSAN_INTERCEPTOR(int, vfork, int fake) {
+ // Some programs (e.g. openjdk) call close for all file descriptors
+ // in the child process. Under tsan it leads to false positives, because
+ // address space is shared, so the parent process also thinks that
+ // the descriptors are closed (while they are actually not).
+ // This leads to false positives due to missed synchronization.
+ // Strictly saying this is undefined behavior, because vfork child is not
+ // allowed to call any functions other than exec/exit. But this is what
+ // openjdk does, so we want to handle it.
+ // We could disable interceptors in the child process. But it's not possible
+ // to simply intercept and wrap vfork, because vfork child is not allowed
+ // to return from the function that calls vfork, and that's exactly what
+ // we would do. So this would require some assembly trickery as well.
+ // Instead we simply turn vfork into fork.
+ return WRAP(fork)(fake);
+}
+
static int OnExit(ThreadState *thr) {
int status = Finalize(thr);
REAL(fflush)(0);
@@ -1841,19 +1998,10 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
}
#include "sanitizer_common/sanitizer_platform_interceptors.h"
-// Causes interceptor recursion (getpwuid_r() calls fopen())
-#undef SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
-#undef SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
// Causes interceptor recursion (getaddrinfo() and fopen())
#undef SANITIZER_INTERCEPT_GETADDRINFO
-#undef SANITIZER_INTERCEPT_GETNAMEINFO
-// Causes interceptor recursion (glob64() calls lstat64())
-#undef SANITIZER_INTERCEPT_GLOB
#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
-#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \
- do { \
- } while (false)
#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr, \
@@ -1871,6 +2019,19 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
ctx = (void *)&_ctx; \
(void) ctx;
+#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) \
+ Acquire(thr, pc, File2addr(path)); \
+ if (file) { \
+ int fd = fileno_unlocked(file); \
+ if (fd >= 0) FdFileCreate(thr, pc, fd); \
+ }
+
+#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) \
+ if (file) { \
+ int fd = fileno_unlocked(file); \
+ if (fd >= 0) FdClose(thr, pc, fd); \
+ }
+
#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
FdAcquire(((TsanInterceptorContext *) ctx)->thr, pc, fd)
@@ -1887,7 +2048,7 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
ThreadSetName(((TsanInterceptorContext *) ctx)->thr, name)
#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
- CTX()->thread_registry->SetThreadNameByUserId(thread, name)
+ __tsan::ctx->thread_registry->SetThreadNameByUserId(thread, name)
#define COMMON_INTERCEPTOR_BLOCK_REAL(name) BLOCK_REAL(name)
@@ -1914,6 +2075,8 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
#define TSAN_SYSCALL() \
ThreadState *thr = cur_thread(); \
+ if (thr->ignore_interceptors) \
+ return; \
ScopedSyscall scoped_syscall(thr) \
/**/
@@ -1922,15 +2085,11 @@ struct ScopedSyscall {
explicit ScopedSyscall(ThreadState *thr)
: thr(thr) {
- if (thr->in_rtl == 0)
- Initialize(thr);
- thr->in_rtl++;
+ Initialize(thr);
}
~ScopedSyscall() {
- thr->in_rtl--;
- if (thr->in_rtl == 0)
- ProcessPendingSignals(thr);
+ ProcessPendingSignals(thr);
}
};
@@ -1942,12 +2101,12 @@ static void syscall_access_range(uptr pc, uptr p, uptr s, bool write) {
static void syscall_acquire(uptr pc, uptr addr) {
TSAN_SYSCALL();
Acquire(thr, pc, addr);
- Printf("syscall_acquire(%p)\n", addr);
+ DPrintf("syscall_acquire(%p)\n", addr);
}
static void syscall_release(uptr pc, uptr addr) {
TSAN_SYSCALL();
- Printf("syscall_release(%p)\n", addr);
+ DPrintf("syscall_release(%p)\n", addr);
Release(thr, pc, addr);
}
@@ -1959,26 +2118,32 @@ static void syscall_fd_close(uptr pc, int fd) {
static USED void syscall_fd_acquire(uptr pc, int fd) {
TSAN_SYSCALL();
FdAcquire(thr, pc, fd);
- Printf("syscall_fd_acquire(%p)\n", fd);
+ DPrintf("syscall_fd_acquire(%p)\n", fd);
}
static USED void syscall_fd_release(uptr pc, int fd) {
TSAN_SYSCALL();
- Printf("syscall_fd_release(%p)\n", fd);
+ DPrintf("syscall_fd_release(%p)\n", fd);
FdRelease(thr, pc, fd);
}
static void syscall_pre_fork(uptr pc) {
TSAN_SYSCALL();
+ ForkBefore(thr, pc);
}
-static void syscall_post_fork(uptr pc, int res) {
+static void syscall_post_fork(uptr pc, int pid) {
TSAN_SYSCALL();
- if (res == 0) {
+ if (pid == 0) {
// child
+ ForkChildAfter(thr, pc);
FdOnFork(thr, pc);
- } else if (res > 0) {
+ } else if (pid > 0) {
// parent
+ ForkParentAfter(thr, pc);
+ } else {
+ // error
+ ForkParentAfter(thr, pc);
}
}
@@ -2027,68 +2192,21 @@ static void finalize(void *arg) {
uptr pc = 0;
atexit_ctx->exit(thr, pc);
int status = Finalize(thr);
- REAL(fflush)(0);
+ // Make sure the output is not lost.
+ // Flushing all the streams here may freeze the process if a child thread is
+ // performing file stream operations at the same time.
+ REAL(fflush)(stdout);
+ REAL(fflush)(stderr);
if (status)
REAL(_exit)(status);
}
-void ProcessPendingSignals(ThreadState *thr) {
- CHECK_EQ(thr->in_rtl, 0);
- SignalContext *sctx = SigCtx(thr);
- if (sctx == 0 || sctx->pending_signal_count == 0 || thr->in_signal_handler)
- return;
- Context *ctx = CTX();
- thr->in_signal_handler = true;
- sctx->pending_signal_count = 0;
- // These are too big for stack.
- static THREADLOCAL __sanitizer_sigset_t emptyset, oldset;
- REAL(sigfillset)(&emptyset);
- pthread_sigmask(SIG_SETMASK, &emptyset, &oldset);
- for (int sig = 0; sig < kSigCount; sig++) {
- SignalDesc *signal = &sctx->pending_signals[sig];
- if (signal->armed) {
- signal->armed = false;
- if (sigactions[sig].sa_handler != SIG_DFL
- && sigactions[sig].sa_handler != SIG_IGN) {
- // Insure that the handler does not spoil errno.
- const int saved_errno = errno;
- errno = 0;
- if (signal->sigaction)
- sigactions[sig].sa_sigaction(sig, &signal->siginfo, &signal->ctx);
- else
- sigactions[sig].sa_handler(sig);
- if (flags()->report_bugs && errno != 0) {
- ScopedInRtl in_rtl;
- __tsan::StackTrace stack;
- uptr pc = signal->sigaction ?
- (uptr)sigactions[sig].sa_sigaction :
- (uptr)sigactions[sig].sa_handler;
- pc += 1; // return address is expected, OutputReport() will undo this
- stack.Init(&pc, 1);
- ThreadRegistryLock l(ctx->thread_registry);
- ScopedReport rep(ReportTypeErrnoInSignal);
- if (!IsFiredSuppression(ctx, rep, stack)) {
- rep.AddStack(&stack);
- OutputReport(ctx, rep, rep.GetReport()->stacks[0]);
- }
- }
- errno = saved_errno;
- }
- }
- }
- pthread_sigmask(SIG_SETMASK, &oldset, 0);
- CHECK_EQ(thr->in_signal_handler, true);
- thr->in_signal_handler = false;
-}
-
static void unreachable() {
- Printf("FATAL: ThreadSanitizer: unreachable called\n");
+ Report("FATAL: ThreadSanitizer: unreachable called\n");
Die();
}
void InitializeInterceptors() {
- CHECK_GT(cur_thread()->in_rtl, 0);
-
// We need to setup it early, because functions like dlsym() can call it.
REAL(memset) = internal_memset;
REAL(memcpy) = internal_memcpy;
@@ -2098,7 +2216,7 @@ void InitializeInterceptors() {
mallopt(1, 0); // M_MXFAST
mallopt(-3, 32*1024); // M_MMAP_THRESHOLD
- SANITIZER_COMMON_INTERCEPTORS_INIT;
+ InitializeCommonInterceptors();
// We can not use TSAN_INTERCEPT to get setjmp addr,
// because it does &setjmp and setjmp is not present in some versions of libc.
@@ -2128,8 +2246,6 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(strlen);
TSAN_INTERCEPT(memset);
TSAN_INTERCEPT(memcpy);
- TSAN_INTERCEPT(memchr);
- TSAN_INTERCEPT(memrchr);
TSAN_INTERCEPT(memmove);
TSAN_INTERCEPT(memcmp);
TSAN_INTERCEPT(strchr);
@@ -2144,6 +2260,13 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(pthread_join);
TSAN_INTERCEPT(pthread_detach);
+ TSAN_INTERCEPT_VER(pthread_cond_init, "GLIBC_2.3.2");
+ TSAN_INTERCEPT_VER(pthread_cond_signal, "GLIBC_2.3.2");
+ TSAN_INTERCEPT_VER(pthread_cond_broadcast, "GLIBC_2.3.2");
+ TSAN_INTERCEPT_VER(pthread_cond_wait, "GLIBC_2.3.2");
+ TSAN_INTERCEPT_VER(pthread_cond_timedwait, "GLIBC_2.3.2");
+ TSAN_INTERCEPT_VER(pthread_cond_destroy, "GLIBC_2.3.2");
+
TSAN_INTERCEPT(pthread_mutex_init);
TSAN_INTERCEPT(pthread_mutex_destroy);
TSAN_INTERCEPT(pthread_mutex_trylock);
@@ -2165,9 +2288,6 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(pthread_rwlock_timedwrlock);
TSAN_INTERCEPT(pthread_rwlock_unlock);
- INTERCEPT_FUNCTION_VER(pthread_cond_destroy, "GLIBC_2.3.2");
- INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, "GLIBC_2.3.2");
-
TSAN_INTERCEPT(pthread_barrier_init);
TSAN_INTERCEPT(pthread_barrier_destroy);
TSAN_INTERCEPT(pthread_barrier_wait);
@@ -2223,12 +2343,10 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(recv);
TSAN_INTERCEPT(unlink);
- TSAN_INTERCEPT(fopen);
- TSAN_INTERCEPT(freopen);
- TSAN_INTERCEPT(fclose);
+ TSAN_INTERCEPT(tmpfile);
+ TSAN_INTERCEPT(tmpfile64);
TSAN_INTERCEPT(fread);
TSAN_INTERCEPT(fwrite);
- TSAN_INTERCEPT(fflush);
TSAN_INTERCEPT(abort);
TSAN_INTERCEPT(puts);
TSAN_INTERCEPT(rmdir);
@@ -2255,6 +2373,7 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(munlockall);
TSAN_INTERCEPT(fork);
+ TSAN_INTERCEPT(vfork);
TSAN_INTERCEPT(dlopen);
TSAN_INTERCEPT(dlclose);
TSAN_INTERCEPT(on_exit);
@@ -2280,16 +2399,19 @@ void InitializeInterceptors() {
FdInit();
}
-void internal_start_thread(void(*func)(void *arg), void *arg) {
- // Start the thread with signals blocked, otherwise it can steal users
- // signals.
- __sanitizer_kernel_sigset_t set, old;
+void *internal_start_thread(void(*func)(void *arg), void *arg) {
+ // Start the thread with signals blocked, otherwise it can steal user signals.
+ __sanitizer_sigset_t set, old;
internal_sigfillset(&set);
internal_sigprocmask(SIG_SETMASK, &set, &old);
void *th;
REAL(pthread_create)(&th, 0, (void*(*)(void *arg))func, arg);
- REAL(pthread_detach)(th);
internal_sigprocmask(SIG_SETMASK, &old, 0);
+ return th;
+}
+
+void internal_join_thread(void *th) {
+ REAL(pthread_join)(th, 0);
}
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_interface_ann.cc b/libsanitizer/tsan/tsan_interface_ann.cc
index 38224f429cd..20e3d9a35ac 100644
--- a/libsanitizer/tsan/tsan_interface_ann.cc
+++ b/libsanitizer/tsan/tsan_interface_ann.cc
@@ -31,22 +31,16 @@ class ScopedAnnotation {
public:
ScopedAnnotation(ThreadState *thr, const char *aname, const char *f, int l,
uptr pc)
- : thr_(thr)
- , in_rtl_(thr->in_rtl) {
- CHECK_EQ(thr_->in_rtl, 0);
+ : thr_(thr) {
FuncEntry(thr_, pc);
- thr_->in_rtl++;
DPrintf("#%d: annotation %s() %s:%d\n", thr_->tid, aname, f, l);
}
~ScopedAnnotation() {
- thr_->in_rtl--;
- CHECK_EQ(in_rtl_, thr_->in_rtl);
FuncExit(thr_);
}
private:
ThreadState *const thr_;
- const int in_rtl_;
};
#define SCOPED_ANNOTATION(typ) \
@@ -56,7 +50,7 @@ class ScopedAnnotation {
const uptr caller_pc = (uptr)__builtin_return_address(0); \
StatInc(thr, StatAnnotation); \
StatInc(thr, Stat##typ); \
- ScopedAnnotation sa(thr, __FUNCTION__, f, l, caller_pc); \
+ ScopedAnnotation sa(thr, __func__, f, l, caller_pc); \
const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
(void)pc; \
/**/
@@ -309,7 +303,7 @@ void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
ExpectRace *race = dyn_ann_ctx->expect.next;
if (race->hitcount == 0) {
- CTX()->nmissed_expected++;
+ ctx->nmissed_expected++;
ReportMissedExpectedRace(race);
}
race->prev->next = race->next;
diff --git a/libsanitizer/tsan/tsan_interface_atomic.cc b/libsanitizer/tsan/tsan_interface_atomic.cc
index 180d87b7993..3f5a4ccc9f7 100644
--- a/libsanitizer/tsan/tsan_interface_atomic.cc
+++ b/libsanitizer/tsan/tsan_interface_atomic.cc
@@ -10,7 +10,7 @@
//===----------------------------------------------------------------------===//
// ThreadSanitizer atomic operations are based on C++11/C1x standards.
-// For background see C++11 standard. A slightly older, publically
+// For background see C++11 standard. A slightly older, publicly
// available draft of the standard (not entirely up-to-date, but close enough
// for casual browsing) is available here:
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
@@ -19,7 +19,7 @@
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
-#include "tsan_interface_atomic.h"
+#include "sanitizer_common/sanitizer_mutex.h"
#include "tsan_flags.h"
#include "tsan_rtl.h"
@@ -28,42 +28,52 @@ using namespace __tsan; // NOLINT
#define SCOPED_ATOMIC(func, ...) \
const uptr callpc = (uptr)__builtin_return_address(0); \
uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
- mo = ConvertOrder(mo); \
mo = flags()->force_seq_cst_atomics ? (morder)mo_seq_cst : mo; \
ThreadState *const thr = cur_thread(); \
+ if (thr->ignore_interceptors) \
+ return NoTsanAtomic##func(__VA_ARGS__); \
AtomicStatInc(thr, sizeof(*a), mo, StatAtomic##func); \
- ScopedAtomic sa(thr, callpc, a, mo, __FUNCTION__); \
+ ScopedAtomic sa(thr, callpc, a, mo, __func__); \
return Atomic##func(thr, pc, __VA_ARGS__); \
/**/
-// Some shortcuts.
-typedef __tsan_memory_order morder;
-typedef __tsan_atomic8 a8;
-typedef __tsan_atomic16 a16;
-typedef __tsan_atomic32 a32;
-typedef __tsan_atomic64 a64;
-typedef __tsan_atomic128 a128;
-const morder mo_relaxed = __tsan_memory_order_relaxed;
-const morder mo_consume = __tsan_memory_order_consume;
-const morder mo_acquire = __tsan_memory_order_acquire;
-const morder mo_release = __tsan_memory_order_release;
-const morder mo_acq_rel = __tsan_memory_order_acq_rel;
-const morder mo_seq_cst = __tsan_memory_order_seq_cst;
+// These should match declarations from public tsan_interface_atomic.h header.
+typedef unsigned char a8;
+typedef unsigned short a16; // NOLINT
+typedef unsigned int a32;
+typedef unsigned long long a64; // NOLINT
+#if defined(__SIZEOF_INT128__) \
+ || (__clang_major__ * 100 + __clang_minor__ >= 302)
+__extension__ typedef __int128 a128;
+# define __TSAN_HAS_INT128 1
+#else
+# define __TSAN_HAS_INT128 0
+#endif
+
+// Protects emulation of 128-bit atomic operations.
+static StaticSpinMutex mutex128;
+
+// Part of ABI, do not change.
+// http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/atomic?view=markup
+typedef enum {
+ mo_relaxed,
+ mo_consume,
+ mo_acquire,
+ mo_release,
+ mo_acq_rel,
+ mo_seq_cst
+} morder;
class ScopedAtomic {
public:
ScopedAtomic(ThreadState *thr, uptr pc, const volatile void *a,
morder mo, const char *func)
: thr_(thr) {
- CHECK_EQ(thr_->in_rtl, 0);
- ProcessPendingSignals(thr);
FuncEntry(thr_, pc);
DPrintf("#%d: %s(%p, %d)\n", thr_->tid, func, a, mo);
- thr_->in_rtl++;
}
~ScopedAtomic() {
- thr_->in_rtl--;
- CHECK_EQ(thr_->in_rtl, 0);
+ ProcessPendingSignals(thr_);
FuncExit(thr_);
}
private:
@@ -108,27 +118,6 @@ static bool IsAcqRelOrder(morder mo) {
return mo == mo_acq_rel || mo == mo_seq_cst;
}
-static morder ConvertOrder(morder mo) {
- if (mo > (morder)100500) {
- mo = morder(mo - 100500);
- if (mo == morder(1 << 0))
- mo = mo_relaxed;
- else if (mo == morder(1 << 1))
- mo = mo_consume;
- else if (mo == morder(1 << 2))
- mo = mo_acquire;
- else if (mo == morder(1 << 3))
- mo = mo_release;
- else if (mo == morder(1 << 4))
- mo = mo_acq_rel;
- else if (mo == morder(1 << 5))
- mo = mo_seq_cst;
- }
- CHECK_GE(mo, mo_relaxed);
- CHECK_LE(mo, mo_seq_cst);
- return mo;
-}
-
template<typename T> T func_xchg(volatile T *v, T op) {
T res = __sync_lock_test_and_set(v, op);
// __sync_lock_test_and_set does not contain full barrier.
@@ -178,48 +167,56 @@ template<typename T> T func_cas(volatile T *v, T cmp, T xch) {
// from non-instrumented code.
#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
a128 func_xchg(volatile a128 *v, a128 op) {
+ SpinMutexLock lock(&mutex128);
a128 cmp = *v;
*v = op;
return cmp;
}
a128 func_add(volatile a128 *v, a128 op) {
+ SpinMutexLock lock(&mutex128);
a128 cmp = *v;
*v = cmp + op;
return cmp;
}
a128 func_sub(volatile a128 *v, a128 op) {
+ SpinMutexLock lock(&mutex128);
a128 cmp = *v;
*v = cmp - op;
return cmp;
}
a128 func_and(volatile a128 *v, a128 op) {
+ SpinMutexLock lock(&mutex128);
a128 cmp = *v;
*v = cmp & op;
return cmp;
}
a128 func_or(volatile a128 *v, a128 op) {
+ SpinMutexLock lock(&mutex128);
a128 cmp = *v;
*v = cmp | op;
return cmp;
}
a128 func_xor(volatile a128 *v, a128 op) {
+ SpinMutexLock lock(&mutex128);
a128 cmp = *v;
*v = cmp ^ op;
return cmp;
}
a128 func_nand(volatile a128 *v, a128 op) {
+ SpinMutexLock lock(&mutex128);
a128 cmp = *v;
*v = ~(cmp & op);
return cmp;
}
a128 func_cas(volatile a128 *v, a128 cmp, a128 xch) {
+ SpinMutexLock lock(&mutex128);
a128 cur = *v;
if (cur == cmp)
*v = xch;
@@ -241,26 +238,74 @@ static int SizeLog() {
// this leads to false negatives only in very obscure cases.
}
+static atomic_uint8_t *to_atomic(const volatile a8 *a) {
+ return (atomic_uint8_t*)a;
+}
+
+static atomic_uint16_t *to_atomic(const volatile a16 *a) {
+ return (atomic_uint16_t*)a;
+}
+
+static atomic_uint32_t *to_atomic(const volatile a32 *a) {
+ return (atomic_uint32_t*)a;
+}
+
+static atomic_uint64_t *to_atomic(const volatile a64 *a) {
+ return (atomic_uint64_t*)a;
+}
+
+static memory_order to_mo(morder mo) {
+ switch (mo) {
+ case mo_relaxed: return memory_order_relaxed;
+ case mo_consume: return memory_order_consume;
+ case mo_acquire: return memory_order_acquire;
+ case mo_release: return memory_order_release;
+ case mo_acq_rel: return memory_order_acq_rel;
+ case mo_seq_cst: return memory_order_seq_cst;
+ }
+ CHECK(0);
+ return memory_order_seq_cst;
+}
+
+template<typename T>
+static T NoTsanAtomicLoad(const volatile T *a, morder mo) {
+ return atomic_load(to_atomic(a), to_mo(mo));
+}
+
+static a128 NoTsanAtomicLoad(const volatile a128 *a, morder mo) {
+ SpinMutexLock lock(&mutex128);
+ return *a;
+}
+
template<typename T>
static T AtomicLoad(ThreadState *thr, uptr pc, const volatile T *a,
morder mo) {
CHECK(IsLoadOrder(mo));
// This fast-path is critical for performance.
// Assume the access is atomic.
- if (!IsAcquireOrder(mo) && sizeof(T) <= sizeof(a)) {
+ if (!IsAcquireOrder(mo)) {
MemoryReadAtomic(thr, pc, (uptr)a, SizeLog<T>());
- return *a; // as if atomic
+ return NoTsanAtomicLoad(a, mo);
}
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, false);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, false);
AcquireImpl(thr, pc, &s->clock);
- T v = *a;
+ T v = NoTsanAtomicLoad(a, mo);
s->mtx.ReadUnlock();
- __sync_synchronize();
MemoryReadAtomic(thr, pc, (uptr)a, SizeLog<T>());
return v;
}
template<typename T>
+static void NoTsanAtomicStore(volatile T *a, T v, morder mo) {
+ atomic_store(to_atomic(a), v, to_mo(mo));
+}
+
+static void NoTsanAtomicStore(volatile a128 *a, a128 v, morder mo) {
+ SpinMutexLock lock(&mutex128);
+ *a = v;
+}
+
+template<typename T>
static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v,
morder mo) {
CHECK(IsStoreOrder(mo));
@@ -269,21 +314,18 @@ static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v,
// Assume the access is atomic.
// Strictly saying even relaxed store cuts off release sequence,
// so must reset the clock.
- if (!IsReleaseOrder(mo) && sizeof(T) <= sizeof(a)) {
- *a = v; // as if atomic
+ if (!IsReleaseOrder(mo)) {
+ NoTsanAtomicStore(a, v, mo);
return;
}
__sync_synchronize();
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, true);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, true);
thr->fast_state.IncrementEpoch();
// Can't increment epoch w/o writing to the trace as well.
TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
ReleaseImpl(thr, pc, &s->clock);
- *a = v;
+ NoTsanAtomicStore(a, v, mo);
s->mtx.Unlock();
- // Trainling memory barrier to provide sequential consistency
- // for Dekker-like store-load synchronization.
- __sync_synchronize();
}
template<typename T, T (*F)(volatile T *v, T op)>
@@ -291,7 +333,7 @@ static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {
MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
SyncVar *s = 0;
if (mo != mo_relaxed) {
- s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, true);
+ s = ctx->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, true);
thr->fast_state.IncrementEpoch();
// Can't increment epoch w/o writing to the trace as well.
TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
@@ -309,6 +351,41 @@ static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {
}
template<typename T>
+static T NoTsanAtomicExchange(volatile T *a, T v, morder mo) {
+ return func_xchg(a, v);
+}
+
+template<typename T>
+static T NoTsanAtomicFetchAdd(volatile T *a, T v, morder mo) {
+ return func_add(a, v);
+}
+
+template<typename T>
+static T NoTsanAtomicFetchSub(volatile T *a, T v, morder mo) {
+ return func_sub(a, v);
+}
+
+template<typename T>
+static T NoTsanAtomicFetchAnd(volatile T *a, T v, morder mo) {
+ return func_and(a, v);
+}
+
+template<typename T>
+static T NoTsanAtomicFetchOr(volatile T *a, T v, morder mo) {
+ return func_or(a, v);
+}
+
+template<typename T>
+static T NoTsanAtomicFetchXor(volatile T *a, T v, morder mo) {
+ return func_xor(a, v);
+}
+
+template<typename T>
+static T NoTsanAtomicFetchNand(volatile T *a, T v, morder mo) {
+ return func_nand(a, v);
+}
+
+template<typename T>
static T AtomicExchange(ThreadState *thr, uptr pc, volatile T *a, T v,
morder mo) {
return AtomicRMW<T, func_xchg>(thr, pc, a, v, mo);
@@ -351,13 +428,34 @@ static T AtomicFetchNand(ThreadState *thr, uptr pc, volatile T *a, T v,
}
template<typename T>
+static bool NoTsanAtomicCAS(volatile T *a, T *c, T v, morder mo, morder fmo) {
+ return atomic_compare_exchange_strong(to_atomic(a), c, v, to_mo(mo));
+}
+
+static bool NoTsanAtomicCAS(volatile a128 *a, a128 *c, a128 v,
+ morder mo, morder fmo) {
+ a128 old = *c;
+ a128 cur = func_cas(a, old, v);
+ if (cur == old)
+ return true;
+ *c = cur;
+ return false;
+}
+
+template<typename T>
+static bool NoTsanAtomicCAS(volatile T *a, T c, T v, morder mo, morder fmo) {
+ return NoTsanAtomicCAS(a, &c, v, mo, fmo);
+}
+
+template<typename T>
static bool AtomicCAS(ThreadState *thr, uptr pc,
volatile T *a, T *c, T v, morder mo, morder fmo) {
(void)fmo; // Unused because llvm does not pass it yet.
MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
SyncVar *s = 0;
+ bool write_lock = mo != mo_acquire && mo != mo_consume;
if (mo != mo_relaxed) {
- s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, true);
+ s = ctx->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, write_lock);
thr->fast_state.IncrementEpoch();
// Can't increment epoch w/o writing to the trace as well.
TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
@@ -370,8 +468,12 @@ static bool AtomicCAS(ThreadState *thr, uptr pc,
}
T cc = *c;
T pr = func_cas(a, cc, v);
- if (s)
- s->mtx.Unlock();
+ if (s) {
+ if (write_lock)
+ s->mtx.Unlock();
+ else
+ s->mtx.ReadUnlock();
+ }
if (pr == cc)
return true;
*c = pr;
@@ -385,293 +487,362 @@ static T AtomicCAS(ThreadState *thr, uptr pc,
return c;
}
+static void NoTsanAtomicFence(morder mo) {
+ __sync_synchronize();
+}
+
static void AtomicFence(ThreadState *thr, uptr pc, morder mo) {
// FIXME(dvyukov): not implemented.
__sync_synchronize();
}
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_load(const volatile a8 *a, morder mo) {
SCOPED_ATOMIC(Load, a, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_load(const volatile a16 *a, morder mo) {
SCOPED_ATOMIC(Load, a, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_load(const volatile a32 *a, morder mo) {
SCOPED_ATOMIC(Load, a, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_load(const volatile a64 *a, morder mo) {
SCOPED_ATOMIC(Load, a, mo);
}
#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_load(const volatile a128 *a, morder mo) {
SCOPED_ATOMIC(Load, a, mo);
}
#endif
+SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_atomic8_store(volatile a8 *a, a8 v, morder mo) {
SCOPED_ATOMIC(Store, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_atomic16_store(volatile a16 *a, a16 v, morder mo) {
SCOPED_ATOMIC(Store, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_atomic32_store(volatile a32 *a, a32 v, morder mo) {
SCOPED_ATOMIC(Store, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_atomic64_store(volatile a64 *a, a64 v, morder mo) {
SCOPED_ATOMIC(Store, a, v, mo);
}
#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_atomic128_store(volatile a128 *a, a128 v, morder mo) {
SCOPED_ATOMIC(Store, a, v, mo);
}
#endif
+SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, morder mo) {
SCOPED_ATOMIC(Exchange, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, morder mo) {
SCOPED_ATOMIC(Exchange, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, morder mo) {
SCOPED_ATOMIC(Exchange, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, morder mo) {
SCOPED_ATOMIC(Exchange, a, v, mo);
}
#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, morder mo) {
SCOPED_ATOMIC(Exchange, a, v, mo);
}
#endif
+SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, morder mo) {
SCOPED_ATOMIC(FetchAdd, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, morder mo) {
SCOPED_ATOMIC(FetchAdd, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, morder mo) {
SCOPED_ATOMIC(FetchAdd, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, morder mo) {
SCOPED_ATOMIC(FetchAdd, a, v, mo);
}
#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, morder mo) {
SCOPED_ATOMIC(FetchAdd, a, v, mo);
}
#endif
+SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, morder mo) {
SCOPED_ATOMIC(FetchSub, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, morder mo) {
SCOPED_ATOMIC(FetchSub, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, morder mo) {
SCOPED_ATOMIC(FetchSub, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, morder mo) {
SCOPED_ATOMIC(FetchSub, a, v, mo);
}
#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, morder mo) {
SCOPED_ATOMIC(FetchSub, a, v, mo);
}
#endif
+SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, morder mo) {
SCOPED_ATOMIC(FetchAnd, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, morder mo) {
SCOPED_ATOMIC(FetchAnd, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, morder mo) {
SCOPED_ATOMIC(FetchAnd, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, morder mo) {
SCOPED_ATOMIC(FetchAnd, a, v, mo);
}
#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, morder mo) {
SCOPED_ATOMIC(FetchAnd, a, v, mo);
}
#endif
+SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, morder mo) {
SCOPED_ATOMIC(FetchOr, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, morder mo) {
SCOPED_ATOMIC(FetchOr, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, morder mo) {
SCOPED_ATOMIC(FetchOr, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, morder mo) {
SCOPED_ATOMIC(FetchOr, a, v, mo);
}
#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, morder mo) {
SCOPED_ATOMIC(FetchOr, a, v, mo);
}
#endif
+SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, morder mo) {
SCOPED_ATOMIC(FetchXor, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, morder mo) {
SCOPED_ATOMIC(FetchXor, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, morder mo) {
SCOPED_ATOMIC(FetchXor, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, morder mo) {
SCOPED_ATOMIC(FetchXor, a, v, mo);
}
#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, morder mo) {
SCOPED_ATOMIC(FetchXor, a, v, mo);
}
#endif
+SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, morder mo) {
SCOPED_ATOMIC(FetchNand, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, morder mo) {
SCOPED_ATOMIC(FetchNand, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, morder mo) {
SCOPED_ATOMIC(FetchNand, a, v, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, morder mo) {
SCOPED_ATOMIC(FetchNand, a, v, mo);
}
#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, morder mo) {
SCOPED_ATOMIC(FetchNand, a, v, mo);
}
#endif
+SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
#endif
+SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
#endif
+SANITIZER_INTERFACE_ATTRIBUTE
a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
+
+SANITIZER_INTERFACE_ATTRIBUTE
a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
#endif
+SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_atomic_thread_fence(morder mo) {
char* a = 0;
SCOPED_ATOMIC(Fence, mo);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void __tsan_atomic_signal_fence(morder mo) {
}
+} // extern "C"
diff --git a/libsanitizer/tsan/tsan_interface_java.cc b/libsanitizer/tsan/tsan_interface_java.cc
index 70b5e5fcc65..7f451690946 100644
--- a/libsanitizer/tsan/tsan_interface_java.cc
+++ b/libsanitizer/tsan/tsan_interface_java.cc
@@ -77,13 +77,9 @@ class ScopedJavaFunc {
: thr_(thr) {
Initialize(thr_);
FuncEntry(thr, pc);
- CHECK_EQ(thr_->in_rtl, 0);
- thr_->in_rtl++;
}
~ScopedJavaFunc() {
- thr_->in_rtl--;
- CHECK_EQ(thr_->in_rtl, 0);
FuncExit(thr_);
// FIXME(dvyukov): process pending signals.
}
@@ -134,7 +130,7 @@ SyncVar* GetJavaSync(ThreadState *thr, uptr pc, uptr addr,
}
if (s == 0 && create) {
DPrintf("#%d: creating new sync for %p\n", thr->tid, addr);
- s = CTX()->synctab.Create(thr, pc, addr);
+ s = ctx->synctab.Create(thr, pc, addr);
s->next = b->head;
b->head = s;
}
diff --git a/libsanitizer/tsan/tsan_mman.cc b/libsanitizer/tsan/tsan_mman.cc
index 832374becf5..3df0531f0c8 100644
--- a/libsanitizer/tsan/tsan_mman.cc
+++ b/libsanitizer/tsan/tsan_mman.cc
@@ -88,7 +88,6 @@ void AllocatorPrintStats() {
static void SignalUnsafeCall(ThreadState *thr, uptr pc) {
if (!thr->in_signal_handler || !flags()->report_signal_unsafe)
return;
- Context *ctx = CTX();
StackTrace stack;
stack.ObtainCurrent(thr, pc);
ThreadRegistryLock l(ctx->thread_registry);
@@ -100,7 +99,6 @@ static void SignalUnsafeCall(ThreadState *thr, uptr pc) {
}
void *user_alloc(ThreadState *thr, uptr pc, uptr sz, uptr align) {
- CHECK_GT(thr->in_rtl, 0);
if ((sz >= (1ull << 40)) || (align >= (1ull << 40)))
return AllocatorReturnNull();
void *p = allocator()->Allocate(&thr->alloc_cache, sz, align);
@@ -108,7 +106,7 @@ void *user_alloc(ThreadState *thr, uptr pc, uptr sz, uptr align) {
return 0;
MBlock *b = new(allocator()->GetMetaData(p)) MBlock;
b->Init(sz, thr->tid, CurrentStackId(thr, pc));
- if (CTX() && CTX()->initialized) {
+ if (ctx && ctx->initialized) {
if (thr->ignore_reads_and_writes == 0)
MemoryRangeImitateWrite(thr, pc, (uptr)p, sz);
else
@@ -120,7 +118,6 @@ void *user_alloc(ThreadState *thr, uptr pc, uptr sz, uptr align) {
}
void user_free(ThreadState *thr, uptr pc, void *p) {
- CHECK_GT(thr->in_rtl, 0);
CHECK_NE(p, (void*)0);
DPrintf("#%d: free(%p)\n", thr->tid, p);
MBlock *b = (MBlock*)allocator()->GetMetaData(p);
@@ -136,7 +133,7 @@ void user_free(ThreadState *thr, uptr pc, void *p) {
}
b->ListReset();
}
- if (CTX() && CTX()->initialized && thr->in_rtl == 1) {
+ if (ctx && ctx->initialized) {
if (thr->ignore_reads_and_writes == 0)
MemoryRangeFreed(thr, pc, (uptr)p, b->Size());
}
@@ -145,7 +142,6 @@ void user_free(ThreadState *thr, uptr pc, void *p) {
}
void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz) {
- CHECK_GT(thr->in_rtl, 0);
void *p2 = 0;
// FIXME: Handle "shrinking" more efficiently,
// it seems that some software actually does this.
@@ -165,7 +161,6 @@ void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz) {
}
uptr user_alloc_usable_size(ThreadState *thr, uptr pc, void *p) {
- CHECK_GT(thr->in_rtl, 0);
if (p == 0)
return 0;
MBlock *b = (MBlock*)allocator()->GetMetaData(p);
@@ -182,24 +177,21 @@ MBlock *user_mblock(ThreadState *thr, void *p) {
}
void invoke_malloc_hook(void *ptr, uptr size) {
- Context *ctx = CTX();
ThreadState *thr = cur_thread();
- if (ctx == 0 || !ctx->initialized || thr->in_rtl)
+ if (ctx == 0 || !ctx->initialized || thr->ignore_interceptors)
return;
__tsan_malloc_hook(ptr, size);
}
void invoke_free_hook(void *ptr) {
- Context *ctx = CTX();
ThreadState *thr = cur_thread();
- if (ctx == 0 || !ctx->initialized || thr->in_rtl)
+ if (ctx == 0 || !ctx->initialized || thr->ignore_interceptors)
return;
__tsan_free_hook(ptr);
}
void *internal_alloc(MBlockType typ, uptr sz) {
ThreadState *thr = cur_thread();
- CHECK_GT(thr->in_rtl, 0);
CHECK_LE(sz, InternalSizeClassMap::kMaxSize);
if (thr->nomalloc) {
thr->nomalloc = 0; // CHECK calls internal_malloc().
@@ -210,7 +202,6 @@ void *internal_alloc(MBlockType typ, uptr sz) {
void internal_free(void *p) {
ThreadState *thr = cur_thread();
- CHECK_GT(thr->in_rtl, 0);
if (thr->nomalloc) {
thr->nomalloc = 0; // CHECK calls internal_malloc().
CHECK(0);
@@ -224,19 +215,15 @@ using namespace __tsan;
extern "C" {
uptr __tsan_get_current_allocated_bytes() {
- u64 stats[AllocatorStatCount];
+ uptr stats[AllocatorStatCount];
allocator()->GetStats(stats);
- u64 m = stats[AllocatorStatMalloced];
- u64 f = stats[AllocatorStatFreed];
- return m >= f ? m - f : 1;
+ return stats[AllocatorStatAllocated];
}
uptr __tsan_get_heap_size() {
- u64 stats[AllocatorStatCount];
+ uptr stats[AllocatorStatCount];
allocator()->GetStats(stats);
- u64 m = stats[AllocatorStatMmapped];
- u64 f = stats[AllocatorStatUnmapped];
- return m >= f ? m - f : 1;
+ return stats[AllocatorStatMapped];
}
uptr __tsan_get_free_bytes() {
diff --git a/libsanitizer/tsan/tsan_mutex.cc b/libsanitizer/tsan/tsan_mutex.cc
index e7846c53e4a..0c3bb4a6721 100644
--- a/libsanitizer/tsan/tsan_mutex.cc
+++ b/libsanitizer/tsan/tsan_mutex.cc
@@ -31,13 +31,14 @@ static MutexType CanLockTab[MutexTypeCount][MutexTypeCount] = {
/*2 MutexTypeThreads*/ {MutexTypeReport},
/*3 MutexTypeReport*/ {MutexTypeSyncTab, MutexTypeSyncVar,
MutexTypeMBlock, MutexTypeJavaMBlock},
- /*4 MutexTypeSyncVar*/ {},
+ /*4 MutexTypeSyncVar*/ {MutexTypeDDetector},
/*5 MutexTypeSyncTab*/ {MutexTypeSyncVar},
/*6 MutexTypeSlab*/ {MutexTypeLeaf},
/*7 MutexTypeAnnotations*/ {},
/*8 MutexTypeAtExit*/ {MutexTypeSyncTab},
/*9 MutexTypeMBlock*/ {MutexTypeSyncVar},
/*10 MutexTypeJavaMBlock*/ {MutexTypeSyncVar},
+ /*11 MutexTypeDDetector*/ {},
};
static bool CanLockAdj[MutexTypeCount][MutexTypeCount];
@@ -121,12 +122,12 @@ void InitializeMutex() {
#endif
}
-DeadlockDetector::DeadlockDetector() {
+InternalDeadlockDetector::InternalDeadlockDetector() {
// Rely on zero initialization because some mutexes can be locked before ctor.
}
#if TSAN_DEBUG && !TSAN_GO
-void DeadlockDetector::Lock(MutexType t) {
+void InternalDeadlockDetector::Lock(MutexType t) {
// Printf("LOCK %d @%zu\n", t, seq_ + 1);
CHECK_GT(t, MutexTypeInvalid);
CHECK_LT(t, MutexTypeCount);
@@ -153,7 +154,7 @@ void DeadlockDetector::Lock(MutexType t) {
}
}
-void DeadlockDetector::Unlock(MutexType t) {
+void InternalDeadlockDetector::Unlock(MutexType t) {
// Printf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]);
CHECK(locked_[t]);
locked_[t] = 0;
@@ -208,7 +209,7 @@ Mutex::~Mutex() {
void Mutex::Lock() {
#if TSAN_DEBUG && !TSAN_GO
- cur_thread()->deadlock_detector.Lock(type_);
+ cur_thread()->internal_deadlock_detector.Lock(type_);
#endif
uptr cmp = kUnlocked;
if (atomic_compare_exchange_strong(&state_, &cmp, kWriteLock,
@@ -233,13 +234,13 @@ void Mutex::Unlock() {
(void)prev;
DCHECK_NE(prev & kWriteLock, 0);
#if TSAN_DEBUG && !TSAN_GO
- cur_thread()->deadlock_detector.Unlock(type_);
+ cur_thread()->internal_deadlock_detector.Unlock(type_);
#endif
}
void Mutex::ReadLock() {
#if TSAN_DEBUG && !TSAN_GO
- cur_thread()->deadlock_detector.Lock(type_);
+ cur_thread()->internal_deadlock_detector.Lock(type_);
#endif
uptr prev = atomic_fetch_add(&state_, kReadLock, memory_order_acquire);
if ((prev & kWriteLock) == 0)
@@ -261,7 +262,7 @@ void Mutex::ReadUnlock() {
DCHECK_EQ(prev & kWriteLock, 0);
DCHECK_GT(prev & ~kWriteLock, 0);
#if TSAN_DEBUG && !TSAN_GO
- cur_thread()->deadlock_detector.Unlock(type_);
+ cur_thread()->internal_deadlock_detector.Unlock(type_);
#endif
}
diff --git a/libsanitizer/tsan/tsan_mutex.h b/libsanitizer/tsan/tsan_mutex.h
index 6d145059330..f075ce831e6 100644
--- a/libsanitizer/tsan/tsan_mutex.h
+++ b/libsanitizer/tsan/tsan_mutex.h
@@ -29,6 +29,7 @@ enum MutexType {
MutexTypeAtExit,
MutexTypeMBlock,
MutexTypeJavaMBlock,
+ MutexTypeDDetector,
// This must be the last.
MutexTypeCount
@@ -63,9 +64,9 @@ class Mutex {
typedef GenericScopedLock<Mutex> Lock;
typedef GenericScopedReadLock<Mutex> ReadLock;
-class DeadlockDetector {
+class InternalDeadlockDetector {
public:
- DeadlockDetector();
+ InternalDeadlockDetector();
void Lock(MutexType t);
void Unlock(MutexType t);
private:
diff --git a/libsanitizer/tsan/tsan_mutexset.h b/libsanitizer/tsan/tsan_mutexset.h
index df36b462c60..7fdc194109f 100644
--- a/libsanitizer/tsan/tsan_mutexset.h
+++ b/libsanitizer/tsan/tsan_mutexset.h
@@ -36,6 +36,10 @@ class MutexSet {
uptr Size() const;
Desc Get(uptr i) const;
+ void operator=(const MutexSet &other) {
+ internal_memcpy(this, &other, sizeof(*this));
+ }
+
private:
#ifndef TSAN_GO
uptr size_;
@@ -43,6 +47,7 @@ class MutexSet {
#endif
void RemovePos(uptr i);
+ MutexSet(const MutexSet&);
};
// Go does not have mutexes, so do not spend memory and time.
diff --git a/libsanitizer/tsan/tsan_platform.h b/libsanitizer/tsan/tsan_platform.h
index 164ee45d6c6..60eb1a84995 100644
--- a/libsanitizer/tsan/tsan_platform.h
+++ b/libsanitizer/tsan/tsan_platform.h
@@ -75,6 +75,8 @@ static const uptr kLinuxShadowMsk = 0x200000000000ULL;
#elif defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW
static const uptr kLinuxAppMemBeg = 0x290000000000ULL;
static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL;
+static const uptr kAppMemGapBeg = 0x2c0000000000ULL;
+static const uptr kAppMemGapEnd = 0x7d0000000000ULL;
#else
static const uptr kLinuxAppMemBeg = 0x7cf000000000ULL;
static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL;
@@ -103,7 +105,12 @@ static const uptr kLinuxShadowEnd =
MemToShadow(kLinuxAppMemEnd) | 0xff;
static inline bool IsAppMem(uptr mem) {
+#if defined(TSAN_COMPAT_SHADOW) && TSAN_COMPAT_SHADOW
+ return (mem >= kLinuxAppMemBeg && mem < kAppMemGapBeg) ||
+ (mem >= kAppMemGapEnd && mem <= kLinuxAppMemEnd);
+#else
return mem >= kLinuxAppMemBeg && mem <= kLinuxAppMemEnd;
+#endif
}
static inline bool IsShadowMem(uptr mem) {
@@ -138,8 +145,9 @@ const char *InitializePlatform();
void FinalizePlatform();
// The additional page is to catch shadow stack overflow as paging fault.
-const uptr kTotalTraceSize = (kTraceSize * sizeof(Event) + sizeof(Trace) + 4096
- + 4095) & ~4095;
+// Windows wants 64K alignment for mmaps.
+const uptr kTotalTraceSize = (kTraceSize * sizeof(Event) + sizeof(Trace)
+ + (64 << 10) + (64 << 10) - 1) & ~((64 << 10) - 1);
uptr ALWAYS_INLINE GetThreadTrace(int tid) {
uptr p = kTraceMemBegin + (uptr)tid * kTotalTraceSize;
@@ -154,7 +162,8 @@ uptr ALWAYS_INLINE GetThreadTraceHeader(int tid) {
return p;
}
-void internal_start_thread(void(*func)(void*), void *arg);
+void *internal_start_thread(void(*func)(void*), void *arg);
+void internal_join_thread(void *th);
// Says whether the addr relates to a global var.
// Guesses with high probability, may yield both false positives and negatives.
@@ -162,6 +171,10 @@ bool IsGlobalVar(uptr addr);
int ExtractResolvFDs(void *state, int *fds, int nfd);
int ExtractRecvmsgFDs(void *msg, int *fds, int nfd);
+int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,
+ void *abstime), void *c, void *m, void *abstime,
+ void(*cleanup)(void *arg), void *arg);
+
} // namespace __tsan
#else // defined(__LP64__) || defined(_WIN64)
diff --git a/libsanitizer/tsan/tsan_platform_linux.cc b/libsanitizer/tsan/tsan_platform_linux.cc
index fe69430b711..062e84615cc 100644
--- a/libsanitizer/tsan/tsan_platform_linux.cc
+++ b/libsanitizer/tsan/tsan_platform_linux.cc
@@ -59,27 +59,6 @@ namespace __tsan {
const uptr kPageSize = 4096;
-#ifndef TSAN_GO
-ScopedInRtl::ScopedInRtl()
- : thr_(cur_thread()) {
- in_rtl_ = thr_->in_rtl;
- thr_->in_rtl++;
- errno_ = errno;
-}
-
-ScopedInRtl::~ScopedInRtl() {
- thr_->in_rtl--;
- errno = errno_;
- CHECK_EQ(in_rtl_, thr_->in_rtl);
-}
-#else
-ScopedInRtl::ScopedInRtl() {
-}
-
-ScopedInRtl::~ScopedInRtl() {
-}
-#endif
-
void FillProfileCallback(uptr start, uptr rss, bool file,
uptr *mem, uptr stats_size) {
CHECK_EQ(7, stats_size);
@@ -133,7 +112,6 @@ void FlushShadowMemory() {
#ifndef TSAN_GO
static void ProtectRange(uptr beg, uptr end) {
- ScopedInRtl in_rtl;
CHECK_LE(beg, end);
if (beg == end)
return;
@@ -159,17 +137,19 @@ static void MapRodata() {
#endif
if (tmpdir == 0)
return;
- char filename[256];
- internal_snprintf(filename, sizeof(filename), "%s/tsan.rodata.%d",
+ char name[256];
+ internal_snprintf(name, sizeof(name), "%s/tsan.rodata.%d",
tmpdir, (int)internal_getpid());
- uptr openrv = internal_open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
+ uptr openrv = internal_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
if (internal_iserror(openrv))
return;
+ internal_unlink(name); // Unlink it now, so that we can reuse the buffer.
fd_t fd = openrv;
// Fill the file with kShadowRodata.
const uptr kMarkerSize = 512 * 1024 / sizeof(u64);
InternalScopedBuffer<u64> marker(kMarkerSize);
- for (u64 *p = marker.data(); p < marker.data() + kMarkerSize; p++)
+ // volatile to prevent insertion of memset
+ for (volatile u64 *p = marker.data(); p < marker.data() + kMarkerSize; p++)
*p = kShadowRodata;
internal_write(fd, marker.data(), marker.size());
// Map the file into memory.
@@ -177,13 +157,12 @@ static void MapRodata() {
MAP_PRIVATE | MAP_ANONYMOUS, fd, 0);
if (internal_iserror(page)) {
internal_close(fd);
- internal_unlink(filename);
return;
}
// Map the file into shadow of .rodata sections.
MemoryMappingLayout proc_maps(/*cache_enabled*/true);
uptr start, end, offset, prot;
- char name[128];
+ // Reusing the buffer 'name'.
while (proc_maps.Next(&start, &end, &offset, name, ARRAY_SIZE(name), &prot)) {
if (name[0] != 0 && name[0] != '['
&& (prot & MemoryMappingLayout::kProtectionRead)
@@ -200,7 +179,6 @@ static void MapRodata() {
}
}
internal_close(fd);
- internal_unlink(filename);
}
void InitializeShadowMemory() {
@@ -314,10 +292,10 @@ const char *InitializePlatform() {
// we re-exec the program with limited stack size as a best effort.
if (getlim(RLIMIT_STACK) == (rlim_t)-1) {
const uptr kMaxStackSize = 32 * 1024 * 1024;
- Report("WARNING: Program is run with unlimited stack size, which "
- "wouldn't work with ThreadSanitizer.\n");
- Report("Re-execing with stack size limited to %zd bytes.\n",
- kMaxStackSize);
+ VReport(1, "Program is run with unlimited stack size, which wouldn't "
+ "work with ThreadSanitizer.\n"
+ "Re-execing with stack size limited to %zd bytes.\n",
+ kMaxStackSize);
SetStackSizeLimitInBytes(kMaxStackSize);
reexec = true;
}
@@ -378,8 +356,19 @@ int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) {
}
return res;
}
-#endif
+int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,
+ void *abstime), void *c, void *m, void *abstime,
+ void(*cleanup)(void *arg), void *arg) {
+ // pthread_cleanup_push/pop are hardcore macros mess.
+ // We can't intercept nor call them w/o including pthread.h.
+ int res;
+ pthread_cleanup_push(cleanup, arg);
+ res = fn(c, m, abstime);
+ pthread_cleanup_pop(0);
+ return res;
+}
+#endif
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_platform_mac.cc b/libsanitizer/tsan/tsan_platform_mac.cc
index 3dca611dc92..c3d4d905219 100644
--- a/libsanitizer/tsan/tsan_platform_mac.cc
+++ b/libsanitizer/tsan/tsan_platform_mac.cc
@@ -38,17 +38,18 @@
namespace __tsan {
-ScopedInRtl::ScopedInRtl() {
+uptr GetShadowMemoryConsumption() {
+ return 0;
}
-ScopedInRtl::~ScopedInRtl() {
+void FlushShadowMemory() {
}
-uptr GetShadowMemoryConsumption() {
- return 0;
+void WriteMemoryProfile(char *buf, uptr buf_size) {
}
-void FlushShadowMemory() {
+uptr GetRSS() {
+ return 0;
}
#ifndef TSAN_GO
@@ -88,6 +89,20 @@ void FinalizePlatform() {
fflush(0);
}
+#ifndef TSAN_GO
+int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,
+ void *abstime), void *c, void *m, void *abstime,
+ void(*cleanup)(void *arg), void *arg) {
+ // pthread_cleanup_push/pop are hardcore macros mess.
+ // We can't intercept nor call them w/o including pthread.h.
+ int res;
+ pthread_cleanup_push(cleanup, arg);
+ res = fn(c, m, abstime);
+ pthread_cleanup_pop(0);
+ return res;
+}
+#endif
+
} // namespace __tsan
#endif // SANITIZER_MAC
diff --git a/libsanitizer/tsan/tsan_platform_windows.cc b/libsanitizer/tsan/tsan_platform_windows.cc
index 6e49ef42f0c..f16bebf7f4c 100644
--- a/libsanitizer/tsan/tsan_platform_windows.cc
+++ b/libsanitizer/tsan/tsan_platform_windows.cc
@@ -19,17 +19,18 @@
namespace __tsan {
-ScopedInRtl::ScopedInRtl() {
+uptr GetShadowMemoryConsumption() {
+ return 0;
}
-ScopedInRtl::~ScopedInRtl() {
+void FlushShadowMemory() {
}
-uptr GetShadowMemoryConsumption() {
- return 0;
+void WriteMemoryProfile(char *buf, uptr buf_size) {
}
-void FlushShadowMemory() {
+uptr GetRSS() {
+ return 0;
}
const char *InitializePlatform() {
diff --git a/libsanitizer/tsan/tsan_report.cc b/libsanitizer/tsan/tsan_report.cc
index f2484166e81..00a512e0cf8 100644
--- a/libsanitizer/tsan/tsan_report.cc
+++ b/libsanitizer/tsan/tsan_report.cc
@@ -38,6 +38,7 @@ ReportDesc::ReportDesc()
, locs(MBlockReportLoc)
, mutexes(MBlockReportMutex)
, threads(MBlockReportThread)
+ , unique_tids(MBlockReportThread)
, sleep()
, count() {
}
@@ -71,10 +72,20 @@ static const char *ReportTypeString(ReportType typ) {
return "thread leak";
if (typ == ReportTypeMutexDestroyLocked)
return "destroy of a locked mutex";
+ if (typ == ReportTypeMutexDoubleLock)
+ return "double lock of a mutex";
+ if (typ == ReportTypeMutexBadUnlock)
+ return "unlock of an unlocked mutex (or by a wrong thread)";
+ if (typ == ReportTypeMutexBadReadLock)
+ return "read lock of a write locked mutex";
+ if (typ == ReportTypeMutexBadReadUnlock)
+ return "read unlock of a write locked mutex";
if (typ == ReportTypeSignalUnsafe)
return "signal-unsafe call inside of a signal";
if (typ == ReportTypeErrnoInSignal)
return "signal handler spoils errno";
+ if (typ == ReportTypeDeadlock)
+ return "lock-order-inversion (potential deadlock)";
return "";
}
@@ -153,6 +164,17 @@ static void PrintLocation(const ReportLocation *loc) {
PrintStack(loc->stack);
}
+static void PrintMutexShort(const ReportMutex *rm, const char *after) {
+ Decorator d;
+ Printf("%sM%zd%s%s", d.Mutex(), rm->id, d.EndMutex(), after);
+}
+
+static void PrintMutexShortWithAddress(const ReportMutex *rm,
+ const char *after) {
+ Decorator d;
+ Printf("%sM%zd (%p)%s%s", d.Mutex(), rm->id, rm->addr, d.EndMutex(), after);
+}
+
static void PrintMutex(const ReportMutex *rm) {
Decorator d;
if (rm->destroyed) {
@@ -161,7 +183,7 @@ static void PrintMutex(const ReportMutex *rm) {
Printf("%s", d.EndMutex());
} else {
Printf("%s", d.Mutex());
- Printf(" Mutex M%llu created at:\n", rm->id);
+ Printf(" Mutex M%llu (%p) created at:\n", rm->id, rm->addr);
Printf("%s", d.EndMutex());
PrintStack(rm->stack);
}
@@ -221,10 +243,42 @@ void PrintReport(const ReportDesc *rep) {
(int)internal_getpid());
Printf("%s", d.EndWarning());
- for (uptr i = 0; i < rep->stacks.Size(); i++) {
- if (i)
- Printf(" and:\n");
- PrintStack(rep->stacks[i]);
+ if (rep->typ == ReportTypeDeadlock) {
+ char thrbuf[kThreadBufSize];
+ Printf(" Cycle in lock order graph: ");
+ for (uptr i = 0; i < rep->mutexes.Size(); i++)
+ PrintMutexShortWithAddress(rep->mutexes[i], " => ");
+ PrintMutexShort(rep->mutexes[0], "\n\n");
+ CHECK_GT(rep->mutexes.Size(), 0U);
+ CHECK_EQ(rep->mutexes.Size() * (flags()->second_deadlock_stack ? 2 : 1),
+ rep->stacks.Size());
+ for (uptr i = 0; i < rep->mutexes.Size(); i++) {
+ Printf(" Mutex ");
+ PrintMutexShort(rep->mutexes[(i + 1) % rep->mutexes.Size()],
+ " acquired here while holding mutex ");
+ PrintMutexShort(rep->mutexes[i], " in ");
+ Printf("%s", d.ThreadDescription());
+ Printf("%s:\n", thread_name(thrbuf, rep->unique_tids[i]));
+ Printf("%s", d.EndThreadDescription());
+ if (flags()->second_deadlock_stack) {
+ PrintStack(rep->stacks[2*i]);
+ Printf(" Mutex ");
+ PrintMutexShort(rep->mutexes[i],
+ " previously acquired by the same thread here:\n");
+ PrintStack(rep->stacks[2*i+1]);
+ } else {
+ PrintStack(rep->stacks[i]);
+ if (i == 0)
+ Printf(" Hint: use TSAN_OPTIONS=second_deadlock_stack=1 "
+ "to get more informative warning message\n\n");
+ }
+ }
+ } else {
+ for (uptr i = 0; i < rep->stacks.Size(); i++) {
+ if (i)
+ Printf(" and:\n");
+ PrintStack(rep->stacks[i]);
+ }
}
for (uptr i = 0; i < rep->mops.Size(); i++)
@@ -236,8 +290,10 @@ void PrintReport(const ReportDesc *rep) {
for (uptr i = 0; i < rep->locs.Size(); i++)
PrintLocation(rep->locs[i]);
- for (uptr i = 0; i < rep->mutexes.Size(); i++)
- PrintMutex(rep->mutexes[i]);
+ if (rep->typ != ReportTypeDeadlock) {
+ for (uptr i = 0; i < rep->mutexes.Size(); i++)
+ PrintMutex(rep->mutexes[i]);
+ }
for (uptr i = 0; i < rep->threads.Size(); i++)
PrintThread(rep->threads[i]);
@@ -289,11 +345,26 @@ static void PrintThread(const ReportThread *rt) {
void PrintReport(const ReportDesc *rep) {
Printf("==================\n");
- Printf("WARNING: DATA RACE");
- for (uptr i = 0; i < rep->mops.Size(); i++)
- PrintMop(rep->mops[i], i == 0);
- for (uptr i = 0; i < rep->threads.Size(); i++)
- PrintThread(rep->threads[i]);
+ if (rep->typ == ReportTypeRace) {
+ Printf("WARNING: DATA RACE");
+ for (uptr i = 0; i < rep->mops.Size(); i++)
+ PrintMop(rep->mops[i], i == 0);
+ for (uptr i = 0; i < rep->threads.Size(); i++)
+ PrintThread(rep->threads[i]);
+ } else if (rep->typ == ReportTypeDeadlock) {
+ Printf("WARNING: DEADLOCK\n");
+ for (uptr i = 0; i < rep->mutexes.Size(); i++) {
+ Printf("Goroutine %d lock mutex %d while holding mutex %d:\n",
+ 999, rep->mutexes[i]->id,
+ rep->mutexes[(i+1) % rep->mutexes.Size()]->id);
+ PrintStack(rep->stacks[2*i]);
+ Printf("\n");
+ Printf("Mutex %d was previously locked here:\n",
+ rep->mutexes[(i+1) % rep->mutexes.Size()]->id);
+ PrintStack(rep->stacks[2*i + 1]);
+ Printf("\n");
+ }
+ }
Printf("==================\n");
}
diff --git a/libsanitizer/tsan/tsan_report.h b/libsanitizer/tsan/tsan_report.h
index c0eef9eb023..d773e057af0 100644
--- a/libsanitizer/tsan/tsan_report.h
+++ b/libsanitizer/tsan/tsan_report.h
@@ -22,8 +22,13 @@ enum ReportType {
ReportTypeUseAfterFree,
ReportTypeThreadLeak,
ReportTypeMutexDestroyLocked,
+ ReportTypeMutexDoubleLock,
+ ReportTypeMutexBadUnlock,
+ ReportTypeMutexBadReadLock,
+ ReportTypeMutexBadReadUnlock,
ReportTypeSignalUnsafe,
- ReportTypeErrnoInSignal
+ ReportTypeErrnoInSignal,
+ ReportTypeDeadlock
};
struct ReportStack {
@@ -87,6 +92,7 @@ struct ReportThread {
struct ReportMutex {
u64 id;
+ uptr addr;
bool destroyed;
ReportStack *stack;
};
@@ -99,6 +105,7 @@ class ReportDesc {
Vector<ReportLocation*> locs;
Vector<ReportMutex*> mutexes;
Vector<ReportThread*> threads;
+ Vector<int> unique_tids;
ReportStack *sleep;
int count;
diff --git a/libsanitizer/tsan/tsan_rtl.cc b/libsanitizer/tsan/tsan_rtl.cc
index 573eeb8a918..7932a6d9e04 100644
--- a/libsanitizer/tsan/tsan_rtl.cc
+++ b/libsanitizer/tsan/tsan_rtl.cc
@@ -35,22 +35,21 @@ namespace __tsan {
THREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64);
#endif
static char ctx_placeholder[sizeof(Context)] ALIGNED(64);
+Context *ctx;
// Can be overriden by a front-end.
#ifdef TSAN_EXTERNAL_HOOKS
bool OnFinalize(bool failed);
+void OnInitialize();
#else
SANITIZER_INTERFACE_ATTRIBUTE
bool WEAK OnFinalize(bool failed) {
return failed;
}
+SANITIZER_INTERFACE_ATTRIBUTE
+void WEAK OnInitialize() {}
#endif
-static Context *ctx;
-Context *CTX() {
- return ctx;
-}
-
static char thread_registry_placeholder[sizeof(ThreadRegistry)];
static ThreadContextBase *CreateThreadContext(u32 tid) {
@@ -74,7 +73,7 @@ Context::Context()
, nreported()
, nmissed_expected()
, thread_registry(new(thread_registry_placeholder) ThreadRegistry(
- CreateThreadContext, kMaxTid, kThreadQuarantineSize))
+ CreateThreadContext, kMaxTid, kThreadQuarantineSize, kMaxTidReuse))
, racy_stacks(MBlockRacyStacks)
, racy_addresses(MBlockRacyAddresses)
, fired_suppressions(8) {
@@ -82,13 +81,15 @@ Context::Context()
// The objects are allocated in TLS, so one may rely on zero-initialization.
ThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,
+ unsigned reuse_count,
uptr stk_addr, uptr stk_size,
uptr tls_addr, uptr tls_size)
: fast_state(tid, epoch)
// Do not touch these, rely on zero initialization,
// they may be accessed before the ctor.
// , ignore_reads_and_writes()
- // , in_rtl()
+ // , ignore_interceptors()
+ , clock(tid, reuse_count)
#ifndef TSAN_GO
, jmp_bufs(MBlockJmpBuf)
#endif
@@ -97,7 +98,11 @@ ThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,
, stk_addr(stk_addr)
, stk_size(stk_size)
, tls_addr(tls_addr)
- , tls_size(tls_size) {
+ , tls_size(tls_size)
+#ifndef TSAN_GO
+ , last_sleep_clock(tid)
+#endif
+{
}
static void MemoryProfiler(Context *ctx, fd_t fd, int i) {
@@ -113,8 +118,13 @@ static void MemoryProfiler(Context *ctx, fd_t fd, int i) {
}
static void BackgroundThread(void *arg) {
- ScopedInRtl in_rtl;
- Context *ctx = CTX();
+#ifndef TSAN_GO
+ // This is a non-initialized non-user thread, nothing to see here.
+ // We don't use ScopedIgnoreInterceptors, because we want ignores to be
+ // enabled even when the thread function exits (e.g. during pthread thread
+ // shutdown code).
+ cur_thread()->ignore_interceptors++;
+#endif
const u64 kMs2Ns = 1000 * 1000;
fd_t mprof_fd = kInvalidFd;
@@ -133,8 +143,10 @@ static void BackgroundThread(void *arg) {
u64 last_flush = NanoTime();
uptr last_rss = 0;
- for (int i = 0; ; i++) {
- SleepForSeconds(1);
+ for (int i = 0;
+ atomic_load(&ctx->stop_background_thread, memory_order_relaxed) == 0;
+ i++) {
+ SleepForMillis(100);
u64 now = NanoTime();
// Flush memory if requested.
@@ -185,6 +197,16 @@ static void BackgroundThread(void *arg) {
}
}
+static void StartBackgroundThread() {
+ ctx->background_thread = internal_start_thread(&BackgroundThread, 0);
+}
+
+static void StopBackgroundThread() {
+ atomic_store(&ctx->stop_background_thread, 1, memory_order_relaxed);
+ internal_join_thread(ctx->background_thread);
+ ctx->background_thread = 0;
+}
+
void DontNeedShadowFor(uptr addr, uptr size) {
uptr shadow_beg = MemToShadow(addr);
uptr shadow_end = MemToShadow(addr + size);
@@ -192,6 +214,9 @@ void DontNeedShadowFor(uptr addr, uptr size) {
}
void MapShadow(uptr addr, uptr size) {
+ // Global data is not 64K aligned, but there are no adjacent mappings,
+ // so we can get away with unaligned mapping.
+ // CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment
MmapFixedNoReserve(MemToShadow(addr), size * kShadowMultiplier);
}
@@ -199,6 +224,7 @@ void MapThreadTrace(uptr addr, uptr size) {
DPrintf("#0: Mapping trace at %p-%p(0x%zx)\n", addr, addr + size, size);
CHECK_GE(addr, kTraceMemBegin);
CHECK_LE(addr + size, kTraceMemBegin + kTraceMemSize);
+ CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment
uptr addr1 = (uptr)MmapFixedNoReserve(addr, size);
if (addr1 != addr) {
Printf("FATAL: ThreadSanitizer can not mmap thread trace (%p/%p->%p)\n",
@@ -213,11 +239,12 @@ void Initialize(ThreadState *thr) {
if (is_initialized)
return;
is_initialized = true;
+ // We are not ready to handle interceptors yet.
+ ScopedIgnoreInterceptors ignore;
SanitizerToolName = "ThreadSanitizer";
// Install tool-specific callbacks in sanitizer_common.
SetCheckFailedCallback(TsanCheckFailed);
- ScopedInRtl in_rtl;
#ifndef TSAN_GO
InitializeAllocator();
#endif
@@ -235,19 +262,13 @@ void Initialize(ThreadState *thr) {
InitializeSuppressions();
#ifndef TSAN_GO
InitializeLibIgnore();
- // Initialize external symbolizer before internal threads are started.
- const char *external_symbolizer = flags()->external_symbolizer_path;
- bool external_symbolizer_started =
- Symbolizer::Init(external_symbolizer)->IsExternalAvailable();
- if (external_symbolizer != 0 && external_symbolizer[0] != '\0' &&
- !external_symbolizer_started) {
- Printf("Failed to start external symbolizer: '%s'\n",
- external_symbolizer);
- Die();
- }
+ Symbolizer::Init(common_flags()->external_symbolizer_path);
Symbolizer::Get()->AddHooks(EnterSymbolizer, ExitSymbolizer);
#endif
- internal_start_thread(&BackgroundThread, 0);
+ StartBackgroundThread();
+ SetSandboxingCallback(StopBackgroundThread);
+ if (flags()->detect_deadlocks)
+ ctx->dd = DDetector::Create(flags());
if (ctx->flags.verbosity)
Printf("***** Running under ThreadSanitizer v2 (pid %d) *****\n",
@@ -257,7 +278,6 @@ void Initialize(ThreadState *thr) {
int tid = ThreadCreate(thr, 0, 0, true);
CHECK_EQ(tid, 0);
ThreadStart(thr, tid, internal_getpid());
- CHECK_EQ(thr->in_rtl, 1);
ctx->initialized = true;
if (flags()->stop_on_start) {
@@ -266,10 +286,11 @@ void Initialize(ThreadState *thr) {
(int)internal_getpid());
while (__tsan_resumed == 0) {}
}
+
+ OnInitialize();
}
int Finalize(ThreadState *thr) {
- ScopedInRtl in_rtl;
Context *ctx = __tsan::ctx;
bool failed = false;
@@ -319,6 +340,38 @@ int Finalize(ThreadState *thr) {
}
#ifndef TSAN_GO
+void ForkBefore(ThreadState *thr, uptr pc) {
+ ctx->thread_registry->Lock();
+ ctx->report_mtx.Lock();
+}
+
+void ForkParentAfter(ThreadState *thr, uptr pc) {
+ ctx->report_mtx.Unlock();
+ ctx->thread_registry->Unlock();
+}
+
+void ForkChildAfter(ThreadState *thr, uptr pc) {
+ ctx->report_mtx.Unlock();
+ ctx->thread_registry->Unlock();
+
+ uptr nthread = 0;
+ ctx->thread_registry->GetNumberOfThreads(0, 0, &nthread /* alive threads */);
+ VPrintf(1, "ThreadSanitizer: forked new process with pid %d,"
+ " parent had %d threads\n", (int)internal_getpid(), (int)nthread);
+ if (nthread == 1) {
+ internal_start_thread(&BackgroundThread, 0);
+ } else {
+ // We've just forked a multi-threaded process. We cannot reasonably function
+ // after that (some mutexes may be locked before fork). So just enable
+ // ignores for everything in the hope that we will exec soon.
+ ctx->after_multithreaded_fork = true;
+ thr->ignore_interceptors++;
+ ThreadIgnoreBegin(thr, pc);
+ ThreadIgnoreSyncBegin(thr, pc);
+ }
+}
+#endif
+
u32 CurrentStackId(ThreadState *thr, uptr pc) {
if (thr->shadow_stack_pos == 0) // May happen during bootstrap.
return 0;
@@ -332,11 +385,9 @@ u32 CurrentStackId(ThreadState *thr, uptr pc) {
thr->shadow_stack_pos--;
return id;
}
-#endif
void TraceSwitch(ThreadState *thr) {
thr->nomalloc++;
- ScopedInRtl in_rtl;
Trace *thr_trace = ThreadTrace(thr->tid);
Lock l(&thr_trace->mtx);
unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts();
@@ -541,17 +592,19 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
FastState fast_state = thr->fast_state;
if (fast_state.GetIgnoreBit())
return;
- fast_state.IncrementEpoch();
- thr->fast_state = fast_state;
+ if (kCollectHistory) {
+ fast_state.IncrementEpoch();
+ thr->fast_state = fast_state;
+ // We must not store to the trace if we do not store to the shadow.
+ // That is, this call must be moved somewhere below.
+ TraceAddEvent(thr, fast_state, EventTypeMop, pc);
+ }
+
Shadow cur(fast_state);
cur.SetAddr0AndSizeLog(addr & 7, kAccessSizeLog);
cur.SetWrite(kAccessIsWrite);
cur.SetAtomic(kIsAtomic);
- // We must not store to the trace if we do not store to the shadow.
- // That is, this call must be moved somewhere below.
- TraceAddEvent(thr, fast_state, EventTypeMop, pc);
-
MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic,
shadow_mem, cur);
}
@@ -581,7 +634,7 @@ static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1);
// UnmapOrDie/MmapFixedNoReserve does not work on Windows,
// so we do it only for C/C++.
- if (kGoMode || size < 64*1024) {
+ if (kGoMode || size < common_flags()->clear_shadow_mmap_threshold) {
u64 *p = (u64*)MemToShadow(addr);
CHECK(IsShadowMem((uptr)p));
CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1)));
@@ -631,8 +684,10 @@ void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) {
thr->is_freeing = true;
MemoryAccessRange(thr, pc, addr, size, true);
thr->is_freeing = false;
- thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeMop, pc);
+ if (kCollectHistory) {
+ thr->fast_state.IncrementEpoch();
+ TraceAddEvent(thr, thr->fast_state, EventTypeMop, pc);
+ }
Shadow s(thr->fast_state);
s.ClearIgnoreBit();
s.MarkAsFreed();
@@ -642,8 +697,10 @@ void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) {
}
void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) {
- thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeMop, pc);
+ if (kCollectHistory) {
+ thr->fast_state.IncrementEpoch();
+ TraceAddEvent(thr, thr->fast_state, EventTypeMop, pc);
+ }
Shadow s(thr->fast_state);
s.ClearIgnoreBit();
s.SetWrite(true);
@@ -653,11 +710,12 @@ void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) {
ALWAYS_INLINE USED
void FuncEntry(ThreadState *thr, uptr pc) {
- DCHECK_EQ(thr->in_rtl, 0);
StatInc(thr, StatFuncEnter);
DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc);
- thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeFuncEnter, pc);
+ if (kCollectHistory) {
+ thr->fast_state.IncrementEpoch();
+ TraceAddEvent(thr, thr->fast_state, EventTypeFuncEnter, pc);
+ }
// Shadow stack maintenance can be replaced with
// stack unwinding during trace switch (which presumably must be faster).
@@ -683,11 +741,12 @@ void FuncEntry(ThreadState *thr, uptr pc) {
ALWAYS_INLINE USED
void FuncExit(ThreadState *thr) {
- DCHECK_EQ(thr->in_rtl, 0);
StatInc(thr, StatFuncExit);
DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid());
- thr->fast_state.IncrementEpoch();
- TraceAddEvent(thr, thr->fast_state, EventTypeFuncExit, 0);
+ if (kCollectHistory) {
+ thr->fast_state.IncrementEpoch();
+ TraceAddEvent(thr, thr->fast_state, EventTypeFuncExit, 0);
+ }
DCHECK_GT(thr->shadow_stack_pos, thr->shadow_stack);
#ifndef TSAN_GO
@@ -702,7 +761,8 @@ void ThreadIgnoreBegin(ThreadState *thr, uptr pc) {
CHECK_GT(thr->ignore_reads_and_writes, 0);
thr->fast_state.SetIgnoreBit();
#ifndef TSAN_GO
- thr->mop_ignore_set.Add(CurrentStackId(thr, pc));
+ if (!ctx->after_multithreaded_fork)
+ thr->mop_ignore_set.Add(CurrentStackId(thr, pc));
#endif
}
@@ -723,7 +783,8 @@ void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc) {
thr->ignore_sync++;
CHECK_GT(thr->ignore_sync, 0);
#ifndef TSAN_GO
- thr->sync_ignore_set.Add(CurrentStackId(thr, pc));
+ if (!ctx->after_multithreaded_fork)
+ thr->sync_ignore_set.Add(CurrentStackId(thr, pc));
#endif
}
@@ -733,7 +794,7 @@ void ThreadIgnoreSyncEnd(ThreadState *thr, uptr pc) {
CHECK_GE(thr->ignore_sync, 0);
#ifndef TSAN_GO
if (thr->ignore_sync == 0)
- thr->mop_ignore_set.Reset();
+ thr->sync_ignore_set.Reset();
#endif
}
diff --git a/libsanitizer/tsan/tsan_rtl.h b/libsanitizer/tsan/tsan_rtl.h
index 20493ea4d3b..e6bc8b28595 100644
--- a/libsanitizer/tsan/tsan_rtl.h
+++ b/libsanitizer/tsan/tsan_rtl.h
@@ -28,6 +28,7 @@
#include "sanitizer_common/sanitizer_allocator_internal.h"
#include "sanitizer_common/sanitizer_asm.h"
#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
#include "sanitizer_common/sanitizer_libignore.h"
#include "sanitizer_common/sanitizer_suppressions.h"
#include "sanitizer_common/sanitizer_thread_registry.h"
@@ -431,11 +432,11 @@ struct ThreadState {
AllocatorCache alloc_cache;
InternalAllocatorCache internal_alloc_cache;
Vector<JmpBuf> jmp_bufs;
+ int ignore_interceptors;
#endif
u64 stat[StatCnt];
const int tid;
const int unique_id;
- int in_rtl;
bool in_symbolizer;
bool in_ignored_lib;
bool is_alive;
@@ -447,7 +448,9 @@ struct ThreadState {
const uptr tls_size;
ThreadContext *tctx;
- DeadlockDetector deadlock_detector;
+ InternalDeadlockDetector internal_deadlock_detector;
+ DDPhysicalThread *dd_pt;
+ DDLogicalThread *dd_lt;
bool in_signal_handler;
SignalContext *signal_ctx;
@@ -462,13 +465,13 @@ struct ThreadState {
int nomalloc;
explicit ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,
+ unsigned reuse_count,
uptr stk_addr, uptr stk_size,
uptr tls_addr, uptr tls_size);
};
-Context *CTX();
-
#ifndef TSAN_GO
+__attribute__((tls_model("initial-exec")))
extern THREADLOCAL char cur_thread_placeholder[];
INLINE ThreadState *cur_thread() {
return reinterpret_cast<ThreadState *>(&cur_thread_placeholder);
@@ -480,11 +483,7 @@ class ThreadContext : public ThreadContextBase {
explicit ThreadContext(int tid);
~ThreadContext();
ThreadState *thr;
-#ifdef TSAN_GO
- StackTrace creation_stack;
-#else
u32 creation_stack_id;
-#endif
SyncClock sync;
// Epoch at which the thread had started.
// If we see an event from the thread stamped by an older epoch,
@@ -527,6 +526,7 @@ struct Context {
Context();
bool initialized;
+ bool after_multithreaded_fork;
SyncTab synctab;
@@ -535,12 +535,16 @@ struct Context {
int nmissed_expected;
atomic_uint64_t last_symbolize_time_ns;
+ void *background_thread;
+ atomic_uint32_t stop_background_thread;
+
ThreadRegistry *thread_registry;
Vector<RacyStacks> racy_stacks;
Vector<RacyAddress> racy_addresses;
// Number of fired suppressions may be large enough.
InternalMmapVector<FiredSuppression> fired_suppressions;
+ DDetector *dd;
Flags flags;
@@ -549,14 +553,20 @@ struct Context {
u64 int_alloc_siz[MBlockTypeCount];
};
-class ScopedInRtl {
- public:
- ScopedInRtl();
- ~ScopedInRtl();
- private:
- ThreadState*thr_;
- int in_rtl_;
- int errno_;
+extern Context *ctx; // The one and the only global runtime context.
+
+struct ScopedIgnoreInterceptors {
+ ScopedIgnoreInterceptors() {
+#ifndef TSAN_GO
+ cur_thread()->ignore_interceptors++;
+#endif
+ }
+
+ ~ScopedIgnoreInterceptors() {
+#ifndef TSAN_GO
+ cur_thread()->ignore_interceptors--;
+#endif
+ }
};
class ScopedReport {
@@ -568,7 +578,10 @@ class ScopedReport {
void AddMemoryAccess(uptr addr, Shadow s, const StackTrace *stack,
const MutexSet *mset);
void AddThread(const ThreadContext *tctx);
+ void AddThread(int unique_tid);
+ void AddUniqueTid(int unique_tid);
void AddMutex(const SyncVar *s);
+ u64 AddMutex(u64 id);
void AddLocation(uptr addr, uptr size);
void AddSleep(u32 stack_id);
void SetCount(int count);
@@ -576,10 +589,12 @@ class ScopedReport {
const ReportDesc *GetReport() const;
private:
- Context *ctx_;
ReportDesc *rep_;
+ // Symbolizer makes lots of intercepted calls. If we try to process them,
+ // at best it will cause deadlocks on internal mutexes.
+ ScopedIgnoreInterceptors ignore_interceptors_;
- void AddMutex(u64 id);
+ void AddDeadMutex(u64 id);
ScopedReport(const ScopedReport&);
void operator = (const ScopedReport&);
@@ -606,10 +621,14 @@ void InitializeInterceptors();
void InitializeLibIgnore();
void InitializeDynamicAnnotations();
+void ForkBefore(ThreadState *thr, uptr pc);
+void ForkParentAfter(ThreadState *thr, uptr pc);
+void ForkChildAfter(ThreadState *thr, uptr pc);
+
void ReportRace(ThreadState *thr);
bool OutputReport(Context *ctx,
const ScopedReport &srep,
- const ReportStack *suppress_stack1 = 0,
+ const ReportStack *suppress_stack1,
const ReportStack *suppress_stack2 = 0,
const ReportLocation *suppress_loc = 0);
bool IsFiredSuppression(Context *ctx,
@@ -707,9 +726,10 @@ void ProcessPendingSignals(ThreadState *thr);
void MutexCreate(ThreadState *thr, uptr pc, uptr addr,
bool rw, bool recursive, bool linker_init);
void MutexDestroy(ThreadState *thr, uptr pc, uptr addr);
-void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec = 1);
+void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec = 1,
+ bool try_lock = false);
int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all = false);
-void MutexReadLock(ThreadState *thr, uptr pc, uptr addr);
+void MutexReadLock(ThreadState *thr, uptr pc, uptr addr, bool try_lock = false);
void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr);
void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr);
void MutexRepair(ThreadState *thr, uptr pc, uptr addr); // call on EOWNERDEAD
@@ -754,6 +774,8 @@ Trace *ThreadTrace(int tid);
extern "C" void __tsan_trace_switch();
void ALWAYS_INLINE TraceAddEvent(ThreadState *thr, FastState fs,
EventType typ, u64 addr) {
+ if (!kCollectHistory)
+ return;
DCHECK_GE((int)typ, 0);
DCHECK_LE((int)typ, 7);
DCHECK_EQ(GetLsb(addr, 61), addr);
diff --git a/libsanitizer/tsan/tsan_rtl_mutex.cc b/libsanitizer/tsan/tsan_rtl_mutex.cc
index d9a3a3baa3f..3724571cfff 100644
--- a/libsanitizer/tsan/tsan_rtl_mutex.cc
+++ b/libsanitizer/tsan/tsan_rtl_mutex.cc
@@ -9,6 +9,9 @@
//
//===----------------------------------------------------------------------===//
+#include <sanitizer_common/sanitizer_deadlock_detector_interface.h>
+#include <sanitizer_common/sanitizer_stackdepot.h>
+
#include "tsan_rtl.h"
#include "tsan_flags.h"
#include "tsan_sync.h"
@@ -18,10 +21,47 @@
namespace __tsan {
+void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r);
+
+struct Callback : DDCallback {
+ ThreadState *thr;
+ uptr pc;
+
+ Callback(ThreadState *thr, uptr pc)
+ : thr(thr)
+ , pc(pc) {
+ DDCallback::pt = thr->dd_pt;
+ DDCallback::lt = thr->dd_lt;
+ }
+
+ virtual u32 Unwind() {
+ return CurrentStackId(thr, pc);
+ }
+ virtual int UniqueTid() {
+ return thr->unique_id;
+ }
+};
+
+void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexInit(&cb, &s->dd);
+ s->dd.ctx = s->GetId();
+}
+
+static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ,
+ uptr addr, u64 mid) {
+ ThreadRegistryLock l(ctx->thread_registry);
+ ScopedReport rep(typ);
+ rep.AddMutex(mid);
+ StackTrace trace;
+ trace.ObtainCurrent(thr, pc);
+ rep.AddStack(&trace);
+ rep.AddLocation(addr, 1);
+ OutputReport(ctx, rep, rep.GetReport()->stacks[0]);
+}
+
void MutexCreate(ThreadState *thr, uptr pc, uptr addr,
bool rw, bool recursive, bool linker_init) {
- Context *ctx = CTX();
- CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: MutexCreate %zx\n", thr->tid, addr);
StatInc(thr, StatMutexCreate);
if (!linker_init && IsAppMem(addr)) {
@@ -38,8 +78,6 @@ void MutexCreate(ThreadState *thr, uptr pc, uptr addr,
}
void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) {
- Context *ctx = CTX();
- CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: MutexDestroy %zx\n", thr->tid, addr);
StatInc(thr, StatMutexDestroy);
#ifndef TSAN_GO
@@ -51,6 +89,10 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) {
SyncVar *s = ctx->synctab.GetAndRemove(thr, pc, addr);
if (s == 0)
return;
+ if (flags()->detect_deadlocks) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexDestroy(&cb, &s->dd);
+ }
if (IsAppMem(addr)) {
CHECK(!thr->is_freeing);
thr->is_freeing = true;
@@ -71,30 +113,30 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) {
RestoreStack(last.tid(), last.epoch(), &trace, 0);
rep.AddStack(&trace);
rep.AddLocation(s->addr, 1);
- OutputReport(ctx, rep);
+ OutputReport(ctx, rep, rep.GetReport()->stacks[0]);
}
thr->mset.Remove(s->GetId());
DestroyAndFree(s);
}
-void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec) {
- CHECK_GT(thr->in_rtl, 0);
+void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec, bool try_lock) {
DPrintf("#%d: MutexLock %zx rec=%d\n", thr->tid, addr, rec);
CHECK_GT(rec, 0);
if (IsAppMem(addr))
MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeLock, s->GetId());
+ bool report_double_lock = false;
if (s->owner_tid == SyncVar::kInvalidTid) {
CHECK_EQ(s->recursion, 0);
s->owner_tid = thr->tid;
s->last_lock = thr->fast_state.raw();
} else if (s->owner_tid == thr->tid) {
CHECK_GT(s->recursion, 0);
- } else {
- Printf("ThreadSanitizer WARNING: double lock of mutex %p\n", addr);
- PrintCurrentStack(thr, pc);
+ } else if (flags()->report_mutex_bugs && !s->is_broken) {
+ s->is_broken = true;
+ report_double_lock = true;
}
if (s->recursion == 0) {
StatInc(thr, StatMutexLock);
@@ -105,30 +147,36 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec) {
}
s->recursion += rec;
thr->mset.Add(s->GetId(), true, thr->fast_state.epoch());
+ if (flags()->detect_deadlocks && s->recursion == 1) {
+ Callback cb(thr, pc);
+ if (!try_lock)
+ ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
+ ctx->dd->MutexAfterLock(&cb, &s->dd, true, try_lock);
+ }
+ u64 mid = s->GetId();
s->mtx.Unlock();
+ // Can't touch s after this point.
+ if (report_double_lock)
+ ReportMutexMisuse(thr, pc, ReportTypeMutexDoubleLock, addr, mid);
+ if (flags()->detect_deadlocks) {
+ Callback cb(thr, pc);
+ ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
+ }
}
int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
- CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: MutexUnlock %zx all=%d\n", thr->tid, addr, all);
if (IsAppMem(addr))
MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
int rec = 0;
- if (s->recursion == 0) {
- if (!s->is_broken) {
- s->is_broken = true;
- Printf("ThreadSanitizer WARNING: unlock of unlocked mutex %p\n", addr);
- PrintCurrentStack(thr, pc);
- }
- } else if (s->owner_tid != thr->tid) {
- if (!s->is_broken) {
+ bool report_bad_unlock = false;
+ if (s->recursion == 0 || s->owner_tid != thr->tid) {
+ if (flags()->report_mutex_bugs && !s->is_broken) {
s->is_broken = true;
- Printf("ThreadSanitizer WARNING: mutex %p is unlocked by wrong thread\n",
- addr);
- PrintCurrentStack(thr, pc);
+ report_bad_unlock = true;
}
} else {
rec = all ? s->recursion : 1;
@@ -142,56 +190,96 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
}
}
thr->mset.Del(s->GetId(), true);
+ if (flags()->detect_deadlocks && s->recursion == 0) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexBeforeUnlock(&cb, &s->dd, true);
+ }
+ u64 mid = s->GetId();
s->mtx.Unlock();
+ // Can't touch s after this point.
+ if (report_bad_unlock)
+ ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr, mid);
+ if (flags()->detect_deadlocks) {
+ Callback cb(thr, pc);
+ ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
+ }
return rec;
}
-void MutexReadLock(ThreadState *thr, uptr pc, uptr addr) {
- CHECK_GT(thr->in_rtl, 0);
+void MutexReadLock(ThreadState *thr, uptr pc, uptr addr, bool trylock) {
DPrintf("#%d: MutexReadLock %zx\n", thr->tid, addr);
StatInc(thr, StatMutexReadLock);
if (IsAppMem(addr))
MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, false);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, false);
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeRLock, s->GetId());
+ bool report_bad_lock = false;
if (s->owner_tid != SyncVar::kInvalidTid) {
- Printf("ThreadSanitizer WARNING: read lock of a write locked mutex %p\n",
- addr);
- PrintCurrentStack(thr, pc);
+ if (flags()->report_mutex_bugs && !s->is_broken) {
+ s->is_broken = true;
+ report_bad_lock = true;
+ }
}
AcquireImpl(thr, pc, &s->clock);
s->last_lock = thr->fast_state.raw();
thr->mset.Add(s->GetId(), false, thr->fast_state.epoch());
+ if (flags()->detect_deadlocks && s->recursion == 0) {
+ Callback cb(thr, pc);
+ if (!trylock)
+ ctx->dd->MutexBeforeLock(&cb, &s->dd, false);
+ ctx->dd->MutexAfterLock(&cb, &s->dd, false, trylock);
+ }
+ u64 mid = s->GetId();
s->mtx.ReadUnlock();
+ // Can't touch s after this point.
+ if (report_bad_lock)
+ ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadLock, addr, mid);
+ if (flags()->detect_deadlocks) {
+ Callback cb(thr, pc);
+ ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
+ }
}
void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
- CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: MutexReadUnlock %zx\n", thr->tid, addr);
StatInc(thr, StatMutexReadUnlock);
if (IsAppMem(addr))
MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
+ bool report_bad_unlock = false;
if (s->owner_tid != SyncVar::kInvalidTid) {
- Printf("ThreadSanitizer WARNING: read unlock of a write locked mutex %p\n",
- addr);
- PrintCurrentStack(thr, pc);
+ if (flags()->report_mutex_bugs && !s->is_broken) {
+ s->is_broken = true;
+ report_bad_unlock = true;
+ }
}
ReleaseImpl(thr, pc, &s->read_clock);
+ if (flags()->detect_deadlocks && s->recursion == 0) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexBeforeUnlock(&cb, &s->dd, false);
+ }
+ u64 mid = s->GetId();
s->mtx.Unlock();
- thr->mset.Del(s->GetId(), false);
+ // Can't touch s after this point.
+ thr->mset.Del(mid, false);
+ if (report_bad_unlock)
+ ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadUnlock, addr, mid);
+ if (flags()->detect_deadlocks) {
+ Callback cb(thr, pc);
+ ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
+ }
}
void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
- CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: MutexReadOrWriteUnlock %zx\n", thr->tid, addr);
if (IsAppMem(addr))
MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
bool write = true;
+ bool report_bad_unlock = false;
if (s->owner_tid == SyncVar::kInvalidTid) {
// Seems to be read unlock.
write = false;
@@ -214,17 +302,25 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
}
} else if (!s->is_broken) {
s->is_broken = true;
- Printf("ThreadSanitizer WARNING: mutex %p is unlock by wrong thread\n",
- addr);
- PrintCurrentStack(thr, pc);
+ report_bad_unlock = true;
}
thr->mset.Del(s->GetId(), write);
+ if (flags()->detect_deadlocks && s->recursion == 0) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexBeforeUnlock(&cb, &s->dd, write);
+ }
+ u64 mid = s->GetId();
s->mtx.Unlock();
+ // Can't touch s after this point.
+ if (report_bad_unlock)
+ ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr, mid);
+ if (flags()->detect_deadlocks) {
+ Callback cb(thr, pc);
+ ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
+ }
}
void MutexRepair(ThreadState *thr, uptr pc, uptr addr) {
- Context *ctx = CTX();
- CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: MutexRepair %zx\n", thr->tid, addr);
SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
s->owner_tid = SyncVar::kInvalidTid;
@@ -233,11 +329,10 @@ void MutexRepair(ThreadState *thr, uptr pc, uptr addr) {
}
void Acquire(ThreadState *thr, uptr pc, uptr addr) {
- CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: Acquire %zx\n", thr->tid, addr);
if (thr->ignore_sync)
return;
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, false);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, false);
AcquireImpl(thr, pc, &s->clock);
s->mtx.ReadUnlock();
}
@@ -255,17 +350,16 @@ void AcquireGlobal(ThreadState *thr, uptr pc) {
DPrintf("#%d: AcquireGlobal\n", thr->tid);
if (thr->ignore_sync)
return;
- ThreadRegistryLock l(CTX()->thread_registry);
- CTX()->thread_registry->RunCallbackForEachThreadLocked(
+ ThreadRegistryLock l(ctx->thread_registry);
+ ctx->thread_registry->RunCallbackForEachThreadLocked(
UpdateClockCallback, thr);
}
void Release(ThreadState *thr, uptr pc, uptr addr) {
- CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: Release %zx\n", thr->tid, addr);
if (thr->ignore_sync)
return;
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->fast_state.IncrementEpoch();
// Can't increment epoch w/o writing to the trace as well.
TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
@@ -274,11 +368,10 @@ void Release(ThreadState *thr, uptr pc, uptr addr) {
}
void ReleaseStore(ThreadState *thr, uptr pc, uptr addr) {
- CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: ReleaseStore %zx\n", thr->tid, addr);
if (thr->ignore_sync)
return;
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->fast_state.IncrementEpoch();
// Can't increment epoch w/o writing to the trace as well.
TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
@@ -301,8 +394,8 @@ void AfterSleep(ThreadState *thr, uptr pc) {
if (thr->ignore_sync)
return;
thr->last_sleep_stack_id = CurrentStackId(thr, pc);
- ThreadRegistryLock l(CTX()->thread_registry);
- CTX()->thread_registry->RunCallbackForEachThreadLocked(
+ ThreadRegistryLock l(ctx->thread_registry);
+ ctx->thread_registry->RunCallbackForEachThreadLocked(
UpdateSleepClockCallback, thr);
}
#endif
@@ -310,7 +403,7 @@ void AfterSleep(ThreadState *thr, uptr pc) {
void AcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) {
if (thr->ignore_sync)
return;
- thr->clock.set(thr->tid, thr->fast_state.epoch());
+ thr->clock.set(thr->fast_state.epoch());
thr->clock.acquire(c);
StatInc(thr, StatSyncAcquire);
}
@@ -318,7 +411,7 @@ void AcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) {
void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) {
if (thr->ignore_sync)
return;
- thr->clock.set(thr->tid, thr->fast_state.epoch());
+ thr->clock.set(thr->fast_state.epoch());
thr->fast_synch_epoch = thr->fast_state.epoch();
thr->clock.release(c);
StatInc(thr, StatSyncRelease);
@@ -327,7 +420,7 @@ void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) {
void ReleaseStoreImpl(ThreadState *thr, uptr pc, SyncClock *c) {
if (thr->ignore_sync)
return;
- thr->clock.set(thr->tid, thr->fast_state.epoch());
+ thr->clock.set(thr->fast_state.epoch());
thr->fast_synch_epoch = thr->fast_state.epoch();
thr->clock.ReleaseStore(c);
StatInc(thr, StatSyncRelease);
@@ -336,11 +429,43 @@ void ReleaseStoreImpl(ThreadState *thr, uptr pc, SyncClock *c) {
void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) {
if (thr->ignore_sync)
return;
- thr->clock.set(thr->tid, thr->fast_state.epoch());
+ thr->clock.set(thr->fast_state.epoch());
thr->fast_synch_epoch = thr->fast_state.epoch();
thr->clock.acq_rel(c);
StatInc(thr, StatSyncAcquire);
StatInc(thr, StatSyncRelease);
}
+void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
+ if (r == 0)
+ return;
+ ThreadRegistryLock l(ctx->thread_registry);
+ ScopedReport rep(ReportTypeDeadlock);
+ for (int i = 0; i < r->n; i++) {
+ rep.AddMutex(r->loop[i].mtx_ctx0);
+ rep.AddUniqueTid((int)r->loop[i].thr_ctx);
+ rep.AddThread((int)r->loop[i].thr_ctx);
+ }
+ StackTrace stacks[2 * DDReport::kMaxLoopSize];
+ uptr dummy_pc = 0x42;
+ for (int i = 0; i < r->n; i++) {
+ uptr size;
+ for (int j = 0; j < (flags()->second_deadlock_stack ? 2 : 1); j++) {
+ u32 stk = r->loop[i].stk[j];
+ if (stk) {
+ const uptr *trace = StackDepotGet(stk, &size);
+ stacks[i].Init(const_cast<uptr *>(trace), size);
+ } else {
+ // Sometimes we fail to extract the stack trace (FIXME: investigate),
+ // but we should still produce some stack trace in the report.
+ stacks[i].Init(&dummy_pc, 1);
+ }
+ rep.AddStack(&stacks[i]);
+ }
+ }
+ // FIXME: use all stacks for suppressions, not just the second stack of the
+ // first edge.
+ OutputReport(ctx, rep, rep.GetReport()->stacks[0]);
+}
+
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_rtl_report.cc b/libsanitizer/tsan/tsan_rtl_report.cc
index f2248afeab2..d19deb066df 100644
--- a/libsanitizer/tsan/tsan_rtl_report.cc
+++ b/libsanitizer/tsan/tsan_rtl_report.cc
@@ -32,7 +32,10 @@ static ReportStack *SymbolizeStack(const StackTrace& trace);
void TsanCheckFailed(const char *file, int line, const char *cond,
u64 v1, u64 v2) {
- ScopedInRtl in_rtl;
+ // There is high probability that interceptors will check-fail as well,
+ // on the other hand there is no sense in processing interceptors
+ // since we are going to die soon.
+ ScopedIgnoreInterceptors ignore;
Printf("FATAL: ThreadSanitizer CHECK failed: "
"%s:%d \"%s\" (0x%zx, 0x%zx)\n",
file, line, cond, (uptr)v1, (uptr)v2);
@@ -99,8 +102,9 @@ static void StackStripMain(ReportStack *stack) {
#endif
}
-#ifndef TSAN_GO
ReportStack *SymbolizeStackId(u32 stack_id) {
+ if (stack_id == 0)
+ return 0;
uptr ssz = 0;
const uptr *stack = StackDepotGet(stack_id, &ssz);
if (stack == 0)
@@ -109,7 +113,6 @@ ReportStack *SymbolizeStackId(u32 stack_id) {
trace.Init(stack, ssz);
return SymbolizeStack(trace);
}
-#endif
static ReportStack *SymbolizeStack(const StackTrace& trace) {
if (trace.IsEmpty())
@@ -143,18 +146,17 @@ static ReportStack *SymbolizeStack(const StackTrace& trace) {
}
ScopedReport::ScopedReport(ReportType typ) {
- ctx_ = CTX();
- ctx_->thread_registry->CheckLocked();
+ ctx->thread_registry->CheckLocked();
void *mem = internal_alloc(MBlockReport, sizeof(ReportDesc));
rep_ = new(mem) ReportDesc;
rep_->typ = typ;
- ctx_->report_mtx.Lock();
+ ctx->report_mtx.Lock();
CommonSanitizerReportMutex.Lock();
}
ScopedReport::~ScopedReport() {
CommonSanitizerReportMutex.Unlock();
- ctx_->report_mtx.Unlock();
+ ctx->report_mtx.Unlock();
DestroyAndFree(rep_);
}
@@ -176,26 +178,16 @@ void ScopedReport::AddMemoryAccess(uptr addr, Shadow s,
mop->stack = SymbolizeStack(*stack);
for (uptr i = 0; i < mset->Size(); i++) {
MutexSet::Desc d = mset->Get(i);
- u64 uid = 0;
- uptr addr = SyncVar::SplitId(d.id, &uid);
- SyncVar *s = ctx_->synctab.GetIfExistsAndLock(addr, false);
- // Check that the mutex is still alive.
- // Another mutex can be created at the same address,
- // so check uid as well.
- if (s && s->CheckId(uid)) {
- ReportMopMutex mtx = {s->uid, d.write};
- mop->mset.PushBack(mtx);
- AddMutex(s);
- } else {
- ReportMopMutex mtx = {d.id, d.write};
- mop->mset.PushBack(mtx);
- AddMutex(d.id);
- }
- if (s)
- s->mtx.ReadUnlock();
+ u64 mid = this->AddMutex(d.id);
+ ReportMopMutex mtx = {mid, d.write};
+ mop->mset.PushBack(mtx);
}
}
+void ScopedReport::AddUniqueTid(int unique_tid) {
+ rep_->unique_tids.PushBack(unique_tid);
+}
+
void ScopedReport::AddThread(const ThreadContext *tctx) {
for (uptr i = 0; i < rep_->threads.Size(); i++) {
if ((u32)rep_->threads[i]->id == tctx->tid)
@@ -207,19 +199,14 @@ void ScopedReport::AddThread(const ThreadContext *tctx) {
rt->id = tctx->tid;
rt->pid = tctx->os_id;
rt->running = (tctx->status == ThreadStatusRunning);
- rt->name = tctx->name ? internal_strdup(tctx->name) : 0;
+ rt->name = internal_strdup(tctx->name);
rt->parent_tid = tctx->parent_tid;
rt->stack = 0;
-#ifdef TSAN_GO
- rt->stack = SymbolizeStack(tctx->creation_stack);
-#else
rt->stack = SymbolizeStackId(tctx->creation_stack_id);
-#endif
}
#ifndef TSAN_GO
static ThreadContext *FindThreadByUidLocked(int unique_id) {
- Context *ctx = CTX();
ctx->thread_registry->CheckLocked();
for (unsigned i = 0; i < kMaxTid; i++) {
ThreadContext *tctx = static_cast<ThreadContext*>(
@@ -232,7 +219,6 @@ static ThreadContext *FindThreadByUidLocked(int unique_id) {
}
static ThreadContext *FindThreadByTidLocked(int tid) {
- Context *ctx = CTX();
ctx->thread_registry->CheckLocked();
return static_cast<ThreadContext*>(
ctx->thread_registry->GetThreadLocked(tid));
@@ -250,7 +236,6 @@ static bool IsInStackOrTls(ThreadContextBase *tctx_base, void *arg) {
}
ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack) {
- Context *ctx = CTX();
ctx->thread_registry->CheckLocked();
ThreadContext *tctx = static_cast<ThreadContext*>(
ctx->thread_registry->FindThreadContextLocked(IsInStackOrTls,
@@ -264,6 +249,12 @@ ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack) {
}
#endif
+void ScopedReport::AddThread(int unique_tid) {
+#ifndef TSAN_GO
+ AddThread(FindThreadByUidLocked(unique_tid));
+#endif
+}
+
void ScopedReport::AddMutex(const SyncVar *s) {
for (uptr i = 0; i < rep_->mutexes.Size(); i++) {
if (rep_->mutexes[i]->id == s->uid)
@@ -273,14 +264,31 @@ void ScopedReport::AddMutex(const SyncVar *s) {
ReportMutex *rm = new(mem) ReportMutex();
rep_->mutexes.PushBack(rm);
rm->id = s->uid;
+ rm->addr = s->addr;
rm->destroyed = false;
- rm->stack = 0;
-#ifndef TSAN_GO
rm->stack = SymbolizeStackId(s->creation_stack_id);
-#endif
}
-void ScopedReport::AddMutex(u64 id) {
+u64 ScopedReport::AddMutex(u64 id) {
+ u64 uid = 0;
+ u64 mid = id;
+ uptr addr = SyncVar::SplitId(id, &uid);
+ SyncVar *s = ctx->synctab.GetIfExistsAndLock(addr, false);
+ // Check that the mutex is still alive.
+ // Another mutex can be created at the same address,
+ // so check uid as well.
+ if (s && s->CheckId(uid)) {
+ mid = s->uid;
+ AddMutex(s);
+ } else {
+ AddDeadMutex(id);
+ }
+ if (s)
+ s->mtx.ReadUnlock();
+ return mid;
+}
+
+void ScopedReport::AddDeadMutex(u64 id) {
for (uptr i = 0; i < rep_->mutexes.Size(); i++) {
if (rep_->mutexes[i]->id == id)
return;
@@ -289,6 +297,7 @@ void ScopedReport::AddMutex(u64 id) {
ReportMutex *rm = new(mem) ReportMutex();
rep_->mutexes.PushBack(rm);
rm->id = id;
+ rm->addr = 0;
rm->destroyed = true;
rm->stack = 0;
}
@@ -369,7 +378,6 @@ void RestoreStack(int tid, const u64 epoch, StackTrace *stk, MutexSet *mset) {
// This function restores stack trace and mutex set for the thread/epoch.
// It does so by getting stack trace and mutex set at the beginning of
// trace part, and then replaying the trace till the given epoch.
- Context *ctx = CTX();
ctx->thread_registry->CheckLocked();
ThreadContext *tctx = static_cast<ThreadContext*>(
ctx->thread_registry->GetThreadLocked(tid));
@@ -434,7 +442,6 @@ void RestoreStack(int tid, const u64 epoch, StackTrace *stk, MutexSet *mset) {
static bool HandleRacyStacks(ThreadState *thr, const StackTrace (&traces)[2],
uptr addr_min, uptr addr_max) {
- Context *ctx = CTX();
bool equal_stack = false;
RacyStacks hash;
if (flags()->suppress_equal_stacks) {
@@ -474,7 +481,6 @@ static bool HandleRacyStacks(ThreadState *thr, const StackTrace (&traces)[2],
static void AddRacyStacks(ThreadState *thr, const StackTrace (&traces)[2],
uptr addr_min, uptr addr_max) {
- Context *ctx = CTX();
if (flags()->suppress_equal_stacks) {
RacyStacks hash;
hash.hash[0] = md5_hash(traces[0].Begin(), traces[0].Size() * sizeof(uptr));
@@ -579,7 +585,7 @@ static bool IsJavaNonsense(const ReportDesc *rep) {
&& frame->module == 0)) {
if (frame) {
FiredSuppression supp = {rep->typ, frame->pc, 0};
- CTX()->fired_suppressions.push_back(supp);
+ ctx->fired_suppressions.push_back(supp);
}
return true;
}
@@ -603,10 +609,12 @@ static bool RaceBetweenAtomicAndFree(ThreadState *thr) {
}
void ReportRace(ThreadState *thr) {
+ // Symbolizer makes lots of intercepted calls. If we try to process them,
+ // at best it will cause deadlocks on internal mutexes.
+ ScopedIgnoreInterceptors ignore;
+
if (!flags()->report_bugs)
return;
- ScopedInRtl in_rtl;
-
if (!flags()->report_atomic_races && !RaceBetweenAtomicAndFree(thr))
return;
@@ -631,7 +639,6 @@ void ReportRace(ThreadState *thr) {
return;
}
- Context *ctx = CTX();
ThreadRegistryLock l0(ctx->thread_registry);
ReportType typ = ReportTypeRace;
@@ -706,8 +713,8 @@ void PrintCurrentStackSlow() {
#ifndef TSAN_GO
__sanitizer::StackTrace *ptrace = new(internal_alloc(MBlockStackTrace,
sizeof(__sanitizer::StackTrace))) __sanitizer::StackTrace;
- ptrace->Unwind(kStackTraceMax, __sanitizer::StackTrace::GetCurrentPc(),
- 0, 0, 0, false);
+ ptrace->Unwind(kStackTraceMax, __sanitizer::StackTrace::GetCurrentPc(), 0, 0,
+ 0, 0, false);
for (uptr i = 0; i < ptrace->size / 2; i++) {
uptr tmp = ptrace->trace[i];
ptrace->trace[i] = ptrace->trace[ptrace->size - i - 1];
diff --git a/libsanitizer/tsan/tsan_rtl_thread.cc b/libsanitizer/tsan/tsan_rtl_thread.cc
index dea66983535..385af7e1fa6 100644
--- a/libsanitizer/tsan/tsan_rtl_thread.cc
+++ b/libsanitizer/tsan/tsan_rtl_thread.cc
@@ -57,11 +57,7 @@ void ThreadContext::OnCreated(void *arg) {
// Can't increment epoch w/o writing to the trace as well.
TraceAddEvent(args->thr, args->thr->fast_state, EventTypeMop, 0);
ReleaseImpl(args->thr, 0, &sync);
-#ifdef TSAN_GO
- creation_stack.ObtainCurrent(args->thr, args->pc);
-#else
creation_stack_id = CurrentStackId(args->thr, args->pc);
-#endif
if (reuse_count == 0)
StatInc(args->thr, StatThreadMaxTid);
}
@@ -87,8 +83,8 @@ void ThreadContext::OnStarted(void *arg) {
// from different threads.
epoch0 = RoundUp(epoch1 + 1, kTracePartSize);
epoch1 = (u64)-1;
- new(thr) ThreadState(CTX(), tid, unique_id,
- epoch0, args->stk_addr, args->stk_size, args->tls_addr, args->tls_size);
+ new(thr) ThreadState(ctx, tid, unique_id, epoch0, reuse_count,
+ args->stk_addr, args->stk_size, args->tls_addr, args->tls_size);
#ifndef TSAN_GO
thr->shadow_stack = &ThreadTrace(thr->tid)->shadow_stack[0];
thr->shadow_stack_pos = thr->shadow_stack;
@@ -104,6 +100,10 @@ void ThreadContext::OnStarted(void *arg) {
#ifndef TSAN_GO
AllocatorThreadStart(thr);
#endif
+ if (flags()->detect_deadlocks) {
+ thr->dd_pt = ctx->dd->CreatePhysicalThread();
+ thr->dd_lt = ctx->dd->CreateLogicalThread(unique_id);
+ }
thr->fast_synch_epoch = epoch0;
AcquireImpl(thr, 0, &sync);
thr->fast_state.SetHistorySize(flags()->history_size);
@@ -128,11 +128,15 @@ void ThreadContext::OnFinished() {
}
epoch1 = thr->fast_state.epoch();
+ if (flags()->detect_deadlocks) {
+ ctx->dd->DestroyPhysicalThread(thr->dd_pt);
+ ctx->dd->DestroyLogicalThread(thr->dd_lt);
+ }
#ifndef TSAN_GO
AllocatorThreadFinish(thr);
#endif
thr->~ThreadState();
- StatAggregate(CTX()->stat, thr->stat);
+ StatAggregate(ctx->stat, thr->stat);
thr = 0;
}
@@ -177,6 +181,8 @@ static void ReportIgnoresEnabled(ThreadContext *tctx, IgnoreSet *set) {
}
static void ThreadCheckIgnore(ThreadState *thr) {
+ if (ctx->after_multithreaded_fork)
+ return;
if (thr->ignore_reads_and_writes)
ReportIgnoresEnabled(thr->tctx, &thr->mop_ignore_set);
if (thr->ignore_sync)
@@ -187,36 +193,31 @@ static void ThreadCheckIgnore(ThreadState *thr) {}
#endif
void ThreadFinalize(ThreadState *thr) {
- CHECK_GT(thr->in_rtl, 0);
ThreadCheckIgnore(thr);
#ifndef TSAN_GO
if (!flags()->report_thread_leaks)
return;
- ThreadRegistryLock l(CTX()->thread_registry);
+ ThreadRegistryLock l(ctx->thread_registry);
Vector<ThreadLeak> leaks(MBlockScopedBuf);
- CTX()->thread_registry->RunCallbackForEachThreadLocked(
+ ctx->thread_registry->RunCallbackForEachThreadLocked(
MaybeReportThreadLeak, &leaks);
for (uptr i = 0; i < leaks.Size(); i++) {
ScopedReport rep(ReportTypeThreadLeak);
rep.AddThread(leaks[i].tctx);
rep.SetCount(leaks[i].count);
- OutputReport(CTX(), rep);
+ OutputReport(ctx, rep, rep.GetReport()->threads[0]->stack);
}
#endif
}
int ThreadCount(ThreadState *thr) {
- CHECK_GT(thr->in_rtl, 0);
- Context *ctx = CTX();
uptr result;
ctx->thread_registry->GetNumberOfThreads(0, 0, &result);
return (int)result;
}
int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
- CHECK_GT(thr->in_rtl, 0);
StatInc(thr, StatThreadCreate);
- Context *ctx = CTX();
OnCreatedArgs args = { thr, pc };
int tid = ctx->thread_registry->CreateThread(uid, detached, thr->tid, &args);
DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", thr->tid, tid, uid);
@@ -225,8 +226,6 @@ int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
}
void ThreadStart(ThreadState *thr, int tid, uptr os_id) {
- Context *ctx = CTX();
- CHECK_GT(thr->in_rtl, 0);
uptr stk_addr = 0;
uptr stk_size = 0;
uptr tls_addr = 0;
@@ -259,10 +258,17 @@ void ThreadStart(ThreadState *thr, int tid, uptr os_id) {
tr->Lock();
thr->tctx = (ThreadContext*)tr->GetThreadLocked(tid);
tr->Unlock();
+
+#ifndef TSAN_GO
+ if (ctx->after_multithreaded_fork) {
+ thr->ignore_interceptors++;
+ ThreadIgnoreBegin(thr, 0);
+ ThreadIgnoreSyncBegin(thr, 0);
+ }
+#endif
}
void ThreadFinish(ThreadState *thr) {
- CHECK_GT(thr->in_rtl, 0);
ThreadCheckIgnore(thr);
StatInc(thr, StatThreadFinish);
if (thr->stk_addr && thr->stk_size)
@@ -270,7 +276,6 @@ void ThreadFinish(ThreadState *thr) {
if (thr->tls_addr && thr->tls_size)
DontNeedShadowFor(thr->tls_addr, thr->tls_size);
thr->is_alive = false;
- Context *ctx = CTX();
ctx->thread_registry->FinishThread(thr->tid);
}
@@ -284,33 +289,26 @@ static bool FindThreadByUid(ThreadContextBase *tctx, void *arg) {
}
int ThreadTid(ThreadState *thr, uptr pc, uptr uid) {
- CHECK_GT(thr->in_rtl, 0);
- Context *ctx = CTX();
int res = ctx->thread_registry->FindThread(FindThreadByUid, (void*)uid);
DPrintf("#%d: ThreadTid uid=%zu tid=%d\n", thr->tid, uid, res);
return res;
}
void ThreadJoin(ThreadState *thr, uptr pc, int tid) {
- CHECK_GT(thr->in_rtl, 0);
CHECK_GT(tid, 0);
CHECK_LT(tid, kMaxTid);
DPrintf("#%d: ThreadJoin tid=%d\n", thr->tid, tid);
- Context *ctx = CTX();
ctx->thread_registry->JoinThread(tid, thr);
}
void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
- CHECK_GT(thr->in_rtl, 0);
CHECK_GT(tid, 0);
CHECK_LT(tid, kMaxTid);
- Context *ctx = CTX();
ctx->thread_registry->DetachThread(tid);
}
void ThreadSetName(ThreadState *thr, const char *name) {
- CHECK_GT(thr->in_rtl, 0);
- CTX()->thread_registry->SetThreadName(thr->tid, name);
+ ctx->thread_registry->SetThreadName(thr->tid, name);
}
void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
diff --git a/libsanitizer/tsan/tsan_stat.cc b/libsanitizer/tsan/tsan_stat.cc
index 6bc345397ad..e8d3a790b1c 100644
--- a/libsanitizer/tsan/tsan_stat.cc
+++ b/libsanitizer/tsan/tsan_stat.cc
@@ -72,6 +72,28 @@ void StatOutput(u64 *stat) {
name[StatSyncAcquire] = " acquired ";
name[StatSyncRelease] = " released ";
+ name[StatClockAcquire] = "Clock acquire ";
+ name[StatClockAcquireEmpty] = " empty clock ";
+ name[StatClockAcquireFastRelease] = " fast from release-store ";
+ name[StatClockAcquireLarge] = " contains my tid ";
+ name[StatClockAcquireRepeat] = " repeated (fast) ";
+ name[StatClockAcquireFull] = " full (slow) ";
+ name[StatClockAcquiredSomething] = " acquired something ";
+ name[StatClockRelease] = "Clock release ";
+ name[StatClockReleaseResize] = " resize ";
+ name[StatClockReleaseFast1] = " fast1 ";
+ name[StatClockReleaseFast2] = " fast2 ";
+ name[StatClockReleaseSlow] = " dirty overflow (slow) ";
+ name[StatClockReleaseFull] = " full (slow) ";
+ name[StatClockReleaseAcquired] = " was acquired ";
+ name[StatClockReleaseClearTail] = " clear tail ";
+ name[StatClockStore] = "Clock release store ";
+ name[StatClockStoreResize] = " resize ";
+ name[StatClockStoreFast] = " fast ";
+ name[StatClockStoreFull] = " slow ";
+ name[StatClockStoreTail] = " clear tail ";
+ name[StatClockAcquireRelease] = "Clock acquire-release ";
+
name[StatAtomic] = "Atomic operations ";
name[StatAtomicLoad] = " Including load ";
name[StatAtomicStore] = " store ";
@@ -96,338 +118,6 @@ void StatOutput(u64 *stat) {
name[StatAtomic8] = " size 8 ";
name[StatAtomic16] = " size 16 ";
- name[StatInterceptor] = "Interceptors ";
- name[StatInt_longjmp] = " longjmp ";
- name[StatInt_siglongjmp] = " siglongjmp ";
- name[StatInt_malloc] = " malloc ";
- name[StatInt___libc_memalign] = " __libc_memalign ";
- name[StatInt_calloc] = " calloc ";
- name[StatInt_realloc] = " realloc ";
- name[StatInt_free] = " free ";
- name[StatInt_cfree] = " cfree ";
- name[StatInt_malloc_usable_size] = " malloc_usable_size ";
- name[StatInt_mmap] = " mmap ";
- name[StatInt_mmap64] = " mmap64 ";
- name[StatInt_munmap] = " munmap ";
- name[StatInt_memalign] = " memalign ";
- name[StatInt_valloc] = " valloc ";
- name[StatInt_pvalloc] = " pvalloc ";
- name[StatInt_posix_memalign] = " posix_memalign ";
- name[StatInt__Znwm] = " _Znwm ";
- name[StatInt__ZnwmRKSt9nothrow_t] = " _ZnwmRKSt9nothrow_t ";
- name[StatInt__Znam] = " _Znam ";
- name[StatInt__ZnamRKSt9nothrow_t] = " _ZnamRKSt9nothrow_t ";
- name[StatInt__ZdlPv] = " _ZdlPv ";
- name[StatInt__ZdlPvRKSt9nothrow_t] = " _ZdlPvRKSt9nothrow_t ";
- name[StatInt__ZdaPv] = " _ZdaPv ";
- name[StatInt__ZdaPvRKSt9nothrow_t] = " _ZdaPvRKSt9nothrow_t ";
- name[StatInt_strlen] = " strlen ";
- name[StatInt_memset] = " memset ";
- name[StatInt_memcpy] = " memcpy ";
- name[StatInt_textdomain] = " textdomain ";
- name[StatInt_strcmp] = " strcmp ";
- name[StatInt_memchr] = " memchr ";
- name[StatInt_memrchr] = " memrchr ";
- name[StatInt_memmove] = " memmove ";
- name[StatInt_memcmp] = " memcmp ";
- name[StatInt_strchr] = " strchr ";
- name[StatInt_strchrnul] = " strchrnul ";
- name[StatInt_strrchr] = " strrchr ";
- name[StatInt_strncmp] = " strncmp ";
- name[StatInt_strcpy] = " strcpy ";
- name[StatInt_strncpy] = " strncpy ";
- name[StatInt_strstr] = " strstr ";
- name[StatInt_strdup] = " strdup ";
- name[StatInt_strcasecmp] = " strcasecmp ";
- name[StatInt_strncasecmp] = " strncasecmp ";
- name[StatInt_atexit] = " atexit ";
- name[StatInt__exit] = " _exit ";
- name[StatInt___cxa_guard_acquire] = " __cxa_guard_acquire ";
- name[StatInt___cxa_guard_release] = " __cxa_guard_release ";
- name[StatInt___cxa_guard_abort] = " __cxa_guard_abort ";
- name[StatInt_pthread_create] = " pthread_create ";
- name[StatInt_pthread_join] = " pthread_join ";
- name[StatInt_pthread_detach] = " pthread_detach ";
- name[StatInt_pthread_mutex_init] = " pthread_mutex_init ";
- name[StatInt_pthread_mutex_destroy] = " pthread_mutex_destroy ";
- name[StatInt_pthread_mutex_lock] = " pthread_mutex_lock ";
- name[StatInt_pthread_mutex_trylock] = " pthread_mutex_trylock ";
- name[StatInt_pthread_mutex_timedlock] = " pthread_mutex_timedlock ";
- name[StatInt_pthread_mutex_unlock] = " pthread_mutex_unlock ";
- name[StatInt_pthread_spin_init] = " pthread_spin_init ";
- name[StatInt_pthread_spin_destroy] = " pthread_spin_destroy ";
- name[StatInt_pthread_spin_lock] = " pthread_spin_lock ";
- name[StatInt_pthread_spin_trylock] = " pthread_spin_trylock ";
- name[StatInt_pthread_spin_unlock] = " pthread_spin_unlock ";
- name[StatInt_pthread_rwlock_init] = " pthread_rwlock_init ";
- name[StatInt_pthread_rwlock_destroy] = " pthread_rwlock_destroy ";
- name[StatInt_pthread_rwlock_rdlock] = " pthread_rwlock_rdlock ";
- name[StatInt_pthread_rwlock_tryrdlock] = " pthread_rwlock_tryrdlock ";
- name[StatInt_pthread_rwlock_timedrdlock]
- = " pthread_rwlock_timedrdlock ";
- name[StatInt_pthread_rwlock_wrlock] = " pthread_rwlock_wrlock ";
- name[StatInt_pthread_rwlock_trywrlock] = " pthread_rwlock_trywrlock ";
- name[StatInt_pthread_rwlock_timedwrlock]
- = " pthread_rwlock_timedwrlock ";
- name[StatInt_pthread_rwlock_unlock] = " pthread_rwlock_unlock ";
- name[StatInt_pthread_cond_init] = " pthread_cond_init ";
- name[StatInt_pthread_cond_destroy] = " pthread_cond_destroy ";
- name[StatInt_pthread_cond_signal] = " pthread_cond_signal ";
- name[StatInt_pthread_cond_broadcast] = " pthread_cond_broadcast ";
- name[StatInt_pthread_cond_wait] = " pthread_cond_wait ";
- name[StatInt_pthread_cond_timedwait] = " pthread_cond_timedwait ";
- name[StatInt_pthread_barrier_init] = " pthread_barrier_init ";
- name[StatInt_pthread_barrier_destroy] = " pthread_barrier_destroy ";
- name[StatInt_pthread_barrier_wait] = " pthread_barrier_wait ";
- name[StatInt_pthread_once] = " pthread_once ";
- name[StatInt_pthread_getschedparam] = " pthread_getschedparam ";
- name[StatInt_pthread_setname_np] = " pthread_setname_np ";
- name[StatInt_sem_init] = " sem_init ";
- name[StatInt_sem_destroy] = " sem_destroy ";
- name[StatInt_sem_wait] = " sem_wait ";
- name[StatInt_sem_trywait] = " sem_trywait ";
- name[StatInt_sem_timedwait] = " sem_timedwait ";
- name[StatInt_sem_post] = " sem_post ";
- name[StatInt_sem_getvalue] = " sem_getvalue ";
- name[StatInt_stat] = " stat ";
- name[StatInt___xstat] = " __xstat ";
- name[StatInt_stat64] = " stat64 ";
- name[StatInt___xstat64] = " __xstat64 ";
- name[StatInt_lstat] = " lstat ";
- name[StatInt___lxstat] = " __lxstat ";
- name[StatInt_lstat64] = " lstat64 ";
- name[StatInt___lxstat64] = " __lxstat64 ";
- name[StatInt_fstat] = " fstat ";
- name[StatInt___fxstat] = " __fxstat ";
- name[StatInt_fstat64] = " fstat64 ";
- name[StatInt___fxstat64] = " __fxstat64 ";
- name[StatInt_open] = " open ";
- name[StatInt_open64] = " open64 ";
- name[StatInt_creat] = " creat ";
- name[StatInt_creat64] = " creat64 ";
- name[StatInt_dup] = " dup ";
- name[StatInt_dup2] = " dup2 ";
- name[StatInt_dup3] = " dup3 ";
- name[StatInt_eventfd] = " eventfd ";
- name[StatInt_signalfd] = " signalfd ";
- name[StatInt_inotify_init] = " inotify_init ";
- name[StatInt_inotify_init1] = " inotify_init1 ";
- name[StatInt_socket] = " socket ";
- name[StatInt_socketpair] = " socketpair ";
- name[StatInt_connect] = " connect ";
- name[StatInt_bind] = " bind ";
- name[StatInt_listen] = " listen ";
- name[StatInt_accept] = " accept ";
- name[StatInt_accept4] = " accept4 ";
- name[StatInt_epoll_create] = " epoll_create ";
- name[StatInt_epoll_create1] = " epoll_create1 ";
- name[StatInt_close] = " close ";
- name[StatInt___close] = " __close ";
- name[StatInt___res_iclose] = " __res_iclose ";
- name[StatInt_pipe] = " pipe ";
- name[StatInt_pipe2] = " pipe2 ";
- name[StatInt_read] = " read ";
- name[StatInt_prctl] = " prctl ";
- name[StatInt_pread] = " pread ";
- name[StatInt_pread64] = " pread64 ";
- name[StatInt_readv] = " readv ";
- name[StatInt_preadv] = " preadv ";
- name[StatInt_preadv64] = " preadv64 ";
- name[StatInt_write] = " write ";
- name[StatInt_pwrite] = " pwrite ";
- name[StatInt_pwrite64] = " pwrite64 ";
- name[StatInt_writev] = " writev ";
- name[StatInt_pwritev] = " pwritev ";
- name[StatInt_pwritev64] = " pwritev64 ";
- name[StatInt_send] = " send ";
- name[StatInt_sendmsg] = " sendmsg ";
- name[StatInt_recv] = " recv ";
- name[StatInt_recvmsg] = " recvmsg ";
- name[StatInt_unlink] = " unlink ";
- name[StatInt_fopen] = " fopen ";
- name[StatInt_freopen] = " freopen ";
- name[StatInt_fclose] = " fclose ";
- name[StatInt_fread] = " fread ";
- name[StatInt_fwrite] = " fwrite ";
- name[StatInt_fflush] = " fflush ";
- name[StatInt_abort] = " abort ";
- name[StatInt_puts] = " puts ";
- name[StatInt_rmdir] = " rmdir ";
- name[StatInt_opendir] = " opendir ";
- name[StatInt_epoll_ctl] = " epoll_ctl ";
- name[StatInt_epoll_wait] = " epoll_wait ";
- name[StatInt_poll] = " poll ";
- name[StatInt_ppoll] = " ppoll ";
- name[StatInt_sigaction] = " sigaction ";
- name[StatInt_signal] = " signal ";
- name[StatInt_sigsuspend] = " sigsuspend ";
- name[StatInt_raise] = " raise ";
- name[StatInt_kill] = " kill ";
- name[StatInt_pthread_kill] = " pthread_kill ";
- name[StatInt_sleep] = " sleep ";
- name[StatInt_usleep] = " usleep ";
- name[StatInt_nanosleep] = " nanosleep ";
- name[StatInt_gettimeofday] = " gettimeofday ";
- name[StatInt_fork] = " fork ";
- name[StatInt_vscanf] = " vscanf ";
- name[StatInt_vsscanf] = " vsscanf ";
- name[StatInt_vfscanf] = " vfscanf ";
- name[StatInt_scanf] = " scanf ";
- name[StatInt_sscanf] = " sscanf ";
- name[StatInt_fscanf] = " fscanf ";
- name[StatInt___isoc99_vscanf] = " vscanf ";
- name[StatInt___isoc99_vsscanf] = " vsscanf ";
- name[StatInt___isoc99_vfscanf] = " vfscanf ";
- name[StatInt___isoc99_scanf] = " scanf ";
- name[StatInt___isoc99_sscanf] = " sscanf ";
- name[StatInt___isoc99_fscanf] = " fscanf ";
- name[StatInt_on_exit] = " on_exit ";
- name[StatInt___cxa_atexit] = " __cxa_atexit ";
- name[StatInt_localtime] = " localtime ";
- name[StatInt_localtime_r] = " localtime_r ";
- name[StatInt_gmtime] = " gmtime ";
- name[StatInt_gmtime_r] = " gmtime_r ";
- name[StatInt_ctime] = " ctime ";
- name[StatInt_ctime_r] = " ctime_r ";
- name[StatInt_asctime] = " asctime ";
- name[StatInt_asctime_r] = " asctime_r ";
- name[StatInt_strptime] = " strptime ";
- name[StatInt_frexp] = " frexp ";
- name[StatInt_frexpf] = " frexpf ";
- name[StatInt_frexpl] = " frexpl ";
- name[StatInt_getpwnam] = " getpwnam ";
- name[StatInt_getpwuid] = " getpwuid ";
- name[StatInt_getgrnam] = " getgrnam ";
- name[StatInt_getgrgid] = " getgrgid ";
- name[StatInt_getpwnam_r] = " getpwnam_r ";
- name[StatInt_getpwuid_r] = " getpwuid_r ";
- name[StatInt_getgrnam_r] = " getgrnam_r ";
- name[StatInt_getgrgid_r] = " getgrgid_r ";
- name[StatInt_clock_getres] = " clock_getres ";
- name[StatInt_clock_gettime] = " clock_gettime ";
- name[StatInt_clock_settime] = " clock_settime ";
- name[StatInt_getitimer] = " getitimer ";
- name[StatInt_setitimer] = " setitimer ";
- name[StatInt_time] = " time ";
- name[StatInt_glob] = " glob ";
- name[StatInt_glob64] = " glob64 ";
- name[StatInt_wait] = " wait ";
- name[StatInt_waitid] = " waitid ";
- name[StatInt_waitpid] = " waitpid ";
- name[StatInt_wait3] = " wait3 ";
- name[StatInt_wait4] = " wait4 ";
- name[StatInt_inet_ntop] = " inet_ntop ";
- name[StatInt_inet_pton] = " inet_pton ";
- name[StatInt_inet_aton] = " inet_aton ";
- name[StatInt_getaddrinfo] = " getaddrinfo ";
- name[StatInt_getnameinfo] = " getnameinfo ";
- name[StatInt_getsockname] = " getsockname ";
- name[StatInt_gethostent] = " gethostent ";
- name[StatInt_gethostbyname] = " gethostbyname ";
- name[StatInt_gethostbyname2] = " gethostbyname2 ";
- name[StatInt_gethostbyaddr] = " gethostbyaddr ";
- name[StatInt_gethostent_r] = " gethostent_r ";
- name[StatInt_gethostbyname_r] = " gethostbyname_r ";
- name[StatInt_gethostbyname2_r] = " gethostbyname2_r ";
- name[StatInt_gethostbyaddr_r] = " gethostbyaddr_r ";
- name[StatInt_getsockopt] = " getsockopt ";
- name[StatInt_modf] = " modf ";
- name[StatInt_modff] = " modff ";
- name[StatInt_modfl] = " modfl ";
- name[StatInt_getpeername] = " getpeername ";
- name[StatInt_ioctl] = " ioctl ";
- name[StatInt_sysinfo] = " sysinfo ";
- name[StatInt_readdir] = " readdir ";
- name[StatInt_readdir64] = " readdir64 ";
- name[StatInt_readdir_r] = " readdir_r ";
- name[StatInt_readdir64_r] = " readdir64_r ";
- name[StatInt_ptrace] = " ptrace ";
- name[StatInt_setlocale] = " setlocale ";
- name[StatInt_getcwd] = " getcwd ";
- name[StatInt_get_current_dir_name] = " get_current_dir_name ";
- name[StatInt_strtoimax] = " strtoimax ";
- name[StatInt_strtoumax] = " strtoumax ";
- name[StatInt_mbstowcs] = " mbstowcs ";
- name[StatInt_mbsrtowcs] = " mbsrtowcs ";
- name[StatInt_mbsnrtowcs] = " mbsnrtowcs ";
- name[StatInt_wcstombs] = " wcstombs ";
- name[StatInt_wcsrtombs] = " wcsrtombs ";
- name[StatInt_wcsnrtombs] = " wcsnrtombs ";
- name[StatInt_tcgetattr] = " tcgetattr ";
- name[StatInt_realpath] = " realpath ";
- name[StatInt_canonicalize_file_name] = " canonicalize_file_name ";
- name[StatInt_confstr] = " confstr ";
- name[StatInt_sched_getaffinity] = " sched_getaffinity ";
- name[StatInt_strerror] = " strerror ";
- name[StatInt_strerror_r] = " strerror_r ";
- name[StatInt___xpg_strerror_r] = " __xpg_strerror_r ";
- name[StatInt_scandir] = " scandir ";
- name[StatInt_scandir64] = " scandir64 ";
- name[StatInt_getgroups] = " getgroups ";
- name[StatInt_wordexp] = " wordexp ";
- name[StatInt_sigwait] = " sigwait ";
- name[StatInt_sigwaitinfo] = " sigwaitinfo ";
- name[StatInt_sigtimedwait] = " sigtimedwait ";
- name[StatInt_sigemptyset] = " sigemptyset ";
- name[StatInt_sigfillset] = " sigfillset ";
- name[StatInt_sigpending] = " sigpending ";
- name[StatInt_sigprocmask] = " sigprocmask ";
- name[StatInt_backtrace] = " backtrace ";
- name[StatInt_backtrace_symbols] = " backtrace_symbols ";
- name[StatInt_dlopen] = " dlopen ";
- name[StatInt_dlclose] = " dlclose ";
- name[StatInt_getmntent] = " getmntent ";
- name[StatInt_getmntent_r] = " getmntent_r ";
- name[StatInt_statfs] = " statfs ";
- name[StatInt_statfs64] = " statfs64 ";
- name[StatInt_fstatfs] = " fstatfs ";
- name[StatInt_fstatfs64] = " fstatfs64 ";
- name[StatInt_statvfs] = " statvfs ";
- name[StatInt_statvfs64] = " statvfs64 ";
- name[StatInt_fstatvfs] = " fstatvfs ";
- name[StatInt_fstatvfs64] = " fstatvfs64 ";
- name[StatInt_initgroups] = " initgroups ";
- name[StatInt_ether_ntoa] = " ether_ntoa ";
- name[StatInt_ether_aton] = " ether_aton ";
- name[StatInt_ether_ntoa_r] = " ether_ntoa_r ";
- name[StatInt_ether_aton_r] = " ether_aton_r ";
- name[StatInt_ether_ntohost] = " ether_ntohost ";
- name[StatInt_ether_hostton] = " ether_hostton ";
- name[StatInt_ether_line] = " ether_line ";
- name[StatInt_shmctl] = " shmctl ";
- name[StatInt_random_r] = " random_r ";
- name[StatInt_tmpnam] = " tmpnam ";
- name[StatInt_tmpnam_r] = " tmpnam_r ";
- name[StatInt_tempnam] = " tempnam ";
- name[StatInt_sincos] = " sincos ";
- name[StatInt_sincosf] = " sincosf ";
- name[StatInt_sincosl] = " sincosl ";
- name[StatInt_remquo] = " remquo ";
- name[StatInt_remquof] = " remquof ";
- name[StatInt_remquol] = " remquol ";
- name[StatInt_lgamma] = " lgamma ";
- name[StatInt_lgammaf] = " lgammaf ";
- name[StatInt_lgammal] = " lgammal ";
- name[StatInt_lgamma_r] = " lgamma_r ";
- name[StatInt_lgammaf_r] = " lgammaf_r ";
- name[StatInt_lgammal_r] = " lgammal_r ";
- name[StatInt_drand48_r] = " drand48_r ";
- name[StatInt_lrand48_r] = " lrand48_r ";
- name[StatInt_getline] = " getline ";
- name[StatInt_getdelim] = " getdelim ";
- name[StatInt_iconv] = " iconv ";
- name[StatInt_times] = " times ";
-
- name[StatInt_pthread_attr_getdetachstate] = " pthread_addr_getdetachstate "; // NOLINT
- name[StatInt_pthread_attr_getguardsize] = " pthread_addr_getguardsize "; // NOLINT
- name[StatInt_pthread_attr_getschedparam] = " pthread_addr_getschedparam "; // NOLINT
- name[StatInt_pthread_attr_getschedpolicy] = " pthread_addr_getschedpolicy "; // NOLINT
- name[StatInt_pthread_attr_getinheritsched] = " pthread_addr_getinheritsched "; // NOLINT
- name[StatInt_pthread_attr_getscope] = " pthread_addr_getscope "; // NOLINT
- name[StatInt_pthread_attr_getstacksize] = " pthread_addr_getstacksize "; // NOLINT
- name[StatInt_pthread_attr_getstack] = " pthread_addr_getstack "; // NOLINT
- name[StatInt_pthread_attr_getaffinity_np] = " pthread_addr_getaffinity_np "; // NOLINT
-
name[StatAnnotation] = "Dynamic annotations ";
name[StatAnnotateHappensBefore] = " HappensBefore ";
name[StatAnnotateHappensAfter] = " HappensAfter ";
@@ -475,11 +165,12 @@ void StatOutput(u64 *stat) {
name[StatMtxAnnotations] = " Annotations ";
name[StatMtxMBlock] = " MBlock ";
name[StatMtxJavaMBlock] = " JavaMBlock ";
+ name[StatMtxDeadlockDetector] = " DeadlockDetector ";
name[StatMtxFD] = " FD ";
Printf("Statistics:\n");
for (int i = 0; i < StatCnt; i++)
- Printf("%s: %zu\n", name[i], (uptr)stat[i]);
+ Printf("%s: %16zu\n", name[i], (uptr)stat[i]);
}
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_stat.h b/libsanitizer/tsan/tsan_stat.h
index 3e08313d1a5..5bdd9de8213 100644
--- a/libsanitizer/tsan/tsan_stat.h
+++ b/libsanitizer/tsan/tsan_stat.h
@@ -67,6 +67,32 @@ enum StatType {
StatSyncAcquire,
StatSyncRelease,
+ // Clocks - acquire.
+ StatClockAcquire,
+ StatClockAcquireEmpty,
+ StatClockAcquireFastRelease,
+ StatClockAcquireLarge,
+ StatClockAcquireRepeat,
+ StatClockAcquireFull,
+ StatClockAcquiredSomething,
+ // Clocks - release.
+ StatClockRelease,
+ StatClockReleaseResize,
+ StatClockReleaseFast1,
+ StatClockReleaseFast2,
+ StatClockReleaseSlow,
+ StatClockReleaseFull,
+ StatClockReleaseAcquired,
+ StatClockReleaseClearTail,
+ // Clocks - release store.
+ StatClockStore,
+ StatClockStoreResize,
+ StatClockStoreFast,
+ StatClockStoreFull,
+ StatClockStoreTail,
+ // Clocks - acquire-release.
+ StatClockAcquireRelease,
+
// Atomics.
StatAtomic,
StatAtomicLoad,
@@ -92,337 +118,6 @@ enum StatType {
StatAtomic8,
StatAtomic16,
- // Interceptors.
- StatInterceptor,
- StatInt_longjmp,
- StatInt_siglongjmp,
- StatInt_malloc,
- StatInt___libc_memalign,
- StatInt_calloc,
- StatInt_realloc,
- StatInt_free,
- StatInt_cfree,
- StatInt_malloc_usable_size,
- StatInt_mmap,
- StatInt_mmap64,
- StatInt_munmap,
- StatInt_memalign,
- StatInt_valloc,
- StatInt_pvalloc,
- StatInt_posix_memalign,
- StatInt__Znwm,
- StatInt__ZnwmRKSt9nothrow_t,
- StatInt__Znam,
- StatInt__ZnamRKSt9nothrow_t,
- StatInt__ZdlPv,
- StatInt__ZdlPvRKSt9nothrow_t,
- StatInt__ZdaPv,
- StatInt__ZdaPvRKSt9nothrow_t,
- StatInt_strlen,
- StatInt_memset,
- StatInt_memcpy,
- StatInt_textdomain,
- StatInt_strcmp,
- StatInt_memchr,
- StatInt_memrchr,
- StatInt_memmove,
- StatInt_memcmp,
- StatInt_strchr,
- StatInt_strchrnul,
- StatInt_strrchr,
- StatInt_strncmp,
- StatInt_strcpy,
- StatInt_strncpy,
- StatInt_strcasecmp,
- StatInt_strncasecmp,
- StatInt_strstr,
- StatInt_strdup,
- StatInt_atexit,
- StatInt__exit,
- StatInt___cxa_guard_acquire,
- StatInt___cxa_guard_release,
- StatInt___cxa_guard_abort,
- StatInt_pthread_create,
- StatInt_pthread_join,
- StatInt_pthread_detach,
- StatInt_pthread_mutex_init,
- StatInt_pthread_mutex_destroy,
- StatInt_pthread_mutex_lock,
- StatInt_pthread_mutex_trylock,
- StatInt_pthread_mutex_timedlock,
- StatInt_pthread_mutex_unlock,
- StatInt_pthread_spin_init,
- StatInt_pthread_spin_destroy,
- StatInt_pthread_spin_lock,
- StatInt_pthread_spin_trylock,
- StatInt_pthread_spin_unlock,
- StatInt_pthread_rwlock_init,
- StatInt_pthread_rwlock_destroy,
- StatInt_pthread_rwlock_rdlock,
- StatInt_pthread_rwlock_tryrdlock,
- StatInt_pthread_rwlock_timedrdlock,
- StatInt_pthread_rwlock_wrlock,
- StatInt_pthread_rwlock_trywrlock,
- StatInt_pthread_rwlock_timedwrlock,
- StatInt_pthread_rwlock_unlock,
- StatInt_pthread_cond_init,
- StatInt_pthread_cond_destroy,
- StatInt_pthread_cond_signal,
- StatInt_pthread_cond_broadcast,
- StatInt_pthread_cond_wait,
- StatInt_pthread_cond_timedwait,
- StatInt_pthread_barrier_init,
- StatInt_pthread_barrier_destroy,
- StatInt_pthread_barrier_wait,
- StatInt_pthread_once,
- StatInt_pthread_getschedparam,
- StatInt_pthread_setname_np,
- StatInt_sem_init,
- StatInt_sem_destroy,
- StatInt_sem_wait,
- StatInt_sem_trywait,
- StatInt_sem_timedwait,
- StatInt_sem_post,
- StatInt_sem_getvalue,
- StatInt_stat,
- StatInt___xstat,
- StatInt_stat64,
- StatInt___xstat64,
- StatInt_lstat,
- StatInt___lxstat,
- StatInt_lstat64,
- StatInt___lxstat64,
- StatInt_fstat,
- StatInt___fxstat,
- StatInt_fstat64,
- StatInt___fxstat64,
- StatInt_open,
- StatInt_open64,
- StatInt_creat,
- StatInt_creat64,
- StatInt_dup,
- StatInt_dup2,
- StatInt_dup3,
- StatInt_eventfd,
- StatInt_signalfd,
- StatInt_inotify_init,
- StatInt_inotify_init1,
- StatInt_socket,
- StatInt_socketpair,
- StatInt_connect,
- StatInt_bind,
- StatInt_listen,
- StatInt_accept,
- StatInt_accept4,
- StatInt_epoll_create,
- StatInt_epoll_create1,
- StatInt_close,
- StatInt___close,
- StatInt___res_iclose,
- StatInt_pipe,
- StatInt_pipe2,
- StatInt_read,
- StatInt_prctl,
- StatInt_pread,
- StatInt_pread64,
- StatInt_readv,
- StatInt_preadv,
- StatInt_preadv64,
- StatInt_write,
- StatInt_pwrite,
- StatInt_pwrite64,
- StatInt_writev,
- StatInt_pwritev,
- StatInt_pwritev64,
- StatInt_send,
- StatInt_sendmsg,
- StatInt_recv,
- StatInt_recvmsg,
- StatInt_unlink,
- StatInt_fopen,
- StatInt_freopen,
- StatInt_fclose,
- StatInt_fread,
- StatInt_fwrite,
- StatInt_fflush,
- StatInt_abort,
- StatInt_puts,
- StatInt_rmdir,
- StatInt_opendir,
- StatInt_epoll_ctl,
- StatInt_epoll_wait,
- StatInt_poll,
- StatInt_ppoll,
- StatInt_sigaction,
- StatInt_signal,
- StatInt_sigsuspend,
- StatInt_raise,
- StatInt_kill,
- StatInt_pthread_kill,
- StatInt_sleep,
- StatInt_usleep,
- StatInt_nanosleep,
- StatInt_gettimeofday,
- StatInt_fork,
- StatInt_vscanf,
- StatInt_vsscanf,
- StatInt_vfscanf,
- StatInt_scanf,
- StatInt_sscanf,
- StatInt_fscanf,
- StatInt___isoc99_vscanf,
- StatInt___isoc99_vsscanf,
- StatInt___isoc99_vfscanf,
- StatInt___isoc99_scanf,
- StatInt___isoc99_sscanf,
- StatInt___isoc99_fscanf,
- StatInt_on_exit,
- StatInt___cxa_atexit,
- StatInt_localtime,
- StatInt_localtime_r,
- StatInt_gmtime,
- StatInt_gmtime_r,
- StatInt_ctime,
- StatInt_ctime_r,
- StatInt_asctime,
- StatInt_asctime_r,
- StatInt_strptime,
- StatInt_frexp,
- StatInt_frexpf,
- StatInt_frexpl,
- StatInt_getpwnam,
- StatInt_getpwuid,
- StatInt_getgrnam,
- StatInt_getgrgid,
- StatInt_getpwnam_r,
- StatInt_getpwuid_r,
- StatInt_getgrnam_r,
- StatInt_getgrgid_r,
- StatInt_clock_getres,
- StatInt_clock_gettime,
- StatInt_clock_settime,
- StatInt_getitimer,
- StatInt_setitimer,
- StatInt_time,
- StatInt_glob,
- StatInt_glob64,
- StatInt_wait,
- StatInt_waitid,
- StatInt_waitpid,
- StatInt_wait3,
- StatInt_wait4,
- StatInt_inet_ntop,
- StatInt_inet_pton,
- StatInt_inet_aton,
- StatInt_getaddrinfo,
- StatInt_getnameinfo,
- StatInt_getsockname,
- StatInt_gethostent,
- StatInt_gethostbyname,
- StatInt_gethostbyname2,
- StatInt_gethostbyaddr,
- StatInt_gethostent_r,
- StatInt_gethostbyname_r,
- StatInt_gethostbyname2_r,
- StatInt_gethostbyaddr_r,
- StatInt_getsockopt,
- StatInt_modf,
- StatInt_modff,
- StatInt_modfl,
- StatInt_getpeername,
- StatInt_ioctl,
- StatInt_sysinfo,
- StatInt_readdir,
- StatInt_readdir64,
- StatInt_readdir_r,
- StatInt_readdir64_r,
- StatInt_ptrace,
- StatInt_setlocale,
- StatInt_getcwd,
- StatInt_get_current_dir_name,
- StatInt_strtoimax,
- StatInt_strtoumax,
- StatInt_mbstowcs,
- StatInt_mbsrtowcs,
- StatInt_mbsnrtowcs,
- StatInt_wcstombs,
- StatInt_wcsrtombs,
- StatInt_wcsnrtombs,
- StatInt_tcgetattr,
- StatInt_realpath,
- StatInt_canonicalize_file_name,
- StatInt_confstr,
- StatInt_sched_getaffinity,
- StatInt_strerror,
- StatInt_strerror_r,
- StatInt___xpg_strerror_r,
- StatInt_scandir,
- StatInt_scandir64,
- StatInt_getgroups,
- StatInt_wordexp,
- StatInt_sigwait,
- StatInt_sigwaitinfo,
- StatInt_sigtimedwait,
- StatInt_sigemptyset,
- StatInt_sigfillset,
- StatInt_sigpending,
- StatInt_sigprocmask,
- StatInt_backtrace,
- StatInt_backtrace_symbols,
- StatInt_dlopen,
- StatInt_dlclose,
- StatInt_getmntent,
- StatInt_getmntent_r,
- StatInt_statfs,
- StatInt_statfs64,
- StatInt_fstatfs,
- StatInt_fstatfs64,
- StatInt_statvfs,
- StatInt_statvfs64,
- StatInt_fstatvfs,
- StatInt_fstatvfs64,
- StatInt_initgroups,
- StatInt_ether_ntoa,
- StatInt_ether_aton,
- StatInt_ether_ntoa_r,
- StatInt_ether_aton_r,
- StatInt_ether_ntohost,
- StatInt_ether_hostton,
- StatInt_ether_line,
- StatInt_shmctl,
- StatInt_random_r,
- StatInt_tmpnam,
- StatInt_tmpnam_r,
- StatInt_tempnam,
- StatInt_sincos,
- StatInt_sincosf,
- StatInt_sincosl,
- StatInt_remquo,
- StatInt_remquof,
- StatInt_remquol,
- StatInt_lgamma,
- StatInt_lgammaf,
- StatInt_lgammal,
- StatInt_lgamma_r,
- StatInt_lgammaf_r,
- StatInt_lgammal_r,
- StatInt_drand48_r,
- StatInt_lrand48_r,
- StatInt_getline,
- StatInt_getdelim,
- StatInt_iconv,
- StatInt_times,
-
- StatInt_pthread_attr_getdetachstate,
- StatInt_pthread_attr_getguardsize,
- StatInt_pthread_attr_getschedparam,
- StatInt_pthread_attr_getschedpolicy,
- StatInt_pthread_attr_getinheritsched,
- StatInt_pthread_attr_getscope,
- StatInt_pthread_attr_getstacksize,
- StatInt_pthread_attr_getstack,
- StatInt_pthread_attr_getaffinity_np,
-
// Dynamic annotations.
StatAnnotation,
StatAnnotateHappensBefore,
@@ -472,6 +167,7 @@ enum StatType {
StatMtxAtExit,
StatMtxMBlock,
StatMtxJavaMBlock,
+ StatMtxDeadlockDetector,
StatMtxFD,
// This must be the last.
diff --git a/libsanitizer/tsan/tsan_suppressions.cc b/libsanitizer/tsan/tsan_suppressions.cc
index fa0c30dc28c..ce8d5fe8611 100644
--- a/libsanitizer/tsan/tsan_suppressions.cc
+++ b/libsanitizer/tsan/tsan_suppressions.cc
@@ -101,10 +101,20 @@ SuppressionType conv(ReportType typ) {
return SuppressionThread;
else if (typ == ReportTypeMutexDestroyLocked)
return SuppressionMutex;
+ else if (typ == ReportTypeMutexDoubleLock)
+ return SuppressionMutex;
+ else if (typ == ReportTypeMutexBadUnlock)
+ return SuppressionMutex;
+ else if (typ == ReportTypeMutexBadReadLock)
+ return SuppressionMutex;
+ else if (typ == ReportTypeMutexBadReadUnlock)
+ return SuppressionMutex;
else if (typ == ReportTypeSignalUnsafe)
return SuppressionSignal;
else if (typ == ReportTypeErrnoInSignal)
return SuppressionNone;
+ else if (typ == ReportTypeDeadlock)
+ return SuppressionDeadlock;
Printf("ThreadSanitizer: unknown report type %d\n", typ),
Die();
}
diff --git a/libsanitizer/tsan/tsan_symbolize.cc b/libsanitizer/tsan/tsan_symbolize.cc
index c0e794be2d2..fa36017846c 100644
--- a/libsanitizer/tsan/tsan_symbolize.cc
+++ b/libsanitizer/tsan/tsan_symbolize.cc
@@ -24,12 +24,14 @@ void EnterSymbolizer() {
ThreadState *thr = cur_thread();
CHECK(!thr->in_symbolizer);
thr->in_symbolizer = true;
+ thr->ignore_interceptors++;
}
void ExitSymbolizer() {
ThreadState *thr = cur_thread();
CHECK(thr->in_symbolizer);
thr->in_symbolizer = false;
+ thr->ignore_interceptors--;
}
ReportStack *NewReportStackEntry(uptr addr) {
@@ -103,13 +105,11 @@ ReportStack *SymbolizeCode(uptr addr) {
ent->col = col;
return ent;
}
- if (!Symbolizer::Get()->IsAvailable())
- return SymbolizeCodeAddr2Line(addr);
static const uptr kMaxAddrFrames = 16;
InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
for (uptr i = 0; i < kMaxAddrFrames; i++)
new(&addr_frames[i]) AddressInfo();
- uptr addr_frames_num = Symbolizer::Get()->SymbolizeCode(
+ uptr addr_frames_num = Symbolizer::Get()->SymbolizePC(
addr, addr_frames.data(), kMaxAddrFrames);
if (addr_frames_num == 0)
return NewReportStackEntry(addr);
@@ -129,8 +129,6 @@ ReportStack *SymbolizeCode(uptr addr) {
}
ReportLocation *SymbolizeData(uptr addr) {
- if (!Symbolizer::Get()->IsAvailable())
- return 0;
DataInfo info;
if (!Symbolizer::Get()->SymbolizeData(addr, &info))
return 0;
@@ -148,8 +146,6 @@ ReportLocation *SymbolizeData(uptr addr) {
}
void SymbolizeFlush() {
- if (!Symbolizer::Get()->IsAvailable())
- return;
Symbolizer::Get()->Flush();
}
diff --git a/libsanitizer/tsan/tsan_symbolize.h b/libsanitizer/tsan/tsan_symbolize.h
index 892c11c0667..0d9077ed379 100644
--- a/libsanitizer/tsan/tsan_symbolize.h
+++ b/libsanitizer/tsan/tsan_symbolize.h
@@ -22,8 +22,6 @@ ReportStack *SymbolizeCode(uptr addr);
ReportLocation *SymbolizeData(uptr addr);
void SymbolizeFlush();
-ReportStack *SymbolizeCodeAddr2Line(uptr addr);
-
ReportStack *NewReportStackEntry(uptr addr);
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc b/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc
deleted file mode 100644
index c278a42f317..00000000000
--- a/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc
+++ /dev/null
@@ -1,191 +0,0 @@
-//===-- tsan_symbolize_addr2line.cc ---------------------------------------===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of ThreadSanitizer (TSan), a race detector.
-//
-//===----------------------------------------------------------------------===//
-#include "sanitizer_common/sanitizer_common.h"
-#include "sanitizer_common/sanitizer_libc.h"
-#include "tsan_symbolize.h"
-#include "tsan_mman.h"
-#include "tsan_rtl.h"
-#include "tsan_platform.h"
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <link.h>
-#include <linux/limits.h>
-#include <sys/types.h>
-
-namespace __tsan {
-
-struct ModuleDesc {
- const char *fullname;
- const char *name;
- uptr base;
- int inp_fd;
- int out_fd;
-};
-
-struct SectionDesc {
- SectionDesc *next;
- ModuleDesc *module;
- uptr base;
- uptr end;
-};
-
-struct DlIteratePhdrCtx {
- SectionDesc *sections;
- bool is_first;
-};
-
-static void NOINLINE InitModule(ModuleDesc *m) {
- int outfd[2] = {};
- if (pipe(&outfd[0])) {
- Printf("ThreadSanitizer: outfd pipe() failed (%d)\n", errno);
- Die();
- }
- int infd[2] = {};
- if (pipe(&infd[0])) {
- Printf("ThreadSanitizer: infd pipe() failed (%d)\n", errno);
- Die();
- }
- int pid = fork();
- if (pid == 0) {
- internal_close(STDOUT_FILENO);
- internal_close(STDIN_FILENO);
- internal_dup2(outfd[0], STDIN_FILENO);
- internal_dup2(infd[1], STDOUT_FILENO);
- internal_close(outfd[0]);
- internal_close(outfd[1]);
- internal_close(infd[0]);
- internal_close(infd[1]);
- for (int fd = getdtablesize(); fd > 2; fd--)
- internal_close(fd);
- execl("/usr/bin/addr2line", "/usr/bin/addr2line", "-Cfe", m->fullname, 0);
- _exit(0);
- } else if (pid < 0) {
- Printf("ThreadSanitizer: failed to fork symbolizer\n");
- Die();
- }
- internal_close(outfd[0]);
- internal_close(infd[1]);
- m->inp_fd = infd[0];
- m->out_fd = outfd[1];
-}
-
-static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
- DlIteratePhdrCtx *ctx = (DlIteratePhdrCtx*)arg;
- InternalScopedBuffer<char> tmp(128);
- if (ctx->is_first) {
- internal_snprintf(tmp.data(), tmp.size(), "/proc/%d/exe",
- (int)internal_getpid());
- info->dlpi_name = tmp.data();
- }
- ctx->is_first = false;
- if (info->dlpi_name == 0 || info->dlpi_name[0] == 0)
- return 0;
- ModuleDesc *m = (ModuleDesc*)internal_alloc(MBlockReportStack,
- sizeof(ModuleDesc));
- m->fullname = internal_strdup(info->dlpi_name);
- m->name = internal_strrchr(m->fullname, '/');
- if (m->name)
- m->name += 1;
- else
- m->name = m->fullname;
- m->base = (uptr)info->dlpi_addr;
- m->inp_fd = -1;
- m->out_fd = -1;
- DPrintf2("Module %s %zx\n", m->name, m->base);
- for (int i = 0; i < info->dlpi_phnum; i++) {
- const Elf64_Phdr *s = &info->dlpi_phdr[i];
- DPrintf2(" Section p_type=%zx p_offset=%zx p_vaddr=%zx p_paddr=%zx"
- " p_filesz=%zx p_memsz=%zx p_flags=%zx p_align=%zx\n",
- (uptr)s->p_type, (uptr)s->p_offset, (uptr)s->p_vaddr,
- (uptr)s->p_paddr, (uptr)s->p_filesz, (uptr)s->p_memsz,
- (uptr)s->p_flags, (uptr)s->p_align);
- if (s->p_type != PT_LOAD)
- continue;
- SectionDesc *sec = (SectionDesc*)internal_alloc(MBlockReportStack,
- sizeof(SectionDesc));
- sec->module = m;
- sec->base = info->dlpi_addr + s->p_vaddr;
- sec->end = sec->base + s->p_memsz;
- sec->next = ctx->sections;
- ctx->sections = sec;
- DPrintf2(" Section %zx-%zx\n", sec->base, sec->end);
- }
- return 0;
-}
-
-static SectionDesc *InitSections() {
- DlIteratePhdrCtx ctx = {0, true};
- dl_iterate_phdr(dl_iterate_phdr_cb, &ctx);
- return ctx.sections;
-}
-
-static SectionDesc *GetSectionDesc(uptr addr) {
- static SectionDesc *sections = 0;
- if (sections == 0)
- sections = InitSections();
- for (SectionDesc *s = sections; s; s = s->next) {
- if (addr >= s->base && addr < s->end) {
- if (s->module->inp_fd == -1)
- InitModule(s->module);
- return s;
- }
- }
- return 0;
-}
-
-ReportStack *SymbolizeCodeAddr2Line(uptr addr) {
- SectionDesc *s = GetSectionDesc(addr);
- if (s == 0)
- return NewReportStackEntry(addr);
- ModuleDesc *m = s->module;
- uptr offset = addr - m->base;
- char addrstr[32];
- internal_snprintf(addrstr, sizeof(addrstr), "%p\n", (void*)offset);
- if (0 >= internal_write(m->out_fd, addrstr, internal_strlen(addrstr))) {
- Printf("ThreadSanitizer: can't write from symbolizer (%d, %d)\n",
- m->out_fd, errno);
- Die();
- }
- InternalScopedBuffer<char> func(1024);
- ssize_t len = internal_read(m->inp_fd, func.data(), func.size() - 1);
- if (len <= 0) {
- Printf("ThreadSanitizer: can't read from symbolizer (%d, %d)\n",
- m->inp_fd, errno);
- Die();
- }
- func.data()[len] = 0;
- ReportStack *res = NewReportStackEntry(addr);
- res->module = internal_strdup(m->name);
- res->offset = offset;
- char *pos = (char*)internal_strchr(func.data(), '\n');
- if (pos && func[0] != '?') {
- res->func = (char*)internal_alloc(MBlockReportStack, pos - func.data() + 1);
- internal_memcpy(res->func, func.data(), pos - func.data());
- res->func[pos - func.data()] = 0;
- char *pos2 = (char*)internal_strchr(pos, ':');
- if (pos2) {
- res->file = (char*)internal_alloc(MBlockReportStack, pos2 - pos - 1 + 1);
- internal_memcpy(res->file, pos + 1, pos2 - pos - 1);
- res->file[pos2 - pos - 1] = 0;
- res->line = atoi(pos2 + 1);
- }
- }
- return res;
-}
-
-ReportStack *SymbolizeDataAddr2Line(uptr addr) {
- return 0;
-}
-
-} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_sync.cc b/libsanitizer/tsan/tsan_sync.cc
index 0c5be105f67..f6f2cb731e7 100644
--- a/libsanitizer/tsan/tsan_sync.cc
+++ b/libsanitizer/tsan/tsan_sync.cc
@@ -15,10 +15,13 @@
namespace __tsan {
+void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s);
+
SyncVar::SyncVar(uptr addr, u64 uid)
: mtx(MutexTypeSyncVar, StatMtxSyncVar)
, addr(addr)
, uid(uid)
+ , creation_stack_id()
, owner_tid(kInvalidTid)
, last_lock()
, recursion()
@@ -60,9 +63,11 @@ SyncVar* SyncTab::Create(ThreadState *thr, uptr pc, uptr addr) {
void *mem = internal_alloc(MBlockSync, sizeof(SyncVar));
const u64 uid = atomic_fetch_add(&uid_gen_, 1, memory_order_relaxed);
SyncVar *res = new(mem) SyncVar(addr, uid);
-#ifndef TSAN_GO
- res->creation_stack_id = CurrentStackId(thr, pc);
-#endif
+ res->creation_stack_id = 0;
+ if (!kGoMode) // Go does not use them
+ res->creation_stack_id = CurrentStackId(thr, pc);
+ if (flags()->detect_deadlocks)
+ DDMutexInit(thr, pc, res);
return res;
}
diff --git a/libsanitizer/tsan/tsan_sync.h b/libsanitizer/tsan/tsan_sync.h
index 2867a8ac79e..3838df91d75 100644
--- a/libsanitizer/tsan/tsan_sync.h
+++ b/libsanitizer/tsan/tsan_sync.h
@@ -13,14 +13,13 @@
#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
#include "tsan_clock.h"
#include "tsan_defs.h"
#include "tsan_mutex.h"
namespace __tsan {
-class SlabCache;
-
class StackTrace {
public:
StackTrace();
@@ -55,8 +54,6 @@ struct SyncVar {
Mutex mtx;
uptr addr;
const u64 uid; // Globally unique id.
- SyncClock clock;
- SyncClock read_clock; // Used for rw mutexes only.
u32 creation_stack_id;
int owner_tid; // Set only by exclusive owners.
u64 last_lock;
@@ -66,8 +63,12 @@ struct SyncVar {
bool is_broken;
bool is_linker_init;
SyncVar *next; // In SyncTab hashtable.
+ DDMutex dd;
+ SyncClock read_clock; // Used for rw mutexes only.
+ // The clock is placed last, so that it is situated on a different cache line
+ // with the mtx. This reduces contention for hot sync objects.
+ SyncClock clock;
- uptr GetMemoryConsumption();
u64 GetId() const {
// 47 lsb is addr, then 14 bits is low part of uid, then 3 zero bits.
return GetLsb((u64)addr | (uid << 47), 61);
@@ -96,8 +97,6 @@ class SyncTab {
SyncVar* Create(ThreadState *thr, uptr pc, uptr addr);
- uptr GetMemoryConsumption(uptr *nsync);
-
private:
struct Part {
Mutex mtx;
diff --git a/libsanitizer/tsan/tsan_vector.h b/libsanitizer/tsan/tsan_vector.h
index 4da8b83d5c3..f65ad2b5560 100644
--- a/libsanitizer/tsan/tsan_vector.h
+++ b/libsanitizer/tsan/tsan_vector.h
@@ -56,10 +56,18 @@ class Vector {
return begin_[i];
}
- T *PushBack(T v = T()) {
+ T *PushBack() {
EnsureSize(Size() + 1);
- end_[-1] = v;
- return &end_[-1];
+ T *p = &end_[-1];
+ internal_memset(p, 0, sizeof(*p));
+ return p;
+ }
+
+ T *PushBack(const T& v) {
+ EnsureSize(Size() + 1);
+ T *p = &end_[-1];
+ internal_memcpy(p, &v, sizeof(*p));
+ return p;
}
void PopBack() {
@@ -72,7 +80,7 @@ class Vector {
EnsureSize(size);
if (old_size < size) {
for (uptr i = old_size; i < size; i++)
- begin_[i] = T();
+ internal_memset(&begin_[i], 0, sizeof(begin_[i]));
}
}
diff --git a/libsanitizer/ubsan/ubsan_diag.cc b/libsanitizer/ubsan/ubsan_diag.cc
index 786ffa7254f..1dfe7255f68 100644
--- a/libsanitizer/ubsan/ubsan_diag.cc
+++ b/libsanitizer/ubsan/ubsan_diag.cc
@@ -11,6 +11,7 @@
#include "ubsan_diag.h"
#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_report_decorator.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
@@ -19,6 +20,22 @@
using namespace __ubsan;
+static void InitializeSanitizerCommon() {
+ static StaticSpinMutex init_mu;
+ SpinMutexLock l(&init_mu);
+ static bool initialized;
+ if (initialized)
+ return;
+ if (0 == internal_strcmp(SanitizerToolName, "SanitizerTool")) {
+ // UBSan is run in a standalone mode. Initialize it now.
+ SanitizerToolName = "UndefinedBehaviorSanitizer";
+ CommonFlags *cf = common_flags();
+ SetCommonFlagsDefaults(cf);
+ cf->print_summary = false;
+ }
+ initialized = true;
+}
+
Location __ubsan::getCallerLocation(uptr CallerLoc) {
if (!CallerLoc)
return Location();
@@ -30,9 +47,11 @@ Location __ubsan::getCallerLocation(uptr CallerLoc) {
Location __ubsan::getFunctionLocation(uptr Loc, const char **FName) {
if (!Loc)
return Location();
+ // FIXME: We may need to run initialization earlier.
+ InitializeSanitizerCommon();
AddressInfo Info;
- if (!Symbolizer::GetOrInit()->SymbolizeCode(Loc, &Info, 1) ||
+ if (!Symbolizer::GetOrInit()->SymbolizePC(Loc, &Info, 1) ||
!Info.module || !*Info.module)
return Location(Loc);
diff --git a/libsanitizer/ubsan/ubsan_value.cc b/libsanitizer/ubsan/ubsan_value.cc
index 141e8b53504..e2f664d3b24 100644
--- a/libsanitizer/ubsan/ubsan_value.cc
+++ b/libsanitizer/ubsan/ubsan_value.cc
@@ -92,6 +92,7 @@ FloatMax Value::getFloatValue() const {
switch (getType().getFloatBitWidth()) {
case 64: return *reinterpret_cast<double*>(Val);
case 80: return *reinterpret_cast<long double*>(Val);
+ case 96: return *reinterpret_cast<long double*>(Val);
case 128: return *reinterpret_cast<long double*>(Val);
}
}
diff --git a/libsanitizer/ubsan/ubsan_value.h b/libsanitizer/ubsan/ubsan_value.h
index 6ca0f56c99d..abfd31fbd99 100644
--- a/libsanitizer/ubsan/ubsan_value.h
+++ b/libsanitizer/ubsan/ubsan_value.h
@@ -12,9 +12,9 @@
#ifndef UBSAN_VALUE_H
#define UBSAN_VALUE_H
-// For now, only support linux and darwin. Other platforms should be easy to
-// add, and probably work as-is.
-#if !defined(__linux__) && !defined(__APPLE__)
+// For now, only support Linux, FreeBSD and Darwin. Other platforms should
+// be easy to add, and probably work as-is.
+#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__APPLE__)
#error "UBSan not supported for this platform!"
#endif
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index cf5d836f325..df15a78672c 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,402 @@
+2014-06-02 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/condition_variable (condition_variable_any::_Unlock): Do
+ not swallow __forced_unwind.
+ * include/std/future (__future_base::_Task_setter): Likewise.
+ (__future_base::_Async_state_impl): Turn __forced_unwind into broken
+ promise and rethrow.
+ * include/std/mutex (try_lock): Likewise.
+ * testsuite/30_threads/async/forced_unwind.cc: New.
+ * testsuite/30_threads/packaged_task/forced_unwind.cc: New.
+
+ * include/bits/regex_compiler.h (__detail::_BracketMatcher): Reorder
+ members to avoid wasted space when not using a cache.
+ (__detail::_BracketMatcher::_M_ready()): Sort and deduplicate set.
+ * include/bits/regex_compiler.tcc
+ (__detail::_BracketMatcher::_M_apply(_CharT, false_type)): Use binary
+ search on set.
+ * include/bits/regex_executor.h (__detail::_Executor::_Match_mode):
+ New enumeration type to indicate match mode.
+ (__detail::_Executor::_State_info): New type holding members only
+ needed in BFS-mode. Replace unique_ptr<vector<bool>> with
+ unique_ptr<bool[]>.
+ (__detail::_Executor::_M_rep_once_more, __detail::_Executor::_M_dfs):
+ Replace template parameter with run-time function parameter.
+ (__detail::_Executor::_M_main): Likewise. Dispatch to ...
+ (__detail::_Executor::_M_main_dispatch): New overloaded functions to
+ implement DFS and BFS mode.
+ * include/bits/regex_executor.tcc (__detail::_Executor::_M_main):
+ Split implementation into ...
+ (__detail::_Executor::_M_main_dispatch): New overloaded functions.
+ (__detail::_Executor::_M_lookahead): Create nested executor on stack.
+ (__detail::_Executor::_M_rep_once_more): Pass match mode as function
+ argument instead of template argument.
+ (__detail::_Executor::_M_dfs): Likewise.
+ * include/bits/regex_scanner.tcc: Fix typos in comments.
+ * testsuite/performance/28_regex/range.cc: New.
+
+2014-06-02 Rüdiger Sonderfeld <ruediger@c-plusplus.de>
+ Jonathan Wakely <jwakely@redhat.com>
+
+ * libstdc++-v3/include/std/type_traits (__strictest_alignment): New
+ helper struct.
+ (aligned_union): New struct (C++11).
+ (aligned_union_t): New type alias (C++14).
+ * doc/xml/manual/status_cxx2011.xml: Update.
+ * libstdc++-v3/testsuite/20_util/aligned_union/1.cc: New file.
+ * testsuite/20_util/declval/requirements/1_neg.cc: Adjust dg-error
+ line number.
+
+2014-06-01 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/61374
+ * include/experimental/string_view (operator basic_string): Correct
+ order of arguments.
+ (to_string): Replace with member function.
+ Add inline specifiers. Remove unused header. Remove _S_empty_rep and
+ allow _M_str to be null.
+ * testsuite/experimental/string_view/cons/char/1.cc: Adjust to new
+ default constructor semantics.
+ * testsuite/experimental/string_view/cons/wchar_t/1.cc: Likewise.
+ * testsuite/experimental/string_view/operations/copy/char/1.cc: Fix
+ copyright dates. Remove unused header.
+ * testsuite/experimental/string_view/operations/copy/wchar_t/1.cc:
+ Likewise.
+ * testsuite/experimental/string_view/operations/data/char/1.cc:
+ Fix copyright dates. Adjust to new default constructor semantics.
+ * testsuite/experimental/string_view/operations/data/wchar_t/1.cc:
+ Likewise.
+ * testsuite/experimental/string_view/operations/to_string/1.cc: New.
+
+ * include/bits/uses_allocator.h (__uses_allocator_helper): Simplify.
+ (__uses_allocator_arg): Remove unused type.
+ (__uses_alloc0): Turn into a trivial type.
+ (__uses_alloc): Add missing template parameter in primary template.
+ (__uses_alloc_impl): Rename to __uses_alloc_t.
+
+2014-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/lib/libstdc++.exp (libstdc++_init): Adjust regexp to
+ work with previous versions of Tcl.
+
+ * doc/xml/manual/appendix_contributing.xml (list.copyright): Replace
+ Benjamin's old email address.
+
+ * doc/xml/manual/appendix_contributing.xml (list.copyright): Add
+ Paolo's address too.
+
+2014-05-29 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/tr2/bool_set: Use UTF-8 for accented characters.
+ * scripts/run_doxygen: Handle Doxygen 1.8.x change.
+ * doc/doxygen/user.cfg.in: Update to Doxygen 1.8.6 format. Set
+ QUIET=YES, remove obsolete SYMBOL_CACHE_SIZE tag.
+
+2014-05-27 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/61329
+ * include/bits/regex_automaton.tcc (_State_base::_M_print): Add
+ inline specifier.
+ (_State_base::_M_dot): Likewise.
+
+2014-05-25 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * include/profile/map.h: Fix typo in comment; minor formatting fix.
+ * include/profile/multimap.h: Likewise.
+ * include/profile/set.h: Likewise.
+ * include/profile/multiset.h: Likewise.
+
+2014-05-24 François Dumont <fdumont@gcc.gnu.org>
+
+ * include/profile/array: Clean useless white chars.
+ * include/profile/base.h: Likewise.
+ * include/profile/iterator_tracker.h: Likewise.
+ * include/profile/bitset: Code cleanup and remove not instrumented code.
+ * include/profile/deque: Likewise.
+ * include/profile/forward_list: Likewise.
+ * include/profile/list (std::__profile::_List_profile<>): New.
+ (std::__profile::list<>): Inherit from latter and adapt.
+ * include/profile/impl/profiler_map_to_unordered_map.h: Generalize
+ advise to match any ordered to unordered container conversion.
+ * include/profile/ordered_base.h (std::__profile::_Ordered_profile<>):
+ New.
+ * include/Makefile.am: Add latter.
+ * include/Makefile.in: Regenerate.
+ * include/profile/map.h (std::__profile::map<>): Inherit from latter,
+ remove not instrumented code.
+ * include/profile/multimap.h (std::__profile::multimap<>): Likewise.
+ * include/profile/set.h (std::__profile::set<>): Likewise.
+ * include/profile/multiset.h (std::__profile::multiset<>): Likewise.
+ * include/profile/unordered_base.h: Add some line feed.
+ * include/profile/unordered_map: Clean useless white chars and replace
+ spaces with tabs.
+ * include/profile/unordered_set: Likewise.
+ * include/profile/vector (std::__profile::_Vector_profile_pre<>): New.
+ (std::__profile::_Vector_profile_post<>): New.
+ (std::__profile::vector<>): Inherit from latter and adapt.
+
+2014-05-23 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/60793
+ * testsuite/*: Use 's/\*-\*-freebsd\* /&*-*-dragonfly* /' to add
+ dragonfly target selector to all tests that run on freebsd.
+
+ * testsuite/23_containers/vector/capacity/resize/1.cc: Add xfail for
+ dragonfly.
+ * testsuite/30_threads/call_once/60497.cc: Add target selectors.
+ * testsuite/30_threads/condition_variable/members/53841.cc: Likewise.
+
+ * testsuite/30_threads/async/54297.cc: Remove duplicate dragonfly
+ selector.
+ * testsuite/30_threads/call_once/60497.cc: Likewise.
+ * testsuite/30_threads/condition_variable/54185.cc: Likewise.
+ * testsuite/30_threads/condition_variable_any/53830.cc: Likewise.
+ * testsuite/30_threads/packaged_task/60564.cc: Likewise.
+ * testsuite/30_threads/packaged_task/cons/56492.cc: Likewise.
+ * testsuite/30_threads/promise/60966.cc: Likewise.
+ * testsuite/30_threads/shared_lock/cons/1.cc: Likewise.
+ * testsuite/30_threads/shared_lock/cons/2.cc: Likewise.
+ * testsuite/30_threads/shared_lock/cons/3.cc: Likewise.
+ * testsuite/30_threads/shared_lock/cons/4.cc: Likewise.
+ * testsuite/30_threads/shared_lock/cons/5.cc: Likewise.
+ * testsuite/30_threads/shared_lock/cons/6.cc: Likewise.
+ * testsuite/30_threads/shared_lock/locking/1.cc: Likewise.
+ * testsuite/30_threads/shared_lock/locking/2.cc: Likewise.
+ * testsuite/30_threads/shared_lock/locking/3.cc: Likewise.
+ * testsuite/30_threads/shared_lock/locking/4.cc: Likewise.
+ * testsuite/30_threads/shared_lock/modifiers/1.cc: Likewise.
+ * testsuite/30_threads/shared_lock/modifiers/2.cc: Likewise.
+ * testsuite/30_threads/shared_timed_mutex/cons/1.cc: Likewise.
+ * testsuite/30_threads/shared_timed_mutex/try_lock/1.cc:
+ * testsuite/30_threads/shared_timed_mutex/try_lock/2.cc: Likewise.
+ * testsuite/30_threads/thread/native_handle/cancel.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/try_lock_until/57641.cc: Likewise.
+
+2014-05-21 François Dumont <fdumont@gcc.gnu.org>
+
+ PR libstdc++/61143
+ * include/bits/hashtable.h: Fix move semantic to leave hashtable in a
+ usable state.
+ * testsuite/23_containers/unordered_set/61143.cc: New.
+ * testsuite/23_containers/unordered_set/modifiers/swap.cc: New.
+
+2014-05-21 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/61269
+ * include/std/type_traits: Move include outside namespace std.
+ * testsuite/20_util/declval/requirements/1_neg.cc: Adjust dg-error.
+ * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Likewise.
+ * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc:
+ Likewise.
+
+ * config/locale/dragonfly/c_locale.cc (facet::_S_create_c_locale):
+ Fix warning.
+
+2014-05-21 John Marino <gnugcc@marino.st>
+
+ * acinclude.m4 (*-*-dragonfly*): New target.
+ * configure: Regenerate.
+ * configure.host (*-*-dragonfly*): New target.
+ * config/locale/dragonfly/c_locale.cc: New.
+ * config/locale/dragonfly/ctype_members.cc: New.
+ * config/os/bsd/dragonfly/ctype_base.h: New.
+ * config/os/bsd/dragonfly/ctype_configure_char.cc: New.
+ * config/os/bsd/dragonfly/ctype_inline.h: New.
+ * config/os/bsd/dragonfly/os_defines.h: New.
+
+2014-05-20 Cesar Philippidis <cesar@codesourcery.com>
+
+ * scripts/testsuite_flags.in (cxxflags): Remove @CXXFLAGS@ since
+ libstdc++.exp imports those flags via getenv.
+ * testsuite/lib/libstdc++.exp (libstdc++_init): Ensure that
+ CXXFLAGS contains a '-O' flag.
+
+2014-05-20 Alexey Merzlyakov <alexey.merzlyakov@samsung.com>
+
+ PR libstdc++/61223
+ Revert:
+ 2014-05-16 Alexey Merzlyakov <alexey.merzlyakov@samsung.com>
+
+ PR libstdc++/60758
+ * libsupc++/eh_arm.cc (__cxa_end_cleanup): Change r4 to lr in save/restore
+ and add unwind directives.
+
+2014-05-20 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * testsuite/lib/libstdc++.exp (load_gcc_lib): Register loaded libs.
+
+2014-05-20 Tim Shen <timshen91@gmail.com>
+
+ PR libstdc++/61227
+ * include/bits/regex_compiler.h
+ (_BracketMatcher<>::_M_add_character_class): Add negative character
+ class support.
+ * include/bits/regex_compiler.tcc (_BracketMatcher<>::_M_apply):
+ Likewise.
+ * testsuite/28_regex/algorithms/regex_match/ecma/char/quoted_char.cc:
+ Add more testcases.
+
+2014-05-19 Jonathan Wakely <jwakely@redhat.com>
+
+ * python/libstdcxx/v6/printers.py: Use Python3 raise syntax.
+
+2014-05-17 Marc Glisse <marc.glisse@inria.fr>
+
+ * libsupc++/new_op.cc: Factor the calls to malloc, use __builtin_expect.
+ * libsupc++/new_opnt.cc: Likewise.
+
+2014-05-17 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/60966
+ * include/std/future (__future_base::_State_baseV2::_M_set_result):
+ Pass lock into _M_do_set and hold it until the function returns.
+ Signal condition variable after call_once completes.
+ (__future_base::_State_baseV2::_M_do_set): Use lock argument. Do not
+ signal here.
+ * testsuite/30_threads/promise/60966.cc: New.
+
+2014-05-16 Iain Sandoe <iain@codesourcery.com>
+ Sandra Loosemore <sandra@codesourcery.com>
+
+ * testsuite/libstdc++-abi/abi.exp: Defer setting of baseline_subdir
+ until after checking that the test is eligible to be run.
+
+2014-05-16 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/20_util/make_unsigned/requirements/typedefs-1.cc: Fix
+ test for 32-bit target.
+ * testsuite/20_util/make_unsigned/requirements/typedefs-2.cc:
+ Likewise.
+ * testsuite/tr1/2_general_utilities/shared_ptr/modifiers/reset_neg.cc:
+ Fix test.
+
+2014-05-16 Alexey Merzlyakov <alexey.merzlyakov@samsung.com>
+
+ PR libstdc++/60758
+ * libsupc++/eh_arm.cc (__cxa_end_cleanup): Change r4 to lr in save/restore
+ and add unwind directives.
+
+2014-05-16 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/parse_numbers.h (__parse_int::_Number_help): Check for
+ overflow.
+ * include/std/chrono (chrono_literals::__select_type::_Select_type):
+ Remove.
+ (chrono_literals::_Checked_integral_constant): Define.
+ Simplify UDL operator templates and check for overflow.
+ * testsuite/20_util/duration/literals/range.cc: New.
+
+2014-05-16 Ed Smith-Rowland <3dw4rd@verizon.net>
+ Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/61166
+ * include/bits/parse_numbers.h: Use integral_constant to remove
+ duplication and simplify.
+ * testsuite/20_util/duration/literals/61166.cc: New.
+
+2014-05-15 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/60326
+ * include/std/type_traits (__make_unsigned, __make_signed): Define
+ specializations for wchar_t, char16_t and char32_t.
+ * testsuite/20_util/make_signed/requirements/typedefs-4.cc: New.
+ * testsuite/20_util/make_unsigned/requirements/typedefs-1.cc: Correct
+ test for make_unsigned<volatile wchar_t>.
+ * testsuite/20_util/make_unsigned/requirements/typedefs-2.cc:
+ Likewise.
+ * testsuite/20_util/declval/requirements/1_neg.cc: Adjust dg-error
+ line number.
+ * testsuite/20_util/make_signed/requirements/typedefs_neg.cc:
+ Likewise.
+ * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc:
+ Likewise.
+
+2014-05-15 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/tuple (tuple_size<cv _Tp>): Implement LWG 2313.
+ * include/std/array (tuple_size, tuple_element): Add Doxygen comments.
+ * include/std/utility (tuple_size, tuple_element): Likewise.
+ * testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc:
+ Adjust dg-error line number.
+
+2014-05-14 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/tuple (__add_c_ref, __add_ref, __add_r_ref): Remove.
+ (__tuple_element_t): Define.
+ (tuple_element): Use __tuple_element_t.
+ (__cv_tuple_size): Define.
+ (tuple_size<cv _Tp>): Use __cv_tuple_size.
+ (get, __get_helper, __get_helper2): Remove uses of __add_ref etc.
+ (get<_Tp>(tuple<_Types...>&&)): Use forward instead of move.
+ (__tuple_compare): Remove size check, re-order parameters.
+ (operator==, operator<): Use static_assert to check requirements.
+ * include/std/functional (__volget): use __tuple_element_t.
+ * testsuite/20_util/tuple/element_access/get_by_type.cc: Test rvalues.
+ * testsuite/20_util/uses_allocator/cons_neg.cc: Adjust dg-error.
+
+2014-05-13 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/60497
+ * include/std/tuple (get, __tuple_compare): Qualify more calls to
+ prevent ADL. Cast comparison results to bool.
+ * testsuite/20_util/tuple/60497.cc: Test accessing rvalues.
+ * testsuite/20_util/tuple/comparison_operators/overloaded.cc: New.
+
+ PR libstdc++/60497
+ * include/debug/array (get): Qualify call to other get overload.
+ * include/profile/array (get): Likewise.
+ * include/std/array (get): Likewise.
+ * include/std/functional (_Mu, _Bind, _Bind_result): Qualify std::get.
+ * include/std/mutex (unique_lock, call_once): Use __addressof.
+ (__unlock_impl): Remove unused template.
+ (__try_to_lock): Declare inline.
+ (__try_lock_impl::__do_try_lock): Qualify function calls.
+ (lock): Avoid narrowing conversion.
+ * testsuite/20_util/bind/60497.cc: New.
+ * testsuite/23_containers/array/element_access/60497.cc: New.
+ * testsuite/30_threads/call_once/60497.cc: New.
+ * testsuite/30_threads/unique_lock/cons/60497.cc: New.
+
+2014-05-09 Jonathan Wakely <jwakely@redhat.com>
+
+ * config/abi/pre/gnu.ver (GLIBCXX_3.4.20): Correct regex_error export.
+ (GLIBCXX_3.4.21): Export base object constructor for regex_error.
+ * acinclude.m4 (libtool_VERSION): Bump.
+ * configure: Regenerate.
+ * testsuite/util/testsuite_abi.cc: Add GLIBCXX_3.4.21 version.
+ * testsuite/28_regex/regex_error/base.cc: New.
+
+2014-05-08 Joshua Gay <jgay@gnu.org>
+
+ PR libstdc++/61117
+ * doc/xml/faq.xml (faq.license.what_restrictions): Replace "open
+ source" with "free software".
+ * doc/html/faq.html: Likewise.
+
+2014-05-08 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/57394
+ * include/bits/ios_base.h (ios_base(const ios_base&)): Define as
+ deleted for C++11.
+ (operator=(const ios_base&)): Likewise.
+ * include/std/streambuf: Remove trailing whitespace.
+ (basic_streambuf(const basic_streambuf&)): Fix initializer for
+ _M_out_end. Define as defaulted for C++11.
+ (operator=(const basic_streambuf&)): Define as defaulted for C++11.
+ (swap(basic_streambuf&)): Define for C++11.
+ * testsuite/27_io/basic_streambuf/cons/57394.cc: New.
+
+ PR libstdc++/13860
+ * include/std/fstream (basic_filebuf): Enforce requirements on traits.
+
+ * include/std/iostream: Fix URL in comment.
+ * src/c++98/ios_init.cc: Fix path in comment.
+
+2014-05-08 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * acinclude.m4 ([GLIBCXX_ENABLE_C99]): Avoid -Wwrite-strings warning.
+ * configure: Regenerate.
+
2014-05-07 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/61023
diff --git a/libstdc++-v3/ChangeLog-2013 b/libstdc++-v3/ChangeLog-2013
index 820b029a783..72344acefae 100644
--- a/libstdc++-v3/ChangeLog-2013
+++ b/libstdc++-v3/ChangeLog-2013
@@ -2013,7 +2013,7 @@
2013-08-14 Uros Bizjak <ubizjak@gmail.com>
* src/c++98/compatibility.cc (_ZTIe): Use
- reinterpret_cast<const cast *> to avoid -Wcast-qual warnings.
+ reinterpret_cast<const void *> to avoid -Wcast-qual warnings.
(_ZTIPe): Ditto.
(ZTIPKe): Ditto.
@@ -3834,7 +3834,7 @@
2013-04-03 Jonathan Wakely <jwakely.gcc@gmail.com>
* libsupc++/exception (get_terminate(), get_unexpected()): Declare.
- * libsupc++/eh_terminate.cc (get_terminate() , set_unexpected()):
+ * libsupc++/eh_terminate.cc (get_terminate(), get_unexpected()):
Define.
(set_terminate(terminate_handler)): Set atomically.
(set_unexpected(terminate_handler)): Likewise.
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 437221f3ab1..69b165f1805 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -1052,8 +1052,8 @@ AC_DEFUN([GLIBCXX_ENABLE_C99], [
vscanf("%i", args);
vsnprintf(fmt, 0, "%i", args);
vsscanf(fmt, "%i", args);
- }],
- [snprintf("12", 0, "%i");],
+ snprintf(fmt, 0, "%i");
+ }], [],
[glibcxx_cv_c99_stdio=yes], [glibcxx_cv_c99_stdio=no])
])
AC_MSG_RESULT($glibcxx_cv_c99_stdio)
@@ -1989,6 +1989,9 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
darwin* | freebsd*)
enable_clocale_flag=darwin
;;
+ dragonfly*)
+ enable_clocale_flag=dragonfly
+ ;;
openbsd*)
enable_clocale_flag=newlib
;;
@@ -2081,6 +2084,23 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
;;
+ dragonfly)
+ AC_MSG_RESULT(dragonfly)
+
+ CLOCALE_H=config/locale/generic/c_locale.h
+ CLOCALE_CC=config/locale/dragonfly/c_locale.cc
+ CCODECVT_CC=config/locale/generic/codecvt_members.cc
+ CCOLLATE_CC=config/locale/generic/collate_members.cc
+ CCTYPE_CC=config/locale/dragonfly/ctype_members.cc
+ CMESSAGES_H=config/locale/generic/messages_members.h
+ CMESSAGES_CC=config/locale/generic/messages_members.cc
+ CMONEY_CC=config/locale/generic/monetary_members.cc
+ CNUMERIC_CC=config/locale/generic/numeric_members.cc
+ CTIME_H=config/locale/generic/time_members.h
+ CTIME_CC=config/locale/generic/time_members.cc
+ CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+ ;;
+
gnu)
AC_MSG_RESULT(gnu)
@@ -3353,7 +3373,7 @@ changequote([,])dnl
fi
# For libtool versioning info, format is CURRENT:REVISION:AGE
-libtool_VERSION=6:20:0
+libtool_VERSION=6:21:0
# Everything parsed; figure out what files and settings to use.
case $enable_symvers in
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 162504813e7..ed7a93f646d 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -1363,10 +1363,18 @@ GLIBCXX_3.4.20 {
_ZSt24__throw_out_of_range_fmtPKcz;
# std::regex_error::regex_error(std::regex_constants::error_type)
- _ZNSt11regex_errorC[01]ENSt15regex_constants10error_typeE;
+ _ZNSt11regex_errorC1ENSt15regex_constants10error_typeE;
} GLIBCXX_3.4.19;
+GLIBCXX_3.4.21 {
+
+ # std::regex_error::regex_error(std::regex_constants::error_type)
+ _ZNSt11regex_errorC2ENSt15regex_constants10error_typeE;
+
+} GLIBCXX_3.4.20;
+
+
# Symbols in the support library (libsupc++) have their own tag.
CXXABI_1.3 {
diff --git a/libstdc++-v3/config/locale/dragonfly/c_locale.cc b/libstdc++-v3/config/locale/dragonfly/c_locale.cc
new file mode 100644
index 00000000000..b698f821ad8
--- /dev/null
+++ b/libstdc++-v3/config/locale/dragonfly/c_locale.cc
@@ -0,0 +1,299 @@
+// Wrapper for underlying C-language localization -*- C++ -*-
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+//
+// ISO C++ 14882: 22.8 Standard locale categories.
+//
+
+// Written by Benjamin Kosnik <bkoz@redhat.com>
+
+#include <cerrno> // For errno
+#include <cmath> // For isinf, finite, finitef, fabs
+#include <cstdlib> // For strof, strtold
+#include <cstring>
+#include <cstdio>
+#include <locale>
+#include <limits>
+
+#ifdef _GLIBCXX_HAVE_IEEEFP_H
+#include <ieeefp.h>
+#endif
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ template<>
+ void
+ __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
+ const __c_locale&) throw()
+ {
+ // Assumes __s formatted for "C" locale.
+ char* __old = setlocale(LC_ALL, 0);
+ const size_t __len = strlen(__old) + 1;
+ char* __sav = new char[__len];
+ memcpy(__sav, __old, __len);
+ setlocale(LC_ALL, "C");
+ char* __sanity;
+ bool __overflow = false;
+
+#if !__FLT_HAS_INFINITY__
+ errno = 0;
+#endif
+
+#ifdef _GLIBCXX_HAVE_STRTOF
+ __v = strtof(__s, &__sanity);
+#else
+ double __d = strtod(__s, &__sanity);
+ __v = static_cast<float>(__d);
+#ifdef _GLIBCXX_HAVE_FINITEF
+ if (!finitef (__v))
+ __overflow = true;
+#elif defined (_GLIBCXX_HAVE_FINITE)
+ if (!finite (static_cast<double> (__v)))
+ __overflow = true;
+#elif defined (_GLIBCXX_HAVE_ISINF)
+ if (isinf (static_cast<double> (__v)))
+ __overflow = true;
+#else
+ if (fabs(__d) > numeric_limits<float>::max())
+ __overflow = true;
+#endif
+#endif // _GLIBCXX_HAVE_STRTOF
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 23. Num_get overflow result.
+ if (__sanity == __s || *__sanity != '\0')
+ {
+ __v = 0.0f;
+ __err = ios_base::failbit;
+ }
+ else if (__overflow
+#if __FLT_HAS_INFINITY__
+ || __v == numeric_limits<float>::infinity()
+ || __v == -numeric_limits<float>::infinity()
+#else
+ || ((__v > 1.0f || __v < -1.0f) && errno == ERANGE)
+#endif
+ )
+ {
+ if (__v > 0.0f)
+ __v = numeric_limits<float>::max();
+ else
+ __v = -numeric_limits<float>::max();
+ __err = ios_base::failbit;
+ }
+
+ setlocale(LC_ALL, __sav);
+ delete [] __sav;
+ }
+
+ template<>
+ void
+ __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
+ const __c_locale&) throw()
+ {
+ // Assumes __s formatted for "C" locale.
+ char* __old = setlocale(LC_ALL, 0);
+ const size_t __len = strlen(__old) + 1;
+ char* __sav = new char[__len];
+ memcpy(__sav, __old, __len);
+ setlocale(LC_ALL, "C");
+ char* __sanity;
+
+#if !__DBL_HAS_INFINITY__
+ errno = 0;
+#endif
+
+ __v = strtod(__s, &__sanity);
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 23. Num_get overflow result.
+ if (__sanity == __s || *__sanity != '\0')
+ {
+ __v = 0.0;
+ __err = ios_base::failbit;
+ }
+ else if (
+#if __DBL_HAS_INFINITY__
+ __v == numeric_limits<double>::infinity()
+ || __v == -numeric_limits<double>::infinity())
+#else
+ (__v > 1.0 || __v < -1.0) && errno == ERANGE)
+#endif
+ {
+ if (__v > 0.0)
+ __v = numeric_limits<double>::max();
+ else
+ __v = -numeric_limits<double>::max();
+ __err = ios_base::failbit;
+ }
+
+ setlocale(LC_ALL, __sav);
+ delete [] __sav;
+ }
+
+ template<>
+ void
+ __convert_to_v(const char* __s, long double& __v,
+ ios_base::iostate& __err, const __c_locale&) throw()
+ {
+ // Assumes __s formatted for "C" locale.
+ char* __old = setlocale(LC_ALL, 0);
+ const size_t __len = strlen(__old) + 1;
+ char* __sav = new char[__len];
+ memcpy(__sav, __old, __len);
+ setlocale(LC_ALL, "C");
+
+#if !__LDBL_HAS_INFINITY__
+ errno = 0;
+#endif
+
+#if defined(_GLIBCXX_HAVE_STRTOLD) && !defined(_GLIBCXX_HAVE_BROKEN_STRTOLD)
+ char* __sanity;
+ __v = strtold(__s, &__sanity);
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 23. Num_get overflow result.
+ if (__sanity == __s || *__sanity != '\0')
+#else
+ typedef char_traits<char>::int_type int_type;
+ int __p = sscanf(__s, "%Lf", &__v);
+
+ if (!__p || static_cast<int_type>(__p) == char_traits<char>::eof())
+#endif
+ {
+ __v = 0.0l;
+ __err = ios_base::failbit;
+ }
+ else if (
+#if __LDBL_HAS_INFINITY__
+ __v == numeric_limits<long double>::infinity()
+ || __v == -numeric_limits<long double>::infinity())
+#else
+ (__v > 1.0l || __v < -1.0l) && errno == ERANGE)
+#endif
+ {
+ if (__v > 0.0l)
+ __v = numeric_limits<long double>::max();
+ else
+ __v = -numeric_limits<long double>::max();
+ __err = ios_base::failbit;
+ }
+
+ setlocale(LC_ALL, __sav);
+ delete [] __sav;
+ }
+
+
+ /* DragonFly's implementation of setlocale won't accept something like
+ "de_DE". According to nls manpage, the expected format is:
+ language[_territory][.codeset][@modifier], but it seems that both
+ the _territory and .codeset components are required.
+
+ As an attempt to correct for this, we'll tack on ".UTF-8" if
+ a period is not detected in the locale string.
+
+ There are no locales with modifiers on DragonFly so if found, they
+ will just be stripped off silently. e.g "de_DE@euro" will be reduced
+ to "de_DE". The UTF-8 default would be added after that.
+ */
+
+ void
+ locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
+ __c_locale)
+ {
+ const size_t size__s = (__s == NULL) ? 1 : strlen (__s);
+ const char UTF8[] = ".UTF-8";
+ char localspec[size__s + 6 + 1];
+
+ if (__s == NULL) {
+ localspec[0] = '\0';
+ } else {
+ strcpy (localspec, __s);
+ char * pch = strchr (localspec, '@');
+ if (pch != NULL)
+ *pch = 0;
+
+ if ( (strchr (__s, '.') == NULL)
+ && (strcmp (__s, "C") != 0)
+ && (strcmp (__s, "POSIX") != 0))
+ strncat (localspec, UTF8, 6);
+ }
+
+ const char * result = std::setlocale(LC_ALL, localspec);
+
+ if ((strcmp(result, "C") != 0) && (strcmp (result, localspec) != 0))
+ __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
+ "name not valid"));
+ __cloc = 0;
+ }
+
+ void
+ locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
+ { __cloc = 0; }
+
+ __c_locale
+ locale::facet::_S_clone_c_locale(__c_locale&) throw()
+ { return __c_locale(); }
+
+ __c_locale
+ locale::facet::_S_lc_ctype_c_locale(__c_locale, const char*)
+ { return __c_locale(); }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
+ {
+ "LC_CTYPE",
+ "LC_NUMERIC",
+ "LC_TIME",
+ "LC_COLLATE",
+ "LC_MONETARY",
+ "LC_MESSAGES"
+ };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ const char* const* const locale::_S_categories = __gnu_cxx::category_names;
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+// XXX GLIBCXX_ABI Deprecated
+#ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
+#define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
+ extern "C" void ldbl (void) __attribute__ ((alias (#dbl)))
+_GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi);
+#endif // _GLIBCXX_LONG_DOUBLE_COMPAT
diff --git a/libstdc++-v3/config/locale/dragonfly/ctype_members.cc b/libstdc++-v3/config/locale/dragonfly/ctype_members.cc
new file mode 100644
index 00000000000..4fe58fbd8dc
--- /dev/null
+++ b/libstdc++-v3/config/locale/dragonfly/ctype_members.cc
@@ -0,0 +1,173 @@
+// std::ctype implementation details, GNU version -*- C++ -*-
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+//
+// ISO C++ 14882: 22.2.1.1.2 ctype virtual functions.
+//
+
+// Written by Benjamin Kosnik <bkoz@redhat.com>
+
+#include <locale>
+#include <bits/c++locale_internal.h>
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+ // NB: The other ctype<char> specializations are in src/locale.cc and
+ // various /config/os/* files.
+
+ ctype_byname<char>::ctype_byname(const char* __s, size_t __refs)
+ : ctype<char>(0, false, __refs)
+ {
+ if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
+ {
+ this->_S_destroy_c_locale(this->_M_c_locale_ctype);
+ this->_S_create_c_locale(this->_M_c_locale_ctype, __s);
+ }
+ }
+
+ ctype_byname<char>::~ctype_byname()
+ { }
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+ ctype<wchar_t>::__wmask_type
+ ctype<wchar_t>::_M_convert_to_wmask(
+ const mask __attribute__((__unused__)) __m) const throw()
+ {
+ // DragonFly uses the same codes for 'char' as 'wchar_t', so this routine
+ // never gets called.
+ return __wmask_type();
+ };
+
+ wchar_t
+ ctype<wchar_t>::do_toupper(wchar_t __c) const
+ { return towupper(__c); }
+
+ const wchar_t*
+ ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const
+ {
+ while (__lo < __hi)
+ {
+ *__lo = towupper(*__lo);
+ ++__lo;
+ }
+ return __hi;
+ }
+
+ wchar_t
+ ctype<wchar_t>::do_tolower(wchar_t __c) const
+ { return towlower(__c); }
+
+ const wchar_t*
+ ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const
+ {
+ while (__lo < __hi)
+ {
+ *__lo = towlower(*__lo);
+ ++__lo;
+ }
+ return __hi;
+ }
+
+ wchar_t
+ ctype<wchar_t>::
+ do_widen(char __c) const
+ { return _M_widen[static_cast<unsigned char>(__c)]; }
+
+ const char*
+ ctype<wchar_t>::
+ do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const
+ {
+ while (__lo < __hi)
+ {
+ *__dest = _M_widen[static_cast<unsigned char>(*__lo)];
+ ++__lo;
+ ++__dest;
+ }
+ return __hi;
+ }
+
+ char
+ ctype<wchar_t>::
+ do_narrow(wchar_t __wc, char __dfault) const
+ {
+ if (__wc >= 0 && __wc < 128 && _M_narrow_ok)
+ return _M_narrow[__wc];
+ const int __c = wctob(__wc);
+ return (__c == EOF ? __dfault : static_cast<char>(__c));
+ }
+
+ const wchar_t*
+ ctype<wchar_t>::
+ do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault,
+ char* __dest) const
+ {
+ if (_M_narrow_ok)
+ while (__lo < __hi)
+ {
+ if (*__lo >= 0 && *__lo < 128)
+ *__dest = _M_narrow[*__lo];
+ else
+ {
+ const int __c = wctob(*__lo);
+ *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
+ }
+ ++__lo;
+ ++__dest;
+ }
+ else
+ while (__lo < __hi)
+ {
+ const int __c = wctob(*__lo);
+ *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
+ ++__lo;
+ ++__dest;
+ }
+ return __hi;
+ }
+
+ void
+ ctype<wchar_t>::_M_initialize_ctype() throw()
+ {
+ wint_t __i;
+ for (__i = 0; __i < 128; ++__i)
+ {
+ const int __c = wctob(__i);
+ if (__c == EOF)
+ break;
+ else
+ _M_narrow[__i] = static_cast<char>(__c);
+ }
+ if (__i == 128)
+ _M_narrow_ok = true;
+ else
+ _M_narrow_ok = false;
+ for (size_t __i = 0;
+ __i < sizeof(_M_widen) / sizeof(wint_t); ++__i)
+ _M_widen[__i] = btowc(__i);
+ }
+#endif // _GLIBCXX_USE_WCHAR_T
+}
diff --git a/libstdc++-v3/config/os/bsd/dragonfly/ctype_base.h b/libstdc++-v3/config/os/bsd/dragonfly/ctype_base.h
new file mode 100644
index 00000000000..a95b248d016
--- /dev/null
+++ b/libstdc++-v3/config/os/bsd/dragonfly/ctype_base.h
@@ -0,0 +1,58 @@
+// Locale support -*- C++ -*-
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+//
+// ISO C++ 14882: 22.1 Locales
+//
+
+// Information as gleaned from /usr/include/ctype.h on DragonFly.
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /// @brief Base class for ctype.
+ struct ctype_base
+ {
+ // Non-standard typedefs.
+ typedef const int* __to_type;
+
+ // NB: Offsets into ctype<char>::_M_table force a particular size
+ // on the mask type. Because of this, we don't use an enum.
+ typedef unsigned long mask;
+ static const mask upper = _CTYPE_U;
+ static const mask lower = _CTYPE_L;
+ static const mask alpha = _CTYPE_A;
+ static const mask digit = _CTYPE_D;
+ static const mask xdigit = _CTYPE_X;
+ static const mask space = _CTYPE_S;
+ static const mask print = _CTYPE_R;
+ static const mask graph = _CTYPE_A | _CTYPE_D | _CTYPE_P;
+ static const mask cntrl = _CTYPE_C;
+ static const mask punct = _CTYPE_P;
+ static const mask alnum = _CTYPE_A | _CTYPE_D;
+ };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/config/os/bsd/dragonfly/ctype_configure_char.cc b/libstdc++-v3/config/os/bsd/dragonfly/ctype_configure_char.cc
new file mode 100644
index 00000000000..11fa22e737e
--- /dev/null
+++ b/libstdc++-v3/config/os/bsd/dragonfly/ctype_configure_char.cc
@@ -0,0 +1,99 @@
+// Locale support -*- C++ -*-
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file ctype_configure_char.cc */
+
+//
+// ISO C++ 14882: 22.1 Locales
+//
+
+#include <locale>
+#include <cstdlib>
+#include <cstring>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+// Information as gleaned from /usr/include/ctype.h
+
+ const ctype_base::mask*
+ ctype<char>::classic_table() throw()
+ { return 0; }
+
+ ctype<char>::ctype(__c_locale, const mask* __table, bool __del,
+ size_t __refs)
+ : facet(__refs), _M_del(__table != 0 && __del),
+ _M_toupper(NULL), _M_tolower(NULL),
+ _M_table(__table ? __table : classic_table())
+ {
+ memset(_M_widen, 0, sizeof(_M_widen));
+ _M_widen_ok = 0;
+ memset(_M_narrow, 0, sizeof(_M_narrow));
+ _M_narrow_ok = 0;
+ }
+
+ ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
+ : facet(__refs), _M_del(__table != 0 && __del),
+ _M_toupper(NULL), _M_tolower(NULL),
+ _M_table(__table ? __table : classic_table())
+ {
+ memset(_M_widen, 0, sizeof(_M_widen));
+ _M_widen_ok = 0;
+ memset(_M_narrow, 0, sizeof(_M_narrow));
+ _M_narrow_ok = 0;
+ }
+
+ char
+ ctype<char>::do_toupper(char __c) const
+ { return ::toupper((int) __c); }
+
+ const char*
+ ctype<char>::do_toupper(char* __low, const char* __high) const
+ {
+ while (__low < __high)
+ {
+ *__low = ::toupper((int) *__low);
+ ++__low;
+ }
+ return __high;
+ }
+
+ char
+ ctype<char>::do_tolower(char __c) const
+ { return ::tolower((int) __c); }
+
+ const char*
+ ctype<char>::do_tolower(char* __low, const char* __high) const
+ {
+ while (__low < __high)
+ {
+ *__low = ::tolower((int) *__low);
+ ++__low;
+ }
+ return __high;
+ }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/config/os/bsd/dragonfly/ctype_inline.h b/libstdc++-v3/config/os/bsd/dragonfly/ctype_inline.h
new file mode 100644
index 00000000000..984665ef948
--- /dev/null
+++ b/libstdc++-v3/config/os/bsd/dragonfly/ctype_inline.h
@@ -0,0 +1,133 @@
+// Locale support -*- C++ -*-
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/ctype_inline.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{locale}
+ */
+
+//
+// ISO C++ 14882: 22.1 Locales
+//
+
+// ctype bits to be inlined go here. Non-inlinable (ie virtual do_*)
+// functions go in ctype.cc
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ bool
+ ctype<char>::
+ is(mask __m, char __c) const
+ {
+ if (_M_table)
+ return _M_table[static_cast<unsigned char>(__c)] & __m;
+ else
+ return __istype(__c, __m);
+ }
+
+ const char*
+ ctype<char>::
+ is(const char* __low, const char* __high, mask* __vec) const
+ {
+ if (_M_table)
+ while (__low < __high)
+ *__vec++ = _M_table[static_cast<unsigned char>(*__low++)];
+ else
+ for (;__low < __high; ++__vec, ++__low)
+ {
+ *__vec = __maskrune (*__low, upper | lower | alpha | digit | xdigit
+ | space | print | graph | cntrl | punct | alnum);
+ }
+ return __high;
+ }
+
+ const char*
+ ctype<char>::
+ scan_is(mask __m, const char* __low, const char* __high) const
+ {
+ if (_M_table)
+ while (__low < __high
+ && !(_M_table[static_cast<unsigned char>(*__low)] & __m))
+ ++__low;
+ else
+ while (__low < __high && !this->is(__m, *__low))
+ ++__low;
+ return __low;
+ }
+
+ const char*
+ ctype<char>::
+ scan_not(mask __m, const char* __low, const char* __high) const
+ {
+ if (_M_table)
+ while (__low < __high
+ && (_M_table[static_cast<unsigned char>(*__low)] & __m) != 0)
+ ++__low;
+ else
+ while (__low < __high && this->is(__m, *__low) != 0)
+ ++__low;
+ return __low;
+ }
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+ inline bool
+ ctype<wchar_t>::
+ do_is(mask __m, wchar_t __c) const
+ {
+ return __istype (__c, __m);
+ }
+
+ inline const wchar_t*
+ ctype<wchar_t>::
+ do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const
+ {
+ for (; __lo < __hi; ++__vec, ++__lo)
+ *__vec = __maskrune (*__lo, upper | lower | alpha | digit | xdigit
+ | space | print | graph | cntrl | punct | alnum);
+ return __hi;
+ }
+
+ inline const wchar_t*
+ ctype<wchar_t>::
+ do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const
+ {
+ while (__lo < __hi && ! __istype (*__lo, __m))
+ ++__lo;
+ return __lo;
+ }
+
+ inline const wchar_t*
+ ctype<wchar_t>::
+ do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const
+ {
+ while (__lo < __hi && __istype (*__lo, __m))
+ ++__lo;
+ return __lo;
+ }
+#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/config/os/bsd/dragonfly/os_defines.h b/libstdc++-v3/config/os/bsd/dragonfly/os_defines.h
new file mode 100644
index 00000000000..9160eeb1254
--- /dev/null
+++ b/libstdc++-v3/config/os/bsd/dragonfly/os_defines.h
@@ -0,0 +1,32 @@
+// Specific definitions for BSD -*- C++ -*-
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+
+#ifndef _GLIBCXX_OS_DEFINES
+#define _GLIBCXX_OS_DEFINES 1
+
+// System-specific #define, typedefs, corrections, etc, go here. This
+// file will come before all others.
+
+#endif
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 9b842c70937..32ba6145f61 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -15849,6 +15849,9 @@ fi
darwin* | freebsd*)
enable_clocale_flag=darwin
;;
+ dragonfly*)
+ enable_clocale_flag=dragonfly
+ ;;
openbsd*)
enable_clocale_flag=newlib
;;
@@ -15994,6 +15997,24 @@ $as_echo "darwin or freebsd" >&6; }
CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
;;
+ dragonfly)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: dragonfly" >&5
+$as_echo "dragonfly" >&6; }
+
+ CLOCALE_H=config/locale/generic/c_locale.h
+ CLOCALE_CC=config/locale/dragonfly/c_locale.cc
+ CCODECVT_CC=config/locale/generic/codecvt_members.cc
+ CCOLLATE_CC=config/locale/generic/collate_members.cc
+ CCTYPE_CC=config/locale/dragonfly/ctype_members.cc
+ CMESSAGES_H=config/locale/generic/messages_members.h
+ CMESSAGES_CC=config/locale/generic/messages_members.cc
+ CMONEY_CC=config/locale/generic/monetary_members.cc
+ CNUMERIC_CC=config/locale/generic/numeric_members.cc
+ CTIME_H=config/locale/generic/time_members.h
+ CTIME_CC=config/locale/generic/time_members.cc
+ CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+ ;;
+
gnu)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: gnu" >&5
$as_echo "gnu" >&6; }
@@ -16900,11 +16921,12 @@ else
vscanf("%i", args);
vsnprintf(fmt, 0, "%i", args);
vsscanf(fmt, "%i", args);
+ snprintf(fmt, 0, "%i");
}
int
main ()
{
-snprintf("12", 0, "%i");
+
;
return 0;
}
@@ -16930,11 +16952,12 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
vscanf("%i", args);
vsnprintf(fmt, 0, "%i", args);
vsscanf(fmt, "%i", args);
+ snprintf(fmt, 0, "%i");
}
int
main ()
{
-snprintf("12", 0, "%i");
+
;
return 0;
}
@@ -77916,7 +77939,7 @@ $as_echo "$as_me: WARNING: === Symbol versioning will be disabled." >&2;}
fi
# For libtool versioning info, format is CURRENT:REVISION:AGE
-libtool_VERSION=6:20:0
+libtool_VERSION=6:21:0
# Everything parsed; figure out what files and settings to use.
case $enable_symvers in
diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host
index dc6c977bcc4..a12871aa365 100644
--- a/libstdc++-v3/configure.host
+++ b/libstdc++-v3/configure.host
@@ -260,6 +260,9 @@ case "${host_os}" in
os_include_dir="os/djgpp"
error_constants_dir="os/djgpp"
;;
+ dragonfly*)
+ os_include_dir="os/bsd/dragonfly"
+ ;;
freebsd*)
os_include_dir="os/bsd/freebsd"
;;
diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in b/libstdc++-v3/doc/doxygen/user.cfg.in
index 45efb632b87..c2ac1362dcc 100644
--- a/libstdc++-v3/doc/doxygen/user.cfg.in
+++ b/libstdc++-v3/doc/doxygen/user.cfg.in
@@ -1,110 +1,121 @@
-# Doxyfile 1.8.3.1
+# Doxyfile 1.8.6
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
-# All text after a hash (#) is considered a comment and will be ignored.
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
# The format is:
-# TAG = value [value, ...]
-# For lists items can also be appended using:
-# TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ").
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all
-# text before the first occurrence of this tag. Doxygen uses libiconv (or the
-# iconv built into libc) for the transcoding. See
-# http://www.gnu.org/software/libiconv for the list of possible encodings.
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
DOXYFILE_ENCODING = UTF-8
-# The PROJECT_NAME tag is a single word (or sequence of words) that should
-# identify the project. Note that if you do not use Doxywizard you need
-# to put quotes around the project name if it contains spaces.
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
PROJECT_NAME = libstdc++
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
-# if some version control system is used.
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
PROJECT_NUMBER =
# Using the PROJECT_BRIEF tag one can provide an optional one line description
-# for a project that appears at the top of each page and should give viewer
-# a quick idea about the purpose of the project. Keep the description short.
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF =
-# With the PROJECT_LOGO tag one can specify an logo or icon that is
-# included in the documentation. The maximum height of the logo should not
-# exceed 55 pixels and the maximum width should not exceed 200 pixels.
-# Doxygen will copy the logo to the output directory.
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
PROJECT_LOGO =
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
-# where doxygen was started. If left blank the current directory will be used.
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
OUTPUT_DIRECTORY = @outdir@
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
-# otherwise cause performance problems for the file system.
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
CREATE_SUBDIRS = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
-# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
-# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
-# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
-# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
OUTPUT_LANGUAGE = English
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
-# Set to NO to disable this.
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
BRIEF_MEMBER_DESC = NO
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
+# The default value is: YES.
REPEAT_BRIEF = YES
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
-# "represents" "a" "an" "the"
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
+# doxygen will generate a detailed section even if there is only a brief
# description.
+# The default value is: NO.
ALWAYS_DETAILED_SEC = YES
@@ -112,182 +123,206 @@ ALWAYS_DETAILED_SEC = YES
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
+# The default value is: NO.
INLINE_INHERITED_MEMB = YES
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
-# to NO the shortest path that makes the file name unique will be used.
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
FULL_PATH_NAMES = NO
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
-# path to strip. Note that you specify absolute paths here, but also
-# relative paths, which will be relative from the directory where doxygen is
-# started.
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH =
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
-# are normally passed to the compiler using the -I flag.
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
STRIP_FROM_INC_PATH =
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful if your file system
-# doesn't support long names like on DOS, Mac, or CD-ROM.
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
SHORT_NAMES = @shortname@
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like regular Qt-style comments
-# (thus requiring an explicit @brief command for a brief description.)
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
JAVADOC_AUTOBRIEF = NO
-# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
-# interpret the first line (until the first dot) of a Qt-style
-# comment as the brief description. If set to NO, the comments
-# will behave just like regular Qt-style comments (thus requiring
-# an explicit \brief command for a brief description.)
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
QT_AUTOBRIEF = NO
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
MULTILINE_CPP_IS_BRIEF = YES
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# re-implements.
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
INHERIT_DOCS = YES
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
-# be part of the file/class/namespace that contains it.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
TAB_SIZE = 4
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
ALIASES = "doctodo=@todo\nNeeds documentation! See http://gcc.gnu.org/onlinedocs/libstdc++/manual/documentation_style.html" \
"headername{1}=Instead, include \<\1\>." \
"headername{2}=Instead, include \<\1\> or \<\2\>."
# This tag can be used to specify a number of word-keyword mappings (TCL only).
-# A mapping has the form "name=value". For example adding
-# "class=itcl::class" will allow you to use the command class in the
-# itcl::class meaning.
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
TCL_SUBST =
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
-# of all members will be omitted, etc.
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
OPTIMIZE_OUTPUT_FOR_C = NO
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for
-# Java. For instance, namespaces will be presented as packages, qualified
-# scopes will look different, etc.
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources only. Doxygen will then generate output that is more tailored for
-# Fortran.
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for
-# VHDL.
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
OPTIMIZE_OUTPUT_VHDL = NO
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
-# using this tag. The format is ext=language, where ext is a file extension,
-# and language is one of the parsers supported by doxygen: IDL, Java,
-# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
-# C++. For instance to make doxygen treat .inc files as Fortran files (default
-# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
-# that for custom extensions you also need to set FILE_PATTERNS otherwise the
-# files are not read by doxygen.
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
EXTENSION_MAPPING =
-# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
-# comments according to the Markdown format, which allows for more readable
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
# documentation. See http://daringfireball.net/projects/markdown/ for details.
-# The output of markdown processing is further processed by doxygen, so you
-# can mix doxygen, HTML, and XML commands with Markdown formatting.
-# Disable only in case of backward compatibilities issues.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
MARKDOWN_SUPPORT = NO
-# When enabled doxygen tries to link words that correspond to
-# documented classes, or namespaces to their corresponding
-# documentation. Such a link can be prevented in individual cases by
-# by putting a % sign in front of the word or globally by setting
-# AUTOLINK_SUPPORT to NO.
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
AUTOLINK_SUPPORT = NO
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also makes the inheritance and collaboration
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
BUILTIN_STL_SUPPORT = NO
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
+# The default value is: NO.
CPP_CLI_SUPPORT = NO
-# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
-# Doxygen will parse them like normal C++ but will assume all classes use public
-# instead of private inheritance when no explicit protection keyword is present.
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate
-# getter and setter methods for a property. Setting this option to YES (the
-# default) will make doxygen replace the get and set methods by a property in
-# the documentation. This will only work if the methods are indeed getting or
-# setting a simple type. If this is not the case, or you want to show the
-# methods anyway, you should set this option to NO.
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
IDL_PROPERTY_SUPPORT = NO
@@ -295,67 +330,61 @@ IDL_PROPERTY_SUPPORT = NO
# tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
+# The default value is: NO.
DISTRIBUTE_GROUP_DOC = YES
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
-# the \nosubgrouping command.
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
SUBGROUPING = YES
-# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
-# unions are shown inside the group in which they are included (e.g. using
-# @ingroup) instead of on a separate page (for HTML and Man pages) or
-# section (for LaTeX and RTF).
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
INLINE_GROUPED_CLASSES = NO
-# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
-# unions with only public data fields will be shown inline in the documentation
-# of the scope in which they are defined (i.e. file, namespace, or group
-# documentation), provided this scope is documented. If set to NO (the default),
-# structs, classes, and unions are shown on a separate page (for HTML and Man
-# pages) or section (for LaTeX and RTF).
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
INLINE_SIMPLE_STRUCTS = NO
-# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
-# is documented as struct, union, or enum with the name of the typedef. So
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically
-# be useful for C code in case the coding convention dictates that all compound
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
TYPEDEF_HIDES_STRUCT = NO
-# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
-# determine which symbols to keep in memory and which to flush to disk.
-# When the cache is full, less often used symbols will be written to disk.
-# For small to medium size projects (<1000 input files) the default value is
-# probably good enough. For larger projects a too small cache size can cause
-# doxygen to be busy swapping symbols to and from disk most of the time
-# causing a significant performance penalty.
-# If the system has enough physical memory increasing the cache will improve the
-# performance by keeping more symbols in memory. Note that the value works on
-# a logarithmic scale so increasing the size by one will roughly double the
-# memory usage. The cache size is given by this formula:
-# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols.
-
-SYMBOL_CACHE_SIZE = 0
-
-# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
-# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
-# their name and scope. Since this can be an expensive process and often the
-# same symbol appear multiple times in the code, doxygen keeps a cache of
-# pre-resolved symbols. If the cache is too small doxygen will become slower.
-# If the cache is too large, memory is wasted. The cache size is given by this
-# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols.
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
LOOKUP_CACHE_SIZE = 0
@@ -364,312 +393,357 @@ LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
EXTRACT_ALL = NO
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
-# will be included in the documentation.
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
EXTRACT_PRIVATE = NO
# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
# scope will be included in the documentation.
+# The default value is: NO.
EXTRACT_PACKAGE = NO
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
-# will be included in the documentation.
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
EXTRACT_STATIC = YES
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
-# If set to NO only classes defined in header files are included.
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
EXTRACT_LOCAL_CLASSES = YES
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
-# If set to NO (the default) only methods in the interface are included.
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
EXTRACT_LOCAL_METHODS = YES
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base
-# name of the file that contains the anonymous namespace. By default
-# anonymous namespaces are hidden.
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
EXTRACT_ANON_NSPACES = NO
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
-# This option has no effect if EXTRACT_ALL is enabled.
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
HIDE_UNDOC_MEMBERS = NO
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
HIDE_UNDOC_CLASSES = YES
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
-# documentation.
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
-# function's detailed documentation block.
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
HIDE_IN_BODY_DOCS = NO
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
-# Set it to YES to include the internal documentation.
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
INTERNAL_DOCS = NO
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
CASE_SENSE_NAMES = NO
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
-# documentation. If set to YES the scope will be hidden.
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
HIDE_SCOPE_NAMES = NO
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
-# of that file.
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
SHOW_INCLUDE_FILES = NO
-# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
-# will list include files with double quotes in the documentation
-# rather than with sharp brackets.
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
FORCE_LOCAL_INCLUDES = NO
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
-# is inserted in the documentation for inline members.
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
INLINE_INFO = YES
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
-# declaration order.
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
SORT_MEMBER_DOCS = YES
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
-# declaration order.
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
SORT_BRIEF_DOCS = YES
-# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
-# will sort the (brief and detailed) documentation of class members so that
-# constructors and destructors are listed first. If set to NO (the default)
-# the constructors will appear in the respective orders defined by
-# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
-# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
-# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
SORT_MEMBERS_CTORS_1ST = YES
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
-# hierarchy of group names into alphabetical order. If set to NO (the default)
-# the group names will appear in their defined order.
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
SORT_GROUP_NAMES = YES
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
-# alphabetical list.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
SORT_BY_SCOPE_NAME = YES
-# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
-# do proper type resolution of all parameters of a function it will reject a
-# match between the prototype and the implementation of a member function even
-# if there is only one candidate or it is obvious which candidate to choose
-# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
-# will still accept a match between prototype and implementation in such cases.
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
STRICT_PROTO_MATCHING = NO
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
-# commands in the documentation.
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
GENERATE_TODOLIST = YES
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
-# commands in the documentation.
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
GENERATE_TESTLIST = NO
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
-# commands in the documentation.
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
GENERATE_BUGLIST = YES
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
-# \deprecated commands in the documentation.
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
GENERATE_DEPRECATEDLIST= YES
-# The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if section-label ... \endif
-# and \cond section-label ... \endcond blocks.
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
ENABLED_SECTIONS = @enabled_sections@
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or macro consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and macros in the
-# documentation can be controlled using \showinitializer or \hideinitializer
-# command in the documentation regardless of this setting.
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
MAX_INITIALIZER_LINES = 0
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
-# list will mention the files that were used to generate the documentation.
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
SHOW_USED_FILES = YES
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
-# This will remove the Files entry from the Quick Index and from the
-# Folder Tree View (if specified). The default is YES.
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
SHOW_FILES = YES
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
-# Namespaces page.
-# This will remove the Namespaces entry from the Quick Index
-# and from the Folder Tree View (if specified). The default is YES.
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
SHOW_NAMESPACES = YES
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
-# is used as the file version. See the manual for examples.
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. To create the layout file
-# that represents doxygen's defaults, run doxygen with the -l option.
-# You can optionally specify a file name after the option, if omitted
-# DoxygenLayout.xml will be used as the name of the layout file.
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
LAYOUT_FILE =
-# The CITE_BIB_FILES tag can be used to specify one or more bib files
-# containing the references data. This must be a list of .bib files. The
-# .bib extension is automatically appended if omitted. Using this command
-# requires the bibtex tool to be installed. See also
-# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
-# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
-# feature you need bibtex and perl available in the search path. Do not use
-# file names with spaces, bibtex cannot handle them.
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. Do not use file names with spaces, bibtex cannot handle them. See
+# also \cite for info how to create references.
CITE_BIB_FILES =
#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
+# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
-# The QUIET tag can be used to turn on/off the messages that are generated
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
-QUIET = NO
+QUIET = YES
# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
-# NO is used.
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
WARNINGS = YES
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
-# automatically be disabled.
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
WARN_IF_UNDOCUMENTED = NO
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
-# don't exist or using markup commands wrongly.
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
WARN_IF_DOC_ERROR = YES
-# The WARN_NO_PARAMDOC option can be enabled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
-# documentation.
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
WARN_NO_PARAMDOC = NO
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
-# be obtained via FILE_VERSION_FILTER)
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text "
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
-# to stderr.
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
WARN_LOGFILE =
#---------------------------------------------------------------------------
-# configuration options related to the input files
+# Configuration options related to the input files
#---------------------------------------------------------------------------
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
-# with spaces.
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
INPUT = @srcdir@/doc/doxygen/doxygroups.cc \
@srcdir@/libsupc++/cxxabi.h \
@@ -839,34 +913,37 @@ INPUT = @srcdir@/doc/doxygen/doxygroups.cc \
include/ext/pb_ds/detail/unordered_iterator
# This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-# also the default input encoding. Doxygen uses libiconv (or the iconv built
-# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
-# the list of possible encodings.
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
-# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
-# *.f90 *.f *.for *.vhd *.vhdl
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
FILE_PATTERNS = *.h \
*.hpp \
*.tcc
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
-# If left blank NO is used.
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
RECURSIVE = NO
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
# Note that relative paths are relative to the directory from which doxygen is
# run.
@@ -875,14 +952,16 @@ EXCLUDE = Makefile
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
+# The default value is: NO.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
-# for example use the pattern */test/*
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS = stamp-* \
doxygroups.cc \
@@ -894,819 +973,1080 @@ EXCLUDE_PATTERNS = stamp-* \
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
EXCLUDE_SYMBOLS =
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
-# the \include command).
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank all files are included.
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
EXAMPLE_PATTERNS =
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
-# Possible values are YES and NO. If left blank NO is used.
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
EXAMPLE_RECURSIVE = NO
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
-# the \image command).
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output.
-# If FILTER_PATTERNS is specified, this tag will be
-# ignored.
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis.
-# Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match.
-# The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty or if
-# non of the patterns match the file name, INPUT_FILTER is applied.
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
FILTER_SOURCE_FILES = NO
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
-# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
-# and it is also possible to disable source filtering for a specific pattern
-# using *.ext= (so without naming a filter). This option only has effect when
-# FILTER_SOURCE_FILES is enabled.
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
FILTER_SOURCE_PATTERNS =
-# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that
-# is part of the input, its contents will be placed on the main page (index.html).
-# This can be useful if you have a project on for instance GitHub and want reuse
-# the introduction page also for the doxygen output.
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
-# configuration options related to source browsing
+# Configuration options related to source browsing
#---------------------------------------------------------------------------
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
-# VERBATIM_HEADERS is set to NO.
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
SOURCE_BROWSER = YES
-# Setting the INLINE_SOURCES tag to YES will include the body
-# of functions and classes directly in the documentation.
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
INLINE_SOURCES = NO
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C, C++ and Fortran comments will always remain visible.
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
STRIP_CODE_COMMENTS = NO
-# If the REFERENCED_BY_RELATION tag is set to YES
-# then for each documented function all documented
-# functions referencing it will be listed.
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
REFERENCED_BY_RELATION = YES
-# If the REFERENCES_RELATION tag is set to YES
-# then for each documented function all documented entities
-# called/used by that function will be listed.
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
REFERENCES_RELATION = YES
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code.
-# Otherwise they will link to the documentation.
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
REFERENCES_LINK_SOURCE = YES
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
-# will need version 4.8.6 or higher.
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
USE_HTAGS = NO
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
-# which an include is specified. Set to NO to disable this.
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
VERBATIM_HEADERS = NO
#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
+# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
-# contains a lot of classes, structs, unions or interfaces.
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
ALPHABETICAL_INDEX = YES
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
-# in which this list will be split (can be a number in the range [1..20])
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
COLS_IN_ALPHA_INDEX = 2
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
-# should be ignored while generating the index headers.
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
-# configuration options related to the HTML output
+# Configuration options related to the HTML output
#---------------------------------------------------------------------------
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
-# generate HTML output.
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
GENERATE_HTML = @do_html@
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `html' will be used as the default path.
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = html
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
-# doxygen will generate files with .html extension.
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FILE_EXTENSION = .html
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard header. Note that when using a custom header you are responsible
-# for the proper inclusion of any scripts and style sheets that doxygen
-# needs, which is dependent on the configuration options used.
-# It is advised to generate a default header using "doxygen -w html
-# header.html footer.html stylesheet.css YourConfigFile" and then modify
-# that header. Note that the header is subject to change so you typically
-# have to redo this when upgrading to a newer version of doxygen or when
-# changing the value of configuration settings such as GENERATE_TREEVIEW!
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_HEADER =
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard footer.
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER =
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If left blank doxygen will
-# generate a default style sheet. Note that it is recommended to use
-# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
-# tag will in the future become obsolete.
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_STYLESHEET =
-# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
-# user-defined cascading style sheet that is included after the standard
-# style sheets created by doxygen. Using this option one can overrule
-# certain style aspects. This is preferred over using HTML_STYLESHEET
-# since it does not replace the standard style sheet and is therefor more
-# robust against future updates. Doxygen will copy the style sheet file to
-# the output directory.
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
+# defined cascading style sheet that is included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet file to the output directory. For an example
+# see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
-# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
-# files. In the HTML_STYLESHEET file, use the file name only. Also note that
-# the files will be copied as-is; there are no commands or markers available.
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES =
-# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
-# Doxygen will adjust the colors in the style sheet and background images
-# according to this color. Hue is specified as an angle on a colorwheel,
-# see http://en.wikipedia.org/wiki/Hue for more information.
-# For instance the value 0 represents red, 60 is yellow, 120 is green,
-# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
-# The allowed range is 0 to 359.
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_HUE = 220
-# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
-# the colors in the HTML output. For a value of 0 the output will use
-# grayscales only. A value of 255 will produce the most vivid colors.
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_SAT = 100
-# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
-# the luminance component of the colors in the HTML output. Values below
-# 100 gradually make the output lighter, whereas values above 100 make
-# the output darker. The value divided by 100 is the actual gamma applied,
-# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
-# and 100 does not change the gamma.
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
-# page will contain the date and time when the page was generated. Setting
-# this to NO can help when comparing the output of multiple runs.
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_DYNAMIC_SECTIONS = NO
-# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
-# entries shown in the various tree structured indices initially; the user
-# can expand and collapse entries dynamically later on. Doxygen will expand
-# the tree to such a level that at most the specified number of entries are
-# visible (unless a fully collapsed tree already exceeds this amount).
-# So setting the number of entries 1 will produce a full collapsed tree by
-# default. 0 is a special value representing an infinite number of entries
-# and will result in a full expanded tree by default.
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_INDEX_NUM_ENTRIES = 0
-# If the GENERATE_DOCSET tag is set to YES, additional index files
-# will be generated that can be used as input for Apple's Xcode 3
-# integrated development environment, introduced with OSX 10.5 (Leopard).
-# To create a documentation set, doxygen will generate a Makefile in the
-# HTML output directory. Running make will produce the docset in that
-# directory and running "make install" will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
-# it at startup.
-# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_DOCSET = NO
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
-# feed. A documentation feed provides an umbrella under which multiple
-# documentation sets from a single provider (such as a company or product suite)
-# can be grouped.
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDNAME = "Doxygen generated docs"
-# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
-# should uniquely identify the documentation set bundle. This should be a
-# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
-# will append .docset to the name.
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_BUNDLE_ID = org.gnu.libstdc++
-# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
-# identify the documentation publisher. This should be a reverse domain-name
-# style string, e.g. com.mycompany.MyDocSet.documentation.
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_ID = org.fsf
-# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_NAME = libstdc++
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
-# of the generated HTML documentation.
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_HTMLHELP = NO
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
-# the HTML help compiler on the generated index.hhp.
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
-# it should be included in the master .chm file (NO).
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
-# is used to encode HtmlHelp index (hhk), content (hhc) and project file
-# content.
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
-# normal table of contents (NO) in the .chm file.
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
-# to the contents of the HTML help documentation and to the tree view.
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
-# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
-# that can be used as input for Qt's qhelpgenerator to generate a
-# Qt Compressed Help (.qch) of the generated HTML documentation.
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_QHP = NO
-# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
-# be used to specify the file name of the resulting .qch file.
-# The path specified is relative to the HTML output folder.
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
QCH_FILE =
-# The QHP_NAMESPACE tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#namespace
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_NAMESPACE = org.doxygen.Project
-# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_VIRTUAL_FOLDER = doc
-# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
-# add. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#custom-filters
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
-# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
-# custom filter to add. For more information please see
-# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
-# Qt Help Project / Custom Filters</a>.
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
-# project's
-# filter section matches.
-# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
-# Qt Help Project / Filter Attributes</a>.
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS =
-# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
-# be used to specify the location of Qt's qhelpgenerator.
-# If non-empty doxygen will try to run qhelpgenerator on the generated
-# .qhp file.
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION =
-# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
-# will be generated, which together with the HTML files, form an Eclipse help
-# plugin. To install this plugin and make it available under the help contents
-# menu in Eclipse, the contents of the directory containing the HTML and XML
-# files needs to be copied into the plugins directory of eclipse. The name of
-# the directory within the plugins directory should be the same as
-# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
-# the help appears.
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_ECLIPSEHELP = NO
-# A unique identifier for the eclipse help plugin. When installing the plugin
-# the directory name containing the HTML and XML files should also have
-# this name.
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
ECLIPSE_DOC_ID = org.doxygen.Project
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
-# at top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it. Since the tabs have the same information as the
-# navigation tree you can set this option to NO if you already set
-# GENERATE_TREEVIEW to YES.
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = YES
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
-# structure should be generated to display hierarchical information.
-# If the tag value is set to YES, a side panel will be generated
-# containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
-# Windows users are probably better off using the HTML help feature.
-# Since the tree basically has the same information as the tab index you
-# could consider to set DISABLE_INDEX to NO when enabling this option.
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = YES
-# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
-# (range [0,1..20]) that doxygen will group on one line in the generated HTML
-# documentation. Note that a value of 0 will completely suppress the enum
-# values from appearing in the overview section.
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
ENUM_VALUES_PER_LINE = 4
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
-# is shown.
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
TREEVIEW_WIDTH = 250
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
-# links to external symbols imported via tag files in a separate window.
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
EXT_LINKS_IN_WINDOW = NO
-# Use this tag to change the font size of Latex formulas included
-# as images in the HTML documentation. The default is 10. Note that
-# when you change the font size after a successful doxygen run you need
-# to manually remove any form_*.png images from the HTML output directory
-# to force them to be regenerated.
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_FONTSIZE = 10
# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are
-# not supported properly for IE 6.0, but are supported on all modern browsers.
-# Note that when changing this option you need to delete any form_*.png files
-# in the HTML output before the changes have effect.
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_TRANSPARENT = YES
-# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
-# (see http://www.mathjax.org) which uses client side Javascript for the
-# rendering instead of using prerendered bitmaps. Use this if you do not
-# have LaTeX installed or if you want to formulas look prettier in the HTML
-# output. When enabled you may also need to install MathJax separately and
-# configure the path to it using the MATHJAX_RELPATH option.
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
USE_MATHJAX = NO
# When MathJax is enabled you can set the default output format to be used for
-# thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and
-# SVG. The default value is HTML-CSS, which is slower, but has the best
-# compatibility.
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_FORMAT = HTML-CSS
-# When MathJax is enabled you need to specify the location relative to the
-# HTML output directory using the MATHJAX_RELPATH option. The destination
-# directory should contain the MathJax.js script. For instance, if the mathjax
-# directory is located at the same level as the HTML output directory, then
-# MATHJAX_RELPATH should be ../mathjax. The default value points to
-# the MathJax Content Delivery Network so you can quickly see the result without
-# installing MathJax.
-# However, it is strongly recommended to install a local
-# copy of MathJax from http://www.mathjax.org before deployment.
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
-# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
-# names that should be enabled during MathJax rendering.
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
-# When the SEARCHENGINE tag is enabled doxygen will generate a search box
-# for the HTML output. The underlying search engine uses javascript
-# and DHTML and should work on any modern browser. Note that when using
-# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
-# (GENERATE_DOCSET) there is already a search function so this one should
-# typically be disabled. For large projects the javascript based search engine
-# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
SEARCHENGINE = NO
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript.
-# There are two flavours of web server based search depending on the
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavours of web server based searching depending on the
# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
# searching and an index file used by the script. When EXTERNAL_SEARCH is
-# enabled the indexing and searching needs to be provided by external tools.
-# See the manual for details.
+# enabled the indexing and searching needs to be provided by external tools. See
+# the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
SERVER_BASED_SEARCH = NO
-# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
# script for searching. Instead the search results are written to an XML file
# which needs to be processed by an external indexer. Doxygen will invoke an
-# external search engine pointed to by the SEARCHENGINE_URL option to obtain
-# the search results. Doxygen ships with an example indexer (doxyindexer) and
-# search engine (doxysearch.cgi) which are based on the open source search engine
-# library Xapian. See the manual for configuration details.
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
-# which will returned the search results when EXTERNAL_SEARCH is enabled.
-# Doxygen ships with an example search engine (doxysearch) which is based on
-# the open source search engine library Xapian. See the manual for configuration
-# details.
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHDATA_FILE = searchdata.xml
-# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
# all added to the same external search index. Each project needs to have a
-# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id
-# of to a relative location where the documentation can be found.
-# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ...
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
+# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
-# generate Latex output.
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
GENERATE_LATEX = @do_latex@
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `latex' will be used as the default path.
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
-# invoked. If left blank `latex' will be used as the default command name.
-# Note that when enabling USE_PDFLATEX this option is only used for
-# generating bitmaps for formulas in the HTML output, but not in the
-# Makefile that is written to the output directory.
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_CMD_NAME =
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
-# default command name.
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
MAKEINDEX_CMD_NAME = makeindex
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
-# save some trees in general.
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
COMPACT_LATEX = YES
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, letter, legal and
-# executive. If left blank a4wide will be used.
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
PAPER_TYPE = letter
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
-# packages that should be included in the LaTeX output.
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
EXTRA_PACKAGES = amsmath
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
-# standard header. Notice: only use this tag if you know what you are doing!
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
-# the generated latex document. The footer should contain everything after
-# the last chapter. If it is left blank doxygen will generate a
-# standard footer. Notice: only use this tag if you know what you are doing!
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
-# This makes the output suitable for online browsing using a pdf viewer.
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
PDF_HYPERLINKS = YES
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
USE_PDFLATEX = YES
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
-# This option is also used when generating formulas in HTML.
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BATCHMODE = YES
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
-# in the output.
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HIDE_INDICES = YES
-# If LATEX_SOURCE_CODE is set to YES then doxygen will include
-# source code with syntax highlighting in the LaTeX output.
-# Note that which sources are shown also depends on other settings
-# such as SOURCE_BROWSER.
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_SOURCE_CODE = NO
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
-# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
-# http://en.wikipedia.org/wiki/BibTeX for more info.
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BIB_STYLE = plain
#---------------------------------------------------------------------------
-# configuration options related to the RTF output
+# Configuration options related to the RTF output
#---------------------------------------------------------------------------
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
-# other RTF readers or editors.
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
GENERATE_RTF = NO
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `rtf' will be used as the default path.
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_OUTPUT = rtf
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
-# save some trees in general.
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
COMPACT_RTF = NO
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
-# Note: wordpad (write) and others do not support links.
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_HYPERLINKS = NO
-# Load style sheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
-# replacements, missing definitions are set to their default value.
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_STYLESHEET_FILE =
-# Set optional variables used in the generation of an rtf document.
-# Syntax is similar to doxygen's config file.
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
-# configuration options related to the man page output
+# Configuration options related to the man page output
#---------------------------------------------------------------------------
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
-# generate man pages
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
GENERATE_MAN = @do_man@
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `man' will be used as the default path.
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_OUTPUT = man
-# The MAN_EXTENSION tag determines the extension that is added to
-# the generated man pages (default is the subroutine's section .3)
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_EXTENSION = .3
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
-# would be unable to find the correct page. The default is NO.
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_LINKS = NO
#---------------------------------------------------------------------------
-# configuration options related to the XML output
+# Configuration options related to the XML output
#---------------------------------------------------------------------------
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
-# the code including all documentation.
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
GENERATE_XML = @do_xml@
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `xml' will be used as the default path.
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
XML_OUTPUT = xml
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
+# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
XML_SCHEMA =
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
+# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
XML_DTD =
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
-# enabling this will significantly increase the size of the XML output.
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
XML_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
-# and incomplete at the moment.
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
+# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
GENERATE_PERLMOD = NO
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
-# to generate PDF and DVI output from the Perl module output.
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_LATEX = NO
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader.
-# This is useful
-# if you want to understand what is going on.
-# On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
-# and Perl will parse it just the same.
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_PRETTY = YES
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
-# Makefile don't overwrite each other's variables.
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_MAKEVAR_PREFIX =
@@ -1714,50 +2054,58 @@ PERLMOD_MAKEVAR_PREFIX =
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
-# files.
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
ENABLE_PREPROCESSING = YES
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
-# way by setting EXPAND_ONLY_PREDEF to YES.
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
MACRO_EXPANSION = YES
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
-# PREDEFINED and EXPAND_AS_DEFINED tags.
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_ONLY_PREDEF = NO
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# pointed to by INCLUDE_PATH will be searched when a #include is found.
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
-# the preprocessor.
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH = include
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
-# be used.
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
INCLUDE_FILE_PATTERNS =
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
-# instead of the = operator.
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = __cplusplus=201103L \
__GTHREADS \
@@ -1802,59 +2150,73 @@ PREDEFINED = __cplusplus=201103L \
__glibcxx_class_requires3=// \
__glibcxx_class_requires4=//
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition that
-# overrules the definition found in the source code.
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED =
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all references to function-like macros
-# that are alone on a line, have an all uppercase name, and do not end with a
-# semicolon, because these will confuse the parser if not removed.
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all refrences to function-like macros that are alone on a line, have an
+# all uppercase name, and do not end with a semicolon. Such function macros are
+# typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
-# Configuration::additions related to external references
+# Configuration options related to external references
#---------------------------------------------------------------------------
-# The TAGFILES option can be used to specify one or more tagfiles. For each
-# tag file the location of the external documentation should be added. The
-# format of a tag file without this location is as follows:
-#
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
-#
# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths
-# or URLs. Note that each tag file must have a unique name (where the name does
-# NOT include the path). If a tag file is not located in the directory in which
-# doxygen is run, you must also specify the path to the tagfile here.
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have an unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
TAGFILES =
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
-# a tag file that is based on the input files it reads.
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
GENERATE_TAGFILE = @generate_tagfile@
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
-# will be listed.
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
ALLEXTERNALS = YES
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
-# be listed.
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
EXTERNAL_GROUPS = YES
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of `which perl').
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
PERL_PATH = /usr/bin/perl
@@ -1862,222 +2224,293 @@ PERL_PATH = /usr/bin/perl
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option also works with HAVE_DOT disabled, but it is recommended to
-# install and use dot, since it yields more powerful graphs.
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
CLASS_DIAGRAMS = YES
# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see
-# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
MSCGEN_PATH =
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
-# or is not a class.
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
HIDE_UNDOC_RELATIONS = NO
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
-# have no effect if this option is set to NO (the default)
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
HAVE_DOT = YES
-# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
-# allowed to run in parallel. When set to 0 (the default) doxygen will
-# base this on the number of processors available in the system. You can set it
-# explicitly to a value larger than 0 to get control over the balance
-# between CPU load and processing speed.
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NUM_THREADS = 0
-# By default doxygen will use the Helvetica font for all dot files that
-# doxygen generates. When you want a differently looking font you can specify
-# the font name using DOT_FONTNAME. You need to make sure dot is able to find
-# the font, which can be done by putting it in a standard location or by setting
-# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
-# directory containing the font.
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTNAME = FreeSans
-# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
-# The default size is 10pt.
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTSIZE = 9
-# By default doxygen will tell dot to use the Helvetica font.
-# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
-# set the path where dot can find it.
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
-# CLASS_DIAGRAMS tag to NO.
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
-# class references variables) of the class with other documented classes.
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
COLLABORATION_GRAPH = NO
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for groups, showing the direct groups dependencies
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
GROUP_GRAPHS = YES
# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
UML_LOOK = NO
-# If the UML_LOOK tag is enabled, the fields and methods are shown inside
-# the class node. If there are many fields or methods and many nodes the
-# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
-# threshold limits the number of items for each type to make the size more
-# managable. Set this to 0 for no limit. Note that the threshold may be
-# exceeded by 50% before the limit is enforced.
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
UML_LIMIT_NUM_FIELDS = 10
-# If set to YES, the inheritance and collaboration graphs will show the
-# relations between templates and their instances.
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
TEMPLATE_RELATIONS = NO
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
-# other documented files.
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDE_GRAPH = NO
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
-# indirectly include this file.
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDED_BY_GRAPH = NO
-# If the CALL_GRAPH and HAVE_DOT options are set to YES then
-# doxygen will generate a call dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable call graphs
-# for selected functions only using the \callgraph command.
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
CALL_GRAPH = NO
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
-# doxygen will generate a caller dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable caller
-# graphs for selected functions only using the \callergraph command.
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
CALLER_GRAPH = NO
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will generate a graphical hierarchy of all classes instead of a textual one.
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
GRAPHICAL_HIERARCHY = YES
-# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
-# in a graphical way. The dependency relations are determined by the #include
-# relations between the files in the directories.
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
DIRECTORY_GRAPH = NO
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are svg, png, jpg, or gif.
-# If left blank png will be used. If you choose svg you need to set
-# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
-# visible in IE 9+ (other browsers do not have this requirement).
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_IMAGE_FORMAT = svg
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
-# Note that this requires a modern browser other than Internet Explorer.
-# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
-# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
-# visible. Older versions of IE do not have SVG support.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
INTERACTIVE_SVG = YES
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
-# \dotfile command).
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
-# contain msc files that are included in the documentation (see the
-# \mscfile command).
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
MSCFILE_DIRS =
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
-# nodes that will be shown in the graph. If the number of nodes in a graph
-# becomes larger than this value, doxygen will truncate the graph, which is
-# visualized by representing a node as a red box. Note that doxygen if the
-# number of direct children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
-# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_GRAPH_MAX_NODES = 50
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
-# graphs generated by dot. A depth value of 3 means that only nodes reachable
-# from the root by following a path via at most 3 edges will be shown. Nodes
-# that lay further from the root node will be omitted. Note that setting this
-# option to 1 or 2 may greatly reduce the computation time needed for large
-# code bases. Also note that the size of a graph can be further restricted by
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not
-# seem to support this out of the box. Warning: Depending on the platform used,
-# enabling this option may lead to badly anti-aliased labels on the edges of
-# a graph (i.e. they become hard to read).
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
-# support this, this feature is disabled by default.
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_MULTI_TARGETS = YES
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
-# arrows in the dot generated graphs.
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
-# the various graphs.
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES
diff --git a/libstdc++-v3/doc/html/faq.html b/libstdc++-v3/doc/html/faq.html
index 2e0f3e252c9..81b295f036f 100644
--- a/libstdc++-v3/doc/html/faq.html
+++ b/libstdc++-v3/doc/html/faq.html
@@ -223,7 +223,7 @@
</p></td></tr><tr class="question"><td align="left" valign="top"><a id="faq.license.what_restrictions"></a><a id="q-license.what_restrictions"></a><p><strong>2.4.</strong></p></td><td align="left" valign="top"><p>
I see. So, what restrictions are there on programs that use the library?
</p></td></tr><tr class="answer"><td align="left" valign="top"><a id="a-license.what_restrictions"></a></td><td align="left" valign="top"><p>
- None. We encourage such programs to be released as open source,
+ None. We encourage such programs to be released as free software,
but we won't punish you or sue you if you choose otherwise.
</p></td></tr><tr class="toc"><td align="left" valign="top" colspan="2"><dl><dt>3.1. <a href="faq.html#faq.how_to_install">How do I install libstdc++?
</a></dt><dt>3.2. <a href="faq.html#faq.how_to_get_sources">How does one get current libstdc++ sources?
diff --git a/libstdc++-v3/doc/xml/faq.xml b/libstdc++-v3/doc/xml/faq.xml
index 3a2fbad8ed6..69e2f902200 100644
--- a/libstdc++-v3/doc/xml/faq.xml
+++ b/libstdc++-v3/doc/xml/faq.xml
@@ -241,7 +241,7 @@
</question>
<answer xml:id="a-license.what_restrictions">
<para>
- None. We encourage such programs to be released as open source,
+ None. We encourage such programs to be released as free software,
but we won't punish you or sue you if you choose otherwise.
</para>
</answer>
diff --git a/libstdc++-v3/doc/xml/manual/appendix_contributing.xml b/libstdc++-v3/doc/xml/manual/appendix_contributing.xml
index bd7dfc7064a..2c3b9fb3f1c 100644
--- a/libstdc++-v3/doc/xml/manual/appendix_contributing.xml
+++ b/libstdc++-v3/doc/xml/manual/appendix_contributing.xml
@@ -110,12 +110,14 @@
</para>
<para>
- Please contact Benjamin Kosnik at
- <email>bkoz+assign@redhat.com</email> if you are confused
- about the assignment or have general licensing questions. When
- requesting an assignment form from
- <email>mailto:assign@gnu.org</email>, please cc the libstdc++
- maintainer above so that progress can be monitored.
+ Please contact
+ Paolo Carlini at <email>paolo.carlini@oracle.com</email>
+ or
+ Jonathan Wakely at <email>jwakely+assign@redhat.com</email>
+ if you are confused about the assignment or have general licensing
+ questions. When requesting an assignment form from
+ <email>assign@gnu.org</email>, please CC the libstdc++
+ maintainers above so that progress can be monitored.
</para>
</section>
diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2011.xml b/libstdc++-v3/doc/xml/manual/status_cxx2011.xml
index b3c24d888c7..cad41112505 100644
--- a/libstdc++-v3/doc/xml/manual/status_cxx2011.xml
+++ b/libstdc++-v3/doc/xml/manual/status_cxx2011.xml
@@ -871,11 +871,10 @@ particular release.
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#B0B0B0" ?>
<entry>20.9.7.6</entry>
<entry>Other transformations</entry>
- <entry>Partial</entry>
- <entry>Missing <code>aligned_union</code>.</entry>
+ <entry>Y</entry>
+ <entry/>
</row>
<row>
<entry>20.10</entry>
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 0d676dbdf39..a079ff6af0b 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -816,6 +816,7 @@ profile_headers = \
${profile_srcdir}/map.h \
${profile_srcdir}/multimap.h \
${profile_srcdir}/multiset.h \
+ ${profile_srcdir}/ordered_base.h \
${profile_srcdir}/set \
${profile_srcdir}/set.h \
${profile_srcdir}/iterator_tracker.h
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index be525f77b3e..502f04e0490 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -1079,6 +1079,7 @@ profile_headers = \
${profile_srcdir}/map.h \
${profile_srcdir}/multimap.h \
${profile_srcdir}/multiset.h \
+ ${profile_srcdir}/ordered_base.h \
${profile_srcdir}/set \
${profile_srcdir}/set.h \
${profile_srcdir}/iterator_tracker.h
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index 22e17d29d7b..9b6394c4e49 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -316,14 +316,49 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
size_type _M_element_count;
_RehashPolicy _M_rehash_policy;
+ // A single bucket used when only need for 1 bucket. Especially
+ // interesting in move semantic to leave hashtable with only 1 buckets
+ // which is not allocated so that we can have those operations noexcept
+ // qualified.
+ // Note that we can't leave hashtable with 0 bucket without adding
+ // numerous checks in the code to avoid 0 modulus.
+ __bucket_type _M_single_bucket;
+
+ bool
+ _M_uses_single_bucket(__bucket_type* __bkts) const
+ { return __builtin_expect(_M_buckets == &_M_single_bucket, false); }
+
+ bool
+ _M_uses_single_bucket() const
+ { return _M_uses_single_bucket(_M_buckets); }
+
__hashtable_alloc&
_M_base_alloc() { return *this; }
- using __hashtable_alloc::_M_deallocate_buckets;
+ __bucket_type*
+ _M_allocate_buckets(size_type __n)
+ {
+ if (__builtin_expect(__n == 1, false))
+ {
+ _M_single_bucket = nullptr;
+ return &_M_single_bucket;
+ }
+
+ return __hashtable_alloc::_M_allocate_buckets(__n);
+ }
+
+ void
+ _M_deallocate_buckets(__bucket_type* __bkts, size_type __n)
+ {
+ if (_M_uses_single_bucket(__bkts))
+ return;
+
+ __hashtable_alloc::_M_deallocate_buckets(__bkts, __n);
+ }
void
_M_deallocate_buckets()
- { this->_M_deallocate_buckets(_M_buckets, _M_bucket_count); }
+ { _M_deallocate_buckets(_M_buckets, _M_bucket_count); }
// Gets bucket begin, deals with the fact that non-empty buckets contain
// their before begin node.
@@ -703,11 +738,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
size_type
erase(const key_type& __k)
- {
- if (__builtin_expect(_M_bucket_count == 0, false))
- return 0;
- return _M_erase(__unique_keys(), __k);
- }
+ { return _M_erase(__unique_keys(), __k); }
iterator
erase(const_iterator, const_iterator);
@@ -768,7 +799,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_rehash_policy()
{
_M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
- _M_buckets = this->_M_allocate_buckets(_M_bucket_count);
+ _M_buckets = _M_allocate_buckets(_M_bucket_count);
}
template<typename _Key, typename _Value,
@@ -796,7 +827,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems),
__bucket_hint));
- _M_buckets = this->_M_allocate_buckets(_M_bucket_count);
+ _M_buckets = _M_allocate_buckets(_M_bucket_count);
__try
{
for (; __f != __l; ++__f)
@@ -833,9 +864,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
// Replacement allocator cannot free existing storage.
this->_M_deallocate_nodes(_M_begin());
- if (__builtin_expect(_M_bucket_count != 0, true))
- _M_deallocate_buckets();
- _M_reset();
+ _M_before_begin._M_nxt = nullptr;
+ _M_deallocate_buckets();
+ _M_buckets = nullptr;
std::__alloc_on_copy(__this_alloc, __that_alloc);
__hashtable_base::operator=(__ht);
_M_bucket_count = __ht._M_bucket_count;
@@ -867,7 +898,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (_M_bucket_count != __ht._M_bucket_count)
{
__former_buckets = _M_buckets;
- _M_buckets = this->_M_allocate_buckets(__ht._M_bucket_count);
+ _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
_M_bucket_count = __ht._M_bucket_count;
}
else
@@ -885,8 +916,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[&__roan](const __node_type* __n)
{ return __roan(__n->_M_v()); });
if (__former_buckets)
- this->_M_deallocate_buckets(__former_buckets,
- __former_bucket_count);
+ _M_deallocate_buckets(__former_buckets, __former_bucket_count);
}
__catch(...)
{
@@ -917,7 +947,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
__bucket_type* __buckets = nullptr;
if (!_M_buckets)
- _M_buckets = __buckets = this->_M_allocate_buckets(_M_bucket_count);
+ _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count);
__try
{
@@ -964,8 +994,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_reset() noexcept
{
_M_rehash_policy._M_reset();
- _M_bucket_count = 0;
- _M_buckets = nullptr;
+ _M_bucket_count = 1;
+ _M_single_bucket = nullptr;
+ _M_buckets = &_M_single_bucket;
_M_before_begin._M_nxt = nullptr;
_M_element_count = 0;
}
@@ -980,12 +1011,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_move_assign(_Hashtable&& __ht, std::true_type)
{
this->_M_deallocate_nodes(_M_begin());
- if (__builtin_expect(_M_bucket_count != 0, true))
- _M_deallocate_buckets();
-
+ _M_deallocate_buckets();
__hashtable_base::operator=(std::move(__ht));
_M_rehash_policy = __ht._M_rehash_policy;
- _M_buckets = __ht._M_buckets;
+ if (!__ht._M_uses_single_bucket())
+ _M_buckets = __ht._M_buckets;
+ else
+ {
+ _M_buckets = &_M_single_bucket;
+ _M_single_bucket = __ht._M_single_bucket;
+ }
_M_bucket_count = __ht._M_bucket_count;
_M_before_begin._M_nxt = __ht._M_before_begin._M_nxt;
_M_element_count = __ht._M_element_count;
@@ -1019,7 +1054,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (_M_bucket_count != __ht._M_bucket_count)
{
__former_buckets = _M_buckets;
- _M_buckets = this->_M_allocate_buckets(__ht._M_bucket_count);
+ _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
_M_bucket_count = __ht._M_bucket_count;
}
else
@@ -1093,10 +1128,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_element_count(__ht._M_element_count),
_M_rehash_policy(__ht._M_rehash_policy)
{
+ // Update, if necessary, buckets if __ht is using its single bucket.
+ if (__ht._M_uses_single_bucket())
+ {
+ _M_buckets = &_M_single_bucket;
+ _M_single_bucket = __ht._M_single_bucket;
+ }
+
// Update, if necessary, bucket pointing to before begin that hasn't
// moved.
if (_M_begin())
_M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
+
__ht._M_reset();
}
@@ -1139,7 +1182,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (__ht._M_node_allocator() == this->_M_node_allocator())
{
- _M_buckets = __ht._M_buckets;
+ if (__ht._M_uses_single_bucket())
+ {
+ _M_buckets = &_M_single_bucket;
+ _M_single_bucket = __ht._M_single_bucket;
+ }
+ else
+ _M_buckets = __ht._M_buckets;
+
_M_before_begin._M_nxt = __ht._M_before_begin._M_nxt;
// Update, if necessary, bucket pointing to before begin that hasn't
// moved.
@@ -1189,15 +1239,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::__alloc_on_swap(this->_M_node_allocator(), __x._M_node_allocator());
std::swap(_M_rehash_policy, __x._M_rehash_policy);
- std::swap(_M_buckets, __x._M_buckets);
+
+ // Deal properly with potentially moved instances.
+ if (this->_M_uses_single_bucket())
+ {
+ if (!__x._M_uses_single_bucket())
+ {
+ _M_buckets = __x._M_buckets;
+ __x._M_buckets = &__x._M_single_bucket;
+ }
+ }
+ else if (__x._M_uses_single_bucket())
+ {
+ __x._M_buckets = _M_buckets;
+ _M_buckets = &_M_single_bucket;
+ }
+ else
+ std::swap(_M_buckets, __x._M_buckets);
+
std::swap(_M_bucket_count, __x._M_bucket_count);
std::swap(_M_before_begin._M_nxt, __x._M_before_begin._M_nxt);
std::swap(_M_element_count, __x._M_element_count);
+ std::swap(_M_single_bucket, __x._M_single_bucket);
// Fix buckets containing the _M_before_begin pointers that can't be
// swapped.
if (_M_begin())
_M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
+
if (__x._M_begin())
__x._M_buckets[__x._M_bucket_index(__x._M_begin())]
= &__x._M_before_begin;
@@ -1230,9 +1299,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
find(const key_type& __k)
{
- if (__builtin_expect(_M_bucket_count == 0, false))
- return end();
-
__hash_code __code = this->_M_hash_code(__k);
std::size_t __n = _M_bucket_index(__k, __code);
__node_type* __p = _M_find_node(__n, __k, __code);
@@ -1250,9 +1316,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
find(const key_type& __k) const
{
- if (__builtin_expect(_M_bucket_count == 0, false))
- return end();
-
__hash_code __code = this->_M_hash_code(__k);
std::size_t __n = _M_bucket_index(__k, __code);
__node_type* __p = _M_find_node(__n, __k, __code);
@@ -1270,9 +1333,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
count(const key_type& __k) const
{
- if (__builtin_expect(_M_bucket_count == 0, false))
- return 0;
-
__hash_code __code = this->_M_hash_code(__k);
std::size_t __n = _M_bucket_index(__k, __code);
__node_type* __p = _M_bucket_begin(__n);
@@ -1287,7 +1347,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
else if (__result)
// All equivalent values are next to each other, if we
// found a non-equivalent value after an equivalent one it
- // means that we won't find any more equivalent values.
+ // means that we won't find any new equivalent value.
break;
if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
break;
@@ -1311,9 +1371,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
equal_range(const key_type& __k)
{
- if (__builtin_expect(_M_bucket_count == 0, false))
- return std::make_pair(end(), end());
-
__hash_code __code = this->_M_hash_code(__k);
std::size_t __n = _M_bucket_index(__k, __code);
__node_type* __p = _M_find_node(__n, __k, __code);
@@ -1347,9 +1404,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
equal_range(const key_type& __k) const
{
- if (__builtin_expect(_M_bucket_count == 0, false))
- return std::make_pair(end(), end());
-
__hash_code __code = this->_M_hash_code(__k);
std::size_t __n = _M_bucket_index(__k, __code);
__node_type* __p = _M_find_node(__n, __k, __code);
@@ -1944,7 +1998,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
_M_rehash_aux(size_type __n, std::true_type)
{
- __bucket_type* __new_buckets = this->_M_allocate_buckets(__n);
+ __bucket_type* __new_buckets = _M_allocate_buckets(__n);
__node_type* __p = _M_begin();
_M_before_begin._M_nxt = nullptr;
std::size_t __bbegin_bkt = 0;
@@ -1969,8 +2023,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__p = __next;
}
- if (__builtin_expect(_M_bucket_count != 0, true))
- _M_deallocate_buckets();
+ _M_deallocate_buckets();
_M_bucket_count = __n;
_M_buckets = __new_buckets;
}
@@ -1986,7 +2039,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
_M_rehash_aux(size_type __n, std::false_type)
{
- __bucket_type* __new_buckets = this->_M_allocate_buckets(__n);
+ __bucket_type* __new_buckets = _M_allocate_buckets(__n);
__node_type* __p = _M_begin();
_M_before_begin._M_nxt = nullptr;
@@ -2060,8 +2113,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__new_buckets[__next_bkt] = __prev_p;
}
- if (__builtin_expect(_M_bucket_count != 0, true))
- _M_deallocate_buckets();
+ _M_deallocate_buckets();
_M_bucket_count = __n;
_M_buckets = __new_buckets;
}
diff --git a/libstdc++-v3/include/bits/ios_base.h b/libstdc++-v3/include/bits/ios_base.h
index ae856de7b45..59c506696f5 100644
--- a/libstdc++-v3/include/bits/ios_base.h
+++ b/libstdc++-v3/include/bits/ios_base.h
@@ -780,6 +780,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
protected:
ios_base() throw ();
+#if __cplusplus < 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 50. Copy constructor and assignment operator of ios_base
private:
@@ -787,6 +788,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
ios_base&
operator=(const ios_base&);
+#else
+ public:
+ ios_base(const ios_base&) = delete;
+
+ ios_base&
+ operator=(const ios_base&) = delete;
+#endif
};
// [27.4.5.1] fmtflags manipulators
diff --git a/libstdc++-v3/include/bits/parse_numbers.h b/libstdc++-v3/include/bits/parse_numbers.h
index 91a127c4ebe..a29d1272255 100644
--- a/libstdc++-v3/include/bits/parse_numbers.h
+++ b/libstdc++-v3/include/bits/parse_numbers.h
@@ -27,8 +27,8 @@
* Do not attempt to use it directly. @headername{chrono}
*/
-#ifndef _PARSE_NUMBERS_H
-#define _PARSE_NUMBERS_H 1
+#ifndef _GLIBCXX_PARSE_NUMBERS_H
+#define _GLIBCXX_PARSE_NUMBERS_H 1
#pragma GCC system_header
@@ -36,289 +36,182 @@
#if __cplusplus > 201103L
+#include <limits>
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
-namespace __parse_int {
-
+namespace __parse_int
+{
template<unsigned _Base, char _Dig>
struct _Digit;
template<unsigned _Base>
- struct _Digit<_Base, '0'>
+ struct _Digit<_Base, '0'> : integral_constant<unsigned, 0>
{
- static constexpr bool valid{true};
- static constexpr unsigned value{0};
+ using __valid = true_type;
};
template<unsigned _Base>
- struct _Digit<_Base, '1'>
+ struct _Digit<_Base, '1'> : integral_constant<unsigned, 1>
{
- static constexpr bool valid{true};
- static constexpr unsigned value{1};
+ using __valid = true_type;
};
- template<unsigned _Base>
- struct _Digit<_Base, '2'>
+ template<unsigned _Base, unsigned _Val>
+ struct _Digit_impl : integral_constant<unsigned, _Val>
{
- static_assert(_Base > 2, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{2};
+ static_assert(_Base > _Val, "invalid digit");
+ using __valid = true_type;
};
template<unsigned _Base>
- struct _Digit<_Base, '3'>
- {
- static_assert(_Base > 3, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{3};
- };
+ struct _Digit<_Base, '2'> : _Digit_impl<_Base, 2>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, '4'>
- {
- static_assert(_Base > 4, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{4};
- };
+ struct _Digit<_Base, '3'> : _Digit_impl<_Base, 3>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, '5'>
- {
- static_assert(_Base > 5, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{5};
- };
+ struct _Digit<_Base, '4'> : _Digit_impl<_Base, 4>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, '6'>
- {
- static_assert(_Base > 6, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{6};
- };
+ struct _Digit<_Base, '5'> : _Digit_impl<_Base, 5>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, '7'>
- {
- static_assert(_Base > 7, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{7};
- };
+ struct _Digit<_Base, '6'> : _Digit_impl<_Base, 6>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, '8'>
- {
- static_assert(_Base > 8, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{8};
- };
+ struct _Digit<_Base, '7'> : _Digit_impl<_Base, 7>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, '9'>
- {
- static_assert(_Base > 9, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{9};
- };
+ struct _Digit<_Base, '8'> : _Digit_impl<_Base, 8>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, 'a'>
- {
- static_assert(_Base > 0xa, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{0xa};
- };
+ struct _Digit<_Base, '9'> : _Digit_impl<_Base, 9>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, 'A'>
- {
- static_assert(_Base > 0xa, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{0xa};
- };
+ struct _Digit<_Base, 'a'> : _Digit_impl<_Base, 0xa>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, 'b'>
- {
- static_assert(_Base > 0xb, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{0xb};
- };
+ struct _Digit<_Base, 'A'> : _Digit_impl<_Base, 0xa>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, 'B'>
- {
- static_assert(_Base > 0xb, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{0xb};
- };
+ struct _Digit<_Base, 'b'> : _Digit_impl<_Base, 0xb>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, 'c'>
- {
- static_assert(_Base > 0xc, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{0xc};
- };
+ struct _Digit<_Base, 'B'> : _Digit_impl<_Base, 0xb>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, 'C'>
- {
- static_assert(_Base > 0xc, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{0xc};
- };
+ struct _Digit<_Base, 'c'> : _Digit_impl<_Base, 0xc>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, 'd'>
- {
- static_assert(_Base > 0xd, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{0xd};
- };
+ struct _Digit<_Base, 'C'> : _Digit_impl<_Base, 0xc>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, 'D'>
- {
- static_assert(_Base > 0xd, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{0xd};
- };
+ struct _Digit<_Base, 'd'> : _Digit_impl<_Base, 0xd>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, 'e'>
- {
- static_assert(_Base > 0xe, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{0xe};
- };
+ struct _Digit<_Base, 'D'> : _Digit_impl<_Base, 0xd>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, 'E'>
- {
- static_assert(_Base > 0xe, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{0xe};
- };
+ struct _Digit<_Base, 'e'> : _Digit_impl<_Base, 0xe>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, 'f'>
- {
- static_assert(_Base > 0xf, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{0xf};
- };
+ struct _Digit<_Base, 'E'> : _Digit_impl<_Base, 0xe>
+ { };
template<unsigned _Base>
- struct _Digit<_Base, 'F'>
- {
- static_assert(_Base > 0xf, "invalid digit");
- static constexpr bool valid{true};
- static constexpr unsigned value{0xf};
- };
+ struct _Digit<_Base, 'f'> : _Digit_impl<_Base, 0xf>
+ { };
- // Digit separator
template<unsigned _Base>
- struct _Digit<_Base, '\''>
- {
- static constexpr bool valid{false};
- static constexpr unsigned value{0};
- };
-
-
-//------------------------------------------------------------------------------
-
- template<unsigned _Base, char _Dig, char... _Digs>
- struct _Digits_help
- {
- static constexpr unsigned
- value{_Digit<_Base, _Dig>::valid ?
- 1U + _Digits_help<_Base, _Digs...>::value :
- _Digits_help<_Base, _Digs...>::value};
- };
-
- template<unsigned _Base, char _Dig>
- struct _Digits_help<_Base, _Dig>
- {
- static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U};
- };
-
- template<unsigned _Base, char... _Digs>
- struct _Digits
- {
- static constexpr unsigned value{_Digits_help<_Base, _Digs...>::value};
- };
+ struct _Digit<_Base, 'F'> : _Digit_impl<_Base, 0xf>
+ { };
+ // Digit separator
template<unsigned _Base>
- struct _Digits<_Base>
+ struct _Digit<_Base, '\''> : integral_constant<unsigned, 0>
{
- static constexpr unsigned value{0U};
+ using __valid = false_type;
};
//------------------------------------------------------------------------------
+ template<unsigned long long _Val>
+ using __ull_constant = integral_constant<unsigned long long, _Val>;
+
template<unsigned _Base, char _Dig, char... _Digs>
struct _Power_help
{
- static constexpr unsigned
- value{_Digit<_Base, _Dig>::valid ?
- _Base * _Power_help<_Base, _Digs...>::value :
- _Power_help<_Base, _Digs...>::value};
+ using __next = typename _Power_help<_Base, _Digs...>::type;
+ using __valid_digit = typename _Digit<_Base, _Dig>::__valid;
+ using type
+ = __ull_constant<__next::value * (__valid_digit{} ? _Base : 1ULL)>;
};
template<unsigned _Base, char _Dig>
struct _Power_help<_Base, _Dig>
{
- static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U};
+ using __valid_digit = typename _Digit<_Base, _Dig>::__valid;
+ using type = __ull_constant<__valid_digit::value>;
};
template<unsigned _Base, char... _Digs>
- struct _Power
- {
- static constexpr unsigned value{_Power_help<_Base, _Digs...>::value};
- };
+ struct _Power : _Power_help<_Base, _Digs...>::type
+ { };
template<unsigned _Base>
- struct _Power<_Base>
- {
- static constexpr unsigned value{0U};
- };
+ struct _Power<_Base> : __ull_constant<0>
+ { };
//------------------------------------------------------------------------------
- template<unsigned _Base, unsigned _Pow, char _Dig, char... _Digs>
+ template<unsigned _Base, unsigned long long _Pow, char _Dig, char... _Digs>
struct _Number_help
{
- static constexpr unsigned
- value{_Digit<_Base, _Dig>::valid ?
- _Pow * _Digit<_Base, _Dig>::value
- + _Number_help<_Base, _Pow / _Base, _Digs...>::value :
- _Number_help<_Base, _Pow, _Digs...>::value};
+ using __digit = _Digit<_Base, _Dig>;
+ using __valid_digit = typename __digit::__valid;
+ using __next = _Number_help<_Base,
+ _Pow / (_Base * __valid_digit::value),
+ _Digs...>;
+ using type = __ull_constant<_Pow * __digit::value + __next::type::value>;
+ static_assert((type::value / _Pow) == __digit::value, "overflow");
};
- template<unsigned _Base, unsigned _Pow, char _Dig>
+ template<unsigned _Base, unsigned long long _Pow, char _Dig>
struct _Number_help<_Base, _Pow, _Dig>
{
//static_assert(_Pow == 1U, "power should be one");
- static constexpr unsigned
- value{_Digit<_Base, _Dig>::valid ? _Digit<_Base, _Dig>::value : 0U};
+ using type = __ull_constant<_Digit<_Base, _Dig>::value>;
};
template<unsigned _Base, char... _Digs>
struct _Number
- {
- static constexpr unsigned
- value{_Number_help<_Base, _Power<_Base, _Digs...>::value,
- _Digs...>::value};
- };
+ : _Number_help<_Base, _Power<_Base, _Digs...>::value, _Digs...>::type
+ { };
template<unsigned _Base>
struct _Number<_Base>
- {
- static constexpr unsigned value{0U};
- };
+ : __ull_constant<0>
+ { };
//------------------------------------------------------------------------------
// This _Parse_int is the same 'level' as the old _Base_dispatch.
@@ -328,84 +221,62 @@ namespace __parse_int {
template<char... _Digs>
struct _Parse_int<'0', 'b', _Digs...>
- {
- static constexpr unsigned long long
- value{_Number<2U, _Digs...>::value};
- };
+ : _Number<2U, _Digs...>::type
+ { };
template<char... _Digs>
struct _Parse_int<'0', 'B', _Digs...>
- {
- static constexpr unsigned long long
- value{_Number<2U, _Digs...>::value};
- };
+ : _Number<2U, _Digs...>::type
+ { };
template<char... _Digs>
struct _Parse_int<'0', 'x', _Digs...>
- {
- static constexpr unsigned long long
- value{_Number<16U, _Digs...>::value};
- };
+ : _Number<16U, _Digs...>::type
+ { };
template<char... _Digs>
struct _Parse_int<'0', 'X', _Digs...>
- {
- static constexpr unsigned long long
- value{_Number<16U, _Digs...>::value};
- };
+ : _Number<16U, _Digs...>::type
+ { };
template<char... _Digs>
struct _Parse_int<'0', _Digs...>
- {
- static constexpr unsigned long long
- value{_Number<8U, _Digs...>::value};
- };
+ : _Number<8U, _Digs...>::type
+ { };
template<char... _Digs>
struct _Parse_int
- {
- static constexpr unsigned long long
- value{_Number<10U, _Digs...>::value};
- };
+ : _Number<10U, _Digs...>::type
+ { };
} // namespace __parse_int
-namespace __select_int {
-
+namespace __select_int
+{
template<unsigned long long _Val, typename... _Ints>
struct _Select_int_base;
template<unsigned long long _Val, typename _IntType, typename... _Ints>
struct _Select_int_base<_Val, _IntType, _Ints...>
- : integral_constant
- <
- typename conditional
- <
- _Val <= static_cast<unsigned long long>
- (std::numeric_limits<_IntType>::max()),
- _IntType,
- typename _Select_int_base<_Val, _Ints...>::value_type
- >::type,
- _Val
- >
+ : conditional_t<(_Val <= std::numeric_limits<_IntType>::max()),
+ integral_constant<_IntType, _Val>,
+ _Select_int_base<_Val, _Ints...>>
{ };
template<unsigned long long _Val>
- struct _Select_int_base<_Val> : integral_constant<unsigned long long, _Val>
+ struct _Select_int_base<_Val>
{ };
template<char... _Digs>
- struct _Select_int
- : _Select_int_base<
+ using _Select_int = typename _Select_int_base<
__parse_int::_Parse_int<_Digs...>::value,
unsigned char,
unsigned short,
unsigned int,
unsigned long,
unsigned long long
- >
- { };
+ >::type;
} // namespace __select_int
@@ -414,4 +285,4 @@ _GLIBCXX_END_NAMESPACE_VERSION
#endif // __cplusplus > 201103L
-#endif // _PARSE_NUMBERS_H
+#endif // _GLIBCXX_PARSE_NUMBERS_H
diff --git a/libstdc++-v3/include/bits/regex.tcc b/libstdc++-v3/include/bits/regex.tcc
index 0d737a0b74b..a81f51750dc 100644
--- a/libstdc++-v3/include/bits/regex.tcc
+++ b/libstdc++-v3/include/bits/regex.tcc
@@ -32,7 +32,7 @@
// If _GLIBCXX_REGEX_USE_THOMPSON_NFA is defined, the thompson NFA
// algorithm will be used. This algorithm is not enabled by default,
// and cannot be used if the regex contains back-references, but has better
-// (polynomial instead of exponential) worst case performace.
+// (polynomial instead of exponential) worst case performance.
// See __regex_algo_impl below.
namespace std _GLIBCXX_VISIBILITY(default)
diff --git a/libstdc++-v3/include/bits/regex_automaton.tcc b/libstdc++-v3/include/bits/regex_automaton.tcc
index e0ac3f94ceb..1c6cfdd1b9f 100644
--- a/libstdc++-v3/include/bits/regex_automaton.tcc
+++ b/libstdc++-v3/include/bits/regex_automaton.tcc
@@ -35,7 +35,7 @@ namespace __detail
_GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef _GLIBCXX_DEBUG
- std::ostream&
+ inline std::ostream&
_State_base::_M_print(std::ostream& ostr) const
{
switch (_M_opcode)
@@ -67,7 +67,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
// Prints graphviz dot commands for state.
- std::ostream&
+ inline std::ostream&
_State_base::_M_dot(std::ostream& __ostr, _StateIdT __id) const
{
switch (_M_opcode)
diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h
index d7e21624e37..ca116de53af 100644
--- a/libstdc++-v3/include/bits/regex_compiler.h
+++ b/libstdc++-v3/include/bits/regex_compiler.h
@@ -43,7 +43,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct _BracketMatcher;
/**
- * @brief Builds an NFA from an input iterator interval.
+ * @brief Builds an NFA from an input iterator range.
*
* The %_TraitsT type should fulfill requirements [28.3].
*/
@@ -329,7 +329,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator()(_CharT __ch) const
{
_GLIBCXX_DEBUG_ASSERT(_M_is_ready);
- return _M_apply(__ch, _IsChar());
+ return _M_apply(__ch, _UseCache());
}
void
@@ -369,15 +369,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
}
+ // __neg should be true for \D, \S and \W only.
void
- _M_add_character_class(const _StringT& __s)
+ _M_add_character_class(const _StringT& __s, bool __neg)
{
auto __mask = _M_traits.lookup_classname(__s.data(),
__s.data() + __s.size(),
__icase);
if (__mask == 0)
__throw_regex_error(regex_constants::error_ctype);
- _M_class_set |= __mask;
+ if (!__neg)
+ _M_class_set |= __mask;
+ else
+ _M_neg_class_set.push_back(__mask);
#ifdef _GLIBCXX_DEBUG
_M_is_ready = false;
#endif
@@ -387,7 +391,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_make_range(_CharT __l, _CharT __r)
{
_M_range_set.push_back(make_pair(_M_translator._M_transform(__l),
- _M_translator._M_transform(__r)));
+ _M_translator._M_transform(__r)));
#ifdef _GLIBCXX_DEBUG
_M_is_ready = false;
#endif
@@ -396,21 +400,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
_M_ready()
{
- _M_make_cache(_IsChar());
+ std::sort(_M_char_set.begin(), _M_char_set.end());
+ auto __end = std::unique(_M_char_set.begin(), _M_char_set.end());
+ _M_char_set.erase(__end, _M_char_set.end());
+ _M_make_cache(_UseCache());
#ifdef _GLIBCXX_DEBUG
_M_is_ready = true;
#endif
}
private:
- typedef typename is_same<_CharT, char>::type _IsChar;
+ // Currently we only use the cache for char
+ typedef typename std::is_same<_CharT, char>::type _UseCache;
+
+ static constexpr size_t
+ _S_cache_size() { return 1ul << (sizeof(_CharT) * __CHAR_BIT__); }
+
struct _Dummy { };
- typedef typename conditional<_IsChar::value,
- std::bitset<1 << (8 * sizeof(_CharT))>,
- _Dummy>::type _CacheT;
- typedef typename make_unsigned<_CharT>::type _UnsignedCharT;
+ typedef typename std::conditional<_UseCache::value,
+ std::bitset<_S_cache_size()>,
+ _Dummy>::type _CacheT;
+ typedef typename std::make_unsigned<_CharT>::type _UnsignedCharT;
- private:
bool
_M_apply(_CharT __ch, false_type) const;
@@ -421,9 +432,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
_M_make_cache(true_type)
{
- for (size_t __i = 0; __i < _M_cache.size(); __i++)
- _M_cache[static_cast<_UnsignedCharT>(__i)] =
- _M_apply(__i, false_type());
+ for (unsigned __i = 0; __i < _M_cache.size(); __i++)
+ _M_cache[__i] = _M_apply(static_cast<_CharT>(__i), false_type());
}
void
@@ -431,14 +441,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ }
private:
- _CacheT _M_cache;
std::vector<_CharT> _M_char_set;
std::vector<_StringT> _M_equiv_set;
std::vector<pair<_StrTransT, _StrTransT>> _M_range_set;
+ std::vector<_CharClassT> _M_neg_class_set;
_CharClassT _M_class_set;
_TransT _M_translator;
const _TraitsT& _M_traits;
bool _M_is_non_matching;
+ _CacheT _M_cache;
#ifdef _GLIBCXX_DEBUG
bool _M_is_ready;
#endif
diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc
index 3cf9e457ccd..0df10cc1a8b 100644
--- a/libstdc++-v3/include/bits/regex_compiler.tcc
+++ b/libstdc++-v3/include/bits/regex_compiler.tcc
@@ -37,9 +37,9 @@
// When compiling, states are *chained* instead of tree- or graph-constructed.
// It's more like structured programs: there's if statement and loop statement.
//
-// For alternative structure(say "a|b"), aka "if statement", two branchs should
-// be constructed. However, these two shall merge to an "end_tag" at the end of
-// this operator:
+// For alternative structure (say "a|b"), aka "if statement", two branches
+// should be constructed. However, these two shall merge to an "end_tag" at
+// the end of this operator:
//
// branch1
// / \
@@ -151,7 +151,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
else if (_M_match_token(_ScannerT::_S_token_line_end))
_M_stack.push(_StateSeqT(_M_nfa, _M_nfa._M_insert_line_end()));
else if (_M_match_token(_ScannerT::_S_token_word_bound))
- // _M_value[0] == 'n' means it's negtive, say "not word boundary".
+ // _M_value[0] == 'n' means it's negative, say "not word boundary".
_M_stack.push(_StateSeqT(_M_nfa, _M_nfa.
_M_insert_word_bound(_M_value[0] == 'n')));
else if (_M_match_token(_ScannerT::_S_token_subexpr_lookahead_begin))
@@ -256,7 +256,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
auto __end = _M_nfa._M_insert_dummy();
// _M_alt is the "match more" branch, and _M_next is the
// "match less" one. Switch _M_alt and _M_next of all created
- // nodes. This is a hacking but IMO works well.
+ // nodes. This is a hack but IMO works well.
std::stack<_StateIdT> __stack;
for (long __i = 0; __i < __n; ++__i)
{
@@ -397,7 +397,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_DEBUG_ASSERT(_M_value.size() == 1);
_BracketMatcher<_TraitsT, __icase, __collate> __matcher
(_M_ctype.is(_CtypeT::upper, _M_value[0]), _M_traits);
- __matcher._M_add_character_class(_M_value);
+ __matcher._M_add_character_class(_M_value, false);
__matcher._M_ready();
_M_stack.push(_StateSeqT(_M_nfa,
_M_nfa._M_insert_matcher(std::move(__matcher))));
@@ -428,7 +428,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
else if (_M_match_token(_ScannerT::_S_token_equiv_class_name))
__matcher._M_add_equivalence_class(_M_value);
else if (_M_match_token(_ScannerT::_S_token_char_class_name))
- __matcher._M_add_character_class(_M_value);
+ __matcher._M_add_character_class(_M_value, false);
else if (_M_try_char()) // [a
{
auto __ch = _M_value[0];
@@ -451,6 +451,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
__matcher._M_add_char(__ch);
}
+ else if (_M_match_token(_ScannerT::_S_token_quoted_class))
+ __matcher._M_add_character_class(_M_value,
+ _M_ctype.is(_CtypeT::upper,
+ _M_value[0]));
else
__throw_regex_error(regex_constants::error_brack);
}
@@ -507,12 +511,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_BracketMatcher<_TraitsT, __icase, __collate>::
_M_apply(_CharT __ch, false_type) const
{
- bool __ret = false;
- if (std::find(_M_char_set.begin(), _M_char_set.end(),
- _M_translator._M_translate(__ch))
- != _M_char_set.end())
- __ret = true;
- else
+ bool __ret = std::binary_search(_M_char_set.begin(), _M_char_set.end(),
+ _M_translator._M_translate(__ch));
+ if (!__ret)
{
auto __s = _M_translator._M_transform(__ch);
for (auto& __it : _M_range_set)
@@ -527,6 +528,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_traits.transform_primary(&__ch, &__ch+1))
!= _M_equiv_set.end())
__ret = true;
+ else
+ {
+ for (auto& __it : _M_neg_class_set)
+ if (!_M_traits.isctype(__ch, __it))
+ {
+ __ret = true;
+ break;
+ }
+ }
}
if (_M_is_non_matching)
return !__ret;
diff --git a/libstdc++-v3/include/bits/regex_executor.h b/libstdc++-v3/include/bits/regex_executor.h
index c110b88a3f4..1991c0007a1 100644
--- a/libstdc++-v3/include/bits/regex_executor.h
+++ b/libstdc++-v3/include/bits/regex_executor.h
@@ -42,8 +42,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
/**
- * @brief Takes a regex and an input string in and
- * do the matching.
+ * @brief Takes a regex and an input string and does the matching.
*
* The %_Executor class has two modes: DFS mode and BFS mode, controlled
* by the template parameter %__dfs_mode.
@@ -52,6 +51,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool __dfs_mode>
class _Executor
{
+ using __search_mode = integral_constant<bool, __dfs_mode>;
+ using __dfs = true_type;
+ using __bfs = false_type;
+
+ enum class _Match_mode : unsigned char { _Exact, _Prefix };
+
public:
typedef typename iterator_traits<_BiIter>::value_type _CharT;
typedef basic_regex<_CharT, _TraitsT> _RegexT;
@@ -71,24 +76,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_re(__re),
_M_nfa(*__re._M_automaton),
_M_results(__results),
- _M_match_queue(__dfs_mode ? nullptr
- : new vector<pair<_StateIdT, _ResultsVec>>()),
_M_rep_count(_M_nfa.size()),
- _M_visited(__dfs_mode ? nullptr : new vector<bool>(_M_nfa.size())),
+ _M_states(_M_nfa._M_start(), _M_nfa.size()),
_M_flags((__flags & regex_constants::match_prev_avail)
? (__flags
& ~regex_constants::match_not_bol
& ~regex_constants::match_not_bow)
- : __flags),
- _M_start_state(_M_nfa._M_start())
+ : __flags)
{ }
- // Set matched when string exactly match the pattern.
+ // Set matched when string exactly matches the pattern.
bool
_M_match()
{
_M_current = _M_begin;
- return _M_main<true>();
+ return _M_main(_Match_mode::_Exact);
}
// Set matched when some prefix of the string matches the pattern.
@@ -96,24 +98,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_search_from_first()
{
_M_current = _M_begin;
- return _M_main<false>();
+ return _M_main(_Match_mode::_Prefix);
}
bool
_M_search();
private:
- template<bool __match_mode>
- void
- _M_rep_once_more(_StateIdT);
+ void
+ _M_rep_once_more(_Match_mode __match_mode, _StateIdT);
- template<bool __match_mode>
- void
- _M_dfs(_StateIdT __start);
+ void
+ _M_dfs(_Match_mode __match_mode, _StateIdT __start);
- template<bool __match_mode>
- bool
- _M_main();
+ bool
+ _M_main(_Match_mode __match_mode)
+ { return _M_main_dispatch(__match_mode, __search_mode{}); }
+
+ bool
+ _M_main_dispatch(_Match_mode __match_mode, __dfs);
+
+ bool
+ _M_main_dispatch(_Match_mode __match_mode, __bfs);
bool
_M_is_word(_CharT __ch) const
@@ -144,6 +150,53 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool
_M_lookahead(_State<_TraitsT> __state);
+ // Holds additional information used in BFS-mode.
+ template<typename _SearchMode, typename _ResultsVec>
+ struct _State_info;
+
+ template<typename _ResultsVec>
+ struct _State_info<__bfs, _ResultsVec>
+ {
+ explicit
+ _State_info(_StateIdT __start, size_t __n)
+ : _M_start(__start), _M_visited_states(new bool[__n]())
+ { }
+
+ bool _M_visited(_StateIdT __i)
+ {
+ if (_M_visited_states[__i])
+ return true;
+ _M_visited_states[__i] = true;
+ return false;
+ }
+
+ void _M_queue(_StateIdT __i, const _ResultsVec& __res)
+ { _M_match_queue.emplace_back(__i, __res); }
+
+ // Saves states that need to be considered for the next character.
+ vector<pair<_StateIdT, _ResultsVec>> _M_match_queue;
+ // Indicates which states are already visited.
+ unique_ptr<bool[]> _M_visited_states;
+ // To record current solution.
+ _StateIdT _M_start;
+ };
+
+ template<typename _ResultsVec>
+ struct _State_info<__dfs, _ResultsVec>
+ {
+ explicit
+ _State_info(_StateIdT __start, size_t) : _M_start(__start)
+ { }
+
+ // Dummy implementations for DFS mode.
+ bool _M_visited(_StateIdT) const { return false; }
+ void _M_queue(_StateIdT, const _ResultsVec&) { }
+
+ // To record current solution.
+ _StateIdT _M_start;
+ };
+
+
public:
_ResultsVec _M_cur_results;
_BiIter _M_current;
@@ -152,15 +205,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const _RegexT& _M_re;
const _NFAT& _M_nfa;
_ResultsVec& _M_results;
- // Used in BFS, saving states that need to be considered for the next
- // character.
- unique_ptr<vector<pair<_StateIdT, _ResultsVec>>> _M_match_queue;
- // Used in BFS, indicating that which state is already visited.
vector<pair<_BiIter, int>> _M_rep_count;
- unique_ptr<vector<bool>> _M_visited;
+ _State_info<__search_mode, _ResultsVec> _M_states;
_FlagT _M_flags;
- // To record current solution.
- _StateIdT _M_start_state;
// Do we have a solution so far?
bool _M_has_sol;
};
diff --git a/libstdc++-v3/include/bits/regex_executor.tcc b/libstdc++-v3/include/bits/regex_executor.tcc
index 7f8993382c8..aefa8f47137 100644
--- a/libstdc++-v3/include/bits/regex_executor.tcc
+++ b/libstdc++-v3/include/bits/regex_executor.tcc
@@ -35,7 +35,7 @@ namespace __detail
_GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _BiIter, typename _Alloc, typename _TraitsT,
- bool __dfs_mode>
+ bool __dfs_mode>
bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
_M_search()
{
@@ -45,7 +45,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
do
{
_M_current = __cur;
- if (_M_main<false>())
+ if (_M_main(_Match_mode::_Prefix))
return true;
}
// Continue when __cur == _M_end
@@ -53,8 +53,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return false;
}
- // This function operates in different modes, DFS mode or BFS mode, indicated
- // by template parameter __dfs_mode. See _M_main for details.
+ // The _M_main function operates in different modes, DFS mode or BFS mode,
+ // indicated by template parameter __dfs_mode, and dispatches to one of the
+ // _M_main_dispatch overloads.
//
// ------------------------------------------------------------
//
@@ -62,12 +63,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
//
// It applies a Depth-First-Search (aka backtracking) on given NFA and input
// string.
- // At the very beginning the executor stands in the start state, then it tries
- // every possible state transition in current state recursively. Some state
- // transitions consume input string, say, a single-char-matcher or a
+ // At the very beginning the executor stands in the start state, then it
+ // tries every possible state transition in current state recursively. Some
+ // state transitions consume input string, say, a single-char-matcher or a
// back-reference matcher; some don't, like assertion or other anchor nodes.
- // When the input is exhausted and/or the current state is an accepting state,
- // the whole executor returns true.
+ // When the input is exhausted and/or the current state is an accepting
+ // state, the whole executor returns true.
//
// TODO: This approach is exponentially slow for certain input.
// Try to compile the NFA to a DFA.
@@ -75,6 +76,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Time complexity: \Omega(match_length), O(2^(_M_nfa.size()))
// Space complexity: \theta(match_results.size() + match_length)
//
+ template<typename _BiIter, typename _Alloc, typename _TraitsT,
+ bool __dfs_mode>
+ bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
+ _M_main_dispatch(_Match_mode __match_mode, __dfs)
+ {
+ _M_has_sol = false;
+ _M_cur_results = _M_results;
+ _M_dfs(__match_mode, _M_states._M_start);
+ return _M_has_sol;
+ }
+
// ------------------------------------------------------------
//
// BFS mode:
@@ -84,11 +96,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
//
// It first computes epsilon closure (states that can be achieved without
// consuming characters) for every state that's still matching,
- // using the same DFS algorithm, but doesn't re-enter states (find a true in
- // _M_visited), nor follows _S_opcode_match.
+ // using the same DFS algorithm, but doesn't re-enter states (using
+ // _M_states._M_visited to check), nor follow _S_opcode_match.
//
- // Then apply DFS using every _S_opcode_match (in _M_match_queue) as the start
- // state.
+ // Then apply DFS using every _S_opcode_match (in _M_states._M_match_queue)
+ // as the start state.
//
// It significantly reduces potential duplicate states, so has a better
// upper bound; but it requires more overhead.
@@ -98,60 +110,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Space complexity: \Omega(_M_nfa.size() + match_results.size())
// O(_M_nfa.size() * match_results.size())
template<typename _BiIter, typename _Alloc, typename _TraitsT,
- bool __dfs_mode>
- template<bool __match_mode>
+ bool __dfs_mode>
bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
- _M_main()
+ _M_main_dispatch(_Match_mode __match_mode, __bfs)
{
- if (__dfs_mode)
+ _M_states._M_queue(_M_states._M_start, _M_results);
+ bool __ret = false;
+ while (1)
{
_M_has_sol = false;
- _M_cur_results = _M_results;
- _M_dfs<__match_mode>(_M_start_state);
- return _M_has_sol;
- }
- else
- {
- _M_match_queue->push_back(make_pair(_M_start_state, _M_results));
- bool __ret = false;
- while (1)
+ if (_M_states._M_match_queue.empty())
+ break;
+ std::fill_n(_M_states._M_visited_states.get(), _M_nfa.size(), false);
+ auto __old_queue = std::move(_M_states._M_match_queue);
+ for (auto& __task : __old_queue)
{
- _M_has_sol = false;
- if (_M_match_queue->empty())
- break;
- _M_visited->assign(_M_visited->size(), false);
- auto _M_old_queue = std::move(*_M_match_queue);
- for (auto __task : _M_old_queue)
- {
- _M_cur_results = __task.second;
- _M_dfs<__match_mode>(__task.first);
- }
- if (!__match_mode)
- __ret |= _M_has_sol;
- if (_M_current == _M_end)
- break;
- ++_M_current;
+ _M_cur_results = std::move(__task.second);
+ _M_dfs(__match_mode, __task.first);
}
- if (__match_mode)
- __ret = _M_has_sol;
- return __ret;
+ if (__match_mode == _Match_mode::_Prefix)
+ __ret |= _M_has_sol;
+ if (_M_current == _M_end)
+ break;
+ ++_M_current;
}
+ if (__match_mode == _Match_mode::_Exact)
+ __ret = _M_has_sol;
+ return __ret;
}
// Return whether now match the given sub-NFA.
template<typename _BiIter, typename _Alloc, typename _TraitsT,
- bool __dfs_mode>
+ bool __dfs_mode>
bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
_M_lookahead(_State<_TraitsT> __state)
{
_ResultsVec __what(_M_cur_results.size());
- auto __sub = std::unique_ptr<_Executor>(new _Executor(_M_current,
- _M_end,
- __what,
- _M_re,
- _M_flags));
- __sub->_M_start_state = __state._M_alt;
- if (__sub->_M_search_from_first())
+ _Executor __sub(_M_current, _M_end, __what, _M_re, _M_flags);
+ __sub._M_states._M_start = __state._M_alt;
+ if (__sub._M_search_from_first())
{
for (size_t __i = 0; __i < __what.size(); __i++)
if (__what[__i].matched)
@@ -169,9 +166,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// we need to spare one more time for potential group capture.
template<typename _BiIter, typename _Alloc, typename _TraitsT,
bool __dfs_mode>
- template<bool __match_mode>
void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
- _M_rep_once_more(_StateIdT __i)
+ _M_rep_once_more(_Match_mode __match_mode, _StateIdT __i)
{
const auto& __state = _M_nfa[__i];
auto& __rep_count = _M_rep_count[__i];
@@ -180,7 +176,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
auto __back = __rep_count;
__rep_count.first = _M_current;
__rep_count.second = 1;
- _M_dfs<__match_mode>(__state._M_alt);
+ _M_dfs(__match_mode, __state._M_alt);
__rep_count = __back;
}
else
@@ -188,24 +184,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__rep_count.second < 2)
{
__rep_count.second++;
- _M_dfs<__match_mode>(__state._M_alt);
+ _M_dfs(__match_mode, __state._M_alt);
__rep_count.second--;
}
}
};
template<typename _BiIter, typename _Alloc, typename _TraitsT,
- bool __dfs_mode>
- template<bool __match_mode>
+ bool __dfs_mode>
void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
- _M_dfs(_StateIdT __i)
+ _M_dfs(_Match_mode __match_mode, _StateIdT __i)
{
- if (!__dfs_mode)
- {
- if ((*_M_visited)[__i])
- return;
- (*_M_visited)[__i] = true;
- }
+ if (_M_states._M_visited(__i))
+ return;
const auto& __state = _M_nfa[__i];
// Every change on _M_cur_results and _M_current will be rolled back after
@@ -221,33 +212,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Greedy.
if (!__state._M_neg)
{
- _M_rep_once_more<__match_mode>(__i);
+ _M_rep_once_more(__match_mode, __i);
// If it's DFS executor and already accepted, we're done.
if (!__dfs_mode || !_M_has_sol)
- _M_dfs<__match_mode>(__state._M_next);
+ _M_dfs(__match_mode, __state._M_next);
}
else // Non-greedy mode
{
if (__dfs_mode)
{
// vice-versa.
- _M_dfs<__match_mode>(__state._M_next);
+ _M_dfs(__match_mode, __state._M_next);
if (!_M_has_sol)
- _M_rep_once_more<__match_mode>(__i);
+ _M_rep_once_more(__match_mode, __i);
}
else
{
// DON'T attempt anything, because there's already another
- // state with higher priority accepted. This state cannot be
- // better by attempting its next node.
+ // state with higher priority accepted. This state cannot
+ // be better by attempting its next node.
if (!_M_has_sol)
{
- _M_dfs<__match_mode>(__state._M_next);
+ _M_dfs(__match_mode, __state._M_next);
// DON'T attempt anything if it's already accepted. An
// accepted state *must* be better than a solution that
// matches a non-greedy quantifier one more time.
if (!_M_has_sol)
- _M_rep_once_more<__match_mode>(__i);
+ _M_rep_once_more(__match_mode, __i);
}
}
}
@@ -258,7 +249,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
auto& __res = _M_cur_results[__state._M_subexpr];
auto __back = __res.first;
__res.first = _M_current;
- _M_dfs<__match_mode>(__state._M_next);
+ _M_dfs(__match_mode, __state._M_next);
__res.first = __back;
}
break;
@@ -268,27 +259,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
auto __back = __res;
__res.second = _M_current;
__res.matched = true;
- _M_dfs<__match_mode>(__state._M_next);
+ _M_dfs(__match_mode, __state._M_next);
__res = __back;
}
break;
case _S_opcode_line_begin_assertion:
if (_M_at_begin())
- _M_dfs<__match_mode>(__state._M_next);
+ _M_dfs(__match_mode, __state._M_next);
break;
case _S_opcode_line_end_assertion:
if (_M_at_end())
- _M_dfs<__match_mode>(__state._M_next);
+ _M_dfs(__match_mode, __state._M_next);
break;
case _S_opcode_word_boundary:
if (_M_word_boundary(__state) == !__state._M_neg)
- _M_dfs<__match_mode>(__state._M_next);
+ _M_dfs(__match_mode, __state._M_next);
break;
// Here __state._M_alt offers a single start node for a sub-NFA.
// We recursively invoke our algorithm to match the sub-NFA.
case _S_opcode_subexpr_lookahead:
if (_M_lookahead(__state) == !__state._M_neg)
- _M_dfs<__match_mode>(__state._M_next);
+ _M_dfs(__match_mode, __state._M_next);
break;
case _S_opcode_match:
if (__dfs_mode)
@@ -296,14 +287,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (_M_current != _M_end && __state._M_matches(*_M_current))
{
++_M_current;
- _M_dfs<__match_mode>(__state._M_next);
+ _M_dfs(__match_mode, __state._M_next);
--_M_current;
}
}
else
if (__state._M_matches(*_M_current))
- _M_match_queue->push_back(make_pair(__state._M_next,
- _M_cur_results));
+ _M_states._M_queue(__state._M_next, _M_cur_results);
break;
// First fetch the matched result from _M_cur_results as __submatch;
// then compare it with
@@ -328,11 +318,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
auto __backup = _M_current;
_M_current = __last;
- _M_dfs<__match_mode>(__state._M_next);
+ _M_dfs(__match_mode, __state._M_next);
_M_current = __backup;
}
else
- _M_dfs<__match_mode>(__state._M_next);
+ _M_dfs(__match_mode, __state._M_next);
}
}
break;
@@ -340,7 +330,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__dfs_mode)
{
_GLIBCXX_DEBUG_ASSERT(!_M_has_sol);
- if (__match_mode)
+ if (__match_mode == _Match_mode::_Exact)
_M_has_sol = _M_current == _M_end;
else
_M_has_sol = true;
@@ -355,7 +345,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (_M_current == _M_begin
&& (_M_flags & regex_constants::match_not_null))
break;
- if (!__match_mode || _M_current == _M_end)
+ if (__match_mode == _Match_mode::_Prefix || _M_current == _M_end)
if (!_M_has_sol)
{
_M_has_sol = true;
@@ -364,9 +354,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
break;
case _S_opcode_alternative:
- _M_dfs<__match_mode>(__state._M_alt);
+ _M_dfs(__match_mode, __state._M_alt);
if (!__dfs_mode || !_M_has_sol)
- _M_dfs<__match_mode>(__state._M_next);
+ _M_dfs(__match_mode, __state._M_next);
break;
default:
_GLIBCXX_DEBUG_ASSERT(false);
@@ -375,7 +365,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Return whether now is at some word boundary.
template<typename _BiIter, typename _Alloc, typename _TraitsT,
- bool __dfs_mode>
+ bool __dfs_mode>
bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
_M_word_boundary(_State<_TraitsT> __state) const
{
diff --git a/libstdc++-v3/include/bits/regex_scanner.tcc b/libstdc++-v3/include/bits/regex_scanner.tcc
index f501ff6c2cb..818e47b5670 100644
--- a/libstdc++-v3/include/bits/regex_scanner.tcc
+++ b/libstdc++-v3/include/bits/regex_scanner.tcc
@@ -227,14 +227,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
// In POSIX, when encountering "[]" or "[^]", the ']' is interpreted
- // literally. So "[]]" or "[^]]" is valid regex. See the testcases
+ // literally. So "[]]" and "[^]]" are valid regexes. See the testcases
// `*/empty_range.cc`.
else if (__c == ']' && (_M_is_ecma() || !_M_at_bracket_start))
{
_M_token = _S_token_bracket_end;
_M_state = _S_state_normal;
}
- // ECMAScirpt and awk permmits escaping in bracket.
+ // ECMAScript and awk permits escaping in bracket.
else if (__c == '\\' && (_M_is_ecma() || _M_is_awk()))
(this->*_M_eat_escape)();
else
@@ -344,7 +344,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
_M_token = _S_token_hex_num;
}
- // ECMAScript recongnizes multi-digit back-references.
+ // ECMAScript recognizes multi-digit back-references.
else if (_M_ctype.is(_CtypeT::digit, __c))
{
_M_value.assign(1, __c);
@@ -392,6 +392,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
else
{
#ifdef __STRICT_ANSI__
+ // POSIX says it is undefined to escape ordinary characters
__throw_regex_error(regex_constants::error_escape);
#else
_M_token = _S_token_ord_char;
@@ -435,8 +436,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__throw_regex_error(regex_constants::error_escape);
}
- // Eats a character class or throwns an exception.
- // __ch cound be ':', '.' or '=', _M_current is the char after ']' when
+ // Eats a character class or throws an exception.
+ // __ch could be ':', '.' or '=', _M_current is the char after ']' when
// returning.
template<typename _CharT>
void
diff --git a/libstdc++-v3/include/bits/uses_allocator.h b/libstdc++-v3/include/bits/uses_allocator.h
index 10131c0a967..7281508fc06 100644
--- a/libstdc++-v3/include/bits/uses_allocator.h
+++ b/libstdc++-v3/include/bits/uses_allocator.h
@@ -45,35 +45,33 @@ _GLIBCXX_HAS_NESTED_TYPE(allocator_type)
template<typename _Tp, typename _Alloc,
bool = __has_allocator_type<_Tp>::value>
struct __uses_allocator_helper
- : public false_type { };
+ : false_type { };
template<typename _Tp, typename _Alloc>
struct __uses_allocator_helper<_Tp, _Alloc, true>
- : public integral_constant<bool, is_convertible<_Alloc,
- typename _Tp::allocator_type>::value>
+ : is_convertible<_Alloc, typename _Tp::allocator_type>::type
{ };
/// [allocator.uses.trait]
template<typename _Tp, typename _Alloc>
struct uses_allocator
- : public integral_constant<bool,
- __uses_allocator_helper<_Tp, _Alloc>::value>
+ : __uses_allocator_helper<_Tp, _Alloc>::type
{ };
- template<typename _Tp, typename _Alloc, typename... _Args>
- struct __uses_allocator_arg
- : is_constructible<_Tp, _Alloc, _Args...>
- { static_assert( uses_allocator<_Tp, _Alloc>::value, "uses allocator" ); };
-
struct __uses_alloc_base { };
+
struct __uses_alloc0 : __uses_alloc_base
- { struct _Anything { _Anything(...) { } } _M_a; };
+ {
+ struct _Sink { void operator=(const void*) { } } _M_a;
+ };
+
template<typename _Alloc>
struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; };
+
template<typename _Alloc>
struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; };
- template<bool, typename _Alloc, typename... _Args>
+ template<bool, typename _Tp, typename _Alloc, typename... _Args>
struct __uses_alloc;
template<typename _Tp, typename _Alloc, typename... _Args>
@@ -89,15 +87,14 @@ _GLIBCXX_HAS_NESTED_TYPE(allocator_type)
: __uses_alloc0 { };
template<typename _Tp, typename _Alloc, typename... _Args>
- struct __uses_alloc_impl
- : __uses_alloc<uses_allocator<_Tp, _Alloc>::value, _Tp, _Alloc, _Args...>
- { };
+ using __uses_alloc_t =
+ __uses_alloc<uses_allocator<_Tp, _Alloc>::value, _Tp, _Alloc, _Args...>;
template<typename _Tp, typename _Alloc, typename... _Args>
- __uses_alloc_impl<_Tp, _Alloc, _Args...>
+ inline __uses_alloc_t<_Tp, _Alloc, _Args...>
__use_alloc(const _Alloc& __a)
{
- __uses_alloc_impl<_Tp, _Alloc, _Args...> __ret;
+ __uses_alloc_t<_Tp, _Alloc, _Args...> __ret;
__ret._M_a = &__a;
return __ret;
}
diff --git a/libstdc++-v3/include/debug/array b/libstdc++-v3/include/debug/array
index ef01c981bd4..2266a53e41a 100644
--- a/libstdc++-v3/include/debug/array
+++ b/libstdc++-v3/include/debug/array
@@ -278,7 +278,7 @@ namespace __debug
get(array<_Tp, _Nm>&& __arr) noexcept
{
static_assert(_Int < _Nm, "index is out of bounds");
- return std::move(get<_Int>(__arr));
+ return std::move(__debug::get<_Int>(__arr));
}
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
diff --git a/libstdc++-v3/include/experimental/string_view b/libstdc++-v3/include/experimental/string_view
index 6b6588b9770..49f46af544f 100644
--- a/libstdc++-v3/include/experimental/string_view
+++ b/libstdc++-v3/include/experimental/string_view
@@ -39,7 +39,6 @@
# include <bits/c++14_warning.h>
#else
-#include <debug/debug.h>
#include <string>
#include <limits>
@@ -66,18 +65,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* _CharT* _M_str
* size_t _M_len
* @endcode
- *
- * A basic_string_view represents an empty string with a static constexpr
- * length one string:
- *
- * @code
- * static constexpr value_type _S_empty_str[1]{0};
- * @endcode
*/
- template<typename _CharT, typename _Traits = char_traits<_CharT>>
+ template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
class basic_string_view
{
-
public:
// types
@@ -99,7 +90,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr
basic_string_view() noexcept
- : _M_len{0}, _M_str{_S_empty_str}
+ : _M_len{0}, _M_str{nullptr}
{ }
constexpr basic_string_view(const basic_string_view&) noexcept = default;
@@ -112,12 +103,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr basic_string_view(const _CharT* __str)
: _M_len{__str == nullptr ? 0 : traits_type::length(__str)},
- _M_str{__str == nullptr ? _S_empty_str : __str}
+ _M_str{__str}
{ }
constexpr basic_string_view(const _CharT* __str, size_type __len)
- : _M_len{__str == nullptr ? 0 :__len},
- _M_str{__str == nullptr ? _S_empty_str : __str}
+ : _M_len{__len},
+ _M_str{__str}
{ }
basic_string_view&
@@ -143,19 +134,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const_reverse_iterator
rbegin() const noexcept
- { return std::reverse_iterator<const_iterator>(this->end()); }
+ { return const_reverse_iterator(this->end()); }
const_reverse_iterator
rend() const noexcept
- { return std::reverse_iterator<const_iterator>(this->begin()); }
+ { return const_reverse_iterator(this->begin()); }
const_reverse_iterator
crbegin() const noexcept
- { return std::reverse_iterator<const_iterator>(this->end()); }
+ { return const_reverse_iterator(this->end()); }
const_reverse_iterator
crend() const noexcept
- { return std::reverse_iterator<const_iterator>(this->begin()); }
+ { return const_reverse_iterator(this->begin()); }
// [string.view.capacity], capacity
@@ -169,8 +160,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr size_type
max_size() const noexcept
- { return ((npos - sizeof(size_type) - sizeof(void*))
- / sizeof(value_type) / 4); }
+ {
+ return (npos - sizeof(size_type) - sizeof(void*))
+ / sizeof(value_type) / 4;
+ }
constexpr bool
empty() const noexcept
@@ -195,7 +188,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
"(which is %zu) >= this->size() "
"(which is %zu)"),
__pos, this->size()),
- _S_empty_str[0]);
+ *this->_M_str);
}
constexpr const _CharT&
@@ -219,11 +212,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return this->_M_str; }
// [string.view.modifiers], modifiers:
+
void
clear() noexcept
{
this->_M_len = 0;
- this->_M_str = _S_empty_str;
+ this->_M_str = nullptr;
}
void
@@ -251,8 +245,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Allocator>
explicit operator basic_string<_CharT, _Traits, _Allocator>() const
{
- return basic_string<_CharT, _Traits, _Allocator>
- (this->_M_len, this->_M_str);
+ return { this->_M_str, this->_M_len };
+ }
+
+ template<typename _Allocator = std::allocator<_CharT>>
+ basic_string<_CharT, _Traits, _Allocator>
+ to_string(const _Allocator& __alloc = _Allocator()) const
+ {
+ return { this->_M_str, this->_M_len, __alloc };
}
size_type
@@ -431,8 +431,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: static_cast<int>(difference_type{__n1 - __n2});
}
- static constexpr value_type _S_empty_str[1]{};
-
size_t _M_len;
const _CharT* _M_str;
};
@@ -456,131 +454,119 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator==(basic_string_view<_CharT, _Traits> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{ return __x.compare(__y) == 0; }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator==(basic_string_view<_CharT, _Traits> __x,
__detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
{ return __x.compare(__y) == 0; }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator==(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{ return __x.compare(__y) == 0; }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator!=(basic_string_view<_CharT, _Traits> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{ return !(__x == __y); }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator!=(basic_string_view<_CharT, _Traits> __x,
__detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
{ return !(__x == __y); }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator!=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{ return !(__x == __y); }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator< (basic_string_view<_CharT, _Traits> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{ return __x.compare(__y) < 0; }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator< (basic_string_view<_CharT, _Traits> __x,
__detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
{ return __x.compare(__y) < 0; }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator< (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{ return __x.compare(__y) < 0; }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator> (basic_string_view<_CharT, _Traits> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{ return __x.compare(__y) > 0; }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator> (basic_string_view<_CharT, _Traits> __x,
__detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
{ return __x.compare(__y) > 0; }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator> (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{ return __x.compare(__y) > 0; }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator<=(basic_string_view<_CharT, _Traits> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{ return __x.compare(__y) <= 0; }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator<=(basic_string_view<_CharT, _Traits> __x,
__detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
{ return __x.compare(__y) <= 0; }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator<=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{ return __x.compare(__y) <= 0; }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator>=(basic_string_view<_CharT, _Traits> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{ return __x.compare(__y) >= 0; }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator>=(basic_string_view<_CharT, _Traits> __x,
__detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
{ return __x.compare(__y) >= 0; }
template<typename _CharT, typename _Traits>
- bool
+ inline bool
operator>=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
{ return __x.compare(__y) >= 0; }
- // [string.view.comparison], sufficient additional overloads of comparison functions
-
- // [string.view.nonmem], other non-member basic_string_view functions
- template<typename _CharT, typename _Traits = char_traits<_CharT>,
- typename _Allocator = allocator<_CharT>>
- basic_string<_CharT, _Traits, _Allocator>
- to_string(basic_string_view<_CharT, _Traits> __str,
- const _Allocator& __alloc = _Allocator())
- {
- return basic_string<_CharT, _Traits, _Allocator>
- (__str.begin(), __str.end(), __alloc);
- }
-
+ // [string.view.io], Inserters and extractors
template<typename _CharT, typename _Traits>
- basic_ostream<_CharT, _Traits>&
- operator<<(basic_ostream<_CharT, _Traits>& __os,
- basic_string_view<_CharT,_Traits> __str)
- { return __ostream_insert(__os, __str.data(), __str.size()); }
+ inline basic_ostream<_CharT, _Traits>&
+ operator<<(basic_ostream<_CharT, _Traits>& __os,
+ basic_string_view<_CharT,_Traits> __str)
+ { return __ostream_insert(__os, __str.data(), __str.size()); }
// basic_string_view typedef names
diff --git a/libstdc++-v3/include/experimental/string_view.tcc b/libstdc++-v3/include/experimental/string_view.tcc
index 1af3a4d9bbd..44562665abe 100644
--- a/libstdc++-v3/include/experimental/string_view.tcc
+++ b/libstdc++-v3/include/experimental/string_view.tcc
@@ -47,10 +47,6 @@ namespace experimental
_GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _CharT, typename _Traits>
- constexpr _CharT
- basic_string_view<_CharT, _Traits>::_S_empty_str[1];
-
- template<typename _CharT, typename _Traits>
typename basic_string_view<_CharT, _Traits>::size_type
basic_string_view<_CharT, _Traits>::
find(const _CharT* __str, size_type __pos, size_type __n) const noexcept
diff --git a/libstdc++-v3/include/profile/array b/libstdc++-v3/include/profile/array
index 1c38b05c56c..3561c761525 100644
--- a/libstdc++-v3/include/profile/array
+++ b/libstdc++-v3/include/profile/array
@@ -83,19 +83,19 @@ namespace __profile
end() const noexcept
{ return const_iterator(data() + _Nm); }
- reverse_iterator
+ reverse_iterator
rbegin() noexcept
{ return reverse_iterator(end()); }
- const_reverse_iterator
+ const_reverse_iterator
rbegin() const noexcept
{ return const_reverse_iterator(end()); }
- reverse_iterator
+ reverse_iterator
rend() noexcept
{ return reverse_iterator(begin()); }
- const_reverse_iterator
+ const_reverse_iterator
rend() const noexcept
{ return const_reverse_iterator(begin()); }
@@ -107,22 +107,22 @@ namespace __profile
cend() const noexcept
{ return const_iterator(data() + _Nm); }
- const_reverse_iterator
+ const_reverse_iterator
crbegin() const noexcept
{ return const_reverse_iterator(end()); }
- const_reverse_iterator
+ const_reverse_iterator
crend() const noexcept
{ return const_reverse_iterator(begin()); }
// Capacity.
- constexpr size_type
+ constexpr size_type
size() const noexcept { return _Nm; }
- constexpr size_type
+ constexpr size_type
max_size() const noexcept { return _Nm; }
- constexpr bool
+ constexpr bool
empty() const noexcept { return size() == 0; }
// Element access.
@@ -157,23 +157,23 @@ namespace __profile
_AT_Type::_S_ref(_M_elems, 0));
}
- reference
+ reference
front() noexcept
{ return *begin(); }
- constexpr const_reference
+ constexpr const_reference
front() const noexcept
{ return _AT_Type::_S_ref(_M_elems, 0); }
- reference
+ reference
back() noexcept
{ return _Nm ? *(end() - 1) : *end(); }
- constexpr const_reference
+ constexpr const_reference
back() const noexcept
{
return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1)
- : _AT_Type::_S_ref(_M_elems, 0);
+ : _AT_Type::_S_ref(_M_elems, 0);
}
pointer
@@ -187,7 +187,7 @@ namespace __profile
// Array comparisons.
template<typename _Tp, std::size_t _Nm>
- inline bool
+ inline bool
operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
{ return std::equal(__one.begin(), __one.end(), __two.begin()); }
@@ -199,9 +199,9 @@ namespace __profile
template<typename _Tp, std::size_t _Nm>
inline bool
operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
- {
+ {
return std::lexicographical_compare(__a.begin(), __a.end(),
- __b.begin(), __b.end());
+ __b.begin(), __b.end());
}
template<typename _Tp, std::size_t _Nm>
@@ -240,7 +240,7 @@ namespace __profile
get(array<_Tp, _Nm>&& __arr) noexcept
{
static_assert(_Int < _Nm, "index is out of bounds");
- return std::move(get<_Int>(__arr));
+ return std::move(__profile::get<_Int>(__arr));
}
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
diff --git a/libstdc++-v3/include/profile/base.h b/libstdc++-v3/include/profile/base.h
index 342bb704288..9ca0c3f4aba 100644
--- a/libstdc++-v3/include/profile/base.h
+++ b/libstdc++-v3/include/profile/base.h
@@ -40,9 +40,9 @@
* @namespace std::__profile
* @brief GNU profile code, replaces standard behavior with profile behavior.
*/
-namespace std _GLIBCXX_VISIBILITY(default)
-{
- namespace __profile { }
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+ namespace __profile { }
}
/**
diff --git a/libstdc++-v3/include/profile/bitset b/libstdc++-v3/include/profile/bitset
index a9f37aaf1b5..651f25cd885 100644
--- a/libstdc++-v3/include/profile/bitset
+++ b/libstdc++-v3/include/profile/bitset
@@ -35,7 +35,8 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
namespace __profile
{
- /// Class std::bitset wrapper with performance instrumentation.
+ /// Class std::bitset wrapper with performance instrumentation, none at the
+ /// moment.
template<size_t _Nb>
class bitset
: public _GLIBCXX_STD_C::bitset<_Nb>
@@ -43,60 +44,13 @@ namespace __profile
typedef _GLIBCXX_STD_C::bitset<_Nb> _Base;
public:
- // bit reference:
- class reference
- : private _Base::reference
- {
- typedef typename _Base::reference _Base_ref;
-
- friend class bitset;
- reference();
-
- reference(const _Base_ref& __base, bitset* __seq) _GLIBCXX_NOEXCEPT
- : _Base_ref(__base)
- { }
-
- public:
- reference(const reference& __x) _GLIBCXX_NOEXCEPT
- : _Base_ref(__x)
- { }
-
- reference&
- operator=(bool __x) _GLIBCXX_NOEXCEPT
- {
- *static_cast<_Base_ref*>(this) = __x;
- return *this;
- }
-
- reference&
- operator=(const reference& __x) _GLIBCXX_NOEXCEPT
- {
- *static_cast<_Base_ref*>(this) = __x;
- return *this;
- }
-
- bool
- operator~() const _GLIBCXX_NOEXCEPT
- {
- return ~(*static_cast<const _Base_ref*>(this));
- }
-
- operator bool() const _GLIBCXX_NOEXCEPT
- {
- return *static_cast<const _Base_ref*>(this);
- }
-
- reference&
- flip() _GLIBCXX_NOEXCEPT
- {
- _Base_ref::flip();
- return *this;
- }
- };
-
// 23.3.5.1 constructors:
- _GLIBCXX_CONSTEXPR bitset() _GLIBCXX_NOEXCEPT
+#if __cplusplus < 201103L
+ bitset()
: _Base() { }
+#else
+ constexpr bitset() = default;
+#endif
#if __cplusplus >= 201103L
constexpr bitset(unsigned long long __val) noexcept
@@ -106,8 +60,8 @@ namespace __profile
: _Base(__val) { }
template<typename _CharT, typename _Traits, typename _Alloc>
- explicit
- bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str,
+ explicit
+ bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str,
typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
__pos = 0,
typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
@@ -129,8 +83,8 @@ namespace __profile
#if __cplusplus >= 201103L
template<typename _CharT>
- explicit
- bitset(const _CharT* __str,
+ explicit
+ bitset(const _CharT* __str,
typename std::basic_string<_CharT>::size_type __n
= std::basic_string<_CharT>::npos,
_CharT __zero = _CharT('0'), _CharT __one = _CharT('1'))
@@ -221,92 +175,6 @@ namespace __profile
return *this;
}
- // element access:
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 11. Bitset minor problems
- reference
- operator[](size_t __pos)
- {
- return reference(_M_base()[__pos], this);
- }
-
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 11. Bitset minor problems
- _GLIBCXX_CONSTEXPR bool
- operator[](size_t __pos) const
- {
- return _Base::operator[](__pos);
- }
-
- using _Base::to_ulong;
-#if __cplusplus >= 201103L
- using _Base::to_ullong;
-#endif
-
- template <typename _CharT, typename _Traits, typename _Alloc>
- std::basic_string<_CharT, _Traits, _Alloc>
- to_string() const
- { return _M_base().template to_string<_CharT, _Traits, _Alloc>(); }
-
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 396. what are characters zero and one.
- template<class _CharT, class _Traits, class _Alloc>
- std::basic_string<_CharT, _Traits, _Alloc>
- to_string(_CharT __zero, _CharT __one = _CharT('1')) const
- {
- return _M_base().template
- to_string<_CharT, _Traits, _Alloc>(__zero, __one);
- }
-
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 434. bitset::to_string() hard to use.
- template<typename _CharT, typename _Traits>
- std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
- to_string() const
- { return to_string<_CharT, _Traits, std::allocator<_CharT> >(); }
-
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 853. to_string needs updating with zero and one.
- template<class _CharT, class _Traits>
- std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
- to_string(_CharT __zero, _CharT __one = _CharT('1')) const
- { return to_string<_CharT, _Traits,
- std::allocator<_CharT> >(__zero, __one); }
-
- template<typename _CharT>
- std::basic_string<_CharT, std::char_traits<_CharT>,
- std::allocator<_CharT> >
- to_string() const
- {
- return to_string<_CharT, std::char_traits<_CharT>,
- std::allocator<_CharT> >();
- }
-
- template<class _CharT>
- std::basic_string<_CharT, std::char_traits<_CharT>,
- std::allocator<_CharT> >
- to_string(_CharT __zero, _CharT __one = _CharT('1')) const
- {
- return to_string<_CharT, std::char_traits<_CharT>,
- std::allocator<_CharT> >(__zero, __one);
- }
-
- std::basic_string<char, std::char_traits<char>, std::allocator<char> >
- to_string() const
- {
- return to_string<char,std::char_traits<char>,std::allocator<char> >();
- }
-
- std::basic_string<char, std::char_traits<char>, std::allocator<char> >
- to_string(char __zero, char __one = '1') const
- {
- return to_string<char, std::char_traits<char>,
- std::allocator<char> >(__zero, __one);
- }
-
- using _Base::count;
- using _Base::size;
-
bool
operator==(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT
{ return _M_base() == __rhs; }
@@ -315,11 +183,6 @@ namespace __profile
operator!=(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT
{ return _M_base() != __rhs; }
- using _Base::test;
- using _Base::all;
- using _Base::any;
- using _Base::none;
-
bitset<_Nb>
operator<<(size_t __pos) const _GLIBCXX_NOEXCEPT
{ return bitset<_Nb>(_M_base() << __pos); }
diff --git a/libstdc++-v3/include/profile/deque b/libstdc++-v3/include/profile/deque
index 2c4f9cbd019..13513f4bdc7 100644
--- a/libstdc++-v3/include/profile/deque
+++ b/libstdc++-v3/include/profile/deque
@@ -43,26 +43,29 @@ namespace __profile
typedef _GLIBCXX_STD_C::deque<_Tp, _Allocator> _Base;
public:
- typedef typename _Base::reference reference;
- typedef typename _Base::const_reference const_reference;
-
- typedef typename _Base::iterator iterator;
- typedef typename _Base::const_iterator const_iterator;
- typedef typename _Base::reverse_iterator reverse_iterator;
- typedef typename _Base::const_reverse_iterator const_reverse_iterator;
-
- typedef typename _Base::size_type size_type;
- typedef typename _Base::difference_type difference_type;
-
- typedef _Tp value_type;
- typedef _Allocator allocator_type;
- typedef typename _Base::pointer pointer;
- typedef typename _Base::const_pointer const_pointer;
+ typedef typename _Base::size_type size_type;
+ typedef typename _Base::value_type value_type;
// 23.2.1.1 construct/copy/destroy:
+#if __cplusplus < 201103L
deque()
: _Base() { }
+ deque(const deque& __x)
+ : _Base(__x) { }
+
+ ~deque() { }
+#else
+ deque() = default;
+ deque(const deque&) = default;
+ deque(deque&&) = default;
+
+ ~deque() = default;
+
+ deque(initializer_list<value_type> __l,
+ const _Allocator& __a = _Allocator())
+ : _Base(__l, __a) { }
+#endif
explicit
deque(const _Allocator& __a)
@@ -89,346 +92,48 @@ namespace __profile
#else
template<typename _InputIterator>
#endif
- deque(_InputIterator __first, _InputIterator __last,
+ deque(_InputIterator __first, _InputIterator __last,
const _Allocator& __a = _Allocator())
: _Base(__first, __last, __a)
- { }
-
- deque(const deque& __x)
- : _Base(__x) { }
+ { }
deque(const _Base& __x)
: _Base(__x) { }
-#if __cplusplus >= 201103L
- deque(deque&& __x)
- : _Base(std::move(__x))
- { }
-
- deque(initializer_list<value_type> __l,
- const allocator_type& __a = allocator_type())
- : _Base(__l, __a) { }
-#endif
-
- ~deque() _GLIBCXX_NOEXCEPT { }
-
+#if __cplusplus < 201103L
deque&
operator=(const deque& __x)
{
- *static_cast<_Base*>(this) = __x;
+ _M_base() = __x;
return *this;
}
+#else
+ deque&
+ operator=(const deque&) = default;
-#if __cplusplus >= 201103L
deque&
- operator=(deque&& __x) noexcept
- {
- // NB: DR 1204.
- // NB: DR 675.
- this->clear();
- this->swap(__x);
- return *this;
- }
+ operator=(deque&&) = default;
deque&
operator=(initializer_list<value_type> __l)
{
- *static_cast<_Base*>(this) = __l;
+ _M_base() = __l;
return *this;
}
#endif
-#if __cplusplus >= 201103L
- template<typename _InputIterator,
- typename = std::_RequireInputIter<_InputIterator>>
-#else
- template<typename _InputIterator>
-#endif
- void
- assign(_InputIterator __first, _InputIterator __last)
- {
- _Base::assign(__first, __last);
- }
-
- void
- assign(size_type __n, const _Tp& __t)
- {
- _Base::assign(__n, __t);
- }
-
-#if __cplusplus >= 201103L
- void
- assign(initializer_list<value_type> __l)
- {
- _Base::assign(__l);
- }
-#endif
-
- using _Base::get_allocator;
-
- // iterators:
- iterator
- begin() _GLIBCXX_NOEXCEPT
- { return iterator(_Base::begin()); }
-
- const_iterator
- begin() const _GLIBCXX_NOEXCEPT
- { return const_iterator(_Base::begin()); }
-
- iterator
- end() _GLIBCXX_NOEXCEPT
- { return iterator(_Base::end()); }
-
- const_iterator
- end() const _GLIBCXX_NOEXCEPT
- { return const_iterator(_Base::end()); }
-
- reverse_iterator
- rbegin() _GLIBCXX_NOEXCEPT
- { return reverse_iterator(end()); }
-
- const_reverse_iterator
- rbegin() const _GLIBCXX_NOEXCEPT
- { return const_reverse_iterator(end()); }
-
- reverse_iterator
- rend() _GLIBCXX_NOEXCEPT
- { return reverse_iterator(begin()); }
-
- const_reverse_iterator
- rend() const _GLIBCXX_NOEXCEPT
- { return const_reverse_iterator(begin()); }
-
-#if __cplusplus >= 201103L
- const_iterator
- cbegin() const noexcept
- { return const_iterator(_Base::begin()); }
-
- const_iterator
- cend() const noexcept
- { return const_iterator(_Base::end()); }
-
- const_reverse_iterator
- crbegin() const noexcept
- { return const_reverse_iterator(end()); }
-
- const_reverse_iterator
- crend() const noexcept
- { return const_reverse_iterator(begin()); }
-#endif
-
- // 23.2.1.2 capacity:
- using _Base::size;
- using _Base::max_size;
-
-#if __cplusplus >= 201103L
- void
- resize(size_type __sz)
- {
- _Base::resize(__sz);
- }
-
- void
- resize(size_type __sz, const _Tp& __c)
- {
- _Base::resize(__sz, __c);
- }
-#else
void
- resize(size_type __sz, _Tp __c = _Tp())
- {
- _Base::resize(__sz, __c);
- }
-#endif
-
+ swap(deque& __x)
#if __cplusplus >= 201103L
- using _Base::shrink_to_fit;
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
-
- using _Base::empty;
-
- // element access:
- reference
- operator[](size_type __n) _GLIBCXX_NOEXCEPT
- {
- return _M_base()[__n];
- }
-
- const_reference
- operator[](size_type __n) const _GLIBCXX_NOEXCEPT
- {
- return _M_base()[__n];
- }
-
- using _Base::at;
-
- reference
- front() _GLIBCXX_NOEXCEPT
- {
- return _Base::front();
- }
-
- const_reference
- front() const _GLIBCXX_NOEXCEPT
- {
- return _Base::front();
- }
-
- reference
- back() _GLIBCXX_NOEXCEPT
- {
- return _Base::back();
- }
-
- const_reference
- back() const _GLIBCXX_NOEXCEPT
- {
- return _Base::back();
- }
-
- // 23.2.1.3 modifiers:
- void
- push_front(const _Tp& __x)
- {
- _Base::push_front(__x);
- }
-
- void
- push_back(const _Tp& __x)
- {
- _Base::push_back(__x);
- }
-
-#if __cplusplus >= 201103L
- void
- push_front(_Tp&& __x)
- { emplace_front(std::move(__x)); }
-
- void
- push_back(_Tp&& __x)
- { emplace_back(std::move(__x)); }
-
- template<typename... _Args>
- void
- emplace_front(_Args&&... __args)
- {
- _Base::emplace_front(std::forward<_Args>(__args)...);
- }
-
- template<typename... _Args>
- void
- emplace_back(_Args&&... __args)
- {
- _Base::emplace_back(std::forward<_Args>(__args)...);
- }
-
- template<typename... _Args>
- iterator
- emplace(const_iterator __position, _Args&&... __args)
- {
- typename _Base::iterator __res = _Base::emplace(__position,
- std::forward<_Args>(__args)...);
- return iterator(__res);
- }
-#endif
-
- iterator
-#if __cplusplus >= 201103L
- insert(const_iterator __position, const _Tp& __x)
-#else
- insert(iterator __position, const _Tp& __x)
-#endif
- {
- typename _Base::iterator __res = _Base::insert(__position, __x);
- return iterator(__res);
- }
-
-#if __cplusplus >= 201103L
- iterator
- insert(const_iterator __position, _Tp&& __x)
- { return emplace(__position, std::move(__x)); }
-
- iterator
- insert(const_iterator __p, initializer_list<value_type> __l)
- { return _Base::insert(__p, __l); }
-#endif
-
-#if __cplusplus >= 201103L
- iterator
- insert(const_iterator __position, size_type __n, const _Tp& __x)
- { return _Base::insert(__position, __n, __x); }
-#else
- void
- insert(iterator __position, size_type __n, const _Tp& __x)
- { _Base::insert(__position, __n, __x); }
-#endif
-
-#if __cplusplus >= 201103L
- template<typename _InputIterator,
- typename = std::_RequireInputIter<_InputIterator>>
- iterator
- insert(const_iterator __position,
- _InputIterator __first, _InputIterator __last)
- { return _Base::insert(__position, __first, __last); }
-#else
- template<typename _InputIterator>
- void
- insert(iterator __position,
- _InputIterator __first, _InputIterator __last)
- { _Base::insert(__position, __first, __last); }
-#endif
-
- void
- pop_front() _GLIBCXX_NOEXCEPT
- {
- _Base::pop_front();
- }
-
- void
- pop_back() _GLIBCXX_NOEXCEPT
- {
- _Base::pop_back();
- }
-
- iterator
-#if __cplusplus >= 201103L
- erase(const_iterator __position)
-#else
- erase(iterator __position)
-#endif
- {
- return _Base::erase(__position);
- }
-
- iterator
-#if __cplusplus >= 201103L
- erase(const_iterator __first, const_iterator __last)
-#else
- erase(iterator __first, iterator __last)
-#endif
- {
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 151. can't currently clear() empty container
- return _Base::erase(__first, __last);
- }
-
- void
- swap(deque& __x) _GLIBCXX_NOEXCEPT
- {
- _Base::swap(__x);
- }
-
- void
- clear() _GLIBCXX_NOEXCEPT
- {
- _Base::clear();
- }
+ { _Base::swap(__x); }
_Base&
- _M_base() _GLIBCXX_NOEXCEPT { return *this; }
+ _M_base() _GLIBCXX_NOEXCEPT { return *this; }
const _Base&
- _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
+ _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
};
template<typename _Tp, typename _Alloc>
diff --git a/libstdc++-v3/include/profile/forward_list b/libstdc++-v3/include/profile/forward_list
index 260f1d65b4b..290e4f9d703 100644
--- a/libstdc++-v3/include/profile/forward_list
+++ b/libstdc++-v3/include/profile/forward_list
@@ -46,13 +46,9 @@ namespace __profile
{
typedef _GLIBCXX_STD_C::forward_list<_Tp, _Alloc> _Base;
- typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
- rebind<_GLIBCXX_STD_C::_Fwd_list_node<_Tp>>::other _Node_alloc_type;
-
- typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits;
-
public:
- typedef typename _Base::size_type size_type;
+ typedef typename _Base::size_type size_type;
+ typedef typename _Base::const_iterator const_iterator;
// 23.2.3.1 construct/copy/destroy:
explicit
@@ -73,98 +69,135 @@ namespace __profile
{ }
forward_list(size_type __n, const _Tp& __value,
- const _Alloc& __al = _Alloc())
+ const _Alloc& __al = _Alloc())
: _Base(__n, __value, __al)
{ }
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
- forward_list(_InputIterator __first, _InputIterator __last,
- const _Alloc& __al = _Alloc())
- : _Base(__first, __last, __al)
- { }
-
- forward_list(const forward_list& __list)
- : _Base(__list)
- { }
+ forward_list(_InputIterator __first, _InputIterator __last,
+ const _Alloc& __al = _Alloc())
+ : _Base(__first, __last, __al)
+ { }
- forward_list(forward_list&& __list) noexcept
- : _Base(std::move(__list)) { }
+ forward_list(const forward_list&) = default;
+ forward_list(forward_list&&) = default;
forward_list(std::initializer_list<_Tp> __il,
- const _Alloc& __al = _Alloc())
+ const _Alloc& __al = _Alloc())
: _Base(__il, __al)
{ }
- ~forward_list() noexcept
- { }
+ ~forward_list() = default;
forward_list&
- operator=(const forward_list& __list)
- {
- static_cast<_Base&>(*this) = __list;
- return *this;
- }
+ operator=(const forward_list&) = default;
forward_list&
- operator=(forward_list&& __list)
- noexcept(_Node_alloc_traits::_S_nothrow_move())
- {
- static_cast<_Base&>(*this) = std::move(__list);
- return *this;
- }
+ operator=(forward_list&&) = default;
forward_list&
operator=(std::initializer_list<_Tp> __il)
{
- static_cast<_Base&>(*this) = __il;
- return *this;
+ _M_base() = __il;
+ return *this;
}
+ void
+ swap(forward_list& __fl)
+ noexcept( noexcept(declval<_Base>().swap(__fl)) )
+ { _Base::swap(__fl); }
+
+ void
+ splice_after(const_iterator __pos, forward_list&& __fl)
+ { _Base::splice_after(__pos, std::move(__fl)); }
+
+ void
+ splice_after(const_iterator __pos, forward_list& __list)
+ { _Base::splice_after(__pos, __list); }
+
+ void
+ splice_after(const_iterator __pos, forward_list&& __list,
+ const_iterator __i)
+ { _Base::splice_after(__pos, std::move(__list), __i); }
+
+ void
+ splice_after(const_iterator __pos, forward_list& __list,
+ const_iterator __i)
+ { _Base::splice_after(__pos, __list, __i); }
+
+ void
+ splice_after(const_iterator __pos, forward_list&& __list,
+ const_iterator __before, const_iterator __last)
+ { _Base::splice_after(__pos, std::move(__list), __before, __last); }
+
+ void
+ splice_after(const_iterator __pos, forward_list& __list,
+ const_iterator __before, const_iterator __last)
+ { _Base::splice_after(__pos, __list, __before, __last); }
+
+ void
+ merge(forward_list&& __list)
+ { _Base::merge(std::move(__list)); }
+
+ void
+ merge(forward_list& __list)
+ { _Base::merge(__list); }
+
+ template<typename _Comp>
+ void
+ merge(forward_list&& __list, _Comp __comp)
+ { _Base::merge(std::move(__list), __comp); }
+
+ template<typename _Comp>
+ void
+ merge(forward_list& __list, _Comp __comp)
+ { _Base::merge(__list, __comp); }
+
_Base&
- _M_base() noexcept { return *this; }
+ _M_base() noexcept { return *this; }
const _Base&
- _M_base() const noexcept { return *this; }
+ _M_base() const noexcept { return *this; }
};
template<typename _Tp, typename _Alloc>
inline bool
operator==(const forward_list<_Tp, _Alloc>& __lx,
- const forward_list<_Tp, _Alloc>& __ly)
+ const forward_list<_Tp, _Alloc>& __ly)
{ return __lx._M_base() == __ly._M_base(); }
template<typename _Tp, typename _Alloc>
inline bool
operator<(const forward_list<_Tp, _Alloc>& __lx,
- const forward_list<_Tp, _Alloc>& __ly)
+ const forward_list<_Tp, _Alloc>& __ly)
{ return __lx._M_base() < __ly._M_base(); }
template<typename _Tp, typename _Alloc>
inline bool
operator!=(const forward_list<_Tp, _Alloc>& __lx,
- const forward_list<_Tp, _Alloc>& __ly)
+ const forward_list<_Tp, _Alloc>& __ly)
{ return !(__lx == __ly); }
/// Based on operator<
template<typename _Tp, typename _Alloc>
inline bool
operator>(const forward_list<_Tp, _Alloc>& __lx,
- const forward_list<_Tp, _Alloc>& __ly)
+ const forward_list<_Tp, _Alloc>& __ly)
{ return (__ly < __lx); }
/// Based on operator<
template<typename _Tp, typename _Alloc>
inline bool
operator>=(const forward_list<_Tp, _Alloc>& __lx,
- const forward_list<_Tp, _Alloc>& __ly)
+ const forward_list<_Tp, _Alloc>& __ly)
{ return !(__lx < __ly); }
/// Based on operator<
template<typename _Tp, typename _Alloc>
inline bool
operator<=(const forward_list<_Tp, _Alloc>& __lx,
- const forward_list<_Tp, _Alloc>& __ly)
+ const forward_list<_Tp, _Alloc>& __ly)
{ return !(__ly < __lx); }
/// See std::forward_list::swap().
diff --git a/libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h b/libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h
index 4ef9da1edc7..c1b2da10765 100644
--- a/libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h
+++ b/libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h
@@ -40,7 +40,7 @@ namespace __gnu_profile
__log2(std::size_t __size)
{
for (int __bit_count = sizeof(std::size_t) - 1; __bit_count >= 0;
- -- __bit_count)
+ -- __bit_count)
if ((2 << __bit_count) & __size)
return __bit_count;
return 0;
@@ -48,7 +48,7 @@ namespace __gnu_profile
inline float
__map_insert_cost(std::size_t __size)
- { return (_GLIBCXX_PROFILE_DATA(__map_insert_cost_factor).__value
+ { return (_GLIBCXX_PROFILE_DATA(__map_insert_cost_factor).__value
* static_cast<float>(__log2(__size))); }
inline float
@@ -61,7 +61,7 @@ namespace __gnu_profile
{ return (_GLIBCXX_PROFILE_DATA(__map_find_cost_factor).__value
* static_cast<float>(__log2(__size))); }
- /** @brief A map-to-unordered_map instrumentation line in the
+ /** @brief A map-to-unordered_map instrumentation line in the
object table. */
class __map2umap_info
: public __object_info_base
@@ -70,9 +70,9 @@ namespace __gnu_profile
__map2umap_info()
: _M_insert(0), _M_erase(0), _M_find(0), _M_iterate(0),
_M_umap_cost(0.0), _M_map_cost(0.0), _M_valid(true) { }
-
+
__map2umap_info(__stack_t __stack)
- : __object_info_base(__stack), _M_insert(0), _M_erase(0), _M_find(0),
+ : __object_info_base(__stack), _M_insert(0), _M_erase(0), _M_find(0),
_M_iterate(0), _M_umap_cost(0.0), _M_map_cost(0.0), _M_valid(true) { }
virtual ~__map2umap_info() { }
@@ -108,32 +108,38 @@ namespace __gnu_profile
std::string
__advice() const
- { return "change std::map to std::unordered_map"; }
+ { return "prefer an unordered container"; }
void
__record_insert(std::size_t __size, std::size_t __count)
{
- _M_insert += __count;
- _M_map_cost += __count * __map_insert_cost(__size);
- _M_umap_cost
- += (__count
- * _GLIBCXX_PROFILE_DATA(__umap_insert_cost_factor).__value);
+ ++_M_insert;
+ if (__count)
+ {
+ _M_map_cost += __count * __map_insert_cost(__size);
+ _M_umap_cost
+ += (__count
+ * _GLIBCXX_PROFILE_DATA(__umap_insert_cost_factor).__value);
+ }
}
void
__record_erase(std::size_t __size, std::size_t __count)
{
- _M_erase += __count;
- _M_map_cost += __count * __map_erase_cost(__size);
- _M_umap_cost
- += (__count
- * _GLIBCXX_PROFILE_DATA(__umap_erase_cost_factor).__value);
+ ++_M_erase;
+ if (__count)
+ {
+ _M_map_cost += __count * __map_erase_cost(__size);
+ _M_umap_cost
+ += (__count
+ * _GLIBCXX_PROFILE_DATA(__umap_erase_cost_factor).__value);
+ }
}
void
__record_find(std::size_t __size)
{
- _M_find += 1;
+ ++_M_find;
_M_map_cost += __map_find_cost(__size);
_M_umap_cost += _GLIBCXX_PROFILE_DATA(__umap_find_cost_factor).__value;
}
@@ -165,9 +171,9 @@ namespace __gnu_profile
};
- /** @brief A map-to-unordered_map instrumentation line in the
+ /** @brief A map-to-unordered_map instrumentation line in the
stack table. */
- class __map2umap_stack_info
+ class __map2umap_stack_info
: public __map2umap_info
{
public:
@@ -177,12 +183,12 @@ namespace __gnu_profile
/** @brief Map-to-unordered_map instrumentation producer. */
class __trace_map2umap
- : public __trace_base<__map2umap_info, __map2umap_stack_info>
+ : public __trace_base<__map2umap_info, __map2umap_stack_info>
{
public:
__trace_map2umap()
: __trace_base<__map2umap_info, __map2umap_stack_info>()
- { __id = "map-to-unordered-map"; }
+ { __id = "ordered-to-unordered"; }
};
inline void
@@ -193,7 +199,7 @@ namespace __gnu_profile
__trace_map_to_unordered_map_report(FILE* __f,
__warning_vector_t& __warnings)
{
- if (_GLIBCXX_PROFILE_DATA(_S_map2umap))
+ if (_GLIBCXX_PROFILE_DATA(_S_map2umap))
{
_GLIBCXX_PROFILE_DATA(_S_map2umap)->__collect_warnings(__warnings);
_GLIBCXX_PROFILE_DATA(_S_map2umap)->__write(__f);
@@ -220,7 +226,7 @@ namespace __gnu_profile
}
inline void
- __trace_map_to_unordered_map_insert(const void* __obj,
+ __trace_map_to_unordered_map_insert(const void* __obj,
std::size_t __size, std::size_t __count)
{
if (!__profcxx_init())
@@ -234,13 +240,13 @@ namespace __gnu_profile
}
inline void
- __trace_map_to_unordered_map_erase(const void* __obj,
+ __trace_map_to_unordered_map_erase(const void* __obj,
std::size_t __size, std::size_t __count)
{
- if (!__profcxx_init())
+ if (!__profcxx_init())
return;
- __map2umap_info* __info
+ __map2umap_info* __info
= _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj);
if (__info)
@@ -268,7 +274,7 @@ namespace __gnu_profile
__map2umap_info* __info
= _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj);
-
+
if (__info)
__info->__record_iterate(__count);
}
diff --git a/libstdc++-v3/include/profile/iterator_tracker.h b/libstdc++-v3/include/profile/iterator_tracker.h
index df92c84295a..9b2aeab5e83 100644
--- a/libstdc++-v3/include/profile/iterator_tracker.h
+++ b/libstdc++-v3/include/profile/iterator_tracker.h
@@ -35,9 +35,8 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
namespace __profile
{
-
template<typename _Iterator, typename _Sequence>
- class __iterator_tracker
+ class __iterator_tracker
{
typedef __iterator_tracker _Self;
@@ -49,12 +48,12 @@ namespace __profile
typedef std::iterator_traits<_Iterator> _Traits;
public:
- typedef _Iterator _Base_iterator;
- typedef typename _Traits::iterator_category iterator_category;
- typedef typename _Traits::value_type value_type;
- typedef typename _Traits::difference_type difference_type;
- typedef typename _Traits::reference reference;
- typedef typename _Traits::pointer pointer;
+ typedef _Iterator _Base_iterator;
+ typedef typename _Traits::iterator_category iterator_category;
+ typedef typename _Traits::value_type value_type;
+ typedef typename _Traits::difference_type difference_type;
+ typedef typename _Traits::reference reference;
+ typedef typename _Traits::pointer pointer;
__iterator_tracker() _GLIBCXX_NOEXCEPT
: _M_current(), _M_ds(0) { }
@@ -67,7 +66,7 @@ namespace __profile
: _M_current(__x._M_current), _M_ds(__x._M_ds) { }
template<typename _MutableIterator>
- __iterator_tracker(const __iterator_tracker<_MutableIterator,
+ __iterator_tracker(const __iterator_tracker<_MutableIterator,
typename __gnu_cxx::__enable_if
<(std::__are_same<_MutableIterator, typename
_Sequence::iterator::_Base_iterator>::__value),
@@ -76,7 +75,7 @@ namespace __profile
_Iterator
base() const _GLIBCXX_NOEXCEPT { return _M_current; }
-
+
/**
* @brief Conversion to underlying non-debug iterator to allow
* better interaction with non-profile containers.
@@ -199,7 +198,7 @@ namespace __profile
template<typename _Iterator, typename _Sequence>
inline bool
operator!=(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
- const __iterator_tracker<_Iterator, _Sequence>& __rhs)
+ const __iterator_tracker<_Iterator, _Sequence>& __rhs)
_GLIBCXX_NOEXCEPT
{ return __lhs.base() != __rhs.base(); }
diff --git a/libstdc++-v3/include/profile/list b/libstdc++-v3/include/profile/list
index 87d99a0b93d..438b440108c 100644
--- a/libstdc++-v3/include/profile/list
+++ b/libstdc++-v3/include/profile/list
@@ -30,81 +30,109 @@
#define _GLIBCXX_PROFILE_LIST 1
#include <list>
-#include <profile/base.h>
-#include <profile/iterator_tracker.h>
+#include <profile/base.h>
+#include <profile/iterator_tracker.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
namespace __profile
{
+ template<typename _List>
+ class _List_profile
+ {
+ _List&
+ _M_conjure()
+ { return *static_cast<_List*>(this); }
+
+ public:
+ _List_profile() _GLIBCXX_NOEXCEPT
+ {
+ __profcxx_list_construct(&_M_conjure()); // list2slist
+ __profcxx_list_construct2(&_M_conjure()); // list2vector
+ }
+
+#if __cplusplus >= 201103L
+ _List_profile(const _List_profile&) noexcept
+ : _List_profile() { }
+ _List_profile(_List_profile&&) noexcept
+ : _List_profile() { }
+
+ _List_profile&
+ operator=(const _List_profile&) = default;
+ _List_profile&
+ operator=(_List_profile&&) = default;
+#endif
+
+ ~_List_profile()
+ {
+ __profcxx_list_destruct(&_M_conjure());
+ __profcxx_list_destruct2(&_M_conjure());
+ }
+ };
+
/** @brief List wrapper with performance instrumentation. */
-template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
+ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
class list
- : public _GLIBCXX_STD_C::list<_Tp, _Allocator>
+ : public _GLIBCXX_STD_C::list<_Tp, _Allocator>,
+ public _List_profile<list<_Tp, _Allocator> >
{
- typedef _GLIBCXX_STD_C::list<_Tp, _Allocator> _Base;
+ typedef _GLIBCXX_STD_C::list<_Tp, _Allocator> _Base;
public:
- typedef typename _Base::reference reference;
- typedef typename _Base::const_reference const_reference;
+ typedef typename _Base::reference reference;
+ typedef typename _Base::const_reference const_reference;
- typedef __iterator_tracker<typename _Base::iterator, list>
- iterator;
- typedef __iterator_tracker<typename _Base::const_iterator, list>
- const_iterator;
+ typedef __iterator_tracker<typename _Base::iterator, list>
+ iterator;
+ typedef __iterator_tracker<typename _Base::const_iterator, list>
+ const_iterator;
- typedef typename _Base::size_type size_type;
- typedef typename _Base::difference_type difference_type;
+ typedef typename _Base::size_type size_type;
+ typedef typename _Base::difference_type difference_type;
- typedef _Tp value_type;
- typedef _Allocator allocator_type;
- typedef typename _Base::pointer pointer;
- typedef typename _Base::const_pointer const_pointer;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef _Tp value_type;
+ typedef _Allocator allocator_type;
+ typedef typename _Base::pointer pointer;
+ typedef typename _Base::const_pointer const_pointer;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
// 23.2.2.1 construct/copy/destroy:
- list() _GLIBCXX_NOEXCEPT
- : _Base()
- {
- __profcxx_list_construct(this); // list2slist
- __profcxx_list_construct2(this); // list2vector
- }
+#if __cplusplus < 201103L
+ list() { }
+ list(const list& __x)
+ : _Base(__x) { }
+
+ ~list() { }
+#else
+ list() = default;
+ list(const list&) = default;
+ list(list&&) = default;
+ ~list() = default;
+
+ list(initializer_list<value_type> __l,
+ const allocator_type& __a = allocator_type())
+ : _Base(__l, __a) { }
+#endif
explicit
list(const _Allocator& __a) _GLIBCXX_NOEXCEPT
- : _Base(__a)
- {
- __profcxx_list_construct(this); // list2slist
- __profcxx_list_construct2(this); // list2vector
- }
+ : _Base(__a) { }
#if __cplusplus >= 201103L
explicit
list(size_type __n)
- : _Base(__n)
- {
- __profcxx_list_construct(this);
- __profcxx_list_construct2(this);
- }
+ : _Base(__n) { }
list(size_type __n, const _Tp& __value,
const _Allocator& __a = _Allocator())
- : _Base(__n, __value, __a)
- {
- __profcxx_list_construct(this);
- __profcxx_list_construct2(this);
- }
+ : _Base(__n, __value, __a) { }
#else
explicit
list(size_type __n, const _Tp& __value = _Tp(),
const _Allocator& __a = _Allocator())
- : _Base(__n, __value, __a)
- {
- __profcxx_list_construct(this);
- __profcxx_list_construct2(this);
- }
+ : _Base(__n, __value, __a) { }
#endif
#if __cplusplus >= 201103L
@@ -115,91 +143,33 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
#endif
list(_InputIterator __first, _InputIterator __last,
const _Allocator& __a = _Allocator())
- : _Base(__first, __last, __a)
- {
- __profcxx_list_construct(this);
- __profcxx_list_construct2(this);
- }
-
- list(const list& __x)
- : _Base(__x)
- {
- __profcxx_list_construct(this);
- __profcxx_list_construct2(this);
- }
+ : _Base(__first, __last, __a) { }
list(const _Base& __x)
- : _Base(__x)
- {
- __profcxx_list_construct(this);
- __profcxx_list_construct2(this);
- }
-
-#if __cplusplus >= 201103L
- list(list&& __x) noexcept
- : _Base(std::move(__x))
- {
- __profcxx_list_construct(this);
- __profcxx_list_construct2(this);
- }
-
- list(initializer_list<value_type> __l,
- const allocator_type& __a = allocator_type())
- : _Base(__l, __a) { }
-#endif
-
- ~list() _GLIBCXX_NOEXCEPT
- {
- __profcxx_list_destruct(this);
- __profcxx_list_destruct2(this);
- }
+ : _Base(__x) { }
+#if __cplusplus < 201103L
list&
operator=(const list& __x)
{
- static_cast<_Base&>(*this) = __x;
+ _M_base() = __x;
return *this;
}
+#else
+ list&
+ operator=(const list&) = default;
-#if __cplusplus >= 201103L
list&
- operator=(list&& __x)
- {
- // NB: DR 1204.
- // NB: DR 675.
- this->clear();
- this->swap(__x);
- return *this;
- }
+ operator=(list&&) = default;
list&
operator=(initializer_list<value_type> __l)
{
- static_cast<_Base&>(*this) = __l;
+ _M_base() = __l;
return *this;
}
-
- void
- assign(initializer_list<value_type> __l)
- { _Base::assign(__l); }
#endif
-#if __cplusplus >= 201103L
- template<typename _InputIterator,
- typename = std::_RequireInputIter<_InputIterator>>
-#else
- template<class _InputIterator>
-#endif
- void
- assign(_InputIterator __first, _InputIterator __last)
- { _Base::assign(__first, __last); }
-
- void
- assign(size_type __n, const _Tp& __t)
- { _Base::assign(__n, __t); }
-
- using _Base::get_allocator;
-
// iterators:
iterator
begin() _GLIBCXX_NOEXCEPT
@@ -212,29 +182,29 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
iterator
end() _GLIBCXX_NOEXCEPT
{
- __profcxx_list_rewind(this);
- return iterator(_Base::end(), this);
+ __profcxx_list_rewind(this);
+ return iterator(_Base::end(), this);
}
const_iterator
end() const _GLIBCXX_NOEXCEPT
{
- __profcxx_list_rewind(this);
- return const_iterator(_Base::end(), this);
+ __profcxx_list_rewind(this);
+ return const_iterator(_Base::end(), this);
}
reverse_iterator
rbegin() _GLIBCXX_NOEXCEPT
{
- __profcxx_list_rewind(this);
- return reverse_iterator(end());
+ __profcxx_list_rewind(this);
+ return reverse_iterator(end());
}
const_reverse_iterator
rbegin() const _GLIBCXX_NOEXCEPT
- {
- __profcxx_list_rewind(this);
- return const_reverse_iterator(end());
+ {
+ __profcxx_list_rewind(this);
+ return const_reverse_iterator(end());
}
reverse_iterator
@@ -248,11 +218,11 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
#if __cplusplus >= 201103L
const_iterator
cbegin() const noexcept
- { return const_iterator(_Base::begin(), this); }
+ { return const_iterator(_Base::cbegin(), this); }
const_iterator
cend() const noexcept
- { return const_iterator(_Base::end(), this); }
+ { return const_iterator(_Base::cend(), this); }
const_reverse_iterator
crbegin() const noexcept
@@ -264,44 +234,17 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
#endif
// 23.2.2.2 capacity:
- using _Base::empty;
- using _Base::size;
- using _Base::max_size;
-
-#if __cplusplus >= 201103L
- void
- resize(size_type __sz)
- { _Base::resize(__sz); }
-
- void
- resize(size_type __sz, const _Tp& __c)
- { _Base::resize(__sz, __c); }
-#else
- void
- resize(size_type __sz, _Tp __c = _Tp())
- { _Base::resize(__sz, __c); }
-#endif
-
- // element access:
- reference
- front() _GLIBCXX_NOEXCEPT
- { return _Base::front(); }
-
- const_reference
- front() const _GLIBCXX_NOEXCEPT
- { return _Base::front(); }
-
reference
back() _GLIBCXX_NOEXCEPT
{
- __profcxx_list_rewind(this);
+ __profcxx_list_rewind(this);
return _Base::back();
}
const_reference
back() const _GLIBCXX_NOEXCEPT
{
- __profcxx_list_rewind(this);
+ __profcxx_list_rewind(this);
return _Base::back();
}
@@ -309,44 +252,32 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
void
push_front(const value_type& __x)
{
- __profcxx_list_invalid_operator(this);
- __profcxx_list_operation(this);
- _Base::push_front(__x);
+ __profcxx_list_invalid_operator(this);
+ __profcxx_list_operation(this);
+ _Base::push_front(__x);
}
-#if __cplusplus >= 201103L
- using _Base::emplace_front;
-#endif
-
void
pop_front() _GLIBCXX_NOEXCEPT
{
- __profcxx_list_operation(this);
+ __profcxx_list_operation(this);
_Base::pop_front();
}
- using _Base::push_back;
-
-#if __cplusplus >= 201103L
- using _Base::emplace_back;
-#endif
-
void
pop_back() _GLIBCXX_NOEXCEPT
{
- iterator __victim = end();
- --__victim;
_Base::pop_back();
- __profcxx_list_rewind(this);
+ __profcxx_list_rewind(this);
}
#if __cplusplus >= 201103L
template<typename... _Args>
- iterator
- emplace(const_iterator __position, _Args&&... __args)
+ iterator
+ emplace(const_iterator __position, _Args&&... __args)
{
return iterator(_Base::emplace(__position.base(),
- std::forward<_Args>(__args)...),
+ std::forward<_Args>(__args)...),
this);
}
#endif
@@ -358,24 +289,24 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
insert(iterator __position, const _Tp& __x)
#endif
{
- _M_profile_insert(this, __position, size());
- return iterator(_Base::insert(__position.base(), __x), this);
+ _M_profile_insert(this, __position, this->size());
+ return iterator(_Base::insert(__position.base(), __x), this);
}
#if __cplusplus >= 201103L
iterator
insert(const_iterator __position, _Tp&& __x)
{
- _M_profile_insert(this, __position, size());
- return iterator(_Base::emplace(__position.base(), std::move(__x)),
- this);
+ _M_profile_insert(this, __position, this->size());
+ return iterator(_Base::emplace(__position.base(), std::move(__x)),
+ this);
}
iterator
insert(const_iterator __position, initializer_list<value_type> __l)
{
- _M_profile_insert(this, __position, size());
- return iterator(_Base::insert(__position.base(), __l), this);
+ _M_profile_insert(this, __position, this->size());
+ return iterator(_Base::insert(__position.base(), __l), this);
}
#endif
@@ -383,14 +314,14 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
iterator
insert(const_iterator __position, size_type __n, const _Tp& __x)
{
- _M_profile_insert(this, __position, size());
+ _M_profile_insert(this, __position, this->size());
return iterator(_Base::insert(__position.base(), __n, __x), this);
}
#else
void
insert(iterator __position, size_type __n, const _Tp& __x)
{
- _M_profile_insert(this, __position, size());
+ _M_profile_insert(this, __position, this->size());
_Base::insert(__position.base(), __n, __x);
}
#endif
@@ -399,20 +330,20 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
iterator
- insert(const_iterator __position, _InputIterator __first,
+ insert(const_iterator __position, _InputIterator __first,
_InputIterator __last)
{
- _M_profile_insert(this, __position, size());
+ _M_profile_insert(this, __position, this->size());
return iterator(_Base::insert(__position.base(), __first, __last),
this);
}
#else
template<class _InputIterator>
- void
- insert(iterator __position, _InputIterator __first,
+ void
+ insert(iterator __position, _InputIterator __first,
_InputIterator __last)
{
- _M_profile_insert(this, __position, size());
+ _M_profile_insert(this, __position, this->size());
_Base::insert(__position.base(), __first, __last);
}
#endif
@@ -439,12 +370,11 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
void
swap(list& __x)
+#if __cplusplus >= 201103L
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
+#endif
{ _Base::swap(__x); }
- void
- clear() _GLIBCXX_NOEXCEPT
- { _Base::clear(); }
-
// 23.2.2.4 list operations:
void
#if __cplusplus >= 201103L
@@ -488,9 +418,6 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
iterator __last)
#endif
{
- // We used to perform the splice_alloc check: not anymore, redundant
- // after implementing the relevant bits of N1599.
-
_Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()),
__first.base(), __last.base());
}
@@ -515,12 +442,12 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
}
template<class _Predicate>
- void
- remove_if(_Predicate __pred)
- {
+ void
+ remove_if(_Predicate __pred)
+ {
for (iterator __x = begin(); __x != end(); )
{
- __profcxx_list_operation(this);
+ __profcxx_list_operation(this);
if (__pred(*__x))
__x = erase(__x);
else
@@ -538,7 +465,7 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
iterator __next = __first;
while (++__next != __last)
{
- __profcxx_list_operation(this);
+ __profcxx_list_operation(this);
if (*__first == *__next)
erase(__next);
else
@@ -548,9 +475,9 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
}
template<class _BinaryPredicate>
- void
- unique(_BinaryPredicate __binary_pred)
- {
+ void
+ unique(_BinaryPredicate __binary_pred)
+ {
iterator __first = begin();
iterator __last = end();
if (__first == __last)
@@ -558,7 +485,7 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
iterator __next = __first;
while (++__next != __last)
{
- __profcxx_list_operation(this);
+ __profcxx_list_operation(this);
if (__binary_pred(*__first, *__next))
erase(__next);
else
@@ -573,12 +500,7 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
#else
merge(list& __x)
#endif
- {
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 300. list::merge() specification incomplete
- if (this != &__x)
- { _Base::merge(_GLIBCXX_MOVE(__x._M_base())); }
- }
+ { _Base::merge(_GLIBCXX_MOVE(__x._M_base())); }
#if __cplusplus >= 201103L
void
@@ -587,63 +509,49 @@ template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
#endif
template<class _Compare>
- void
+ void
#if __cplusplus >= 201103L
- merge(list&& __x, _Compare __comp)
+ merge(list&& __x, _Compare __comp)
#else
- merge(list& __x, _Compare __comp)
+ merge(list& __x, _Compare __comp)
#endif
- {
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 300. list::merge() specification incomplete
- if (this != &__x)
- { _Base::merge(_GLIBCXX_MOVE(__x._M_base()), __comp); }
- }
+ { _Base::merge(_GLIBCXX_MOVE(__x._M_base()), __comp); }
#if __cplusplus >= 201103L
template<typename _Compare>
- void
- merge(list& __x, _Compare __comp)
- { this->merge(std::move(__x), __comp); }
+ void
+ merge(list& __x, _Compare __comp)
+ { this->merge(std::move(__x), __comp); }
#endif
- void
- sort() { _Base::sort(); }
-
- template<typename _StrictWeakOrdering>
- void
- sort(_StrictWeakOrdering __pred) { _Base::sort(__pred); }
-
- using _Base::reverse;
-
_Base&
- _M_base() _GLIBCXX_NOEXCEPT { return *this; }
+ _M_base() _GLIBCXX_NOEXCEPT { return *this; }
const _Base&
- _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
+ _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
void _M_profile_find() const
{ }
- void _M_profile_iterate(int __rewind = 0) const
+ void _M_profile_iterate(int __rewind = 0) const
{
- __profcxx_list_operation(this);
- __profcxx_list_iterate(this);
- if (__rewind)
- __profcxx_list_rewind(this);
+ __profcxx_list_operation(this);
+ __profcxx_list_iterate(this);
+ if (__rewind)
+ __profcxx_list_rewind(this);
}
private:
size_type
_M_profile_insert(void* obj, const_iterator __pos, size_type __size)
{
- size_type __shift = 0;
- typename _Base::const_iterator __it = __pos.base();
- for (; __it != _Base::end(); ++__it)
- __shift++;
- __profcxx_list_rewind(this);
- __profcxx_list_operation(this);
- __profcxx_list_insert(this, __shift, __size);
+ size_type __shift = 0;
+ typename _Base::const_iterator __it = __pos.base();
+ for (; __it != _Base::end(); ++__it)
+ __shift++;
+ __profcxx_list_rewind(this);
+ __profcxx_list_operation(this);
+ __profcxx_list_insert(this, __shift, __size);
}
};
diff --git a/libstdc++-v3/include/profile/map.h b/libstdc++-v3/include/profile/map.h
index 6a3160b8e6b..cc0f5bb05dc 100644
--- a/libstdc++-v3/include/profile/map.h
+++ b/libstdc++-v3/include/profile/map.h
@@ -28,8 +28,8 @@
#ifndef _GLIBCXX_PROFILE_MAP_H
#define _GLIBCXX_PROFILE_MAP_H 1
-#include <utility>
#include <profile/base.h>
+#include <profile/ordered_base.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -39,44 +39,47 @@ namespace __profile
template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > >
class map
- : public _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator>
+ : public _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator>,
+ public _Ordered_profile<map<_Key, _Tp, _Compare, _Allocator> >
{
typedef _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator> _Base;
-#if __cplusplus >= 201103L
- typedef __gnu_cxx::__alloc_traits<_Allocator> _Alloc_traits;
-#endif
-
public:
// types:
- typedef _Key key_type;
- typedef _Tp mapped_type;
- typedef std::pair<const _Key, _Tp> value_type;
- typedef _Compare key_compare;
- typedef _Allocator allocator_type;
- typedef typename _Base::reference reference;
- typedef typename _Base::const_reference const_reference;
-
- typedef typename _Base::iterator iterator;
- typedef typename _Base::const_iterator const_iterator;
- typedef typename _Base::size_type size_type;
- typedef typename _Base::difference_type difference_type;
- typedef typename _Base::pointer pointer;
- typedef typename _Base::const_pointer const_pointer;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef _Key key_type;
+ typedef _Tp mapped_type;
+ typedef typename _Base::value_type value_type;
+ typedef _Compare key_compare;
+ typedef typename _Base::reference reference;
+ typedef typename _Base::const_reference const_reference;
+
+ typedef typename _Base::iterator iterator;
+ typedef typename _Base::const_iterator const_iterator;
+ typedef typename _Base::size_type size_type;
+ typedef typename _Base::difference_type difference_type;
+ typedef typename _Base::reverse_iterator reverse_iterator;
+ typedef typename _Base::const_reverse_iterator const_reverse_iterator;
// 23.3.1.1 construct/copy/destroy:
+#if __cplusplus < 201103L
map()
- : _Base()
- { __profcxx_map_to_unordered_map_construct(this); }
+ : _Base() { }
+ map(const map& __x)
+ : _Base(__x) { }
+ ~map()
+ { }
+#else
+ map() = default;
+ map(const map&) = default;
+ map(map&&) = default;
+ ~map() = default;
+#endif
explicit
map(const _Compare& __comp,
const _Allocator& __a = _Allocator())
- : _Base(__comp, __a)
- { __profcxx_map_to_unordered_map_construct(this); }
+ : _Base(__comp, __a) { }
#if __cplusplus >= 201103L
template<typename _InputIterator,
@@ -84,61 +87,40 @@ namespace __profile
#else
template<typename _InputIterator>
#endif
- map(_InputIterator __first, _InputIterator __last,
+ map(_InputIterator __first, _InputIterator __last,
const _Compare& __comp = _Compare(),
const _Allocator& __a = _Allocator())
- : _Base(__first, __last, __comp, __a)
- { __profcxx_map_to_unordered_map_construct(this); }
-
- map(const map& __x)
- : _Base(__x)
- { __profcxx_map_to_unordered_map_construct(this); }
+ : _Base(__first, __last, __comp, __a) { }
map(const _Base& __x)
- : _Base(__x)
- { __profcxx_map_to_unordered_map_construct(this); }
+ : _Base(__x) { }
#if __cplusplus >= 201103L
- map(map&& __x)
- noexcept(is_nothrow_copy_constructible<_Compare>::value)
- : _Base(std::move(__x))
- { __profcxx_map_to_unordered_map_construct(this); }
-
map(initializer_list<value_type> __l,
const _Compare& __c = _Compare(),
- const allocator_type& __a = allocator_type())
- : _Base(__l, __c, __a)
- { __profcxx_map_to_unordered_map_construct(this); }
+ const _Allocator& __a = _Allocator())
+ : _Base(__l, __c, __a) { }
explicit
- map(const allocator_type& __a)
- : _Base(__a)
- { __profcxx_map_to_unordered_map_construct(this); }
+ map(const _Allocator& __a)
+ : _Base(__a) { }
- map(const map& __x, const allocator_type& __a)
- : _Base(__x, __a)
- { __profcxx_map_to_unordered_map_construct(this); }
+ map(const map& __x, const _Allocator& __a)
+ : _Base(__x, __a) { }
- map(map&& __x, const allocator_type& __a)
- noexcept(is_nothrow_copy_constructible<_Compare>::value
- && _Alloc_traits::_S_always_equal())
- : _Base(std::move(__x), __a)
- { __profcxx_map_to_unordered_map_construct(this); }
+ map(map&& __x, const _Allocator& __a)
+ noexcept( noexcept(_Base(std::move(__x), __a)) )
+ : _Base(std::move(__x), __a) { }
- map(initializer_list<value_type> __l, const allocator_type& __a)
- : _Base(__l, __a)
- { __profcxx_map_to_unordered_map_construct(this); }
+ map(initializer_list<value_type> __l, const _Allocator& __a)
+ : _Base(__l, __a) { }
template<typename _InputIterator>
- map(_InputIterator __first, _InputIterator __last,
- const allocator_type& __a)
- : _Base(__first, __last, __a)
- { __profcxx_map_to_unordered_map_construct(this); }
+ map(_InputIterator __first, _InputIterator __last,
+ const _Allocator& __a)
+ : _Base(__first, __last, __a) { }
#endif
- ~map() _GLIBCXX_NOEXCEPT
- { __profcxx_map_to_unordered_map_destruct(this); }
-
#if __cplusplus < 201103L
map&
operator=(const map& __x)
@@ -161,113 +143,79 @@ namespace __profile
}
#endif
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 133. map missing get_allocator()
- using _Base::get_allocator;
-
- // iterators:
- iterator
- begin() _GLIBCXX_NOEXCEPT
- { return _Base::begin(); }
-
- const_iterator
- begin() const _GLIBCXX_NOEXCEPT
- { return _Base::begin(); }
-
- iterator
- end() _GLIBCXX_NOEXCEPT
- { return _Base::end(); }
-
- const_iterator
- end() const _GLIBCXX_NOEXCEPT
- { return _Base::end(); }
-
reverse_iterator
rbegin() _GLIBCXX_NOEXCEPT
- {
- __profcxx_map_to_unordered_map_invalidate(this);
- return reverse_iterator(end());
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rbegin();
}
const_reverse_iterator
rbegin() const _GLIBCXX_NOEXCEPT
{
- __profcxx_map_to_unordered_map_invalidate(this);
- return const_reverse_iterator(end());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rbegin();
}
reverse_iterator
rend() _GLIBCXX_NOEXCEPT
{
- __profcxx_map_to_unordered_map_invalidate(this);
- return reverse_iterator(begin());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rend();
}
const_reverse_iterator
rend() const _GLIBCXX_NOEXCEPT
{
- __profcxx_map_to_unordered_map_invalidate(this);
- return const_reverse_iterator(begin());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rend();
}
#if __cplusplus >= 201103L
- const_iterator
- cbegin() const noexcept
- { return const_iterator(_Base::begin()); }
-
- const_iterator
- cend() const noexcept
- { return const_iterator(_Base::end()); }
-
const_reverse_iterator
crbegin() const noexcept
{
- __profcxx_map_to_unordered_map_invalidate(this);
- return const_reverse_iterator(end());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::crbegin();
}
const_reverse_iterator
crend() const noexcept
{
- __profcxx_map_to_unordered_map_invalidate(this);
- return const_reverse_iterator(begin());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::crend();
}
#endif
- // capacity:
- using _Base::empty;
- using _Base::size;
- using _Base::max_size;
-
// 23.3.1.2 element access:
mapped_type&
operator[](const key_type& __k)
{
- __profcxx_map_to_unordered_map_find(this, size());
- return _Base::operator[](__k);
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::operator[](__k);
}
#if __cplusplus >= 201103L
mapped_type&
operator[](key_type&& __k)
{
- __profcxx_map_to_unordered_map_find(this, size());
- return _Base::operator[](std::move(__k));
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::operator[](std::move(__k));
}
#endif
mapped_type&
at(const key_type& __k)
{
- __profcxx_map_to_unordered_map_find(this, size());
- return _Base::at(__k);
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::at(__k);
}
const mapped_type&
at(const key_type& __k) const
{
- __profcxx_map_to_unordered_map_find(this, size());
- return _Base::at(__k);
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::at(__k);
}
// modifiers:
@@ -276,21 +224,20 @@ namespace __profile
std::pair<iterator, bool>
emplace(_Args&&... __args)
{
- __profcxx_map_to_unordered_map_insert(this, size(), 1);
- auto __res = _Base::emplace(std::forward<_Args>(__args)...);
- return std::pair<iterator, bool>(iterator(__res.first),
- __res.second);
+ // The cost is the same whether or not the element is inserted so we
+ // always report insertion of 1 element.
+ __profcxx_map_to_unordered_map_insert(this, this->size(), 1);
+ return _Base::emplace(std::forward<_Args>(__args)...);
}
template<typename... _Args>
iterator
emplace_hint(const_iterator __pos, _Args&&... __args)
{
- size_type size_before = size();
- auto __res = _Base::emplace_hint(__pos,
- std::forward<_Args>(__args)...);
+ auto size_before = this->size();
+ auto __res = _Base::emplace_hint(__pos, std::forward<_Args>(__args)...);
__profcxx_map_to_unordered_map_insert(this, size_before,
- size() - size_before);
+ _M_hint_used(__pos, __res) ? 0 : 1);
return __res;
}
#endif
@@ -298,67 +245,56 @@ namespace __profile
std::pair<iterator, bool>
insert(const value_type& __x)
{
- __profcxx_map_to_unordered_map_insert(this, size(), 1);
- typedef typename _Base::iterator _Base_iterator;
- std::pair<_Base_iterator, bool> __res = _Base::insert(__x);
- return std::pair<iterator, bool>(iterator(__res.first),
- __res.second);
+ __profcxx_map_to_unordered_map_insert(this, this->size(), 1);
+ return _Base::insert(__x);
}
#if __cplusplus >= 201103L
template<typename _Pair, typename = typename
std::enable_if<std::is_constructible<value_type,
_Pair&&>::value>::type>
- std::pair<iterator, bool>
- insert(_Pair&& __x)
- {
- __profcxx_map_to_unordered_map_insert(this, size(), 1);
- typedef typename _Base::iterator _Base_iterator;
- std::pair<_Base_iterator, bool> __res
- = _Base::insert(std::forward<_Pair>(__x));
- return std::pair<iterator, bool>(iterator(__res.first),
- __res.second);
+ std::pair<iterator, bool>
+ insert(_Pair&& __x)
+ {
+ __profcxx_map_to_unordered_map_insert(this, this->size(), 1);
+ return _Base::insert(std::forward<_Pair>(__x));
}
#endif
#if __cplusplus >= 201103L
void
insert(std::initializer_list<value_type> __list)
- {
- size_type size_before = size();
- _Base::insert(__list);
- __profcxx_map_to_unordered_map_insert(this, size_before,
- size() - size_before);
- }
+ { insert(__list.begin(), __list.end()); }
#endif
iterator
#if __cplusplus >= 201103L
- insert(const_iterator __position, const value_type& __x)
+ insert(const_iterator __pos, const value_type& __x)
#else
- insert(iterator __position, const value_type& __x)
+ insert(iterator __pos, const value_type& __x)
#endif
{
- size_type size_before = size();
- iterator __i = iterator(_Base::insert(__position, __x));
- __profcxx_map_to_unordered_map_insert(this, size_before,
- size() - size_before);
- return __i;
+ size_type size_before = this->size();
+ iterator __res = _Base::insert(__pos, __x);
+
+ __profcxx_map_to_unordered_map_insert(this, size_before,
+ _M_hint_used(__pos, __res) ? 0 : 1);
+ return __res;
}
#if __cplusplus >= 201103L
template<typename _Pair, typename = typename
std::enable_if<std::is_constructible<value_type,
_Pair&&>::value>::type>
- iterator
- insert(const_iterator __position, _Pair&& __x)
- {
- size_type size_before = size();
- iterator __i
- = iterator(_Base::insert(__position, std::forward<_Pair>(__x)));
- __profcxx_map_to_unordered_map_insert(this, size_before,
- size() - size_before);
- return __i;
+ iterator
+ insert(const_iterator __pos, _Pair&& __x)
+ {
+ size_type size_before = this->size();
+ auto __res = _Base::insert(__pos, std::forward<_Pair>(__x));
+
+ __profcxx_map_to_unordered_map_insert(this, size_before,
+ _M_hint_used(__pos, __res) ? 0 : 1);
+ return __res;
}
#endif
@@ -368,151 +304,163 @@ namespace __profile
#else
template<typename _InputIterator>
#endif
- void
- insert(_InputIterator __first, _InputIterator __last)
- {
- size_type size_before = size();
- _Base::insert(__first, __last);
- __profcxx_map_to_unordered_map_insert(this, size_before,
- size() - size_before);
+ void
+ insert(_InputIterator __first, _InputIterator __last)
+ {
+ for (; __first != __last; ++__first)
+ insert(*__first);
}
#if __cplusplus >= 201103L
iterator
erase(const_iterator __position)
{
- iterator __i = _Base::erase(__position);
- __profcxx_map_to_unordered_map_erase(this, size(), 1);
- return __i;
+ __profcxx_map_to_unordered_map_erase(this, this->size(), 1);
+ return _Base::erase(__position);
}
iterator
erase(iterator __position)
- { return erase(const_iterator(__position)); }
+ {
+ __profcxx_map_to_unordered_map_erase(this, this->size(), 1);
+ return _Base::erase(__position);
+ }
#else
void
erase(iterator __position)
{
+ __profcxx_map_to_unordered_map_erase(this, this->size(), 1);
_Base::erase(__position);
- __profcxx_map_to_unordered_map_erase(this, size(), 1);
}
#endif
size_type
erase(const key_type& __x)
{
- iterator __victim = find(__x);
- if (__victim == end())
- return 0;
- else
- {
- _Base::erase(__victim);
- return 1;
- }
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_erase(this, this->size(), 1);
+ return _Base::erase(__x);
}
#if __cplusplus >= 201103L
iterator
erase(const_iterator __first, const_iterator __last)
- { return iterator(_Base::erase(__first, __last)); }
+ {
+ if (__first != __last)
+ {
+ iterator __ret;
+ for (; __first != __last;)
+ __ret = erase(__first++);
+ return __ret;
+ }
+ else
+ return _Base::erase(__first, __last);
+ }
#else
void
erase(iterator __first, iterator __last)
- { _Base::erase(__first, __last); }
+ {
+ for (; __first != __last;)
+ erase(__first++);
+ }
#endif
void
swap(map& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
{ _Base::swap(__x); }
- void
- clear() _GLIBCXX_NOEXCEPT
- { this->erase(begin(), end()); }
-
- // observers:
- using _Base::key_comp;
- using _Base::value_comp;
-
// 23.3.1.3 map operations:
iterator
find(const key_type& __x)
{
- __profcxx_map_to_unordered_map_find(this, size());
- return iterator(_Base::find(__x));
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::find(__x);
}
const_iterator
find(const key_type& __x) const
{
- __profcxx_map_to_unordered_map_find(this, size());
- return const_iterator(_Base::find(__x));
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::find(__x);
}
size_type
count(const key_type& __x) const
{
- __profcxx_map_to_unordered_map_find(this, size());
- return _Base::count(__x);
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::count(__x);
}
iterator
lower_bound(const key_type& __x)
- {
- __profcxx_map_to_unordered_map_invalidate(this);
- return iterator(_Base::lower_bound(__x));
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::lower_bound(__x);
}
const_iterator
lower_bound(const key_type& __x) const
- {
- __profcxx_map_to_unordered_map_invalidate(this);
- return const_iterator(_Base::lower_bound(__x));
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::lower_bound(__x);
}
iterator
upper_bound(const key_type& __x)
- {
- __profcxx_map_to_unordered_map_invalidate(this);
- return iterator(_Base::upper_bound(__x));
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::upper_bound(__x);
}
const_iterator
upper_bound(const key_type& __x) const
- {
- __profcxx_map_to_unordered_map_invalidate(this);
- return const_iterator(_Base::upper_bound(__x));
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::upper_bound(__x);
}
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
- typedef typename _Base::iterator _Base_iterator;
- std::pair<_Base_iterator, _Base_iterator> __res =
- _Base::equal_range(__x);
- return std::make_pair(iterator(__res.first),
- iterator(__res.second));
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::equal_range(__x);
}
std::pair<const_iterator,const_iterator>
equal_range(const key_type& __x) const
{
- __profcxx_map_to_unordered_map_find(this, size());
- typedef typename _Base::const_iterator _Base_const_iterator;
- std::pair<_Base_const_iterator, _Base_const_iterator> __res =
- _Base::equal_range(__x);
- return std::make_pair(const_iterator(__res.first),
- const_iterator(__res.second));
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::equal_range(__x);
}
- _Base&
- _M_base() _GLIBCXX_NOEXCEPT { return *this; }
+ _Base&
+ _M_base() _GLIBCXX_NOEXCEPT { return *this; }
const _Base&
- _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
-
+ _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
+
+ private:
+ /** If hint is used we consider that the map and unordered_map
+ * operations have equivalent insertion cost so we do not update metrics
+ * about it.
+ * Note that to find out if hint has been used is libstdc++
+ * implementation dependent.
+ */
+ bool
+ _M_hint_used(const_iterator __hint, iterator __res)
+ {
+ return (__hint == __res
+ || (__hint == this->end() && ++__res == this->end())
+ || (__hint != this->end() && (++__hint == __res
+ || ++__res == --__hint)));
+ }
};
template<typename _Key, typename _Tp,
@@ -520,10 +468,10 @@ namespace __profile
inline bool
operator==(const map<_Key, _Tp, _Compare, _Allocator>& __lhs,
const map<_Key, _Tp, _Compare, _Allocator>& __rhs)
- {
+ {
__profcxx_map_to_unordered_map_invalidate(&__lhs);
__profcxx_map_to_unordered_map_invalidate(&__rhs);
- return __lhs._M_base() == __rhs._M_base();
+ return __lhs._M_base() == __rhs._M_base();
}
template<typename _Key, typename _Tp,
@@ -531,10 +479,10 @@ namespace __profile
inline bool
operator!=(const map<_Key, _Tp, _Compare, _Allocator>& __lhs,
const map<_Key, _Tp, _Compare, _Allocator>& __rhs)
- {
+ {
__profcxx_map_to_unordered_map_invalidate(&__lhs);
__profcxx_map_to_unordered_map_invalidate(&__rhs);
- return __lhs._M_base() != __rhs._M_base();
+ return __lhs._M_base() != __rhs._M_base();
}
template<typename _Key, typename _Tp,
@@ -545,7 +493,7 @@ namespace __profile
{
__profcxx_map_to_unordered_map_invalidate(&__lhs);
__profcxx_map_to_unordered_map_invalidate(&__rhs);
- return __lhs._M_base() < __rhs._M_base();
+ return __lhs._M_base() < __rhs._M_base();
}
template<typename _Key, typename _Tp,
diff --git a/libstdc++-v3/include/profile/multimap.h b/libstdc++-v3/include/profile/multimap.h
index 5ba5355ec55..3d25b6e56a6 100644
--- a/libstdc++-v3/include/profile/multimap.h
+++ b/libstdc++-v3/include/profile/multimap.h
@@ -29,7 +29,8 @@
#ifndef _GLIBCXX_PROFILE_MULTIMAP_H
#define _GLIBCXX_PROFILE_MULTIMAP_H 1
-#include <utility>
+#include <profile/base.h>
+#include <profile/ordered_base.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -39,38 +40,44 @@ namespace __profile
template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > >
class multimap
- : public _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator>
+ : public _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator>,
+ public _Ordered_profile<map<_Key, _Tp, _Compare, _Allocator> >
{
typedef _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator> _Base;
-#if __cplusplus >= 201103L
- typedef __gnu_cxx::__alloc_traits<_Allocator> _Alloc_traits;
-#endif
-
public:
// types:
- typedef _Key key_type;
- typedef _Tp mapped_type;
- typedef std::pair<const _Key, _Tp> value_type;
- typedef _Compare key_compare;
- typedef _Allocator allocator_type;
- typedef typename _Base::reference reference;
- typedef typename _Base::const_reference const_reference;
-
- typedef typename _Base::iterator iterator;
- typedef typename _Base::const_iterator const_iterator;
- typedef typename _Base::reverse_iterator reverse_iterator;
- typedef typename _Base::const_reverse_iterator const_reverse_iterator;
-
- typedef typename _Base::size_type size_type;
- typedef typename _Base::difference_type difference_type;
- typedef typename _Base::pointer pointer;
- typedef typename _Base::const_pointer const_pointer;
+ typedef _Key key_type;
+ typedef _Tp mapped_type;
+ typedef std::pair<const _Key, _Tp> value_type;
+ typedef _Compare key_compare;
+ typedef typename _Base::reference reference;
+ typedef typename _Base::const_reference const_reference;
+
+ typedef typename _Base::iterator iterator;
+ typedef typename _Base::const_iterator const_iterator;
+ typedef typename _Base::reverse_iterator reverse_iterator;
+ typedef typename _Base::const_reverse_iterator const_reverse_iterator;
+
+ typedef typename _Base::size_type size_type;
+ typedef typename _Base::difference_type difference_type;
+ typedef typename _Base::pointer pointer;
+ typedef typename _Base::const_pointer const_pointer;
// 23.3.1.1 construct/copy/destroy:
+#if __cplusplus < 201103L
multimap()
: _Base() { }
+ multimap(const multimap& __x)
+ : _Base(__x) { }
+ ~multimap() { }
+#else
+ multimap() = default;
+ multimap(const multimap&) = default;
+ multimap(multimap&&) = default;
+ ~multimap() = default;
+#endif
explicit multimap(const _Compare& __comp,
const _Allocator& __a = _Allocator())
@@ -82,49 +89,40 @@ namespace __profile
#else
template<typename _InputIterator>
#endif
- multimap(_InputIterator __first, _InputIterator __last,
- const _Compare& __comp = _Compare(),
- const _Allocator& __a = _Allocator())
- : _Base(__first, __last, __comp, __a) { }
-
-#if __cplusplus < 201103L
- multimap(const multimap& __x)
- : _Base(__x) { }
-#else
- multimap(const multimap&) = default;
- multimap(multimap&&) = default;
+ multimap(_InputIterator __first, _InputIterator __last,
+ const _Compare& __comp = _Compare(),
+ const _Allocator& __a = _Allocator())
+ : _Base(__first, __last, __comp, __a) { }
+#if __cplusplus >= 201103L
multimap(initializer_list<value_type> __l,
const _Compare& __c = _Compare(),
- const allocator_type& __a = allocator_type())
+ const _Allocator& __a = _Allocator())
: _Base(__l, __c, __a) { }
explicit
- multimap(const allocator_type& __a)
- : _Base(__a) { }
+ multimap(const _Allocator& __a)
+ : _Base(__a) { }
- multimap(const multimap& __x, const allocator_type& __a)
+ multimap(const multimap& __x, const _Allocator& __a)
: _Base(__x, __a) { }
- multimap(multimap&& __x, const allocator_type& __a)
- noexcept(is_nothrow_copy_constructible<_Compare>::value
- && _Alloc_traits::_S_always_equal())
+ multimap(multimap&& __x, const _Allocator& __a)
+ noexcept( noexcept(_Base(std::move(__x), __a)) )
: _Base(std::move(__x), __a) { }
- multimap(initializer_list<value_type> __l, const allocator_type& __a)
+ multimap(initializer_list<value_type> __l, const _Allocator& __a)
: _Base(__l, __a) { }
template<typename _InputIterator>
- multimap(_InputIterator __first, _InputIterator __last,
- const allocator_type& __a)
- : _Base(__first, __last, __a) { }
+ multimap(_InputIterator __first, _InputIterator __last,
+ const _Allocator& __a)
+ : _Base(__first, __last, __a) { }
#endif
multimap(const _Base& __x)
: _Base(__x) { }
- ~multimap() _GLIBCXX_NOEXCEPT { }
-
#if __cplusplus < 201103L
multimap&
operator=(const multimap& __x)
@@ -147,117 +145,125 @@ namespace __profile
}
#endif
- using _Base::get_allocator;
-
- // iterators:
- iterator
- begin() _GLIBCXX_NOEXCEPT
- { return iterator(_Base::begin()); }
-
- const_iterator
- begin() const _GLIBCXX_NOEXCEPT
- { return const_iterator(_Base::begin()); }
-
- iterator
- end() _GLIBCXX_NOEXCEPT
- { return iterator(_Base::end()); }
-
- const_iterator
- end() const _GLIBCXX_NOEXCEPT
- { return const_iterator(_Base::end()); }
-
reverse_iterator
rbegin() _GLIBCXX_NOEXCEPT
- { return reverse_iterator(end()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rbegin();
+ }
const_reverse_iterator
rbegin() const _GLIBCXX_NOEXCEPT
- { return const_reverse_iterator(end()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rbegin();
+ }
reverse_iterator
rend() _GLIBCXX_NOEXCEPT
- { return reverse_iterator(begin()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rend();
+ }
const_reverse_iterator
rend() const _GLIBCXX_NOEXCEPT
- { return const_reverse_iterator(begin()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rend();
+ }
#if __cplusplus >= 201103L
- const_iterator
- cbegin() const noexcept
- { return const_iterator(_Base::begin()); }
-
- const_iterator
- cend() const noexcept
- { return const_iterator(_Base::end()); }
-
const_reverse_iterator
crbegin() const noexcept
- { return const_reverse_iterator(end()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::crbegin();
+ }
const_reverse_iterator
crend() const noexcept
- { return const_reverse_iterator(begin()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::crend();
+ }
#endif
- // capacity:
- using _Base::empty;
- using _Base::size;
- using _Base::max_size;
-
// modifiers:
#if __cplusplus >= 201103L
template<typename... _Args>
iterator
emplace(_Args&&... __args)
{
- return iterator(_Base::emplace(std::forward<_Args>(__args)...));
+ __profcxx_map_to_unordered_map_insert(this, this->size(), 1);
+ return _Base::emplace(std::forward<_Args>(__args)...);
}
template<typename... _Args>
iterator
emplace_hint(const_iterator __pos, _Args&&... __args)
{
- return iterator(_Base::emplace_hint(__pos,
- std::forward<_Args>(__args)...));
+ auto size_before = this->size();
+ auto __res
+ = _Base::emplace_hint(__pos, std::forward<_Args>(__args)...);
+ __profcxx_map_to_unordered_map_insert(this, size_before,
+ _M_hint_used(__pos, __res) ? 0 : 1);
+ return __res;
}
#endif
-
+
iterator
insert(const value_type& __x)
- { return iterator(_Base::insert(__x)); }
+ {
+ __profcxx_map_to_unordered_map_insert(this, this->size(), 1);
+ return _Base::insert(__x);
+ }
#if __cplusplus >= 201103L
template<typename _Pair, typename = typename
std::enable_if<std::is_constructible<value_type,
_Pair&&>::value>::type>
- iterator
- insert(_Pair&& __x)
- { return iterator(_Base::insert(std::forward<_Pair>(__x))); }
+ iterator
+ insert(_Pair&& __x)
+ {
+ __profcxx_map_to_unordered_map_insert(this, this->size(), 1);
+ return _Base::insert(std::forward<_Pair>(__x));
+ }
#endif
#if __cplusplus >= 201103L
void
insert(std::initializer_list<value_type> __list)
- { _Base::insert(__list); }
+ { insert(__list.begin(), __list.end()); }
#endif
iterator
#if __cplusplus >= 201103L
- insert(const_iterator __position, const value_type& __x)
+ insert(const_iterator __pos, const value_type& __x)
#else
- insert(iterator __position, const value_type& __x)
+ insert(iterator __pos, const value_type& __x)
#endif
- { return iterator(_Base::insert(__position, __x)); }
+ {
+ size_type size_before = this->size();
+ iterator __res = _Base::insert(__pos, __x);
+ __profcxx_map_to_unordered_map_insert(this, size_before,
+ _M_hint_used(__pos, __res) ? 0 : 1);
+ return __res;
+ }
#if __cplusplus >= 201103L
template<typename _Pair, typename = typename
std::enable_if<std::is_constructible<value_type,
_Pair&&>::value>::type>
- iterator
- insert(const_iterator __position, _Pair&& __x)
- { return iterator(_Base::insert(__position,
- std::forward<_Pair>(__x))); }
+ iterator
+ insert(const_iterator __pos, _Pair&& __x)
+ {
+ size_type size_before = this->size();
+ auto __res = _Base::insert(__pos, std::forward<_Pair>(__x));
+ __profcxx_map_to_unordered_map_insert(this, size_before,
+ _M_hint_used(__pos, __res) ? 0 : 1);
+ return __res;
+ }
#endif
#if __cplusplus >= 201103L
@@ -266,115 +272,163 @@ namespace __profile
#else
template<typename _InputIterator>
#endif
- void
- insert(_InputIterator __first, _InputIterator __last)
- { _Base::insert(__first, __last); }
+ void
+ insert(_InputIterator __first, _InputIterator __last)
+ {
+ for (; __first != __last; ++__first)
+ insert(*__first);
+ }
#if __cplusplus >= 201103L
iterator
- erase(const_iterator __position)
- { return iterator(_Base::erase(__position)); }
+ erase(const_iterator __pos)
+ {
+ __profcxx_map_to_unordered_map_erase(this, this->size(), 1);
+ return _Base::erase(__pos);
+ }
iterator
- erase(iterator __position)
- { return iterator(_Base::erase(__position)); }
+ erase(iterator __pos)
+ {
+ __profcxx_map_to_unordered_map_erase(this, this->size(), 1);
+ return _Base::erase(__pos);
+ }
#else
void
- erase(iterator __position)
- { _Base::erase(__position); }
+ erase(iterator __pos)
+ {
+ __profcxx_map_to_unordered_map_erase(this, this->size(), 1);
+ _Base::erase(__pos);
+ }
#endif
size_type
erase(const key_type& __x)
{
- std::pair<iterator, iterator> __victims = this->equal_range(__x);
- size_type __count = 0;
- while (__victims.first != __victims.second)
- {
- iterator __victim = __victims.first++;
- _Base::erase(__victim);
- ++__count;
- }
- return __count;
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_erase(this, this->size(), 1);
+ return _Base::erase(__x);
}
#if __cplusplus >= 201103L
iterator
erase(const_iterator __first, const_iterator __last)
- { return iterator(_Base::erase(__first, __last)); }
+ {
+ if (__first != __last)
+ {
+ iterator __ret;
+ for (; __first != __last;)
+ __ret = erase(__first++);
+ return __ret;
+ }
+ else
+ return _Base::erase(__first, __last);
+ }
#else
void
erase(iterator __first, iterator __last)
- { _Base::erase(__first, __last); }
+ {
+ for (; __first != __last;)
+ erase(__first++);
+ }
#endif
void
swap(multimap& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
{ _Base::swap(__x); }
- void
- clear() _GLIBCXX_NOEXCEPT
- { this->erase(begin(), end()); }
-
- // observers:
- using _Base::key_comp;
- using _Base::value_comp;
-
// 23.3.1.3 multimap operations:
iterator
find(const key_type& __x)
- { return iterator(_Base::find(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::find(__x);
+ }
const_iterator
find(const key_type& __x) const
- { return const_iterator(_Base::find(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::find(__x);
+ }
- using _Base::count;
+ size_type
+ count(const key_type& __x) const
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::count(__x);
+ }
iterator
lower_bound(const key_type& __x)
- { return iterator(_Base::lower_bound(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::lower_bound(__x);
+ }
const_iterator
lower_bound(const key_type& __x) const
- { return const_iterator(_Base::lower_bound(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::lower_bound(__x);
+ }
iterator
upper_bound(const key_type& __x)
- { return iterator(_Base::upper_bound(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::upper_bound(__x);
+ }
const_iterator
upper_bound(const key_type& __x) const
- { return const_iterator(_Base::upper_bound(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::upper_bound(__x);
+ }
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
- typedef typename _Base::iterator _Base_iterator;
- std::pair<_Base_iterator, _Base_iterator> __res =
- _Base::equal_range(__x);
- return std::make_pair(iterator(__res.first),
- iterator(__res.second));
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::equal_range(__x);
}
std::pair<const_iterator,const_iterator>
equal_range(const key_type& __x) const
{
- typedef typename _Base::const_iterator _Base_const_iterator;
- std::pair<_Base_const_iterator, _Base_const_iterator> __res =
- _Base::equal_range(__x);
- return std::make_pair(const_iterator(__res.first),
- const_iterator(__res.second));
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::equal_range(__x);
}
_Base&
- _M_base() _GLIBCXX_NOEXCEPT { return *this; }
+ _M_base() _GLIBCXX_NOEXCEPT { return *this; }
const _Base&
- _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
+ _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
+
+ private:
+ /** If hint is used we consider that the map and unordered_map
+ * operations have equivalent insertion cost so we do not update metrics
+ * about it.
+ * Note that to find out if hint has been used is libstdc++
+ * implementation dependent.
+ */
+ bool
+ _M_hint_used(const_iterator __hint, iterator __res)
+ {
+ return (__hint == __res
+ || (__hint == this->end() && ++__res == this->end())
+ || (__hint != this->end() && (++__hint == __res
+ || ++__res == --__hint)));
+ }
};
template<typename _Key, typename _Tp,
diff --git a/libstdc++-v3/include/profile/multiset.h b/libstdc++-v3/include/profile/multiset.h
index 8ef6e6b0de7..25011097c51 100644
--- a/libstdc++-v3/include/profile/multiset.h
+++ b/libstdc++-v3/include/profile/multiset.h
@@ -29,7 +29,8 @@
#ifndef _GLIBCXX_PROFILE_MULTISET_H
#define _GLIBCXX_PROFILE_MULTISET_H 1
-#include <utility>
+#include <profile/base.h>
+#include <profile/ordered_base.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -39,38 +40,45 @@ namespace __profile
template<typename _Key, typename _Compare = std::less<_Key>,
typename _Allocator = std::allocator<_Key> >
class multiset
- : public _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator>
+ : public _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator>,
+ public _Ordered_profile<multiset<_Key, _Compare, _Allocator> >
{
typedef _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator> _Base;
-#if __cplusplus >= 201103L
- typedef __gnu_cxx::__alloc_traits<_Allocator> _Alloc_traits;
-#endif
-
public:
// types:
- typedef _Key key_type;
- typedef _Key value_type;
- typedef _Compare key_compare;
- typedef _Compare value_compare;
- typedef _Allocator allocator_type;
- typedef typename _Base::reference reference;
- typedef typename _Base::const_reference const_reference;
-
- typedef typename _Base::iterator iterator;
- typedef typename _Base::const_iterator const_iterator;
- typedef typename _Base::reverse_iterator reverse_iterator;
- typedef typename _Base::const_reverse_iterator const_reverse_iterator;
-
- typedef typename _Base::size_type size_type;
- typedef typename _Base::difference_type difference_type;
- typedef typename _Base::pointer pointer;
- typedef typename _Base::const_pointer const_pointer;
+ typedef _Key key_type;
+ typedef _Key value_type;
+ typedef _Compare key_compare;
+ typedef _Compare value_compare;
+ typedef _Allocator allocator_type;
+ typedef typename _Base::reference reference;
+ typedef typename _Base::const_reference const_reference;
+
+ typedef typename _Base::iterator iterator;
+ typedef typename _Base::const_iterator const_iterator;
+ typedef typename _Base::reverse_iterator reverse_iterator;
+ typedef typename _Base::const_reverse_iterator const_reverse_iterator;
+
+ typedef typename _Base::size_type size_type;
+ typedef typename _Base::difference_type difference_type;
+ typedef typename _Base::pointer pointer;
+ typedef typename _Base::const_pointer const_pointer;
// 23.3.3.1 construct/copy/destroy:
+#if __cplusplus < 201103L
multiset()
: _Base() { }
+ multiset(const multiset& __x)
+ : _Base(__x) { }
+ ~multiset() { }
+#else
+ multiset() = default;
+ multiset(const multiset&) = default;
+ multiset(multiset&&) = default;
+ ~multiset() = default;
+#endif
explicit multiset(const _Compare& __comp,
const _Allocator& __a = _Allocator())
@@ -82,18 +90,12 @@ namespace __profile
#else
template<typename _InputIterator>
#endif
- multiset(_InputIterator __first, _InputIterator __last,
+ multiset(_InputIterator __first, _InputIterator __last,
const _Compare& __comp = _Compare(),
const _Allocator& __a = _Allocator())
: _Base(__first, __last, __comp, __a) { }
-#if __cplusplus < 201103L
- multiset(const multiset& __x)
- : _Base(__x) { }
-#else
- multiset(const multiset&) = default;
- multiset(multiset&&) = default;
-
+#if __cplusplus >= 201103L
multiset(initializer_list<value_type> __l,
const _Compare& __comp = _Compare(),
const allocator_type& __a = allocator_type())
@@ -101,30 +103,27 @@ namespace __profile
explicit
multiset(const allocator_type& __a)
- : _Base(__a) { }
+ : _Base(__a) { }
multiset(const multiset& __x, const allocator_type& __a)
: _Base(__x, __a) { }
multiset(multiset&& __x, const allocator_type& __a)
- noexcept(is_nothrow_copy_constructible<_Compare>::value
- && _Alloc_traits::_S_always_equal())
+ noexcept( noexcept(_Base(std::move(__x), __a)) )
: _Base(std::move(__x), __a) { }
multiset(initializer_list<value_type> __l, const allocator_type& __a)
: _Base(__l, __a) { }
template<typename _InputIterator>
- multiset(_InputIterator __first, _InputIterator __last,
- const allocator_type& __a)
- : _Base(__first, __last, __a) { }
+ multiset(_InputIterator __first, _InputIterator __last,
+ const allocator_type& __a)
+ : _Base(__first, __last, __a) { }
#endif
multiset(const _Base& __x)
: _Base(__x) { }
- ~multiset() _GLIBCXX_NOEXCEPT { }
-
#if __cplusplus < 201103L
multiset&
operator=(const multiset& __x)
@@ -147,98 +146,112 @@ namespace __profile
}
#endif
- using _Base::get_allocator;
-
// iterators:
- iterator
- begin() _GLIBCXX_NOEXCEPT
- { return iterator(_Base::begin()); }
-
- const_iterator
- begin() const _GLIBCXX_NOEXCEPT
- { return const_iterator(_Base::begin()); }
-
- iterator
- end() _GLIBCXX_NOEXCEPT
- { return iterator(_Base::end()); }
-
- const_iterator
- end() const _GLIBCXX_NOEXCEPT
- { return const_iterator(_Base::end()); }
-
reverse_iterator
rbegin() _GLIBCXX_NOEXCEPT
- { return reverse_iterator(end()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rbegin();
+ }
const_reverse_iterator
rbegin() const _GLIBCXX_NOEXCEPT
- { return const_reverse_iterator(end()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rbegin();
+ }
reverse_iterator
rend() _GLIBCXX_NOEXCEPT
- { return reverse_iterator(begin()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rend();
+ }
const_reverse_iterator
rend() const _GLIBCXX_NOEXCEPT
- { return const_reverse_iterator(begin()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rend();
+ }
#if __cplusplus >= 201103L
- const_iterator
- cbegin() const noexcept
- { return const_iterator(_Base::begin()); }
-
- const_iterator
- cend() const noexcept
- { return const_iterator(_Base::end()); }
-
const_reverse_iterator
crbegin() const noexcept
- { return const_reverse_iterator(end()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::crbegin();
+ }
const_reverse_iterator
crend() const noexcept
- { return const_reverse_iterator(begin()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::crend();
+ }
#endif
- // capacity:
- using _Base::empty;
- using _Base::size;
- using _Base::max_size;
-
// modifiers:
#if __cplusplus >= 201103L
template<typename... _Args>
iterator
emplace(_Args&&... __args)
- { return iterator(_Base::emplace(std::forward<_Args>(__args)...)); }
+ {
+ // The cost is the same whether or not the element is inserted so we
+ // always report insertion of 1 element.
+ __profcxx_map_to_unordered_map_insert(this, this->size(), 1);
+ return _Base::emplace(std::forward<_Args>(__args)...);
+ }
template<typename... _Args>
iterator
emplace_hint(const_iterator __pos, _Args&&... __args)
{
- return iterator(_Base::emplace_hint(__pos,
- std::forward<_Args>(__args)...));
+ auto size_before = this->size();
+ auto __res = _Base::emplace_hint(__pos, std::forward<_Args>(__args)...);
+ __profcxx_map_to_unordered_map_insert(this, size_before,
+ _M_hint_used(__pos, __res) ? 0 : 1);
+ return __res;
}
#endif
iterator
insert(const value_type& __x)
- { return iterator(_Base::insert(__x)); }
+ {
+ __profcxx_map_to_unordered_map_insert(this, this->size(), 1);
+ return _Base::insert(__x);
+ }
#if __cplusplus >= 201103L
iterator
insert(value_type&& __x)
- { return iterator(_Base::insert(std::move(__x))); }
+ {
+ __profcxx_map_to_unordered_map_insert(this, this->size(), 1);
+ return _Base::insert(std::move(__x));
+ }
#endif
iterator
- insert(const_iterator __position, const value_type& __x)
- { return iterator(_Base::insert(__position, __x)); }
+ insert(const_iterator __pos, const value_type& __x)
+ {
+ size_type size_before = this->size();
+ iterator __res = _Base::insert(__pos, __x);
+
+ __profcxx_map_to_unordered_map_insert(this, size_before,
+ _M_hint_used(__pos, __res) ? 0 : 1);
+ return __res;
+ }
#if __cplusplus >= 201103L
iterator
- insert(const_iterator __position, value_type&& __x)
- { return iterator(_Base::insert(__position, std::move(__x))); }
+ insert(const_iterator __pos, value_type&& __x)
+ {
+ auto size_before = this->size();
+ auto __res = _Base::insert(__pos, std::move(__x));
+ __profcxx_map_to_unordered_map_insert(this, size_before,
+ _M_hint_used(__pos, __res) ? 0 : 1);
+ return __res;
+ }
#endif
#if __cplusplus >= 201103L
@@ -247,106 +260,137 @@ namespace __profile
#else
template<typename _InputIterator>
#endif
- void
- insert(_InputIterator __first, _InputIterator __last)
- { _Base::insert(__first, __last); }
+ void
+ insert(_InputIterator __first, _InputIterator __last)
+ {
+ for (; __first != __last; ++__first)
+ insert(*__first);
+ }
#if __cplusplus >= 201103L
void
insert(initializer_list<value_type> __l)
- { _Base::insert(__l); }
+ { insert(__l.begin(), __l.end()); }
#endif
#if __cplusplus >= 201103L
iterator
- erase(const_iterator __position)
- { return iterator(_Base::erase(__position)); }
+ erase(const_iterator __pos)
+ {
+ __profcxx_map_to_unordered_map_erase(this, this->size(), 1);
+ return _Base::erase(__pos);
+ }
#else
void
- erase(iterator __position)
- { _Base::erase(__position); }
+ erase(iterator __pos)
+ {
+ __profcxx_map_to_unordered_map_erase(this, this->size(), 1);
+ _Base::erase(__pos);
+ }
#endif
size_type
erase(const key_type& __x)
{
- std::pair<iterator, iterator> __victims = this->equal_range(__x);
- size_type __count = 0;
- while (__victims.first != __victims.second)
- {
- iterator __victim = __victims.first++;
- _Base::erase(__victim);
- ++__count;
- }
- return __count;
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_erase(this, this->size(), 1);
+ return _Base::erase(__x);
}
#if __cplusplus >= 201103L
iterator
erase(const_iterator __first, const_iterator __last)
- { return iterator(_Base::erase(__first, __last)); }
+ {
+ if (__first != __last)
+ {
+ iterator __ret;
+ for (; __first != __last;)
+ __ret = erase(__first++);
+ return __ret;
+ }
+ else
+ return _Base::erase(__first, __last);
+ }
#else
void
erase(iterator __first, iterator __last)
- { _Base::erase(__first, __last); }
+ {
+ for (; __first != __last;)
+ erase(__first++);
+ }
#endif
void
swap(multiset& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
{ _Base::swap(__x); }
- void
- clear() _GLIBCXX_NOEXCEPT
- { this->erase(begin(), end()); }
-
- // observers:
- using _Base::key_comp;
- using _Base::value_comp;
-
// multiset operations:
iterator
find(const key_type& __x)
- { return iterator(_Base::find(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::find(__x);
+ }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 214. set::find() missing const overload
const_iterator
find(const key_type& __x) const
- { return const_iterator(_Base::find(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::find(__x);
+ }
- using _Base::count;
+ size_type
+ count(const key_type& __x) const
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::count(__x);
+ }
iterator
lower_bound(const key_type& __x)
- { return iterator(_Base::lower_bound(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::lower_bound(__x);
+ }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 214. set::find() missing const overload
const_iterator
lower_bound(const key_type& __x) const
- { return const_iterator(_Base::lower_bound(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::lower_bound(__x);
+ }
iterator
upper_bound(const key_type& __x)
- { return iterator(_Base::upper_bound(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::upper_bound(__x);
+ }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 214. set::find() missing const overload
const_iterator
upper_bound(const key_type& __x) const
- { return const_iterator(_Base::upper_bound(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::upper_bound(__x);
+ }
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
- typedef typename _Base::iterator _Base_iterator;
- std::pair<_Base_iterator, _Base_iterator> __res =
- _Base::equal_range(__x);
- return std::make_pair(iterator(__res.first),
- iterator(__res.second));
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::equal_range(__x);
}
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -354,19 +398,31 @@ namespace __profile
std::pair<const_iterator,const_iterator>
equal_range(const key_type& __x) const
{
- typedef typename _Base::const_iterator _Base_iterator;
- std::pair<_Base_iterator, _Base_iterator> __res =
- _Base::equal_range(__x);
- return std::make_pair(const_iterator(__res.first),
- const_iterator(__res.second));
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::equal_range(__x);
}
_Base&
- _M_base() _GLIBCXX_NOEXCEPT { return *this; }
+ _M_base() _GLIBCXX_NOEXCEPT { return *this; }
const _Base&
- _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
-
+ _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
+
+ private:
+ /** If hint is used we consider that the map and unordered_map
+ * operations have equivalent insertion cost so we do not update metrics
+ * about it.
+ * Note that to find out if hint has been used is libstdc++
+ * implementation dependent.
+ */
+ bool
+ _M_hint_used(const_iterator __hint, iterator __res)
+ {
+ return (__hint == __res
+ || (__hint == this->end() && ++__res == this->end())
+ || (__hint != this->end() && (++__hint == __res
+ || ++__res == --__hint)));
+ }
};
template<typename _Key, typename _Compare, typename _Allocator>
diff --git a/libstdc++-v3/include/profile/ordered_base.h b/libstdc++-v3/include/profile/ordered_base.h
new file mode 100644
index 00000000000..c76adfc48f0
--- /dev/null
+++ b/libstdc++-v3/include/profile/ordered_base.h
@@ -0,0 +1,65 @@
+// Profiling unordered containers implementation details -*- C++ -*-
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+//
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+/** @file profile/ordered_base.h
+ * This file is a GNU profile extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_PROFILE_ORDERED
+#define _GLIBCXX_PROFILE_ORDERED 1
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace __profile
+{
+ template<typename _Cont>
+ class _Ordered_profile
+ {
+ _Cont&
+ _M_conjure()
+ { return *static_cast<_Cont*>(this); }
+
+ public:
+ _Ordered_profile() _GLIBCXX_NOEXCEPT
+ { __profcxx_map_to_unordered_map_construct(&_M_conjure()); }
+
+#if __cplusplus >= 201103L
+ _Ordered_profile(const _Ordered_profile&) noexcept
+ : _Ordered_profile() { }
+ _Ordered_profile(_Ordered_profile&&) noexcept
+ : _Ordered_profile() { }
+
+ _Ordered_profile&
+ operator=(const _Ordered_profile&) = default;
+ _Ordered_profile&
+ operator=(_Ordered_profile&&) = default;
+#endif
+
+ ~_Ordered_profile()
+ { __profcxx_map_to_unordered_map_destruct(&_M_conjure()); }
+ };
+
+} // namespace __profile
+} // namespace std
+
+#endif
diff --git a/libstdc++-v3/include/profile/set.h b/libstdc++-v3/include/profile/set.h
index 05fbeb9f6b1..e8275a4cc6d 100644
--- a/libstdc++-v3/include/profile/set.h
+++ b/libstdc++-v3/include/profile/set.h
@@ -29,9 +29,10 @@
#ifndef _GLIBCXX_PROFILE_SET_H
#define _GLIBCXX_PROFILE_SET_H 1
-#include <utility>
+#include <profile/base.h>
+#include <profile/ordered_base.h>
-namespace std _GLIBCXX_VISIBILITY(default)
+namespace std _GLIBCXX_VISIBILITY(default)
{
namespace __profile
{
@@ -39,7 +40,8 @@ namespace __profile
template<typename _Key, typename _Compare = std::less<_Key>,
typename _Allocator = std::allocator<_Key> >
class set
- : public _GLIBCXX_STD_C::set<_Key,_Compare,_Allocator>
+ : public _GLIBCXX_STD_C::set<_Key,_Compare,_Allocator>,
+ public _Ordered_profile<set<_Key, _Compare, _Allocator> >
{
typedef _GLIBCXX_STD_C::set<_Key, _Compare, _Allocator> _Base;
@@ -49,28 +51,36 @@ namespace __profile
public:
// types:
- typedef _Key key_type;
- typedef _Key value_type;
- typedef _Compare key_compare;
- typedef _Compare value_compare;
- typedef _Allocator allocator_type;
- typedef typename _Base::reference reference;
- typedef typename _Base::const_reference const_reference;
-
- typedef typename _Base::iterator iterator;
- typedef typename _Base::const_iterator const_iterator;
- typedef typename _Base::reverse_iterator reverse_iterator;
- typedef typename _Base::const_reverse_iterator const_reverse_iterator;
-
- typedef typename _Base::size_type size_type;
- typedef typename _Base::difference_type difference_type;
- typedef typename _Base::pointer pointer;
- typedef typename _Base::const_pointer const_pointer;
+ typedef _Key key_type;
+ typedef _Key value_type;
+ typedef _Compare key_compare;
+ typedef _Compare value_compare;
+ typedef typename _Base::reference reference;
+ typedef typename _Base::const_reference const_reference;
+
+ typedef typename _Base::iterator iterator;
+ typedef typename _Base::const_iterator const_iterator;
+ typedef typename _Base::reverse_iterator reverse_iterator;
+ typedef typename _Base::const_reverse_iterator const_reverse_iterator;
+
+ typedef typename _Base::size_type size_type;
+ typedef typename _Base::difference_type difference_type;
+ typedef typename _Base::pointer pointer;
+ typedef typename _Base::const_pointer const_pointer;
// 23.3.3.1 construct/copy/destroy:
-
+#if __cplusplus < 201103L
set()
: _Base() { }
+ set(const set& __x)
+ : _Base(__x) { }
+ ~set() { }
+#else
+ set() = default;
+ set(const set&) = default;
+ set(set&&) = default;
+ ~set() = default;
+#endif
explicit set(const _Compare& __comp,
const _Allocator& __a = _Allocator())
@@ -82,49 +92,40 @@ namespace __profile
#else
template<typename _InputIterator>
#endif
- set(_InputIterator __first, _InputIterator __last,
+ set(_InputIterator __first, _InputIterator __last,
const _Compare& __comp = _Compare(),
const _Allocator& __a = _Allocator())
: _Base(__first, __last, __comp, __a) { }
-#if __cplusplus < 201103L
- set(const set& __x)
- : _Base(__x) { }
-#else
- set(const set&) = default;
- set(set&&) = default;
-
+#if __cplusplus >= 201103L
set(initializer_list<value_type> __l,
const _Compare& __comp = _Compare(),
- const allocator_type& __a = allocator_type())
+ const _Allocator& __a = _Allocator())
: _Base(__l, __comp, __a) { }
explicit
- set(const allocator_type& __a)
- : _Base(__a) { }
+ set(const _Allocator& __a)
+ : _Base(__a) { }
- set(const set& __x, const allocator_type& __a)
+ set(const set& __x, const _Allocator& __a)
: _Base(__x, __a) { }
- set(set&& __x, const allocator_type& __a)
- noexcept(is_nothrow_copy_constructible<_Compare>::value
- && _Alloc_traits::_S_always_equal())
+ set(set&& __x, const _Allocator& __a)
+ noexcept( noexcept(_Base(std::move(__x), __a)) )
: _Base(std::move(__x), __a) { }
- set(initializer_list<value_type> __l, const allocator_type& __a)
+ set(initializer_list<value_type> __l, const _Allocator& __a)
: _Base(__l, __a) { }
template<typename _InputIterator>
- set(_InputIterator __first, _InputIterator __last,
- const allocator_type& __a)
- : _Base(__first, __last, __a) { }
+ set(_InputIterator __first, _InputIterator __last,
+ const _Allocator& __a)
+ : _Base(__first, __last, __a) { }
#endif
set(const _Base& __x)
: _Base(__x) { }
- ~set() _GLIBCXX_NOEXCEPT { }
-
#if __cplusplus < 201103L
set&
operator=(const set& __x)
@@ -147,108 +148,98 @@ namespace __profile
}
#endif
- using _Base::get_allocator;
-
- // iterators:
- iterator
- begin() _GLIBCXX_NOEXCEPT
- { return iterator(_Base::begin()); }
-
- const_iterator
- begin() const _GLIBCXX_NOEXCEPT
- { return const_iterator(_Base::begin()); }
-
- iterator
- end() _GLIBCXX_NOEXCEPT
- { return iterator(_Base::end()); }
-
- const_iterator
- end() const _GLIBCXX_NOEXCEPT
- { return const_iterator(_Base::end()); }
-
reverse_iterator
rbegin() _GLIBCXX_NOEXCEPT
- { return reverse_iterator(end()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rbegin();
+ }
const_reverse_iterator
rbegin() const _GLIBCXX_NOEXCEPT
- { return const_reverse_iterator(end()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rbegin();
+ }
reverse_iterator
rend() _GLIBCXX_NOEXCEPT
- { return reverse_iterator(begin()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rend();
+ }
const_reverse_iterator
rend() const _GLIBCXX_NOEXCEPT
- { return const_reverse_iterator(begin()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::rend();
+ }
#if __cplusplus >= 201103L
- const_iterator
- cbegin() const noexcept
- { return const_iterator(_Base::begin()); }
-
- const_iterator
- cend() const noexcept
- { return const_iterator(_Base::end()); }
-
const_reverse_iterator
crbegin() const noexcept
- { return const_reverse_iterator(end()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::crbegin();
+ }
const_reverse_iterator
crend() const noexcept
- { return const_reverse_iterator(begin()); }
+ {
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::crend();
+ }
#endif
- // capacity:
- using _Base::empty;
- using _Base::size;
- using _Base::max_size;
-
// modifiers:
#if __cplusplus >= 201103L
template<typename... _Args>
std::pair<iterator, bool>
emplace(_Args&&... __args)
{
- auto __res = _Base::emplace(std::forward<_Args>(__args)...);
- return std::pair<iterator, bool>(iterator(__res.first),
- __res.second);
+ __profcxx_map_to_unordered_map_insert(this, this->size(), 1);
+ return _Base::emplace(std::forward<_Args>(__args)...);
}
template<typename... _Args>
iterator
emplace_hint(const_iterator __pos, _Args&&... __args)
{
- return iterator(_Base::emplace_hint(__pos,
- std::forward<_Args>(__args)...));
+ auto size_before = this->size();
+ auto __res
+ = _Base::emplace_hint(__pos, std::forward<_Args>(__args)...);
+ __profcxx_map_to_unordered_map_insert(this, size_before,
+ _M_hint_used(__pos, __res) ? 0 : 1);
+ return __res;
}
#endif
std::pair<iterator, bool>
insert(const value_type& __x)
{
- typedef typename _Base::iterator _Base_iterator;
- std::pair<_Base_iterator, bool> __res = _Base::insert(__x);
- return std::pair<iterator, bool>(iterator(__res.first),
- __res.second);
+ __profcxx_map_to_unordered_map_insert(this, this->size(), 1);
+ return _Base::insert(__x);
}
#if __cplusplus >= 201103L
std::pair<iterator, bool>
insert(value_type&& __x)
{
- typedef typename _Base::iterator _Base_iterator;
- std::pair<_Base_iterator, bool> __res
- = _Base::insert(std::move(__x));
- return std::pair<iterator, bool>(iterator(__res.first),
- __res.second);
+ __profcxx_map_to_unordered_map_insert(this, this->size(), 1);
+ return _Base::insert(std::move(__x));
}
#endif
iterator
- insert(const_iterator __position, const value_type& __x)
- { return iterator(_Base::insert(__position, __x)); }
+ insert(const_iterator __pos, const value_type& __x)
+ {
+ size_type size_before = this->size();
+ iterator __res = _Base::insert(__pos, __x);
+ __profcxx_map_to_unordered_map_insert(this, size_before,
+ _M_hint_used(__pos, __res) ? 0 : 1);
+ return __res;
+ }
#if __cplusplus >= 201103L
iterator
@@ -262,125 +253,162 @@ namespace __profile
#else
template<typename _InputIterator>
#endif
- void
- insert(_InputIterator __first, _InputIterator __last)
- { _Base::insert(__first, __last); }
+ void
+ insert(_InputIterator __first, _InputIterator __last)
+ {
+ for (; __first != __last; ++__first)
+ insert(*__first);
+ }
#if __cplusplus >= 201103L
void
insert(initializer_list<value_type> __l)
- { _Base::insert(__l); }
+ { insert(__l.begin(), __l.end()); }
#endif
#if __cplusplus >= 201103L
iterator
- erase(const_iterator __position)
- { return iterator(_Base::erase(__position)); }
+ erase(const_iterator __pos)
+ {
+ __profcxx_map_to_unordered_map_erase(this, this->size(), 1);
+ return _Base::erase(__pos);
+ }
#else
void
- erase(iterator __position)
- { _Base::erase(__position); }
+ erase(iterator __pos)
+ {
+ __profcxx_map_to_unordered_map_erase(this, this->size(), 1);
+ _Base::erase(__pos);
+ }
#endif
size_type
erase(const key_type& __x)
{
- iterator __victim = find(__x);
- if (__victim == end())
- return 0;
- else
- {
- _Base::erase(__victim);
- return 1;
- }
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_erase(this, this->size(), 1);
+ return _Base::erase(__x);
}
#if __cplusplus >= 201103L
iterator
erase(const_iterator __first, const_iterator __last)
- { return iterator(_Base::erase(__first, __last)); }
+ {
+ if (__first != __last)
+ {
+ iterator __ret;
+ for (; __first != __last;)
+ __ret = erase(__first++);
+ return __ret;
+ }
+
+ return _Base::erase(__first, __last);
+ }
#else
void
erase(iterator __first, iterator __last)
- { _Base::erase(__first, __last); }
+ {
+ for (; __first != __last;)
+ erase(__first++);
+ }
#endif
void
swap(set& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
{ _Base::swap(__x); }
- void
- clear() _GLIBCXX_NOEXCEPT
- { this->erase(begin(), end()); }
-
- // observers:
- using _Base::key_comp;
- using _Base::value_comp;
-
// set operations:
iterator
find(const key_type& __x)
- { return iterator(_Base::find(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::find(__x);
+ }
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 214. set::find() missing const overload
const_iterator
find(const key_type& __x) const
- { return const_iterator(_Base::find(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::find(__x);
+ }
- using _Base::count;
+ size_type
+ count(const key_type& __x) const
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::count(__x);
+ }
iterator
lower_bound(const key_type& __x)
- { return iterator(_Base::lower_bound(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::lower_bound(__x);
+ }
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 214. set::find() missing const overload
const_iterator
lower_bound(const key_type& __x) const
- { return const_iterator(_Base::lower_bound(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::lower_bound(__x);
+ }
iterator
upper_bound(const key_type& __x)
- { return iterator(_Base::upper_bound(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::upper_bound(__x);
+ }
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 214. set::find() missing const overload
const_iterator
upper_bound(const key_type& __x) const
- { return const_iterator(_Base::upper_bound(__x)); }
+ {
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ __profcxx_map_to_unordered_map_invalidate(this);
+ return _Base::upper_bound(__x);
+ }
- std::pair<iterator,iterator>
+ std::pair<iterator, iterator>
equal_range(const key_type& __x)
{
- typedef typename _Base::iterator _Base_iterator;
- std::pair<_Base_iterator, _Base_iterator> __res =
- _Base::equal_range(__x);
- return std::make_pair(iterator(__res.first),
- iterator(__res.second));
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::equal_range(__x);
}
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 214. set::find() missing const overload
- std::pair<const_iterator,const_iterator>
+ std::pair<const_iterator, const_iterator>
equal_range(const key_type& __x) const
{
- typedef typename _Base::const_iterator _Base_iterator;
- std::pair<_Base_iterator, _Base_iterator> __res =
- _Base::equal_range(__x);
- return std::make_pair(const_iterator(__res.first),
- const_iterator(__res.second));
+ __profcxx_map_to_unordered_map_find(this, this->size());
+ return _Base::equal_range(__x);
}
_Base&
- _M_base() _GLIBCXX_NOEXCEPT { return *this; }
+ _M_base() _GLIBCXX_NOEXCEPT { return *this; }
const _Base&
- _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
-
+ _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
+
+ private:
+ /** If hint is used we consider that the map and unordered_map
+ * operations have equivalent insertion cost so we do not update metrics
+ * about it.
+ * Note that to find out if hint has been used is libstdc++
+ * implementation dependent.
+ */
+ bool
+ _M_hint_used(const_iterator __hint, iterator __res)
+ {
+ return (__hint == __res
+ || (__hint == this->end() && ++__res == this->end())
+ || (__hint != this->end() && (++__hint == __res
+ || ++__res == --__hint)));
+ }
};
template<typename _Key, typename _Compare, typename _Allocator>
diff --git a/libstdc++-v3/include/profile/unordered_base.h b/libstdc++-v3/include/profile/unordered_base.h
index 6c52f0a65fd..283f87ce715 100644
--- a/libstdc++-v3/include/profile/unordered_base.h
+++ b/libstdc++-v3/include/profile/unordered_base.h
@@ -157,7 +157,7 @@ namespace __profile
_Unordered_profile()
{
auto& __uc = _M_conjure();
- __profcxx_hashtable_construct(&__uc, __uc.bucket_count());
+ __profcxx_hashtable_construct(&__uc, __uc.bucket_count());
__profcxx_hashtable_construct2(&__uc);
}
_Unordered_profile(const _Unordered_profile&)
@@ -168,8 +168,8 @@ namespace __profile
~_Unordered_profile() noexcept
{
auto& __uc = _M_conjure();
- __profcxx_hashtable_destruct(&__uc, __uc.bucket_count(), __uc.size());
- _M_profile_destruct();
+ __profcxx_hashtable_destruct(&__uc, __uc.bucket_count(), __uc.size());
+ _M_profile_destruct();
}
_Unordered_profile&
@@ -210,6 +210,7 @@ namespace __profile
auto __lend = __uc.end(__bkt);
for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit)
++__chain;
+
if (__chain)
{
++__chain;
@@ -245,6 +246,7 @@ namespace __profile
__pit = __it;
}
}
+
if (__chain)
{
++__chain;
diff --git a/libstdc++-v3/include/profile/unordered_map b/libstdc++-v3/include/profile/unordered_map
index 994438274f0..e13c069e58e 100644
--- a/libstdc++-v3/include/profile/unordered_map
+++ b/libstdc++-v3/include/profile/unordered_map
@@ -56,73 +56,66 @@ namespace __profile
typedef typename _GLIBCXX_STD_BASE _Base;
_Base&
- _M_base() noexcept { return *this; }
+ _M_base() noexcept { return *this; }
const _Base&
- _M_base() const noexcept { return *this; }
+ _M_base() const noexcept { return *this; }
public:
- typedef typename _Base::size_type size_type;
- typedef typename _Base::hasher hasher;
- typedef typename _Base::key_equal key_equal;
- typedef typename _Base::allocator_type allocator_type;
- typedef typename _Base::key_type key_type;
- typedef typename _Base::value_type value_type;
- typedef typename _Base::difference_type difference_type;
- typedef typename _Base::reference reference;
- typedef typename _Base::const_reference const_reference;
- typedef typename _Base::mapped_type mapped_type;
-
- typedef typename _Base::iterator iterator;
- typedef typename _Base::const_iterator const_iterator;
+ typedef typename _Base::size_type size_type;
+ typedef typename _Base::hasher hasher;
+ typedef typename _Base::key_equal key_equal;
+ typedef typename _Base::allocator_type allocator_type;
+ typedef typename _Base::key_type key_type;
+ typedef typename _Base::value_type value_type;
+ typedef typename _Base::difference_type difference_type;
+ typedef typename _Base::reference reference;
+ typedef typename _Base::const_reference const_reference;
+ typedef typename _Base::mapped_type mapped_type;
+
+ typedef typename _Base::iterator iterator;
+ typedef typename _Base::const_iterator const_iterator;
explicit
unordered_map(size_type __n = 10,
const hasher& __hf = hasher(),
const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type())
- : _Base(__n, __hf, __eql, __a)
- { }
+ : _Base(__n, __hf, __eql, __a) { }
template<typename _InputIterator>
- unordered_map(_InputIterator __f, _InputIterator __l,
+ unordered_map(_InputIterator __f, _InputIterator __l,
size_type __n = 0,
const hasher& __hf = hasher(),
const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type())
- : _Base(__f, __l, __n, __hf, __eql, __a)
- { }
+ : _Base(__f, __l, __n, __hf, __eql, __a) { }
unordered_map(const unordered_map&) = default;
unordered_map(const _Base& __x)
- : _Base(__x)
- { }
+ : _Base(__x) { }
unordered_map(unordered_map&&) = default;
explicit
unordered_map(const allocator_type& __a)
- : _Base(__a)
- { }
+ : _Base(__a) { }
unordered_map(const unordered_map& __umap,
const allocator_type& __a)
- : _Base(__umap, __a)
- { }
+ : _Base(__umap, __a) { }
unordered_map(unordered_map&& __umap,
const allocator_type& __a)
- : _Base(std::move(__umap._M_base()), __a)
- { }
+ : _Base(std::move(__umap._M_base()), __a) { }
unordered_map(initializer_list<value_type> __l,
size_type __n = 0,
const hasher& __hf = hasher(),
const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type())
- : _Base(__l, __n, __hf, __eql, __a)
- { }
+ : _Base(__l, __n, __hf, __eql, __a) { }
unordered_map&
operator=(const unordered_map&) = default;
@@ -140,9 +133,9 @@ namespace __profile
void
clear() noexcept
{
- __profcxx_hashtable_destruct(this, _Base::bucket_count(),
+ __profcxx_hashtable_destruct(this, _Base::bucket_count(),
_Base::size());
- this->_M_profile_destruct();
+ this->_M_profile_destruct();
_Base::clear();
}
@@ -170,81 +163,81 @@ namespace __profile
void
insert(std::initializer_list<value_type> __l)
- {
- size_type __old_size = _Base::bucket_count();
- _Base::insert(__l);
- _M_profile_resize(__old_size);
+ {
+ size_type __old_size = _Base::bucket_count();
+ _Base::insert(__l);
+ _M_profile_resize(__old_size);
}
std::pair<iterator, bool>
insert(const value_type& __obj)
{
- size_type __old_size = _Base::bucket_count();
- std::pair<iterator, bool> __res = _Base::insert(__obj);
- _M_profile_resize(__old_size);
- return __res;
+ size_type __old_size = _Base::bucket_count();
+ std::pair<iterator, bool> __res = _Base::insert(__obj);
+ _M_profile_resize(__old_size);
+ return __res;
}
iterator
insert(const_iterator __iter, const value_type& __v)
- {
- size_type __old_size = _Base::bucket_count();
- iterator __res = _Base::insert(__iter, __v);
- _M_profile_resize(__old_size);
- return __res;
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__iter, __v);
+ _M_profile_resize(__old_size);
+ return __res;
}
template<typename _Pair, typename = typename
std::enable_if<std::is_constructible<value_type,
_Pair&&>::value>::type>
- std::pair<iterator, bool>
- insert(_Pair&& __obj)
- {
+ std::pair<iterator, bool>
+ insert(_Pair&& __obj)
+ {
size_type __old_size = _Base::bucket_count();
std::pair<iterator, bool> __res
= _Base::insert(std::forward<_Pair>(__obj));
- _M_profile_resize(__old_size);
+ _M_profile_resize(__old_size);
return __res;
}
template<typename _Pair, typename = typename
std::enable_if<std::is_constructible<value_type,
_Pair&&>::value>::type>
- iterator
- insert(const_iterator __iter, _Pair&& __v)
- {
- size_type __old_size = _Base::bucket_count();
+ iterator
+ insert(const_iterator __iter, _Pair&& __v)
+ {
+ size_type __old_size = _Base::bucket_count();
iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
- _M_profile_resize(__old_size);
+ _M_profile_resize(__old_size);
return __res;
}
template<typename _InputIter>
- void
- insert(_InputIter __first, _InputIter __last)
- {
- size_type __old_size = _Base::bucket_count();
+ void
+ insert(_InputIter __first, _InputIter __last)
+ {
+ size_type __old_size = _Base::bucket_count();
_Base::insert(__first, __last);
- _M_profile_resize(__old_size);
+ _M_profile_resize(__old_size);
}
// operator[]
mapped_type&
operator[](const _Key& __k)
{
- size_type __old_size = _Base::bucket_count();
- mapped_type& __res = _M_base()[__k];
- _M_profile_resize(__old_size);
- return __res;
+ size_type __old_size = _Base::bucket_count();
+ mapped_type& __res = _M_base()[__k];
+ _M_profile_resize(__old_size);
+ return __res;
}
mapped_type&
operator[](_Key&& __k)
{
- size_type __old_size = _Base::bucket_count();
- mapped_type& __res = _M_base()[std::move(__k)];
- _M_profile_resize(__old_size);
- return __res;
+ size_type __old_size = _Base::bucket_count();
+ mapped_type& __res = _M_base()[std::move(__k)];
+ _M_profile_resize(__old_size);
+ return __res;
}
void
@@ -256,7 +249,7 @@ namespace __profile
{
size_type __old_size = _Base::bucket_count();
_Base::rehash(__n);
- _M_profile_resize(__old_size);
+ _M_profile_resize(__old_size);
}
private:
@@ -305,76 +298,69 @@ namespace __profile
public _Unordered_profile<unordered_multimap<_Key, _Tp,
_Hash, _Pred, _Alloc>,
false>
- {
+ {
typedef typename _GLIBCXX_STD_BASE _Base;
_Base&
- _M_base() noexcept { return *this; }
+ _M_base() noexcept { return *this; }
const _Base&
- _M_base() const noexcept { return *this; }
+ _M_base() const noexcept { return *this; }
public:
- typedef typename _Base::size_type size_type;
- typedef typename _Base::hasher hasher;
- typedef typename _Base::key_equal key_equal;
- typedef typename _Base::allocator_type allocator_type;
- typedef typename _Base::key_type key_type;
- typedef typename _Base::value_type value_type;
- typedef typename _Base::difference_type difference_type;
- typedef typename _Base::reference reference;
- typedef typename _Base::const_reference const_reference;
-
- typedef typename _Base::iterator iterator;
- typedef typename _Base::const_iterator const_iterator;
+ typedef typename _Base::size_type size_type;
+ typedef typename _Base::hasher hasher;
+ typedef typename _Base::key_equal key_equal;
+ typedef typename _Base::allocator_type allocator_type;
+ typedef typename _Base::key_type key_type;
+ typedef typename _Base::value_type value_type;
+ typedef typename _Base::difference_type difference_type;
+ typedef typename _Base::reference reference;
+ typedef typename _Base::const_reference const_reference;
+
+ typedef typename _Base::iterator iterator;
+ typedef typename _Base::const_iterator const_iterator;
explicit
unordered_multimap(size_type __n = 10,
const hasher& __hf = hasher(),
const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type())
- : _Base(__n, __hf, __eql, __a)
- { }
+ : _Base(__n, __hf, __eql, __a) { }
template<typename _InputIterator>
- unordered_multimap(_InputIterator __f, _InputIterator __l,
+ unordered_multimap(_InputIterator __f, _InputIterator __l,
size_type __n = 0,
const hasher& __hf = hasher(),
const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type())
- : _Base(__f, __l, __n, __hf, __eql, __a)
- { }
+ : _Base(__f, __l, __n, __hf, __eql, __a) { }
unordered_multimap(const unordered_multimap&) = default;
unordered_multimap(const _Base& __x)
- : _Base(__x)
- { }
+ : _Base(__x) { }
unordered_multimap(unordered_multimap&&) = default;
explicit
unordered_multimap(const allocator_type& __a)
- : _Base(__a)
- { }
+ : _Base(__a) { }
unordered_multimap(const unordered_multimap& __ummap,
const allocator_type& __a)
- : _Base(__ummap._M_base(), __a)
- { }
+ : _Base(__ummap._M_base(), __a) { }
unordered_multimap(unordered_multimap&& __ummap,
const allocator_type& __a)
- : _Base(std::move(__ummap._M_base()), __a)
- { }
+ : _Base(std::move(__ummap._M_base()), __a) { }
unordered_multimap(initializer_list<value_type> __l,
size_type __n = 0,
const hasher& __hf = hasher(),
const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type())
- : _Base(__l, __n, __hf, __eql, __a)
- { }
+ : _Base(__l, __n, __hf, __eql, __a) { }
unordered_multimap&
operator=(const unordered_multimap&) = default;
@@ -392,7 +378,7 @@ namespace __profile
void
clear() noexcept
{
- __profcxx_hashtable_destruct(this, _Base::bucket_count(),
+ __profcxx_hashtable_destruct(this, _Base::bucket_count(),
_Base::size());
this->_M_profile_destruct();
_Base::clear();
@@ -422,61 +408,61 @@ namespace __profile
void
insert(std::initializer_list<value_type> __l)
- {
- size_type __old_size = _Base::bucket_count();
- _Base::insert(__l);
- _M_profile_resize(__old_size);
+ {
+ size_type __old_size = _Base::bucket_count();
+ _Base::insert(__l);
+ _M_profile_resize(__old_size);
}
iterator
insert(const value_type& __obj)
{
- size_type __old_size = _Base::bucket_count();
- iterator __res = _Base::insert(__obj);
- _M_profile_resize(__old_size);
- return __res;
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__obj);
+ _M_profile_resize(__old_size);
+ return __res;
}
iterator
insert(const_iterator __iter, const value_type& __v)
- {
- size_type __old_size = _Base::bucket_count();
- iterator __res = _Base::insert(__iter, __v);
- _M_profile_resize(__old_size);
- return __res;
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__iter, __v);
+ _M_profile_resize(__old_size);
+ return __res;
}
template<typename _Pair, typename = typename
std::enable_if<std::is_constructible<value_type,
_Pair&&>::value>::type>
- iterator
- insert(_Pair&& __obj)
- {
+ iterator
+ insert(_Pair&& __obj)
+ {
size_type __old_size = _Base::bucket_count();
iterator __res = _Base::insert(std::forward<_Pair>(__obj));
- _M_profile_resize(__old_size);
+ _M_profile_resize(__old_size);
return __res;
}
template<typename _Pair, typename = typename
std::enable_if<std::is_constructible<value_type,
_Pair&&>::value>::type>
- iterator
- insert(const_iterator __iter, _Pair&& __v)
- {
- size_type __old_size = _Base::bucket_count();
+ iterator
+ insert(const_iterator __iter, _Pair&& __v)
+ {
+ size_type __old_size = _Base::bucket_count();
iterator __res = _Base::insert(__iter, std::forward<_Pair>(__v));
- _M_profile_resize(__old_size);
+ _M_profile_resize(__old_size);
return __res;
}
template<typename _InputIter>
- void
- insert(_InputIter __first, _InputIter __last)
- {
- size_type __old_size = _Base::bucket_count();
+ void
+ insert(_InputIter __first, _InputIter __last)
+ {
+ size_type __old_size = _Base::bucket_count();
_Base::insert(__first, __last);
- _M_profile_resize(__old_size);
+ _M_profile_resize(__old_size);
}
void
@@ -487,9 +473,9 @@ namespace __profile
void
rehash(size_type __n)
{
- size_type __old_size = _Base::bucket_count();
- _Base::rehash(__n);
- _M_profile_resize(__old_size);
+ size_type __old_size = _Base::bucket_count();
+ _Base::rehash(__n);
+ _M_profile_resize(__old_size);
}
private:
@@ -497,8 +483,8 @@ namespace __profile
_M_profile_resize(size_type __old_size)
{
size_type __new_size = _Base::bucket_count();
- if (__old_size != __new_size)
- __profcxx_hashtable_resize(this, __old_size, __new_size);
+ if (__old_size != __new_size)
+ __profcxx_hashtable_resize(this, __old_size, __new_size);
}
};
diff --git a/libstdc++-v3/include/profile/unordered_set b/libstdc++-v3/include/profile/unordered_set
index a7f8ea8aa3b..c42ddfeda62 100644
--- a/libstdc++-v3/include/profile/unordered_set
+++ b/libstdc++-v3/include/profile/unordered_set
@@ -44,7 +44,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
namespace __profile
{
/** @brief Unordered_set wrapper with performance instrumentation. */
- template<typename _Key,
+ template<typename _Key,
typename _Hash = std::hash<_Key>,
typename _Pred = std::equal_to<_Key>,
typename _Alloc = std::allocator<_Key> >
@@ -62,18 +62,18 @@ namespace __profile
_M_base() const noexcept { return *this; }
public:
- typedef typename _Base::size_type size_type;
- typedef typename _Base::hasher hasher;
- typedef typename _Base::key_equal key_equal;
- typedef typename _Base::allocator_type allocator_type;
- typedef typename _Base::key_type key_type;
- typedef typename _Base::value_type value_type;
- typedef typename _Base::difference_type difference_type;
- typedef typename _Base::reference reference;
- typedef typename _Base::const_reference const_reference;
-
- typedef typename _Base::iterator iterator;
- typedef typename _Base::const_iterator const_iterator;
+ typedef typename _Base::size_type size_type;
+ typedef typename _Base::hasher hasher;
+ typedef typename _Base::key_equal key_equal;
+ typedef typename _Base::allocator_type allocator_type;
+ typedef typename _Base::key_type key_type;
+ typedef typename _Base::value_type value_type;
+ typedef typename _Base::difference_type difference_type;
+ typedef typename _Base::reference reference;
+ typedef typename _Base::const_reference const_reference;
+
+ typedef typename _Base::iterator iterator;
+ typedef typename _Base::const_iterator const_iterator;
explicit
unordered_set(size_type __n = 10,
@@ -84,7 +84,7 @@ namespace __profile
{ }
template<typename _InputIterator>
- unordered_set(_InputIterator __f, _InputIterator __l,
+ unordered_set(_InputIterator __f, _InputIterator __l,
size_type __n = 0,
const hasher& __hf = hasher(),
const key_equal& __eql = key_equal(),
@@ -144,10 +144,10 @@ namespace __profile
void
clear() noexcept
{
- __profcxx_hashtable_destruct(this, _Base::bucket_count(),
- _Base::size());
- this->_M_profile_destruct();
- _Base::clear();
+ __profcxx_hashtable_destruct(this, _Base::bucket_count(),
+ _Base::size());
+ this->_M_profile_destruct();
+ _Base::clear();
}
template<typename... _Args>
@@ -174,63 +174,63 @@ namespace __profile
void
insert(std::initializer_list<value_type> __l)
- {
- size_type __old_size = _Base::bucket_count();
- _Base::insert(__l);
- _M_profile_resize(__old_size);
+ {
+ size_type __old_size = _Base::bucket_count();
+ _Base::insert(__l);
+ _M_profile_resize(__old_size);
}
std::pair<iterator, bool>
insert(const value_type& __obj)
{
- size_type __old_size = _Base::bucket_count();
- std::pair<iterator, bool> __res = _Base::insert(__obj);
- _M_profile_resize(__old_size);
- return __res;
+ size_type __old_size = _Base::bucket_count();
+ std::pair<iterator, bool> __res = _Base::insert(__obj);
+ _M_profile_resize(__old_size);
+ return __res;
}
iterator
insert(const_iterator __iter, const value_type& __v)
- {
- size_type __old_size = _Base::bucket_count();
- iterator __res = _Base::insert(__iter, __v);
- _M_profile_resize(__old_size);
- return __res;
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__iter, __v);
+ _M_profile_resize(__old_size);
+ return __res;
}
std::pair<iterator, bool>
insert(value_type&& __obj)
{
- size_type __old_size = _Base::bucket_count();
- std::pair<iterator, bool> __res = _Base::insert(std::move(__obj));
- _M_profile_resize(__old_size);
- return __res;
+ size_type __old_size = _Base::bucket_count();
+ std::pair<iterator, bool> __res = _Base::insert(std::move(__obj));
+ _M_profile_resize(__old_size);
+ return __res;
}
iterator
insert(const_iterator __iter, value_type&& __v)
- {
- size_type __old_size = _Base::bucket_count();
- iterator __res = _Base::insert(__iter, std::move(__v));
- _M_profile_resize(__old_size);
- return __res;
+ {
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__iter, std::move(__v));
+ _M_profile_resize(__old_size);
+ return __res;
}
template<typename _InputIter>
- void
- insert(_InputIter __first, _InputIter __last)
- {
- size_type __old_size = _Base::bucket_count();
+ void
+ insert(_InputIter __first, _InputIter __last)
+ {
+ size_type __old_size = _Base::bucket_count();
_Base::insert(__first, __last);
- _M_profile_resize(__old_size);
+ _M_profile_resize(__old_size);
}
void
rehash(size_type __n)
{
- size_type __old_size = _Base::bucket_count();
- _Base::rehash(__n);
- _M_profile_resize(__old_size);
+ size_type __old_size = _Base::bucket_count();
+ _Base::rehash(__n);
+ _M_profile_resize(__old_size);
}
private:
@@ -287,10 +287,10 @@ namespace __profile
public:
typedef typename _Base::size_type size_type;
- typedef typename _Base::hasher hasher;
+ typedef typename _Base::hasher hasher;
typedef typename _Base::key_equal key_equal;
typedef typename _Base::allocator_type allocator_type;
- typedef typename _Base::key_type key_type;
+ typedef typename _Base::key_type key_type;
typedef typename _Base::value_type value_type;
typedef typename _Base::difference_type difference_type;
typedef typename _Base::reference reference;
@@ -308,7 +308,7 @@ namespace __profile
{ }
template<typename _InputIterator>
- unordered_multiset(_InputIterator __f, _InputIterator __l,
+ unordered_multiset(_InputIterator __f, _InputIterator __l,
size_type __n = 0,
const hasher& __hf = hasher(),
const key_equal& __eql = key_equal(),
@@ -368,10 +368,10 @@ namespace __profile
void
clear() noexcept
{
- __profcxx_hashtable_destruct(this, _Base::bucket_count(),
- _Base::size());
- this->_M_profile_destruct();
- _Base::clear();
+ __profcxx_hashtable_destruct(this, _Base::bucket_count(),
+ _Base::size());
+ this->_M_profile_destruct();
+ _Base::clear();
}
template<typename... _Args>
@@ -397,63 +397,63 @@ namespace __profile
void
insert(std::initializer_list<value_type> __l)
- {
- size_type __old_size = _Base::bucket_count();
- _Base::insert(__l);
- _M_profile_resize(__old_size);
+ {
+ size_type __old_size = _Base::bucket_count();
+ _Base::insert(__l);
+ _M_profile_resize(__old_size);
}
iterator
insert(const value_type& __obj)
{
- size_type __old_size = _Base::bucket_count();
- iterator __res = _Base::insert(__obj);
- _M_profile_resize(__old_size);
- return __res;
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__obj);
+ _M_profile_resize(__old_size);
+ return __res;
}
iterator
insert(const_iterator __iter, const value_type& __v)
{
- size_type __old_size = _Base::bucket_count();
- iterator __res = _Base::insert(__iter, __v);
- _M_profile_resize(__old_size);
- return __res;
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__iter, __v);
+ _M_profile_resize(__old_size);
+ return __res;
}
iterator
insert(value_type&& __obj)
{
size_type __old_size = _Base::bucket_count();
- iterator __res = _Base::insert(std::move(__obj));
- _M_profile_resize(__old_size);
- return __res;
+ iterator __res = _Base::insert(std::move(__obj));
+ _M_profile_resize(__old_size);
+ return __res;
}
iterator
insert(const_iterator __iter, value_type&& __v)
{
- size_type __old_size = _Base::bucket_count();
- iterator __res = _Base::insert(__iter, std::move(__v));
- _M_profile_resize(__old_size);
- return __res;
+ size_type __old_size = _Base::bucket_count();
+ iterator __res = _Base::insert(__iter, std::move(__v));
+ _M_profile_resize(__old_size);
+ return __res;
}
template<typename _InputIter>
- void
- insert(_InputIter __first, _InputIter __last)
- {
- size_type __old_size = _Base::bucket_count();
+ void
+ insert(_InputIter __first, _InputIter __last)
+ {
+ size_type __old_size = _Base::bucket_count();
_Base::insert(__first, __last);
- _M_profile_resize(__old_size);
+ _M_profile_resize(__old_size);
}
void
rehash(size_type __n)
{
- size_type __old_size = _Base::bucket_count();
- _Base::rehash(__n);
- _M_profile_resize(__old_size);
+ size_type __old_size = _Base::bucket_count();
+ _Base::rehash(__n);
+ _M_profile_resize(__old_size);
}
private:
@@ -461,8 +461,8 @@ namespace __profile
_M_profile_resize(size_type __old_size)
{
size_type __new_size = _Base::bucket_count();
- if (__old_size != __new_size)
- __profcxx_hashtable_resize(this, __old_size, __new_size);
+ if (__old_size != __new_size)
+ __profcxx_hashtable_resize(this, __old_size, __new_size);
}
};
diff --git a/libstdc++-v3/include/profile/vector b/libstdc++-v3/include/profile/vector
index 5c2c6219029..0933ca34cc2 100644
--- a/libstdc++-v3/include/profile/vector
+++ b/libstdc++-v3/include/profile/vector
@@ -37,87 +37,134 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
namespace __profile
{
- template<typename _Tp,
- typename _Allocator = std::allocator<_Tp> >
- class vector
- : public _GLIBCXX_STD_C::vector<_Tp, _Allocator>
+ template<typename _Vector>
+ class _Vector_profile_pre
{
- typedef _GLIBCXX_STD_C::vector<_Tp, _Allocator> _Base;
+ _Vector&
+ _M_conjure()
+ { return *static_cast<_Vector*>(this); }
+
+ public:
+#if __cplusplus >= 201103L
+ _Vector_profile_pre() = default;
+ _Vector_profile_pre(const _Vector_profile_pre&) = default;
+ _Vector_profile_pre(_Vector_profile_pre&&) = default;
+
+ _Vector_profile_pre&
+ operator=(const _Vector_profile_pre&) = default;
- typedef typename _Base::iterator _Base_iterator;
- typedef typename _Base::const_iterator _Base_const_iterator;
+ _Vector_profile_pre&
+ operator=(_Vector_profile_pre&&) noexcept
+ { _M_profile_destruct(); }
+#endif
+
+ void
+ _M_profile_destruct()
+ {
+ __profcxx_vector_destruct2(&_M_conjure());
+ __profcxx_vector_destruct(&_M_conjure(),
+ _M_conjure().capacity(), _M_conjure().size());
+ }
+ };
+
+ template<typename _Vector>
+ class _Vector_profile_post
+ {
+ _Vector&
+ _M_conjure()
+ { return *static_cast<_Vector*>(this); }
+
+ protected:
+ _Vector_profile_post() _GLIBCXX_NOEXCEPT
+ {
+ __profcxx_vector_construct(&_M_conjure(), _M_conjure().capacity());
+ __profcxx_vector_construct2(&_M_conjure());
+ }
#if __cplusplus >= 201103L
- typedef __gnu_cxx::__alloc_traits<_Allocator> _Alloc_traits;
+ _Vector_profile_post(const _Vector_profile_post&) noexcept
+ : _Vector_profile_post() { }
+ _Vector_profile_post(_Vector_profile_post&&) noexcept
+ : _Vector_profile_post() { }
+
+ _Vector_profile_post&
+ operator=(const _Vector_profile_post&) = default;
+ _Vector_profile_post&
+ operator=(_Vector_profile_post&&) = default;
#endif
+ ~_Vector_profile_post()
+ { _M_conjure()._M_profile_destruct(); }
+ };
+
+ template<typename _Tp,
+ typename _Allocator = std::allocator<_Tp> >
+ class vector
+ : public _Vector_profile_pre<vector<_Tp, _Allocator> >,
+ public _GLIBCXX_STD_C::vector<_Tp, _Allocator>,
+ public _Vector_profile_post<vector<_Tp, _Allocator> >
+ {
+ typedef _GLIBCXX_STD_C::vector<_Tp, _Allocator> _Base;
+
+ typedef typename _Base::iterator _Base_iterator;
+ typedef typename _Base::const_iterator _Base_const_iterator;
+
public:
- typedef typename _Base::reference reference;
- typedef typename _Base::const_reference const_reference;
+ typedef typename _Base::reference reference;
+ typedef typename _Base::const_reference const_reference;
typedef __iterator_tracker<_Base_iterator, vector>
- iterator;
+ iterator;
typedef __iterator_tracker<_Base_const_iterator, vector>
- const_iterator;
-
- typedef typename _Base::size_type size_type;
- typedef typename _Base::difference_type difference_type;
-
- typedef _Tp value_type;
- typedef _Allocator allocator_type;
- typedef typename _Base::pointer pointer;
- typedef typename _Base::const_pointer const_pointer;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-
+ const_iterator;
+
+ typedef typename _Base::size_type size_type;
+ typedef typename _Base::difference_type difference_type;
+
+ typedef _Tp value_type;
+ typedef _Allocator allocator_type;
+ typedef typename _Base::pointer pointer;
+ typedef typename _Base::const_pointer const_pointer;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
_Base&
- _M_base() _GLIBCXX_NOEXCEPT { return *this; }
+ _M_base() _GLIBCXX_NOEXCEPT { return *this; }
const _Base&
- _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
+ _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
// 23.2.4.1 construct/copy/destroy:
- vector() _GLIBCXX_NOEXCEPT
- : _Base()
- {
- __profcxx_vector_construct(this, this->capacity());
- __profcxx_vector_construct2(this);
- }
+#if __cplusplus < 201103L
+ vector()
+ { }
+
+ vector(const vector& __x)
+ : _Base(__x) { }
+#else
+ vector() = default;
+ vector(const vector&) = default;
+ vector(vector&&) = default;
+#endif
explicit
vector(const _Allocator& __a) _GLIBCXX_NOEXCEPT
- : _Base(__a)
- {
- __profcxx_vector_construct(this, this->capacity());
- __profcxx_vector_construct2(this);
- }
+ : _Base(__a) { }
#if __cplusplus >= 201103L
explicit
vector(size_type __n, const _Allocator& __a = _Allocator())
- : _Base(__n, __a)
- {
- __profcxx_vector_construct(this, this->capacity());
- __profcxx_vector_construct2(this);
- }
+ : _Base(__n, __a) { }
vector(size_type __n, const _Tp& __value,
const _Allocator& __a = _Allocator())
- : _Base(__n, __value, __a)
- {
- __profcxx_vector_construct(this, this->capacity());
- __profcxx_vector_construct2(this);
- }
+ : _Base(__n, __value, __a) { }
#else
explicit
vector(size_type __n, const _Tp& __value = _Tp(),
const _Allocator& __a = _Allocator())
- : _Base(__n, __value, __a)
- {
- __profcxx_vector_construct(this, this->capacity());
- __profcxx_vector_construct2(this);
- }
+ : _Base(__n, __value, __a) { }
#endif
#if __cplusplus >= 201103L
@@ -126,91 +173,48 @@ namespace __profile
#else
template<typename _InputIterator>
#endif
- vector(_InputIterator __first, _InputIterator __last,
+ vector(_InputIterator __first, _InputIterator __last,
const _Allocator& __a = _Allocator())
- : _Base(__first, __last, __a)
- {
- __profcxx_vector_construct(this, this->capacity());
- __profcxx_vector_construct2(this);
- }
+ : _Base(__first, __last, __a) { }
- vector(const vector& __x)
- : _Base(__x)
- {
- __profcxx_vector_construct(this, this->capacity());
- __profcxx_vector_construct2(this);
- }
-
- /// Construction from a release-mode vector
+ /// Construction from a normal-mode vector
vector(const _Base& __x)
- : _Base(__x)
- {
- __profcxx_vector_construct(this, this->capacity());
- __profcxx_vector_construct2(this);
- }
+ : _Base(__x) { }
#if __cplusplus >= 201103L
- vector(vector&& __x) noexcept
- : _Base(std::move(__x))
- {
- __profcxx_vector_construct(this, this->capacity());
- __profcxx_vector_construct2(this);
- }
-
vector(const _Base& __x, const _Allocator& __a)
- : _Base(__x, __a)
- {
- __profcxx_vector_construct(this, this->capacity());
- __profcxx_vector_construct2(this);
- }
+ : _Base(__x, __a) { }
vector(vector&& __x, const _Allocator& __a)
- : _Base(std::move(__x), __a)
- {
- __profcxx_vector_construct(this, this->capacity());
- __profcxx_vector_construct2(this);
- }
+ : _Base(std::move(__x), __a) { }
vector(initializer_list<value_type> __l,
const allocator_type& __a = allocator_type())
: _Base(__l, __a) { }
#endif
- ~vector() _GLIBCXX_NOEXCEPT
- {
- __profcxx_vector_destruct(this, this->capacity(), this->size());
- __profcxx_vector_destruct2(this);
- }
-
+#if __cplusplus < 201103L
vector&
operator=(const vector& __x)
{
- static_cast<_Base&>(*this) = __x;
- return *this;
+ _M_base() = __x;
+ return *this;
}
+#else
+ vector&
+ operator=(const vector&) = default;
-#if __cplusplus >= 201103L
vector&
- operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __profcxx_vector_destruct(this, this->capacity(), this->size());
- __profcxx_vector_destruct2(this);
- static_cast<_Base&>(*this) = std::move(__x);
- return *this;
- }
+ operator=(vector&&) = default;
vector&
operator=(initializer_list<value_type> __l)
{
- static_cast<_Base&>(*this) = __l;
+ _M_base() = __l;
return *this;
}
#endif
- using _Base::assign;
- using _Base::get_allocator;
-
-
// iterators:
iterator
begin() _GLIBCXX_NOEXCEPT
@@ -263,183 +267,135 @@ namespace __profile
#endif
// 23.2.4.2 capacity:
- using _Base::size;
- using _Base::max_size;
#if __cplusplus >= 201103L
void
resize(size_type __sz)
{
- __profcxx_vector_invalid_operator(this);
- _M_profile_resize(this, this->capacity(), __sz);
- _Base::resize(__sz);
+ __profcxx_vector_invalid_operator(this);
+ _M_profile_resize(this->capacity(), __sz);
+ _Base::resize(__sz);
}
void
resize(size_type __sz, const _Tp& __c)
{
- __profcxx_vector_invalid_operator(this);
- _M_profile_resize(this, this->capacity(), __sz);
- _Base::resize(__sz, __c);
+ __profcxx_vector_invalid_operator(this);
+ _M_profile_resize(this->capacity(), __sz);
+ _Base::resize(__sz, __c);
}
#else
void
resize(size_type __sz, _Tp __c = _Tp())
{
- __profcxx_vector_invalid_operator(this);
- _M_profile_resize(this, this->capacity(), __sz);
- _Base::resize(__sz, __c);
+ __profcxx_vector_invalid_operator(this);
+ _M_profile_resize(this->capacity(), __sz);
+ _Base::resize(__sz, __c);
}
#endif
-#if __cplusplus >= 201103L
- using _Base::shrink_to_fit;
-#endif
-
- using _Base::empty;
-
// element access:
reference
operator[](size_type __n) _GLIBCXX_NOEXCEPT
{
- __profcxx_vector_invalid_operator(this);
- return _M_base()[__n];
+ __profcxx_vector_invalid_operator(this);
+ return _M_base()[__n];
}
const_reference
operator[](size_type __n) const _GLIBCXX_NOEXCEPT
{
- __profcxx_vector_invalid_operator(this);
- return _M_base()[__n];
- }
-
- using _Base::at;
-
- reference
- front() _GLIBCXX_NOEXCEPT
- {
- return _Base::front();
- }
-
- const_reference
- front() const _GLIBCXX_NOEXCEPT
- {
- return _Base::front();
+ __profcxx_vector_invalid_operator(this);
+ return _M_base()[__n];
}
- reference
- back() _GLIBCXX_NOEXCEPT
- {
- return _Base::back();
- }
-
- const_reference
- back() const _GLIBCXX_NOEXCEPT
- {
- return _Base::back();
- }
-
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // DR 464. Suggestion for new member functions in standard containers.
- using _Base::data;
-
// 23.2.4.3 modifiers:
void
push_back(const _Tp& __x)
{
- size_type __old_size = this->capacity();
+ size_type __old_size = this->capacity();
_Base::push_back(__x);
- _M_profile_resize(this, __old_size, this->capacity());
+ _M_profile_resize(__old_size, this->capacity());
}
#if __cplusplus >= 201103L
void
push_back(_Tp&& __x)
{
- size_type __old_size = this->capacity();
- _Base::push_back(std::move(__x));
- _M_profile_resize(this, __old_size, this->capacity());
+ size_type __old_size = this->capacity();
+ _Base::push_back(std::move(__x));
+ _M_profile_resize(__old_size, this->capacity());
}
#endif
iterator
#if __cplusplus >= 201103L
- insert(const_iterator __position, const _Tp& __x)
+ insert(const_iterator __pos, const _Tp& __x)
#else
- insert(iterator __position, const _Tp& __x)
+ insert(iterator __pos, const _Tp& __x)
#endif
{
- __profcxx_vector_insert(this, __position.base() - _Base::begin(),
- this->size());
- size_type __old_size = this->capacity();
- _Base_iterator __res = _Base::insert(__position.base(), __x);
- _M_profile_resize(this, __old_size, this->capacity());
+ __profcxx_vector_insert(this, __pos.base() - _Base::begin(),
+ this->size());
+ size_type __old_size = this->capacity();
+ _Base_iterator __res = _Base::insert(__pos.base(), __x);
+ _M_profile_resize(__old_size, this->capacity());
return iterator(__res, this);
}
#if __cplusplus >= 201103L
iterator
- insert(const_iterator __position, _Tp&& __x)
+ insert(const_iterator __pos, _Tp&& __x)
{
- __profcxx_vector_insert(this, __position.base() - _Base::cbegin(),
- this->size());
- size_type __old_size = this->capacity();
- _Base_iterator __res = _Base::insert(__position.base(), __x);
- _M_profile_resize(this, __old_size, this->capacity());
+ __profcxx_vector_insert(this, __pos.base() - _Base::cbegin(),
+ this->size());
+ size_type __old_size = this->capacity();
+ _Base_iterator __res = _Base::insert(__pos.base(), __x);
+ _M_profile_resize(__old_size, this->capacity());
return iterator(__res, this);
}
template<typename... _Args>
- iterator
- emplace(const_iterator __position, _Args&&... __args)
- {
- _Base_iterator __res = _Base::emplace(__position.base(),
+ iterator
+ emplace(const_iterator __pos, _Args&&... __args)
+ {
+ _Base_iterator __res = _Base::emplace(__pos.base(),
std::forward<_Args>(__args)...);
return iterator(__res, this);
}
iterator
- insert(const_iterator __position, initializer_list<value_type> __l)
- { return this->insert(__position, __l.begin(), __l.end()); }
-#endif
-
-#if __cplusplus >= 201103L
- void
- swap(vector&& __x)
- {
- _Base::swap(__x);
- }
+ insert(const_iterator __pos, initializer_list<value_type> __l)
+ { return this->insert(__pos, __l.begin(), __l.end()); }
#endif
void
swap(vector& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
- {
- _Base::swap(__x);
- }
+ { _Base::swap(__x); }
#if __cplusplus >= 201103L
iterator
- insert(const_iterator __position, size_type __n, const _Tp& __x)
+ insert(const_iterator __pos, size_type __n, const _Tp& __x)
{
- __profcxx_vector_insert(this, __position.base() - _Base::cbegin(),
- this->size());
- size_type __old_size = this->capacity();
- _Base_iterator __res = _Base::insert(__position, __n, __x);
- _M_profile_resize(this, __old_size, this->capacity());
+ __profcxx_vector_insert(this, __pos.base() - _Base::cbegin(),
+ this->size());
+ size_type __old_size = this->capacity();
+ _Base_iterator __res = _Base::insert(__pos, __n, __x);
+ _M_profile_resize(__old_size, this->capacity());
return iterator(__res, this);
}
#else
void
- insert(iterator __position, size_type __n, const _Tp& __x)
+ insert(iterator __pos, size_type __n, const _Tp& __x)
{
- __profcxx_vector_insert(this, __position.base() - _Base::begin(),
- this->size());
- size_type __old_size = this->capacity();
- _Base::insert(__position, __n, __x);
- _M_profile_resize(this, __old_size, this->capacity());
+ __profcxx_vector_insert(this, __pos.base() - _Base::begin(),
+ this->size());
+ size_type __old_size = this->capacity();
+ _Base::insert(__pos, __n, __x);
+ _M_profile_resize(__old_size, this->capacity());
}
#endif
@@ -447,40 +403,37 @@ namespace __profile
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
iterator
- insert(const_iterator __position,
+ insert(const_iterator __pos,
_InputIterator __first, _InputIterator __last)
- {
- __profcxx_vector_insert(this, __position.base() - _Base::cbegin(),
+ {
+ __profcxx_vector_insert(this, __pos.base() - _Base::cbegin(),
this->size());
size_type __old_size = this->capacity();
- _Base_iterator __res = _Base::insert(__position, __first, __last);
- _M_profile_resize(this, __old_size, this->capacity());
+ _Base_iterator __res = _Base::insert(__pos, __first, __last);
+ _M_profile_resize(__old_size, this->capacity());
return iterator(__res, this);
}
#else
template<typename _InputIterator>
void
- insert(iterator __position,
+ insert(iterator __pos,
_InputIterator __first, _InputIterator __last)
- {
- __profcxx_vector_insert(this, __position.base() - _Base::begin(),
+ {
+ __profcxx_vector_insert(this, __pos.base() - _Base::begin(),
this->size());
size_type __old_size = this->capacity();
- _Base::insert(__position, __first, __last);
- _M_profile_resize(this, __old_size, this->capacity());
+ _Base::insert(__pos, __first, __last);
+ _M_profile_resize(__old_size, this->capacity());
}
#endif
iterator
#if __cplusplus >= 201103L
- erase(const_iterator __position)
+ erase(const_iterator __pos)
#else
- erase(iterator __position)
+ erase(iterator __pos)
#endif
- {
- _Base_iterator __res = _Base::erase(__position.base());
- return iterator(__res, this);
- }
+ { return iterator(_Base::erase(__pos.base()), this); }
iterator
#if __cplusplus >= 201103L
@@ -488,76 +441,66 @@ namespace __profile
#else
erase(iterator __first, iterator __last)
#endif
- {
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 151. can't currently clear() empty container
- _Base_iterator __res = _Base::erase(__first.base(), __last.base());
- return iterator(__res, this);
- }
+ { return iterator(_Base::erase(__first.base(), __last.base()), this); }
void
clear() _GLIBCXX_NOEXCEPT
{
- __profcxx_vector_destruct(this, this->capacity(), this->size());
- __profcxx_vector_destruct2(this);
- _Base::clear();
+ this->_M_profile_destruct();
+ _Base::clear();
}
- inline void _M_profile_find() const
- {
- __profcxx_vector_find(this, size());
- }
+ inline void _M_profile_find() const
+ { __profcxx_vector_find(this, this->size()); }
- inline void _M_profile_iterate(int __rewind = 0) const
- {
- __profcxx_vector_iterate(this);
- }
+ inline void _M_profile_iterate(int __rewind = 0) const
+ { __profcxx_vector_iterate(this); }
private:
- void _M_profile_resize(void* obj, size_type __old_size,
- size_type __new_size)
+ void _M_profile_resize(size_type __old_size, size_type __new_size)
{
- if (__old_size < __new_size) {
- __profcxx_vector_resize(this, this->size(), __new_size);
- __profcxx_vector_resize2(this, this->size(), __new_size);
- }
+ if (__old_size < __new_size)
+ {
+ __profcxx_vector_resize(this, this->size(), __new_size);
+ __profcxx_vector_resize2(this, this->size(), __new_size);
+ }
}
};
template<typename _Tp, typename _Alloc>
inline bool
operator==(const vector<_Tp, _Alloc>& __lhs,
- const vector<_Tp, _Alloc>& __rhs)
+ const vector<_Tp, _Alloc>& __rhs)
{ return __lhs._M_base() == __rhs._M_base(); }
template<typename _Tp, typename _Alloc>
inline bool
operator!=(const vector<_Tp, _Alloc>& __lhs,
- const vector<_Tp, _Alloc>& __rhs)
+ const vector<_Tp, _Alloc>& __rhs)
{ return __lhs._M_base() != __rhs._M_base(); }
template<typename _Tp, typename _Alloc>
inline bool
operator<(const vector<_Tp, _Alloc>& __lhs,
- const vector<_Tp, _Alloc>& __rhs)
+ const vector<_Tp, _Alloc>& __rhs)
{ return __lhs._M_base() < __rhs._M_base(); }
template<typename _Tp, typename _Alloc>
inline bool
operator<=(const vector<_Tp, _Alloc>& __lhs,
- const vector<_Tp, _Alloc>& __rhs)
+ const vector<_Tp, _Alloc>& __rhs)
{ return __lhs._M_base() <= __rhs._M_base(); }
template<typename _Tp, typename _Alloc>
inline bool
operator>=(const vector<_Tp, _Alloc>& __lhs,
- const vector<_Tp, _Alloc>& __rhs)
+ const vector<_Tp, _Alloc>& __rhs)
{ return __lhs._M_base() >= __rhs._M_base(); }
template<typename _Tp, typename _Alloc>
inline bool
operator>(const vector<_Tp, _Alloc>& __lhs,
- const vector<_Tp, _Alloc>& __rhs)
+ const vector<_Tp, _Alloc>& __rhs)
{ return __lhs._M_base() > __rhs._M_base(); }
template<typename _Tp, typename _Alloc>
diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array
index 67680d61e58..cc2c864ebd6 100644
--- a/libstdc++-v3/include/std/array
+++ b/libstdc++-v3/include/std/array
@@ -281,7 +281,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
get(array<_Tp, _Nm>&& __arr) noexcept
{
static_assert(_Int < _Nm, "index is out of bounds");
- return std::move(get<_Int>(__arr));
+ return std::move(_GLIBCXX_STD_C::get<_Int>(__arr));
}
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
@@ -306,6 +306,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
class tuple_size;
+ /// Partial specialization for std::array
template<typename _Tp, std::size_t _Nm>
struct tuple_size<_GLIBCXX_STD_C::array<_Tp, _Nm>>
: public integral_constant<std::size_t, _Nm> { };
@@ -314,6 +315,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<std::size_t _Int, typename _Tp>
class tuple_element;
+ /// Partial specialization for std::array
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
struct tuple_element<_Int, _GLIBCXX_STD_C::array<_Tp, _Nm>>
{
diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
index b114e02f0c2..39ad5e3ba83 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -787,117 +787,79 @@ _GLIBCXX_END_NAMESPACE_VERSION
inline namespace chrono_literals
{
- namespace __select_type
- {
-
- using namespace __parse_int;
-
- template<unsigned long long _Val, typename _Dur>
- struct _Select_type
- : conditional<
- _Val <= static_cast<unsigned long long>
- (numeric_limits<typename _Dur::rep>::max()),
- _Dur, void>
- {
- static constexpr typename _Select_type::type
- value{static_cast<typename _Select_type::type>(_Val)};
- };
-
- template<unsigned long long _Val, typename _Dur>
- constexpr typename _Select_type<_Val, _Dur>::type
- _Select_type<_Val, _Dur>::value;
+ template<typename _Rep, unsigned long long _Val>
+ struct _Checked_integral_constant
+ : integral_constant<_Rep, static_cast<_Rep>(_Val)>
+ {
+ static_assert(_Checked_integral_constant::value > 0
+ && _Checked_integral_constant::value == _Val,
+ "literal value cannot be represented by duration type");
+ };
- } // __select_type
+ template<typename _Dur, char... _Digits>
+ constexpr _Dur __check_overflow()
+ {
+ using _Val = __parse_int::_Parse_int<_Digits...>;
+ using _Rep = typename _Dur::rep;
+ // TODO: should be simply integral_constant<_Rep, _Val::value>
+ // but GCC doesn't reject narrowing conversions to _Rep.
+ using _CheckedVal = _Checked_integral_constant<_Rep, _Val::value>;
+ return _Dur{_CheckedVal::value};
+ }
constexpr chrono::duration<long double, ratio<3600,1>>
operator""h(long double __hours)
{ return chrono::duration<long double, ratio<3600,1>>{__hours}; }
template <char... _Digits>
- constexpr typename
- __select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
- chrono::hours>::type
+ constexpr chrono::hours
operator""h()
- {
- return __select_type::_Select_type<
- __select_int::_Select_int<_Digits...>::value,
- chrono::hours>::value;
- }
+ { return __check_overflow<chrono::hours, _Digits...>(); }
constexpr chrono::duration<long double, ratio<60,1>>
operator""min(long double __mins)
{ return chrono::duration<long double, ratio<60,1>>{__mins}; }
template <char... _Digits>
- constexpr typename
- __select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
- chrono::minutes>::type
+ constexpr chrono::minutes
operator""min()
- {
- return __select_type::_Select_type<
- __select_int::_Select_int<_Digits...>::value,
- chrono::minutes>::value;
- }
+ { return __check_overflow<chrono::minutes, _Digits...>(); }
constexpr chrono::duration<long double>
operator""s(long double __secs)
{ return chrono::duration<long double>{__secs}; }
template <char... _Digits>
- constexpr typename
- __select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
- chrono::seconds>::type
+ constexpr chrono::seconds
operator""s()
- {
- return __select_type::_Select_type<
- __select_int::_Select_int<_Digits...>::value,
- chrono::seconds>::value;
- }
+ { return __check_overflow<chrono::seconds, _Digits...>(); }
constexpr chrono::duration<long double, milli>
operator""ms(long double __msecs)
{ return chrono::duration<long double, milli>{__msecs}; }
template <char... _Digits>
- constexpr typename
- __select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
- chrono::milliseconds>::type
+ constexpr chrono::milliseconds
operator""ms()
- {
- return __select_type::_Select_type<
- __select_int::_Select_int<_Digits...>::value,
- chrono::milliseconds>::value;
- }
+ { return __check_overflow<chrono::milliseconds, _Digits...>(); }
constexpr chrono::duration<long double, micro>
operator""us(long double __usecs)
{ return chrono::duration<long double, micro>{__usecs}; }
template <char... _Digits>
- constexpr typename
- __select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
- chrono::microseconds>::type
+ constexpr chrono::microseconds
operator""us()
- {
- return __select_type::_Select_type<
- __select_int::_Select_int<_Digits...>::value,
- chrono::microseconds>::value;
- }
+ { return __check_overflow<chrono::microseconds, _Digits...>(); }
constexpr chrono::duration<long double, nano>
operator""ns(long double __nsecs)
{ return chrono::duration<long double, nano>{__nsecs}; }
template <char... _Digits>
- constexpr typename
- __select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
- chrono::nanoseconds>::type
+ constexpr chrono::nanoseconds
operator""ns()
- {
- return __select_type::_Select_type<
- __select_int::_Select_int<_Digits...>::value,
- chrono::nanoseconds>::value;
- }
+ { return __check_overflow<chrono::nanoseconds, _Digits...>(); }
} // inline namespace chrono_literals
} // inline namespace literals
diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable
index fc111dd3d37..921cb837de9 100644
--- a/libstdc++-v3/include/std/condition_variable
+++ b/libstdc++-v3/include/std/condition_variable
@@ -189,7 +189,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
~_Unlock() noexcept(false)
{
if (uncaught_exception())
- __try { _M_lock.lock(); } __catch(...) { }
+ {
+ __try
+ { _M_lock.lock(); }
+ __catch(const __cxxabiv1::__forced_unwind&)
+ { __throw_exception_again; }
+ __catch(...)
+ { }
+ }
else
_M_lock.lock();
}
diff --git a/libstdc++-v3/include/std/fstream b/libstdc++-v3/include/std/fstream
index 17ccac62868..51db21b525c 100644
--- a/libstdc++-v3/include/std/fstream
+++ b/libstdc++-v3/include/std/fstream
@@ -71,6 +71,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _CharT, typename _Traits>
class basic_filebuf : public basic_streambuf<_CharT, _Traits>
{
+#if __cplusplus >= 201103L
+ template<typename _Tp>
+ using __chk_state = __and_<is_copy_assignable<_Tp>,
+ is_copy_constructible<_Tp>,
+ is_default_constructible<_Tp>>;
+
+ static_assert(__chk_state<typename _Traits::state_type>::value,
+ "state_type must be CopyAssignable, CopyConstructible"
+ " and DefaultConstructible");
+
+ static_assert(is_same<typename _Traits::pos_type,
+ fpos<typename _Traits::state_type>>::value,
+ "pos_type must be fpos<state_type>");
+#endif
public:
// Types:
typedef _CharT char_type;
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 295022de8ee..e677c248d27 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -1120,7 +1120,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
const _Index_tuple<_Indexes...>&) const volatile
-> decltype(__arg(declval<_Args>()...))
{
- return __arg(std::forward<_Args>(get<_Indexes>(__tuple))...);
+ return __arg(std::forward<_Args>(std::get<_Indexes>(__tuple))...);
}
};
@@ -1230,14 +1230,14 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
template<std::size_t _Ind, typename... _Tp>
inline auto
__volget(volatile tuple<_Tp...>& __tuple)
- -> typename tuple_element<_Ind, tuple<_Tp...>>::type volatile&
+ -> __tuple_element_t<_Ind, tuple<_Tp...>> volatile&
{ return std::get<_Ind>(const_cast<tuple<_Tp...>&>(__tuple)); }
// std::get<I> for const-volatile-qualified tuples
template<std::size_t _Ind, typename... _Tp>
inline auto
__volget(const volatile tuple<_Tp...>& __tuple)
- -> typename tuple_element<_Ind, tuple<_Tp...>>::type const volatile&
+ -> __tuple_element_t<_Ind, tuple<_Tp...>> const volatile&
{ return std::get<_Ind>(const_cast<const tuple<_Tp...>&>(__tuple)); }
/// Type of the function object returned from bind().
@@ -1261,7 +1261,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
__call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>)
{
return _M_f(_Mu<_Bound_args>()
- (get<_Indexes>(_M_bound_args), __args)...);
+ (std::get<_Indexes>(_M_bound_args), __args)...);
}
// Call as const
@@ -1270,7 +1270,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
__call_c(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const
{
return _M_f(_Mu<_Bound_args>()
- (get<_Indexes>(_M_bound_args), __args)...);
+ (std::get<_Indexes>(_M_bound_args), __args)...);
}
// Call as volatile
@@ -1393,7 +1393,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
typename __disable_if_void<_Res>::type = 0)
{
return _M_f(_Mu<_Bound_args>()
- (get<_Indexes>(_M_bound_args), __args)...);
+ (std::get<_Indexes>(_M_bound_args), __args)...);
}
// Call unqualified, return void
@@ -1403,7 +1403,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
typename __enable_if_void<_Res>::type = 0)
{
_M_f(_Mu<_Bound_args>()
- (get<_Indexes>(_M_bound_args), __args)...);
+ (std::get<_Indexes>(_M_bound_args), __args)...);
}
// Call as const
@@ -1413,7 +1413,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
typename __disable_if_void<_Res>::type = 0) const
{
return _M_f(_Mu<_Bound_args>()
- (get<_Indexes>(_M_bound_args), __args)...);
+ (std::get<_Indexes>(_M_bound_args), __args)...);
}
// Call as const, return void
@@ -1423,7 +1423,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
typename __enable_if_void<_Res>::type = 0) const
{
_M_f(_Mu<_Bound_args>()
- (get<_Indexes>(_M_bound_args), __args)...);
+ (std::get<_Indexes>(_M_bound_args), __args)...);
}
// Call as volatile
diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future
index 717ce7105df..094914448c4 100644
--- a/libstdc++-v3/include/std/future
+++ b/libstdc++-v3/include/std/future
@@ -365,12 +365,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
_M_set_result(function<_Ptr_type()> __res, bool __ignore_failure = false)
{
- bool __set = __ignore_failure;
+ unique_lock<mutex> __lock(_M_mutex, defer_lock);
// all calls to this function are serialized,
// side-effects of invoking __res only happen once
- call_once(_M_once, &_State_baseV2::_M_do_set, this, ref(__res),
- ref(__set));
- if (!__set)
+ call_once(_M_once, &_State_baseV2::_M_do_set, this,
+ ref(__res), ref(__lock));
+ if (__lock.owns_lock())
+ _M_cond.notify_all();
+ else if (!__ignore_failure)
__throw_future_error(int(future_errc::promise_already_satisfied));
}
@@ -478,15 +480,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
private:
void
- _M_do_set(function<_Ptr_type()>& __f, bool& __set)
+ _M_do_set(function<_Ptr_type()>& __f, unique_lock<mutex>& __lock)
{
- _Ptr_type __res = __f();
- {
- lock_guard<mutex> __lock(_M_mutex);
- _M_result.swap(__res);
- }
- _M_cond.notify_all();
- __set = true;
+ _Ptr_type __res = __f(); // do not hold lock while running setter
+ __lock.lock();
+ _M_result.swap(__res);
}
bool _M_ready() const noexcept { return static_cast<bool>(_M_result); }
@@ -495,6 +493,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
virtual void _M_complete_async() { }
// Return true if state contains a deferred function.
+ // Caller must own _M_mutex.
virtual bool _M_has_deferred() const { return false; }
};
@@ -1231,6 +1230,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_M_result->_M_set(_M_fn());
}
+ __catch(const __cxxabiv1::__forced_unwind&)
+ {
+ __throw_exception_again; // will cause broken_promise
+ }
__catch(...)
{
_M_result->_M_error = current_exception();
@@ -1250,6 +1253,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_M_fn();
}
+ __catch(const __cxxabiv1::__forced_unwind&)
+ {
+ __throw_exception_again; // will cause broken_promise
+ }
__catch(...)
{
_M_result->_M_error = current_exception();
@@ -1510,7 +1517,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: _M_result(new _Result<_Res>()), _M_fn(std::move(__fn))
{
_M_thread = std::thread{ [this] {
- _M_set_result(_S_task_setter(_M_result, _M_fn));
+ __try
+ {
+ _M_set_result(_S_task_setter(_M_result, _M_fn));
+ }
+ __catch (const __cxxabiv1::__forced_unwind&)
+ {
+ // make the shared state ready on thread cancellation
+ if (static_cast<bool>(_M_result))
+ this->_M_break_promise(std::move(_M_result));
+ __throw_exception_again;
+ }
} };
}
diff --git a/libstdc++-v3/include/std/iostream b/libstdc++-v3/include/std/iostream
index 85d2b959ffe..5c1086909a4 100644
--- a/libstdc++-v3/include/std/iostream
+++ b/libstdc++-v3/include/std/iostream
@@ -48,13 +48,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* The &lt;iostream&gt; header declares the eight <em>standard stream
* objects</em>. For other declarations, see
- * http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt11ch24.html
+ * http://gcc.gnu.org/onlinedocs/libstdc++/manual/io.html
* and the @link iosfwd I/O forward declarations @endlink
*
* They are required by default to cooperate with the global C
* library's @c FILE streams, and to be available during program
- * startup and termination. For more information, see the HOWTO
- * linked to above.
+ * startup and termination. For more information, see the section of the
+ * manual linked to above.
*/
//@{
extern istream cin; /// Linked to standard input
diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex
index 0b481d609fe..f6b851c90b0 100644
--- a/libstdc++-v3/include/std/mutex
+++ b/libstdc++-v3/include/std/mutex
@@ -44,6 +44,7 @@
#include <bits/functexcept.h>
#include <bits/gthr.h>
#include <bits/move.h> // for std::swap
+#include <bits/cxxabi_forced.h>
#ifdef _GLIBCXX_USE_C99_STDINT_TR1
@@ -400,22 +401,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ }
explicit unique_lock(mutex_type& __m)
- : _M_device(&__m), _M_owns(false)
+ : _M_device(std::__addressof(__m)), _M_owns(false)
{
lock();
_M_owns = true;
}
unique_lock(mutex_type& __m, defer_lock_t) noexcept
- : _M_device(&__m), _M_owns(false)
+ : _M_device(std::__addressof(__m)), _M_owns(false)
{ }
unique_lock(mutex_type& __m, try_to_lock_t)
- : _M_device(&__m), _M_owns(_M_device->try_lock())
+ : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock())
{ }
unique_lock(mutex_type& __m, adopt_lock_t)
- : _M_device(&__m), _M_owns(true)
+ : _M_device(std::__addressof(__m)), _M_owns(true)
{
// XXX calling thread owns mutex
}
@@ -423,13 +424,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Clock, typename _Duration>
unique_lock(mutex_type& __m,
const chrono::time_point<_Clock, _Duration>& __atime)
- : _M_device(&__m), _M_owns(_M_device->try_lock_until(__atime))
+ : _M_device(std::__addressof(__m)),
+ _M_owns(_M_device->try_lock_until(__atime))
{ }
template<typename _Rep, typename _Period>
unique_lock(mutex_type& __m,
const chrono::duration<_Rep, _Period>& __rtime)
- : _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime))
+ : _M_device(std::__addressof(__m)),
+ _M_owns(_M_device->try_lock_for(__rtime))
{ }
~unique_lock()
@@ -563,37 +566,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool _M_owns; // XXX use atomic_bool
};
- /// Partial specialization for unique_lock objects.
+ /// Swap overload for unique_lock objects.
template<typename _Mutex>
inline void
swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
{ __x.swap(__y); }
- template<int _Idx>
- struct __unlock_impl
- {
- template<typename... _Lock>
- static void
- __do_unlock(tuple<_Lock&...>& __locks)
- {
- std::get<_Idx>(__locks).unlock();
- __unlock_impl<_Idx - 1>::__do_unlock(__locks);
- }
- };
-
- template<>
- struct __unlock_impl<-1>
- {
- template<typename... _Lock>
- static void
- __do_unlock(tuple<_Lock&...>&)
- { }
- };
-
template<typename _Lock>
- unique_lock<_Lock>
+ inline unique_lock<_Lock>
__try_to_lock(_Lock& __l)
- { return unique_lock<_Lock>(__l, try_to_lock); }
+ { return unique_lock<_Lock>{__l, try_to_lock}; }
template<int _Idx, bool _Continue = true>
struct __try_lock_impl
@@ -603,11 +585,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
{
__idx = _Idx;
- auto __lock = __try_to_lock(std::get<_Idx>(__locks));
+ auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
if (__lock.owns_lock())
{
- __try_lock_impl<_Idx + 1, _Idx + 2 < sizeof...(_Lock)>::
- __do_try_lock(__locks, __idx);
+ constexpr bool __cont = _Idx + 2 < sizeof...(_Lock);
+ using __try_locker = __try_lock_impl<_Idx + 1, __cont>;
+ __try_locker::__do_try_lock(__locks, __idx);
if (__idx == -1)
__lock.release();
}
@@ -622,7 +605,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
{
__idx = _Idx;
- auto __lock = __try_to_lock(std::get<_Idx>(__locks));
+ auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
if (__lock.owns_lock())
{
__idx = -1;
@@ -649,6 +632,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
auto __locks = std::tie(__l1, __l2, __l3...);
__try
{ __try_lock_impl<0>::__do_try_lock(__locks, __idx); }
+ __catch(const __cxxabiv1::__forced_unwind&)
+ { __throw_exception_again; }
__catch(...)
{ }
return __idx;
@@ -665,16 +650,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* and unlock(). If the call exits via an exception any locks that were
* obtained will be released.
*/
- template<typename _L1, typename _L2, typename ..._L3>
+ template<typename _L1, typename _L2, typename... _L3>
void
lock(_L1& __l1, _L2& __l2, _L3&... __l3)
{
while (true)
{
+ using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>;
unique_lock<_L1> __first(__l1);
int __idx;
auto __locks = std::tie(__l2, __l3...);
- __try_lock_impl<0, sizeof...(_L3)>::__do_try_lock(__locks, __idx);
+ __try_locker::__do_try_lock(__locks, __idx);
if (__idx == -1)
{
__first.release();
@@ -735,7 +721,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef _GLIBCXX_HAVE_TLS
auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f),
std::forward<_Args>(__args)...);
- __once_callable = &__bound_functor;
+ __once_callable = std::__addressof(__bound_functor);
__once_call = &__once_call_impl<decltype(__bound_functor)>;
#else
unique_lock<mutex> __functor_lock(__get_once_mutex());
diff --git a/libstdc++-v3/include/std/streambuf b/libstdc++-v3/include/std/streambuf
index 865f26b933d..0cb609d8b44 100644
--- a/libstdc++-v3/include/std/streambuf
+++ b/libstdc++-v3/include/std/streambuf
@@ -117,7 +117,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* from the sequence).
*/
template<typename _CharT, typename _Traits>
- class basic_streambuf
+ class basic_streambuf
{
public:
//@{
@@ -137,7 +137,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// This is a non-standard type.
typedef basic_streambuf<char_type, traits_type> __streambuf_type;
//@}
-
+
friend class basic_ios<char_type, traits_type>;
friend class basic_istream<char_type, traits_type>;
friend class basic_ostream<char_type, traits_type>;
@@ -148,7 +148,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__copy_streambufs_eof<>(basic_streambuf*, basic_streambuf*, bool&);
template<bool _IsMove, typename _CharT2>
- friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
+ friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
_CharT2*>::__type
__copy_move_a2(istreambuf_iterator<_CharT2>,
istreambuf_iterator<_CharT2>, _CharT2*);
@@ -189,12 +189,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
char_type* _M_out_end; ///< End of put area.
/// Current locale setting.
- locale _M_buf_locale;
+ locale _M_buf_locale;
public:
/// Destructor deallocates no buffer space.
- virtual
- ~basic_streambuf()
+ virtual
+ ~basic_streambuf()
{ }
// [27.5.2.2.1] locales
@@ -205,7 +205,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* Calls the derived imbue(__loc).
*/
- locale
+ locale
pubimbue(const locale& __loc)
{
locale __tmp(this->getloc());
@@ -222,9 +222,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* is returned. Otherwise the global locale in effect at the time
* of construction is returned.
*/
- locale
+ locale
getloc() const
- { return _M_buf_locale; }
+ { return _M_buf_locale; }
// [27.5.2.2.2] buffer management and positioning
//@{
@@ -236,7 +236,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* and returning the result unchanged.
*/
basic_streambuf*
- pubsetbuf(char_type* __s, streamsize __n)
+ pubsetbuf(char_type* __s, streamsize __n)
{ return this->setbuf(__s, __n); }
/**
@@ -247,8 +247,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* Calls virtual seekoff function.
*/
- pos_type
- pubseekoff(off_type __off, ios_base::seekdir __way,
+ pos_type
+ pubseekoff(off_type __off, ios_base::seekdir __way,
ios_base::openmode __mode = ios_base::in | ios_base::out)
{ return this->seekoff(__off, __way, __mode); }
@@ -259,7 +259,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* Calls virtual seekpos function.
*/
- pos_type
+ pos_type
pubseekpos(pos_type __sp,
ios_base::openmode __mode = ios_base::in | ios_base::out)
{ return this->seekpos(__sp, __mode); }
@@ -267,7 +267,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/**
* @brief Calls virtual sync function.
*/
- int
+ int
pubsync() { return this->sync(); }
//@}
@@ -280,9 +280,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* available for reading before the buffer must be refilled.
* Otherwise returns the derived @c showmanyc().
*/
- streamsize
- in_avail()
- {
+ streamsize
+ in_avail()
+ {
const streamsize __ret = this->egptr() - this->gptr();
return __ret ? __ret : this->showmanyc();
}
@@ -294,11 +294,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* Calls @c sbumpc(), and if that function returns
* @c traits::eof(), so does this function. Otherwise, @c sgetc().
*/
- int_type
+ int_type
snextc()
{
int_type __ret = traits_type::eof();
- if (__builtin_expect(!traits_type::eq_int_type(this->sbumpc(),
+ if (__builtin_expect(!traits_type::eq_int_type(this->sbumpc(),
__ret), true))
__ret = this->sgetc();
return __ret;
@@ -312,7 +312,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* and increments the read pointer, otherwise calls and returns
* @c uflow().
*/
- int_type
+ int_type
sbumpc()
{
int_type __ret;
@@ -321,7 +321,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__ret = traits_type::to_int_type(*this->gptr());
this->gbump(1);
}
- else
+ else
__ret = this->uflow();
return __ret;
}
@@ -331,16 +331,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @return The next character, or eof.
*
* If the input read position is available, returns that character,
- * otherwise calls and returns @c underflow(). Does not move the
+ * otherwise calls and returns @c underflow(). Does not move the
* read position after fetching the character.
*/
- int_type
+ int_type
sgetc()
{
int_type __ret;
if (__builtin_expect(this->gptr() < this->egptr(), true))
__ret = traits_type::to_int_type(*this->gptr());
- else
+ else
__ret = this->underflow();
return __ret;
}
@@ -353,7 +353,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* Returns xsgetn(__s,__n). The effect is to fill @a __s[0] through
* @a __s[__n-1] with characters from the input sequence, if possible.
*/
- streamsize
+ streamsize
sgetn(char_type* __s, streamsize __n)
{ return this->xsgetn(__s, __n); }
@@ -368,15 +368,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* the next character fetched from the input stream will be @a
* __c.
*/
- int_type
+ int_type
sputbackc(char_type __c)
{
int_type __ret;
const bool __testpos = this->eback() < this->gptr();
- if (__builtin_expect(!__testpos ||
+ if (__builtin_expect(!__testpos ||
!traits_type::eq(__c, this->gptr()[-1]), false))
__ret = this->pbackfail(traits_type::to_int_type(__c));
- else
+ else
{
this->gbump(-1);
__ret = traits_type::to_int_type(*this->gptr());
@@ -393,7 +393,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* calls and returns pbackfail(). The effect is to @a unget
* the last character @a gotten.
*/
- int_type
+ int_type
sungetc()
{
int_type __ret;
@@ -402,7 +402,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
this->gbump(-1);
__ret = traits_type::to_int_type(*this->gptr());
}
- else
+ else
__ret = this->pbackfail();
return __ret;
}
@@ -420,7 +420,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* the position, and returns @c traits::to_int_type(__c). If a write
* position is not available, returns @c overflow(__c).
*/
- int_type
+ int_type
sputc(char_type __c)
{
int_type __ret;
@@ -446,7 +446,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* Returns xsputn(__s,__n). The effect is to write @a __s[0] through
* @a __s[__n-1] to the output sequence, if possible.
*/
- streamsize
+ streamsize
sputn(const char_type* __s, streamsize __n)
{ return this->xsputn(__s, __n); }
@@ -461,9 +461,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* - this is not an error
*/
basic_streambuf()
- : _M_in_beg(0), _M_in_cur(0), _M_in_end(0),
+ : _M_in_beg(0), _M_in_cur(0), _M_in_end(0),
_M_out_beg(0), _M_out_cur(0), _M_out_end(0),
- _M_buf_locale(locale())
+ _M_buf_locale(locale())
{ }
// [27.5.2.3.1] get area access
@@ -478,13 +478,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* - gptr() returns the next pointer for the input sequence
* - egptr() returns the end pointer for the input sequence
*/
- char_type*
+ char_type*
eback() const { return _M_in_beg; }
- char_type*
+ char_type*
gptr() const { return _M_in_cur; }
- char_type*
+ char_type*
egptr() const { return _M_in_end; }
//@}
@@ -494,7 +494,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* This just advances the read position without returning any data.
*/
- void
+ void
gbump(int __n) { _M_in_cur += __n; }
/**
@@ -505,7 +505,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @post @a __gbeg == @c eback(), @a __gnext == @c gptr(), and
* @a __gend == @c egptr()
*/
- void
+ void
setg(char_type* __gbeg, char_type* __gnext, char_type* __gend)
{
_M_in_beg = __gbeg;
@@ -525,13 +525,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* - pptr() returns the next pointer for the output sequence
* - epptr() returns the end pointer for the output sequence
*/
- char_type*
+ char_type*
pbase() const { return _M_out_beg; }
- char_type*
+ char_type*
pptr() const { return _M_out_cur; }
- char_type*
+ char_type*
epptr() const { return _M_out_end; }
//@}
@@ -541,7 +541,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* This just advances the write position without returning any data.
*/
- void
+ void
pbump(int __n) { _M_out_cur += __n; }
/**
@@ -551,10 +551,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @post @a __pbeg == @c pbase(), @a __pbeg == @c pptr(), and
* @a __pend == @c epptr()
*/
- void
+ void
setp(char_type* __pbeg, char_type* __pend)
- {
- _M_out_beg = _M_out_cur = __pbeg;
+ {
+ _M_out_beg = _M_out_cur = __pbeg;
_M_out_end = __pend;
}
@@ -572,8 +572,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* @note Base class version does nothing.
*/
- virtual void
- imbue(const locale& __loc)
+ virtual void
+ imbue(const locale& __loc)
{ }
// [27.5.2.4.2] buffer management and positioning
@@ -581,16 +581,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @brief Manipulates the buffer.
*
* Each derived class provides its own appropriate behavior. See
- * the next-to-last paragraph of
+ * the next-to-last paragraph of
* http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt11ch25s02.html
* for more on this function.
*
* @note Base class version does nothing, returns @c this.
*/
- virtual basic_streambuf<char_type,_Traits>*
+ virtual basic_streambuf<char_type,_Traits>*
setbuf(char_type*, streamsize)
{ return this; }
-
+
/**
* @brief Alters the stream positions.
*
@@ -598,10 +598,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @note Base class version does nothing, returns a @c pos_type
* that represents an invalid stream position.
*/
- virtual pos_type
+ virtual pos_type
seekoff(off_type, ios_base::seekdir,
ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
- { return pos_type(off_type(-1)); }
+ { return pos_type(off_type(-1)); }
/**
* @brief Alters the stream positions.
@@ -610,10 +610,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @note Base class version does nothing, returns a @c pos_type
* that represents an invalid stream position.
*/
- virtual pos_type
- seekpos(pos_type,
+ virtual pos_type
+ seekpos(pos_type,
ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
- { return pos_type(off_type(-1)); }
+ { return pos_type(off_type(-1)); }
/**
* @brief Synchronizes the buffer arrays with the controlled sequences.
@@ -623,7 +623,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* including the definition of @a failure.
* @note Base class version does nothing, returns zero.
*/
- virtual int
+ virtual int
sync() { return 0; }
// [27.5.2.4.3] get area
@@ -645,7 +645,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @note The standard adds that <em>the morphemes of @c showmanyc are
* @b es-how-many-see, not @b show-manic.</em>
*/
- virtual streamsize
+ virtual streamsize
showmanyc() { return 0; }
/**
@@ -661,7 +661,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* It is expected that derived classes provide a more efficient
* implementation by overriding this definition.
*/
- virtual streamsize
+ virtual streamsize
xsgetn(char_type* __s, streamsize __n);
/**
@@ -683,7 +683,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* @note Base class version does nothing, returns eof().
*/
- virtual int_type
+ virtual int_type
underflow()
{ return traits_type::eof(); }
@@ -696,18 +696,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* the new character, like @c underflow() does. However, this
* function also moves the read position forward by one.
*/
- virtual int_type
- uflow()
+ virtual int_type
+ uflow()
{
int_type __ret = traits_type::eof();
- const bool __testeof = traits_type::eq_int_type(this->underflow(),
+ const bool __testeof = traits_type::eq_int_type(this->underflow(),
__ret);
if (!__testeof)
{
__ret = traits_type::to_int_type(*this->gptr());
this->gbump(1);
}
- return __ret;
+ return __ret;
}
// [27.5.2.4.4] putback
@@ -720,7 +720,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* @note Base class version does nothing, returns eof().
*/
- virtual int_type
+ virtual int_type
pbackfail(int_type __c = traits_type::eof())
{ return traits_type::eof(); }
@@ -738,7 +738,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* It is expected that derived classes provide a more efficient
* implementation by overriding this definition.
*/
- virtual streamsize
+ virtual streamsize
xsputn(const char_type* __s, streamsize __n);
/**
@@ -764,7 +764,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* @note Base class version does nothing, returns eof().
*/
- virtual int_type
+ virtual int_type
overflow(int_type __c = traits_type::eof())
{ return traits_type::eof(); }
@@ -779,35 +779,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* See http://gcc.gnu.org/ml/libstdc++/2002-05/msg00168.html
*/
- void
- stossc()
+ void
+ stossc()
{
- if (this->gptr() < this->egptr())
+ if (this->gptr() < this->egptr())
this->gbump(1);
- else
+ else
this->uflow();
}
#endif
// Also used by specializations for char and wchar_t in src.
- void
+ void
__safe_gbump(streamsize __n) { _M_in_cur += __n; }
void
__safe_pbump(streamsize __n) { _M_out_cur += __n; }
+#if __cplusplus < 201103L
private:
// _GLIBCXX_RESOLVE_LIB_DEFECTS
- // Side effect of DR 50.
+ // Side effect of DR 50.
basic_streambuf(const basic_streambuf& __sb)
- : _M_in_beg(__sb._M_in_beg), _M_in_cur(__sb._M_in_cur),
- _M_in_end(__sb._M_in_end), _M_out_beg(__sb._M_out_beg),
- _M_out_cur(__sb._M_out_cur), _M_out_end(__sb._M_out_cur),
- _M_buf_locale(__sb._M_buf_locale)
+ : _M_in_beg(__sb._M_in_beg), _M_in_cur(__sb._M_in_cur),
+ _M_in_end(__sb._M_in_end), _M_out_beg(__sb._M_out_beg),
+ _M_out_cur(__sb._M_out_cur), _M_out_end(__sb._M_out_end),
+ _M_buf_locale(__sb._M_buf_locale)
{ }
basic_streambuf&
- operator=(const basic_streambuf&) { return *this; };
+ operator=(const basic_streambuf&) { return *this; }
+#else
+ protected:
+ basic_streambuf(const basic_streambuf&) = default;
+
+ basic_streambuf&
+ operator=(const basic_streambuf&) = default;
+
+ void
+ swap(basic_streambuf& __sb)
+ {
+ std::swap(_M_in_beg, __sb._M_in_beg);
+ std::swap(_M_in_cur, __sb._M_in_cur);
+ std::swap(_M_in_end, __sb._M_in_end);
+ std::swap(_M_out_beg, __sb._M_out_beg);
+ std::swap(_M_out_cur, __sb._M_out_cur);
+ std::swap(_M_out_end, __sb._M_out_end);
+ std::swap(_M_buf_locale, __sb._M_buf_locale);
+ }
+#endif
};
// Explicit specialization declarations, defined in src/streambuf.cc.
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 03d87d77aa0..ef8aa5ab6f4 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -48,33 +48,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @{
*/
- // Adds a const reference to a non-reference type.
- template<typename _Tp>
- struct __add_c_ref
- { typedef const _Tp& type; };
-
- template<typename _Tp>
- struct __add_c_ref<_Tp&>
- { typedef _Tp& type; };
-
- // Adds a reference to a non-reference type.
- template<typename _Tp>
- struct __add_ref
- { typedef _Tp& type; };
-
- template<typename _Tp>
- struct __add_ref<_Tp&>
- { typedef _Tp& type; };
-
- // Adds an rvalue reference to a non-reference type.
- template<typename _Tp>
- struct __add_r_ref
- { typedef _Tp&& type; };
-
- template<typename _Tp>
- struct __add_r_ref<_Tp&>
- { typedef _Tp& type; };
-
template<std::size_t _Idx, typename _Head, bool _IsEmptyNotFinal>
struct _Head_base;
@@ -689,25 +662,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef _Head type;
};
+ // Duplicate of C++14's tuple_element_t for internal use in C++11 mode
+ template<std::size_t __i, typename _Tp>
+ using __tuple_element_t = typename tuple_element<__i, _Tp>::type;
+
template<std::size_t __i, typename _Tp>
struct tuple_element<__i, const _Tp>
{
- typedef typename
- add_const<typename tuple_element<__i, _Tp>::type>::type type;
+ typedef typename add_const<__tuple_element_t<__i, _Tp>>::type type;
};
template<std::size_t __i, typename _Tp>
struct tuple_element<__i, volatile _Tp>
{
- typedef typename
- add_volatile<typename tuple_element<__i, _Tp>::type>::type type;
+ typedef typename add_volatile<__tuple_element_t<__i, _Tp>>::type type;
};
template<std::size_t __i, typename _Tp>
struct tuple_element<__i, const volatile _Tp>
{
- typedef typename
- add_cv<typename tuple_element<__i, _Tp>::type>::type type;
+ typedef typename add_cv<__tuple_element_t<__i, _Tp>>::type type;
};
#if __cplusplus > 201103L
@@ -719,23 +693,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
struct tuple_size;
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2313. tuple_size should always derive from integral_constant<size_t, N>
template<typename _Tp>
struct tuple_size<const _Tp>
- : public integral_constant<
- typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
- tuple_size<_Tp>::value> { };
+ : integral_constant<size_t, tuple_size<_Tp>::value> { };
template<typename _Tp>
struct tuple_size<volatile _Tp>
- : public integral_constant<
- typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
- tuple_size<_Tp>::value> { };
+ : integral_constant<size_t, tuple_size<_Tp>::value> { };
template<typename _Tp>
struct tuple_size<const volatile _Tp>
- : public integral_constant<
- typename remove_cv<decltype(tuple_size<_Tp>::value)>::type,
- tuple_size<_Tp>::value> { };
+ : integral_constant<size_t, tuple_size<_Tp>::value> { };
/// class tuple_size
template<typename... _Elements>
@@ -743,98 +713,93 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public integral_constant<std::size_t, sizeof...(_Elements)> { };
template<std::size_t __i, typename _Head, typename... _Tail>
- constexpr typename __add_ref<_Head>::type
+ constexpr _Head&
__get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
{ return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
template<std::size_t __i, typename _Head, typename... _Tail>
- constexpr typename __add_c_ref<_Head>::type
+ constexpr const _Head&
__get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
{ return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
- // Return a reference (const reference, rvalue reference) to the ith element
- // of a tuple. Any const or non-const ref elements are returned with their
- // original type.
+ /// Return a reference to the ith element of a tuple.
template<std::size_t __i, typename... _Elements>
- constexpr typename __add_ref<
- typename tuple_element<__i, tuple<_Elements...>>::type
- >::type
+ constexpr __tuple_element_t<__i, tuple<_Elements...>>&
get(tuple<_Elements...>& __t) noexcept
{ return std::__get_helper<__i>(__t); }
+ /// Return a const reference to the ith element of a const tuple.
template<std::size_t __i, typename... _Elements>
- constexpr typename __add_c_ref<
- typename tuple_element<__i, tuple<_Elements...>>::type
- >::type
+ constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
get(const tuple<_Elements...>& __t) noexcept
{ return std::__get_helper<__i>(__t); }
+ /// Return an rvalue reference to the ith element of a tuple rvalue.
template<std::size_t __i, typename... _Elements>
- constexpr typename __add_r_ref<
- typename tuple_element<__i, tuple<_Elements...>>::type
- >::type
+ constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
get(tuple<_Elements...>&& __t) noexcept
- { return std::forward<typename tuple_element<__i,
- tuple<_Elements...>>::type&&>(get<__i>(__t)); }
+ {
+ typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
+ return std::forward<__element_type&&>(std::get<__i>(__t));
+ }
#if __cplusplus > 201103L
template<typename _Head, size_t __i, typename... _Tail>
- constexpr typename __add_ref<_Head>::type
+ constexpr _Head&
__get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
{ return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
template<typename _Head, size_t __i, typename... _Tail>
- constexpr typename __add_c_ref<_Head>::type
+ constexpr const _Head&
__get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
{ return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
+ /// Return a reference to the unique element of type _Tp of a tuple.
template <typename _Tp, typename... _Types>
constexpr _Tp&
get(tuple<_Types...>& __t) noexcept
{ return std::__get_helper2<_Tp>(__t); }
+ /// Return a reference to the unique element of type _Tp of a tuple rvalue.
template <typename _Tp, typename... _Types>
constexpr _Tp&&
get(tuple<_Types...>&& __t) noexcept
- { return std::move(std::__get_helper2<_Tp>(__t)); }
+ { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); }
+ /// Return a const reference to the unique element of type _Tp of a tuple.
template <typename _Tp, typename... _Types>
constexpr const _Tp&
get(const tuple<_Types...>& __t) noexcept
{ return std::__get_helper2<_Tp>(__t); }
#endif
- // This class helps construct the various comparison operations on tuples
- template<std::size_t __check_equal_size, std::size_t __i, std::size_t __j,
- typename _Tp, typename _Up>
- struct __tuple_compare;
-
- template<std::size_t __i, std::size_t __j, typename _Tp, typename _Up>
- struct __tuple_compare<0, __i, __j, _Tp, _Up>
+ // This class performs the comparison operations on tuples
+ template<typename _Tp, typename _Up, size_t __i, size_t __size>
+ struct __tuple_compare
{
- static constexpr bool
+ static constexpr bool
__eq(const _Tp& __t, const _Up& __u)
{
- return (get<__i>(__t) == get<__i>(__u) &&
- __tuple_compare<0, __i + 1, __j, _Tp, _Up>::__eq(__t, __u));
+ return bool(std::get<__i>(__t) == std::get<__i>(__u))
+ && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
}
-
- static constexpr bool
+
+ static constexpr bool
__less(const _Tp& __t, const _Up& __u)
{
- return ((get<__i>(__t) < get<__i>(__u))
- || !(get<__i>(__u) < get<__i>(__t)) &&
- __tuple_compare<0, __i + 1, __j, _Tp, _Up>::__less(__t, __u));
+ return bool(std::get<__i>(__t) < std::get<__i>(__u))
+ || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
+ && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
}
};
- template<std::size_t __i, typename _Tp, typename _Up>
- struct __tuple_compare<0, __i, __i, _Tp, _Up>
+ template<typename _Tp, typename _Up, size_t __size>
+ struct __tuple_compare<_Tp, _Up, __size, __size>
{
- static constexpr bool
+ static constexpr bool
__eq(const _Tp&, const _Up&) { return true; }
-
- static constexpr bool
+
+ static constexpr bool
__less(const _Tp&, const _Up&) { return false; }
};
@@ -843,10 +808,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator==(const tuple<_TElements...>& __t,
const tuple<_UElements...>& __u)
{
- typedef tuple<_TElements...> _Tp;
- typedef tuple<_UElements...> _Up;
- return bool(__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Up>::value,
- 0, tuple_size<_Tp>::value, _Tp, _Up>::__eq(__t, __u));
+ static_assert(sizeof...(_TElements) == sizeof...(_UElements),
+ "tuple objects can only be compared if they have equal sizes.");
+ using __compare = __tuple_compare<tuple<_TElements...>,
+ tuple<_UElements...>,
+ 0, sizeof...(_TElements)>;
+ return __compare::__eq(__t, __u);
}
template<typename... _TElements, typename... _UElements>
@@ -854,10 +821,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator<(const tuple<_TElements...>& __t,
const tuple<_UElements...>& __u)
{
- typedef tuple<_TElements...> _Tp;
- typedef tuple<_UElements...> _Up;
- return bool(__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Up>::value,
- 0, tuple_size<_Tp>::value, _Tp, _Up>::__less(__t, __u));
+ static_assert(sizeof...(_TElements) == sizeof...(_UElements),
+ "tuple objects can only be compared if they have equal sizes.");
+ using __compare = __tuple_compare<tuple<_TElements...>,
+ tuple<_UElements...>,
+ 0, sizeof...(_TElements)>;
+ return __compare::__less(__t, __u);
}
template<typename... _TElements, typename... _UElements>
@@ -922,17 +891,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
<typename std::remove_reference<_Tp>::type>::type>::type
{ };
- template<std::size_t, typename, typename, std::size_t>
+ template<size_t, typename, typename, size_t>
struct __make_tuple_impl;
- template<std::size_t _Idx, typename _Tuple, typename... _Tp,
- std::size_t _Nm>
+ template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
- {
- typedef typename __make_tuple_impl<_Idx + 1, tuple<_Tp...,
- typename std::tuple_element<_Idx, _Tuple>::type>, _Tuple, _Nm>::__type
- __type;
- };
+ : __make_tuple_impl<_Idx + 1,
+ tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
+ _Tuple, _Nm>
+ { };
template<std::size_t _Nm, typename _Tuple, typename... _Tp>
struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
@@ -942,8 +909,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tuple>
struct __do_make_tuple
- : public __make_tuple_impl<0, tuple<>, _Tuple,
- std::tuple_size<_Tuple>::value>
+ : __make_tuple_impl<0, tuple<>, _Tuple, std::tuple_size<_Tuple>::value>
{ };
// Returns the std::tuple equivalent of a tuple-like type.
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 4b434a6025b..da8a95f034e 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -37,6 +37,18 @@
#include <bits/c++config.h>
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+# if defined (__UINT_LEAST16_TYPE__) && defined(__UINT_LEAST32_TYPE__)
+namespace std
+{
+ typedef __UINT_LEAST16_TYPE__ uint_least16_t;
+ typedef __UINT_LEAST32_TYPE__ uint_least32_t;
+}
+# else
+# include <cstdint>
+# endif
+#endif
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -1583,6 +1595,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __make_unsigned<long long>
{ typedef unsigned long long __type; };
+#if defined(_GLIBCXX_USE_WCHAR_T) && !defined(__WCHAR_UNSIGNED__)
+ template<>
+ struct __make_unsigned<wchar_t> : __make_unsigned<__WCHAR_TYPE__>
+ { };
+#endif
+
#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
template<>
struct __make_unsigned<__int128>
@@ -1665,6 +1683,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __make_signed<unsigned long long>
{ typedef signed long long __type; };
+#if defined(_GLIBCXX_USE_WCHAR_T) && defined(__WCHAR_UNSIGNED__)
+ template<>
+ struct __make_signed<wchar_t> : __make_signed<__WCHAR_TYPE__>
+ { };
+#endif
+
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+ template<>
+ struct __make_signed<char16_t> : __make_signed<uint_least16_t>
+ { };
+ template<>
+ struct __make_signed<char32_t> : __make_signed<uint_least32_t>
+ { };
+#endif
+
#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)
template<>
struct __make_signed<unsigned __int128>
@@ -1837,6 +1870,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
};
+ template <typename... _Types>
+ struct __strictest_alignment
+ {
+ static const size_t _S_alignment = 0;
+ static const size_t _S_size = 0;
+ };
+
+ template <typename _Tp, typename... _Types>
+ struct __strictest_alignment<_Tp, _Types...>
+ {
+ static const size_t _S_alignment =
+ alignof(_Tp) > __strictest_alignment<_Types...>::_S_alignment
+ ? alignof(_Tp) : __strictest_alignment<_Types...>::_S_alignment;
+ static const size_t _S_size =
+ sizeof(_Tp) > __strictest_alignment<_Types...>::_S_size
+ ? sizeof(_Tp) : __strictest_alignment<_Types...>::_S_size;
+ };
+
+ /**
+ * @brief Provide aligned storage for types.
+ *
+ * [meta.trans.other]
+ *
+ * Provides aligned storage for any of the provided types of at
+ * least size _Len.
+ *
+ * @see aligned_storage
+ */
+ template <size_t _Len, typename... _Types>
+ struct aligned_union
+ {
+ private:
+ static_assert(sizeof...(_Types) != 0, "At least one type is required");
+
+ using __strictest = __strictest_alignment<_Types...>;
+ static const size_t _S_len = _Len > __strictest::_S_size
+ ? _Len : __strictest::_S_size;
+ public:
+ /// The value of the strictest alignment of _Types.
+ static const size_t alignment_value = __strictest::_S_alignment;
+ /// The storage.
+ typedef typename aligned_storage<_S_len, alignment_value>::type type;
+ };
+
+ template <size_t _Len, typename... _Types>
+ const size_t aligned_union<_Len, _Types...>::alignment_value;
// Decay trait for arrays and functions, used for perfect forwarding
// in make_pair, make_tuple, etc.
@@ -2173,6 +2252,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__alignof__(typename __aligned_storage_msa<_Len>::__type)>
using aligned_storage_t = typename aligned_storage<_Len, _Align>::type;
+ template <size_t _Len, typename... _Types>
+ using aligned_union_t = typename aligned_union<_Len, _Types...>::type;
+
/// Alias template for decay
template<typename _Tp>
using decay_t = typename decay<_Tp>::type;
diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
index 4da92095f11..6d12839e509 100644
--- a/libstdc++-v3/include/std/utility
+++ b/libstdc++-v3/include/std/utility
@@ -84,14 +84,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class tuple_element;
// Various functions which give std::pair a tuple-like interface.
+
+ /// Partial specialization for std::pair
template<class _Tp1, class _Tp2>
struct tuple_size<std::pair<_Tp1, _Tp2>>
: public integral_constant<std::size_t, 2> { };
+ /// Partial specialization for std::pair
template<class _Tp1, class _Tp2>
struct tuple_element<0, std::pair<_Tp1, _Tp2>>
{ typedef _Tp1 type; };
+ /// Partial specialization for std::pair
template<class _Tp1, class _Tp2>
struct tuple_element<1, std::pair<_Tp1, _Tp2>>
{ typedef _Tp2 type; };
diff --git a/libstdc++-v3/include/tr2/bool_set b/libstdc++-v3/include/tr2/bool_set
index d97714c1107..34e58f4a97a 100644
--- a/libstdc++-v3/include/tr2/bool_set
+++ b/libstdc++-v3/include/tr2/bool_set
@@ -44,7 +44,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* bool_set
*
* See N2136, Bool_set: multi-valued logic
- * by Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion.
+ * by Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion.
*
* The implicit conversion to bool is slippery! I may use the new
* explicit conversion. This has been specialized in the language
diff --git a/libstdc++-v3/libsupc++/new_op.cc b/libstdc++-v3/libsupc++/new_op.cc
index 4a3e85848ce..fb54488e608 100644
--- a/libstdc++-v3/libsupc++/new_op.cc
+++ b/libstdc++-v3/libsupc++/new_op.cc
@@ -46,14 +46,13 @@ operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
/* malloc (0) is unpredictable; avoid it. */
if (sz == 0)
sz = 1;
- p = (void *) malloc (sz);
- while (p == 0)
+
+ while (__builtin_expect ((p = malloc (sz)) == 0, false))
{
new_handler handler = std::get_new_handler ();
if (! handler)
_GLIBCXX_THROW_OR_ABORT(bad_alloc());
handler ();
- p = (void *) malloc (sz);
}
return p;
diff --git a/libstdc++-v3/libsupc++/new_opnt.cc b/libstdc++-v3/libsupc++/new_opnt.cc
index b83da60b542..968082f4096 100644
--- a/libstdc++-v3/libsupc++/new_opnt.cc
+++ b/libstdc++-v3/libsupc++/new_opnt.cc
@@ -39,8 +39,8 @@ operator new (std::size_t sz, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
/* malloc (0) is unpredictable; avoid it. */
if (sz == 0)
sz = 1;
- p = (void *) malloc (sz);
- while (p == 0)
+
+ while (__builtin_expect ((p = malloc (sz)) == 0, false))
{
new_handler handler = std::get_new_handler ();
if (! handler)
@@ -53,8 +53,6 @@ operator new (std::size_t sz, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
{
return 0;
}
-
- p = (void *) malloc (sz);
}
return p;
diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 1f1f860a5b0..623a815cb89 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -51,7 +51,7 @@ def find_type(orig, name):
# anything fancier here.
field = typ.fields()[0]
if not field.is_base_class:
- raise ValueError, "Cannot find type %s::%s" % (str(orig), name)
+ raise ValueError("Cannot find type %s::%s" % (str(orig), name))
typ = field.type
class SharedPointerPrinter:
@@ -276,7 +276,7 @@ class StdTuplePrinter:
# Set the actual head to the first pair.
self.head = self.head.cast (nodes[0].type)
elif len (nodes) != 0:
- raise ValueError, "Top of tuple tree does not consist of a single node."
+ raise ValueError("Top of tuple tree does not consist of a single node.")
self.count = 0
def __iter__ (self):
@@ -289,7 +289,7 @@ class StdTuplePrinter:
raise StopIteration
# Check that this iteration has an expected structure.
if len (nodes) != 2:
- raise ValueError, "Cannot parse more than 2 nodes in a tuple tree."
+ raise ValueError("Cannot parse more than 2 nodes in a tuple tree.")
# - Left node is the next recursion parent.
# - Right node is the actual class contained in the tuple.
@@ -389,7 +389,7 @@ def get_value_from_Rb_tree_node(node):
return p.dereference()
except:
pass
- raise ValueError, "Unsupported implementation for %s" % str(node.type)
+ raise ValueError("Unsupported implementation for %s" % str(node.type))
# This is a pretty printer for std::_Rb_tree_iterator (which is
# std::map::iterator), and has nothing to do with the RbtreeIterator
@@ -827,7 +827,7 @@ class Printer(object):
# A small sanity check.
# FIXME
if not self.compiled_rx.match(name + '<>'):
- raise ValueError, 'libstdc++ programming error: "%s" does not match' % name
+ raise ValueError('libstdc++ programming error: "%s" does not match' % name)
printer = RxPrinter(name, function)
self.subprinters.append(printer)
self.lookup[name] = printer
diff --git a/libstdc++-v3/scripts/run_doxygen b/libstdc++-v3/scripts/run_doxygen
index c81bc182485..8f5993698b6 100644
--- a/libstdc++-v3/scripts/run_doxygen
+++ b/libstdc++-v3/scripts/run_doxygen
@@ -193,8 +193,15 @@ fi
if $do_latex; then
cd ${outdir}/${mode}
- # Also drop in the header file and style sheet
- doxygen -w latex header.tex doxygen.sty
+ # Grrr, Doxygen 1.8.x changed the -w latex options.
+ need_footer=`doxygen -h | sed -n -e '/-w latex/s=.*footer.*=true=p'`
+
+ # Also drop in the header file (maybe footer file) and style sheet
+ if $need_footer; then
+ doxygen -w latex header.tex footer.tex doxygen.sty
+ else
+ doxygen -w latex header.tex doxygen.sty
+ fi
echo ::
echo :: LaTeX pages begin with
diff --git a/libstdc++-v3/scripts/testsuite_flags.in b/libstdc++-v3/scripts/testsuite_flags.in
index cf692f8f059..5e7ad328090 100755
--- a/libstdc++-v3/scripts/testsuite_flags.in
+++ b/libstdc++-v3/scripts/testsuite_flags.in
@@ -57,7 +57,7 @@ case ${query} in
;;
--cxxflags)
CXXFLAGS_default="-D_GLIBCXX_ASSERT -fmessage-length=0"
- CXXFLAGS_config="@SECTION_FLAGS@ @CXXFLAGS@ @EXTRA_CXX_FLAGS@"
+ CXXFLAGS_config="@SECTION_FLAGS@ @EXTRA_CXX_FLAGS@"
echo ${CXXFLAGS_default} ${CXXFLAGS_config}
;;
--cxxvtvflags)
diff --git a/libstdc++-v3/src/c++98/ios_init.cc b/libstdc++-v3/src/c++98/ios_init.cc
index d8d2a0d256a..b5c14f29b2a 100644
--- a/libstdc++-v3/src/c++98/ios_init.cc
+++ b/libstdc++-v3/src/c++98/ios_init.cc
@@ -37,7 +37,7 @@ namespace __gnu_internal _GLIBCXX_VISIBILITY(hidden)
{
using namespace __gnu_cxx;
- // Extern declarations for global objects in src/globals.cc.
+ // Extern declarations for global objects in src/c++98/globals.cc.
extern stdio_sync_filebuf<char> buf_cout_sync;
extern stdio_sync_filebuf<char> buf_cin_sync;
extern stdio_sync_filebuf<char> buf_cerr_sync;
diff --git a/libstdc++-v3/testsuite/17_intro/headers/c++1998/stdc++.cc b/libstdc++-v3/testsuite/17_intro/headers/c++1998/stdc++.cc
index d20c8e6f114..38d28a3d609 100644
--- a/libstdc++-v3/testsuite/17_intro/headers/c++1998/stdc++.cc
+++ b/libstdc++-v3/testsuite/17_intro/headers/c++1998/stdc++.cc
@@ -1,5 +1,5 @@
// FreeBSD wants warning clean system headers:
-// { dg-options "-Wall -Wsystem-headers" { target *-*-freebsd* } }
+// { dg-options "-Wall -Wsystem-headers" { target *-*-freebsd* *-*-dragonfly* } }
// { dg-do compile }
// 1999-05-12 bkoz
diff --git a/libstdc++-v3/testsuite/17_intro/headers/c++1998/stdc++_multiple_inclusion.cc b/libstdc++-v3/testsuite/17_intro/headers/c++1998/stdc++_multiple_inclusion.cc
index e1f326ceb96..724a6692b06 100644
--- a/libstdc++-v3/testsuite/17_intro/headers/c++1998/stdc++_multiple_inclusion.cc
+++ b/libstdc++-v3/testsuite/17_intro/headers/c++1998/stdc++_multiple_inclusion.cc
@@ -1,5 +1,5 @@
// FreeBSD wants warning clean system headers:
-// { dg-options "-Wall -Wsystem-headers" { target *-*-freebsd* } }
+// { dg-options "-Wall -Wsystem-headers" { target *-*-freebsd* *-*-dragonfly* } }
// { dg-do compile }
// 1999-05-12 bkoz
diff --git a/libstdc++-v3/testsuite/17_intro/headers/c++200x/stdc++.cc b/libstdc++-v3/testsuite/17_intro/headers/c++200x/stdc++.cc
index 7ea17a9a956..38508a90b36 100644
--- a/libstdc++-v3/testsuite/17_intro/headers/c++200x/stdc++.cc
+++ b/libstdc++-v3/testsuite/17_intro/headers/c++200x/stdc++.cc
@@ -1,5 +1,5 @@
// FreeBSD wants warning clean system headers:
-// { dg-options "-Wall -Wsystem-headers" { target *-*-freebsd* } }
+// { dg-options "-Wall -Wsystem-headers" { target *-*-freebsd* *-*-dragonfly* } }
// { dg-options "-std=gnu++0x" }
// { dg-do compile }
diff --git a/libstdc++-v3/testsuite/17_intro/headers/c++200x/stdc++_multiple_inclusion.cc b/libstdc++-v3/testsuite/17_intro/headers/c++200x/stdc++_multiple_inclusion.cc
index 4ada6b1ef06..28a271b354b 100644
--- a/libstdc++-v3/testsuite/17_intro/headers/c++200x/stdc++_multiple_inclusion.cc
+++ b/libstdc++-v3/testsuite/17_intro/headers/c++200x/stdc++_multiple_inclusion.cc
@@ -1,5 +1,5 @@
// FreeBSD wants warning clean system headers:
-// { dg-options "-Wall -Wsystem-headers" { target *-*-freebsd* } }
+// { dg-options "-Wall -Wsystem-headers" { target *-*-freebsd* *-*-dragonfly* } }
// { dg-options "-std=gnu++0x" }
// { dg-do compile }
diff --git a/libstdc++-v3/testsuite/18_support/pthread_guard.cc b/libstdc++-v3/testsuite/18_support/pthread_guard.cc
index 72ae2cdaffc..7ac344f31ce 100644
--- a/libstdc++-v3/testsuite/18_support/pthread_guard.cc
+++ b/libstdc++-v3/testsuite/18_support/pthread_guard.cc
@@ -16,8 +16,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options "-pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-darwin* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-darwin* } }
#include <cstdlib>
#include <pthread.h>
diff --git a/libstdc++-v3/testsuite/20_util/aligned_union/1.cc b/libstdc++-v3/testsuite/20_util/aligned_union/1.cc
new file mode 100644
index 00000000000..5285bb044fc
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/aligned_union/1.cc
@@ -0,0 +1,72 @@
+// { dg-options " -std=gnu++11 " }
+// { dg-do compile }
+
+// 2014-04-16 Rüdiger Sonderfeld <ruediger@c-plusplus.de>
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// C++11 [meta.trans.other] 20.9.7.6: aligned_union
+
+#include <type_traits>
+#include <testsuite_tr1.h>
+
+struct MSAlignType { } __attribute__((__aligned__));
+
+template<typename...T>
+ struct mymax
+ {
+ static const std::size_t alignment = 0;
+ static const std::size_t size = 0;
+ };
+
+template<typename L, typename...T>
+ struct mymax<L, T...>
+ {
+ static const std::size_t alignment = alignof(L) > mymax<T...>::alignment
+ ? alignof(L) : mymax<T...>::alignment;
+ static const std::size_t size = sizeof(L) > mymax<T...>::size
+ ? sizeof(L) : mymax<T...>::size;
+ };
+
+void test01()
+{
+ using std::aligned_union;
+ using std::alignment_of;
+ using std::size_t;
+ using namespace __gnu_test;
+
+ const size_t max_a = mymax<char, short, int, double, int[4],
+ ClassType, MSAlignType>::alignment;
+ const size_t max_s = mymax<char, short, int, double, int[4],
+ ClassType, MSAlignType>::size;
+
+ typedef aligned_union<0, char, short, int, double, int[4],
+ ClassType, MSAlignType> au_type;
+ static_assert(au_type::alignment_value == max_a, "Alignment value");
+ static_assert(sizeof(au_type::type) >= max_s, "Storage size");
+
+ typedef aligned_union<max_s+100, char, short, int, double, int[4],
+ ClassType, MSAlignType> au_type2;
+ static_assert(sizeof(au_type2::type) >= max_s+100,
+ "Storage size (at least len)");
+}
+
+int main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/20_util/auto_ptr/assign_neg.cc b/libstdc++-v3/testsuite/20_util/auto_ptr/assign_neg.cc
index c88d4a291fd..1a699b74a18 100644
--- a/libstdc++-v3/testsuite/20_util/auto_ptr/assign_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/auto_ptr/assign_neg.cc
@@ -36,7 +36,6 @@ test01()
{
std::auto_ptr<Base> ptr2;
ptr2 = new Base; // { dg-error "no match" }
- // { dg-error "candidate" "candidate note" { target *-*-* } 38 }
return 0;
}
diff --git a/libstdc++-v3/testsuite/20_util/bind/60497.cc b/libstdc++-v3/testsuite/20_util/bind/60497.cc
new file mode 100644
index 00000000000..759c9d8b885
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bind/60497.cc
@@ -0,0 +1,40 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// libstdc++/60497
+
+#include <functional>
+#include <memory>
+
+struct A;
+template<typename T> struct B { T t; };
+
+using UP = std::unique_ptr<B<A>>;
+
+bool f(UP&, UP&) { return true; }
+
+bool g(UP& p)
+{
+ auto binder = std::bind(f, std::ref(p), std::placeholders::_1);
+ bool b1 = binder(std::ref(p));
+ auto binderbinder = std::bind(binder, std::placeholders::_1);
+ bool b2 = binderbinder(std::ref(p));
+ return b1 && b2;
+}
diff --git a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
index a744d832637..774858cafdc 100644
--- a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
@@ -19,7 +19,7 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-error "static assertion failed" "" { target *-*-* } 2003 }
+// { dg-error "static assertion failed" "" { target *-*-* } 2082 }
#include <utility>
diff --git a/libstdc++-v3/testsuite/20_util/duration/literals/61166.cc b/libstdc++-v3/testsuite/20_util/duration/literals/61166.cc
new file mode 100644
index 00000000000..e06adf8b060
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/duration/literals/61166.cc
@@ -0,0 +1,39 @@
+// { dg-do run }
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// libstdc++/61166
+
+#include <chrono>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ using namespace std::literals::chrono_literals;
+
+ // std::numeric_limits<unsigned>::max() == 4294967295
+ VERIFY( (429496729510h).count() == 429496729510 );
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/20_util/duration/literals/range.cc b/libstdc++-v3/testsuite/20_util/duration/literals/range.cc
new file mode 100644
index 00000000000..c005df650e2
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/duration/literals/range.cc
@@ -0,0 +1,31 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <chrono>
+
+void
+test01()
+{
+ using namespace std::literals::chrono_literals;
+
+ // std::numeric_limits<int64_t>::max() == 9223372036854775807;
+ auto h = 9223372036854775808h;
+ // { dg-error "cannot be represented" "" { target *-*-* } 794 }
+}
diff --git a/libstdc++-v3/testsuite/20_util/forward/1_neg.cc b/libstdc++-v3/testsuite/20_util/forward/1_neg.cc
index 06f7bcbdfd7..f34fc8a5d52 100644
--- a/libstdc++-v3/testsuite/20_util/forward/1_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/forward/1_neg.cc
@@ -28,7 +28,7 @@ template<class T, class A1, class A2>
factory(A1&& a1, A2&& a2)
{
return std::shared_ptr<T>(new T(std::forward<A1>(a1),
- std::forward<A2>(a2))); // { dg-error "no matching function" }
+ std::forward<A2>(a2))); // { dg-error "rvalue" }
}
struct A
diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-4.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-4.cc
new file mode 100644
index 00000000000..4950e5470cd
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-4.cc
@@ -0,0 +1,33 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+// { dg-require-cstdint "" }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+//
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <type_traits>
+
+// libstdc++/60326
+
+using namespace std;
+#ifdef _GLIBCXX_USE_WCHAR_T
+using wchar_signed = make_signed<wchar_t>::type;
+using wchar_unsigned = make_unsigned<wchar_t>::type;
+static_assert( !is_same<wchar_signed, wchar_unsigned>::value, "wchar_t" );
+#endif
+static_assert( is_signed<make_signed<char16_t>::type>::value, "char16_t");
+static_assert( is_signed<make_signed<char32_t>::type>::value, "char32_t");
diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
index 9f155ea92e2..d711546050d 100644
--- a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
@@ -48,5 +48,5 @@ void test01()
// { dg-error "required from here" "" { target *-*-* } 40 }
// { dg-error "required from here" "" { target *-*-* } 42 }
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1714 }
-// { dg-error "declaration of" "" { target *-*-* } 1678 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1747 }
+// { dg-error "declaration of" "" { target *-*-* } 1711 }
diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-1.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-1.cc
index f07cf4a621b..d9f13aabb80 100644
--- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-1.cc
+++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-1.cc
@@ -49,7 +49,7 @@ void test01()
#ifdef _GLIBCXX_USE_WCHAR_T
typedef make_unsigned<volatile wchar_t>::type test23_type;
- static_assert(is_same<test23_type, volatile wchar_t>::value, "");
+ static_assert(is_unsigned<test23_type>::value, "");
#endif
// Chapter 48, chapter 20. Smallest rank such that new unsigned type
diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-2.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-2.cc
index 8997fb7d812..807e2bf3f69 100644
--- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-2.cc
+++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-2.cc
@@ -30,6 +30,7 @@ void test01()
{
using std::make_unsigned;
using std::is_same;
+ using std::is_unsigned;
// Positive tests.
typedef make_unsigned<const unsigned int>::type test2_type;
@@ -50,7 +51,7 @@ void test01()
#ifdef _GLIBCXX_USE_WCHAR_T
typedef make_unsigned<volatile wchar_t>::type test23_type;
- static_assert(is_same<test23_type, volatile wchar_t>::value, "");
+ static_assert(is_unsigned<test23_type>::value, "");
#endif
typedef make_unsigned<test_enum>::type test24_type;
diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
index 57a5c616714..c77205be01d 100644
--- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
@@ -48,5 +48,5 @@ void test01()
// { dg-error "required from here" "" { target *-*-* } 40 }
// { dg-error "required from here" "" { target *-*-* } 42 }
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1632 }
-// { dg-error "declaration of" "" { target *-*-* } 1596 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1650 }
+// { dg-error "declaration of" "" { target *-*-* } 1614 }
diff --git a/libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type_neg.cc b/libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type_neg.cc
index a2bb0ab292d..34bc46e7734 100644
--- a/libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/pair/astuple/get_by_type_neg.cc
@@ -24,5 +24,5 @@ void test01()
{
std::pair<int, int> p;
- std::get<int>(p); // { dg-error "ambiguous" }
+ std::get<int>(p); // { dg-error "ambiguous|lvalue" }
}
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/assign/unique_ptr_lvalue_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/assign/unique_ptr_lvalue_neg.cc
index 48f1c00fd8a..c7d178bf093 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/assign/unique_ptr_lvalue_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/assign/unique_ptr_lvalue_neg.cc
@@ -35,7 +35,7 @@ test01()
std::shared_ptr<A> a;
std::unique_ptr<A> u;
- a = u; // { dg-error "cannot bind" }
+ a = u; // { dg-error "" }
return 0;
}
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr_neg.cc
index 563d2f83ef3..b0e9781864b 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr_neg.cc
@@ -34,7 +34,7 @@ test01()
bool test __attribute__((unused)) = true;
std::unique_ptr<A> a;
- std::shared_ptr<A> p(a); // { dg-error "cannot bind" }
+ std::shared_ptr<A> p(a); // { dg-error "" }
return 0;
}
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/modifiers/reset_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/modifiers/reset_neg.cc
index 45fa86af14a..4f343d06114 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/modifiers/reset_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/modifiers/reset_neg.cc
@@ -34,7 +34,7 @@ test01()
bool test __attribute__((unused)) = true;
const std::shared_ptr<A> p1(new A);
- p1.reset(); // { dg-error "discards qualifiers" }
+ p1.reset(); // { dg-error "" }
return 0;
}
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/thread/default_weaktoshared.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/thread/default_weaktoshared.cc
index 1255b7407c9..37305b36b2d 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/thread/default_weaktoshared.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/thread/default_weaktoshared.cc
@@ -17,8 +17,8 @@
// 20.6.6.2 Template class shared_ptr [util.smartptr.shared]
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options "-pthread -std=gnu++0x" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options "-pthread -std=gnu++0x" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options "-pthreads -std=gnu++0x" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/thread/mutex_weaktoshared.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/thread/mutex_weaktoshared.cc
index d8182fadf67..9366c4a0354 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/thread/mutex_weaktoshared.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/thread/mutex_weaktoshared.cc
@@ -17,8 +17,8 @@
// 20.6.6.2 Template class shared_ptr [util.smartptr.shared]
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
diff --git a/libstdc++-v3/testsuite/20_util/tuple/60497.cc b/libstdc++-v3/testsuite/20_util/tuple/60497.cc
index 76d4223165f..40d053b2168 100644
--- a/libstdc++-v3/testsuite/20_util/tuple/60497.cc
+++ b/libstdc++-v3/testsuite/20_util/tuple/60497.cc
@@ -35,3 +35,9 @@ auto a = std::get<0>(t);
auto b = std::get<0>(ct);
auto c = std::get<element_type>(t);
auto d = std::get<element_type>(ct);
+
+// same again for rvalues
+auto e = std::get<0>(std::move(t));
+auto f = std::get<0>(std::move(ct));
+auto g = std::get<element_type>(std::move(t));
+auto h = std::get<element_type>(std::move(ct));
diff --git a/libstdc++-v3/testsuite/20_util/tuple/comparison_operators/overloaded.cc b/libstdc++-v3/testsuite/20_util/tuple/comparison_operators/overloaded.cc
new file mode 100644
index 00000000000..0a343ae19d5
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/tuple/comparison_operators/overloaded.cc
@@ -0,0 +1,52 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tuple>
+
+// A type that is contextually convertible to bool but cannot be used with
+// the usual logical operators, and/or/not.
+struct TwistedLogic {
+ bool value;
+
+ explicit operator bool() const noexcept { return value; }
+};
+
+template<typename T>
+bool operator&&(const T&, TwistedLogic) = delete;
+
+template<typename T>
+bool operator&&(TwistedLogic, const T&) = delete;
+
+template<typename T>
+bool operator||(const T&, TwistedLogic) = delete;
+
+template<typename T>
+bool operator||(TwistedLogic, const T&) = delete;
+
+bool operator!(TwistedLogic) noexcept = delete;
+
+struct Compares {};
+
+TwistedLogic operator==(const Compares&, const Compares&) { return {true}; }
+TwistedLogic operator<(const Compares&, const Compares&) { return {false}; }
+
+auto a = std::make_tuple(nullptr, Compares{}, 2, 'U');
+auto b = a == a;
+auto c = a < a;
diff --git a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_by_type.cc b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_by_type.cc
index 226e9e4a89c..042f2149a0d 100644
--- a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_by_type.cc
+++ b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_by_type.cc
@@ -41,4 +41,8 @@ main()
get<1>(b)=5;
VERIFY(get<int>(b)==1 && get<int&>(b)==5 && get<const int&>(b)==2);
VERIFY(j==5);
+ // test rvalue overload:
+ VERIFY(get<int>(std::move(b))==1);
+ VERIFY(get<int&>(std::move(b))==5);
+ VERIFY(get<const int&>(std::move(b))==2);
}
diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/assign_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/assign_neg.cc
index 76e33def11f..f00f9d8555a 100644
--- a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/assign_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/assign_neg.cc
@@ -46,7 +46,6 @@ void
test03()
{
std::unique_ptr<int[2]> p1(new int[3]); // { dg-error "no match" }
- // { dg-error "candidate" "candidate-note" { target *-*-* } 48 }
std::unique_ptr<int[2]> p2 = p1; // { dg-error "deleted" }
}
diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/pointer_array_convertible_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/pointer_array_convertible_neg.cc
index 57c22239ad1..05a2e070169 100644
--- a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/pointer_array_convertible_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/pointer_array_convertible_neg.cc
@@ -35,7 +35,7 @@ struct B : A
void
test01()
{
- std::unique_ptr<B[]> B_from_A(new A[3]); //{ dg-error "invalid conversion from" }
+ std::unique_ptr<B[]> B_from_A(new A[3]); //{ dg-error "" }
}
// { dg-prune-output "include" }
diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/reset_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/reset_neg.cc
index 45e2c5ab966..5aecd48b195 100644
--- a/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/reset_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/reset_neg.cc
@@ -32,7 +32,7 @@ struct B : A
void test01()
{
std::unique_ptr<B[]> up;
- up.reset(new A[3]); // { dg-error "invalid conversion" }
+ up.reset(new A[3]); // { dg-error "" }
}
// { dg-prune-output "include" }
diff --git a/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc b/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc
index 5ce344c377f..cf5d6a57dd9 100644
--- a/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc
@@ -44,4 +44,4 @@ void test01()
tuple<Type> t(allocator_arg, a, 1);
}
-// { dg-error "no matching function" "" { target *-*-* } 118 }
+// { dg-error "no matching function" "" { target *-*-* } 91 }
diff --git a/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc b/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc
index 377bfe060c9..ceb20220f4c 100644
--- a/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc
@@ -31,7 +31,6 @@ test01()
{
std::weak_ptr<A> p1;
p1 < p1; // { dg-error "no match" }
- // { dg-error "candidate" "candidate note" { target *-*-* } 33 }
return 0;
}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/pthread18185.cc b/libstdc++-v3/testsuite/21_strings/basic_string/pthread18185.cc
index 6bf2313ff7e..c8ee4387633 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/pthread18185.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/pthread18185.cc
@@ -16,8 +16,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options "-pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options "-pthreads" { target *-*-solaris* } }
#include <ext/new_allocator.h>
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/pthread4.cc b/libstdc++-v3/testsuite/21_strings/basic_string/pthread4.cc
index cfa8a5ac57d..ceef4ef7db8 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/pthread4.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/pthread4.cc
@@ -19,8 +19,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options "-pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options "-pthreads" { target *-*-solaris* } }
#include <string>
diff --git a/libstdc++-v3/testsuite/22_locale/locale/cons/12658_thread-1.cc b/libstdc++-v3/testsuite/22_locale/locale/cons/12658_thread-1.cc
index 138641d88cb..03721662bde 100644
--- a/libstdc++-v3/testsuite/22_locale/locale/cons/12658_thread-1.cc
+++ b/libstdc++-v3/testsuite/22_locale/locale/cons/12658_thread-1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options "-pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options "-pthreads" { target *-*-solaris* } }
// { dg-require-namedlocale "en_US" }
// { dg-require-namedlocale "fr_FR" }
diff --git a/libstdc++-v3/testsuite/22_locale/locale/cons/12658_thread-2.cc b/libstdc++-v3/testsuite/22_locale/locale/cons/12658_thread-2.cc
index 0ff9fae2a10..93bc51634d4 100644
--- a/libstdc++-v3/testsuite/22_locale/locale/cons/12658_thread-2.cc
+++ b/libstdc++-v3/testsuite/22_locale/locale/cons/12658_thread-2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options "-pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options "-pthreads" { target *-*-solaris* } }
// { dg-require-namedlocale "en_US" }
// { dg-require-namedlocale "fr_FR" }
diff --git a/libstdc++-v3/testsuite/23_containers/array/element_access/60497.cc b/libstdc++-v3/testsuite/23_containers/array/element_access/60497.cc
new file mode 100644
index 00000000000..14932a1b303
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/array/element_access/60497.cc
@@ -0,0 +1,38 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+//
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+//
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// libstdc++/60497
+
+#include <array>
+#include <debug/array>
+#include <profile/array>
+#include <memory>
+
+struct A;
+template<typename T> struct B { T t; };
+
+std::array<B<A>*, 1> a;
+auto b = std::get<0>(std::move(a));
+
+std::__debug::array<B<A>*, 1> c;
+auto d = std::__debug::get<0>(std::move(c));
+
+std::__profile::array<B<A>*, 1> e;
+auto f = std::__profile::get<0>(std::move(e));
diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc
index f80798c9108..4b1e5aeb661 100644
--- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc
@@ -23,4 +23,4 @@
typedef std::tuple_element<1, std::array<int, 1>>::type type;
-// { dg-error "static assertion failed" "" { target *-*-* } 320 }
+// { dg-error "static assertion failed" "" { target *-*-* } 322 }
diff --git a/libstdc++-v3/testsuite/23_containers/list/pthread1.cc b/libstdc++-v3/testsuite/23_containers/list/pthread1.cc
index cdca89ffaad..28abed5f2c7 100644
--- a/libstdc++-v3/testsuite/23_containers/list/pthread1.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/pthread1.cc
@@ -17,8 +17,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options "-pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options "-pthreads" { target *-*-solaris* } }
// This multi-threading C++/STL/POSIX code adheres to rules outlined here:
diff --git a/libstdc++-v3/testsuite/23_containers/list/pthread5.cc b/libstdc++-v3/testsuite/23_containers/list/pthread5.cc
index ead8d332c40..8dc32f1c1f1 100644
--- a/libstdc++-v3/testsuite/23_containers/list/pthread5.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/pthread5.cc
@@ -19,8 +19,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options "-pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options "-pthreads" { target *-*-solaris* } }
#include <vector>
diff --git a/libstdc++-v3/testsuite/23_containers/map/pthread6.cc b/libstdc++-v3/testsuite/23_containers/map/pthread6.cc
index 74027bb97b5..aabeac37c8e 100644
--- a/libstdc++-v3/testsuite/23_containers/map/pthread6.cc
+++ b/libstdc++-v3/testsuite/23_containers/map/pthread6.cc
@@ -18,8 +18,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options "-pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options "-pthreads" { target *-*-solaris* } }
#include <string>
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/61143.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/61143.cc
new file mode 100644
index 00000000000..b9464254f12
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/61143.cc
@@ -0,0 +1,38 @@
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// libstdc++/61143
+
+#include <unordered_set>
+
+void test01()
+{
+ std::unordered_set<int> us1, us2;
+ us1.insert(1);
+
+ us2 = std::move(us1);
+
+ us1.insert(1);
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/swap.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/swap.cc
new file mode 100644
index 00000000000..d03fd1dc3b1
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/swap.cc
@@ -0,0 +1,65 @@
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <unordered_set>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ std::unordered_set<int> us1 { 0, 1 };
+ {
+ std::unordered_set<int> us2(std::move(us1));
+
+ us1.swap(us2);
+
+ VERIFY( us1.find(0) != us1.end() );
+
+ us1.insert(2);
+
+ VERIFY( us1.size() == 3 );
+
+ us2.swap(us1);
+
+ VERIFY( us2.size() == 3 );
+ VERIFY( us2.find(2) != us2.end() );
+
+ us1 = { 3, 4, 5 };
+
+ VERIFY( us1.size() == 3 );
+ VERIFY( us1.bucket_count() >= 3 );
+
+ std::unordered_set<int> us3(std::move(us1));
+ us3 = std::move(us2);
+
+ us1.swap(us2);
+
+ VERIFY( us1.empty() );
+ VERIFY( us2.empty() );
+ }
+
+ us1 = { 0, 1 };
+ VERIFY( us1.size() == 2 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/capacity/resize/1.cc b/libstdc++-v3/testsuite/23_containers/vector/capacity/resize/1.cc
index 1c30ff5ae29..c4cd790c707 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/capacity/resize/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/capacity/resize/1.cc
@@ -22,7 +22,7 @@
// This fails on some versions of Darwin 8 because malloc doesn't return
// NULL even if an allocation fails (filed as Radar 3884894).
-// { dg-do run { xfail *-*-darwin8.[0-4].* } }
+// { dg-do run { xfail *-*-darwin8.[0-4].* *-*-dragonfly* } }
#include <vector>
#include <stdexcept>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/multithreaded_swap.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/multithreaded_swap.cc
index fb55a3a262d..b2973ae373b 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/debug/multithreaded_swap.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/debug/multithreaded_swap.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/c_math_dynamic.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/c_math_dynamic.cc
index 9baa1662580..40f52f47564 100644
--- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/c_math_dynamic.cc
+++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/c_math_dynamic.cc
@@ -19,7 +19,7 @@
// { dg-do link }
-// { dg-options "-D_XOPEN_SOURCE" { target *-*-freebsd* } }
+// { dg-options "-D_XOPEN_SOURCE" { target *-*-freebsd* *-*-dragonfly* } }
#include <cmath>
diff --git a/libstdc++-v3/testsuite/27_io/basic_ofstream/pthread2.cc b/libstdc++-v3/testsuite/27_io/basic_ofstream/pthread2.cc
index 233df3f082b..c966c3f8580 100644
--- a/libstdc++-v3/testsuite/27_io/basic_ofstream/pthread2.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_ofstream/pthread2.cc
@@ -18,8 +18,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options "-pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options "-pthreads" { target *-*-solaris* } }
#include <fstream>
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostringstream/pthread3.cc b/libstdc++-v3/testsuite/27_io/basic_ostringstream/pthread3.cc
index 5925558b2b6..de25ad1fd29 100644
--- a/libstdc++-v3/testsuite/27_io/basic_ostringstream/pthread3.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_ostringstream/pthread3.cc
@@ -18,8 +18,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options "-pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options "-pthreads" { target *-*-solaris* } }
#include <sstream>
diff --git a/libstdc++-v3/testsuite/27_io/basic_streambuf/cons/57394.cc b/libstdc++-v3/testsuite/27_io/basic_streambuf/cons/57394.cc
new file mode 100644
index 00000000000..f58c545a6f2
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_streambuf/cons/57394.cc
@@ -0,0 +1,113 @@
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-require-namedlocale "de_DE" }
+
+// 27.6.3 template class basic_streambuf
+
+#include <streambuf>
+#include <testsuite_hooks.h>
+
+struct streambuf : std::streambuf
+{
+ streambuf()
+ {
+ setp(pbuf, std::end(pbuf));
+ setg(gbuf, gbuf, gbuf);
+ }
+
+ streambuf(const std::locale& loc) : streambuf()
+ {
+ imbue(loc);
+ }
+
+ // implement tests as member functions to be able to call protected members
+ void test_copy() const;
+ void test_assign() const;
+ void test_swap() const;
+
+ char gbuf[32];
+ char pbuf[32];
+};
+
+void streambuf::test_copy() const
+{
+ bool test __attribute__((unused)) = true;
+
+ streambuf a(*this);
+
+ VERIFY( eback() == a.eback() );
+ VERIFY( gptr() == a.gptr() );
+ VERIFY( egptr() == a.egptr() );
+ VERIFY( pbase() == a.pbase() );
+ VERIFY( pptr() == a.pptr() );
+ VERIFY( epptr() == a.epptr() );
+ VERIFY( getloc() == a.getloc() );
+}
+
+void streambuf::test_assign() const
+{
+ bool test __attribute__((unused)) = true;
+
+ streambuf a;
+ a = *this;
+
+ VERIFY( eback() == a.eback() );
+ VERIFY( gptr() == a.gptr() );
+ VERIFY( egptr() == a.egptr() );
+ VERIFY( pbase() == a.pbase() );
+ VERIFY( pptr() == a.pptr() );
+ VERIFY( epptr() == a.epptr() );
+ VERIFY( getloc() == a.getloc() );
+}
+
+void streambuf::test_swap() const
+{
+ bool test __attribute__((unused)) = true;
+
+ streambuf a(*this);
+ streambuf b;
+ const streambuf c(b);
+
+ a.swap(b);
+
+ VERIFY( eback() == b.eback() );
+ VERIFY( gptr() == b.gptr() );
+ VERIFY( egptr() == b.egptr() );
+ VERIFY( pbase() == b.pbase() );
+ VERIFY( pptr() == b.pptr() );
+ VERIFY( epptr() == b.epptr() );
+ VERIFY( getloc() == b.getloc() );
+
+ VERIFY( c.eback() == a.eback() );
+ VERIFY( c.gptr() == a.gptr() );
+ VERIFY( c.egptr() == a.egptr() );
+ VERIFY( c.pbase() == a.pbase() );
+ VERIFY( c.pptr() == a.pptr() );
+ VERIFY( c.epptr() == a.epptr() );
+ VERIFY( c.getloc() == a.getloc() );
+}
+
+int main()
+{
+ std::locale loc("de_DE");
+ streambuf s(loc);
+ s.test_copy();
+ s.test_assign();
+ s.test_swap();
+}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/quoted_char.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/quoted_char.cc
index e7280acbdbd..86417323516 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/quoted_char.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/quoted_char.cc
@@ -44,6 +44,16 @@ test01()
VERIFY(regex_match_debug("_az", regex("\\w*")));
VERIFY(regex_match_debug("!@#$%", regex("\\W*")));
VERIFY(!regex_match_debug("_01234", regex("\\W*")));
+
+ VERIFY(regex_match_debug("01", regex("[\\d]*")));
+ VERIFY(regex_match_debug("asdfjkl", regex("[\\D]*")));
+ VERIFY(!regex_match_debug("asdfjkl0", regex("[\\D]*")));
+ VERIFY(regex_match_debug("\r\t\v\f ", regex("[\\s]*")));
+ VERIFY(regex_match_debug("asdfjkl", regex("[\\S]*")));
+ VERIFY(!regex_match_debug("asdfjkl\r", regex("[\\S]*")));
+ VERIFY(regex_match_debug("_az", regex("[\\w]*")));
+ VERIFY(regex_match_debug("!@#$%", regex("[\\W]*")));
+ VERIFY(!regex_match_debug("_01234", regex("[\\W]*")));
}
int
diff --git a/libstdc++-v3/testsuite/28_regex/regex_error/base.cc b/libstdc++-v3/testsuite/28_regex/regex_error/base.cc
new file mode 100644
index 00000000000..a7318af1361
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/regex_error/base.cc
@@ -0,0 +1,32 @@
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+//
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 28.6 [re.badexp]
+
+// { dg-options "-std=c++11" }
+
+#include <regex>
+
+struct re : std::regex_error
+{
+ re() : regex_error(std::regex_constants::error_stack) { }
+};
+
+int main()
+{
+ re r __attribute__((unused));
+}
diff --git a/libstdc++-v3/testsuite/30_threads/async/42819.cc b/libstdc++-v3/testsuite/30_threads/async/42819.cc
index 587403556c6..95416a6eaf9 100644
--- a/libstdc++-v3/testsuite/30_threads/async/42819.cc
+++ b/libstdc++-v3/testsuite/30_threads/async/42819.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/async/49668.cc b/libstdc++-v3/testsuite/30_threads/async/49668.cc
index a13a1a22dd4..1d42b6a6e51 100644
--- a/libstdc++-v3/testsuite/30_threads/async/49668.cc
+++ b/libstdc++-v3/testsuite/30_threads/async/49668.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/async/54297.cc b/libstdc++-v3/testsuite/30_threads/async/54297.cc
index d760363aed8..281916dabc8 100644
--- a/libstdc++-v3/testsuite/30_threads/async/54297.cc
+++ b/libstdc++-v3/testsuite/30_threads/async/54297.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/async/any.cc b/libstdc++-v3/testsuite/30_threads/async/any.cc
index 733f345b37c..d4406ca3df8 100644
--- a/libstdc++-v3/testsuite/30_threads/async/any.cc
+++ b/libstdc++-v3/testsuite/30_threads/async/any.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/async/async.cc b/libstdc++-v3/testsuite/30_threads/async/async.cc
index 3bd3da129a7..de1ad575169 100644
--- a/libstdc++-v3/testsuite/30_threads/async/async.cc
+++ b/libstdc++-v3/testsuite/30_threads/async/async.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/async/forced_unwind.cc b/libstdc++-v3/testsuite/30_threads/async/forced_unwind.cc
new file mode 100644
index 00000000000..7b0a49280fc
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/async/forced_unwind.cc
@@ -0,0 +1,45 @@
+// { dg-do run { target *-*-linux* *-*-gnu* } }
+// { dg-options " -std=gnu++11 -pthread" { target *-*-linux* *-*-gnu* } }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Test (non-standard) handling of __forced_unwind exception.
+
+#include <future>
+#include <stdexcept>
+#include <pthread.h>
+#include <testsuite_hooks.h>
+
+void f() { pthread_exit(nullptr); }
+
+int main()
+{
+ auto fut = std::async(std::launch::async, f);
+ try
+ {
+ fut.get();
+ throw std::logic_error("Unreachable");
+ }
+ catch (const std::future_error& e)
+ {
+ VERIFY( e.code() == std::future_errc::broken_promise );
+ }
+}
diff --git a/libstdc++-v3/testsuite/30_threads/async/launch.cc b/libstdc++-v3/testsuite/30_threads/async/launch.cc
index 2dfaf571f06..7a0988664b4 100644
--- a/libstdc++-v3/testsuite/30_threads/async/launch.cc
+++ b/libstdc++-v3/testsuite/30_threads/async/launch.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/async/sync.cc b/libstdc++-v3/testsuite/30_threads/async/sync.cc
index 89ae51423b4..9cf0ed7d1ad 100644
--- a/libstdc++-v3/testsuite/30_threads/async/sync.cc
+++ b/libstdc++-v3/testsuite/30_threads/async/sync.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/call_once/39909.cc b/libstdc++-v3/testsuite/30_threads/call_once/39909.cc
index ea88d5e47b8..a6fcd072ae3 100644
--- a/libstdc++-v3/testsuite/30_threads/call_once/39909.cc
+++ b/libstdc++-v3/testsuite/30_threads/call_once/39909.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/call_once/49668.cc b/libstdc++-v3/testsuite/30_threads/call_once/49668.cc
index bcedcfc2cd9..8d0d4325204 100644
--- a/libstdc++-v3/testsuite/30_threads/call_once/49668.cc
+++ b/libstdc++-v3/testsuite/30_threads/call_once/49668.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/call_once/60497.cc b/libstdc++-v3/testsuite/30_threads/call_once/60497.cc
new file mode 100644
index 00000000000..05edc613f94
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/call_once/60497.cc
@@ -0,0 +1,41 @@
+// { dg-do compile { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++11 -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++11 -pthreads" { target *-*-solaris* } }
+// { dg-options " -std=gnu++11 " { target *-*-cygwin *-*-darwin* } }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// libstdc++/60497
+
+#include <mutex>
+#include <memory>
+
+struct A;
+template<typename T> struct B { T t; };
+
+using UP = std::unique_ptr<B<A>>;
+
+void f(UP&) { }
+
+void g(UP& p)
+{
+ std::once_flag o;
+ std::call_once(o, f, std::ref(p));
+}
diff --git a/libstdc++-v3/testsuite/30_threads/call_once/call_once1.cc b/libstdc++-v3/testsuite/30_threads/call_once/call_once1.cc
index 57f2529e5bf..e5623f45d59 100644
--- a/libstdc++-v3/testsuite/30_threads/call_once/call_once1.cc
+++ b/libstdc++-v3/testsuite/30_threads/call_once/call_once1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable/54185.cc b/libstdc++-v3/testsuite/30_threads/condition_variable/54185.cc
index 924271826b9..509d5dbc2a1 100644
--- a/libstdc++-v3/testsuite/30_threads/condition_variable/54185.cc
+++ b/libstdc++-v3/testsuite/30_threads/condition_variable/54185.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin1[1-9]* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin1[1-9]* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable/cons/1.cc b/libstdc++-v3/testsuite/30_threads/condition_variable/cons/1.cc
index 197c5f93a57..5db4852381a 100644
--- a/libstdc++-v3/testsuite/30_threads/condition_variable/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/condition_variable/cons/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable/members/1.cc b/libstdc++-v3/testsuite/30_threads/condition_variable/members/1.cc
index dcd6f3d2c89..34f915928dc 100644
--- a/libstdc++-v3/testsuite/30_threads/condition_variable/members/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/condition_variable/members/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc b/libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc
index 1fc906a6cba..db417cb2538 100644
--- a/libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable/members/53841.cc b/libstdc++-v3/testsuite/30_threads/condition_variable/members/53841.cc
index ee998c17c5d..90d02d91f55 100644
--- a/libstdc++-v3/testsuite/30_threads/condition_variable/members/53841.cc
+++ b/libstdc++-v3/testsuite/30_threads/condition_variable/members/53841.cc
@@ -1,5 +1,5 @@
-// { dg-do compile }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* hppa*-hp-hpux11* } }
+// { dg-do compile { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* hppa*-hp-hpux11* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* hppa*-hp-hpux11* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable/native_handle/typesizes.cc b/libstdc++-v3/testsuite/30_threads/condition_variable/native_handle/typesizes.cc
index 540a5404669..dda078ceefd 100644
--- a/libstdc++-v3/testsuite/30_threads/condition_variable/native_handle/typesizes.cc
+++ b/libstdc++-v3/testsuite/30_threads/condition_variable/native_handle/typesizes.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable_any/50862.cc b/libstdc++-v3/testsuite/30_threads/condition_variable_any/50862.cc
index ffb45b56f10..eefdc9edfb4 100644
--- a/libstdc++-v3/testsuite/30_threads/condition_variable_any/50862.cc
+++ b/libstdc++-v3/testsuite/30_threads/condition_variable_any/50862.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable_any/53830.cc b/libstdc++-v3/testsuite/30_threads/condition_variable_any/53830.cc
index 1350048d77b..d3d8abacdc8 100644
--- a/libstdc++-v3/testsuite/30_threads/condition_variable_any/53830.cc
+++ b/libstdc++-v3/testsuite/30_threads/condition_variable_any/53830.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable_any/cons/1.cc b/libstdc++-v3/testsuite/30_threads/condition_variable_any/cons/1.cc
index 89304694620..7592a856175 100644
--- a/libstdc++-v3/testsuite/30_threads/condition_variable_any/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/condition_variable_any/cons/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable_any/members/1.cc b/libstdc++-v3/testsuite/30_threads/condition_variable_any/members/1.cc
index fa5b58a8679..a580c9eb28f 100644
--- a/libstdc++-v3/testsuite/30_threads/condition_variable_any/members/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/condition_variable_any/members/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable_any/members/2.cc b/libstdc++-v3/testsuite/30_threads/condition_variable_any/members/2.cc
index 0d2a3f9107d..1b482705973 100644
--- a/libstdc++-v3/testsuite/30_threads/condition_variable_any/members/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/condition_variable_any/members/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/future/cons/move.cc b/libstdc++-v3/testsuite/30_threads/future/cons/move.cc
index d8d4f492aa7..9cf21a076ad 100644
--- a/libstdc++-v3/testsuite/30_threads/future/cons/move.cc
+++ b/libstdc++-v3/testsuite/30_threads/future/cons/move.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/future/members/45133.cc b/libstdc++-v3/testsuite/30_threads/future/members/45133.cc
index a1685f78df3..6209cedd48b 100644
--- a/libstdc++-v3/testsuite/30_threads/future/members/45133.cc
+++ b/libstdc++-v3/testsuite/30_threads/future/members/45133.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/future/members/get.cc b/libstdc++-v3/testsuite/30_threads/future/members/get.cc
index 367b00912aa..5e4b087c9fb 100644
--- a/libstdc++-v3/testsuite/30_threads/future/members/get.cc
+++ b/libstdc++-v3/testsuite/30_threads/future/members/get.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/future/members/get2.cc b/libstdc++-v3/testsuite/30_threads/future/members/get2.cc
index 6e54df07550..7c4d7c7be6a 100644
--- a/libstdc++-v3/testsuite/30_threads/future/members/get2.cc
+++ b/libstdc++-v3/testsuite/30_threads/future/members/get2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/future/members/share.cc b/libstdc++-v3/testsuite/30_threads/future/members/share.cc
index 074404a4977..d881e3c7474 100644
--- a/libstdc++-v3/testsuite/30_threads/future/members/share.cc
+++ b/libstdc++-v3/testsuite/30_threads/future/members/share.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/future/members/valid.cc b/libstdc++-v3/testsuite/30_threads/future/members/valid.cc
index de1446ad171..bcbc338aa99 100644
--- a/libstdc++-v3/testsuite/30_threads/future/members/valid.cc
+++ b/libstdc++-v3/testsuite/30_threads/future/members/valid.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/future/members/wait.cc b/libstdc++-v3/testsuite/30_threads/future/members/wait.cc
index f2fb9780340..e42427eac4a 100644
--- a/libstdc++-v3/testsuite/30_threads/future/members/wait.cc
+++ b/libstdc++-v3/testsuite/30_threads/future/members/wait.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/future/members/wait_for.cc b/libstdc++-v3/testsuite/30_threads/future/members/wait_for.cc
index 05623c715d4..63ec9b356d0 100644
--- a/libstdc++-v3/testsuite/30_threads/future/members/wait_for.cc
+++ b/libstdc++-v3/testsuite/30_threads/future/members/wait_for.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/future/members/wait_until.cc b/libstdc++-v3/testsuite/30_threads/future/members/wait_until.cc
index 88ff4c48f90..1e3793a0b7d 100644
--- a/libstdc++-v3/testsuite/30_threads/future/members/wait_until.cc
+++ b/libstdc++-v3/testsuite/30_threads/future/members/wait_until.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/lock/1.cc b/libstdc++-v3/testsuite/30_threads/lock/1.cc
index 4cb6f15488a..a3f00896ef2 100644
--- a/libstdc++-v3/testsuite/30_threads/lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/lock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/lock/2.cc b/libstdc++-v3/testsuite/30_threads/lock/2.cc
index acde4342042..8bfdbb4c0de 100644
--- a/libstdc++-v3/testsuite/30_threads/lock/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/lock/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/lock/3.cc b/libstdc++-v3/testsuite/30_threads/lock/3.cc
index 93b584668a8..be16b15f80f 100644
--- a/libstdc++-v3/testsuite/30_threads/lock/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/lock/3.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/lock/4.cc b/libstdc++-v3/testsuite/30_threads/lock/4.cc
index d6fa4293dff..0579d789c6e 100644
--- a/libstdc++-v3/testsuite/30_threads/lock/4.cc
+++ b/libstdc++-v3/testsuite/30_threads/lock/4.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/mutex/cons/1.cc b/libstdc++-v3/testsuite/30_threads/mutex/cons/1.cc
index aab9ff76503..870e75434df 100644
--- a/libstdc++-v3/testsuite/30_threads/mutex/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/mutex/cons/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/mutex/dest/destructor_locked.cc b/libstdc++-v3/testsuite/30_threads/mutex/dest/destructor_locked.cc
index 6a4f12fb232..71ea574e73b 100644
--- a/libstdc++-v3/testsuite/30_threads/mutex/dest/destructor_locked.cc
+++ b/libstdc++-v3/testsuite/30_threads/mutex/dest/destructor_locked.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/mutex/lock/1.cc b/libstdc++-v3/testsuite/30_threads/mutex/lock/1.cc
index 4d407f82dc4..1702880e090 100644
--- a/libstdc++-v3/testsuite/30_threads/mutex/lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/mutex/lock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/mutex/native_handle/1.cc b/libstdc++-v3/testsuite/30_threads/mutex/native_handle/1.cc
index 9c48155425d..324d4e7ef9b 100644
--- a/libstdc++-v3/testsuite/30_threads/mutex/native_handle/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/mutex/native_handle/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/mutex/native_handle/typesizes.cc b/libstdc++-v3/testsuite/30_threads/mutex/native_handle/typesizes.cc
index a60ea236e37..5b9a812876e 100644
--- a/libstdc++-v3/testsuite/30_threads/mutex/native_handle/typesizes.cc
+++ b/libstdc++-v3/testsuite/30_threads/mutex/native_handle/typesizes.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/mutex/try_lock/1.cc b/libstdc++-v3/testsuite/30_threads/mutex/try_lock/1.cc
index 7e35c460342..47a3cd1dc32 100644
--- a/libstdc++-v3/testsuite/30_threads/mutex/try_lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/mutex/try_lock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/mutex/try_lock/2.cc b/libstdc++-v3/testsuite/30_threads/mutex/try_lock/2.cc
index 98cc94d7593..d0355812d9a 100644
--- a/libstdc++-v3/testsuite/30_threads/mutex/try_lock/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/mutex/try_lock/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/mutex/unlock/1.cc b/libstdc++-v3/testsuite/30_threads/mutex/unlock/1.cc
index 402d7ddd016..4512a8a633a 100644
--- a/libstdc++-v3/testsuite/30_threads/mutex/unlock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/mutex/unlock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/49668.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/49668.cc
index 05fac3dce23..f8f81e7459e 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/49668.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/49668.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/60564.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/60564.cc
index 956d506d756..5554a494137 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/60564.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/60564.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++11 -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++11 -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++11 -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++11 " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/1.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/1.cc
index 3128b635650..af83a4f8b21 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/2.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/2.cc
index 62f951e01b2..54c4cd2ab66 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/3.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/3.cc
index 9238753e7ac..996dbadfbf0 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/3.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/56492.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/56492.cc
index c256565fd02..be07a91ed4f 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/56492.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/56492.cc
@@ -1,5 +1,5 @@
-// { dg-do compile { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++11 -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do compile { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++11 -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++11 -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++11 " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/alloc.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/alloc.cc
index 9de283e9cd8..77a7c67603b 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/alloc.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/alloc.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/move.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/move.cc
index 263e0f05077..4b25b1e4c46 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/move.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/move.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/move_assign.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/move_assign.cc
index dcde7ef4f73..5d1981eda6e 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/move_assign.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/move_assign.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/forced_unwind.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/forced_unwind.cc
new file mode 100644
index 00000000000..235ab178f05
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/forced_unwind.cc
@@ -0,0 +1,48 @@
+// { dg-do run { target *-*-linux* *-*-gnu* } }
+// { dg-options " -std=gnu++11 -pthread" { target *-*-linux* *-*-gnu* } }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Test (non-standard) handling of __forced_unwind exception.
+
+#include <future>
+#include <stdexcept>
+#include <pthread.h>
+#include <testsuite_hooks.h>
+
+void f() { pthread_exit(nullptr); }
+
+int main()
+{
+ std::packaged_task<void()> p(f);
+ auto fut = p.get_future();
+ std::thread t(std::move(p));
+ try
+ {
+ fut.get();
+ throw std::logic_error("Unreachable");
+ }
+ catch (const std::future_error& e)
+ {
+ VERIFY( e.code() == std::future_errc::broken_promise );
+ }
+ t.join();
+}
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/members/get_future.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/members/get_future.cc
index f12ab2d9de2..318d1c3b3a7 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/members/get_future.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/members/get_future.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/members/get_future2.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/members/get_future2.cc
index 544a0c371dd..a4fb528af24 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/members/get_future2.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/members/get_future2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke.cc
index 26d2267dffe..eafda434229 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke2.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke2.cc
index 4afe37f1a67..4ee48b446c3 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke2.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke3.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke3.cc
index b977b84aaa7..fc5f9becb6b 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke3.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke3.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke4.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke4.cc
index 3b01043012c..5c81afd1c0e 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke4.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke4.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke5.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke5.cc
index bb991f0fe74..8780952dc68 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke5.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke5.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/members/reset.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/members/reset.cc
index 331c3a4b048..2da868f7c4c 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/members/reset.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/members/reset.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/members/reset2.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/members/reset2.cc
index 6b418f0280a..7f488e19c8f 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/members/reset2.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/members/reset2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/members/swap.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/members/swap.cc
index d68aa5472cf..92f04308bc6 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/members/swap.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/members/swap.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/members/valid.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/members/valid.cc
index 6515f9b8737..cc6911eae2f 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/members/valid.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/members/valid.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/promise/60966.cc b/libstdc++-v3/testsuite/30_threads/promise/60966.cc
new file mode 100644
index 00000000000..47333a1fd0e
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/promise/60966.cc
@@ -0,0 +1,67 @@
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++11 -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++11 -pthreads" { target *-*-solaris* } }
+// { dg-options " -std=gnu++11 " { target *-*-cygwin *-*-darwin* } }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// libstdc++/60966
+// This test hangs if std::promise::~promise() destroys the
+// shared state before std::promise::set_value() finishes using it.
+
+#include <future>
+#include <thread>
+#include <vector>
+
+const int THREADS = 10;
+
+void run_task(std::promise<void>* pr)
+{
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ pr->set_value();
+}
+
+int main()
+{
+ std::vector<std::promise<void>*> tasks(THREADS);
+ std::vector<std::thread> threads(THREADS);
+ std::vector<std::future<void>> futures(THREADS);
+
+ for (int i = 0; i < THREADS; ++i)
+ {
+ std::promise<void>* task = new std::promise<void>;
+ tasks[i] = task;
+ futures[i] = task->get_future();
+ threads[i] = std::thread(run_task, task);
+ }
+
+ for (int i = 0; i < THREADS; ++i)
+ {
+ // the temporary future releases the state as soon as wait() returns
+ std::future<void>(std::move(futures[i])).wait();
+ // state is ready, should now be safe to delete promise, so it
+ // releases the shared state too
+ delete tasks[i];
+ }
+
+ for (auto& t : threads)
+ t.join();
+}
diff --git a/libstdc++-v3/testsuite/30_threads/promise/cons/1.cc b/libstdc++-v3/testsuite/30_threads/promise/cons/1.cc
index 89130601629..409bfd42c6f 100644
--- a/libstdc++-v3/testsuite/30_threads/promise/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/promise/cons/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/promise/cons/alloc.cc b/libstdc++-v3/testsuite/30_threads/promise/cons/alloc.cc
index 10fa8824c94..ac8fb1313c0 100644
--- a/libstdc++-v3/testsuite/30_threads/promise/cons/alloc.cc
+++ b/libstdc++-v3/testsuite/30_threads/promise/cons/alloc.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/promise/cons/move.cc b/libstdc++-v3/testsuite/30_threads/promise/cons/move.cc
index 7196e93e0cd..00ebc171ea4 100644
--- a/libstdc++-v3/testsuite/30_threads/promise/cons/move.cc
+++ b/libstdc++-v3/testsuite/30_threads/promise/cons/move.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/promise/cons/move_assign.cc b/libstdc++-v3/testsuite/30_threads/promise/cons/move_assign.cc
index 1bfbd356027..d6a0dad86f3 100644
--- a/libstdc++-v3/testsuite/30_threads/promise/cons/move_assign.cc
+++ b/libstdc++-v3/testsuite/30_threads/promise/cons/move_assign.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/promise/members/get_future.cc b/libstdc++-v3/testsuite/30_threads/promise/members/get_future.cc
index 3f0e37a0add..51457dfbb48 100644
--- a/libstdc++-v3/testsuite/30_threads/promise/members/get_future.cc
+++ b/libstdc++-v3/testsuite/30_threads/promise/members/get_future.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/promise/members/get_future2.cc b/libstdc++-v3/testsuite/30_threads/promise/members/get_future2.cc
index 6e0814636ae..aff4f5b2f82 100644
--- a/libstdc++-v3/testsuite/30_threads/promise/members/get_future2.cc
+++ b/libstdc++-v3/testsuite/30_threads/promise/members/get_future2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/promise/members/set_exception.cc b/libstdc++-v3/testsuite/30_threads/promise/members/set_exception.cc
index e07893e481d..585ed3b708a 100644
--- a/libstdc++-v3/testsuite/30_threads/promise/members/set_exception.cc
+++ b/libstdc++-v3/testsuite/30_threads/promise/members/set_exception.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/promise/members/set_exception2.cc b/libstdc++-v3/testsuite/30_threads/promise/members/set_exception2.cc
index 949702c5627..d12a0d2dc6f 100644
--- a/libstdc++-v3/testsuite/30_threads/promise/members/set_exception2.cc
+++ b/libstdc++-v3/testsuite/30_threads/promise/members/set_exception2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/promise/members/set_value.cc b/libstdc++-v3/testsuite/30_threads/promise/members/set_value.cc
index a670ab0d88c..75e9b5177f6 100644
--- a/libstdc++-v3/testsuite/30_threads/promise/members/set_value.cc
+++ b/libstdc++-v3/testsuite/30_threads/promise/members/set_value.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/promise/members/set_value2.cc b/libstdc++-v3/testsuite/30_threads/promise/members/set_value2.cc
index 3764d11b2e4..6633a53afd0 100644
--- a/libstdc++-v3/testsuite/30_threads/promise/members/set_value2.cc
+++ b/libstdc++-v3/testsuite/30_threads/promise/members/set_value2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/promise/members/set_value3.cc b/libstdc++-v3/testsuite/30_threads/promise/members/set_value3.cc
index e7bd13f5f72..6a3e03efc08 100644
--- a/libstdc++-v3/testsuite/30_threads/promise/members/set_value3.cc
+++ b/libstdc++-v3/testsuite/30_threads/promise/members/set_value3.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/promise/members/swap.cc b/libstdc++-v3/testsuite/30_threads/promise/members/swap.cc
index c003a404773..30612493636 100644
--- a/libstdc++-v3/testsuite/30_threads/promise/members/swap.cc
+++ b/libstdc++-v3/testsuite/30_threads/promise/members/swap.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_mutex/cons/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_mutex/cons/1.cc
index 8bef41d6a04..7604a14bcb3 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_mutex/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_mutex/cons/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_mutex/dest/destructor_locked.cc b/libstdc++-v3/testsuite/30_threads/recursive_mutex/dest/destructor_locked.cc
index 7ced0dabbf3..348a10ba0b2 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_mutex/dest/destructor_locked.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_mutex/dest/destructor_locked.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_mutex/lock/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_mutex/lock/1.cc
index af58e5306c7..6e3c1b397b0 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_mutex/lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_mutex/lock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_mutex/native_handle/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_mutex/native_handle/1.cc
index be25308e2f3..765be0dd9c3 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_mutex/native_handle/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_mutex/native_handle/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_mutex/native_handle/typesizes.cc b/libstdc++-v3/testsuite/30_threads/recursive_mutex/native_handle/typesizes.cc
index c2bfae22a32..30d0c28d250 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_mutex/native_handle/typesizes.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_mutex/native_handle/typesizes.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_mutex/try_lock/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_mutex/try_lock/1.cc
index 2c0a7d2d5ec..63133940c22 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_mutex/try_lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_mutex/try_lock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_mutex/try_lock/2.cc b/libstdc++-v3/testsuite/30_threads/recursive_mutex/try_lock/2.cc
index 76fa20aa056..a7c229d0f55 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_mutex/try_lock/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_mutex/try_lock/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_mutex/unlock/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_mutex/unlock/1.cc
index 2aef2749e3a..42f991be250 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_mutex/unlock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_mutex/unlock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/1.cc
index a6a9a28eff2..10b0bcc2867 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/dest/destructor_locked.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/dest/destructor_locked.cc
index 5cc92b58af2..38f02a245e6 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/dest/destructor_locked.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/dest/destructor_locked.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/1.cc
index d90874dc646..5993eb19568 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/2.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/2.cc
index 75f01b442bd..2e0ece93165 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/1.cc
index f3f8f1d7143..369d1b4f33f 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/typesizes.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/typesizes.cc
index 71632abb470..6e9d771c17a 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/typesizes.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/typesizes.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/1.cc
index c6ec13846b0..13536e31749 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/2.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/2.cc
index 4f02074cc71..34ff1fa0fdf 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options "-std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options "-std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options "-std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options "-std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/1.cc
index 41a1a75869e..3c5fe0cbfca 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/2.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/2.cc
index ef344a2de0f..6cde543f120 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/3.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/3.cc
index 90353a781c2..b6a9372003e 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/3.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/1.cc
index c6ec13846b0..13536e31749 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/2.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/2.cc
index 2cfdfb2ea8a..8c0becf3c16 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/unlock/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/unlock/1.cc
index 18b3f53cb68..46396ed691f 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/unlock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/unlock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_future/cons/move.cc b/libstdc++-v3/testsuite/30_threads/shared_future/cons/move.cc
index de67e3a10c3..f1fcc04113b 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_future/cons/move.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_future/cons/move.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_future/members/45133.cc b/libstdc++-v3/testsuite/30_threads/shared_future/members/45133.cc
index 5723d64c0c6..07b8f490b58 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_future/members/45133.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_future/members/45133.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_future/members/get.cc b/libstdc++-v3/testsuite/30_threads/shared_future/members/get.cc
index 590c7183a0f..189451b02ff 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_future/members/get.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_future/members/get.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_future/members/get2.cc b/libstdc++-v3/testsuite/30_threads/shared_future/members/get2.cc
index 3c593d8ce8b..62723ccc311 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_future/members/get2.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_future/members/get2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_future/members/valid.cc b/libstdc++-v3/testsuite/30_threads/shared_future/members/valid.cc
index 078073ee2c1..b65f17d9dec 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_future/members/valid.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_future/members/valid.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_future/members/wait.cc b/libstdc++-v3/testsuite/30_threads/shared_future/members/wait.cc
index 702b26f0a23..8484926df42 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_future/members/wait.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_future/members/wait.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_future/members/wait_for.cc b/libstdc++-v3/testsuite/30_threads/shared_future/members/wait_for.cc
index a3fae991d25..b4e23f64205 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_future/members/wait_for.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_future/members/wait_for.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_future/members/wait_until.cc b/libstdc++-v3/testsuite/30_threads/shared_future/members/wait_until.cc
index 37384e973b4..98af10c6a0b 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_future/members/wait_until.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_future/members/wait_until.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/cons/1.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/1.cc
index c271577cf3e..f727f5afd33 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_lock/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/cons/2.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/2.cc
index af01e0e661d..3ad7dc9536f 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_lock/cons/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/cons/3.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/3.cc
index 17023b410a7..2c89a3635f3 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_lock/cons/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/3.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/cons/4.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/4.cc
index db761e1f55d..ebbac5f4b03 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_lock/cons/4.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/4.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/cons/5.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/5.cc
index 712e68ca663..7abf1e4e485 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_lock/cons/5.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/5.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/cons/6.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/6.cc
index bb1f902acec..bfb6aa53330 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_lock/cons/6.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_lock/cons/6.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/locking/1.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/locking/1.cc
index ececeb0074a..aba161cfa64 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_lock/locking/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_lock/locking/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/locking/2.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/locking/2.cc
index 3f120ad4465..00fe5270dec 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_lock/locking/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_lock/locking/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/locking/3.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/locking/3.cc
index 2770a75ed16..87e99e87dd6 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_lock/locking/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_lock/locking/3.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/locking/4.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/locking/4.cc
index 8d11de9b035..868c815d4dc 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_lock/locking/4.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_lock/locking/4.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/modifiers/1.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/modifiers/1.cc
index 03abcc4c8d7..c941e10b51f 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_lock/modifiers/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_lock/modifiers/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/modifiers/2.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/modifiers/2.cc
index a5e3493738f..856b2fdf37f 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_lock/modifiers/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_lock/modifiers/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/cons/1.cc b/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/cons/1.cc
index b38cdbbcbca..ea9dbff9e60 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/cons/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock/1.cc b/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock/1.cc
index c13e05b57e1..d1fff0e7ff7 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock/2.cc b/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock/2.cc
index 28f833ba6f3..2390b2bfef6 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++1y -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++1y -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++1y " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/1.cc b/libstdc++-v3/testsuite/30_threads/this_thread/1.cc
index 8ea38b6a008..fabd21db1d4 100644
--- a/libstdc++-v3/testsuite/30_threads/this_thread/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/this_thread/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/2.cc b/libstdc++-v3/testsuite/30_threads/this_thread/2.cc
index 8f91094de67..d29cd15494c 100644
--- a/libstdc++-v3/testsuite/30_threads/this_thread/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/this_thread/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/3.cc b/libstdc++-v3/testsuite/30_threads/this_thread/3.cc
index 88406c5ac3e..678e85197b9 100644
--- a/libstdc++-v3/testsuite/30_threads/this_thread/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/this_thread/3.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/4.cc b/libstdc++-v3/testsuite/30_threads/this_thread/4.cc
index 1e585a69773..bd4b58f32ee 100644
--- a/libstdc++-v3/testsuite/30_threads/this_thread/4.cc
+++ b/libstdc++-v3/testsuite/30_threads/this_thread/4.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/1.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/1.cc
index 273b34c4ad8..df2aa22b47a 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/cons/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/2.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/2.cc
index 2c058fd6751..75e484c7a01 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/cons/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/cons/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/3.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/3.cc
index 266d7b9b8c1..092804c114d 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/cons/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/cons/3.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/4.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/4.cc
index ae97783fd5f..bf9b18dbe76 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/cons/4.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/cons/4.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/49668.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/49668.cc
index 0082259d445..c03027f8ba9 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/cons/49668.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/cons/49668.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/5.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/5.cc
index 20678b89f78..2a690592eb1 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/cons/5.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/cons/5.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/6.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/6.cc
index 736119ec987..a2ea5a8f0f7 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/cons/6.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/cons/6.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/7.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/7.cc
index 0857ec59ac5..36a261d8cd0 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/cons/7.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/cons/7.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/8.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/8.cc
index 4feb19f2834..9758bf0b03b 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/cons/8.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/cons/8.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/9.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/9.cc
index 9331509d4a3..cf03b920ba7 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/cons/9.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/cons/9.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/moveable.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/moveable.cc
index a0fca883062..42cc83544f1 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/cons/moveable.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/cons/moveable.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/members/1.cc b/libstdc++-v3/testsuite/30_threads/thread/members/1.cc
index 6f9d1b5a3fd..8892197715a 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/members/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/members/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/members/2.cc b/libstdc++-v3/testsuite/30_threads/thread/members/2.cc
index d7f9320fbf9..b6be5f1a71e 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/members/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/members/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/members/3.cc b/libstdc++-v3/testsuite/30_threads/thread/members/3.cc
index 01c4ea1723b..245ac2015f7 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/members/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/members/3.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/members/4.cc b/libstdc++-v3/testsuite/30_threads/thread/members/4.cc
index 23e4a8cc824..cdfab534929 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/members/4.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/members/4.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/members/5.cc b/libstdc++-v3/testsuite/30_threads/thread/members/5.cc
index dd141c41e64..4ed1742c11c 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/members/5.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/members/5.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/members/hardware_concurrency.cc b/libstdc++-v3/testsuite/30_threads/thread/members/hardware_concurrency.cc
index f7f8e3ffaa7..95829866ac2 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/members/hardware_concurrency.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/members/hardware_concurrency.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/native_handle/cancel.cc b/libstdc++-v3/testsuite/30_threads/thread/native_handle/cancel.cc
index d2fd5d859ee..6ebc2a9bf0e 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/native_handle/cancel.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/native_handle/cancel.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/thread/swap/1.cc b/libstdc++-v3/testsuite/30_threads/thread/swap/1.cc
index 271e0b9a3e8..f424a0ae848 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/swap/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/swap/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/1.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/1.cc
index 6576aafe47c..bf16e2984cc 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/dest/destructor_locked.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/dest/destructor_locked.cc
index f871a035df2..288c75a6170 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/dest/destructor_locked.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/dest/destructor_locked.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/lock/1.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/lock/1.cc
index d5c12bb5cd8..cf2fe18792d 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/lock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/1.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/1.cc
index 9475fcb7049..8de6e1e3553 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/typesizes.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/typesizes.cc
index dc771e56868..24f32339954 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/typesizes.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/typesizes.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/1.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/1.cc
index b14d8793ad4..712186f1163 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/2.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/2.cc
index 8ab64bbdb9c..5d43cc2209b 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/1.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/1.cc
index 48c55af82e1..ff822d7c542 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/2.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/2.cc
index 4a40b3c8855..6274352bc4b 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/3.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/3.cc
index 82951db24b8..97e70bfb01c 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/3.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/1.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/1.cc
index b14d8793ad4..712186f1163 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/2.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/2.cc
index 8ab64bbdb9c..5d43cc2209b 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/57641.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/57641.cc
index e51cf5fbad9..4042937c725 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/57641.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/57641.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/unlock/1.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/unlock/1.cc
index 6c2162ffd1a..11a251e478c 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/unlock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/unlock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/try_lock/1.cc b/libstdc++-v3/testsuite/30_threads/try_lock/1.cc
index 5a2648d7589..fe87da6df35 100644
--- a/libstdc++-v3/testsuite/30_threads/try_lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/try_lock/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/try_lock/2.cc b/libstdc++-v3/testsuite/30_threads/try_lock/2.cc
index bbf93e2e34b..5be10542dab 100644
--- a/libstdc++-v3/testsuite/30_threads/try_lock/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/try_lock/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/try_lock/3.cc b/libstdc++-v3/testsuite/30_threads/try_lock/3.cc
index e91f5638521..072353ab970 100644
--- a/libstdc++-v3/testsuite/30_threads/try_lock/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/try_lock/3.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/try_lock/4.cc b/libstdc++-v3/testsuite/30_threads/try_lock/4.cc
index de9b69eef9e..774179826b2 100644
--- a/libstdc++-v3/testsuite/30_threads/try_lock/4.cc
+++ b/libstdc++-v3/testsuite/30_threads/try_lock/4.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/1.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/1.cc
index ca2cad91d00..8c696f8c1e2 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/2.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/2.cc
index 4085803f9a3..c91ee0e7f79 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/3.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/3.cc
index de38838bb26..78898f672f7 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/3.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/4.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/4.cc
index f6a4ccaf286..5c1624b3286 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/4.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/4.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/5.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/5.cc
index 941f6529383..147d8f4c4d8 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/5.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/5.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/6.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/6.cc
index 8b94afd32f8..0ed6216719a 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/6.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/6.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/60497.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/60497.cc
new file mode 100644
index 00000000000..19be845fd94
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/60497.cc
@@ -0,0 +1,49 @@
+// { dg-do compile }
+// { dg-options " -std=gnu++11 " }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// libstdc++/60497
+
+#include <mutex>
+#include <memory>
+
+struct A;
+template<typename T> struct B { T t; };
+
+template<typename Dummy>
+struct Lockable
+{
+ void lock();
+ void unlock();
+ bool try_lock();
+};
+
+using test_type = Lockable<std::unique_ptr<B<A>>>;
+
+void test01()
+{
+ test_type l;
+ std::unique_lock<test_type> ul(l);
+}
+
+void test02()
+{
+ test_type l1, l2, l3;
+ std::lock(l1, l2, l3);
+}
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/locking/1.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/locking/1.cc
index efa1aac50bc..d31f8e36432 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/locking/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/locking/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/locking/2.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/locking/2.cc
index e0a302e0530..0c9be1be803 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/locking/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/locking/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/locking/3.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/locking/3.cc
index 01bc682c03f..e8792aa7b33 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/locking/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/locking/3.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/locking/4.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/locking/4.cc
index 192f3a82334..035b6649708 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/locking/4.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/locking/4.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/modifiers/1.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/modifiers/1.cc
index 0c5408f489b..10114ed85f9 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/modifiers/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/modifiers/1.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/modifiers/2.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/modifiers/2.cc
index 28a01b230fb..9e547546844 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/modifiers/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/modifiers/2.cc
@@ -1,5 +1,5 @@
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
-// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
diff --git a/libstdc++-v3/testsuite/experimental/string_view/cons/char/1.cc b/libstdc++-v3/testsuite/experimental/string_view/cons/char/1.cc
index c879cc7e00e..a443b0ac7e0 100644
--- a/libstdc++-v3/testsuite/experimental/string_view/cons/char/1.cc
+++ b/libstdc++-v3/testsuite/experimental/string_view/cons/char/1.cc
@@ -33,7 +33,7 @@ test01()
// basic_string_view()
const std::experimental::string_view str00{};
VERIFY( str00.length() == 0 );
- VERIFY( str00.data() != nullptr );
+ VERIFY( str00.data() == nullptr );
// basic_string_view(const char*)
const char str_lit01[] = "rodeo beach, marin";
@@ -54,11 +54,6 @@ test01()
VERIFY( str05.length() == len_lit01 );
VERIFY( str05.data() == str_lit01 );
- // basic_string_view(const char* s, std::size_t l)
- std::experimental::string_view str06{nullptr, len_lit01};
- VERIFY( str06.length() == 0 );
- VERIFY( str06.data() != nullptr );
-
// basic_string_view(basic_string& s)
std::string istr07(10, 'z');
std::experimental::string_view str07{istr07};
diff --git a/libstdc++-v3/testsuite/experimental/string_view/cons/wchar_t/1.cc b/libstdc++-v3/testsuite/experimental/string_view/cons/wchar_t/1.cc
index 12db72f2865..9ba9b84a180 100644
--- a/libstdc++-v3/testsuite/experimental/string_view/cons/wchar_t/1.cc
+++ b/libstdc++-v3/testsuite/experimental/string_view/cons/wchar_t/1.cc
@@ -33,7 +33,7 @@ test01()
// basic_string_view()
const std::experimental::wstring_view str00{};
VERIFY( str00.length() == 0 );
- VERIFY( str00.data() != nullptr );
+ VERIFY( str00.data() == nullptr );
// basic_string_view(const char*)
const wchar_t str_lit01[] = L"rodeo beach, marin";
@@ -54,11 +54,6 @@ test01()
VERIFY( str05.length() == len_lit01 );
VERIFY( str05.data() == str_lit01 );
- // basic_string_view(const wchar_t* s, std::size_t l)
- std::experimental::wstring_view str06{nullptr, len_lit01};
- VERIFY( str06.length() == 0 );
- VERIFY( str06.data() != nullptr );
-
// basic_string_view(basic_string& s)
std::wstring istr07(10, L'z');
std::experimental::wstring_view str07{istr07};
diff --git a/libstdc++-v3/testsuite/experimental/string_view/operations/copy/char/1.cc b/libstdc++-v3/testsuite/experimental/string_view/operations/copy/char/1.cc
index 25b2af133d3..d0f3e8d6901 100644
--- a/libstdc++-v3/testsuite/experimental/string_view/operations/copy/char/1.cc
+++ b/libstdc++-v3/testsuite/experimental/string_view/operations/copy/char/1.cc
@@ -1,6 +1,6 @@
// { dg-options "-std=gnu++1y" }
-// Copyright (C) 2013 Free Software Foundation, Inc.
+// Copyright (C) 2013-2014 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -20,7 +20,6 @@
// basic_string_view::copy
#include <experimental/string_view>
-#include <stdexcept>
#include <testsuite_hooks.h>
bool
diff --git a/libstdc++-v3/testsuite/experimental/string_view/operations/copy/wchar_t/1.cc b/libstdc++-v3/testsuite/experimental/string_view/operations/copy/wchar_t/1.cc
index 0348e1f98fc..bf3f14b14bd 100644
--- a/libstdc++-v3/testsuite/experimental/string_view/operations/copy/wchar_t/1.cc
+++ b/libstdc++-v3/testsuite/experimental/string_view/operations/copy/wchar_t/1.cc
@@ -1,6 +1,6 @@
// { dg-options "-std=gnu++1y" }
-// Copyright (C) 2013 Free Software Foundation, Inc.
+// Copyright (C) 2013-2014 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -20,7 +20,6 @@
// basic_string_view::copy
#include <experimental/string_view>
-#include <stdexcept>
#include <testsuite_hooks.h>
bool
diff --git a/libstdc++-v3/testsuite/experimental/string_view/operations/data/char/1.cc b/libstdc++-v3/testsuite/experimental/string_view/operations/data/char/1.cc
index be75de91791..a34492606ad 100644
--- a/libstdc++-v3/testsuite/experimental/string_view/operations/data/char/1.cc
+++ b/libstdc++-v3/testsuite/experimental/string_view/operations/data/char/1.cc
@@ -1,6 +1,6 @@
// { dg-options "-std=gnu++1y" }
-// Copyright (C) 2013 Free Software Foundation, Inc.
+// Copyright (C) 2013-2014 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -29,10 +29,9 @@ test01()
std::experimental::string_view empty;
- // data() for size == 0 is non-NULL.
VERIFY( empty.size() == 0 );
const std::experimental::string_view::value_type* p = empty.data();
- VERIFY( p );
+ VERIFY( p == nullptr );
return 0;
}
diff --git a/libstdc++-v3/testsuite/experimental/string_view/operations/data/wchar_t/1.cc b/libstdc++-v3/testsuite/experimental/string_view/operations/data/wchar_t/1.cc
index 5e00b00b601..41d2d1411d9 100644
--- a/libstdc++-v3/testsuite/experimental/string_view/operations/data/wchar_t/1.cc
+++ b/libstdc++-v3/testsuite/experimental/string_view/operations/data/wchar_t/1.cc
@@ -1,6 +1,6 @@
// { dg-options "-std=gnu++1y" }
-// Copyright (C) 2013 Free Software Foundation, Inc.
+// Copyright (C) 2013-2014 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -29,10 +29,9 @@ test01()
std::experimental::wstring_view empty;
- // data() for size == 0 is non-NULL.
VERIFY( empty.size() == 0 );
const std::experimental::wstring_view::value_type* p = empty.data();
- VERIFY( p );
+ VERIFY( p == nullptr );
return 0;
}
diff --git a/libstdc++-v3/testsuite/experimental/string_view/operations/to_string/1.cc b/libstdc++-v3/testsuite/experimental/string_view/operations/to_string/1.cc
new file mode 100644
index 00000000000..c0a5734c675
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/string_view/operations/to_string/1.cc
@@ -0,0 +1,53 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// basic_string_view::to_string
+
+#include <experimental/string_view>
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+bool
+test01()
+{
+ bool test [[gnu::unused]] = true;
+
+ const char str_lit[] = "123456789A";
+ const std::experimental::string_view sv(str_lit);
+ char buffer[4] = { 0 };
+
+ auto s1 = sv.to_string();
+ VERIFY( s1 == str_lit );
+ using test_alloc = __gnu_test::tracker_allocator<char>;
+ auto s2 = sv.to_string( test_alloc{} );
+ static_assert( std::is_same<decltype(s2)::allocator_type, test_alloc>::value,
+ "to_string() uses custom allocator" );
+ VERIFY( std::equal(s1.begin(), s1.end(), s2.begin(), s2.end()) );
+ auto s3 = static_cast<std::string>(sv);
+ VERIFY( s3 == s1 );
+
+ return test;
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/ext/rope/pthread7-rope.cc b/libstdc++-v3/testsuite/ext/rope/pthread7-rope.cc
index 94591750373..7ae8e492eb9 100644
--- a/libstdc++-v3/testsuite/ext/rope/pthread7-rope.cc
+++ b/libstdc++-v3/testsuite/ext/rope/pthread7-rope.cc
@@ -17,8 +17,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options "-pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options "-pthreads" { target *-*-solaris* } }
#include <ext/rope>
diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp
index 95954d8dbac..d91bed64719 100644
--- a/libstdc++-v3/testsuite/lib/libstdc++.exp
+++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
@@ -38,8 +38,10 @@
# ~/.dejagnurc or $DEJAGNU.
proc load_gcc_lib { filename } {
- global srcdir
+ global srcdir loaded_libs
+
load_file $srcdir/../../gcc/testsuite/lib/$filename
+ set loaded_libs($filename) ""
}
# system routines
@@ -280,6 +282,11 @@ proc libstdc++_init { testfile } {
}
append cxxflags " "
append cxxflags [getenv CXXFLAGS]
+
+ if ![regexp ".*-O" $cxxflags] {
+ append cxxflags " -g -O2"
+ }
+
v3track cxxflags 2
# Always use MO files built by this test harness.
diff --git a/libstdc++-v3/testsuite/libstdc++-abi/abi.exp b/libstdc++-v3/testsuite/libstdc++-abi/abi.exp
index 9b381d8578e..0d657fbdecb 100644
--- a/libstdc++-v3/testsuite/libstdc++-abi/abi.exp
+++ b/libstdc++-v3/testsuite/libstdc++-abi/abi.exp
@@ -24,8 +24,6 @@ if { [string match "*-*-darwin*" $target_triplet] } {
set lib $blddir/src/.libs/libstdc++.so
}
-set baseline_subdir "[eval exec $cxx $baseline_subdir_switch]"
-
# Build the support objects.
v3-build_support
@@ -35,6 +33,8 @@ if { (${v3-symver} == 0) || ![info exists baseline_dir] \
return
}
+set baseline_subdir "[eval exec $cxx $baseline_subdir_switch]"
+
set baseline_file \
[file join $baseline_dir $baseline_subdir "baseline_symbols.txt"]
# If there is no ABI-specific reference file use that of the default ABI.
diff --git a/libstdc++-v3/testsuite/performance/28_regex/range.cc b/libstdc++-v3/testsuite/performance/28_regex/range.cc
new file mode 100644
index 00000000000..891cc2e2621
--- /dev/null
+++ b/libstdc++-v3/testsuite/performance/28_regex/range.cc
@@ -0,0 +1,41 @@
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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 this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <regex>
+#include <testsuite_performance.h>
+
+using namespace __gnu_test;
+
+int main()
+{
+ time_counter time;
+ resource_counter resource;
+
+ start_counters(time, resource);
+
+ // this should get compiled to just L"[abcd]"
+ auto re = std::wregex(L'[' + std::wstring(300, L'a') + L"bc"
+ + std::wstring(1000, 'a') + L"d]");
+ bool ok = true;
+ for (int i = 0; i < 100000; ++i)
+ ok = ok && (std::regex_match(L"b", re) && std::regex_match(L"d", re));
+
+ stop_counters(time, resource);
+ report_performance(__FILE__, "", time, resource);
+
+ return ok ? 0 : 1;
+}
diff --git a/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/assign/auto_ptr_rvalue_neg.cc b/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/assign/auto_ptr_rvalue_neg.cc
index 662a985ea79..defafb3778d 100644
--- a/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/assign/auto_ptr_rvalue_neg.cc
+++ b/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/assign/auto_ptr_rvalue_neg.cc
@@ -34,7 +34,7 @@ test01()
bool test __attribute__((unused)) = true;
std::tr1::shared_ptr<A> a;
- a = source(); // { dg-error "no match" }
+ a = source(); // { dg-error "" }
return 0;
}
diff --git a/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/modifiers/reset_neg.cc b/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/modifiers/reset_neg.cc
index b3c5914f36b..dd52a70d526 100644
--- a/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/modifiers/reset_neg.cc
+++ b/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/modifiers/reset_neg.cc
@@ -33,7 +33,7 @@ test01()
bool test __attribute__((unused)) = true;
const std::tr1::shared_ptr<A> p1(new A);
- p1.reset(); // { dg-error "discards qualifiers" }
+ p1.reset(); // { dg-error "no match" }
return 0;
}
diff --git a/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/thread/default_weaktoshared.cc b/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/thread/default_weaktoshared.cc
index 75dedb8d34e..8b2bab59ee7 100644
--- a/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/thread/default_weaktoshared.cc
+++ b/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/thread/default_weaktoshared.cc
@@ -17,8 +17,8 @@
// TR1 2.2.2 Template class shared_ptr [tr.util.smartptr.shared]
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options "-pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options "-pthreads" { target *-*-solaris* } }
#include <tr1/memory>
diff --git a/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/thread/mutex_weaktoshared.cc b/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/thread/mutex_weaktoshared.cc
index 9e83894f0c6..ac5f41d33b4 100644
--- a/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/thread/mutex_weaktoshared.cc
+++ b/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/thread/mutex_weaktoshared.cc
@@ -17,8 +17,8 @@
// TR1 2.2.2 Template class shared_ptr [tr.util.smartptr.shared]
-// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
-// { dg-options "-pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* } }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } }
+// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } }
// { dg-options "-pthreads" { target *-*-solaris* } }
#include <tr1/memory>
diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc
index 39635cb2fca..06991144dc1 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc
@@ -200,6 +200,7 @@ check_version(symbol& test, bool added)
known_versions.push_back("GLIBCXX_3.4.18");
known_versions.push_back("GLIBCXX_3.4.19");
known_versions.push_back("GLIBCXX_3.4.20");
+ known_versions.push_back("GLIBCXX_3.4.21");
known_versions.push_back("CXXABI_1.3");
known_versions.push_back("CXXABI_LDBL_1.3");
known_versions.push_back("CXXABI_1.3.1");
@@ -227,7 +228,7 @@ check_version(symbol& test, bool added)
test.version_status = symbol::incompatible;
// Check that added symbols are added in the latest pre-release version.
- bool latestp = (test.version_name == "GLIBCXX_3.4.20"
+ bool latestp = (test.version_name == "GLIBCXX_3.4.21"
|| test.version_name == "CXXABI_1.3.9"
|| test.version_name == "CXXABI_TM_1");
if (added && !latestp)
diff --git a/lto-plugin/ChangeLog b/lto-plugin/ChangeLog
index 75a1f8f6076..332067ea48e 100644
--- a/lto-plugin/ChangeLog
+++ b/lto-plugin/ChangeLog
@@ -1,3 +1,9 @@
+2014-05-15 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR lto/60981
+ * configure.ac: Check for -static-libgcc.
+ * configure: Regenerate.
+
2014-04-17 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/56781
diff --git a/lto-plugin/configure b/lto-plugin/configure
index 2fc838329c7..a579b99f404 100755
--- a/lto-plugin/configure
+++ b/lto-plugin/configure
@@ -4087,8 +4087,32 @@ fi
done
CFLAGS="$save_CFLAGS"
+
+# Check whether -static-libgcc is supported.
+saved_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS -static-libgcc"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -static-libgcc" >&5
+$as_echo_n "checking for -static-libgcc... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ int main() {}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ have_static_libgcc=yes
+else
+ have_static_libgcc=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_static_libgcc" >&5
+$as_echo "$have_static_libgcc" >&6; };
+LDFLAGS="$saved_LDFLAGS"
# Need -Wc to get it through libtool.
-if test "x$GCC" = xyes; then ac_lto_plugin_ldflags="-Wc,-static-libgcc"; fi
+if test "x$have_static_libgcc" = xyes; then
+ ac_lto_plugin_ldflags="-Wc,-static-libgcc"
+fi
+
case `pwd` in
*\ * | *\ *)
@@ -10562,7 +10586,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10565 "configure"
+#line 10589 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10668,7 +10692,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10671 "configure"
+#line 10695 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
diff --git a/lto-plugin/configure.ac b/lto-plugin/configure.ac
index 4003ae61bdc..a5f1774dff4 100644
--- a/lto-plugin/configure.ac
+++ b/lto-plugin/configure.ac
@@ -7,9 +7,21 @@ AM_MAINTAINER_MODE
AC_PROG_CC
AC_SYS_LARGEFILE
ACX_PROG_CC_WARNING_OPTS([-Wall], [ac_lto_plugin_warn_cflags])
+
+# Check whether -static-libgcc is supported.
+saved_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS -static-libgcc"
+AC_MSG_CHECKING([for -static-libgcc])
+AC_LINK_IFELSE([
+ int main() {}], [have_static_libgcc=yes], [have_static_libgcc=no])
+AC_MSG_RESULT($have_static_libgcc);
+LDFLAGS="$saved_LDFLAGS"
# Need -Wc to get it through libtool.
-if test "x$GCC" = xyes; then ac_lto_plugin_ldflags="-Wc,-static-libgcc"; fi
+if test "x$have_static_libgcc" = xyes; then
+ ac_lto_plugin_ldflags="-Wc,-static-libgcc"
+fi
AC_SUBST(ac_lto_plugin_ldflags)
+
AM_PROG_LIBTOOL
ACX_LT_HOST_FLAGS
AC_SUBST(target_noncanonical)
diff --git a/maintainer-scripts/ChangeLog b/maintainer-scripts/ChangeLog
index a60e93b709b..7205523caa5 100644
--- a/maintainer-scripts/ChangeLog
+++ b/maintainer-scripts/ChangeLog
@@ -1,3 +1,7 @@
+2014-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * generate_libstdcxx_web_docs: New script.
+
2014-04-11 Jakub Jelinek <jakub@redhat.com>
* crontab: Enable snapshots from gcc-4_9-branch.
diff --git a/maintainer-scripts/generate_libstdcxx_web_docs b/maintainer-scripts/generate_libstdcxx_web_docs
new file mode 100644
index 00000000000..700e522e25c
--- /dev/null
+++ b/maintainer-scripts/generate_libstdcxx_web_docs
@@ -0,0 +1,56 @@
+#!/bin/bash
+# Generate the libstdc++ onlinedocs for a GCC release
+# i.e. http://gcc.gnu.org/onlinedocs/gcc-x.y.z/libstdc++*
+
+SRCDIR=${1}
+DOCSDIR=${2}
+
+if ! [ $# -eq 2 -a -x "${SRCDIR}/configure" -a -d "${DOCSDIR}" ]
+then
+ echo "Usage: $0 <gcc src dir> <doc output dir>" >&2
+ exit 1
+fi
+
+set -e
+
+# Check we have some of the required tools
+for i in doxygen dot dblatex pdflatex makeindex
+do
+ echo -n "Checking for $i... "
+ which $i
+done
+
+start=$PWD
+WORKDIR=`mktemp -d $PWD/build.XXXXXX`
+DESTDIR=`mktemp -d $PWD/dest.XXXXXX`
+cd $WORKDIR
+disabled_libs=
+for dir in ${SRCDIR}/lib*
+do
+ dir="${dir##*/}"
+ [ $dir == 'libstdc++-v3' ] || disabled_libs="$disabled_libs --disable-$dir"
+done
+set -x
+${SRCDIR}/configure --enable-languages=c,c++ --disable-gcc $disabled_libs --docdir=/docs
+eval `grep '^target=' config.log`
+make configure-target
+make -C $target/libstdc++-v3 doc-install-html doc-install-xml doc-install-pdf DESTDIR=$DESTDIR
+cd $DESTDIR/docs
+mkdir libstdc++
+for which in api manual
+do
+ if [ -f libstdc++-$which-single.xml ] # Only needed for GCC 4.7.x
+ then
+ mv libstdc++-$which-single.xml libstdc++-$which.xml
+ fi
+ gzip --best libstdc++-$which.xml
+ gzip --best libstdc++-$which.pdf
+ mv libstdc++-$which{.html,-html}
+ tar czf libstdc++-$which-html.tar.gz libstdc++-$which-html
+ mv libstdc++-$which-html libstdc++/$which
+done
+mv *.gz libstdc++ $DOCSDIR/
+cd $start
+rm -r $WORKDIR
+rm -r $DESTDIR
+