aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>2019-10-08 07:16:20 +0000
committeraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>2019-10-08 07:16:20 +0000
commita7e9778fa31d278344041579c27cbbeb6365f777 (patch)
tree24ae9f7f7cca0794b54fdcc58088dce8cb05ac5e
parent19ba44e43008541aa17f43d9f5970449bbd505e5 (diff)
parent07603136be4090e44c89c0000b7a4620b0604614 (diff)
Merge branch 'trunk-at-merge' into merge
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/ranger@276687 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog691
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog4
-rw-r--r--gcc/ada/gcc-interface/utils.c1
-rw-r--r--gcc/brig/ChangeLog4
-rw-r--r--gcc/brig/brig-lang.c1
-rw-r--r--gcc/builtins.c29
-rw-r--r--gcc/builtins.def43
-rw-r--r--gcc/c-family/ChangeLog22
-rw-r--r--gcc/c-family/c-cppbuiltin.c1
-rw-r--r--gcc/c-family/c-format.c16
-rw-r--r--gcc/c-family/c-format.h2
-rw-r--r--gcc/c-family/c-opts.c6
-rw-r--r--gcc/cgraph.c50
-rw-r--r--gcc/cgraph.h18
-rw-r--r--gcc/cgraphclones.c6
-rw-r--r--gcc/cif-code.def4
-rw-r--r--gcc/config.in6
-rw-r--r--gcc/config/arc/arc.h3
-rw-r--r--gcc/config/arm/arm.c7
-rw-r--r--gcc/config/darwin-driver.c44
-rw-r--r--gcc/config/darwin.c72
-rw-r--r--gcc/config/darwin.h31
-rw-r--r--gcc/config/h8300/h8300.md14
-rw-r--r--gcc/config/i386/darwin.h6
-rw-r--r--gcc/config/i386/i386-expand.c220
-rw-r--r--gcc/config/i386/i386-features.c63
-rw-r--r--gcc/config/i386/i386-protos.h6
-rw-r--r--gcc/config/i386/predicates.md5
-rw-r--r--gcc/config/i386/sse.md13
-rw-r--r--gcc/config/mips/mips.c2
-rw-r--r--gcc/config/msp430/constraints.md10
-rw-r--r--gcc/config/msp430/driver-msp430.c13
-rw-r--r--gcc/config/msp430/msp430-protos.h2
-rw-r--r--gcc/config/msp430/msp430.c243
-rw-r--r--gcc/config/msp430/msp430.h13
-rw-r--r--gcc/config/msp430/msp430.md262
-rw-r--r--gcc/config/msp430/msp430.opt12
-rw-r--r--gcc/config/msp430/predicates.md10
-rw-r--r--gcc/config/msp430/t-msp43011
-rw-r--r--gcc/config/pa/pa.c30
-rw-r--r--gcc/config/pa/pa.h13
-rw-r--r--gcc/config/rs6000/darwin.h3
-rw-r--r--gcc/config/rs6000/rs6000-protos.h2
-rw-r--r--gcc/config/rs6000/rs6000-string.c51
-rw-r--r--gcc/config/rs6000/rs6000.c12
-rw-r--r--gcc/config/rs6000/rs6000.md24
-rwxr-xr-xgcc/configure74
-rw-r--r--gcc/configure.ac14
-rw-r--r--gcc/coretypes.h3
-rw-r--r--gcc/cp/ChangeLog148
-rw-r--r--gcc/cp/call.c3
-rw-r--r--gcc/cp/class.c44
-rw-r--r--gcc/cp/constexpr.c618
-rw-r--r--gcc/cp/cp-gimplify.c15
-rw-r--r--gcc/cp/cp-objcp-common.c6
-rw-r--r--gcc/cp/cp-tree.h9
-rw-r--r--gcc/cp/decl.c67
-rw-r--r--gcc/cp/decl2.c3
-rw-r--r--gcc/cp/init.c112
-rw-r--r--gcc/cp/method.c69
-rw-r--r--gcc/cp/name-lookup.c14
-rw-r--r--gcc/cp/parser.c28
-rw-r--r--gcc/cp/pt.c27
-rw-r--r--gcc/cp/typeck2.c15
-rw-r--r--gcc/doc/extend.texi25
-rw-r--r--gcc/doc/invoke.texi91
-rw-r--r--gcc/expr.c146
-rw-r--r--gcc/expr.h3
-rw-r--r--gcc/fortran/ChangeLog156
-rw-r--r--gcc/fortran/array.c2
-rw-r--r--gcc/fortran/check.c10
-rw-r--r--gcc/fortran/decl.c64
-rw-r--r--gcc/fortran/dump-parse-tree.c1
-rw-r--r--gcc/fortran/error.c11
-rw-r--r--gcc/fortran/expr.c8
-rw-r--r--gcc/fortran/f95-lang.c2
-rw-r--r--gcc/fortran/gfortran.h3
-rw-r--r--gcc/fortran/interface.c11
-rw-r--r--gcc/fortran/intrinsic.c27
-rw-r--r--gcc/fortran/io.c48
-rw-r--r--gcc/fortran/match.c10
-rw-r--r--gcc/fortran/misc.c71
-rw-r--r--gcc/fortran/module.c6
-rw-r--r--gcc/fortran/openmp.c32
-rw-r--r--gcc/fortran/parse.c16
-rw-r--r--gcc/fortran/primary.c27
-rw-r--r--gcc/fortran/resolve.c47
-rw-r--r--gcc/fortran/simplify.c51
-rw-r--r--gcc/fortran/trans-decl.c11
-rw-r--r--gcc/fortran/trans-expr.c48
-rw-r--r--gcc/fortran/trans-openmp.c14
-rw-r--r--gcc/fortran/trans.h4
-rw-r--r--gcc/generic-match-head.c1
-rw-r--r--gcc/genmatch.c299
-rw-r--r--gcc/gimple-expr.c25
-rw-r--r--gcc/gimple-expr.h1
-rw-r--r--gcc/gimple-iterator.h31
-rw-r--r--gcc/gimple-ssa-store-merging.c356
-rw-r--r--gcc/gimple.c14
-rw-r--r--gcc/gimplify.c5
-rw-r--r--gcc/ginclude/stdint-gcc.h5
-rw-r--r--gcc/glimits.h5
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/ast-dump.cc8
-rw-r--r--gcc/go/gofrontend/escape.cc1
-rw-r--r--gcc/go/gofrontend/export.cc12
-rw-r--r--gcc/go/gofrontend/expressions.cc67
-rw-r--r--gcc/go/gofrontend/expressions.h5
-rw-r--r--gcc/go/gofrontend/gogo.cc28
-rw-r--r--gcc/go/gofrontend/parse.cc26
-rw-r--r--gcc/go/gofrontend/statements.cc17
-rw-r--r--gcc/go/gofrontend/types.cc40
-rw-r--r--gcc/hash-map.h47
-rw-r--r--gcc/hash-table.c2
-rw-r--r--gcc/hash-table.h8
-rw-r--r--gcc/ifcvt.c17
-rw-r--r--gcc/ifcvt.h4
-rw-r--r--gcc/ipa-cp.c1
-rw-r--r--gcc/ipa-devirt.c4
-rw-r--r--gcc/ipa-icf.c11
-rw-r--r--gcc/ipa-inline.c154
-rw-r--r--gcc/ipa-prop.c29
-rw-r--r--gcc/ipa-prop.h2
-rw-r--r--gcc/ira-color.c1
-rw-r--r--gcc/ira-lives.c86
-rw-r--r--gcc/langhooks-def.h2
-rw-r--r--gcc/langhooks.h3
-rw-r--r--gcc/lra-lives.c6
-rw-r--r--gcc/lto/ChangeLog4
-rw-r--r--gcc/lto/lto-lang.c1
-rw-r--r--gcc/machmode.h87
-rw-r--r--gcc/match.pd150
-rw-r--r--gcc/omp-general.c8
-rw-r--r--gcc/omp-general.h1
-rw-r--r--gcc/omp-low.c5
-rw-r--r--gcc/optabs-tree.c39
-rw-r--r--gcc/optabs.c19
-rw-r--r--gcc/optabs.h6
-rw-r--r--gcc/opts.c4
-rw-r--r--gcc/params.def31
-rw-r--r--gcc/range-op.cc79
-rw-r--r--gcc/reginfo.c4
-rw-r--r--gcc/testsuite/ChangeLog326
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array20.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array21.C27
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-delete2.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-67.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/locations1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-array7.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-new.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/constexpr-array1.C46
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/eval-order5.C31
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-dtor1.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-dtor2.C66
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C185
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-new1.C39
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-new2.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C73
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-new4.C29
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C32
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/integral-array-size-1.C7
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/not-a-function-template-1.C9
-rw-r--r--gcc/testsuite/g++.dg/ext/constexpr-attr-cleanup1.C30
-rw-r--r--gcc/testsuite/g++.dg/ext/is_literal_type3.C26
-rw-r--r--gcc/testsuite/g++.dg/init/new43.C178
-rw-r--r--gcc/testsuite/g++.dg/lookup/friend12.C2
-rw-r--r--gcc/testsuite/g++.dg/lookup/pr79766.C2
-rw-r--r--gcc/testsuite/g++.dg/lookup/pr84375.C2
-rw-r--r--gcc/testsuite/g++.dg/other/new-size-type.C2
-rw-r--r--gcc/testsuite/g++.dg/template/crash107.C4
-rw-r--r--gcc/testsuite/g++.dg/template/dependent-expr1.C8
-rw-r--r--gcc/testsuite/g++.dg/template/error17.C2
-rw-r--r--gcc/testsuite/g++.dg/torture/pr91606.C109
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/ivopts-3.C6
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr53844.C2
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr61034.C2
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp2
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/loop-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/Warray-bounds-18.c2
-rw-r--r--gcc/testsuite/gcc.dg/Wnonnull-2.c55
-rw-r--r--gcc/testsuite/gcc.dg/Wnonnull-3.c71
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-17.c20
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-18.c239
-rw-r--r--gcc/testsuite/gcc.dg/c11-builtins-1.c19
-rw-r--r--gcc/testsuite/gcc.dg/c2x-builtins-1.c13
-rw-r--r--gcc/testsuite/gcc.dg/cr-decimal-dig-2.c10
-rw-r--r--gcc/testsuite/gcc.dg/dfp/c2x-builtins-dfp-1.c11
-rw-r--r--gcc/testsuite/gcc.dg/format/c2x-strftime-1.c15
-rw-r--r--gcc/testsuite/gcc.dg/ipa/inline-7.c2
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-sra-19.c1
-rw-r--r--gcc/testsuite/gcc.dg/limits-width-2.c54
-rw-r--r--gcc/testsuite/gcc.dg/nonnull-3.c10
-rw-r--r--gcc/testsuite/gcc.dg/optimize-bswapsi-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr87047.c19
-rw-r--r--gcc/testsuite/gcc.dg/pr91734.c97
-rw-r--r--gcc/testsuite/gcc.dg/sinhovercosh-1.c45
-rw-r--r--gcc/testsuite/gcc.dg/stdint-width-2.c175
-rw-r--r--gcc/testsuite/gcc.dg/torture/builtin-fp-int-inexact-c2x.c7
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/cunroll-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-vfa-vect-101.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-vfa-vect-102.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr79920.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr83202-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-105.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-93.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-bswap16.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-bswap16a.c5
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-double-reduc-6.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-profile-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/winline-3.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/shracc_1.c6
-rw-r--r--gcc/testsuite/gcc.target/aarch64/torture/simd-abi-8.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr71801.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr91994.c35
-rw-r--r--gcc/testsuite/gcc.target/mips/call-clobbered-3.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/call-clobbered-4.c23
-rw-r--r--gcc/testsuite/gcc.target/mips/pr91769.c19
-rw-r--r--gcc/testsuite/gcc.target/msp430/430x-insns.c1646
-rw-r--r--gcc/testsuite/gcc.target/msp430/data-attributes-2.c4
-rw-r--r--gcc/testsuite/gcc.target/msp430/msp430.exp8
-rw-r--r--gcc/testsuite/gcc.target/msp430/object-attributes-430.c14
-rw-r--r--gcc/testsuite/gcc.target/msp430/object-attributes-default.c16
-rw-r--r--gcc/testsuite/gcc.target/msp430/object-attributes-mlarge-any-region.c14
-rw-r--r--gcc/testsuite/gcc.target/msp430/object-attributes-mlarge.c15
-rw-r--r--gcc/testsuite/gfortran.dg/ISO_Fortran_binding_13.c12
-rw-r--r--gcc/testsuite/gfortran.dg/ISO_Fortran_binding_13.f9039
-rw-r--r--gcc/testsuite/gfortran.dg/ISO_Fortran_binding_14.f9041
-rw-r--r--gcc/testsuite/gfortran.dg/auto_in_equiv_1.f9053
-rw-r--r--gcc/testsuite/gfortran.dg/auto_in_equiv_2.f9046
-rw-r--r--gcc/testsuite/gfortran.dg/auto_in_equiv_3.f9063
-rw-r--r--gcc/testsuite/gfortran.dg/bad_operands.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/character_mismatch.f9076
-rw-r--r--gcc/testsuite/gfortran.dg/compare_interfaces.f9073
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/asyncwait-1.f9512
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/asyncwait-2.f954
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/asyncwait-3.f954
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/asyncwait-4.f9520
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/default-2.f44
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/enter-exit-data.f954
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/if.f9514
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/list.f956
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/literal.f952
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/loop-2-kernels-tile.f954
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/loop-2-parallel-tile.f954
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/loop-7.f9520
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/parallel-kernels-clauses.f9528
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/routine-6.f902
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/several-directives.f954
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/sie.f9512
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/tile-1.f908
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/update-if_present-2.f9016
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-simd-1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/is_device_ptr-1.f9027
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/pr29759.f908
-rw-r--r--gcc/testsuite/gfortran.dg/hollerith_to_char_parameter_1.f9011
-rw-r--r--gcc/testsuite/gfortran.dg/hollerith_to_char_parameter_2.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/pr47054_1.f9015
-rw-r--r--gcc/testsuite/gfortran.dg/pr47054_2.f9041
-rw-r--r--gcc/testsuite/gfortran.dg/pr91497.f90127
-rw-r--r--gcc/testsuite/gfortran.dg/pr91587.f906
-rw-r--r--gcc/testsuite/gfortran.dg/pr91784.f909
-rw-r--r--gcc/testsuite/gfortran.dg/pr91785.f908
-rw-r--r--gcc/testsuite/gfortran.dg/pr91942.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/pr91943.f907
-rw-r--r--gcc/testsuite/gfortran.dg/pr91959.f909
-rw-r--r--gcc/testsuite/gfortran.dg/typebound_call_22.f032
-rw-r--r--gcc/testsuite/gfortran.dg/use_without_only_1.f906
-rw-r--r--gcc/testsuite/gfortran.dg/vect/vect-8.f902
-rw-r--r--gcc/testsuite/gfortran.dg/widechar_intrinsics_1.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/widechar_intrinsics_2.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/widechar_intrinsics_3.f904
-rw-r--r--gcc/testsuite/gnat.dg/opt82.adb14
-rw-r--r--gcc/testsuite/gnat.dg/opt82_pkg.ads10
-rw-r--r--gcc/tree-eh.c42
-rw-r--r--gcc/tree-eh.h1
-rw-r--r--gcc/tree-if-conv.c24
-rw-r--r--gcc/tree-object-size.c33
-rw-r--r--gcc/tree-object-size.h3
-rw-r--r--gcc/tree-ssa-dse.c22
-rw-r--r--gcc/tree-ssa-dse.h36
-rw-r--r--gcc/tree-ssa-forwprop.c13
-rw-r--r--gcc/tree-ssa-loop-ivcanon.c5
-rw-r--r--gcc/tree-ssa-strlen.c75
-rw-r--r--gcc/tree-vect-loop.c679
-rw-r--r--gcc/tree-vect-patterns.c148
-rw-r--r--gcc/tree-vect-stmts.c12
-rw-r--r--gcc/tree-vectorizer.h5
-rw-r--r--gcc/tree-vrp.c269
-rw-r--r--gcc/tree-vrp.h1
-rw-r--r--gcc/tree.c5
-rw-r--r--gcc/var-tracking.c5
-rw-r--r--libcpp/ChangeLog10
-rw-r--r--libcpp/internal.h2
-rw-r--r--libcpp/line-map.c8
-rw-r--r--libgcc/ChangeLog4
-rw-r--r--libgcc/config/pa/fptr.c5
-rw-r--r--libgfortran/ChangeLog8
-rw-r--r--libgfortran/runtime/ISO_Fortran_binding.c3
-rw-r--r--libgo/runtime/go-context.S4
-rw-r--r--libgomp/ChangeLog15
-rw-r--r--libgomp/libgomp.h5
-rw-r--r--libgomp/target.c44
-rw-r--r--libgomp/testsuite/libgomp.fortran/use_device_ptr-optional-1.f9036
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-default.h7
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-dim-default.c7
-rw-r--r--libiberty/ChangeLog8
-rw-r--r--libiberty/rust-demangle.c64
-rw-r--r--libiberty/testsuite/rust-demangle-expected2
-rw-r--r--libstdc++-v3/ChangeLog83
-rw-r--r--libstdc++-v3/config.h.in11
-rw-r--r--libstdc++-v3/config/abi/pre/gnu.ver3
-rwxr-xr-xlibstdc++-v3/configure223
-rw-r--r--libstdc++-v3/configure.ac2
-rw-r--r--libstdc++-v3/doc/html/manual/parallel_mode.html20
-rw-r--r--libstdc++-v3/doc/xml/manual/parallel_mode.xml18
-rw-r--r--libstdc++-v3/include/Makefile.am23
-rw-r--r--libstdc++-v3/include/Makefile.in23
-rw-r--r--libstdc++-v3/include/bits/stl_algo.h23
-rw-r--r--libstdc++-v3/include/bits/stl_iterator_base_types.h11
-rw-r--r--libstdc++-v3/include/bits/streambuf_iterator.h26
-rw-r--r--libstdc++-v3/include/debug/forward_list2
-rw-r--r--libstdc++-v3/include/debug/helper_functions.h10
-rw-r--r--libstdc++-v3/include/debug/list2
-rw-r--r--libstdc++-v3/include/debug/safe_iterator.tcc46
-rw-r--r--libstdc++-v3/include/parallel/multiway_merge.h4
-rw-r--r--libstdc++-v3/include/precompiled/stdc++.h2
-rw-r--r--libstdc++-v3/include/std/numeric3
-rw-r--r--libstdc++-v3/include/tr1/hashtable.h9
-rw-r--r--libstdc++-v3/src/c++17/fs_dir.cc1
-rw-r--r--libstdc++-v3/src/c++17/fs_ops.cc3
-rw-r--r--libstdc++-v3/src/filesystem/dir.cc1
-rw-r--r--libstdc++-v3/src/filesystem/ops.cc3
-rw-r--r--libstdc++-v3/testsuite/17_intro/names.cc3
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/copy_n/debug/1_neg.cc38
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/copy_n/debug/2_neg.cc38
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/1.cc73
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/1_neg.cc40
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2_neg.cc38
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_abi.h4
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_allocator.h11
343 files changed, 10902 insertions, 2585 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8843b4ccf41..23e0a259e0c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,481 @@
-2019-09-25 Aldy Hernandez <aldyh@redhat.com>
+2019-10-08 Joseph Myers <joseph@codesourcery.com>
+
+ * doc/invoke.texi (-ffp-int-builtin-inexact): Document
+ -fno-fp-int-builtin-inexact default for C2X.
+
+2019-10-07 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+ Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/91532
+ * tree-if-conv.c: Include tree-ssa-dse.h.
+ (ifcvt_local_dce): Change param from bb to loop,
+ and call dse_classify_store.
+ (tree_if_conversion): Pass loop instead of loop->header as arg
+ to ifcvt_local_dce.
+ * tree-ssa-dse.c: Include tree-ssa-dse.h.
+ (delete_dead_or_redundant_assignment): Remove static qualifier from
+ declaration, and add prototype in tree-ssa-dse.h.
+ (dse_store_status): Move to tree-ssa-dse.h.
+ (dse_classify_store): Remove static qualifier and add new tree param
+ stop_at_vuse, and add prototype in tree-ssa-dse.h.
+ * tree-ssa-dse.h: New header.
+
+2019-10-07 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.c (machopic_output_indirection): Don't put
+ hidden symbol indirections into the .data section, use the
+ non-lazy symbol pointers section as normal.
+ (darwin_encode_section_info): Record if a symbol is hidden.
+ * config/darwin.h (MACHO_SYMBOL_FLAG_HIDDEN_VIS): New.
+ (MACHO_SYMBOL_HIDDEN_VIS_P): New.
+
+2019-10-07 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.c (machopic_symbol_defined_p): Use symbol flag
+ predicates instead of accessing bits directly.
+ (machopic_indirect_call_target): Likewise.
+ (machopic_output_indirection): Likewise.
+ (darwin_encode_section_info): Improve description. Use renamed
+ symbol flags. Use predicate macros for variables and functions.
+ * config/darwin.h:
+ Rename MACHO_SYMBOL_VARIABLE to MACHO_SYMBOL_FLAG_VARIABLE.
+ Rename MACHO_SYMBOL_DEFINED to MACHO_SYMBOL_FLAG_DEFINED.
+ Rename MACHO_SYMBOL_STATIC to MACHO_SYMBOL_FLAG_STATIC.
+ (MACHO_SYMBOL_VARIABLE_P): New.
+ (MACHO_SYMBOL_DEFINED_P):New.
+ (MACHO_SYMBOL_STATIC_P): New.
+ * config/i386/darwin.h (MACHO_SYMBOL_FLAG_VARIABLE): Delete.
+ (SYMBOL_FLAG_SUBT_DEP): New.
+ * config/rs6000/darwin.h (SYMBOL_FLAG_SUBT_DEP): New.
+
+2019-10-07 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/msp430/msp430.c (msp430_file_end): s/msp_/msp430_/
+ (msp430_expand_epilogue): Likewise.
+ * config/msp430/predicates.md: Likewise.
+ * config/msp430/msp430.md: Likewise.
+ Replace blocks of 8 spaces with tabs.
+
+2019-10-07 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/msp430/msp430-protos.h (msp430_split_addsi): New prototype.
+ * config/msp430/msp430.c (msp430_split_addsi): New.
+ * config/msp430/msp430.md: Call msp430_split_addsi () instead of using
+ a block of C code for splitting addsi.
+
+2019-10-07 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386-expand.c (ix86_expand_floorceildf_32,
+ ix86_expand_rounddf_32): Reorder functions.
+ * config/i386/i386-protos.h: Update..
+
+2019-10-07 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config.in: Regenerate.
+ * config/msp430/constraints.md: Fix docstring for "Ys" constraint.
+ Add new "Yx" constraint.
+ * config/msp430/driver-msp430.c (msp430_propagate_region_opt): New spec
+ function.
+ * config/msp430/msp430-protos.h (msp430_op_not_in_high_mem): New
+ prototype.
+ * config/msp430/msp430.c (msp430_option_override): Allow the lower
+ code/data region to be selected in the small memory model.
+ (msp430_section_attr): Don't warn if the "section" and "lower"
+ attributes are used together.
+ (msp430_handle_generic_attribute): Likewise.
+ (msp430_var_in_low_mem): New function.
+ (TARGET_ENCODE_SECTION_INFO): Define.
+ (msp430_encode_section_info): New function.
+ (gen_prefix): Return early in the small memory model.
+ Require TARGET_USE_LOWER_REGION_PREFIX to be set before adding the
+ ".lower" prefix if -m{code,data}-region=lower have been passed.
+ (msp430_output_aligned_decl_common): Emit common symbols when
+ -mdata-region=lower is passed unless TARGET_USE_LOWER_REGION_PREFIX is
+ set.
+ (TARGET_ASM_FILE_END): Define.
+ (msp430_file_end): New function.
+ (msp430_do_not_relax_short_jumps): Allow relaxation when
+ function will be in the lower region.
+ (msp430_op_not_in_high_mem): New function.
+ (msp430_print_operand): Check "msp430_op_not_in_high_mem" for
+ the 'X' operand selector.
+ Clarify comment for 'x' operand selector.
+ * config/msp430/msp430.h (LINK_SPEC): Propagate
+ -m{code,data}-region to the linker via spec function
+ msp430_propagate_region_opt.
+ (msp430_propagate_region_opt): New prototype.
+ (EXTRA_SPEC_FUNCTIONS): Add msp430_propagate_region_opt.
+ (SYMBOL_FLAG_LOW_MEM): Define.
+ * config/msp430/msp430.md (addsipsi3): Add missing "%X" operand
+ selector.
+ (zero_extendqihi2): Fix operand number used by "%X" selector.
+ (zero_extendqisi2): Likewise.
+ (zero_extendhisi2): Likewise.
+ (movqi): Use "Yx" constraint in place of "%X" operand selector.
+ (movhi): Likewise.
+ (addqi3): Likewise.
+ (addhi3): Likewise.
+ (addsi3): Likewise.
+ (addhi3_cy): Likewise.
+ (addchi4_cy): Likewise.
+ (subqi3): Likewise.
+ (subhi3): Likewise.
+ (subsi3): Likewise.
+ (bic<mode>3): Likewise.
+ (and<mode>3): Likewise.
+ (ior<mode>3): Likewise.
+ (xor<mode>3): Likewise.
+ (slli_1): Add missing "%X" operand selector.
+ (slll_1): Likewise.
+ (slll_2): Likewise.
+ (srai_1): Likewise.
+ (sral_1): Likewise.
+ (sral_2): Likewise.
+ (srli_1): Likewise.
+ (srll_1): Likewise.
+ (cbranchqi4_real): Use "Yx" constraint in place of "%X" operand
+ selector.
+ (cbranchhi4_real): Likewise.
+ (cbranchqi4_reversed): Likewise.
+ (cbranchhi4_reversed): Likewise.
+ (*bitbranch<mode>4): Likewise.
+ (*bitbranch<mode>4_z): Remove unnecessary "%x" operand selector.
+ * config/msp430/msp430.opt (mcode-region=): Set default to
+ MSP430_REGION_LOWER. Improve docstring.
+ (mdata-region=): Likewise.
+ (muse-lower-region-prefix): New option.
+ * config/msp430/t-msp430 (MULTILIB_OPTIONS): Add
+ mdata-region=none multilib.
+ (MULTILIB_MATCHES): Set mdata-region={upper,either} to match
+ mdata-region=none multilib.
+ MULTILIB_EXCEPTIONS: Remove.
+ MULTILIB_REQUIRED: Define.
+ * configure: Regenerate.
+ * configure.ac: Define HAVE_AS_GNU_ATTRIBUTE and
+ HAVE_AS_MSPABI_ATTRIBUTE if GAS version >= 2.33.50.
+ * doc/extend.texi: Clarify comment for {upper,lower,either}
+ function attributes.
+ Add separate description for "lower" variable attribute.
+
+2019-10-07 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ PR target/77918
+ * optabs-tree.c (vcond_icode_p): New function.
+ (vcond_eq_icode_p): Likewise.
+ (expand_vec_cond_expr_p): Use vcond_icode_p and
+ vcond_eq_icode_p.
+ * optabs.c (can_vcond_compare_p): New function.
+ * optabs.h (can_vcond_compare_p): Likewise.
+
+2019-10-07 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ PR target/77918
+ * gimple-expr.c (gimple_cond_get_ops_from_tree): Assert that the
+ caller passes a non-trapping condition.
+ (is_gimple_condexpr): Allow trapping conditions.
+ (is_gimple_condexpr_1): New helper function.
+ (is_gimple_condexpr_for_cond): New function, acts like old
+ is_gimple_condexpr.
+ * gimple-expr.h (is_gimple_condexpr_for_cond): New function.
+ * gimple.c (gimple_could_trap_p_1): Handle COND_EXPR and
+ VEC_COND_EXPR. Fix an issue with statements like i = (fp < 1.).
+ * gimplify.c (gimplify_cond_expr): Use
+ is_gimple_condexpr_for_cond.
+ (gimplify_expr): Allow is_gimple_condexpr_for_cond.
+ * tree-eh.c (operation_could_trap_p): Assert on COND_EXPR and
+ VEC_COND_EXPR.
+ (tree_could_trap_p): Handle COND_EXPR and VEC_COND_EXPR.
+ * tree-ssa-forwprop.c (forward_propagate_into_gimple_cond): Use
+ is_gimple_condexpr_for_cond, remove pointless tmp check
+ (forward_propagate_into_cond): Remove pointless tmp check.
+
+2019-10-07 Vladislav Ivanishin <vlad@ispras.ru>
+
+ * gimple-iterator.h (gsi_next_nonvirtual_phi): Change the semantics to
+ match that of other gsi_next_* functions. Adjust the comment.
+ (gsi_start_nonvirtual_phis): New function.
+ * ipa-icf.c (sem_function::compare_phi_node): Update uses of
+ gsi_next_nonvirtual_phi accordingly. (No functional change.)
+
+2019-10-07 Vladislav Ivanishin <vlad@ispras.ru>
+
+ * doc/invoke.texi (-Wuninitialized): Don't mention the clobbered by
+ setjmp situation here. Fix a verb's ending: "the exact variables or
+ elements for which there are warnings depends" -> "... depend".
+
+2019-10-07 Aldy Hernandez <aldyh@redhat.com>
+
+ * ipa-prop.c (ipa_vr::nonzero_p): Add TYPE_UNSIGNED check.
+
+2019-10-07 Aldy Hernandez <aldyh@redhat.com>
+
+ * ipa-prop.c (ipa_vr::nonzero_p): New.
+ (ipcp_update_vr): Use nonzero_p instead of open-coding check for
+ non-zero range.
+ * ipa-prop.h (class ipa_vr): Add nonzero_p.
+ * tree-vrp.c (range_has_numeric_bounds_p): New.
+ (range_int_cst_p): Use range_has_numeric_bounds_p.
+ (get_range_op_handler): New.
+ (supported_types_p): New.
+ (defined_ranges_p): New.
+ (drop_undefines_to_varying): New.
+ (range_fold_binary_symbolics_p): New.
+ (range_fold_unary_symbolics_p): New.
+ (range_fold_unary_expr): Extract out into above functions.
+ (range_fold_binary_expr): Same.
+ (value_range_base::normalize_addresses): New.
+ (value_range_base::normalize_symbolics): Normalize addresses.
+ * tree-vrp.h (class value_range_base): Add normalize_addresses.
+
+2019-10-07 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.c (value_range_base::singleton_p): Use
+ value_range_base::num_pairs instead of vrp_val_is* to check
+ if a range has one sub-range.
+
+2019-10-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * ira-lives.c (check_and_make_def_conflict): Handle cases in which
+ DEF is not a true earlyclobber but is tied to a specific input
+ operand, and so is effectively earlyclobber wrt inputs that have
+ different values.
+ (make_early_clobber_and_input_conflicts): Pass this case to the above.
+
+2019-10-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * machmode.h (opt_mode): Mark constructors with CONSTEXPR.
+ (pod_mode): Mark operators likewise.
+ (scalar_int_mode): Mark non-default constructors and
+ operators with CONSTEXPR.
+ (scalar_float_mode, scalar_mode, complex_mode): Likewise.
+ (fixed_size_mode): Likewise.
+
+2019-10-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/91994
+ * config/i386/sse.md (avx_vzeroupper): Turn into a define_expand
+ and wrap the unspec_volatile in a parallel.
+ (*avx_vzeroupper): New define_insn. Use a match_parallel around
+ the unspec_volatile.
+ * config/i386/predicates.md (vzeroupper_pattern): Expect the
+ unspec_volatile to be wrapped in a parallel.
+ * config/i386/i386-features.c (ix86_add_reg_usage_to_vzeroupper)
+ (ix86_add_reg_usage_to_vzerouppers): New functions.
+ (rest_of_handle_insert_vzeroupper): Use them to add register
+ usage information to the vzeroupper instructions.
+
+2019-10-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/91975
+ * tree-ssa-loop-ivcanon.c (constant_after_peeling): Consistently
+ handle invariants.
+
+2019-10-06 Richard Sandiford <richard.sandiford@arm.com>
+
+ * var-tracking.c (dataflow_set_clear_at_call): Hoist temporary
+ function result outside of EXECUTE_IF_SET_IN_HARD_REG_SET.
+
+2019-10-06 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.c (darwin_override_options): Adjust objective-c
+ ABI version error messages to avoid punctuation and contracted
+ negations.
+
+2019-10-05 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-inline.c: Fix type; compute size rather than self_size
+ for size of caller function.
+
+2019-10-05 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR target/59888
+ * config/darwin.c (darwin_rodata_section): Add relocation flag,
+ choose const_data section for constants with relocations.
+ (machopic_select_section): Pass relocation flag to
+ darwin_rodata_section ().
+
+2019-10-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/91734
+ * generic-match-head.c: Include fold-const-call.h.
+ * match.pd (sqrt(x) cmp c): Check the boundary value and
+ in case inexact computation of c*c affects comparison of the boundary,
+ turn LT_EXPR into LE_EXPR, GE_EXPR into GT_EXPR, LE_EXPR into LT_EXPR
+ or GT_EXPR into GE_EXPR. Punt for sqrt comparisons against NaN and
+ for -frounding-math. For c2, try the next smaller or larger floating
+ point constant depending on comparison code and if it has the same
+ sqrt as c2, use it instead of c2.
+
+2019-10-04 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/91977
+ * tree-ssa-strlen.c (count_nonzero_bytes): Handle assignments with
+ MEM_REF right operand. Avoid failing for MEM_REF assignments from
+ uninitialized objects.
+
+2019-10-04 Martin Sebor <msebor@redhat.com>
+
+ * builtins.c (compute_objsize): Add an argument.
+ * tree-object-size.c (addr_object_size): Same.
+ (compute_builtin_object_size): Same.
+ * tree-object-size.h (compute_builtin_object): Same.
+
+2019-10-04 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-inline.c (inline_insns_single, inline_insns_auto): Fix typo.
+
+2019-10-04 Rafael Tsuha <rafael.tsuha@usp.br>
+
+ * match.pd (sinh (x) / cosh (x)): New simplification rule.
+
+2019-10-04 Martin Jambor <mjambor@suse.cz>
+
+ * tree-ssa-forwprop.c (simplify_builtin_call): Set gimple call
+ fntype when switching to calling memcpy instead of memset.
+
+2019-10-04 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * hash-table.h (hash_table::empty_slow): Don't assign
+ size_t values to int variables.
+
+2019-10-04 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * expr.c (convert_mode_scalar): Remove shadowing local var.
+ (emit_block_move): Rename local vars.
+ (block_move_libcall_safe_for_call_parm): Remove shadowing local var.
+ (emit_push_insn): Rename local vars.
+ (expand_assignment): Fix wrong mode in assign_stack_temp. Remove
+ shadowing local vars.
+ (store_constructor): Remove shadowing local vars. Rename local var.
+ (store_field, expand_cond_expr_using_cmove,
+ expand_expr_real_2): Remove shadowing local vars.
+ (expand_expr_real_1,
+ do_store_flag): Remove shadowing local vars. Rename local vars.
+
+2019-10-04 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * cgraph.h (FOR_EACH_ALIAS): Avoid shadowing the loop variable.
+
+2019-10-04 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * genmatch.c (commutate): Rename local var.
+ (lower_cond): Reuse local var.
+ (dt_node::gen, dt_node::gen_kids, dt_node::gen_kids_1,
+ dt_operand::gen, dt_operand::gen_gimple_expr,
+ dt_simplify::gen): Add a param. Rename generated vars.
+ (decision_tree::insert_operand,
+ (capture_info::walk_match, capture_info::walk_result,
+ capture_info::walk_c_expr): Rename local vars.
+ (expr::gen_transform): Rename generated vars.
+ Use snprintf. Rename local vars.
+ (capture::gen_transform, dt_operand::get_name,
+ dt_operand::gen_opname): Rename generated vars.
+ (write_predicate): Adjust call to gen_kids.
+ (parser::get_internal_capture_id): Rename generated vars.
+ (parser::parse_expr): Rename local vars.
+ (parser::parse_if): Remove local var.
+ (parser::parse_pattern, add_operator): Rename local vars.
+
+2019-10-04 Joseph Myers <joseph@codesourcery.com>
+
+ * builtins.def (DEF_C2X_BUILTIN): New macro.
+ (exp10, exp10f, exp10l, fabsd32, fabsd64, fabsd128, nand32)
+ (nand64, nand128, roundeven, roundevenf, roundevenl, strdup)
+ (strndup): Use DEF_C2X_BUILTIN.
+ * coretypes.h (enum function_class): Add function_c2x_misc.
+
+2019-10-04 Maya Rashish <coypu@sdf.org>
+
+ * ira-color.c (update_costs_from_allocno): Call
+ ira_init_register_move_cost_if_necessary.
+
+2019-10-04 Jeff Law <law@redhat.com>
+
+ * config/h8300/h8300.md (cpymemsi): Disable.
+ (movmd, movmd_internal_<mode>, movstr, movsd):
+ (movstr, movsd, stpcpy_internal_<mode>: Likewise.
+ (movmd splitter, movsd splitter): Likewise.
+
+ * range-op.cc (range_tests): Avoid two tests when ints and
+ shorts are the same size.
+
+2019-10-04 Richard Biener <rguenther@suse.de>
+
+ PR lto/91968
+ * tree.c (find_decls_types_r): Do not remove LABEL_DECLs from
+ BLOCK_VARS.
+
+2019-10-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/91982
+ * tree-vect-loop.c (vectorizable_live_operation): Also guard
+ against EXTRACT_LAST_REDUCTION.
+ * tree-vect-stmts.c (vect_transform_stmt): Likewise.
+
+2019-10-04 Aldy Hernandez <aldyh@redhat.com>
+
+ * range-op.o (value_range_from_overflowed_bounds): Rename from
+ adjust_overflow_bound.
+ (value_range_with_overflow): Rename from
+ create_range_with_overflow.
+ (create_possibly_reversed_range): Adjusted for above renames.
+ (operator_*::wi_fold): Same.
+ (cross_product_operator::wi_cross_productor): Same.
+
+2019-10-04 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * doc/invoke.texi (-Wshadow=global, -Wshadow=local,
+ -Wshadow=compatible-local): Fix description.
+ Add an example where -Wshadow=compatible-local does not
+ warn.
+
+2019-10-03 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/pa.h (MAX_PCREL17F_OFFSET): Adjust.
+
+ * config/pa/pa.c (pa_output_call): Remove 64-bit sibcall sequence.
+ (pa_attr_length_call): Adjust length for 64-bit plabel sequence.
+
+2019-10-03 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ * expr.c (emit_block_move_hints): Slightly cleaner fix to
+ can_move_by_pieces issue.
+
+2019-10-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR target/87243
+ * config/darwin-driver.c (maybe_get_sysroot_from_sdkroot): New.
+ (darwin_driver_init): Use the sysroot provided by SDKROOT when that
+ is available and the user has not set one on the command line.
+
+2019-10-03 Dragan Mladjenovic <dmladjenovic@wavecomp.com>
+
+ PR target/91769
+ * config/mips/mips.c (mips_split_move): Use reg_overlap_mentioned_p
+ instead of REGNO equality check on addr.reg.
+
+2019-10-03 Jan Hubicka <hubicka@ucw.cz>
+
+ * params.def (PARAM_INLINE_HEURISTICS_HINT_PERCENT,
+ PARAM_INLINE_HEURISTICS_HINT_PERCENT_O2): New.
+ * doc/invoke.texi (inline-heuristics-hint-percent,
+ inline-heuristics-hint-percent-O2): Document.
+ * tree-inline.c (inline_insns_single, inline_insns_auto): Add new
+ hint attribute.
+ (can_inline_edge_by_limits_p): Use it.
+
+2019-10-03 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/arm/arm.c (arm_print_value): Use real_to_decimal
+ to print CONST_DOUBLEs.
+
+2019-10-03 Andrea Corallo <andrea.corallo@arm.com>
+
+ * ipa-cp.c (ipa_cp_c_finalize): Release ipcp_transformation_sum.
+ * ipa-prop.c (ipcp_free_transformation_sum): New function.
+ * ipa-prop.h (ipcp_free_transformation_sum): Add declaration.
+
+2019-10-03 Aldy Hernandez <aldyh@redhat.com>
* Makefile.in (OBJS): Add range.o and range-op.o.
Remove wide-int-range.o.
@@ -62,6 +539,218 @@
* wide-int-range.cc: Remove.
* wide-int-range.h: Remove.
+2019-10-02 Michael Meissner <meissner@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (mem_operand_gpr): Use
+ SIGNED_16BIT_OFFSET_EXTRA_P macro.
+ (mem_operand_ds_form): Use SIGNED_16BIT_OFFSET_EXTRA_P macro.
+ (rs6000_mode_dependent_address): Use SIGNED_16BIT_OFFSET_EXTRA_P
+ macro.
+
+2019-10-02 Joseph Myers <joseph@codesourcery.com>
+
+ * ginclude/stdint-gcc.h [__STDC_WANT_IEC_60559_BFP_EXT__]: Change
+ condition on WIDTH macros to [__STDC_WANT_IEC_60559_BFP_EXT__ ||
+ (__STDC_VERSION__ && __STDC_VERSION__ > 201710L)].
+ * glimits.h: Likewise.
+
+2019-10-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/91976
+ * expr.c (emit_block_move_hints): Don't call can_move_by_pieces if
+ size is not CONST_INT_P, set pieces_ok to false in that case. Simplify
+ CONST_INT_P (size) && pieces_ok to pieces_ok. Formatting fix.
+
+2019-10-02 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/80936
+ * builtins.def (bcmp, bcopy, bzero): Declare nonnull.
+
+2019-10-02 Richard Sandiford <richard.sandiford@arm.com>
+
+ * cgraph.c (cgraph_node::rtl_info): Use SET_HARD_REG_SET
+ instead of reg_class_contents[ALL_REGS].
+
+2019-09-30 Jason Merrill <jason@redhat.com>
+
+ Add some hash_map_safe_* functions like vec_safe_*.
+ * hash-map.h (default_hash_map_size): New variable.
+ (create_ggc): Use it as default argument.
+ (hash_map_maybe_create, hash_map_safe_get)
+ (hash_map_safe_get_or_insert, hash_map_safe_put): New fns.
+
+2019-10-02 Jan Hubicka <hubicka@ucw.cz>
+
+ * cif-code.def (MAX_INLINE_INSNS_SINGLE_O2_LIMIT,
+ MAX_INLINE_INSNS_AUTO_O2_LIMIT): New.
+ * ipa-inline.c (inline_insns_single, inline_insns_auto): New functions.
+ (can_inline_edge_by_limits_p): Use it.
+ (big_speedup_p): Use PARAM_INLINE_MIN_SPEEDUP_O2.
+ (want_inline_small_function_p): Use O2 bounds.
+ (edge_badness): LIkewise.
+ * opts.c (default_options): Add OPT_finline_functions.
+ * params.def (PARAM_INLINE_MIN_SPEEDUP_O2,
+ PARAM_MAX_INLINE_INSNS_SINGLE_O2, PARAM_MAX_INLINE_INSNS_AUTO_O2):
+ New parameters.
+ * doc/invoke.texi (-finline-functions): Update documentation.
+ (max-inline-insns-single-O2, max-inline-insns-auto-O2,
+ inline-min-speedup-O2): Document.
+ (early-inlining-insns-O2): Simplify docs.
+
+2019-10-02 Alexander Monakov <amonakov@ispras.ru>
+
+ PR rtl-optimization/87047
+ * ifcvt.c (average_cost): New static function. Use it...
+ (noce_process_if_block): ... here.
+
+2019-10-02 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ * config/rs6000/rs6000-protos.h (expand_block_move): Change prototype.
+ * config/rs6000/rs6000-string.c (expand_block_move): Add
+ might_overlap parm.
+ * config/rs6000/rs6000.md (movmemsi): Add new pattern.
+ (cpymemsi): Add might_overlap parm to expand_block_move() call.
+
+2019-10-02 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ * builtins.c (expand_builtin_memory_copy_args): Add might_overlap parm.
+ (expand_builtin_memcpy): Use might_overlap parm.
+ (expand_builtin_mempcpy_args): Use might_overlap parm.
+ (expand_builtin_memmove): Call expand_builtin_memory_copy_args.
+ (expand_builtin_memory_copy_args): Add might_overlap parm.
+ * expr.c (emit_block_move_via_cpymem): Rename to
+ emit_block_move_via_pattern, add might_overlap parm, use cpymem
+ or movmem optab as appropriate.
+ (emit_block_move_hints): Add might_overlap parm, do the right
+ thing for might_overlap==true.
+ * expr.h (emit_block_move_hints): Update prototype.
+
+2019-10-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * tree-eh.h (unsplit_eh_edges): Declare.
+ * tree-eh.c (maybe_remove_unreachable_handlers): Detect more cases.
+ (unsplit_eh_edges): New function wrapping unsplit_all_eh.
+ * gimple-ssa-store-merging.c: Include cfganal.h cfgcleanup.h except.h.
+ (struct store_immediate_info): Add lp_nr field.
+ (store_immediate_info::store_immediate_info): Add NR2 parameter and
+ initialize lp_nr with it.
+ (struct merged_store_group): Add lp_nr and only_constants fields.
+ (merged_store_group::merged_store_group): Initialize them.
+ (merged_store_group::can_be_merged_into): Deal with them.
+ (pass_store_merging): Rename terminate_and_release_chain into
+ terminate_and_process_chain.
+ (pass_store_merging::terminate_and_process_all_chains): Adjust to above
+ renaming and remove useless assertions.
+ (pass_store_merging::terminate_all_aliasing_chains): Small tweak.
+ (stmts_may_clobber_ref_p): Be prepared for different basic blocks.
+ (imm_store_chain_info::coalesce_immediate_stores): Use only_constants
+ instead of always recomputing it and compare lp_nr.
+ (imm_store_chain_info::output_merged_store): If the group is in an
+ active EH region, register new stores if they can throw. Moreover,
+ if the insertion has created new basic blocks, adjust the PHI nodes
+ of the post landing pad.
+ (imm_store_chain_info::output_merged_stores): If the original stores
+ are in an active EH region, deregister them.
+ (lhs_valid_for_store_merging_p): Prettify.
+ (adjust_bit_pos): New function extracted from...
+ (mem_valid_for_store_merging): ...here. Use it for the base address
+ and also for the offset if it is the addition of a constant.
+ (lp_nr_for_store): New function.
+ (pass_store_merging::process_store): Change return type to bool.
+ Call lp_nr_for_store to initialize the store info. Propagate the
+ return status of various called functions to the return value.
+ (store_valid_for_store_merging_p): New predicate.
+ (enum basic_block_status): New enumeration.
+ (get_status_for_store_merging): New function.
+ (pass_store_merging::execute): If the function can throw and catch
+ non-call exceptions, unsplit the EH edges on entry and clean up the
+ CFG on exit if something changed. Call get_status_for_store_merging
+ for every basic block and keep the chains open across basic blocks
+ when possible. Terminate and process open chains at the end, if any.
+
+2019-10-02 Richard Sandiford <richard.sandiford@arm.com>
+
+ * reginfo.c (globalize_reg): Fix shadowed variable in
+ function_abis walk.
+
+2019-10-02 Martin Jambor <mjambor@suse.cz>
+
+ * cgraph.c (symbol_table::create_edge): New parameter cloning_p,
+ do not compute some stuff when set.
+ (cgraph_node::create_edge): Likewise.
+ (cgraph_node::create_indirect_edge): Renamed last parameter to
+ coning_p and flipped its meaning, don't even calculate
+ inline_failed when set.
+ * cgraph.h (cgraph_node::create_edge): Add new parameter.
+ (symbol_table::::create_edge): Likewise.
+ (cgraph_node::create_indirect_edge): Rename last parameter, flip
+ the default value.
+ * cgraphclones.c (cgraph_edge::clone): Pass true cloning_p to all
+ call graph edge creating functions.
+
+2019-10-01 Jan Hubicka <hubicka@ucw.cz>
+
+ PR c++/91222
+ * ipa-devirt.c (warn_types_mismatch): Fix conditional on anonymous
+ namespace types.
+
+2019-10-02 Shahab Vahedi <shahab@synopsys.com>
+
+ * config/arc/arc.h (ASM_SPEC): Pass -mcode-density.
+
+2019-10-02 Richard Biener <rguenther@suse.de>
+
+ * tree-vectorizer.h (vect_transform_reduction): Declare.
+ * tree-vect-stmts.c (vect_transform_stmt): Use it.
+ * tree-vect-loop.c (vectorizable_reduction): Split out reduction
+ stmt transform to ...
+ (vect_transform_reduction): ... this.
+
+2019-10-02 Tobias Burnus <tobias@codesourcery.com>
+
+ * omp-low.c (lower_omp_target): Dereference optional argument
+ to work with the right pointer.
+
+2019-10-02 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * langhooks-def.h (LANG_HOOKS_OMP_IS_OPTIONAL_ARGUMENT): Default to
+ false.
+ (LANG_HOOKS_DECLS): Add LANG_HOOKS_OMP_IS_OPTIONAL_ARGUMENT.
+ * langhooks.h (omp_is_optional_argument): New hook.
+ * omp-general.c (omp_is_optional_argument): New.
+ * omp-general.h (omp_is_optional_argument): New declaration.
+ * omp-low.c (lower_omp_target): Create temporary for received value
+ and take the address for new_var if the original variable was a
+ DECL_BY_REFERENCE. Use size of referenced object when a
+ pass-by-reference optional argument used as argument to firstprivate.
+
+2019-10-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/91940
+ * tree-vect-patterns.c: Include tree-vector-builder.h and
+ vec-perm-indices.h.
+ (vect_recog_rotate_pattern): Also handle __builtin_bswap16, either by
+ unpromoting the argument back to uint16_t, or by converting into a
+ rotate, or into shifts plus ior.
+
+2019-10-02 Richard Biener <rguenther@suse.de>
+
+ * tree-vectorizer.h (stmt_vec_info_type::cycle_phi_info_type):
+ New.
+ (vect_transform_cycle_phi): Declare.
+ * tree-vect-stmts.c (vect_transform_stmt): Call
+ vect_transform_cycle_phi.
+ * tree-vect-loop.c (vectorizable_reduction): Split out
+ PHI transformation stage to ...
+ (vect_transform_cycle_phi): ... here.
+
+2019-10-02 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR middle-end/91957
+ * lra-lives.c (make_hard_regno_dead): Don't record conflicts for
+ eliminable registers.
+ (make_hard_regno_live): Likewise, and don't make them live.
+
2019-10-01 David Malcolm <dmalcolm@redhat.com>
* diagnostic-show-locus.c (layout::print_gap_in_line_numbering):
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 11b6d832c9b..c440771e27d 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20191002
+20191008
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 6a84b7b80f5..0463038f63a 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,7 @@
+2019-10-04 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc-interface/utils.c (flag_isoc2x): New variable.
+
2019-10-01 Maciej W. Rozycki <macro@wdc.com>
* gcc-interface/Makefile.in (ADA_RTL_DSO_DIR): New variable.
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index b9d5af771e8..d2891f250a7 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -6901,6 +6901,7 @@ def_builtin_1 (enum built_in_function fncode,
static int flag_isoc94 = 0;
static int flag_isoc99 = 0;
static int flag_isoc11 = 0;
+static int flag_isoc2x = 0;
/* Install what the common builtins.def offers plus our local additions.
diff --git a/gcc/brig/ChangeLog b/gcc/brig/ChangeLog
index 462cbab05af..9f824e2173c 100644
--- a/gcc/brig/ChangeLog
+++ b/gcc/brig/ChangeLog
@@ -1,3 +1,7 @@
+2019-10-04 Joseph Myers <joseph@codesourcery.com>
+
+ * brig-lang.c (flag_isoc2x): New variable.
+
2019-08-23 Jakub Jelinek <jakub@redhat.com>
PR middle-end/91283
diff --git a/gcc/brig/brig-lang.c b/gcc/brig/brig-lang.c
index 96c6c572e94..505a83d9123 100644
--- a/gcc/brig/brig-lang.c
+++ b/gcc/brig/brig-lang.c
@@ -587,6 +587,7 @@ static GTY(()) tree signed_size_type_node;
int flag_isoc94;
int flag_isoc99;
int flag_isoc11;
+int flag_isoc2x;
static void
def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...)
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 1fd4b88bcac..a1dc83c0b24 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -127,7 +127,8 @@ static rtx expand_builtin_memchr (tree, rtx);
static rtx expand_builtin_memcpy (tree, rtx);
static rtx expand_builtin_memory_copy_args (tree dest, tree src, tree len,
rtx target, tree exp,
- memop_ret retmode);
+ memop_ret retmode,
+ bool might_overlap);
static rtx expand_builtin_memmove (tree, rtx);
static rtx expand_builtin_mempcpy (tree, rtx);
static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, memop_ret);
@@ -3586,7 +3587,7 @@ compute_objsize (tree dest, int ostype, tree *pdecl /* = NULL */)
/* Only the two least significant bits are meaningful. */
ostype &= 3;
- if (compute_builtin_object_size (dest, ostype, &size))
+ if (compute_builtin_object_size (dest, ostype, &size, pdecl))
return build_int_cst (sizetype, size);
if (TREE_CODE (dest) == SSA_NAME)
@@ -3790,14 +3791,14 @@ expand_builtin_memcpy (tree exp, rtx target)
check_memop_access (exp, dest, src, len);
return expand_builtin_memory_copy_args (dest, src, len, target, exp,
- /*retmode=*/ RETURN_BEGIN);
+ /*retmode=*/ RETURN_BEGIN, false);
}
/* Check a call EXP to the memmove built-in for validity.
Return NULL_RTX on both success and failure. */
static rtx
-expand_builtin_memmove (tree exp, rtx)
+expand_builtin_memmove (tree exp, rtx target)
{
if (!validate_arglist (exp,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
@@ -3809,7 +3810,8 @@ expand_builtin_memmove (tree exp, rtx)
check_memop_access (exp, dest, src, len);
- return NULL_RTX;
+ return expand_builtin_memory_copy_args (dest, src, len, target, exp,
+ /*retmode=*/ RETURN_BEGIN, true);
}
/* Expand a call EXP to the mempcpy builtin.
@@ -3858,7 +3860,8 @@ expand_builtin_mempcpy (tree exp, rtx target)
static rtx
expand_builtin_memory_copy_args (tree dest, tree src, tree len,
- rtx target, tree exp, memop_ret retmode)
+ rtx target, tree exp, memop_ret retmode,
+ bool might_overlap)
{
const char *src_str;
unsigned int src_align = get_pointer_alignment (src);
@@ -3894,9 +3897,12 @@ expand_builtin_memory_copy_args (tree dest, tree src, tree len,
&probable_max_size);
src_str = c_getstr (src);
- /* If SRC is a string constant and block move would be done
- by pieces, we can avoid loading the string from memory
- and only stored the computed constants. */
+ /* If SRC is a string constant and block move would be done by
+ pieces, we can avoid loading the string from memory and only
+ stored the computed constants. This works in the overlap
+ (memmove) case as well because store_by_pieces just generates a
+ series of stores of constants from the string constant returned
+ by c_getstr(). */
if (src_str
&& CONST_INT_P (len_rtx)
&& (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
@@ -3923,13 +3929,14 @@ expand_builtin_memory_copy_args (tree dest, tree src, tree len,
method = BLOCK_OP_TAILCALL;
bool use_mempcpy_call = (targetm.libc_has_fast_function (BUILT_IN_MEMPCPY)
&& retmode == RETURN_END
+ && !might_overlap
&& target != const0_rtx);
if (use_mempcpy_call)
method = BLOCK_OP_NO_LIBCALL_RET;
dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, method,
expected_align, expected_size,
min_size, max_size, probable_max_size,
- use_mempcpy_call, &is_move_done);
+ use_mempcpy_call, &is_move_done, might_overlap);
/* Bail out when a mempcpy call would be expanded as libcall and when
we have a target that provides a fast implementation
@@ -3962,7 +3969,7 @@ expand_builtin_mempcpy_args (tree dest, tree src, tree len,
rtx target, tree orig_exp, memop_ret retmode)
{
return expand_builtin_memory_copy_args (dest, src, len, target, orig_exp,
- retmode);
+ retmode, false);
}
/* Expand into a movstr instruction, if one is available. Return NULL_RTX if
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 8bb7027aac7..d8233f5f760 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -154,6 +154,13 @@ along with GCC; see the file COPYING3. If not see
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
true, true, !flag_isoc11, ATTRS, targetm.libc_has_function (function_c11_misc), true)
+/* Like DEF_LIB_BUILTIN, except that the function is only a part of
+ the standard in C2x or above. */
+#undef DEF_C2X_BUILTIN
+#define DEF_C2X_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ true, true, !flag_isoc2x, ATTRS, targetm.libc_has_function (function_c2x_misc), true)
+
/* Like DEF_C99_BUILTIN, but for complex math functions. */
#undef DEF_C99_COMPL_BUILTIN
#define DEF_C99_COMPL_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
@@ -335,9 +342,9 @@ DEF_C99_BUILTIN (BUILT_IN_ERFCL, "erfcl", BT_FN_LONGDOUBLE_LONGDOUBLE, AT
DEF_C99_BUILTIN (BUILT_IN_ERFF, "erff", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
DEF_C99_BUILTIN (BUILT_IN_ERFL, "erfl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
DEF_LIB_BUILTIN (BUILT_IN_EXP, "exp", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_EXP10, "exp10", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_EXP10F, "exp10f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_EXP10L, "exp10l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C2X_BUILTIN (BUILT_IN_EXP10, "exp10", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C2X_BUILTIN (BUILT_IN_EXP10F, "exp10f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C2X_BUILTIN (BUILT_IN_EXP10L, "exp10l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_BUILTIN (BUILT_IN_EXP2, "exp2", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_BUILTIN (BUILT_IN_EXP2F, "exp2f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_BUILTIN (BUILT_IN_EXP2L, "exp2l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
@@ -352,9 +359,9 @@ DEF_C99_C90RES_BUILTIN (BUILT_IN_FABSL, "fabsl", BT_FN_LONGDOUBLE_LONGDOUBLE, AT
#define FABS_TYPE(F) BT_FN_##F##_##F
DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_FABS, "fabs", FABS_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
#undef FABS_TYPE
-DEF_GCC_BUILTIN (BUILT_IN_FABSD32, "fabsd32", BT_FN_DFLOAT32_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST)
-DEF_GCC_BUILTIN (BUILT_IN_FABSD64, "fabsd64", BT_FN_DFLOAT64_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST)
-DEF_GCC_BUILTIN (BUILT_IN_FABSD128, "fabsd128", BT_FN_DFLOAT128_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C2X_BUILTIN (BUILT_IN_FABSD32, "fabsd32", BT_FN_DFLOAT32_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C2X_BUILTIN (BUILT_IN_FABSD64, "fabsd64", BT_FN_DFLOAT64_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C2X_BUILTIN (BUILT_IN_FABSD128, "fabsd128", BT_FN_DFLOAT128_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_BUILTIN (BUILT_IN_FDIM, "fdim", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_BUILTIN (BUILT_IN_FDIMF, "fdimf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_BUILTIN (BUILT_IN_FDIML, "fdiml", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
@@ -501,9 +508,9 @@ DEF_C99_BUILTIN (BUILT_IN_NANF, "nanf", BT_FN_FLOAT_CONST_STRING, ATTR_CO
DEF_C99_BUILTIN (BUILT_IN_NANL, "nanl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
#define NAN_TYPE(F) BT_FN_##F##_CONST_STRING
DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_NAN, "nan", NAN_TYPE, ATTR_CONST_NOTHROW_NONNULL)
-DEF_GCC_BUILTIN (BUILT_IN_NAND32, "nand32", BT_FN_DFLOAT32_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
-DEF_GCC_BUILTIN (BUILT_IN_NAND64, "nand64", BT_FN_DFLOAT64_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
-DEF_GCC_BUILTIN (BUILT_IN_NAND128, "nand128", BT_FN_DFLOAT128_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_C2X_BUILTIN (BUILT_IN_NAND32, "nand32", BT_FN_DFLOAT32_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_C2X_BUILTIN (BUILT_IN_NAND64, "nand64", BT_FN_DFLOAT64_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_C2X_BUILTIN (BUILT_IN_NAND128, "nand128", BT_FN_DFLOAT128_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
DEF_GCC_BUILTIN (BUILT_IN_NANS, "nans", BT_FN_DOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
DEF_GCC_BUILTIN (BUILT_IN_NANSF, "nansf", BT_FN_FLOAT_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
DEF_GCC_BUILTIN (BUILT_IN_NANSL, "nansl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
@@ -542,9 +549,9 @@ DEF_C99_BUILTIN (BUILT_IN_RINTL, "rintl", BT_FN_LONGDOUBLE_LONGDOUBLE, AT
#define RINT_TYPE(F) BT_FN_##F##_##F
DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_RINT, "rint", RINT_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
#undef RINT_TYPE
-DEF_EXT_LIB_BUILTIN (BUILT_IN_ROUNDEVEN, "roundeven", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_ROUNDEVENF, "roundevenf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_ROUNDEVENL, "roundevenl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C2X_BUILTIN (BUILT_IN_ROUNDEVEN, "roundeven", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C2X_BUILTIN (BUILT_IN_ROUNDEVENF, "roundevenf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C2X_BUILTIN (BUILT_IN_ROUNDEVENL, "roundevenl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_BUILTIN (BUILT_IN_ROUND, "round", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_BUILTIN (BUILT_IN_ROUNDF, "roundf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_BUILTIN (BUILT_IN_ROUNDL, "roundl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
@@ -687,11 +694,9 @@ DEF_C99_COMPL_BUILTIN (BUILT_IN_CTANHL, "ctanhl", BT_FN_COMPLEX_LONGDOUBL
DEF_C99_COMPL_BUILTIN (BUILT_IN_CTANL, "ctanl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
/* Category: string/memory builtins. */
-/* bcmp, bcopy and bzero have traditionally accepted NULL pointers
- when the length parameter is zero, so don't apply attribute "nonnull". */
-DEF_EXT_LIB_BUILTIN (BUILT_IN_BCMP, "bcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_LEAF_LIST)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_BCOPY, "bcopy", BT_FN_VOID_CONST_PTR_PTR_SIZE, ATTR_NOTHROW_LEAF_LIST)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_BZERO, "bzero", BT_FN_VOID_PTR_SIZE, ATTR_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_BCMP, "bcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_BCOPY, "bcopy", BT_FN_VOID_CONST_PTR_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_BZERO, "bzero", BT_FN_VOID_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_INDEX, "index", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_MEMCHR, "memchr", BT_FN_PTR_CONST_PTR_INT_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_MEMCMP, "memcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
@@ -708,8 +713,8 @@ DEF_LIB_BUILTIN (BUILT_IN_STRCHR, "strchr", BT_FN_STRING_CONST_STRING_INT
DEF_LIB_BUILTIN (BUILT_IN_STRCMP, "strcmp", BT_FN_INT_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRCPY, "strcpy", BT_FN_STRING_STRING_CONST_STRING, ATTR_RET1_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRCSPN, "strcspn", BT_FN_SIZE_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_STRDUP, "strdup", BT_FN_STRING_CONST_STRING, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNDUP, "strndup", BT_FN_STRING_CONST_STRING_SIZE, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
+DEF_C2X_BUILTIN (BUILT_IN_STRDUP, "strdup", BT_FN_STRING_CONST_STRING, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
+DEF_C2X_BUILTIN (BUILT_IN_STRNDUP, "strndup", BT_FN_STRING_CONST_STRING_SIZE, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRLEN, "strlen", BT_FN_SIZE_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCASECMP, "strncasecmp", BT_FN_INT_CONST_STRING_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRNCAT, "strncat", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 0eade3cf8d8..93077ff7c0e 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,25 @@
+2019-10-08 Joseph Myers <joseph@codesourcery.com>
+
+ * c-opts.c (c_common_post_options): Set
+ -fno-fp-int-builtin-inexact for C2X.
+
+2019-10-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/91369 - Implement P0784R7: constexpr new
+ * c-cppbuiltin.c (c_cpp_builtins): Predefine
+ __cpp_constexpr_dynamic_alloc=201907 for -std=c++2a.
+
+2019-10-04 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/82752
+ * c-format.c (C_STD_VER): Handle C2x.
+ (C_STD_NAME): Likewise.
+ (strftime_flag_specs): Add 'O' modifier with 'p' flag.
+ (time_char_table): Use separate entry for 'B' and 'b', with 'O'
+ modifier allowed and 'p' flag.
+ * c-format.h (enum format_std_version): Add STD_C2X.
+ (struct format_char_info): Mention 'p' in comment on flags2.
+
2019-10-01 David Malcolm <dmalcolm@redhat.com>
* c-opts.c (c_diagnostic_finalizer): Temporarily clear prefix when
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index fc68bc4d0c4..9e0ce428127 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -989,6 +989,7 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__cpp_constinit=201907");
cpp_define (pfile, "__cpp_nontype_template_parameter_class=201806");
cpp_define (pfile, "__cpp_impl_destroying_delete=201806");
+ cpp_define (pfile, "__cpp_constexpr_dynamic_alloc=201907");
}
if (flag_concepts)
cpp_define (pfile, "__cpp_concepts=201507");
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 91bae3d6096..3c291ca4500 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -404,9 +404,11 @@ decode_format_attr (const_tree fntype, tree atname, tree args,
/* The C standard version we are checking formats against when pedantic. */
#define C_STD_VER ((int) (c_dialect_cxx () \
? CPLUSPLUS_STD_VER \
- : (flag_isoc99 \
- ? STD_C99 \
- : (flag_isoc94 ? STD_C94 : STD_C89))))
+ : (flag_isoc2x \
+ ? STD_C2X \
+ : (flag_isoc99 \
+ ? STD_C99 \
+ : (flag_isoc94 ? STD_C94 : STD_C89)))))
/* The name to give to the standard version we are warning about when
pedantic. FEATURE_VER is the version in which the feature warned out
appeared, which is higher than C_STD_VER. */
@@ -415,7 +417,9 @@ decode_format_attr (const_tree fntype, tree atname, tree args,
: "ISO C++11") \
: ((FEATURE_VER) == STD_EXT \
? "ISO C" \
- : "ISO C90"))
+ : ((FEATURE_VER) == STD_C2X \
+ ? "ISO C17" \
+ : "ISO C90")))
/* Adjust a C standard version, which may be STD_C9L, to account for
-Wno-long-long. Returns other standard versions unchanged. */
#define ADJ_STD(VER) ((int) ((VER) == STD_C9L \
@@ -653,6 +657,7 @@ static const format_flag_spec strftime_flag_specs[] =
{ 'E', 0, 0, 0, N_("'E' modifier"), N_("the 'E' strftime modifier"), STD_C99 },
{ 'O', 0, 0, 0, N_("'O' modifier"), N_("the 'O' strftime modifier"), STD_C99 },
{ 'O', 'o', 0, 0, NULL, N_("the 'O' modifier"), STD_EXT },
+ { 'O', 'p', 0, 0, NULL, N_("the 'O' modifier"), STD_C2X },
{ 0, 0, 0, 0, NULL, NULL, STD_C89 }
};
@@ -887,7 +892,8 @@ static const format_char_info scan_char_table[] =
static const format_char_info time_char_table[] =
{
/* C89 conversion specifiers. */
- { "ABZab", 0, STD_C89, NOLENGTHS, "^#", "", NULL },
+ { "AZa", 0, STD_C89, NOLENGTHS, "^#", "", NULL },
+ { "Bb", 0, STD_C89, NOLENGTHS, "O^#", "p", NULL },
{ "cx", 0, STD_C89, NOLENGTHS, "E", "3", NULL },
{ "HIMSUWdmw", 0, STD_C89, NOLENGTHS, "-_0Ow", "", NULL },
{ "j", 0, STD_C89, NOLENGTHS, "-_0Ow", "o", NULL },
diff --git a/gcc/c-family/c-format.h b/gcc/c-family/c-format.h
index 6aa68dfe883..15a3153cfd3 100644
--- a/gcc/c-family/c-format.h
+++ b/gcc/c-family/c-format.h
@@ -48,6 +48,7 @@ enum format_std_version
STD_C94,
STD_C9L, /* C99, but treat as C89 if -Wno-long-long. */
STD_C99,
+ STD_C2X,
STD_EXT
};
@@ -149,6 +150,7 @@ struct format_char_info
two digit year formats, "3" for strftime formats giving two digit
years in some locales, "4" for "2" which becomes "3" with an "E" modifier,
"o" if use of strftime "O" is a GNU extension beyond C99,
+ "p" if use of strftime "O" is a C2x feature,
"W" if the argument is a pointer which is dereferenced and written into,
"R" if the argument is a pointer which is dereferenced and read from,
"i" for printf integer formats where the '0' flag is ignored with
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index 949d96a7839..4ad24bd3ea0 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -826,6 +826,12 @@ c_common_post_options (const char **pfilename)
else
flag_permitted_flt_eval_methods = PERMITTED_FLT_EVAL_METHODS_C11;
+ /* C2X Annex F does not permit certain built-in functions to raise
+ "inexact". */
+ if (flag_isoc2x
+ && !global_options_set.x_flag_fp_int_builtin_inexact)
+ flag_fp_int_builtin_inexact = 0;
+
/* By default we use C99 inline semantics in GNU99 or C99 mode. C99
inline semantics are not supported in GNU89 or C89 mode. */
if (flag_gnu89_inline == -1)
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 19158f08818..0c3c6e7cac4 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -824,12 +824,13 @@ cgraph_edge::set_call_stmt (gcall *new_stmt, bool update_speculative)
/* Allocate a cgraph_edge structure and fill it with data according to the
parameters of which only CALLEE can be NULL (when creating an indirect call
- edge). */
+ edge). CLONING_P should be set if properties that are copied from an
+ original edge should not be calculated. */
cgraph_edge *
symbol_table::create_edge (cgraph_node *caller, cgraph_node *callee,
gcall *call_stmt, profile_count count,
- bool indir_unknown_callee)
+ bool indir_unknown_callee, bool cloning_p)
{
cgraph_edge *edge;
@@ -862,8 +863,17 @@ symbol_table::create_edge (cgraph_node *caller, cgraph_node *callee,
edge->lto_stmt_uid = 0;
edge->count = count;
-
edge->call_stmt = call_stmt;
+ edge->indirect_info = NULL;
+ edge->indirect_inlining_edge = 0;
+ edge->speculative = false;
+ edge->indirect_unknown_callee = indir_unknown_callee;
+ if (call_stmt && caller->call_site_hash)
+ cgraph_add_edge_to_call_site_hash (edge);
+
+ if (cloning_p)
+ return edge;
+
edge->can_throw_external
= call_stmt ? stmt_can_throw_external (DECL_STRUCT_FUNCTION (caller->decl),
call_stmt) : false;
@@ -881,10 +891,6 @@ symbol_table::create_edge (cgraph_node *caller, cgraph_node *callee,
edge->call_stmt_cannot_inline_p = false;
}
- edge->indirect_info = NULL;
- edge->indirect_inlining_edge = 0;
- edge->speculative = false;
- edge->indirect_unknown_callee = indir_unknown_callee;
if (opt_for_fn (edge->caller->decl, flag_devirtualize)
&& call_stmt && DECL_STRUCT_FUNCTION (caller->decl))
edge->in_polymorphic_cdtor
@@ -892,22 +898,23 @@ symbol_table::create_edge (cgraph_node *caller, cgraph_node *callee,
caller->decl);
else
edge->in_polymorphic_cdtor = caller->thunk.thunk_p;
- if (call_stmt && caller->call_site_hash)
- cgraph_add_edge_to_call_site_hash (edge);
return edge;
}
-/* Create edge from a given function to CALLEE in the cgraph. */
+/* Create edge from a given function to CALLEE in the cgraph. CLONING_P should
+ be set if properties that are copied from an original edge should not be
+ calculated. */
cgraph_edge *
cgraph_node::create_edge (cgraph_node *callee,
- gcall *call_stmt, profile_count count)
+ gcall *call_stmt, profile_count count, bool cloning_p)
{
cgraph_edge *edge = symtab->create_edge (this, callee, call_stmt, count,
- false);
+ false, cloning_p);
- initialize_inline_failed (edge);
+ if (!cloning_p)
+ initialize_inline_failed (edge);
edge->next_caller = callee->callers;
if (callee->callers)
@@ -935,25 +942,28 @@ cgraph_allocate_init_indirect_info (void)
/* Create an indirect edge with a yet-undetermined callee where the call
statement destination is a formal parameter of the caller with index
- PARAM_INDEX. */
+ PARAM_INDEX. CLONING_P should be set if properties that are copied from an
+ original edge should not be calculated and indirect_info structure should
+ not be calculated. */
cgraph_edge *
cgraph_node::create_indirect_edge (gcall *call_stmt, int ecf_flags,
profile_count count,
- bool compute_indirect_info)
+ bool cloning_p)
{
- cgraph_edge *edge = symtab->create_edge (this, NULL, call_stmt,
- count, true);
+ cgraph_edge *edge = symtab->create_edge (this, NULL, call_stmt, count, true,
+ cloning_p);
tree target;
- initialize_inline_failed (edge);
+ if (!cloning_p)
+ initialize_inline_failed (edge);
edge->indirect_info = cgraph_allocate_init_indirect_info ();
edge->indirect_info->ecf_flags = ecf_flags;
edge->indirect_info->vptr_changed = true;
/* Record polymorphic call info. */
- if (compute_indirect_info
+ if (!cloning_p
&& call_stmt
&& (target = gimple_call_fn (call_stmt))
&& virtual_method_call_p (target))
@@ -1856,7 +1866,7 @@ cgraph_node::rtl_info (const_tree decl)
if (node->rtl == NULL)
{
node->rtl = ggc_cleared_alloc<cgraph_rtl_info> ();
- node->rtl->function_used_regs = reg_class_contents[ALL_REGS];
+ SET_HARD_REG_SET (node->rtl->function_used_regs);
}
return node->rtl;
}
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index c35b6b97516..73b2be6d26d 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -648,8 +648,10 @@ symtab_node::checking_verify_symtab_nodes (void)
}
/* Walk all aliases for NODE. */
-#define FOR_EACH_ALIAS(node, alias) \
- for (unsigned x_i = 0; node->iterate_direct_aliases (x_i, alias); x_i++)
+#define FOR_EACH_ALIAS(NODE, ALIAS) \
+ for (unsigned ALIAS##_iter_ = 0; \
+ (NODE)->iterate_direct_aliases (ALIAS##_iter_, ALIAS); \
+ ALIAS##_iter_++)
/* This is the information that is put into the cgraph local structure
to recover a function. */
@@ -1161,14 +1163,15 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
/* Create edge from a given function to CALLEE in the cgraph. */
cgraph_edge *create_edge (cgraph_node *callee,
- gcall *call_stmt, profile_count count);
+ gcall *call_stmt, profile_count count,
+ bool cloning_p = false);
/* Create an indirect edge with a yet-undetermined callee where the call
statement destination is a formal parameter of the caller with index
PARAM_INDEX. */
cgraph_edge *create_indirect_edge (gcall *call_stmt, int ecf_flags,
profile_count count,
- bool compute_indirect_info = true);
+ bool cloning_p = false);
/* Like cgraph_create_edge walk the clone tree and update all clones sharing
same function body. If clones already have edge for OLD_STMT; only
@@ -2381,11 +2384,12 @@ private:
inline cgraph_node * allocate_cgraph_symbol (void);
/* Allocate a cgraph_edge structure and fill it with data according to the
- parameters of which only CALLEE can be NULL (when creating an indirect call
- edge). */
+ parameters of which only CALLEE can be NULL (when creating an indirect
+ call edge). CLONING_P should be set if properties that are copied from an
+ original edge should not be calculated. */
cgraph_edge *create_edge (cgraph_node *caller, cgraph_node *callee,
gcall *call_stmt, profile_count count,
- bool indir_unknown_callee);
+ bool indir_unknown_callee, bool cloning_p);
/* Put the edge onto the free list. */
void free_edge (cgraph_edge *e);
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 909407b9a71..087b5a26280 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -104,19 +104,19 @@ cgraph_edge::clone (cgraph_node *n, gcall *call_stmt, unsigned stmt_uid,
{
cgraph_node *callee = cgraph_node::get (decl);
gcc_checking_assert (callee);
- new_edge = n->create_edge (callee, call_stmt, prof_count);
+ new_edge = n->create_edge (callee, call_stmt, prof_count, true);
}
else
{
new_edge = n->create_indirect_edge (call_stmt,
indirect_info->ecf_flags,
- prof_count, false);
+ prof_count, true);
*new_edge->indirect_info = *indirect_info;
}
}
else
{
- new_edge = n->create_edge (callee, call_stmt, prof_count);
+ new_edge = n->create_edge (callee, call_stmt, prof_count, true);
if (indirect_info)
{
new_edge->indirect_info
diff --git a/gcc/cif-code.def b/gcc/cif-code.def
index ccd08e296ca..8676ee1c0f3 100644
--- a/gcc/cif-code.def
+++ b/gcc/cif-code.def
@@ -70,8 +70,12 @@ DEFCIFCODE(LARGE_STACK_FRAME_GROWTH_LIMIT, CIF_FINAL_NORMAL,
N_("--param large-stack-frame-growth limit reached"))
DEFCIFCODE(MAX_INLINE_INSNS_SINGLE_LIMIT, CIF_FINAL_NORMAL,
N_("--param max-inline-insns-single limit reached"))
+DEFCIFCODE(MAX_INLINE_INSNS_SINGLE_O2_LIMIT, CIF_FINAL_NORMAL,
+ N_("--param max-inline-insns-single-O2 limit reached"))
DEFCIFCODE(MAX_INLINE_INSNS_AUTO_LIMIT, CIF_FINAL_NORMAL,
N_("--param max-inline-insns-auto limit reached"))
+DEFCIFCODE(MAX_INLINE_INSNS_AUTO_O2_LIMIT, CIF_FINAL_NORMAL,
+ N_("--param max-inline-insns-auto-O2 limit reached"))
DEFCIFCODE(INLINE_UNIT_GROWTH_LIMIT, CIF_FINAL_NORMAL,
N_("--param inline-unit-growth limit reached"))
diff --git a/gcc/config.in b/gcc/config.in
index 13fd7959dd7..9b54a4715db 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -553,6 +553,12 @@
#endif
+/* Define if your assembler supports .mspabi_attribute. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MSPABI_ATTRIBUTE
+#endif
+
+
/* Define if the assembler understands -mnan=. */
#ifndef USED_FOR_TARGET
#undef HAVE_AS_NAN
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index 4a9dd07f558..4d7ac3281b4 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -97,7 +97,8 @@ extern const char *arc_cpu_to_as (int argc, const char **argv);
#undef ASM_SPEC
#define ASM_SPEC "%{mbig-endian|EB:-EB} %{EL} " \
- "%:cpu_to_as(%{mcpu=*:%*}) %{mspfp*} %{mdpfp*} %{mfpu=fpuda*:-mfpuda}"
+ "%:cpu_to_as(%{mcpu=*:%*}) %{mspfp*} %{mdpfp*} " \
+ "%{mfpu=fpuda*:-mfpuda} %{mcode-density}"
#define OPTION_DEFAULT_SPECS \
{"cpu", "%{!mcpu=*:%{!mARC*:%{!marc*:%{!mA7:%{!mA6:-mcpu=%(VALUE)}}}}}" }
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 9f0975dc071..39e1a1ef9a2 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -16122,7 +16122,12 @@ arm_print_value (FILE *f, rtx x)
return;
case CONST_DOUBLE:
- fprintf (f, "<0x%lx,0x%lx>", (long)XWINT (x, 2), (long)XWINT (x, 3));
+ {
+ char fpstr[20];
+ real_to_decimal (fpstr, CONST_DOUBLE_REAL_VALUE (x),
+ sizeof (fpstr), 0, 1);
+ fputs (fpstr, f);
+ }
return;
case CONST_VECTOR:
diff --git a/gcc/config/darwin-driver.c b/gcc/config/darwin-driver.c
index 49716fabf2d..82ac231dc4a 100644
--- a/gcc/config/darwin-driver.c
+++ b/gcc/config/darwin-driver.c
@@ -210,6 +210,28 @@ darwin_default_min_version (void)
return new_flag;
}
+/* See if we can find the sysroot from the SDKROOT environment variable. */
+
+static const char *
+maybe_get_sysroot_from_sdkroot ()
+{
+ const char *maybe_sysroot = getenv ("SDKROOT");
+
+ /* We'll use the same rules as the clang driver, for compatibility.
+ 1) The path must be absolute
+ 2) Ignore "/", that is the default anyway and we do not want the
+ sysroot semantics to be applied to it.
+ 3) It must exist (actually, we'll check it's readable too). */
+
+ if (maybe_sysroot == NULL
+ || *maybe_sysroot != '/'
+ || strlen (maybe_sysroot) == 1
+ || access (maybe_sysroot, R_OK) == -1)
+ return NULL;
+
+ return xstrndup (maybe_sysroot, strlen (maybe_sysroot));
+}
+
/* Translate -filelist and -framework options in *DECODED_OPTIONS
(size *DECODED_OPTIONS_COUNT) to use -Xlinker so that they are
considered to be linker inputs in the case that no other inputs are
@@ -234,6 +256,7 @@ darwin_driver_init (unsigned int *decoded_options_count,
bool appendM64 = false;
const char *vers_string = NULL;
bool seen_version_min = false;
+ bool seen_sysroot_p = false;
for (i = 1; i < *decoded_options_count; i++)
{
@@ -314,6 +337,11 @@ darwin_driver_init (unsigned int *decoded_options_count,
--*decoded_options_count;
break;
+ case OPT__sysroot_:
+ case OPT_isysroot:
+ seen_sysroot_p = true;
+ break;
+
default:
break;
}
@@ -375,6 +403,22 @@ darwin_driver_init (unsigned int *decoded_options_count,
&(*decoded_options)[*decoded_options_count - 1]);
}
+ if (! seen_sysroot_p)
+ {
+ /* We will pick up an SDKROOT if we didn't specify a sysroot and treat
+ it as overriding any configure-time --with-sysroot. */
+ const char *sdkroot = maybe_get_sysroot_from_sdkroot ();
+ if (sdkroot)
+ {
+ ++*decoded_options_count;
+ *decoded_options = XRESIZEVEC (struct cl_decoded_option,
+ *decoded_options,
+ *decoded_options_count);
+ generate_option (OPT__sysroot_, sdkroot, 1, CL_DRIVER,
+ &(*decoded_options)[*decoded_options_count - 1]);
+ }
+ }
+
/* We will need to know the OS X version we're trying to build for here
so that we can figure out the mechanism and source for the sysroot to
be used. */
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index 3a1be5a29b9..869e850c575 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -76,7 +76,7 @@ along with GCC; see the file COPYING3. If not see
setting the second word in the .non_lazy_symbol_pointer data
structure to symbol. See indirect_data for the code that handles
the extra indirection, and machopic_output_indirection and its use
- of MACHO_SYMBOL_STATIC for the code that handles @code{static}
+ of MACHO_SYMBOL_FLAG_STATIC for the code that handles @code{static}
symbol indirection. */
typedef struct GTY(()) cdtor_record {
@@ -249,7 +249,7 @@ name_needs_quotes (const char *name)
int
machopic_symbol_defined_p (rtx sym_ref)
{
- if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_DEFINED)
+ if (MACHO_SYMBOL_DEFINED_P (sym_ref))
return true;
/* If a symbol references local and is not an extern to this
@@ -258,7 +258,7 @@ machopic_symbol_defined_p (rtx sym_ref)
{
/* If the symbol references a variable and the variable is a
common symbol, then this symbol is not defined. */
- if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_VARIABLE)
+ if (MACHO_SYMBOL_VARIABLE_P (sym_ref))
{
tree decl = SYMBOL_REF_DECL (sym_ref);
if (!decl)
@@ -797,8 +797,7 @@ machopic_indirect_call_target (rtx target)
if (MACHOPIC_INDIRECT
&& GET_CODE (XEXP (target, 0)) == SYMBOL_REF
- && !(SYMBOL_REF_FLAGS (XEXP (target, 0))
- & MACHO_SYMBOL_FLAG_DEFINED))
+ && ! MACHO_SYMBOL_DEFINED_P (XEXP (target, 0)))
{
rtx sym_ref = XEXP (target, 0);
const char *stub_name = machopic_indirection_name (sym_ref,
@@ -1121,6 +1120,7 @@ machopic_output_indirection (machopic_indirection **slot, FILE *asm_out_file)
machopic_output_stub (asm_out_file, sym, stub);
}
else if (! indirect_data (symbol)
+ && ! MACHO_SYMBOL_HIDDEN_VIS_P (symbol)
&& (machopic_symbol_defined_p (symbol)
|| SYMBOL_REF_LOCAL_P (symbol)))
{
@@ -1167,14 +1167,14 @@ machopic_output_indirection (machopic_indirection **slot, FILE *asm_out_file)
assemble_name (asm_out_file, sym_name);
fprintf (asm_out_file, "\n");
- /* Variables that are marked with MACHO_SYMBOL_STATIC need to
+ /* Variables that are marked with MACHO_SYMBOL_FLAG_STATIC need to
have their symbol name instead of 0 in the second entry of
the non-lazy symbol pointer data structure when they are
defined. This allows the runtime to rebind newer instances
of the translation unit with the original instance of the
symbol. */
- if ((SYMBOL_REF_FLAGS (symbol) & MACHO_SYMBOL_STATIC)
+ if (MACHO_SYMBOL_STATIC_P (symbol)
&& machopic_symbol_defined_p (symbol))
init = gen_rtx_SYMBOL_REF (Pmode, sym_name);
@@ -1205,25 +1205,45 @@ machopic_operand_p (rtx op)
&& XINT (XEXP (op, 0), 1) == UNSPEC_MACHOPIC_OFFSET);
}
-/* This function records whether a given name corresponds to a defined
- or undefined function or variable, for machopic_classify_ident to
- use later. */
+/* This function:
+ computes and caches a series of flags that characterise the symbol's
+ properties that affect Mach-O code gen (including accidental cases
+ from older toolchains).
+
+ TODO:
+ Here we also need to do enough analysis to determine if a symbol's
+ name needs to be made linker-visible. This is more tricky - since
+ it depends on whether we've previously seen a global weak definition
+ in the same section.
+ */
void
-darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
+darwin_encode_section_info (tree decl, rtx rtl, int first)
{
- rtx sym_ref;
+ /* Careful not to prod global register variables. */
+ if (!MEM_P (rtl))
+ return;
- /* Do the standard encoding things first. */
+ /* Do the standard encoding things first; this sets:
+ SYMBOL_FLAG_FUNCTION,
+ SYMBOL_FLAG_LOCAL, (binds_local_p)
+ TLS_MODEL, SYMBOL_FLAG_SMALL
+ SYMBOL_FLAG_EXTERNAL. */
default_encode_section_info (decl, rtl, first);
- if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
+ if (! VAR_OR_FUNCTION_DECL_P (decl))
return;
- sym_ref = XEXP (rtl, 0);
- if (TREE_CODE (decl) == VAR_DECL)
+ rtx sym_ref = XEXP (rtl, 0);
+ if (VAR_P (decl))
SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_VARIABLE;
+ /* For Darwin, if we have specified visibility and it's not the default
+ that's counted 'hidden'. */
+ if (DECL_VISIBILITY_SPECIFIED (decl)
+ && DECL_VISIBILITY (decl) != VISIBILITY_DEFAULT)
+ SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_HIDDEN_VIS;
+
if (!DECL_EXTERNAL (decl)
&& (!TREE_PUBLIC (decl) || !DECL_WEAK (decl))
&& ! lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
@@ -1234,7 +1254,7 @@ darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
if (! TREE_PUBLIC (decl))
- SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_STATIC;
+ SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_STATIC;
}
void
@@ -1251,12 +1271,13 @@ darwin_mark_decl_preserved (const char *name)
}
static section *
-darwin_rodata_section (int use_coal, bool zsize)
+darwin_rodata_section (int use_coal, bool zsize, int reloc)
{
return (use_coal
? darwin_sections[const_coal_section]
: (zsize ? darwin_sections[zobj_const_section]
- : darwin_sections[const_section]));
+ : reloc ? darwin_sections[const_data_section]
+ : darwin_sections[const_section]));
}
static section *
@@ -1549,7 +1570,7 @@ machopic_select_section (tree decl,
case SECCAT_RODATA:
case SECCAT_SRODATA:
- base_section = darwin_rodata_section (use_coal, zsize);
+ base_section = darwin_rodata_section (use_coal, zsize, reloc);
break;
case SECCAT_RODATA_MERGE_STR:
@@ -3151,13 +3172,14 @@ darwin_override_options (void)
if (global_options_set.x_flag_objc_abi && flag_next_runtime)
{
if (TARGET_64BIT && global_options.x_flag_objc_abi < 2)
- error_at (UNKNOWN_LOCATION, "%<-fobjc-abi-version%> >= 2 must be"
- " used for %<-m64%> targets with"
- " %<-fnext-runtime%>");
+ error_at (UNKNOWN_LOCATION, "%<-fobjc-abi-version%> must be greater"
+ " than or equal to 2 for %<-m64%> targets"
+ " with %<-fnext-runtime%>");
if (!TARGET_64BIT && global_options.x_flag_objc_abi >= 2)
- error_at (UNKNOWN_LOCATION, "%<-fobjc-abi-version%> >= 2 is not"
+ error_at (UNKNOWN_LOCATION, "%<-fobjc-abi-version%> %d is not"
" supported on %<-m32%> targets with"
- " %<-fnext-runtime%>");
+ " %<-fnext-runtime%>",
+ global_options.x_flag_objc_abi);
}
/* Don't emit DWARF3/4 unless specifically selected. This is a
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index 93dc638f8bb..87e1eb63b1c 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -812,21 +812,36 @@ extern GTY(()) section * darwin_sections[NUM_DARWIN_SECTIONS];
#undef TARGET_ASM_MARK_DECL_PRESERVED
#define TARGET_ASM_MARK_DECL_PRESERVED darwin_mark_decl_preserved
-/* Set on a symbol with SYMBOL_FLAG_FUNCTION or
- MACHO_SYMBOL_FLAG_VARIABLE to indicate that the function or
- variable has been defined in this translation unit.
- When porting Mach-O to new architectures you need to make
- sure these aren't clobbered by the backend. */
+/* Any port using this header needs to define the first available
+ subtarget symbol bit: SYMBOL_FLAG_SUBT_DEP. */
-#define MACHO_SYMBOL_FLAG_VARIABLE (SYMBOL_FLAG_MACH_DEP)
-#define MACHO_SYMBOL_FLAG_DEFINED ((SYMBOL_FLAG_MACH_DEP) << 1)
+/* Is a variable. */
+#define MACHO_SYMBOL_FLAG_VARIABLE (SYMBOL_FLAG_SUBT_DEP)
+#define MACHO_SYMBOL_VARIABLE_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & MACHO_SYMBOL_FLAG_VARIABLE) != 0)
+
+/* Set on a symbol with SYMBOL_FLAG_FUNCTION or MACHO_SYMBOL_FLAG_VARIABLE
+ to indicate that the function or variable is considered defined in this
+ translation unit. */
+
+#define MACHO_SYMBOL_FLAG_DEFINED ((SYMBOL_FLAG_SUBT_DEP) << 2)
+#define MACHO_SYMBOL_DEFINED_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & MACHO_SYMBOL_FLAG_DEFINED) != 0)
+
+/* Set on a symbol that has specified non-default visibility. */
+
+#define MACHO_SYMBOL_FLAG_HIDDEN_VIS ((SYMBOL_FLAG_SUBT_DEP) << 3)
+#define MACHO_SYMBOL_HIDDEN_VIS_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & MACHO_SYMBOL_FLAG_HIDDEN_VIS) != 0)
/* Set on a symbol to indicate when fix-and-continue style code
generation is being used and the symbol refers to a static symbol
that should be rebound from new instances of a translation unit to
the original instance of the data. */
-#define MACHO_SYMBOL_STATIC ((SYMBOL_FLAG_MACH_DEP) << 2)
+#define MACHO_SYMBOL_FLAG_STATIC ((SYMBOL_FLAG_SUBT_DEP) << 5)
+#define MACHO_SYMBOL_STATIC_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & MACHO_SYMBOL_FLAG_STATIC) != 0)
/* Symbolic names for various things we might know about a symbol. */
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index 778d3e1d132..f3edbb136b6 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -483,7 +483,7 @@
(use (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:SI 2 "" ""))
(use (match_operand:SI 3 "const_int_operand" ""))]
- "TARGET_H8300SX"
+ "TARGET_H8300SX && 0"
{
if (h8sx_emit_movmd (operands[0], operands[1], operands[2], INTVAL (operands[3])))
DONE;
@@ -505,7 +505,7 @@
(clobber (match_dup 5))
(set (match_dup 2)
(const_int 0))])]
- "TARGET_H8300SX"
+ "TARGET_H8300SX && 0"
{
operands[4] = copy_rtx (XEXP (operands[0], 0));
operands[5] = copy_rtx (XEXP (operands[1], 0));
@@ -523,7 +523,7 @@
(clobber (match_operand:P 1 "register_operand" "=f,f"))
(set (match_operand:HI 2 "register_operand" "=c,c")
(const_int 0))]
- "TARGET_H8300SX"
+ "TARGET_H8300SX && 0"
"@
movmd%m6
#"
@@ -553,6 +553,7 @@
(set (match_dup 2)
(const_int 0))]
"TARGET_H8300SX && reload_completed
+ && 0
&& REGNO (operands[4]) != DESTINATION_REG"
[(const_int 0)]
{
@@ -573,7 +574,7 @@
[(use (match_operand 0 "register_operand" ""))
(use (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:BLK 2 "memory_operand" ""))]
- "TARGET_H8300SX"
+ "TARGET_H8300SX && 0"
{
operands[1] = replace_equiv_address
(operands[1], copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
@@ -596,7 +597,7 @@
(clobber (match_dup 3))
(clobber (match_dup 4))
(clobber (match_operand 2 "register_operand" ""))])]
- "TARGET_H8300SX"
+ "TARGET_H8300SX && 0"
{
operands[3] = copy_rtx (XEXP (operands[0], 0));
operands[4] = copy_rtx (XEXP (operands[1], 0));
@@ -611,7 +612,7 @@
(clobber (match_operand:P 0 "register_operand" "=d,??D"))
(clobber (match_operand:P 1 "register_operand" "=f,f"))
(clobber (match_operand:P 2 "register_operand" "=c,c"))]
- "TARGET_H8300SX"
+ "TARGET_H8300SX && 0"
"@
\n1:\tmovsd\t2f\;bra\t1b\n2:
#"
@@ -628,6 +629,7 @@
(clobber (match_operand:P 3 "register_operand" ""))
(clobber (match_operand:P 4 "register_operand" ""))]
"TARGET_H8300SX && reload_completed
+ && 0
&& REGNO (operands[2]) != DESTINATION_REG"
[(const_int 0)]
{
diff --git a/gcc/config/i386/darwin.h b/gcc/config/i386/darwin.h
index 385d2536920..bdb36f00959 100644
--- a/gcc/config/i386/darwin.h
+++ b/gcc/config/i386/darwin.h
@@ -324,10 +324,8 @@ along with GCC; see the file COPYING3. If not see
} \
}
-/* This needs to move since i386 uses the first flag and other flags are
- used in Mach-O. */
-#undef MACHO_SYMBOL_FLAG_VARIABLE
-#define MACHO_SYMBOL_FLAG_VARIABLE ((SYMBOL_FLAG_MACH_DEP) << 3)
+/* First available SYMBOL flag bit for use by subtargets. */
+#define SYMBOL_FLAG_SUBT_DEP (SYMBOL_FLAG_MACH_DEP << 5)
#undef MACHOPIC_NL_SYMBOL_PTR_SECTION
#define MACHOPIC_NL_SYMBOL_PTR_SECTION \
diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c
index 5e377d6dc5f..6d3d14c37dd 100644
--- a/gcc/config/i386/i386-expand.c
+++ b/gcc/config/i386/i386-expand.c
@@ -15903,71 +15903,8 @@ ix86_expand_rint (rtx operand0, rtx operand1)
emit_move_insn (operand0, res);
}
-/* Expand SSE2 sequence for computing floor or ceil from OPERAND1 storing
- into OPERAND0. */
-void
-ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
-{
- /* C code for the stuff we expand below.
- double xa = fabs (x), x2;
- if (!isless (xa, TWO52))
- return x;
- xa = xa + TWO52 - TWO52;
- x2 = copysign (xa, x);
- Compensate. Floor:
- if (x2 > x)
- x2 -= 1;
- Compensate. Ceil:
- if (x2 < x)
- x2 += 1;
- if (HONOR_SIGNED_ZEROS (mode))
- x2 = copysign (x2, x);
- return x2;
- */
- machine_mode mode = GET_MODE (operand0);
- rtx xa, TWO52, tmp, one, res, mask;
- rtx_code_label *label;
-
- TWO52 = ix86_gen_TWO52 (mode);
-
- /* Temporary for holding the result, initialized to the input
- operand to ease control flow. */
- res = gen_reg_rtx (mode);
- emit_move_insn (res, operand1);
-
- /* xa = abs (operand1) */
- xa = ix86_expand_sse_fabs (res, &mask);
-
- /* if (!isless (xa, TWO52)) goto label; */
- label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
-
- /* xa = xa + TWO52 - TWO52; */
- xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
- xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
-
- /* xa = copysign (xa, operand1) */
- ix86_sse_copysign_to_positive (xa, xa, res, mask);
-
- /* generate 1.0 */
- one = force_reg (mode, const_double_from_real_value (dconst1, mode));
-
- /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
- tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
- emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
- tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
- xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
- if (!do_floor && HONOR_SIGNED_ZEROS (mode))
- ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
- emit_move_insn (res, tmp);
-
- emit_label (label);
- LABEL_NUSES (label) = 1;
-
- emit_move_insn (operand0, res);
-}
-
-/* Expand SSE2 sequence for computing floor or ceil from OPERAND1 storing
- into OPERAND0. */
+/* Expand SSE2 sequence for computing floor or ceil
+ from OPERAND1 storing into OPERAND0. */
void
ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
{
@@ -16027,30 +15964,30 @@ ix86_expand_floorceil (rtx operand0, rtx operand1, bool do_floor)
emit_move_insn (operand0, res);
}
-/* Expand SSE sequence for computing round from OPERAND1 storing
- into OPERAND0. Sequence that works without relying on DImode truncation
- via cvttsd2siq that is only available on 64bit targets. */
+/* Expand SSE2 sequence for computing floor or ceil from OPERAND1 storing
+ into OPERAND0 without relying on DImode truncation via cvttsd2siq
+ that is only available on 64bit targets. */
void
-ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
+ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
{
/* C code for the stuff we expand below.
- double xa = fabs (x), xa2, x2;
+ double xa = fabs (x), x2;
if (!isless (xa, TWO52))
return x;
- Using the absolute value and copying back sign makes
- -0.0 -> -0.0 correct.
- xa2 = xa + TWO52 - TWO52;
- Compensate.
- dxa = xa2 - xa;
- if (dxa <= -0.5)
- xa2 += 1;
- else if (dxa > 0.5)
- xa2 -= 1;
- x2 = copysign (xa2, x);
- return x2;
+ xa = xa + TWO52 - TWO52;
+ x2 = copysign (xa, x);
+ Compensate. Floor:
+ if (x2 > x)
+ x2 -= 1;
+ Compensate. Ceil:
+ if (x2 < x)
+ x2 += 1;
+ if (HONOR_SIGNED_ZEROS (mode))
+ x2 = copysign (x2, x);
+ return x2;
*/
machine_mode mode = GET_MODE (operand0);
- rtx xa, xa2, dxa, TWO52, tmp, half, mhalf, one, res, mask;
+ rtx xa, TWO52, tmp, one, res, mask;
rtx_code_label *label;
TWO52 = ix86_gen_TWO52 (mode);
@@ -16066,31 +16003,24 @@ ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
/* if (!isless (xa, TWO52)) goto label; */
label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
- /* xa2 = xa + TWO52 - TWO52; */
- xa2 = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
- xa2 = expand_simple_binop (mode, MINUS, xa2, TWO52, xa2, 0, OPTAB_DIRECT);
-
- /* dxa = xa2 - xa; */
- dxa = expand_simple_binop (mode, MINUS, xa2, xa, NULL_RTX, 0, OPTAB_DIRECT);
+ /* xa = xa + TWO52 - TWO52; */
+ xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
+ xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
- /* generate 0.5, 1.0 and -0.5 */
- half = force_reg (mode, const_double_from_real_value (dconsthalf, mode));
- one = expand_simple_binop (mode, PLUS, half, half, NULL_RTX, 0, OPTAB_DIRECT);
- mhalf = expand_simple_binop (mode, MINUS, half, one, NULL_RTX,
- 0, OPTAB_DIRECT);
+ /* xa = copysign (xa, operand1) */
+ ix86_sse_copysign_to_positive (xa, xa, res, mask);
- /* Compensate. */
- /* xa2 = xa2 - (dxa > 0.5 ? 1 : 0) */
- tmp = ix86_expand_sse_compare_mask (UNGT, dxa, half, false);
- emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
- xa2 = expand_simple_binop (mode, MINUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
- /* xa2 = xa2 + (dxa <= -0.5 ? 1 : 0) */
- tmp = ix86_expand_sse_compare_mask (UNGE, mhalf, dxa, false);
- emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
- xa2 = expand_simple_binop (mode, PLUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
+ /* generate 1.0 */
+ one = force_reg (mode, const_double_from_real_value (dconst1, mode));
- /* res = copysign (xa2, operand1) */
- ix86_sse_copysign_to_positive (res, xa2, force_reg (mode, operand1), mask);
+ /* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
+ tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
+ emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
+ tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
+ xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
+ if (!do_floor && HONOR_SIGNED_ZEROS (mode))
+ ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
+ emit_move_insn (res, tmp);
emit_label (label);
LABEL_NUSES (label) = 1;
@@ -16098,8 +16028,8 @@ ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
emit_move_insn (operand0, res);
}
-/* Expand SSE sequence for computing trunc from OPERAND1 storing
- into OPERAND0. */
+/* Expand SSE sequence for computing trunc
+ from OPERAND1 storing into OPERAND0. */
void
ix86_expand_trunc (rtx operand0, rtx operand1)
{
@@ -16144,7 +16074,8 @@ ix86_expand_trunc (rtx operand0, rtx operand1)
}
/* Expand SSE sequence for computing trunc from OPERAND1 storing
- into OPERAND0. */
+ into OPERAND0 without relying on DImode truncation via cvttsd2siq
+ that is only available on 64bit targets. */
void
ix86_expand_truncdf_32 (rtx operand0, rtx operand1)
{
@@ -16201,8 +16132,8 @@ ix86_expand_truncdf_32 (rtx operand0, rtx operand1)
emit_move_insn (operand0, res);
}
-/* Expand SSE sequence for computing round from OPERAND1 storing
- into OPERAND0. */
+/* Expand SSE sequence for computing round
+ from OPERAND1 storing into OPERAND0. */
void
ix86_expand_round (rtx operand0, rtx operand1)
{
@@ -16251,6 +16182,77 @@ ix86_expand_round (rtx operand0, rtx operand1)
emit_move_insn (operand0, res);
}
+/* Expand SSE sequence for computing round from OPERAND1 storing
+ into OPERAND0 without relying on DImode truncation via cvttsd2siq
+ that is only available on 64bit targets. */
+void
+ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
+{
+ /* C code for the stuff we expand below.
+ double xa = fabs (x), xa2, x2;
+ if (!isless (xa, TWO52))
+ return x;
+ Using the absolute value and copying back sign makes
+ -0.0 -> -0.0 correct.
+ xa2 = xa + TWO52 - TWO52;
+ Compensate.
+ dxa = xa2 - xa;
+ if (dxa <= -0.5)
+ xa2 += 1;
+ else if (dxa > 0.5)
+ xa2 -= 1;
+ x2 = copysign (xa2, x);
+ return x2;
+ */
+ machine_mode mode = GET_MODE (operand0);
+ rtx xa, xa2, dxa, TWO52, tmp, half, mhalf, one, res, mask;
+ rtx_code_label *label;
+
+ TWO52 = ix86_gen_TWO52 (mode);
+
+ /* Temporary for holding the result, initialized to the input
+ operand to ease control flow. */
+ res = gen_reg_rtx (mode);
+ emit_move_insn (res, operand1);
+
+ /* xa = abs (operand1) */
+ xa = ix86_expand_sse_fabs (res, &mask);
+
+ /* if (!isless (xa, TWO52)) goto label; */
+ label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
+
+ /* xa2 = xa + TWO52 - TWO52; */
+ xa2 = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
+ xa2 = expand_simple_binop (mode, MINUS, xa2, TWO52, xa2, 0, OPTAB_DIRECT);
+
+ /* dxa = xa2 - xa; */
+ dxa = expand_simple_binop (mode, MINUS, xa2, xa, NULL_RTX, 0, OPTAB_DIRECT);
+
+ /* generate 0.5, 1.0 and -0.5 */
+ half = force_reg (mode, const_double_from_real_value (dconsthalf, mode));
+ one = expand_simple_binop (mode, PLUS, half, half, NULL_RTX, 0, OPTAB_DIRECT);
+ mhalf = expand_simple_binop (mode, MINUS, half, one, NULL_RTX,
+ 0, OPTAB_DIRECT);
+
+ /* Compensate. */
+ /* xa2 = xa2 - (dxa > 0.5 ? 1 : 0) */
+ tmp = ix86_expand_sse_compare_mask (UNGT, dxa, half, false);
+ emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
+ xa2 = expand_simple_binop (mode, MINUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
+ /* xa2 = xa2 + (dxa <= -0.5 ? 1 : 0) */
+ tmp = ix86_expand_sse_compare_mask (UNGE, mhalf, dxa, false);
+ emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
+ xa2 = expand_simple_binop (mode, PLUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
+
+ /* res = copysign (xa2, operand1) */
+ ix86_sse_copysign_to_positive (res, xa2, force_reg (mode, operand1), mask);
+
+ emit_label (label);
+ LABEL_NUSES (label) = 1;
+
+ emit_move_insn (operand0, res);
+}
+
/* Expand SSE sequence for computing round
from OP1 storing into OP0 using sse4 round insn. */
void
diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c
index 9b297bac191..4781a33a545 100644
--- a/gcc/config/i386/i386-features.c
+++ b/gcc/config/i386/i386-features.c
@@ -1757,6 +1757,68 @@ convert_scalars_to_vector (bool timode_p)
return 0;
}
+/* Modify the vzeroupper pattern in INSN so that it describes the effect
+ that the instruction has on the SSE registers. LIVE_REGS are the set
+ of registers that are live across the instruction.
+
+ For a live register R we use:
+
+ (set (reg:V2DF R) (reg:V2DF R))
+
+ which preserves the low 128 bits but clobbers the upper bits.
+ For a dead register we just use:
+
+ (clobber (reg:V2DF R))
+
+ which invalidates any previous contents of R and stops R from becoming
+ live across the vzeroupper in future. */
+
+static void
+ix86_add_reg_usage_to_vzeroupper (rtx_insn *insn, bitmap live_regs)
+{
+ rtx pattern = PATTERN (insn);
+ unsigned int nregs = TARGET_64BIT ? 16 : 8;
+ rtvec vec = rtvec_alloc (nregs + 1);
+ RTVEC_ELT (vec, 0) = XVECEXP (pattern, 0, 0);
+ for (unsigned int i = 0; i < nregs; ++i)
+ {
+ unsigned int regno = GET_SSE_REGNO (i);
+ rtx reg = gen_rtx_REG (V2DImode, regno);
+ if (bitmap_bit_p (live_regs, regno))
+ RTVEC_ELT (vec, i + 1) = gen_rtx_SET (reg, reg);
+ else
+ RTVEC_ELT (vec, i + 1) = gen_rtx_CLOBBER (VOIDmode, reg);
+ }
+ XVEC (pattern, 0) = vec;
+ df_insn_rescan (insn);
+}
+
+/* Walk the vzeroupper instructions in the function and annotate them
+ with the effect that they have on the SSE registers. */
+
+static void
+ix86_add_reg_usage_to_vzerouppers (void)
+{
+ basic_block bb;
+ rtx_insn *insn;
+ auto_bitmap live_regs;
+
+ df_analyze ();
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ bitmap_copy (live_regs, df_get_live_out (bb));
+ df_simulate_initialize_backwards (bb, live_regs);
+ FOR_BB_INSNS_REVERSE (bb, insn)
+ {
+ if (!NONDEBUG_INSN_P (insn))
+ continue;
+ if (vzeroupper_pattern (PATTERN (insn), VOIDmode))
+ ix86_add_reg_usage_to_vzeroupper (insn, live_regs);
+ df_simulate_one_insn_backwards (bb, insn, live_regs);
+ }
+ }
+}
+
static unsigned int
rest_of_handle_insert_vzeroupper (void)
{
@@ -1773,6 +1835,7 @@ rest_of_handle_insert_vzeroupper (void)
/* Call optimize_mode_switching. */
g->get_passes ()->execute_pass_mode_switching ();
+ ix86_add_reg_usage_to_vzerouppers ();
return 0;
}
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 4d6e76d5580..c07dfe50855 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -193,11 +193,11 @@ extern void ix86_expand_lfloorceil (rtx, rtx, bool);
extern void ix86_expand_rint (rtx, rtx);
extern void ix86_expand_floorceil (rtx, rtx, bool);
extern void ix86_expand_floorceildf_32 (rtx, rtx, bool);
-extern void ix86_expand_round_sse4 (rtx, rtx);
-extern void ix86_expand_round (rtx, rtx);
-extern void ix86_expand_rounddf_32 (rtx, rtx);
extern void ix86_expand_trunc (rtx, rtx);
extern void ix86_expand_truncdf_32 (rtx, rtx);
+extern void ix86_expand_round (rtx, rtx);
+extern void ix86_expand_rounddf_32 (rtx, rtx);
+extern void ix86_expand_round_sse4 (rtx, rtx);
extern void ix86_expand_vecop_qihi (enum rtx_code, rtx, rtx, rtx);
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 72f8e7eae3c..31f1ceabc3a 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -1441,8 +1441,9 @@
;; return true if OP is a vzeroupper pattern.
(define_predicate "vzeroupper_pattern"
- (and (match_code "unspec_volatile")
- (match_test "XINT (op, 1) == UNSPECV_VZEROUPPER")))
+ (and (match_code "parallel")
+ (match_code "unspec_volatile" "a")
+ (match_test "XINT (XVECEXP (op, 0, 0), 1) == UNSPECV_VZEROUPPER")))
;; Return true if OP is an addsub vec_merge operation
(define_predicate "addsub_vm_operator"
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index c7f539fb88f..07922a1bf97 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -19622,9 +19622,16 @@
(set_attr "mode" "OI")])
;; Clear the upper 128bits of AVX registers, equivalent to a NOP
-;; if the upper 128bits are unused.
-(define_insn "avx_vzeroupper"
- [(unspec_volatile [(const_int 0)] UNSPECV_VZEROUPPER)]
+;; if the upper 128bits are unused. Initially we expand the instructions
+;; as though they had no effect on the SSE registers, but later add SETs and
+;; CLOBBERs to the PARALLEL to model the real effect.
+(define_expand "avx_vzeroupper"
+ [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_VZEROUPPER)])]
+ "TARGET_AVX")
+
+(define_insn "*avx_vzeroupper"
+ [(match_parallel 0 "vzeroupper_pattern"
+ [(unspec_volatile [(const_int 0)] UNSPECV_VZEROUPPER)])]
"TARGET_AVX"
"vzeroupper"
[(set_attr "type" "sse")
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 648d95f3808..e7c22123ed5 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -4862,7 +4862,7 @@ mips_split_move (rtx dest, rtx src, enum mips_split_type split_type, rtx insn_)
{
rtx tmp = XEXP (src, 0);
mips_classify_address (&addr, tmp, GET_MODE (tmp), true);
- if (addr.reg && REGNO (addr.reg) != REGNO (dest))
+ if (addr.reg && !reg_overlap_mentioned_p (dest, addr.reg))
validate_change (next, &SET_SRC (set), src, false);
}
else
diff --git a/gcc/config/msp430/constraints.md b/gcc/config/msp430/constraints.md
index 7ef249d4ac2..4422b2b6454 100644
--- a/gcc/config/msp430/constraints.md
+++ b/gcc/config/msp430/constraints.md
@@ -69,9 +69,11 @@
;; These are memory references that are safe to use without the X suffix,
-;; because we know/assume they need not index across the 64k boundary.
+;; because we know/assume they need not index across the 64K boundary.
+;; Note that for a PSImode memory operand, we always need to use the X suffix,
+;; regardless of what this constraint decides.
(define_constraint "Ys"
- "Memory reference, stack only."
+ "Memory reference, indexed or indirect register addressing modes."
(and (match_code "mem")
(ior
(and (match_code "plus" "0")
@@ -93,3 +95,7 @@
(match_test ("REGNO (XEXP (XEXP (op, 0), 0)) != SP_REGNO")))
))))
+(define_constraint "Yx"
+ "Memory reference, in lower memory below address 0x10000."
+ (and (match_code "mem")
+ (match_test "msp430_op_not_in_high_mem (op)")))
diff --git a/gcc/config/msp430/driver-msp430.c b/gcc/config/msp430/driver-msp430.c
index 0a3d1e14c0a..c37b169ff8b 100644
--- a/gcc/config/msp430/driver-msp430.c
+++ b/gcc/config/msp430/driver-msp430.c
@@ -149,3 +149,16 @@ msp430_select_hwmult_lib (int argc ATTRIBUTE_UNUSED,
return "-lmul_none";
}
+
+/* Spec function. Propagate -m{code,data}-region= to the linker, unless the
+ lower region has been specified without -muse-lower-region-prefix also being
+ used. */
+const char *
+msp430_propagate_region_opt (int argc, const char **argv)
+{
+ if (strcmp (argv[0], "lower") != 0)
+ return argv[0];
+ else if ((argc == 2) && (strcmp (argv[1], "-muse-lower-region-prefix") == 0))
+ return argv[0]; /* argv[0] == "lower". */
+ return "none";
+}
diff --git a/gcc/config/msp430/msp430-protos.h b/gcc/config/msp430/msp430-protos.h
index 267b6f59471..37ca48297ac 100644
--- a/gcc/config/msp430/msp430-protos.h
+++ b/gcc/config/msp430/msp430-protos.h
@@ -44,8 +44,10 @@ void msp430_output_labelref (FILE *, const char *);
void msp430_register_pragmas (void);
rtx msp430_return_addr_rtx (int);
void msp430_split_movsi (rtx *);
+int msp430_split_addsi (rtx *);
void msp430_start_function (FILE *, const char *, tree);
rtx msp430_subreg (machine_mode, rtx, machine_mode, int);
bool msp430_use_f5_series_hwmult (void);
+bool msp430_op_not_in_high_mem (rtx op);
#endif /* GCC_MSP430_PROTOS_H */
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 64308239593..ae763faada3 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -35,6 +35,7 @@
#include "tm_p.h"
#include "regs.h"
#include "emit-rtl.h"
+#include "varasm.h"
#include "diagnostic-core.h"
#include "fold-const.h"
#include "stor-layout.h"
@@ -82,7 +83,7 @@ struct GTY(()) machine_function
};
/* This is our init_machine_status, as set in
- msp_option_override. */
+ msp430_option_override. */
static struct machine_function *
msp430_init_machine_status (void)
{
@@ -263,9 +264,6 @@ msp430_option_override (void)
else if (!TARGET_LARGE && msp430_code_region == MSP430_REGION_UPPER)
error ("%<-mcode-region=upper%> requires the large memory model "
"(%<-mlarge%>)");
- else if (!TARGET_LARGE && msp430_code_region == MSP430_REGION_LOWER)
- error ("%<-mcode-region=lower%> requires the large memory model "
- "(%<-mlarge%>)");
if (!TARGET_LARGE && msp430_data_region == MSP430_REGION_EITHER)
error ("%<-mdata-region=either%> requires the large memory model "
@@ -273,10 +271,6 @@ msp430_option_override (void)
else if (!TARGET_LARGE && msp430_data_region == MSP430_REGION_UPPER)
error ("%<-mdata-region=upper%> requires the large memory model "
"(%<-mlarge%>)");
- else if (!TARGET_LARGE && msp430_data_region == MSP430_REGION_LOWER)
- error ("%<-mdata-region=lower%> requires the large memory model "
- "(%<-mlarge%>)");
-
if (flag_exceptions || flag_non_call_exceptions
|| flag_unwind_tables || flag_asynchronous_unwind_tables)
@@ -1386,7 +1380,7 @@ msp430_section_attr (tree * node,
if (has_attr (ATTR_NOINIT, *node))
message = G_("ignoring attribute %qE because it conflicts with "
"attribute %<noinit%>");
- else if (has_attr ("section", *node))
+ else if (has_attr ("section", *node) && !TREE_NAME_EQ (name, "lower"))
message = G_("ignoring attribute %qE because it conflicts with "
"attribute %<section%>");
/* It does not make sense to use upper/lower/either attributes without
@@ -1564,12 +1558,14 @@ msp430_handle_generic_attribute (tree *node,
{
const char *message = NULL;
+ /* The front end has set up an exclusion between the "noinit" and "section"
+ attributes. */
if (!(TREE_NAME_EQ (name, ATTR_NOINIT) || TREE_NAME_EQ (name, "section")))
return NULL_TREE;
- /* The front end has set up an exclusion between the "noinit" and "section"
- attributes. */
- if (has_attr (ATTR_LOWER, *node))
+ /* We allow the "lower" attribute to be used on variables with the "section"
+ attribute. */
+ if (has_attr (ATTR_LOWER, *node) && !TREE_NAME_EQ (name, "section"))
message = G_("ignoring attribute %qE because it conflicts with "
"attribute %<lower%>");
else if (has_attr (ATTR_UPPER, *node))
@@ -1591,6 +1587,55 @@ msp430_handle_generic_attribute (tree *node,
return NULL_TREE;
}
+/* Given a non-automatic VAR_DECL which can possibly have a section, return
+ true if the variable will definitely be placed in the lower memory
+ region (below address 0x10000). */
+static bool
+msp430_var_in_low_mem (tree decl)
+{
+ gcc_assert (VAR_P (decl));
+
+ /* "noinit" variables are always placed in the lower memory region. */
+ if (has_attr (ATTR_UPPER, decl)
+ || has_attr (ATTR_EITHER, decl)
+ || has_attr (ATTR_PERSIST, decl)
+ /* Unless the variable is marked with the lower or noinit attribute, we
+ cannot assume that it is in the lower region if it is marked with the
+ section attribute or -mdata-region={upper,either,none} have been
+ passed.
+ The noinit and section attributes conflict. */
+ || (!has_attr (ATTR_LOWER, decl) && !has_attr (ATTR_NOINIT, decl)
+ && (has_attr ("section", decl)
+ || msp430_data_region == MSP430_REGION_UPPER
+ || msp430_data_region == MSP430_REGION_EITHER
+ || msp430_data_region == MSP430_REGION_ANY)))
+ return false;
+ return true;
+}
+
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO msp430_encode_section_info
+
+/* Encode whether a SYMBOL_REF is definitely in the lower memory region. */
+static void
+msp430_encode_section_info (tree decl, rtx rtl, int first)
+{
+ rtx symbol;
+ default_encode_section_info (decl, rtl, first);
+
+ /* Careful not to prod global register variables. */
+ if (!MEM_P (rtl))
+ return;
+ symbol = XEXP (rtl, 0);
+ if (GET_CODE (symbol) != SYMBOL_REF)
+ return;
+
+ if (VAR_P (decl)
+ && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
+ && msp430_var_in_low_mem (decl))
+ SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOW_MEM;
+}
+
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
@@ -1744,15 +1789,17 @@ gen_prefix (tree decl)
if (has_section_name (".lowtext", decl))
return NULL;
- /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
+ /* Memory regions require the large memory model. */
+ if (!TARGET_LARGE)
+ return NULL;
+
+ /* Note that we always apply the lower prefix when the attribute has been
+ used. But we only apply the lower prefix when the lower region has been
+ specified by a command line option if -muse-lower-region-prefix has also
+ been passed. */
if (has_attr (ATTR_LOWER, decl))
return lower_prefix;
- /* If we are compiling for the MSP430 then we do not support the upper
- region. */
- if (! msp430x)
- return NULL;
-
if (has_attr (ATTR_UPPER, decl))
return upper_prefix;
@@ -1761,7 +1808,8 @@ gen_prefix (tree decl)
if (TREE_CODE (decl) == FUNCTION_DECL)
{
- if (msp430_code_region == MSP430_REGION_LOWER)
+ if ((msp430_code_region == MSP430_REGION_LOWER)
+ && TARGET_USE_LOWER_REGION_PREFIX)
return lower_prefix;
if (msp430_code_region == MSP430_REGION_UPPER)
@@ -1772,7 +1820,8 @@ gen_prefix (tree decl)
}
else
{
- if (msp430_data_region == MSP430_REGION_LOWER)
+ if ((msp430_data_region == MSP430_REGION_LOWER)
+ && TARGET_USE_LOWER_REGION_PREFIX)
return lower_prefix;
if (msp430_data_region == MSP430_REGION_UPPER)
@@ -1966,7 +2015,6 @@ msp430_unique_section (tree decl, int reloc)
/* Emit a declaration of a common symbol.
If a data region is in use then put the symbol into the
equivalent .bss section instead. */
-
void
msp430_output_aligned_decl_common (FILE * stream,
const tree decl,
@@ -1976,7 +2024,9 @@ msp430_output_aligned_decl_common (FILE * stream,
{
/* Only emit a common symbol if the variable does not have a specific section
assigned. */
- if (msp430_data_region == MSP430_REGION_ANY
+ if ((msp430_data_region == MSP430_REGION_ANY
+ || ((msp430_data_region == MSP430_REGION_LOWER)
+ && !TARGET_USE_LOWER_REGION_PREFIX))
&& !(decl != NULL_TREE && DECL_SECTION_NAME (decl))
&& !has_attr (ATTR_EITHER, decl)
&& !has_attr (ATTR_LOWER, decl)
@@ -2021,6 +2071,80 @@ msp430_output_aligned_decl_common (FILE * stream,
}
}
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END msp430_file_end
+
+/* Emit MSPABI and GNU object attributes.
+ Tags and values for MSPABI attributes are:
+ OFBA_MSPABI_Tag_ISA 4
+ MSP430 1
+ MSP430X 2
+ OFBA_MSPABI_Tag_Code_Model 6
+ Small 1
+ Large 2
+ OFBA_MSPABI_Tag_Data_Model 8
+ Small 1
+ Large 2
+ Restricted 3 (Unused by GNU)
+ OFBA_MSPABI_Tag_enum_size 10 (Unused by GNU)
+ Note that Code_Model and Data_Model are always equal for GNU.
+ We define a new .gnu_attribute to keep track of the data region used.
+ Tag_GNU_MSP430_Data_Region 4
+ LOWER 1
+ ANY 2
+ See binutils-gdb/include/elf/msp430.h for the full details. */
+static void
+msp430_file_end (void)
+{
+#ifdef HAVE_AS_GNU_ATTRIBUTE
+ /* Enum for tag names. */
+ enum
+ {
+ OFBA_MSPABI_Tag_ISA = 4,
+ OFBA_MSPABI_Tag_Code_Model = 6,
+ OFBA_MSPABI_Tag_Data_Model = 8,
+ Tag_GNU_MSP430_Data_Region = 4
+ };
+ /* Enum for tag values. */
+ enum
+ {
+ OFBA_MSPABI_Val_ISA_MSP430 = 1,
+ OFBA_MSPABI_Val_ISA_MSP430X = 2,
+ OFBA_MSPABI_Val_Model_Small = 1,
+ OFBA_MSPABI_Val_Model_Large = 2,
+ Tag_GNU_MSP430_Data_Region_Lower = 1,
+ Tag_GNU_MSP430_Data_Region_Any = 2
+ };
+ /* .mspabi_attribute is a GNU assembler directive only. The assembler will
+ construct a .MSP430.attributes section based on the options it is invoked
+ with. The values it reads from these directives are used for validating
+ those options. */
+ const char *msp430_attr = ".mspabi_attribute";
+ const char *gnu_attr = ".gnu_attribute";
+
+ /* Emit .mspabi_attribute directive for OFBA_MSPABI_Tag_ISA. */
+ fprintf (asm_out_file, "\t%s %d, %d\n", msp430_attr, OFBA_MSPABI_Tag_ISA,
+ msp430x ? OFBA_MSPABI_Val_ISA_MSP430X : OFBA_MSPABI_Val_ISA_MSP430);
+ /* Emit .mspabi_attribute directive for OFBA_MSPABI_Tag_Code_Model. */
+ fprintf (asm_out_file, "\t%s %d, %d\n", msp430_attr,
+ OFBA_MSPABI_Tag_Code_Model,
+ TARGET_LARGE ? OFBA_MSPABI_Val_Model_Large
+ : OFBA_MSPABI_Val_Model_Small);
+ /* Emit .mspabi_attribute directive for OFBA_MSPABI_Tag_Data_Model. */
+ fprintf (asm_out_file, "\t%s %d, %d\n", msp430_attr,
+ OFBA_MSPABI_Tag_Data_Model,
+ TARGET_LARGE ? OFBA_MSPABI_Val_Model_Large
+ : OFBA_MSPABI_Val_Model_Small);
+#ifdef HAVE_AS_MSPABI_ATTRIBUTE
+ /* Emit .gnu_attribute directive for Tag_GNU_MSP430_Data_Region. */
+ fprintf (asm_out_file, "\t%s %d, %d\n", gnu_attr, Tag_GNU_MSP430_Data_Region,
+ msp430_data_region == MSP430_REGION_LOWER
+ ? Tag_GNU_MSP430_Data_Region_Lower
+ : Tag_GNU_MSP430_Data_Region_Any);
+#endif
+#endif
+}
+
bool
msp430_do_not_relax_short_jumps (void)
{
@@ -2031,9 +2155,7 @@ msp430_do_not_relax_short_jumps (void)
end up in a low section. */
return
msp430_code_region == MSP430_REGION_EITHER
- || msp430_code_region == MSP430_REGION_LOWER
- || has_attr (ATTR_EITHER, current_function_decl)
- || has_attr (ATTR_LOWER, current_function_decl);
+ || has_attr (ATTR_EITHER, current_function_decl);
}
enum msp430_builtin
@@ -2484,7 +2606,7 @@ msp430_expand_epilogue (int is_eh)
else if (is_reentrant_func ())
emit_insn (gen_enable_interrupts ());
- emit_jump_insn (gen_msp_return ());
+ emit_jump_insn (gen_msp430_return ());
}
/* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
@@ -2721,6 +2843,29 @@ msp430_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
return rv;
}
+int
+msp430_split_addsi (rtx *operands)
+{
+ operands[3] = msp430_subreg (HImode, operands[0], SImode, 0);
+ operands[4] = msp430_subreg (HImode, operands[1], SImode, 0);
+ operands[5] = msp430_subreg (HImode, operands[2], SImode, 0);
+ operands[6] = msp430_subreg (HImode, operands[0], SImode, 2);
+ operands[7] = msp430_subreg (HImode, operands[1], SImode, 2);
+ operands[8] = msp430_subreg (HImode, operands[2], SImode, 2);
+
+ /* BZ 64160: Do not use this splitter when the dest partially overlaps the
+ source. */
+ if (reg_overlap_mentioned_p (operands[3], operands[7])
+ || reg_overlap_mentioned_p (operands[3], operands[8]))
+ return 1;
+
+ if (GET_CODE (operands[5]) == CONST_INT)
+ operands[9] = GEN_INT (INTVAL (operands[5]) & 0xffff);
+ else
+ operands[9] = gen_rtx_ZERO_EXTEND (SImode, operands[5]);
+ return 0;
+}
+
/* Called by movsi_x to generate the HImode operands. */
void
msp430_split_movsi (rtx *operands)
@@ -3074,6 +3219,36 @@ msp430_print_operand_addr (FILE * file, machine_mode /*mode*/, rtx addr)
msp430_print_operand_raw (file, addr);
}
+/* Determine whether an RTX is definitely not a MEM referencing an address in
+ the upper memory region. Returns true if we've decided the address will be
+ in the lower memory region, or the RTX is not a MEM. Returns false
+ otherwise. */
+bool
+msp430_op_not_in_high_mem (rtx op)
+{
+ rtx op0;
+
+ if (!TARGET_LARGE || !MEM_P (op))
+ return true;
+
+ op0 = XEXP (op, 0);
+
+ if (SYMBOL_REF_P (op0) && (SYMBOL_REF_FLAGS (op0) & SYMBOL_FLAG_LOW_MEM))
+ /* msp430_encode_section_info decided this mem will be in lower
+ memory. */
+ return true;
+
+ /* Catch (mem (const (plus ((symbol_ref) (const_int))))) e.g. &addr+2. */
+ if ((GET_CODE (op0) == CONST)
+ && (GET_CODE (XEXP (op0, 0)) == PLUS)
+ && (SYMBOL_REF_P (XEXP (XEXP (op0, 0), 0)))
+ && (SYMBOL_REF_FLAGS (XEXP (XEXP (op0, 0), 0)) & SYMBOL_FLAG_LOW_MEM))
+ return true;
+
+ /* Return false when undecided. */
+ return false;
+}
+
#undef TARGET_PRINT_OPERAND
#define TARGET_PRINT_OPERAND msp430_print_operand
@@ -3245,15 +3420,21 @@ msp430_print_operand (FILE * file, rtx op, int letter)
case 'X':
/* This is used to turn, for example, an ADD opcode into an ADDX
- opcode when we're using 20-bit addresses. */
- if (TARGET_LARGE || GET_MODE (op) == PSImode)
+ opcode when we're using 20-bit addresses.
+ This can be used for insns which have only one operand which might be
+ a mem.
+ If an insn has two different operands which could be memory operands,
+ then the "Yx" constraint must be used to determine if the X suffix is
+ required by checking both operands. */
+ if (GET_MODE (op) == PSImode
+ || !msp430_op_not_in_high_mem (op))
fprintf (file, "X");
- /* We don't care which operand we use, but we want 'X' in the MD
- file, so we do it this way. */
return;
case 'x':
- /* Similarly, but only for PSImodes. BIC, for example, needs this. */
+ /* Similarly, but only for PSImodes. BIC, and other insn patterns using
+ the QHI mode iterator (which includes, QI, HI, and PSImode) use
+ this. */
if (GET_MODE (op) == PSImode)
fprintf (file, "X");
return;
diff --git a/gcc/config/msp430/msp430.h b/gcc/config/msp430/msp430.h
index 3449bd429ae..f885de2bb2f 100644
--- a/gcc/config/msp430/msp430.h
+++ b/gcc/config/msp430/msp430.h
@@ -71,7 +71,10 @@ extern bool msp430x;
is enabled (the GDB testsuite relies upon unused entities not being
deleted). */
#define LINK_SPEC "%{mrelax:--relax} %{mlarge:%{!r:%{!g:--gc-sections}}} " \
- "%{mcode-region=*:--code-region=%*} %{mdata-region=*:--data-region=%*}"
+ "%{mcode-region=*:--code-region=%:" \
+ "msp430_propagate_region_opt(%* %{muse-lower-region-prefix})} " \
+ "%{mdata-region=*:--data-region=%:" \
+ "msp430_propagate_region_opt(%* %{muse-lower-region-prefix})} " \
#define DRIVER_SELF_SPECS \
" %{!mlarge:%{mcode-region=*:%{mdata-region=*:%e-mcode-region and " \
@@ -90,12 +93,16 @@ extern const char * msp430_select_hwmult_lib (int, const char **);
extern const char * msp430_select_cpu (int, const char **);
extern const char * msp430_set_driver_var (int, const char **);
extern const char * msp430_check_path_for_devices (int, const char **);
+extern const char *msp430_propagate_region_opt (int, const char **);
+/* There must be a trailing comma after the last item, see gcc.c
+ "static_spec_functions". */
# define EXTRA_SPEC_FUNCTIONS \
{ "msp430_hwmult_lib", msp430_select_hwmult_lib }, \
{ "msp430_select_cpu", msp430_select_cpu }, \
{ "msp430_set_driver_var", msp430_set_driver_var }, \
- { "msp430_check_path_for_devices", msp430_check_path_for_devices },
+ { "msp430_check_path_for_devices", msp430_check_path_for_devices }, \
+ { "msp430_propagate_region_opt", msp430_propagate_region_opt },
/* Specify the libraries to include on the linker command line.
@@ -482,3 +489,5 @@ typedef struct
#define ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN) \
msp430_output_aligned_decl_common ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
+
+#define SYMBOL_FLAG_LOW_MEM (SYMBOL_FLAG_MACH_DEP << 0)
diff --git a/gcc/config/msp430/msp430.md b/gcc/config/msp430/msp430.md
index f6d688950cb..ebd9c85fbb6 100644
--- a/gcc/config/msp430/msp430.md
+++ b/gcc/config/msp430/msp430.md
@@ -183,29 +183,29 @@
)
(define_insn "movqi_topbyte"
- [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=r")
- (subreg:QI (match_operand:PSI 1 "msp_general_operand" "r") 2))]
+ [(set (match_operand:QI 0 "msp430_nonimmediate_operand" "=r")
+ (subreg:QI (match_operand:PSI 1 "msp430_general_operand" "r") 2))]
"msp430x"
"PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0"
)
(define_insn "movqi"
- [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYs,rm")
- (match_operand:QI 1 "msp_general_operand" "riYs,rmi"))]
+ [(set (match_operand:QI 0 "msp430_nonimmediate_operand" "=rYsYx,rm")
+ (match_operand:QI 1 "msp430_general_operand" "riYsYx,rmi"))]
""
"@
MOV.B\t%1, %0
- MOV%X0.B\t%1, %0"
+ MOVX.B\t%1, %0"
)
(define_insn "movhi"
- [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rYs,rm")
- (match_operand:HI 1 "msp_general_operand" "N,riYs,rmi"))]
+ [(set (match_operand:HI 0 "msp430_nonimmediate_operand" "=r,rYsYx,rm")
+ (match_operand:HI 1 "msp430_general_operand" "N,riYsYx,rmi"))]
""
"@
MOV.B\t%1, %0
MOV.W\t%1, %0
- MOV%X0.W\t%1, %0"
+ MOVX.W\t%1, %0"
)
(define_expand "movsi"
@@ -241,10 +241,10 @@
"msp430_split_movsi (operands);"
)
-;; Some MOVX.A cases can be done with MOVA, this is only a few of them.
+;; FIXME: Some MOVX.A cases can be done with MOVA, this is only a few of them.
(define_insn "movpsi"
- [(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,r,r,Ya,rm")
- (match_operand:PSI 1 "msp_general_operand" "N,O,riYa,r,rmi"))]
+ [(set (match_operand:PSI 0 "msp430_nonimmediate_operand" "=r,r,r,Ya,rm")
+ (match_operand:PSI 1 "msp430_general_operand" "N,O,riYa,r,rmi"))]
""
"@
MOV.B\t%1, %0
@@ -279,9 +279,9 @@
;; Math
(define_insn "addpsi3"
- [(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,rm")
- (plus:PSI (match_operand:PSI 1 "msp_nonimmediate_operand" "%0,0")
- (match_operand:PSI 2 "msp_general_operand" "rLs,rmi")))]
+ [(set (match_operand:PSI 0 "msp430_nonimmediate_operand" "=r,rm")
+ (plus:PSI (match_operand:PSI 1 "msp430_nonimmediate_operand" "%0,0")
+ (match_operand:PSI 2 "msp430_general_operand" "rLs,rmi")))]
""
"@
ADDA\t%2, %0
@@ -289,23 +289,23 @@
)
(define_insn "addqi3"
- [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYs,rm")
- (plus:QI (match_operand:QI 1 "msp_nonimmediate_operand" "%0,0")
- (match_operand:QI 2 "msp_general_operand" "riYs,rmi")))]
+ [(set (match_operand:QI 0 "msp430_nonimmediate_operand" "=rYsYx,rm")
+ (plus:QI (match_operand:QI 1 "msp430_nonimmediate_operand" "%0,0")
+ (match_operand:QI 2 "msp430_general_operand" "riYsYx,rmi")))]
""
"@
ADD.B\t%2, %0
- ADD%X0.B\t%2, %0"
+ ADDX.B\t%2, %0"
)
(define_insn "addhi3"
- [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rYs,rm")
- (plus:HI (match_operand:HI 1 "msp_nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "msp_general_operand" "riYs,rmi")))]
+ [(set (match_operand:HI 0 "msp430_nonimmediate_operand" "=rYsYx,rm")
+ (plus:HI (match_operand:HI 1 "msp430_nonimmediate_operand" "%0,0")
+ (match_operand:HI 2 "msp430_general_operand" "riYsYx,rmi")))]
""
"@
ADD.W\t%2, %0
- ADD%X0.W\t%2, %0"
+ ADDX.W\t%2, %0"
)
; This pattern is needed in order to avoid reload problems.
@@ -317,17 +317,17 @@
(plus:SI (match_operand:SI 1 "register_operand" "0")
(match_operand 2 "general_operand" "rmi")))]
""
- "ADD.W\t%L2, %L0 { ADDC.W\t%H2, %H0 { PUSH.W\t%H0 { PUSH.W\t%L0 { POPM.A\t#1, %0"
+ "ADD%X2.W\t%L2, %L0 { ADDC%X2.W\t%H2, %H0 { PUSH.W\t%H0 { PUSH.W\t%L0 { POPM.A\t#1, %0"
)
(define_insn "addsi3"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,rm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=&rYsYx,rm")
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "r,mi")))]
+ (match_operand:SI 2 "general_operand" "rYsYxi,mi")))]
""
"@
ADD\t%L2, %L0 { ADDC\t%H2, %H0
- ADD%X0\t%L2, %L0 { ADDC%X0\t%H2, %H0"
+ ADDX\t%L2, %L0 { ADDCX\t%H2, %H0"
)
; Version of addhi that exposes the carry operations, for SImode adds.
@@ -358,9 +358,9 @@
; that are not single_set() very well.
(define_insn "addhi3_cy"
- [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rm")
- (plus:HI (match_operand:HI 1 "msp_nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "msp_nonimmediate_operand" "r,rm")))
+ [(set (match_operand:HI 0 "msp430_nonimmediate_operand" "=rYsYx,rm")
+ (plus:HI (match_operand:HI 1 "msp430_nonimmediate_operand" "%0,0")
+ (match_operand:HI 2 "msp430_nonimmediate_operand" "rYsYxi,rm")))
(set (reg:BI CARRY)
(truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
(zero_extend:SI (match_dup 2)))
@@ -369,7 +369,7 @@
""
"@
ADD\t%2, %1 ; cy
- ADD%X0\t%2, %1 ; cy"
+ ADDX\t%2, %1 ; cy"
)
(define_insn "addhi3_cy_i"
@@ -389,15 +389,15 @@
; Version of addhi that adds the carry, for SImode adds.
(define_insn "addchi4_cy"
- [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rm")
- (plus:HI (plus:HI (match_operand:HI 1 "msp_nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "msp_general_operand" "ri,rmi"))
+ [(set (match_operand:HI 0 "msp430_nonimmediate_operand" "=rYsYx,rm")
+ (plus:HI (plus:HI (match_operand:HI 1 "msp430_nonimmediate_operand" "%0,0")
+ (match_operand:HI 2 "msp430_general_operand" "riYsYx,rmi"))
(zero_extend:HI (reg:BI CARRY))))
]
""
"@
ADDC\t%2, %1
- ADDC%X0\t%2, %1"
+ ADDCX\t%2, %1"
)
; Split an SImode add into two HImode adds, keeping track of the carry
@@ -423,23 +423,9 @@
(zero_extend:HI (reg:BI CARRY))))
]
"
- operands[3] = msp430_subreg (HImode, operands[0], SImode, 0);
- operands[4] = msp430_subreg (HImode, operands[1], SImode, 0);
- operands[5] = msp430_subreg (HImode, operands[2], SImode, 0);
- operands[6] = msp430_subreg (HImode, operands[0], SImode, 2);
- operands[7] = msp430_subreg (HImode, operands[1], SImode, 2);
- operands[8] = msp430_subreg (HImode, operands[2], SImode, 2);
-
- /* BZ 64160: Do not use this splitter when the dest partially overlaps the source. */
- if (reg_overlap_mentioned_p (operands[3], operands[7])
- || reg_overlap_mentioned_p (operands[3], operands[8]))
- FAIL;
-
- if (GET_CODE (operands[5]) == CONST_INT)
- operands[9] = GEN_INT (INTVAL (operands[5]) & 0xffff);
- else
- operands[9] = gen_rtx_ZERO_EXTEND (SImode, operands[5]);
- "
+ if (msp430_split_addsi (operands))
+ FAIL;
+ "
)
@@ -458,41 +444,43 @@
;; Alternatives 2 and 3 are to handle cases generated by reload.
(define_insn "subqi3"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=rYs, rm, &?r, ?&r")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=rYsYx, rm, &?r, ?&r")
(minus:QI (match_operand:QI 1 "general_operand" "0, 0, !r, !i")
- (match_operand:QI 2 "general_operand" " riYs, rmi, rmi, r")))]
+ (match_operand:QI 2 "general_operand" " riYsYx, rmi, rmi, r")))]
""
"@
SUB.B\t%2, %0
- SUB%X0.B\t%2, %0
- MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0
+ SUBX.B\t%2, %0
+ MOV%X2.B\t%1, %0 { SUB%X2.B\t%2, %0
MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0"
)
;; Alternatives 2 and 3 are to handle cases generated by reload.
(define_insn "subhi3"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=rYs, rm, &?r, ?&r")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rYsYx, rm, &?r, ?&r")
(minus:HI (match_operand:HI 1 "general_operand" "0, 0, !r, !i")
- (match_operand:HI 2 "general_operand" " riYs, rmi, rmi, r")))]
+ (match_operand:HI 2 "general_operand" " riYsYx, rmi, rmi, r")))]
""
"@
SUB.W\t%2, %0
- SUB%X0.W\t%2, %0
- MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0
+ SUBX.W\t%2, %0
+ MOV%X2.W\t%1, %0 { SUB%X2.W\t%2, %0
MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0"
)
(define_insn "subsi3"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=&rm")
- (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0")
- (match_operand:SI 2 "general_operand" "rmi")))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=&rYsYx,m")
+ (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
+ (match_operand:SI 2 "general_operand" "riYsYx,mi")))]
""
- "SUB%X0\t%L2, %L0 { SUBC%X0\t%H2, %H0"
+ "@
+ SUB\t%L2, %L0 { SUBC\t%H2, %H0
+ SUBX\t%L2, %L0 { SUBCX\t%H2, %H0"
)
(define_insn "*bic<mode>_cg"
- [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,m")
- (and:QHI (match_operand:QHI 1 "msp_general_operand" "0,0")
+ [(set (match_operand:QHI 0 "msp430_nonimmediate_operand" "=rYs,m")
+ (and:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0")
(match_operand 2 "msp430_inv_constgen_operator" "n,n")))]
""
"@
@@ -501,50 +489,50 @@
)
(define_insn "bic<mode>3"
- [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,rm")
- (and:QHI (not:QHI (match_operand:QHI 1 "msp_general_operand" "rYs,rmn"))
- (match_operand:QHI 2 "msp_nonimmediate_operand" "0,0")))]
+ [(set (match_operand:QHI 0 "msp430_nonimmediate_operand" "=rYsYx,rm")
+ (and:QHI (not:QHI (match_operand:QHI 1 "msp430_general_operand" "rYsYx,rmn"))
+ (match_operand:QHI 2 "msp430_nonimmediate_operand" "0,0")))]
""
"@
BIC%x0%b0\t%1, %0
- BIC%X0%b0\t%1, %0"
+ BICX%b0\t%1, %0"
)
(define_insn "and<mode>3"
- [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=r,rYs,rm")
- (and:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0,0")
- (match_operand:QHI 2 "msp_general_operand" "N,riYs,rmi")))]
+ [(set (match_operand:QHI 0 "msp430_nonimmediate_operand" "=r,rYsYx,rm")
+ (and:QHI (match_operand:QHI 1 "msp430_nonimmediate_operand" "%0,0,0")
+ (match_operand:QHI 2 "msp430_general_operand" "N,riYsYx,rmi")))]
""
"@
AND%x0.B\t%2, %0
AND%x0%b0\t%2, %0
- AND%X0%b0\t%2, %0"
+ ANDX%b0\t%2, %0"
)
(define_insn "ior<mode>3"
- [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,rm")
- (ior:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0")
- (match_operand:QHI 2 "msp_general_operand" "riYs,rmi")))]
+ [(set (match_operand:QHI 0 "msp430_nonimmediate_operand" "=rYsYx,rm")
+ (ior:QHI (match_operand:QHI 1 "msp430_nonimmediate_operand" "%0,0")
+ (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))]
""
"@
BIS%x0%b0\t%2, %0
- BIS%X0%b0\t%2, %0"
+ BISX%b0\t%2, %0"
)
(define_insn "xor<mode>3"
- [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,rm")
- (xor:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0")
- (match_operand:QHI 2 "msp_general_operand" "riYs,rmi")))]
+ [(set (match_operand:QHI 0 "msp430_nonimmediate_operand" "=rYsYx,rm")
+ (xor:QHI (match_operand:QHI 1 "msp430_nonimmediate_operand" "%0,0")
+ (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))]
""
"@
XOR%x0%b0\t%2, %0
- XOR%X0%b0\t%2, %0"
+ XORX%b0\t%2, %0"
)
;; Macro : XOR #~0, %0
(define_insn "one_cmpl<mode>2"
- [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,m")
- (not:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "0,0")))]
+ [(set (match_operand:QHI 0 "msp430_nonimmediate_operand" "=rYs,m")
+ (not:QHI (match_operand:QHI 1 "msp430_nonimmediate_operand" "0,0")))]
""
"@
INV%x0%b0\t%0
@@ -552,8 +540,8 @@
)
(define_insn "extendqihi2"
- [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rYs,m")
- (sign_extend:HI (match_operand:QI 1 "msp_nonimmediate_operand" "0,0")))]
+ [(set (match_operand:HI 0 "msp430_nonimmediate_operand" "=rYs,m")
+ (sign_extend:HI (match_operand:QI 1 "msp430_nonimmediate_operand" "0,0")))]
""
"@
SXT%X0\t%0
@@ -561,13 +549,13 @@
)
(define_insn "zero_extendqihi2"
- [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rYs,r,r,m")
- (zero_extend:HI (match_operand:QI 1 "msp_nonimmediate_operand" "0,rYs,m,0")))]
+ [(set (match_operand:HI 0 "msp430_nonimmediate_operand" "=rYs,r,r,m")
+ (zero_extend:HI (match_operand:QI 1 "msp430_nonimmediate_operand" "0,rYs,m,0")))]
""
"@
AND\t#0xff, %0
MOV.B\t%1, %0
- MOV%X0.B\t%1, %0
+ MOV%X1.B\t%1, %0
AND%X0\t#0xff, %0"
)
@@ -583,8 +571,8 @@
)
(define_insn "zero_extendhipsi2"
- [(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,m")
- (zero_extend:PSI (match_operand:HI 1 "msp_nonimmediate_operand" "rm,r")))]
+ [(set (match_operand:PSI 0 "msp430_nonimmediate_operand" "=r,m")
+ (zero_extend:PSI (match_operand:HI 1 "msp430_nonimmediate_operand" "rm,r")))]
""
"@
MOVX\t%1, %0
@@ -592,7 +580,7 @@
)
(define_insn "truncpsihi2"
- [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rm")
+ [(set (match_operand:HI 0 "msp430_nonimmediate_operand" "=rm")
(truncate:HI (match_operand:PSI 1 "register_operand" "r")))]
""
"MOVX\t%1, %0"
@@ -621,7 +609,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=r")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
""
- "MOV.B\t%1,%L0 { CLR\t%H0"
+ "MOV%X1.B\t%1,%L0 { CLR\t%H0"
)
(define_insn "zero_extendhisi2"
@@ -629,7 +617,7 @@
(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")))]
""
"@
- MOV.W\t#0,%H0
+ MOV%X0.W\t#0,%H0
MOV.W\t%1,%L0 { MOV.W\t#0,%H0"
)
@@ -782,7 +770,7 @@
(ashift:HI (match_operand:HI 1 "general_operand" "0")
(const_int 1)))]
""
- "RLA.W\t%0" ;; Note - this is a macro for ADD
+ "RLA%X0.W\t%0" ;; Note - this is a macro for ADD
)
(define_insn "430x_shift_left"
@@ -802,7 +790,7 @@
(ashift:SI (match_operand:SI 1 "general_operand" "0")
(const_int 1)))]
""
- "RLA.W\t%L0 { RLC.W\t%H0"
+ "RLA%X0.W\t%L0 { RLC%X0.W\t%H0"
)
(define_insn "slll_2"
@@ -810,7 +798,7 @@
(ashift:SI (match_operand:SI 1 "general_operand" "0")
(const_int 2)))]
""
- "RLA.W\t%L0 { RLC.W\t%H0 { RLA.W\t%L0 { RLC.W\t%H0"
+ "RLA%X0.W\t%L0 { RLC%X0.W\t%H0 { RLA%X0.W\t%L0 { RLC%X0.W\t%H0"
)
(define_expand "ashlsi3"
@@ -863,11 +851,11 @@
)
(define_insn "srai_1"
- [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rm")
- (ashiftrt:HI (match_operand:HI 1 "msp_general_operand" "0")
+ [(set (match_operand:HI 0 "msp430_nonimmediate_operand" "=rm")
+ (ashiftrt:HI (match_operand:HI 1 "msp430_general_operand" "0")
(const_int 1)))]
""
- "RRA.W\t%0"
+ "RRA%X0.W\t%0"
)
(define_insn "430x_arithmetic_shift_right"
@@ -903,7 +891,7 @@
(ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
(const_int 1)))]
""
- "RRA.W\t%H0 { RRC.W\t%L0"
+ "RRA%X0.W\t%H0 { RRC%X0.W\t%L0"
)
(define_insn "sral_2"
@@ -911,7 +899,7 @@
(ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
(const_int 2)))]
""
- "RRA.W\t%H0 { RRC.W\t%L0 { RRA.W\t%H0 { RRC.W\t%L0"
+ "RRA%X0.W\t%H0 { RRC%X0.W\t%L0 { RRA%X0.W\t%H0 { RRC%X0.W\t%L0"
)
(define_expand "ashrsi3"
@@ -968,7 +956,7 @@
(lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
(const_int 1)))]
""
- "CLRC { RRC.W\t%0"
+ "CLRC { RRC%X0.W\t%0"
)
(define_insn "430x_logical_shift_right"
@@ -994,7 +982,7 @@
(lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
(const_int 1)))]
""
- "CLRC { RRC.W\t%H0 { RRC.W\t%L0"
+ "CLRC { RRC%X0.W\t%H0 { RRC%X0.W\t%L0"
)
(define_insn "srll_2x"
@@ -1106,7 +1094,7 @@
"CALL%Q0\t%1"
)
-(define_insn "msp_return"
+(define_insn "msp430_return"
[(return)]
""
{ return msp430_is_interrupt_func () ? "RETI" : (TARGET_LARGE ? "RETA" : "RET"); }
@@ -1188,8 +1176,8 @@
(define_insn "cbranchqi4_real"
[(set (pc) (if_then_else
(match_operator 0 "msp430_cmp_operator"
- [(match_operand:QI 1 "nonimmediate_operand" "rYs,rm")
- (match_operand:QI 2 "general_operand" "rYsi,rmi")])
+ [(match_operand:QI 1 "nonimmediate_operand" "rYsYx,rm")
+ (match_operand:QI 2 "general_operand" "rYsYxi,rmi")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:BI CARRY))
@@ -1197,14 +1185,14 @@
""
"@
CMP.B\t%2, %1 { J%0\t%l3
- CMP%X0.B\t%2, %1 { J%0\t%l3"
+ CMPX.B\t%2, %1 { J%0\t%l3"
)
(define_insn "cbranchhi4_real"
[(set (pc) (if_then_else
(match_operator 0 "msp430_cmp_operator"
- [(match_operand:HI 1 "nonimmediate_operand" "rYs,rm")
- (match_operand:HI 2 "general_operand" "rYsi,rmi")])
+ [(match_operand:HI 1 "nonimmediate_operand" "rYsYx,rm")
+ (match_operand:HI 2 "general_operand" "rYsYxi,rmi")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:BI CARRY))
@@ -1222,12 +1210,12 @@
{
return which_alternative == 0 ?
\"CMP.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\" :
- \"CMP%X0.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\";
+ \"CMPX.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\";
}
return which_alternative == 0 ?
\"CMP.W\t%2, %1 { J%0\t%l3\" :
- \"CMP%X0.W\t%2, %1 { J%0\t%l3\";
+ \"CMPX.W\t%2, %1 { J%0\t%l3\";
"
[(set (attr "length")
(if_then_else
@@ -1257,8 +1245,8 @@
(define_insn "cbranchqi4_reversed"
[(set (pc) (if_then_else
(match_operator 0 "msp430_reversible_cmp_operator"
- [(match_operand:QI 1 "general_operand" "rYsi,rmi")
- (match_operand:QI 2 "general_operand" "rYs,rm")])
+ [(match_operand:QI 1 "general_operand" "rYsYxi,rmi")
+ (match_operand:QI 2 "general_operand" "rYsYx,rm")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:BI CARRY))
@@ -1266,14 +1254,14 @@
""
"@
CMP.B\t%1, %2 { J%R0\t%l3
- CMP%X0.B\t%1, %2 { J%R0\t%l3"
+ CMPX.B\t%1, %2 { J%R0\t%l3"
)
(define_insn "cbranchhi4_reversed"
[(set (pc) (if_then_else
(match_operator 0 "msp430_reversible_cmp_operator"
- [(match_operand:HI 1 "general_operand" "rYsi,rmi")
- (match_operand:HI 2 "general_operand" "rYs,rm")])
+ [(match_operand:HI 1 "general_operand" "rYsYxi,rmi")
+ (match_operand:HI 2 "general_operand" "rYsYx,rm")])
(label_ref (match_operand 3 "" ""))
(pc)))
(clobber (reg:BI CARRY))
@@ -1281,13 +1269,13 @@
""
"@
CMP.W\t%1, %2 { J%R0\t%l3
- CMP%X0.W\t%1, %2 { J%R0\t%l3"
+ CMPX.W\t%1, %2 { J%R0\t%l3"
)
(define_insn "*bitbranch<mode>4"
[(set (pc) (if_then_else
- (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYs,rm")
- (match_operand:QHI 1 "msp_general_operand" "rYsi,rmi"))
+ (ne (and:QHI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rYsYx,rm")
+ (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
(const_int 0))
(label_ref (match_operand 2 "" ""))
(pc)))
@@ -1296,46 +1284,52 @@
""
"@
BIT%x0%b0\t%1, %0 { JNE\t%l2
- BIT%X0%b0\t%1, %0 { JNE\t%l2"
+ BITX%b0\t%1, %0 { JNE\t%l2"
)
(define_insn "*bitbranch<mode>4"
[(set (pc) (if_then_else
- (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
- (match_operand:QHI 1 "msp_general_operand" "rmi"))
+ (eq (and:QHI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rYsYx,rm")
+ (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
(const_int 0))
(label_ref (match_operand 2 "" ""))
(pc)))
(clobber (reg:BI CARRY))
]
""
- "BIT%x0%b0\t%1, %0 { JEQ\t%l2"
+ "@
+ BIT%x0%b0\t%1, %0 { JEQ\t%l2
+ BITX%b0\t%1, %0 { JEQ\t%l2"
)
(define_insn "*bitbranch<mode>4"
[(set (pc) (if_then_else
- (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
- (match_operand:QHI 1 "msp_general_operand" "rmi"))
+ (eq (and:QHI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rYsYx,rm")
+ (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
(const_int 0))
(pc)
(label_ref (match_operand 2 "" ""))))
(clobber (reg:BI CARRY))
]
""
- "BIT%X0%b0\t%1, %0 { JNE\t%l2"
+ "@
+ BIT%x0%b0\t%1, %0 { JNE\t%l2
+ BITX%b0\t%1, %0 { JNE\t%l2"
)
(define_insn "*bitbranch<mode>4"
[(set (pc) (if_then_else
- (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
- (match_operand:QHI 1 "msp_general_operand" "rmi"))
+ (ne (and:QHI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rYsYx,rm")
+ (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi"))
(const_int 0))
(pc)
(label_ref (match_operand 2 "" ""))))
(clobber (reg:BI CARRY))
]
""
- "BIT%X0%b0\t%1, %0 { JEQ\t%l2"
+ "@
+ BIT%x0%b0\t%1, %0 { JEQ\t%l2
+ BITX%b0\t%1, %0 { JEQ\t%l2"
)
;;------------------------------------------------------------
@@ -1343,7 +1337,7 @@
(define_insn "*bitbranch<mode>4_z"
[(set (pc) (if_then_else
- (ne (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYs,rm")
+ (ne (zero_extract:HI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rYs,rm")
(const_int 1)
(match_operand 1 "msp430_bitpos" "i,i"))
(const_int 0))
@@ -1359,7 +1353,7 @@
(define_insn "*bitbranch<mode>4_z"
[(set (pc) (if_then_else
- (eq (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
+ (eq (zero_extract:HI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rm")
(const_int 1)
(match_operand 1 "msp430_bitpos" "i"))
(const_int 0))
@@ -1368,12 +1362,12 @@
(clobber (reg:BI CARRY))
]
""
- "BIT%x0%X0%b0\t%p1, %0 { JEQ\t%l2"
+ "BIT%X0%b0\t%p1, %0 { JEQ\t%l2"
)
(define_insn "*bitbranch<mode>4_z"
[(set (pc) (if_then_else
- (eq (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
+ (eq (zero_extract:HI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rm")
(const_int 1)
(match_operand 1 "msp430_bitpos" "i"))
(const_int 0))
@@ -1387,7 +1381,7 @@
(define_insn "*bitbranch<mode>4_z"
[(set (pc) (if_then_else
- (ne (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm")
+ (ne (zero_extract:HI (match_operand:QHI 0 "msp430_nonimmediate_operand" "rm")
(const_int 1)
(match_operand 1 "msp430_bitpos" "i"))
(const_int 0))
diff --git a/gcc/config/msp430/msp430.opt b/gcc/config/msp430/msp430.opt
index cbbe0faa6a2..2db2906ca11 100644
--- a/gcc/config/msp430/msp430.opt
+++ b/gcc/config/msp430/msp430.opt
@@ -67,12 +67,16 @@ EnumValue
Enum(msp430_hwmult_types) String(f5series) Value(MSP430_HWMULT_F5SERIES)
mcode-region=
-Target Joined RejectNegative Report ToLower Var(msp430_code_region) Enum(msp430_regions) Init(MSP430_REGION_ANY)
-Specify whether functions should be placed into low or high memory.
+Target Joined RejectNegative Report ToLower Var(msp430_code_region) Enum(msp430_regions) Init(MSP430_REGION_LOWER)
+Specify whether functions should be placed into the lower or upper memory regions, or if they should be shuffled between the regions (either) for best fit (default: lower).
mdata-region=
-Target Joined RejectNegative Report ToLower Var(msp430_data_region) Enum(msp430_regions) Init(MSP430_REGION_ANY)
-Specify whether variables should be placed into low or high memory.
+Target Joined RejectNegative Report ToLower Var(msp430_data_region) Enum(msp430_regions) Init(MSP430_REGION_LOWER)
+Specify whether variables should be placed into the lower or upper memory regions, or if they should be shuffled between the regions (either) for best fit (default: lower).
+
+muse-lower-region-prefix
+Target Mask(USE_LOWER_REGION_PREFIX) Report
+Add the .lower prefix to section names when compiling with -m{code,data}-region=lower (disabled by default).
Enum
Name(msp430_regions) Type(enum msp430_regions)
diff --git a/gcc/config/msp430/predicates.md b/gcc/config/msp430/predicates.md
index 1bfd33da524..751548c4ae8 100644
--- a/gcc/config/msp430/predicates.md
+++ b/gcc/config/msp430/predicates.md
@@ -18,7 +18,7 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
-(define_predicate "msp_volatile_memory_operand"
+(define_predicate "msp430_volatile_memory_operand"
(and (match_code "mem")
(match_test ("memory_address_addr_space_p (GET_MODE (op), XEXP (op, 0), MEM_ADDR_SPACE (op))")))
)
@@ -26,16 +26,16 @@
; TRUE for any valid general operand. We do this because
; general_operand refuses to match volatile memory refs.
-(define_predicate "msp_general_operand"
+(define_predicate "msp430_general_operand"
(ior (match_operand 0 "general_operand")
- (match_operand 0 "msp_volatile_memory_operand"))
+ (match_operand 0 "msp430_volatile_memory_operand"))
)
; Likewise for nonimmediate_operand.
-(define_predicate "msp_nonimmediate_operand"
+(define_predicate "msp430_nonimmediate_operand"
(ior (match_operand 0 "nonimmediate_operand")
- (match_operand 0 "msp_volatile_memory_operand"))
+ (match_operand 0 "msp430_volatile_memory_operand"))
)
(define_predicate "ubyte_operand"
diff --git a/gcc/config/msp430/t-msp430 b/gcc/config/msp430/t-msp430
index b9565103e9a..f8ba7751123 100644
--- a/gcc/config/msp430/t-msp430
+++ b/gcc/config/msp430/t-msp430
@@ -28,17 +28,22 @@ msp430-devices.o: $(srcdir)/config/msp430/msp430-devices.c \
# Enable multilibs:
-MULTILIB_OPTIONS = mcpu=msp430 mlarge
-MULTILIB_DIRNAMES = 430 large
+MULTILIB_OPTIONS = mcpu=msp430 mlarge mdata-region=none
+MULTILIB_DIRNAMES = 430 large full-memory-range
# Match -mcpu=430
MULTILIB_MATCHES = mcpu?msp430=mcpu?430
+# These options are equivalent in terms of the multilib required for them
+MULTILIB_MATCHES += mdata-region?none=mdata-region?upper
+MULTILIB_MATCHES += mdata-region?none=mdata-region?either
# The correct multilib for a given mmcu is selected without the need for
# hard-coded data here, because DRIVER_SELF_SPECS will place the correct
# -mcpu option for a given mcu onto the command line.
-MULTILIB_EXCEPTIONS = mcpu=msp430/mlarge
+MULTILIB_REQUIRED = mcpu=msp430
+MULTILIB_REQUIRED += mlarge
+MULTILIB_REQUIRED += mlarge/mdata-region=none
MULTILIB_EXTRA_OPTS =
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 55637df120a..4f48c416e2d 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -7845,7 +7845,7 @@ pa_attr_length_call (rtx_insn *insn, int sibcall)
/* 64-bit plabel sequence. */
else if (TARGET_64BIT && !local_call)
- length += sibcall ? 28 : 24;
+ length += 24;
/* non-pic long absolute branch sequence. */
else if ((TARGET_LONG_ABS_CALL || local_call) && !flag_pic)
@@ -7917,38 +7917,24 @@ pa_output_call (rtx_insn *insn, rtx call_dest, int sibcall)
xoperands[0] = pa_get_deferred_plabel (call_dest);
xoperands[1] = gen_label_rtx ();
- /* If this isn't a sibcall, we put the load of %r27 into the
- delay slot. We can't do this in a sibcall as we don't
- have a second call-clobbered scratch register available.
- We don't need to do anything when generating fast indirect
- calls. */
- if (seq_length != 0 && !sibcall)
+ /* Put the load of %r27 into the delay slot. We don't need to
+ do anything when generating fast indirect calls. */
+ if (seq_length != 0)
{
final_scan_insn (NEXT_INSN (insn), asm_out_file,
optimize, 0, NULL);
/* Now delete the delay insn. */
SET_INSN_DELETED (NEXT_INSN (insn));
- seq_length = 0;
}
output_asm_insn ("addil LT'%0,%%r27", xoperands);
output_asm_insn ("ldd RT'%0(%%r1),%%r1", xoperands);
output_asm_insn ("ldd 0(%%r1),%%r1", xoperands);
-
- if (sibcall)
- {
- output_asm_insn ("ldd 24(%%r1),%%r27", xoperands);
- output_asm_insn ("ldd 16(%%r1),%%r1", xoperands);
- output_asm_insn ("bve (%%r1)", xoperands);
- }
- else
- {
- output_asm_insn ("ldd 16(%%r1),%%r2", xoperands);
- output_asm_insn ("bve,l (%%r2),%%r2", xoperands);
- output_asm_insn ("ldd 24(%%r1),%%r27", xoperands);
- seq_length = 1;
- }
+ output_asm_insn ("ldd 16(%%r1),%%r2", xoperands);
+ output_asm_insn ("bve,l (%%r2),%%r2", xoperands);
+ output_asm_insn ("ldd 24(%%r1),%%r27", xoperands);
+ seq_length = 1;
}
else
{
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index f38a6dce9f9..1a43e5caadc 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -1292,13 +1292,12 @@ do { \
#endif
/* The maximum offset in bytes for a PA 1.X pc-relative call to the
- head of the preceding stub table. The selected offsets have been
- chosen so that approximately one call stub is allocated for every
- 86.7 instructions. A long branch stub is two instructions when
- not generating PIC code. For HP-UX and ELF targets, PIC stubs are
- seven and four instructions, respectively. */
-#define MAX_PCREL17F_OFFSET \
- (flag_pic ? (TARGET_HPUX ? 198164 : 221312) : 240000)
+ head of the preceding stub table. A long branch stub is two or three
+ instructions for non-PIC and PIC, respectively. Import stubs are
+ seven and five instructions for HP-UX and ELF targets, respectively.
+ The default stub group size for ELF targets is 217856 bytes.
+ FIXME: We need an option to set the maximum offset. */
+#define MAX_PCREL17F_OFFSET (TARGET_HPUX ? 198164 : 217856)
#define NEED_INDICATE_EXEC_STACK 0
diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h
index a626325c2d0..1081967bd61 100644
--- a/gcc/config/rs6000/darwin.h
+++ b/gcc/config/rs6000/darwin.h
@@ -506,6 +506,9 @@ do { \
this will need to be modified similar to the x86 case. */
#define TARGET_FOLD_BUILTIN SUBTARGET_FOLD_BUILTIN
+/* First available SYMBOL flag bit for use by subtargets. */
+#define SYMBOL_FLAG_SUBT_DEP (SYMBOL_FLAG_MACH_DEP)
+
/* Use standard DWARF numbering for DWARF debugging information. */
#define RS6000_USE_DWARF_NUMBERING
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index c51b768d964..08dd88c3e4d 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -69,7 +69,7 @@ extern void rs6000_generate_float2_code (bool, rtx, rtx, rtx);
extern void rs6000_generate_float2_double_code (rtx, rtx, rtx);
extern void rs6000_generate_vsigned2_code (bool, rtx, rtx, rtx);
extern int expand_block_clear (rtx[]);
-extern int expand_block_move (rtx[]);
+extern int expand_block_move (rtx[], bool);
extern bool expand_block_compare (rtx[]);
extern bool expand_strn_compare (rtx[], int);
extern bool rs6000_is_valid_mask (rtx, int *, int *, machine_mode);
diff --git a/gcc/config/rs6000/rs6000-string.c b/gcc/config/rs6000/rs6000-string.c
index b9391855e16..3bc359e33cc 100644
--- a/gcc/config/rs6000/rs6000-string.c
+++ b/gcc/config/rs6000/rs6000-string.c
@@ -2719,7 +2719,7 @@ gen_lvx_v4si_move (rtx dest, rtx src)
#define MAX_MOVE_REG 4
int
-expand_block_move (rtx operands[])
+expand_block_move (rtx operands[], bool might_overlap)
{
rtx orig_dest = operands[0];
rtx orig_src = operands[1];
@@ -2730,6 +2730,7 @@ expand_block_move (rtx operands[])
int bytes;
int offset;
int move_bytes;
+ rtx loads[MAX_MOVE_REG];
rtx stores[MAX_MOVE_REG];
int num_reg = 0;
@@ -2817,47 +2818,35 @@ expand_block_move (rtx operands[])
gen_func.mov = gen_movqi;
}
+ /* Mode is always set to something other than BLKmode by one of the
+ cases of the if statement above. */
+ gcc_assert (mode != BLKmode);
+
src = adjust_address (orig_src, mode, offset);
dest = adjust_address (orig_dest, mode, offset);
- if (mode != BLKmode)
- {
- rtx tmp_reg = gen_reg_rtx (mode);
+ rtx tmp_reg = gen_reg_rtx (mode);
+
+ loads[num_reg] = (*gen_func.mov) (tmp_reg, src);
+ stores[num_reg++] = (*gen_func.mov) (dest, tmp_reg);
- emit_insn ((*gen_func.mov) (tmp_reg, src));
- stores[num_reg++] = (*gen_func.mov) (dest, tmp_reg);
- }
+ /* If we didn't succeed in doing it in one pass, we can't do it in the
+ might_overlap case. Bail out and return failure. */
+ if (might_overlap && num_reg >= MAX_MOVE_REG
+ && bytes > move_bytes)
+ return 0;
- if (mode == BLKmode || num_reg >= MAX_MOVE_REG || bytes == move_bytes)
+ /* Emit loads and stores saved up. */
+ if (num_reg >= MAX_MOVE_REG || bytes == move_bytes)
{
int i;
for (i = 0; i < num_reg; i++)
+ emit_insn (loads[i]);
+ for (i = 0; i < num_reg; i++)
emit_insn (stores[i]);
num_reg = 0;
}
-
- if (mode == BLKmode)
- {
- /* Move the address into scratch registers. The movmemsi
- patterns require zero offset. */
- if (!REG_P (XEXP (src, 0)))
- {
- rtx src_reg = copy_addr_to_reg (XEXP (src, 0));
- src = replace_equiv_address (src, src_reg);
- }
- set_mem_size (src, move_bytes);
-
- if (!REG_P (XEXP (dest, 0)))
- {
- rtx dest_reg = copy_addr_to_reg (XEXP (dest, 0));
- dest = replace_equiv_address (dest, dest_reg);
- }
- set_mem_size (dest, move_bytes);
-
- emit_insn ((*gen_func.movmemsi) (dest, src,
- GEN_INT (move_bytes & 31),
- align_rtx));
- }
+
}
return 1;
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 330e2490301..a4a38822b43 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -7372,7 +7372,7 @@ mem_operand_gpr (rtx op, machine_mode mode)
causes a wrap, so test only the low 16 bits. */
offset = ((offset & 0xffff) ^ 0x8000) - 0x8000;
- return offset + 0x8000 < 0x10000u - extra;
+ return SIGNED_16BIT_OFFSET_EXTRA_P (offset, extra);
}
/* As above, but for DS-FORM VSX insns. Unlike mem_operand_gpr,
@@ -7405,7 +7405,7 @@ mem_operand_ds_form (rtx op, machine_mode mode)
causes a wrap, so test only the low 16 bits. */
offset = ((offset & 0xffff) ^ 0x8000) - 0x8000;
- return offset + 0x8000 < 0x10000u - extra;
+ return SIGNED_16BIT_OFFSET_EXTRA_P (offset, extra);
}
/* Subroutines of rs6000_legitimize_address and rs6000_legitimate_address_p. */
@@ -7754,8 +7754,7 @@ rs6000_legitimate_offset_address_p (machine_mode mode, rtx x,
break;
}
- offset += 0x8000;
- return offset < 0x10000 - extra;
+ return SIGNED_16BIT_OFFSET_EXTRA_P (offset, extra);
}
bool
@@ -8772,8 +8771,9 @@ rs6000_mode_dependent_address (const_rtx addr)
&& XEXP (addr, 0) != arg_pointer_rtx
&& CONST_INT_P (XEXP (addr, 1)))
{
- unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1));
- return val + 0x8000 >= 0x10000 - (TARGET_POWERPC64 ? 8 : 12);
+ HOST_WIDE_INT val = INTVAL (XEXP (addr, 1));
+ HOST_WIDE_INT extra = TARGET_POWERPC64 ? 8 : 12;
+ return !SIGNED_16BIT_OFFSET_EXTRA_P (val, extra);
}
break;
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 4f27f13772b..2dca269744f 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -9107,7 +9107,7 @@
FAIL;
})
-;; String/block move insn.
+;; String/block copy insn (source and destination must not overlap).
;; Argument 0 is the destination
;; Argument 1 is the source
;; Argument 2 is the length
@@ -9120,11 +9120,31 @@
(use (match_operand:SI 3 ""))])]
""
{
- if (expand_block_move (operands))
+ if (expand_block_move (operands, false))
DONE;
else
FAIL;
})
+
+;; String/block move insn (source and destination may overlap).
+;; Argument 0 is the destination
+;; Argument 1 is the source
+;; Argument 2 is the length
+;; Argument 3 is the alignment
+
+(define_expand "movmemsi"
+ [(parallel [(set (match_operand:BLK 0 "")
+ (match_operand:BLK 1 ""))
+ (use (match_operand:SI 2 ""))
+ (use (match_operand:SI 3 ""))])]
+ ""
+{
+ if (expand_block_move (operands, true))
+ DONE;
+ else
+ FAIL;
+})
+
;; Define insns that do load or store with update. Some of these we can
;; get by using pre-decrement or pre-increment, but the hardware can also
diff --git a/gcc/configure b/gcc/configure
index 893a9e6fafc..dc9f5fefaa8 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -27773,6 +27773,80 @@ fi
as_fn_error $? "Requesting --with-nan= requires assembler support for -mnan=" "$LINENO" 5
fi
;;
+ msp430-*-*)
+ # Earlier GAS versions generically support .gnu_attribute, but the
+ # msp430 assembler will not do anything with it.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .gnu_attribute support" >&5
+$as_echo_n "checking assembler for .gnu_attribute support... " >&6; }
+if ${gcc_cv_as_msp430_gnu_attribute+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_msp430_gnu_attribute=no
+ if test $in_tree_gas = yes; then
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 33 \) \* 1000 + 50`
+ then gcc_cv_as_msp430_gnu_attribute=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ $as_echo '.gnu_attribute 4,1' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_msp430_gnu_attribute=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_msp430_gnu_attribute" >&5
+$as_echo "$gcc_cv_as_msp430_gnu_attribute" >&6; }
+if test $gcc_cv_as_msp430_gnu_attribute = yes; then
+
+$as_echo "#define HAVE_AS_GNU_ATTRIBUTE 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .mspabi_attribute support" >&5
+$as_echo_n "checking assembler for .mspabi_attribute support... " >&6; }
+if ${gcc_cv_as_msp430_mspabi_attribute+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_msp430_mspabi_attribute=no
+ if test $in_tree_gas = yes; then
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 33 \) \* 1000 + 50`
+ then gcc_cv_as_msp430_mspabi_attribute=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ $as_echo '.mspabi_attribute 4,1' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ gcc_cv_as_msp430_mspabi_attribute=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_msp430_mspabi_attribute" >&5
+$as_echo "$gcc_cv_as_msp430_mspabi_attribute" >&6; }
+if test $gcc_cv_as_msp430_mspabi_attribute = yes; then
+
+$as_echo "#define HAVE_AS_MSPABI_ATTRIBUTE 1" >>confdefs.h
+
+fi
+
+ ;;
riscv*-*-*)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .attribute support" >&5
$as_echo_n "checking assembler for .attribute support... " >&6; }
diff --git a/gcc/configure.ac b/gcc/configure.ac
index eff849f1f38..54a67159b98 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -4949,6 +4949,20 @@ pointers into PC-relative form.])
[Requesting --with-nan= requires assembler support for -mnan=])
fi
;;
+ msp430-*-*)
+ # Earlier GAS versions generically support .gnu_attribute, but the
+ # msp430 assembler will not do anything with it.
+ gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
+ gcc_cv_as_msp430_gnu_attribute, [2,33,50],,
+ [.gnu_attribute 4,1],,
+ [AC_DEFINE(HAVE_AS_GNU_ATTRIBUTE, 1,
+ [Define if your assembler supports .gnu_attribute.])])
+ gcc_GAS_CHECK_FEATURE([.mspabi_attribute support],
+ gcc_cv_as_msp430_mspabi_attribute, [2,33,50],,
+ [.mspabi_attribute 4,1],,
+ [AC_DEFINE(HAVE_AS_MSPABI_ATTRIBUTE, 1,
+ [Define if your assembler supports .mspabi_attribute.])])
+ ;;
riscv*-*-*)
gcc_GAS_CHECK_FEATURE([.attribute support],
gcc_cv_as_riscv_attribute, [2,32,0],,
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 257de226326..b683f129880 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -378,7 +378,8 @@ enum function_class {
function_c99_misc,
function_c99_math_complex,
function_sincos,
- function_c11_misc
+ function_c11_misc,
+ function_c2x_misc
};
/* Enumerate visibility settings. This is deliberately ordered from most
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a1e520a5137..90cab94e88e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,151 @@
+2019-10-07 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * call.c (resolve_args): Use cp_expr_loc_or_input_loc in one place.
+ * decl.c (grokdeclarator): Use id_loc in one place.
+ * decl2.c (build_anon_union_vars): Use DECL_SOURCE_LOCATION.
+ * parser.c (cp_parser_delete_expression): Fix the location of the
+ returned expression.
+ (cp_parser_throw_expression): Likewise.
+ * pt.c (determine_specialization): Use DECL_SOURCE_LOCATION.
+
+2019-10-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/91369 - Implement P0784R7: constexpr new
+ * cp-tree.h (enum cp_tree_index): Add CPTI_HEAP_UNINIT_IDENTIFIER,
+ CPTI_HEAP_IDENTIFIER and CPTI_HEAP_DELETED_IDENTIFIER.
+ (heap_uninit_identifier, heap_identifier, heap_deleted_identifier):
+ Define.
+ (type_has_constexpr_destructor, build_new_constexpr_heap_type,
+ cxx_constant_dtor): Declare.
+ * class.c (type_maybe_constexpr_default_constructor): Make static.
+ (type_maybe_constexpr_destructor, type_has_constexpr_destructor): New
+ functions.
+ (finalize_literal_type_property): For c++2a, don't clear
+ CLASSTYPE_LITERAL_P for types without trivial destructors unless they
+ have non-constexpr destructors.
+ (explain_non_literal_class): For c++2a, complain about non-constexpr
+ destructors rather than about non-trivial destructors.
+ * constexpr.c: Include stor-layout.h.
+ (struct constexpr_global_ctx): New type.
+ (struct constexpr_ctx): Add global field, remove values and
+ constexpr_ops_count.
+ (cxx_replaceable_global_alloc_fn): New inline function.
+ (cxx_eval_call_expression): For c++2a allow calls to replaceable
+ global allocation functions, for new return address of a heap uninit
+ var, for delete record its deletion. Change ctx->values->{get,put} to
+ ctx->global->values.{get,put}.
+ (non_const_var_error): Add auto_diagnostic_group sentinel. Emit
+ special diagnostics for heap variables.
+ (cxx_eval_store_expression): Change ctx->values->{get,put} to
+ ctx->global->values.{get,put}.
+ (cxx_eval_loop_expr): Initialize jump_target if NULL. Change
+ new_ctx.values->remove to ctx->global->values.remove.
+ (cxx_eval_constant_expression): Change *ctx->constexpr_ops_count
+ to ctx->global->constexpr_ops_count. Change ctx->values->{get,put} to
+ ctx->global->values.{get,put}.
+ <case NOP_EXPR>: Formatting fix. On cast of replaceable global
+ allocation function to some pointer type, adjust the type of
+ the heap variable and change name from heap_uninit_identifier
+ to heap_identifier.
+ (find_heap_var_refs): New function.
+ (cxx_eval_outermost_constant_expr): Add constexpr_dtor argument,
+ handle evaluation of constexpr dtors and add tracking of heap
+ variables. Use tf_no_cleanup for get_target_expr_with_sfinae.
+ (cxx_constant_value): Adjust cxx_eval_outermost_constant_expr caller.
+ (cxx_constant_dtor): New function.
+ (maybe_constant_value, fold_non_dependent_expr_template,
+ maybe_constant_init_1): Adjust cxx_eval_outermost_constant_expr
+ callers.
+ (potential_constant_expression_1): Ignore clobbers. Allow
+ COND_EXPR_IS_VEC_DELETE for c++2a.
+ * decl.c (initialize_predefined_identifiers): Add heap identifiers.
+ (decl_maybe_constant_destruction): New function.
+ (cp_finish_decl): Don't clear TREE_READONLY for constexpr variables
+ with non-trivial, but constexpr destructors.
+ (register_dtor_fn): For constexpr variables with constexpr non-trivial
+ destructors call cxx_maybe_build_cleanup instead of adding destructor
+ calls at runtime.
+ (expand_static_init): For constexpr variables with constexpr
+ non-trivial destructors call cxx_maybe_build_cleanup.
+ (grokdeclarator): Allow constexpr destructors for c++2a. Formatting
+ fix.
+ (cxx_maybe_build_cleanup): For constexpr variables with constexpr
+ non-trivial destructors call cxx_constant_dtor instead of adding
+ destructor calls at runtime.
+ * init.c: Include stor-layout.h.
+ (build_new_constexpr_heap_type, maybe_wrap_new_for_constexpr): New
+ functions.
+ (build_new_1): For c++2a and new[], add cast around the alloc call
+ to help constexpr evaluation figure out the type of the heap storage.
+ (build_vec_delete_1): Set DECL_INITIAL of tbase and emit a DECL_EXPR
+ for it instead of initializing an uninitialized variable.
+ * method.c: Include intl.h.
+ (SFK_CTOR_P, SFK_DTOR_P, SFK_ASSIGN_P, SFK_COPY_P, SFK_MOVE_P): Move
+ definitions earlier.
+ (process_subob_fn): Add sfk argument, adjust non-constexpr call
+ diagnostics based on it.
+ (walk_field_subobs): Formatting fixes. Adjust process_subob_fn caller.
+ (synthesized_method_base_walk): Likewise.
+ (synthesized_method_walk): Set *constexpr_p to true for dtors in c++2a.
+ Fix up DR number in comment.
+ (implicitly_declare_fn): Formatting fix.
+ * typeck2.c (store_init_value): Don't call cp_fully_fold_init on
+ initializers of automatic non-constexpr variables in constexpr
+ functions.
+
+2019-10-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/71504
+ * constexpr.c (cxx_fold_indirect_ref_1): New function.
+ (cxx_fold_indirect_ref): Use it.
+
+ PR c++/91974
+ * cp-gimplify.c (cp_gimplify_expr) <case CALL_EXPR>: For
+ -fstrong-eval-order ensure CALL_EXPR_FN side-effects are evaluated
+ before any arguments. Additionally, ensure CALL_EXPR_FN that isn't
+ invariant nor OBJ_TYPE_REF nor SSA_NAME is forced into a temporary.
+
+2019-10-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * init.c (build_new): Use cp_expr_loc_or_input_loc in two places.
+ * name-lookup.c (do_pushdecl): Use DECL_SOURCE_LOCATION.
+ (push_class_level_binding_1): Likewise.
+ (set_decl_namespace): Likewise.
+
+2019-10-03 Jakub Jelinek <jakub@redhat.com>
+
+ * constexpr.c (cxx_eval_constant_expression) <case CLEANUP_STMT>: If
+ not skipping upon entry to body, run cleanup with the same *jump_target
+ as it started to run the cleanup even if the body returns, breaks or
+ continues.
+ (potential_constant_expression_1): Allow CLEANUP_STMT.
+
+ * constexpr.c (cxx_eval_store_expression): Formatting fix. Handle
+ const_object_being_modified with array type.
+
+2019-10-02 Jason Merrill <jason@redhat.com>
+
+ * typeck2.c (store_init_value): Only clear_cv_and_fold_caches if the
+ value is constant.
+
+2019-09-30 Jason Merrill <jason@redhat.com>
+
+ Use hash_map_safe_* functions.
+ * constexpr.c (maybe_initialize_fundef_copies_table): Remove.
+ (get_fundef_copy): Use hash_map_safe_get_or_insert.
+ * cp-objcp-common.c (cp_get_debug_type): Use hash_map_safe_*.
+ * decl.c (store_decomp_type): Remove.
+ (cp_finish_decomp): Use hash_map_safe_put.
+ * init.c (get_nsdmi): Use hash_map_safe_*.
+ * pt.c (store_defaulted_ttp, lookup_defaulted_ttp): Remove.
+ (add_defaults_to_ttp): Use hash_map_safe_*.
+
+2019-10-02 Richard Biener <rguenther@suse.de>
+
+ PR c++/91606
+ * decl.c (build_ptrmemfunc_type): Mark pointer-to-member
+ fat pointer structure members as DECL_NONADDRESSABLE_P.
+
2019-09-28 Marek Polacek <polacek@redhat.com>
PR c++/91889 - follow-up fix for DR 2352.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 56dcbd391c1..6c9acac4614 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4381,7 +4381,8 @@ resolve_args (vec<tree, va_gc> *args, tsubst_flags_t complain)
else if (VOID_TYPE_P (TREE_TYPE (arg)))
{
if (complain & tf_error)
- error ("invalid use of void expression");
+ error_at (cp_expr_loc_or_input_loc (arg),
+ "invalid use of void expression");
return NULL;
}
else if (invalid_nonstatic_memfn_p (EXPR_LOCATION (arg), arg, complain))
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 3838f765a1d..4abcfaf4c1d 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -206,6 +206,7 @@ static int empty_base_at_nonzero_offset_p (tree, tree, splay_tree);
static tree end_of_base (tree);
static tree get_vcall_index (tree, tree);
static bool type_maybe_constexpr_default_constructor (tree);
+static bool type_maybe_constexpr_destructor (tree);
static bool field_poverlapping_p (tree);
/* Return a COND_EXPR that executes TRUE_STMT if this execution of the
@@ -5242,7 +5243,7 @@ type_has_constexpr_default_constructor (tree t)
without forcing a lazy declaration (which might cause undesired
instantiations). */
-bool
+static bool
type_maybe_constexpr_default_constructor (tree t)
{
if (CLASS_TYPE_P (t) && CLASSTYPE_LAZY_DEFAULT_CTOR (t)
@@ -5252,6 +5253,34 @@ type_maybe_constexpr_default_constructor (tree t)
return type_has_constexpr_default_constructor (t);
}
+/* Returns true iff class T has a constexpr destructor. */
+
+bool
+type_has_constexpr_destructor (tree t)
+{
+ tree fns;
+
+ if (CLASSTYPE_LAZY_DESTRUCTOR (t))
+ /* Non-trivial, we need to check subobject destructors. */
+ lazily_declare_fn (sfk_destructor, t);
+ fns = CLASSTYPE_DESTRUCTOR (t);
+ return (fns && DECL_DECLARED_CONSTEXPR_P (fns));
+}
+
+/* Returns true iff class T has a constexpr destructor or has an
+ implicitly declared destructor that we can't tell if it's constexpr
+ without forcing a lazy declaration (which might cause undesired
+ instantiations). */
+
+static bool
+type_maybe_constexpr_destructor (tree t)
+{
+ if (CLASS_TYPE_P (t) && CLASSTYPE_LAZY_DESTRUCTOR (t))
+ /* Assume it's constexpr. */
+ return true;
+ return type_has_constexpr_destructor (t);
+}
+
/* Returns true iff class TYPE has a virtual destructor. */
bool
@@ -5503,8 +5532,11 @@ finalize_literal_type_property (tree t)
{
tree fn;
- if (cxx_dialect < cxx11
- || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
+ if (cxx_dialect < cxx11)
+ CLASSTYPE_LITERAL_P (t) = false;
+ else if (CLASSTYPE_LITERAL_P (t)
+ && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
+ && (cxx_dialect < cxx2a || !type_maybe_constexpr_destructor (t)))
CLASSTYPE_LITERAL_P (t) = false;
else if (CLASSTYPE_LITERAL_P (t) && LAMBDA_TYPE_P (t))
CLASSTYPE_LITERAL_P (t) = (cxx_dialect >= cxx17);
@@ -5558,8 +5590,12 @@ explain_non_literal_class (tree t)
inform (UNKNOWN_LOCATION,
" %qT is a closure type, which is only literal in "
"C++17 and later", t);
- else if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
+ else if (cxx_dialect < cxx2a && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
inform (UNKNOWN_LOCATION, " %q+T has a non-trivial destructor", t);
+ else if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
+ && !type_maybe_constexpr_destructor (t))
+ inform (UNKNOWN_LOCATION, " %q+T does not have %<constexpr%> destructor",
+ t);
else if (CLASSTYPE_NON_AGGREGATE (t)
&& !TYPE_HAS_TRIVIAL_DFLT (t)
&& !LAMBDA_TYPE_P (t)
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index cb5484f4b72..f50cc04c293 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-fold.h"
#include "timevar.h"
#include "fold-const-call.h"
+#include "stor-layout.h"
static bool verify_constant (tree, bool, bool *, bool *);
#define VERIFY_CONSTANT(X) \
@@ -1006,17 +1007,35 @@ enum constexpr_switch_state {
css_default_processing
};
+/* The constexpr expansion context part which needs one instance per
+ cxx_eval_outermost_constant_expr invocation. VALUES is a map of values of
+ variables initialized within the expression. */
+
+struct constexpr_global_ctx {
+ /* Values for any temporaries or local variables within the
+ constant-expression. */
+ hash_map<tree,tree> values;
+ /* Number of cxx_eval_constant_expression calls (except skipped ones,
+ on simple constants or location wrappers) encountered during current
+ cxx_eval_outermost_constant_expr call. */
+ HOST_WIDE_INT constexpr_ops_count;
+ /* Heap VAR_DECLs created during the evaluation of the outermost constant
+ expression. */
+ auto_vec<tree, 16> heap_vars;
+ /* Constructor. */
+ constexpr_global_ctx () : constexpr_ops_count (0) {}
+};
+
/* The constexpr expansion context. CALL is the current function
expansion, CTOR is the current aggregate initializer, OBJECT is the
- object being initialized by CTOR, either a VAR_DECL or a _REF. VALUES
- is a map of values of variables initialized within the expression. */
+ object being initialized by CTOR, either a VAR_DECL or a _REF. */
struct constexpr_ctx {
+ /* The part of the context that needs to be unique to the whole
+ cxx_eval_outermost_constant_expr invocation. */
+ constexpr_global_ctx *global;
/* The innermost call we're evaluating. */
constexpr_call *call;
- /* Values for any temporaries or local variables within the
- constant-expression. */
- hash_map<tree,tree> *values;
/* SAVE_EXPRs that we've seen within the current LOOP_EXPR. NULL if we
aren't inside a loop. */
vec<tree> *save_exprs;
@@ -1027,10 +1046,6 @@ struct constexpr_ctx {
tree object;
/* If inside SWITCH_EXPR. */
constexpr_switch_state *css_state;
- /* Number of cxx_eval_constant_expression calls (except skipped ones,
- on simple constants or location wrappers) encountered during current
- cxx_eval_outermost_constant_expr call. */
- HOST_WIDE_INT *constexpr_ops_count;
/* Whether we should error on a non-constant expression or fail quietly. */
bool quiet;
@@ -1098,15 +1113,6 @@ maybe_initialize_constexpr_call_table (void)
static GTY(()) hash_map<tree, tree> *fundef_copies_table;
-/* Initialize FUNDEF_COPIES_TABLE if it's not initialized. */
-
-static void
-maybe_initialize_fundef_copies_table ()
-{
- if (fundef_copies_table == NULL)
- fundef_copies_table = hash_map<tree,tree>::create_ggc (101);
-}
-
/* Reuse a copy or create a new unshared copy of the function FUN.
Return this copy. We use a TREE_LIST whose PURPOSE is body, VALUE
is parms, TYPE is result. */
@@ -1114,11 +1120,10 @@ maybe_initialize_fundef_copies_table ()
static tree
get_fundef_copy (constexpr_fundef *fundef)
{
- maybe_initialize_fundef_copies_table ();
-
tree copy;
bool existed;
- tree *slot = &fundef_copies_table->get_or_insert (fundef->decl, &existed);
+ tree *slot = &(hash_map_safe_get_or_insert<hm_ggc>
+ (fundef_copies_table, fundef->decl, &existed, 127));
if (!existed)
{
@@ -1588,6 +1593,17 @@ modifying_const_object_error (tree expr, tree obj)
inform (location_of (obj), "originally declared %<const%> here");
}
+/* Return true if FNDECL is a replaceable global allocation function that
+ should be useable during constant expression evaluation. */
+
+static inline bool
+cxx_replaceable_global_alloc_fn (tree fndecl)
+{
+ return (cxx_dialect >= cxx2a
+ && IDENTIFIER_NEWDEL_OP_P (DECL_NAME (fndecl))
+ && CP_DECL_CONTEXT (fndecl) == global_namespace);
+}
+
/* Subroutine of cxx_eval_constant_expression.
Evaluate the call expression tree T in the context of OLD_CALL expression
evaluation. */
@@ -1666,6 +1682,62 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
lval, non_constant_p, overflow_p);
if (!DECL_DECLARED_CONSTEXPR_P (fun))
{
+ if (cxx_replaceable_global_alloc_fn (fun))
+ {
+ const int nargs = call_expr_nargs (t);
+ tree arg0 = NULL_TREE;
+ for (int i = 0; i < nargs; ++i)
+ {
+ tree arg = CALL_EXPR_ARG (t, i);
+ arg = cxx_eval_constant_expression (ctx, arg, false,
+ non_constant_p, overflow_p);
+ VERIFY_CONSTANT (arg);
+ if (i == 0)
+ arg0 = arg;
+ }
+ gcc_assert (arg0);
+ if (IDENTIFIER_NEW_OP_P (DECL_NAME (fun)))
+ {
+ tree type = build_array_type_nelts (char_type_node,
+ tree_to_uhwi (arg0));
+ tree var = build_decl (loc, VAR_DECL, heap_uninit_identifier,
+ type);
+ DECL_ARTIFICIAL (var) = 1;
+ TREE_STATIC (var) = 1;
+ ctx->global->heap_vars.safe_push (var);
+ ctx->global->values.put (var, NULL_TREE);
+ return fold_convert (ptr_type_node, build_address (var));
+ }
+ else
+ {
+ STRIP_NOPS (arg0);
+ if (TREE_CODE (arg0) == ADDR_EXPR
+ && VAR_P (TREE_OPERAND (arg0, 0)))
+ {
+ tree var = TREE_OPERAND (arg0, 0);
+ if (DECL_NAME (var) == heap_uninit_identifier
+ || DECL_NAME (var) == heap_identifier)
+ {
+ DECL_NAME (var) = heap_deleted_identifier;
+ ctx->global->values.remove (var);
+ return void_node;
+ }
+ else if (DECL_NAME (var) == heap_deleted_identifier)
+ {
+ if (!ctx->quiet)
+ error_at (loc, "deallocation of already deallocated "
+ "storage");
+ *non_constant_p = true;
+ return t;
+ }
+ }
+ if (!ctx->quiet)
+ error_at (loc, "deallocation of storage that was "
+ "not previously allocated");
+ *non_constant_p = true;
+ return t;
+ }
+ }
if (!ctx->quiet)
{
if (!lambda_static_thunk_p (fun))
@@ -1685,7 +1757,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
new_ctx.object = AGGR_INIT_EXPR_SLOT (t);
tree ctor = new_ctx.ctor = build_constructor (DECL_CONTEXT (fun), NULL);
CONSTRUCTOR_NO_CLEARING (ctor) = true;
- ctx->values->put (new_ctx.object, ctor);
+ ctx->global->values.put (new_ctx.object, ctor);
ctx = &new_ctx;
}
@@ -1887,7 +1959,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
arg = unshare_constructor (arg);
if (TREE_CODE (arg) == CONSTRUCTOR)
vec_safe_push (ctors, arg);
- ctx->values->put (remapped, arg);
+ ctx->global->values.put (remapped, arg);
remapped = DECL_CHAIN (remapped);
}
/* Add the RESULT_DECL to the values map, too. */
@@ -1897,11 +1969,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
slot = AGGR_INIT_EXPR_SLOT (t);
tree addr = build_address (slot);
addr = build_nop (TREE_TYPE (res), addr);
- ctx->values->put (res, addr);
- ctx->values->put (slot, NULL_TREE);
+ ctx->global->values.put (res, addr);
+ ctx->global->values.put (slot, NULL_TREE);
}
else
- ctx->values->put (res, NULL_TREE);
+ ctx->global->values.put (res, NULL_TREE);
/* Track the callee's evaluated SAVE_EXPRs so that we can forget
their values after the call. */
@@ -1926,7 +1998,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
result = void_node;
else
{
- result = *ctx->values->get (slot ? slot : res);
+ result = *ctx->global->values.get (slot ? slot : res);
if (result == NULL_TREE && !*non_constant_p)
{
if (!ctx->quiet)
@@ -1944,8 +2016,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
&& CLASS_TYPE_P (TREE_TYPE (new_obj))
&& CP_TYPE_CONST_P (TREE_TYPE (new_obj)))
{
- /* Subobjects might not be stored in ctx->values but we can
- get its CONSTRUCTOR by evaluating *this. */
+ /* Subobjects might not be stored in ctx->global->values but we
+ can get its CONSTRUCTOR by evaluating *this. */
tree e = cxx_eval_constant_expression (ctx, new_obj,
/*lval*/false,
non_constant_p,
@@ -1957,17 +2029,17 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
unsigned int i;
tree save_expr;
FOR_EACH_VEC_ELT (save_exprs, i, save_expr)
- ctx_with_save_exprs.values->remove (save_expr);
+ ctx->global->values.remove (save_expr);
/* Remove the parms/result from the values map. Is it worth
bothering to do this when the map itself is only live for
one constexpr evaluation? If so, maybe also clear out
other vars from call, maybe in BIND_EXPR handling? */
- ctx->values->remove (res);
+ ctx->global->values.remove (res);
if (slot)
- ctx->values->remove (slot);
+ ctx->global->values.remove (slot);
for (tree parm = parms; parm; parm = TREE_CHAIN (parm))
- ctx->values->remove (parm);
+ ctx->global->values.remove (parm);
/* Free any parameter CONSTRUCTORs we aren't returning directly. */
while (!ctors->is_empty ())
@@ -3087,7 +3159,7 @@ verify_ctor_sanity (const constexpr_ctx *ctx, tree type)
(TREE_TYPE (type), TREE_TYPE (otype)))));
}
gcc_assert (!ctx->object || !DECL_P (ctx->object)
- || *(ctx->values->get (ctx->object)) == ctx->ctor);
+ || *(ctx->global->values.get (ctx->object)) == ctx->ctor);
}
/* Subroutine of cxx_eval_constant_expression.
@@ -3356,6 +3428,103 @@ same_type_ignoring_tlq_and_bounds_p (tree type1, tree type2)
return same_type_ignoring_top_level_qualifiers_p (type1, type2);
}
+/* Helper function for cxx_fold_indirect_ref_1, called recursively. */
+
+static tree
+cxx_fold_indirect_ref_1 (location_t loc, tree type, tree op,
+ unsigned HOST_WIDE_INT off, bool *empty_base)
+{
+ tree optype = TREE_TYPE (op);
+ unsigned HOST_WIDE_INT const_nunits;
+ if (off == 0)
+ {
+ if (similar_type_p (optype, type))
+ return op;
+ /* Also handle conversion to an empty base class, which
+ is represented with a NOP_EXPR. */
+ /* *(foo *)&complexfoo => __real__ complexfoo */
+ else if (TREE_CODE (optype) == COMPLEX_TYPE
+ && similar_type_p (type, TREE_TYPE (optype)))
+ return build1_loc (loc, REALPART_EXPR, type, op);
+ }
+ /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
+ else if (TREE_CODE (optype) == COMPLEX_TYPE
+ && similar_type_p (type, TREE_TYPE (optype))
+ && tree_to_uhwi (TYPE_SIZE_UNIT (type)) == off)
+ return build1_loc (loc, IMAGPART_EXPR, type, op);
+ if (is_empty_class (type)
+ && CLASS_TYPE_P (optype)
+ && DERIVED_FROM_P (type, optype))
+ {
+ *empty_base = true;
+ return op;
+ }
+ /* ((foo*)&vectorfoo)[x] => BIT_FIELD_REF<vectorfoo,...> */
+ else if (VECTOR_TYPE_P (optype)
+ && similar_type_p (type, TREE_TYPE (optype))
+ && TYPE_VECTOR_SUBPARTS (optype).is_constant (&const_nunits))
+ {
+ unsigned HOST_WIDE_INT part_width = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+ unsigned HOST_WIDE_INT max_offset = part_width * const_nunits;
+ if (off < max_offset && off % part_width == 0)
+ {
+ tree index = bitsize_int (off * BITS_PER_UNIT);
+ return build3_loc (loc, BIT_FIELD_REF, type, op,
+ TYPE_SIZE (type), index);
+ }
+ }
+ /* ((foo *)&fooarray)[x] => fooarray[x] */
+ else if (TREE_CODE (optype) == ARRAY_TYPE
+ && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (optype)))
+ && !integer_zerop (TYPE_SIZE_UNIT (TREE_TYPE (optype))))
+ {
+ tree type_domain = TYPE_DOMAIN (optype);
+ tree min_val = size_zero_node;
+ if (type_domain && TYPE_MIN_VALUE (type_domain))
+ min_val = TYPE_MIN_VALUE (type_domain);
+ unsigned HOST_WIDE_INT el_sz
+ = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (optype)));
+ unsigned HOST_WIDE_INT idx = off / el_sz;
+ unsigned HOST_WIDE_INT rem = off % el_sz;
+ if (tree_fits_uhwi_p (min_val))
+ {
+ tree index = size_int (idx + tree_to_uhwi (min_val));
+ op = build4_loc (loc, ARRAY_REF, TREE_TYPE (optype), op, index,
+ NULL_TREE, NULL_TREE);
+ return cxx_fold_indirect_ref_1 (loc, type, op, rem,
+ empty_base);
+ }
+ }
+ /* ((foo *)&struct_with_foo_field)[x] => COMPONENT_REF */
+ else if (TREE_CODE (optype) == RECORD_TYPE)
+ {
+ for (tree field = TYPE_FIELDS (optype);
+ field; field = DECL_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL
+ && TREE_TYPE (field) != error_mark_node
+ && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (field))))
+ {
+ tree pos = byte_position (field);
+ if (!tree_fits_uhwi_p (pos))
+ continue;
+ unsigned HOST_WIDE_INT upos = tree_to_uhwi (pos);
+ unsigned el_sz
+ = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field)));
+ if (upos <= off && off < upos + el_sz)
+ {
+ tree cop = build3 (COMPONENT_REF, TREE_TYPE (field),
+ op, field, NULL_TREE);
+ if (tree ret = cxx_fold_indirect_ref_1 (loc, type, cop,
+ off - upos,
+ empty_base))
+ return ret;
+ }
+ }
+ }
+
+ return NULL_TREE;
+}
+
/* A less strict version of fold_indirect_ref_1, which requires cv-quals to
match. We want to be less strict for simple *& folding; if we have a
non-const temporary that we access through a const pointer, that should
@@ -3363,9 +3532,7 @@ same_type_ignoring_tlq_and_bounds_p (tree type1, tree type2)
because we're dealing with things like ADDR_EXPR of INTEGER_CST which
don't really make sense outside of constant expression evaluation. Also
we want to allow folding to COMPONENT_REF, which could cause trouble
- with TBAA in fold_indirect_ref_1.
-
- Try to keep this function synced with fold_indirect_ref_1. */
+ with TBAA in fold_indirect_ref_1. */
static tree
cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
@@ -3396,139 +3563,19 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
else
return op;
}
- /* *(foo *)&fooarray => fooarray[0] */
- else if (TREE_CODE (optype) == ARRAY_TYPE
- && similar_type_p (type, TREE_TYPE (optype)))
- {
- tree type_domain = TYPE_DOMAIN (optype);
- tree min_val = size_zero_node;
- if (type_domain && TYPE_MIN_VALUE (type_domain))
- min_val = TYPE_MIN_VALUE (type_domain);
- return build4_loc (loc, ARRAY_REF, type, op, min_val,
- NULL_TREE, NULL_TREE);
- }
- /* *(foo *)&complexfoo => __real__ complexfoo */
- else if (TREE_CODE (optype) == COMPLEX_TYPE
- && similar_type_p (type, TREE_TYPE (optype)))
- return fold_build1_loc (loc, REALPART_EXPR, type, op);
- /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */
- else if (VECTOR_TYPE_P (optype)
- && similar_type_p (type, TREE_TYPE (optype)))
- {
- tree part_width = TYPE_SIZE (type);
- tree index = bitsize_int (0);
- return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width,
- index);
- }
- /* Also handle conversion to an empty base class, which
- is represented with a NOP_EXPR. */
- else if (is_empty_class (type)
- && CLASS_TYPE_P (optype)
- && DERIVED_FROM_P (type, optype))
- {
- *empty_base = true;
- return op;
- }
- /* *(foo *)&struct_with_foo_field => COMPONENT_REF */
- else if (RECORD_OR_UNION_TYPE_P (optype))
- {
- tree field = TYPE_FIELDS (optype);
- for (; field; field = DECL_CHAIN (field))
- if (TREE_CODE (field) == FIELD_DECL
- && TREE_TYPE (field) != error_mark_node
- && integer_zerop (byte_position (field))
- && similar_type_p (TREE_TYPE (field), type))
- return fold_build3 (COMPONENT_REF, type, op, field, NULL_TREE);
- }
+ else
+ return cxx_fold_indirect_ref_1 (loc, type, op, 0, empty_base);
}
else if (TREE_CODE (sub) == POINTER_PLUS_EXPR
- && poly_int_tree_p (TREE_OPERAND (sub, 1), &const_op01))
+ && tree_fits_uhwi_p (TREE_OPERAND (sub, 1)))
{
tree op00 = TREE_OPERAND (sub, 0);
tree op01 = TREE_OPERAND (sub, 1);
STRIP_NOPS (op00);
if (TREE_CODE (op00) == ADDR_EXPR)
- {
- tree op00type;
- op00 = TREE_OPERAND (op00, 0);
- op00type = TREE_TYPE (op00);
-
- /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
- if (VECTOR_TYPE_P (op00type)
- && similar_type_p (type, TREE_TYPE (op00type))
- /* POINTER_PLUS_EXPR second operand is sizetype, unsigned,
- but we want to treat offsets with MSB set as negative.
- For the code below negative offsets are invalid and
- TYPE_SIZE of the element is something unsigned, so
- check whether op01 fits into poly_int64, which implies
- it is from 0 to INTTYPE_MAXIMUM (HOST_WIDE_INT), and
- then just use poly_uint64 because we want to treat the
- value as unsigned. */
- && tree_fits_poly_int64_p (op01))
- {
- tree part_width = TYPE_SIZE (type);
- poly_uint64 max_offset
- = (tree_to_uhwi (part_width) / BITS_PER_UNIT
- * TYPE_VECTOR_SUBPARTS (op00type));
- if (known_lt (const_op01, max_offset))
- {
- tree index = bitsize_int (const_op01 * BITS_PER_UNIT);
- return fold_build3_loc (loc,
- BIT_FIELD_REF, type, op00,
- part_width, index);
- }
- }
- /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
- else if (TREE_CODE (op00type) == COMPLEX_TYPE
- && similar_type_p (type, TREE_TYPE (op00type)))
- {
- if (known_eq (wi::to_poly_offset (TYPE_SIZE_UNIT (type)),
- const_op01))
- return fold_build1_loc (loc, IMAGPART_EXPR, type, op00);
- }
- /* ((foo *)&fooarray)[1] => fooarray[1] */
- else if (TREE_CODE (op00type) == ARRAY_TYPE
- && similar_type_p (type, TREE_TYPE (op00type)))
- {
- tree type_domain = TYPE_DOMAIN (op00type);
- tree min_val = size_zero_node;
- if (type_domain && TYPE_MIN_VALUE (type_domain))
- min_val = TYPE_MIN_VALUE (type_domain);
- offset_int off = wi::to_offset (op01);
- offset_int el_sz = wi::to_offset (TYPE_SIZE_UNIT (type));
- offset_int remainder;
- off = wi::divmod_trunc (off, el_sz, SIGNED, &remainder);
- if (remainder == 0 && TREE_CODE (min_val) == INTEGER_CST)
- {
- off = off + wi::to_offset (min_val);
- op01 = wide_int_to_tree (sizetype, off);
- return build4_loc (loc, ARRAY_REF, type, op00, op01,
- NULL_TREE, NULL_TREE);
- }
- }
- /* Also handle conversion to an empty base class, which
- is represented with a NOP_EXPR. */
- else if (is_empty_class (type)
- && CLASS_TYPE_P (op00type)
- && DERIVED_FROM_P (type, op00type))
- {
- *empty_base = true;
- return op00;
- }
- /* ((foo *)&struct_with_foo_field)[1] => COMPONENT_REF */
- else if (RECORD_OR_UNION_TYPE_P (op00type))
- {
- tree field = TYPE_FIELDS (op00type);
- for (; field; field = DECL_CHAIN (field))
- if (TREE_CODE (field) == FIELD_DECL
- && TREE_TYPE (field) != error_mark_node
- && tree_int_cst_equal (byte_position (field), op01)
- && similar_type_p (TREE_TYPE (field), type))
- return fold_build3 (COMPONENT_REF, type, op00,
- field, NULL_TREE);
- }
- }
+ return cxx_fold_indirect_ref_1 (loc, type, TREE_OPERAND (op00, 0),
+ tree_to_uhwi (op01), empty_base);
}
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
else if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
@@ -3645,7 +3692,23 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
static void
non_const_var_error (tree r)
{
+ auto_diagnostic_group d;
tree type = TREE_TYPE (r);
+ if (DECL_NAME (r) == heap_uninit_identifier
+ || DECL_NAME (r) == heap_identifier)
+ {
+ error ("the content of uninitialized storage is not usable "
+ "in a constant expression");
+ inform (DECL_SOURCE_LOCATION (r), "allocated here");
+ return;
+ }
+ if (DECL_NAME (r) == heap_deleted_identifier)
+ {
+ error ("use of allocated storage after deallocation in a "
+ "constant expression");
+ inform (DECL_SOURCE_LOCATION (r), "allocated here");
+ return;
+ }
error ("the value of %qD is not usable in a constant "
"expression", r);
/* Avoid error cascade. */
@@ -3889,7 +3952,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
DECL_NAME to handle TARGET_EXPR temporaries, which are fair game. */
valp = NULL;
else if (DECL_P (object))
- valp = ctx->values->get (object);
+ valp = ctx->global->values.get (object);
else
valp = NULL;
if (!valp)
@@ -3905,7 +3968,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
bool no_zero_init = true;
releasing_vec ctors;
- while (!refs->is_empty())
+ while (!refs->is_empty ())
{
if (*valp == NULL_TREE)
{
@@ -4046,7 +4109,9 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
if (const_object_being_modified)
{
bool fail = false;
- if (!CLASS_TYPE_P (TREE_TYPE (const_object_being_modified)))
+ tree const_objtype
+ = strip_array_types (TREE_TYPE (const_object_being_modified));
+ if (!CLASS_TYPE_P (const_objtype))
fail = true;
else
{
@@ -4089,7 +4154,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
non_constant_p, overflow_p);
if (ctors->is_empty())
/* The hash table might have moved since the get earlier. */
- valp = ctx->values->get (object);
+ valp = ctx->global->values.get (object);
}
/* Don't share a CONSTRUCTOR that might be changed later. */
@@ -4365,6 +4430,12 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
tree *jump_target)
{
constexpr_ctx new_ctx = *ctx;
+ tree local_target;
+ if (!jump_target)
+ {
+ local_target = NULL_TREE;
+ jump_target = &local_target;
+ }
tree body, cond = NULL_TREE, expr = NULL_TREE;
int count = 0;
@@ -4443,7 +4514,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
unsigned int i;
tree save_expr;
FOR_EACH_VEC_ELT (save_exprs, i, save_expr)
- new_ctx.values->remove (save_expr);
+ ctx->global->values.remove (save_expr);
save_exprs.truncate (0);
if (++count >= constexpr_loop_limit)
@@ -4467,7 +4538,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
unsigned int i;
tree save_expr;
FOR_EACH_VEC_ELT (save_exprs, i, save_expr)
- new_ctx.values->remove (save_expr);
+ ctx->global->values.remove (save_expr);
return NULL_TREE;
}
@@ -4619,14 +4690,14 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
}
/* Avoid excessively long constexpr evaluations. */
- if (++*ctx->constexpr_ops_count >= constexpr_ops_limit)
+ if (++ctx->global->constexpr_ops_count >= constexpr_ops_limit)
{
if (!ctx->quiet)
error_at (cp_expr_loc_or_input_loc (t),
"%<constexpr%> evaluation operation count exceeds limit of "
"%wd (use %<-fconstexpr-ops-limit=%> to increase the limit)",
constexpr_ops_limit);
- *ctx->constexpr_ops_count = INTTYPE_MINIMUM (HOST_WIDE_INT);
+ ctx->global->constexpr_ops_count = INTTYPE_MINIMUM (HOST_WIDE_INT);
*non_constant_p = true;
return t;
}
@@ -4643,7 +4714,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
/* We ask for an rvalue for the RESULT_DECL when indirecting
through an invisible reference, or in named return value
optimization. */
- if (tree *p = ctx->values->get (t))
+ if (tree *p = ctx->global->values.get (t))
return *p;
else
{
@@ -4699,7 +4770,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
&& TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR)
r = TARGET_EXPR_INITIAL (r);
if (VAR_P (r))
- if (tree *p = ctx->values->get (r))
+ if (tree *p = ctx->global->values.get (r))
if (*p != NULL_TREE)
r = *p;
if (DECL_P (r))
@@ -4726,7 +4797,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
case PARM_DECL:
if (lval && !TYPE_REF_P (TREE_TYPE (t)))
/* glvalue use. */;
- else if (tree *p = ctx->values->get (r))
+ else if (tree *p = ctx->global->values.get (r))
r = *p;
else if (lval)
/* Defer in case this is only used for its type. */;
@@ -4768,7 +4839,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
new_ctx.object = r;
new_ctx.ctor = build_constructor (TREE_TYPE (r), NULL);
CONSTRUCTOR_NO_CLEARING (new_ctx.ctor) = true;
- new_ctx.values->put (r, new_ctx.ctor);
+ ctx->global->values.put (r, new_ctx.ctor);
ctx = &new_ctx;
}
@@ -4784,12 +4855,12 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (CLASS_TYPE_P (TREE_TYPE (r))
&& CP_TYPE_CONST_P (TREE_TYPE (r)))
TREE_READONLY (init) = true;
- ctx->values->put (r, init);
+ ctx->global->values.put (r, init);
}
else if (ctx == &new_ctx)
/* We gave it a CONSTRUCTOR above. */;
else
- ctx->values->put (r, NULL_TREE);
+ ctx->global->values.put (r, NULL_TREE);
}
break;
@@ -4815,7 +4886,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
new_ctx.ctor = build_constructor (TREE_TYPE (t), NULL);
CONSTRUCTOR_NO_CLEARING (new_ctx.ctor) = true;
new_ctx.object = TARGET_EXPR_SLOT (t);
- ctx->values->put (new_ctx.object, new_ctx.ctor);
+ ctx->global->values.put (new_ctx.object, new_ctx.ctor);
ctx = &new_ctx;
}
/* Pass false for 'lval' because this indicates
@@ -4830,7 +4901,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
{
tree slot = TARGET_EXPR_SLOT (t);
r = unshare_constructor (r);
- ctx->values->put (slot, r);
+ ctx->global->values.put (slot, r);
return slot;
}
break;
@@ -4870,13 +4941,13 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
case SAVE_EXPR:
/* Avoid evaluating a SAVE_EXPR more than once. */
- if (tree *p = ctx->values->get (t))
+ if (tree *p = ctx->global->values.get (t))
r = *p;
else
{
r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), false,
non_constant_p, overflow_p);
- ctx->values->put (t, r);
+ ctx->global->values.put (t, r);
if (ctx->save_exprs)
ctx->save_exprs->safe_push (t);
}
@@ -4907,14 +4978,21 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
break;
case CLEANUP_STMT:
- r = cxx_eval_constant_expression (ctx, CLEANUP_BODY (t), lval,
+ {
+ tree initial_jump_target = jump_target ? *jump_target : NULL_TREE;
+ r = cxx_eval_constant_expression (ctx, CLEANUP_BODY (t), lval,
+ non_constant_p, overflow_p,
+ jump_target);
+ if (!CLEANUP_EH_ONLY (t) && !*non_constant_p)
+ /* Also evaluate the cleanup. If we weren't skipping at the
+ start of the CLEANUP_BODY, change jump_target temporarily
+ to &initial_jump_target, so that even a return or break or
+ continue in the body doesn't skip the cleanup. */
+ cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), true,
non_constant_p, overflow_p,
- jump_target);
- if (!CLEANUP_EH_ONLY (t) && !*non_constant_p)
- /* Also evaluate the cleanup. */
- cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), true,
- non_constant_p, overflow_p,
- jump_target);
+ jump_target ? &initial_jump_target
+ : NULL);
+ }
break;
/* These differ from cxx_eval_unary_expression in that this doesn't
@@ -5203,8 +5281,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (VOID_TYPE_P (type))
return void_node;
- if (TREE_CODE (op) == PTRMEM_CST
- && !TYPE_PTRMEM_P (type))
+ if (TREE_CODE (op) == PTRMEM_CST && !TYPE_PTRMEM_P (type))
op = cplus_expand_constant (op);
if (TREE_CODE (op) == PTRMEM_CST && tcode == NOP_EXPR)
@@ -5258,6 +5335,34 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
}
}
+ if (INDIRECT_TYPE_P (type)
+ && TREE_CODE (op) == NOP_EXPR
+ && TREE_TYPE (op) == ptr_type_node
+ && TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR
+ && VAR_P (TREE_OPERAND (TREE_OPERAND (op, 0), 0))
+ && DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
+ 0)) == heap_uninit_identifier)
+ {
+ tree var = TREE_OPERAND (TREE_OPERAND (op, 0), 0);
+ tree var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
+ tree elt_type = TREE_TYPE (type);
+ tree cookie_size = NULL_TREE;
+ if (TREE_CODE (elt_type) == RECORD_TYPE
+ && TYPE_NAME (elt_type) == heap_identifier)
+ {
+ tree fld1 = TYPE_FIELDS (elt_type);
+ tree fld2 = DECL_CHAIN (fld1);
+ elt_type = TREE_TYPE (TREE_TYPE (fld2));
+ cookie_size = TYPE_SIZE_UNIT (TREE_TYPE (fld1));
+ }
+ DECL_NAME (var) = heap_identifier;
+ TREE_TYPE (var)
+ = build_new_constexpr_heap_type (elt_type, cookie_size,
+ var_size);
+ TREE_TYPE (TREE_OPERAND (op, 0))
+ = build_pointer_type (TREE_TYPE (var));
+ }
+
if (op == oldop && tcode != UNARY_PLUS_EXPR)
/* We didn't fold at the top so we could check for ptr-int
conversion. */
@@ -5499,6 +5604,7 @@ instantiate_cx_fn_r (tree *tp, int *walk_subtrees, void */*data*/)
return NULL_TREE;
}
+
static void
instantiate_constexpr_fns (tree t)
{
@@ -5507,34 +5613,58 @@ instantiate_constexpr_fns (tree t)
input_location = loc;
}
+/* Look for heap variables in the expression *TP. */
+
+static tree
+find_heap_var_refs (tree *tp, int *walk_subtrees, void */*data*/)
+{
+ if (VAR_P (*tp)
+ && (DECL_NAME (*tp) == heap_uninit_identifier
+ || DECL_NAME (*tp) == heap_identifier
+ || DECL_NAME (*tp) == heap_deleted_identifier))
+ return *tp;
+
+ if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+ return NULL_TREE;
+}
+
/* ALLOW_NON_CONSTANT is false if T is required to be a constant expression.
STRICT has the same sense as for constant_value_1: true if we only allow
conforming C++ constant expressions, or false if we want a constant value
even if it doesn't conform.
MANIFESTLY_CONST_EVAL is true if T is manifestly const-evaluated as
- per P0595 even when ALLOW_NON_CONSTANT is true. */
+ per P0595 even when ALLOW_NON_CONSTANT is true.
+ CONSTEXPR_DTOR is true when evaluating the dtor of a constexpr variable.
+ OBJECT must be non-NULL in that case. */
static tree
cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
bool strict = true,
bool manifestly_const_eval = false,
+ bool constexpr_dtor = false,
tree object = NULL_TREE)
{
auto_timevar time (TV_CONSTEXPR);
bool non_constant_p = false;
bool overflow_p = false;
- hash_map<tree,tree> map;
- HOST_WIDE_INT constexpr_ctx_count = 0;
- constexpr_ctx ctx = { NULL, &map, NULL, NULL, NULL, NULL,
- &constexpr_ctx_count, allow_non_constant, strict,
+ constexpr_global_ctx global_ctx;
+ constexpr_ctx ctx = { &global_ctx, NULL, NULL, NULL, NULL, NULL,
+ allow_non_constant, strict,
manifestly_const_eval || !allow_non_constant };
tree type = initialized_type (t);
tree r = t;
if (VOID_TYPE_P (type))
- return t;
+ {
+ if (constexpr_dtor)
+ /* Used for destructors of array elements. */
+ type = TREE_TYPE (object);
+ else
+ return t;
+ }
if (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type))
{
/* In C++14 an NSDMI can participate in aggregate initialization,
@@ -5544,8 +5674,22 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
update ctx.values for the VAR_DECL. We use the same strategy
for C++11 constexpr constructors that refer to the object being
initialized. */
- ctx.ctor = build_constructor (type, NULL);
- CONSTRUCTOR_NO_CLEARING (ctx.ctor) = true;
+ if (constexpr_dtor)
+ {
+ gcc_assert (object && VAR_P (object));
+ gcc_assert (DECL_DECLARED_CONSTEXPR_P (object));
+ gcc_assert (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (object));
+ ctx.ctor = unshare_expr (DECL_INITIAL (object));
+ TREE_READONLY (ctx.ctor) = false;
+ /* Temporarily force decl_really_constant_value to return false
+ for it, we want to use ctx.ctor for the current value instead. */
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (object) = false;
+ }
+ else
+ {
+ ctx.ctor = build_constructor (type, NULL);
+ CONSTRUCTOR_NO_CLEARING (ctx.ctor) = true;
+ }
if (!object)
{
if (TREE_CODE (t) == TARGET_EXPR)
@@ -5558,7 +5702,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
gcc_assert (same_type_ignoring_top_level_qualifiers_p
(type, TREE_TYPE (object)));
if (object && DECL_P (object))
- map.put (object, ctx.ctor);
+ global_ctx.values.put (object, ctx.ctor);
if (TREE_CODE (r) == TARGET_EXPR)
/* Avoid creating another CONSTRUCTOR when we expand the
TARGET_EXPR. */
@@ -5569,13 +5713,15 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
r = cxx_eval_constant_expression (&ctx, r,
false, &non_constant_p, &overflow_p);
- verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);
+ if (!constexpr_dtor)
+ verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);
+ else
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (object) = true;
/* Mutable logic is a bit tricky: we want to allow initialization of
constexpr variables with mutable members, but we can't copy those
members to another constexpr variable. */
- if (TREE_CODE (r) == CONSTRUCTOR
- && CONSTRUCTOR_MUTABLE_POISON (r))
+ if (TREE_CODE (r) == CONSTRUCTOR && CONSTRUCTOR_MUTABLE_POISON (r))
{
if (!allow_non_constant)
error ("%qE is not a constant expression because it refers to "
@@ -5583,8 +5729,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
non_constant_p = true;
}
- if (TREE_CODE (r) == CONSTRUCTOR
- && CONSTRUCTOR_NO_CLEARING (r))
+ if (TREE_CODE (r) == CONSTRUCTOR && CONSTRUCTOR_NO_CLEARING (r))
{
if (!allow_non_constant)
error ("%qE is not a constant expression because it refers to "
@@ -5593,6 +5738,32 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
non_constant_p = true;
}
+ if (!global_ctx.heap_vars.is_empty ())
+ {
+ tree heap_var = cp_walk_tree_without_duplicates (&r, find_heap_var_refs,
+ NULL);
+ unsigned int i;
+ if (heap_var)
+ {
+ if (!allow_non_constant && !non_constant_p)
+ error_at (DECL_SOURCE_LOCATION (heap_var),
+ "%qE is not a constant expression because it refers to "
+ "a result of %<operator new%>", t);
+ r = t;
+ non_constant_p = true;
+ }
+ FOR_EACH_VEC_ELT (global_ctx.heap_vars, i, heap_var)
+ if (DECL_NAME (heap_var) != heap_deleted_identifier)
+ {
+ if (!allow_non_constant && !non_constant_p)
+ error_at (DECL_SOURCE_LOCATION (heap_var),
+ "%qE is not a constant expression because allocated "
+ "storage has not been deallocated", t);
+ r = t;
+ non_constant_p = true;
+ }
+ }
+
/* Technically we should check this for all subexpressions, but that
runs into problems with our internal representation of pointer
subtraction and the 5.19 rules are still in flux. */
@@ -5618,6 +5789,8 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
if (non_constant_p && !allow_non_constant)
return error_mark_node;
+ else if (constexpr_dtor)
+ return r;
else if (non_constant_p && TREE_CONSTANT (r))
{
/* If __builtin_is_constant_evaluated () was evaluated to true
@@ -5625,7 +5798,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
punt. */
if (manifestly_const_eval)
return cxx_eval_outermost_constant_expr (t, true, strict,
- false, object);
+ false, false, object);
/* This isn't actually constant, so unset TREE_CONSTANT.
Don't clear TREE_CONSTANT on ADDR_EXPR, as the middle-end requires
it to be set if it is invariant address, even when it is not
@@ -5653,7 +5826,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
return t;
else if (TREE_CODE (t) != CONSTRUCTOR)
{
- r = get_target_expr (r);
+ r = get_target_expr_sfinae (r, tf_warning_or_error | tf_no_cleanup);
TREE_CONSTANT (r) = true;
}
}
@@ -5668,7 +5841,16 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
tree
cxx_constant_value (tree t, tree decl)
{
- return cxx_eval_outermost_constant_expr (t, false, true, true, decl);
+ return cxx_eval_outermost_constant_expr (t, false, true, true, false, decl);
+}
+
+/* Like cxx_constant_value, but used for evaluation of constexpr destructors
+ of constexpr variables. The actual initializer of DECL is not modified. */
+
+void
+cxx_constant_dtor (tree t, tree decl)
+{
+ cxx_eval_outermost_constant_expr (t, false, true, true, true, decl);
}
/* Helper routine for fold_simple function. Either return simplified
@@ -5772,14 +5954,14 @@ maybe_constant_value (tree t, tree decl, bool manifestly_const_eval)
return t;
if (manifestly_const_eval)
- return cxx_eval_outermost_constant_expr (t, true, true, true, decl);
+ return cxx_eval_outermost_constant_expr (t, true, true, true, false, decl);
if (cv_cache == NULL)
cv_cache = hash_map<tree, tree>::create_ggc (101);
if (tree *cached = cv_cache->get (t))
return *cached;
- r = cxx_eval_outermost_constant_expr (t, true, true, false, decl);
+ r = cxx_eval_outermost_constant_expr (t, true, true, false, false, decl);
gcc_checking_assert (r == t
|| CONVERT_EXPR_P (t)
|| TREE_CODE (t) == VIEW_CONVERT_EXPR
@@ -5841,7 +6023,7 @@ fold_non_dependent_expr_template (tree t, tsubst_flags_t complain,
tree r = cxx_eval_outermost_constant_expr (t, true, true,
manifestly_const_eval,
- NULL_TREE);
+ false, NULL_TREE);
/* cp_tree_equal looks through NOPs, so allow them. */
gcc_checking_assert (r == t
|| CONVERT_EXPR_P (t)
@@ -5945,7 +6127,7 @@ maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant,
else
t = cxx_eval_outermost_constant_expr (t, allow_non_constant,
/*strict*/false,
- manifestly_const_eval, decl);
+ manifestly_const_eval, false, decl);
if (TREE_CODE (t) == TARGET_EXPR)
{
tree init = TARGET_EXPR_INITIAL (t);
@@ -6239,7 +6421,10 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
if (!DECL_DECLARED_CONSTEXPR_P (fun)
/* Allow any built-in function; if the expansion
isn't constant, we'll deal with that then. */
- && !fndecl_built_in_p (fun))
+ && !fndecl_built_in_p (fun)
+ /* In C++2a, replaceable global allocation functions
+ are constant expressions. */
+ && !cxx_replaceable_global_alloc_fn (fun))
{
if (flags & tf_error)
{
@@ -6468,6 +6653,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
goto fail;
if (!RECUR (TREE_OPERAND (t, 0), any))
return false;
+ /* Just ignore clobbers. */
+ if (TREE_CLOBBER_P (TREE_OPERAND (t, 1)))
+ return true;
if (!RECUR (TREE_OPERAND (t, 1), rval))
return false;
return true;
@@ -6937,7 +7125,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return true;
case COND_EXPR:
- if (COND_EXPR_IS_VEC_DELETE (t))
+ if (COND_EXPR_IS_VEC_DELETE (t) && cxx_dialect < cxx2a)
{
if (flags & tf_error)
error_at (loc, "%<delete[]%> is not a constant expression");
@@ -6983,6 +7171,12 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return true;
case CLEANUP_STMT:
+ if (!RECUR (CLEANUP_BODY (t), any))
+ return false;
+ if (!CLEANUP_EH_ONLY (t) && !RECUR (CLEANUP_EXPR (t), any))
+ return false;
+ return true;
+
case EMPTY_CLASS_EXPR:
case PREDICT_EXPR:
return false;
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 8bda7361bc4..65453929d31 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -818,6 +818,21 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
case CALL_EXPR:
ret = GS_OK;
+ if (flag_strong_eval_order == 2
+ && CALL_EXPR_FN (*expr_p)
+ && cp_get_callee_fndecl_nofold (*expr_p) == NULL_TREE)
+ {
+ enum gimplify_status t
+ = gimplify_expr (&CALL_EXPR_FN (*expr_p), pre_p, NULL,
+ is_gimple_call_addr, fb_rvalue);
+ if (t == GS_ERROR)
+ ret = GS_ERROR;
+ else if (is_gimple_variable (CALL_EXPR_FN (*expr_p))
+ && TREE_CODE (CALL_EXPR_FN (*expr_p)) != SSA_NAME)
+ CALL_EXPR_FN (*expr_p)
+ = get_initialized_tmp_var (CALL_EXPR_FN (*expr_p), pre_p,
+ NULL);
+ }
if (!CALL_EXPR_FN (*expr_p))
/* Internal function call. */;
else if (CALL_EXPR_REVERSE_ARGS (*expr_p))
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index 4369a5b5570..0a72231456b 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -145,11 +145,9 @@ cp_get_debug_type (const_tree type)
if (dtype)
{
tree ktype = CONST_CAST_TREE (type);
- if (debug_type_map == NULL)
- debug_type_map = tree_cache_map::create_ggc (512);
- else if (tree *slot = debug_type_map->get (ktype))
+ if (tree *slot = hash_map_safe_get (debug_type_map, ktype))
return *slot;
- debug_type_map->put (ktype, dtype);
+ hash_map_safe_put<hm_ggc> (debug_type_map, ktype, dtype);
}
return dtype;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index be1a44e4373..b82b5808197 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -172,6 +172,9 @@ enum cp_tree_index
CPTI_VALUE_IDENTIFIER,
CPTI_FUN_IDENTIFIER,
CPTI_CLOSURE_IDENTIFIER,
+ CPTI_HEAP_UNINIT_IDENTIFIER,
+ CPTI_HEAP_IDENTIFIER,
+ CPTI_HEAP_DELETED_IDENTIFIER,
CPTI_LANG_NAME_C,
CPTI_LANG_NAME_CPLUSPLUS,
@@ -310,6 +313,9 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
#define value_identifier cp_global_trees[CPTI_VALUE_IDENTIFIER]
#define fun_identifier cp_global_trees[CPTI_FUN_IDENTIFIER]
#define closure_identifier cp_global_trees[CPTI_CLOSURE_IDENTIFIER]
+#define heap_uninit_identifier cp_global_trees[CPTI_HEAP_UNINIT_IDENTIFIER]
+#define heap_identifier cp_global_trees[CPTI_HEAP_IDENTIFIER]
+#define heap_deleted_identifier cp_global_trees[CPTI_HEAP_DELETED_IDENTIFIER]
#define lang_name_c cp_global_trees[CPTI_LANG_NAME_C]
#define lang_name_cplusplus cp_global_trees[CPTI_LANG_NAME_CPLUSPLUS]
@@ -6342,6 +6348,7 @@ extern bool vbase_has_user_provided_move_assign (tree);
extern tree default_init_uninitialized_part (tree);
extern bool trivial_default_constructor_is_constexpr (tree);
extern bool type_has_constexpr_default_constructor (tree);
+extern bool type_has_constexpr_destructor (tree);
extern bool type_has_virtual_destructor (tree);
extern bool classtype_has_move_assign_or_move_ctor_p (tree, bool user_declared);
extern bool classtype_has_non_deleted_move_ctor (tree);
@@ -6648,6 +6655,7 @@ extern tree build_offset_ref (tree, tree, bool,
extern tree throw_bad_array_new_length (void);
extern bool type_has_new_extended_alignment (tree);
extern unsigned malloc_alignment (void);
+extern tree build_new_constexpr_heap_type (tree, tree, tree);
extern tree build_new (vec<tree, va_gc> **, tree, tree,
vec<tree, va_gc> **, int,
tsubst_flags_t);
@@ -7747,6 +7755,7 @@ extern bool require_constant_expression (tree);
extern bool require_rvalue_constant_expression (tree);
extern bool require_potential_rvalue_constant_expression (tree);
extern tree cxx_constant_value (tree, tree = NULL_TREE);
+extern void cxx_constant_dtor (tree, tree);
extern tree cxx_constant_init (tree, tree = NULL_TREE);
extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false);
extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 67c4521e98c..e4053679362 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4146,6 +4146,9 @@ initialize_predefined_identifiers (void)
{"value", &value_identifier, cik_normal},
{"_FUN", &fun_identifier, cik_normal},
{"__closure", &closure_identifier, cik_normal},
+ {"heap uninit", &heap_uninit_identifier, cik_normal},
+ {"heap ", &heap_identifier, cik_normal},
+ {"heap deleted", &heap_deleted_identifier, cik_normal},
{NULL, NULL, cik_normal}
};
@@ -7006,6 +7009,19 @@ notice_forced_label_r (tree *tp, int *walk_subtrees, void *)
return NULL_TREE;
}
+/* Return true if DECL has either a trivial destructor, or for C++2A
+ is constexpr and has a constexpr destructor. */
+
+static bool
+decl_maybe_constant_destruction (tree decl, tree type)
+{
+ return (TYPE_HAS_TRIVIAL_DESTRUCTOR (type)
+ || (cxx_dialect >= cxx2a
+ && VAR_P (decl)
+ && DECL_DECLARED_CONSTEXPR_P (decl)
+ && type_has_constexpr_destructor (strip_array_types (type))));
+}
+
/* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
@@ -7430,7 +7446,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
TREE_READONLY (decl) = 1;
/* Likewise if it needs destruction. */
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ if (!decl_maybe_constant_destruction (decl, type))
TREE_READONLY (decl) = 0;
}
@@ -7704,13 +7720,6 @@ get_tuple_decomp_init (tree decl, unsigned i)
based on the actual type of the variable, so store it in a hash table. */
static GTY((cache)) tree_cache_map *decomp_type_table;
-static void
-store_decomp_type (tree v, tree t)
-{
- if (!decomp_type_table)
- decomp_type_table = tree_cache_map::create_ggc (13);
- decomp_type_table->put (v, t);
-}
tree
lookup_decomp_type (tree v)
@@ -7946,7 +7955,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
goto error_out;
}
/* Save the decltype away before reference collapse. */
- store_decomp_type (v[i], eltype);
+ hash_map_safe_put<hm_ggc> (decomp_type_table, v[i], eltype);
eltype = cp_build_reference_type (eltype, !lvalue_p (init));
TREE_TYPE (v[i]) = eltype;
layout_decl (v[i], 0);
@@ -8319,6 +8328,13 @@ register_dtor_fn (tree decl)
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
return void_node;
+ if (decl_maybe_constant_destruction (decl, type)
+ && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+ {
+ cxx_maybe_build_cleanup (decl, tf_warning_or_error);
+ 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
destructor to "__cxa_atexit"; we don't have to build a temporary
@@ -8436,7 +8452,7 @@ expand_static_init (tree decl, tree init)
gcc_assert (TREE_STATIC (decl));
/* Some variables require no dynamic initialization. */
- if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+ if (decl_maybe_constant_destruction (decl, TREE_TYPE (decl)))
{
/* Make sure the destructor is callable. */
cxx_maybe_build_cleanup (decl, tf_warning_or_error);
@@ -9665,10 +9681,12 @@ build_ptrmemfunc_type (tree type)
TYPE_PTRMEMFUNC_FLAG (t) = 1;
field = build_decl (input_location, FIELD_DECL, pfn_identifier, type);
+ DECL_NONADDRESSABLE_P (field) = 1;
fields = field;
field = build_decl (input_location, FIELD_DECL, delta_identifier,
delta_type_node);
+ DECL_NONADDRESSABLE_P (field) = 1;
DECL_CHAIN (field) = fields;
fields = field;
@@ -12702,12 +12720,13 @@ grokdeclarator (const cp_declarator *declarator,
"a destructor cannot be %<concept%>");
return error_mark_node;
}
- if (constexpr_p)
- {
- error_at (declspecs->locations[ds_constexpr],
- "a destructor cannot be %<constexpr%>");
- return error_mark_node;
- }
+ if (constexpr_p && cxx_dialect < cxx2a)
+ {
+ error_at (declspecs->locations[ds_constexpr],
+ "%<constexpr%> destructors only available"
+ " with %<-std=c++2a%> or %<-std=gnu++2a%>");
+ return error_mark_node;
+ }
}
else if (sfk == sfk_constructor && friendp && !ctype)
{
@@ -12735,8 +12754,8 @@ grokdeclarator (const cp_declarator *declarator,
tree tmpl = TREE_OPERAND (unqualified_id, 0);
if (variable_template_p (tmpl))
{
- error ("specialization of variable template %qD "
- "declared as function", tmpl);
+ error_at (id_loc, "specialization of variable template "
+ "%qD declared as function", tmpl);
inform (DECL_SOURCE_LOCATION (tmpl),
"variable template declared here");
return error_mark_node;
@@ -12744,10 +12763,11 @@ grokdeclarator (const cp_declarator *declarator,
}
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
- function_context = (ctype != NULL_TREE) ?
- decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
- publicp = (! friendp || ! staticp)
- && function_context == NULL_TREE;
+ function_context
+ = (ctype != NULL_TREE
+ ? decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE);
+ publicp = ((! friendp || ! staticp)
+ && function_context == NULL_TREE);
decl = grokfndecl (ctype, type,
TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
@@ -16747,6 +16767,9 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
cleanup = error_mark_node;
else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
/* Discard the call. */;
+ else if (decl_maybe_constant_destruction (decl, type)
+ && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+ cxx_constant_dtor (call, decl);
else if (cleanup)
cleanup = cp_build_compound_expr (cleanup, call, complain);
else
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 8f935e8656d..a28e7762a34 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1608,7 +1608,8 @@ build_anon_union_vars (tree type, tree object)
just give an error. */
if (TREE_CODE (type) != UNION_TYPE)
{
- error ("anonymous struct not inside named type");
+ error_at (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
+ "anonymous struct not inside named type");
return error_mark_node;
}
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 67e06568b2f..1c51e26febe 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h"
#include "attribs.h"
#include "asan.h"
+#include "stor-layout.h"
static bool begin_init_stmts (tree *, tree *);
static tree finish_init_stmts (bool, tree, tree);
@@ -563,10 +564,9 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
init = DECL_INITIAL (DECL_TI_TEMPLATE (member));
location_t expr_loc
= cp_expr_loc_or_loc (init, DECL_SOURCE_LOCATION (member));
- tree *slot;
if (TREE_CODE (init) == DEFERRED_PARSE)
/* Unparsed. */;
- else if (nsdmi_inst && (slot = nsdmi_inst->get (member)))
+ else if (tree *slot = hash_map_safe_get (nsdmi_inst, member))
init = *slot;
/* Check recursive instantiation. */
else if (DECL_INSTANTIATING_NSDMI_P (member))
@@ -611,11 +611,7 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
DECL_INSTANTIATING_NSDMI_P (member) = 0;
if (init != error_mark_node)
- {
- if (!nsdmi_inst)
- nsdmi_inst = tree_cache_map::create_ggc (37);
- nsdmi_inst->put (member, init);
- }
+ hash_map_safe_put<hm_ggc> (nsdmi_inst, member, init);
if (pushed)
{
@@ -2865,6 +2861,82 @@ std_placement_new_fn_p (tree alloc_fn)
return false;
}
+/* For element type ELT_TYPE, return the appropriate type of the heap object
+ containing such element(s). COOKIE_SIZE is NULL or the size of cookie
+ in bytes. FULL_SIZE is NULL if it is unknown how big the heap allocation
+ will be, otherwise size of the heap object. If COOKIE_SIZE is NULL,
+ return array type ELT_TYPE[FULL_SIZE / sizeof(ELT_TYPE)], otherwise return
+ struct { size_t[COOKIE_SIZE/sizeof(size_t)]; ELT_TYPE[N]; }
+ where N is nothing (flexible array member) if FULL_SIZE is NULL, otherwise
+ it is computed such that the size of the struct fits into FULL_SIZE. */
+
+tree
+build_new_constexpr_heap_type (tree elt_type, tree cookie_size, tree full_size)
+{
+ gcc_assert (cookie_size == NULL_TREE || tree_fits_uhwi_p (cookie_size));
+ gcc_assert (full_size == NULL_TREE || tree_fits_uhwi_p (full_size));
+ unsigned HOST_WIDE_INT csz = cookie_size ? tree_to_uhwi (cookie_size) : 0;
+ tree itype2 = NULL_TREE;
+ if (full_size)
+ {
+ unsigned HOST_WIDE_INT fsz = tree_to_uhwi (full_size);
+ gcc_assert (fsz >= csz);
+ fsz -= csz;
+ fsz /= int_size_in_bytes (elt_type);
+ itype2 = build_index_type (size_int (fsz - 1));
+ if (!cookie_size)
+ return build_cplus_array_type (elt_type, itype2);
+ }
+ else
+ gcc_assert (cookie_size);
+ csz /= int_size_in_bytes (sizetype);
+ tree itype1 = build_index_type (size_int (csz - 1));
+ tree atype1 = build_cplus_array_type (sizetype, itype1);
+ tree atype2 = build_cplus_array_type (elt_type, itype2);
+ tree rtype = cxx_make_type (RECORD_TYPE);
+ TYPE_NAME (rtype) = heap_identifier;
+ tree fld1 = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, atype1);
+ tree fld2 = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, atype2);
+ DECL_FIELD_CONTEXT (fld1) = rtype;
+ DECL_FIELD_CONTEXT (fld2) = rtype;
+ DECL_ARTIFICIAL (fld1) = true;
+ DECL_ARTIFICIAL (fld2) = true;
+ TYPE_FIELDS (rtype) = fld1;
+ DECL_CHAIN (fld1) = fld2;
+ layout_type (rtype);
+ return rtype;
+}
+
+/* Help the constexpr code to find the right type for the heap variable
+ by adding a NOP_EXPR around ALLOC_CALL if needed for cookie_size.
+ Return ALLOC_CALL or ALLOC_CALL cast to a pointer to
+ struct { size_t[cookie_size/sizeof(size_t)]; elt_type[]; }. */
+
+static tree
+maybe_wrap_new_for_constexpr (tree alloc_call, tree elt_type, tree cookie_size)
+{
+ if (cxx_dialect < cxx2a)
+ return alloc_call;
+
+ if (current_function_decl != NULL_TREE
+ && !DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+ return alloc_call;
+
+ tree call_expr = extract_call_expr (alloc_call);
+ if (call_expr == error_mark_node)
+ return alloc_call;
+
+ tree alloc_call_fndecl = cp_get_callee_fndecl_nofold (call_expr);
+ if (alloc_call_fndecl == NULL_TREE
+ || !IDENTIFIER_NEW_OP_P (DECL_NAME (alloc_call_fndecl))
+ || CP_DECL_CONTEXT (alloc_call_fndecl) != global_namespace)
+ return alloc_call;
+
+ tree rtype = build_new_constexpr_heap_type (elt_type, cookie_size,
+ NULL_TREE);
+ return build_nop (build_pointer_type (rtype), alloc_call);
+}
+
/* Generate code for a new-expression, including calling the "operator
new" function, initializing the object, and, if an exception occurs
during construction, cleaning up. The arguments are as for
@@ -3332,6 +3404,10 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
}
}
+ if (cookie_size)
+ alloc_call = maybe_wrap_new_for_constexpr (alloc_call, elt_type,
+ cookie_size);
+
/* In the simple case, we can stop now. */
pointer_type = build_pointer_type (type);
if (!cookie_size && !is_initialized)
@@ -3759,7 +3835,8 @@ build_new (vec<tree, va_gc> **placement, tree type, tree nelts,
if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
{
if (complain & tf_error)
- permerror (input_location, "size in array new must have integral type");
+ permerror (cp_expr_loc_or_input_loc (nelts),
+ "size in array new must have integral type");
else
return error_mark_node;
}
@@ -3774,7 +3851,8 @@ build_new (vec<tree, va_gc> **placement, tree type, tree nelts,
less than zero. ... If the expression is a constant expression,
the program is ill-fomed. */
if (TREE_CODE (cst_nelts) == INTEGER_CST
- && !valid_array_size_p (input_location, cst_nelts, NULL_TREE,
+ && !valid_array_size_p (cp_expr_loc_or_input_loc (nelts),
+ cst_nelts, NULL_TREE,
complain & tf_error))
return error_mark_node;
@@ -3905,17 +3983,11 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
fold_convert (sizetype, maxindex));
tbase = create_temporary_var (ptype);
- tbase_init
- = cp_build_modify_expr (input_location, tbase, NOP_EXPR,
- fold_build_pointer_plus_loc (input_location,
- fold_convert (ptype,
- base),
- virtual_size),
- complain);
- if (tbase_init == error_mark_node)
- return error_mark_node;
- controller = build3 (BIND_EXPR, void_type_node, tbase,
- NULL_TREE, NULL_TREE);
+ DECL_INITIAL (tbase)
+ = fold_build_pointer_plus_loc (input_location, fold_convert (ptype, base),
+ virtual_size);
+ tbase_init = build_stmt (input_location, DECL_EXPR, tbase);
+ controller = build3 (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (controller) = 1;
body = build1 (EXIT_EXPR, void_type_node,
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 53fa85b9790..01bf534aef2 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "varasm.h"
#include "toplev.h"
+#include "intl.h"
#include "common/common-target.h"
static void do_build_copy_assign (tree);
@@ -1237,12 +1238,24 @@ is_xible (enum tree_code code, tree to, tree from)
return !!expr;
}
+/* Categorize various special_function_kinds. */
+#define SFK_CTOR_P(sfk) \
+ ((sfk) >= sfk_constructor && (sfk) <= sfk_move_constructor)
+#define SFK_DTOR_P(sfk) \
+ ((sfk) == sfk_destructor || (sfk) == sfk_virtual_destructor)
+#define SFK_ASSIGN_P(sfk) \
+ ((sfk) == sfk_copy_assignment || (sfk) == sfk_move_assignment)
+#define SFK_COPY_P(sfk) \
+ ((sfk) == sfk_copy_constructor || (sfk) == sfk_copy_assignment)
+#define SFK_MOVE_P(sfk) \
+ ((sfk) == sfk_move_constructor || (sfk) == sfk_move_assignment)
+
/* Subroutine of synthesized_method_walk. Update SPEC_P, TRIVIAL_P and
DELETED_P or give an error message MSG with argument ARG. */
static void
-process_subob_fn (tree fn, tree *spec_p, bool *trivial_p,
- bool *deleted_p, bool *constexpr_p,
+process_subob_fn (tree fn, special_function_kind sfk, tree *spec_p,
+ bool *trivial_p, bool *deleted_p, bool *constexpr_p,
bool diag, tree arg, bool dtor_from_ctor = false)
{
if (!fn || fn == error_mark_node)
@@ -1283,24 +1296,15 @@ process_subob_fn (tree fn, tree *spec_p, bool *trivial_p,
if (diag)
{
inform (DECL_SOURCE_LOCATION (fn),
- "defaulted constructor calls non-%<constexpr%> %qD", fn);
+ SFK_DTOR_P (sfk)
+ ? G_("defaulted destructor calls non-%<constexpr%> %qD")
+ : G_("defaulted constructor calls non-%<constexpr%> %qD"),
+ fn);
explain_invalid_constexpr_fn (fn);
}
}
}
-/* Categorize various special_function_kinds. */
-#define SFK_CTOR_P(sfk) \
- ((sfk) >= sfk_constructor && (sfk) <= sfk_move_constructor)
-#define SFK_DTOR_P(sfk) \
- ((sfk) == sfk_destructor || (sfk) == sfk_virtual_destructor)
-#define SFK_ASSIGN_P(sfk) \
- ((sfk) == sfk_copy_assignment || (sfk) == sfk_move_assignment)
-#define SFK_COPY_P(sfk) \
- ((sfk) == sfk_copy_constructor || (sfk) == sfk_copy_assignment)
-#define SFK_MOVE_P(sfk) \
- ((sfk) == sfk_move_constructor || (sfk) == sfk_move_assignment)
-
/* Subroutine of synthesized_method_walk to allow recursion into anonymous
aggregates. If DTOR_FROM_CTOR is true, we're walking subobject destructors
called from a synthesized constructor, in which case we don't consider
@@ -1318,8 +1322,7 @@ walk_field_subobs (tree fields, special_function_kind sfk, tree fnname,
{
tree mem_type, argtype, rval;
- if (TREE_CODE (field) != FIELD_DECL
- || DECL_ARTIFICIAL (field))
+ if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
/* Variant members only affect deletedness. In particular, they don't
@@ -1457,7 +1460,7 @@ walk_field_subobs (tree fields, special_function_kind sfk, tree fnname,
rval = locate_fn_flags (mem_type, fnname, argtype, flags, complain);
- process_subob_fn (rval, spec_p, trivial_p, deleted_p,
+ process_subob_fn (rval, sfk, spec_p, trivial_p, deleted_p,
constexpr_p, diag, field, dtor_from_ctor);
}
}
@@ -1510,23 +1513,23 @@ synthesized_method_base_walk (tree binfo, tree base_binfo,
&& DECL_CONTEXT (*inheriting_ctor) == DECL_CONTEXT (rval))
*inheriting_ctor = DECL_CLONED_FUNCTION (rval);
- process_subob_fn (rval, spec_p, trivial_p, deleted_p,
+ process_subob_fn (rval, sfk, spec_p, trivial_p, deleted_p,
constexpr_p, diag, BINFO_TYPE (base_binfo));
- if (SFK_CTOR_P (sfk) &&
- (!BINFO_VIRTUAL_P (base_binfo)
- || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))))
+ if (SFK_CTOR_P (sfk)
+ && (!BINFO_VIRTUAL_P (base_binfo)
+ || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))))
{
/* In a constructor we also need to check the subobject
destructors for cleanup of partially constructed objects. */
tree dtor = locate_fn_flags (base_binfo, complete_dtor_identifier,
NULL_TREE, flags,
diag ? tf_warning_or_error : tf_none);
- /* Note that we don't pass down trivial_p; the subobject
- destructors don't affect triviality of the constructor. Nor
- do they affect constexpr-ness (a constant expression doesn't
- throw) or exception-specification (a throw from one of the
- dtors would be a double-fault). */
- process_subob_fn (dtor, NULL, NULL, deleted_p, NULL, false,
+ /* Note that we don't pass down trivial_p; the subobject
+ destructors don't affect triviality of the constructor. Nor
+ do they affect constexpr-ness (a constant expression doesn't
+ throw) or exception-specification (a throw from one of the
+ dtors would be a double-fault). */
+ process_subob_fn (dtor, sfk, NULL, NULL, deleted_p, NULL, false,
BINFO_TYPE (base_binfo), /*dtor_from_ctor*/true);
}
@@ -1608,7 +1611,8 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
member is a constexpr function. */
if (constexpr_p)
*constexpr_p = (SFK_CTOR_P (sfk)
- || (SFK_ASSIGN_P (sfk) && cxx_dialect >= cxx14));
+ || (SFK_ASSIGN_P (sfk) && cxx_dialect >= cxx14)
+ || (SFK_DTOR_P (sfk) && cxx_dialect >= cxx2a));
bool expected_trivial = type_has_trivial_fn (ctype, sfk);
if (trivial_p)
@@ -1704,8 +1708,8 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
else if (vec_safe_is_empty (vbases))
/* No virtual bases to worry about. */;
else if (ABSTRACT_CLASS_TYPE_P (ctype) && cxx_dialect >= cxx14
- /* DR 1658 specifis that vbases of abstract classes are
- ignored for both ctors and dtors. Except DR 2338
+ /* DR 1658 specifies that vbases of abstract classes are
+ ignored for both ctors and dtors. Except DR 2336
overrides that skipping when determing the eh-spec of a
virtual destructor. */
&& sfk != sfk_virtual_destructor)
@@ -2046,7 +2050,8 @@ implicitly_declare_fn (special_function_kind kind, tree type,
constexpr_p = false;
/* A trivial copy/move constructor is also a constexpr constructor,
unless the class has virtual bases (7.1.5p4). */
- else if (trivial_p && cxx_dialect >= cxx11
+ else if (trivial_p
+ && cxx_dialect >= cxx11
&& (kind == sfk_copy_constructor
|| kind == sfk_move_constructor)
&& !CLASSTYPE_VBASECLASSES (type))
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 4d01a54055e..ff6d5ee6984 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3080,8 +3080,9 @@ do_pushdecl (tree decl, bool is_friend)
/* In a local class, a friend function declaration must
find a matching decl in the innermost non-class scope.
[class.friend/11] */
- error ("friend declaration %qD in local class without "
- "prior local declaration", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "friend declaration %qD in local class without "
+ "prior local declaration", decl);
/* Don't attempt to push it. */
return error_mark_node;
}
@@ -4451,9 +4452,9 @@ push_class_level_binding_1 (tree name, tree x)
tree scope = context_for_name_lookup (x);
if (TYPE_P (scope) && same_type_p (scope, current_class_type))
{
- error ("%qD has the same name as the class in which it is "
- "declared",
- x);
+ error_at (DECL_SOURCE_LOCATION (x),
+ "%qD has the same name as the class in which it is "
+ "declared", x);
return false;
}
}
@@ -4757,7 +4758,8 @@ set_decl_namespace (tree decl, tree scope, bool friendp)
/* Writing "N::i" to declare something directly in "N" is invalid. */
if (CP_DECL_CONTEXT (decl) == current_namespace
&& at_namespace_scope_p ())
- error ("explicit qualification in declaration of %qD", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "explicit qualification in declaration of %qD", decl);
return;
}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 018a03d4965..c61e0b2cb9d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -9014,6 +9014,7 @@ cp_parser_delete_expression (cp_parser* parser)
bool global_scope_p;
bool array_p;
tree expression;
+ location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
/* Look for the optional `::' operator. */
global_scope_p
@@ -9043,8 +9044,18 @@ cp_parser_delete_expression (cp_parser* parser)
if (cp_parser_non_integral_constant_expression (parser, NIC_DEL))
return error_mark_node;
- return delete_sanity (expression, NULL_TREE, array_p, global_scope_p,
- tf_warning_or_error);
+ /* Construct a location e.g.:
+ delete [ ] ptr
+ ^~~~~~~~~~~~~~
+ with caret == start at the start of the "delete" token, and
+ the end at the end of the final token we consumed. */
+ location_t combined_loc = make_location (start_loc, start_loc,
+ parser->lexer);
+ expression = delete_sanity (expression, NULL_TREE, array_p,
+ global_scope_p, tf_warning_or_error);
+ protected_set_expr_location (expression, combined_loc);
+
+ return expression;
}
/* Returns 1 if TOKEN may start a cast-expression and isn't '++', '--',
@@ -25827,6 +25838,7 @@ cp_parser_throw_expression (cp_parser* parser)
{
tree expression;
cp_token* token;
+ location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
cp_parser_require_keyword (parser, RID_THROW, RT_THROW);
token = cp_lexer_peek_token (parser->lexer);
@@ -25842,7 +25854,17 @@ cp_parser_throw_expression (cp_parser* parser)
else
expression = cp_parser_assignment_expression (parser);
- return build_throw (expression);
+ /* Construct a location e.g.:
+ throw x
+ ^~~~~~~
+ with caret == start at the start of the "throw" token, and
+ the end at the end of the final token we consumed. */
+ location_t combined_loc = make_location (start_loc, start_loc,
+ parser->lexer);
+ expression = build_throw (expression);
+ protected_set_expr_location (expression, combined_loc);
+
+ return expression;
}
/* GNU Extensions */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 44b36183304..6310e7b399b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2137,7 +2137,8 @@ determine_specialization (tree template_id,
if (TREE_CODE (decl) == FUNCTION_DECL && !is_overloaded_fn (fns))
{
- error ("%qD is not a function template", fns);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qD is not a function template", fns);
return error_mark_node;
}
else if (VAR_P (decl) && !variable_template_p (fns))
@@ -2416,7 +2417,8 @@ determine_specialization (tree template_id,
error ("template-id %qD for %q+D does not match any template "
"declaration", template_id, decl);
if (header_count && header_count != template_count + 1)
- inform (input_location, "saw %d %<template<>%>, need %d for "
+ inform (DECL_SOURCE_LOCATION (decl),
+ "saw %d %<template<>%>, need %d for "
"specializing a member function template",
header_count, template_count + 1);
else
@@ -7357,21 +7359,6 @@ coerce_template_args_for_ttp (tree templ, tree arglist,
/* A cache of template template parameters with match-all default
arguments. */
static GTY((deletable)) hash_map<tree,tree> *defaulted_ttp_cache;
-static void
-store_defaulted_ttp (tree v, tree t)
-{
- if (!defaulted_ttp_cache)
- defaulted_ttp_cache = hash_map<tree,tree>::create_ggc (13);
- defaulted_ttp_cache->put (v, t);
-}
-static tree
-lookup_defaulted_ttp (tree v)
-{
- if (defaulted_ttp_cache)
- if (tree *p = defaulted_ttp_cache->get (v))
- return *p;
- return NULL_TREE;
-}
/* T is a bound template template-parameter. Copy its arguments into default
arguments of the template template-parameter's template parameters. */
@@ -7379,8 +7366,8 @@ lookup_defaulted_ttp (tree v)
static tree
add_defaults_to_ttp (tree otmpl)
{
- if (tree c = lookup_defaulted_ttp (otmpl))
- return c;
+ if (tree *c = hash_map_safe_get (defaulted_ttp_cache, otmpl))
+ return *c;
tree ntmpl = copy_node (otmpl);
@@ -7410,7 +7397,7 @@ add_defaults_to_ttp (tree otmpl)
}
}
- store_defaulted_ttp (otmpl, ntmpl);
+ hash_map_safe_put<hm_ggc> (defaulted_ttp_cache, otmpl, ntmpl);
return ntmpl;
}
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 58fa54f40af..54d6b848157 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -902,14 +902,17 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
value = oldval;
}
}
- value = cp_fully_fold_init (value);
+ /* Don't fold initializers of automatic variables in constexpr functions,
+ that might fold away something that needs to be diagnosed at constexpr
+ evaluation time. */
+ if (!current_function_decl
+ || !DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+ || TREE_STATIC (decl))
+ value = cp_fully_fold_init (value);
/* Handle aggregate NSDMI in non-constant initializers, too. */
value = replace_placeholders (value, decl);
- /* DECL may change value; purge caches. */
- clear_cv_and_fold_caches ();
-
/* If the initializer is not a constant, fill in DECL_INITIAL with
the bits that are constant, and then return an expression that
will perform the dynamic initialization. */
@@ -918,6 +921,10 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
|| vla_type_p (type)
|| ! reduced_constant_expression_p (value)))
return split_nonconstant_init (decl, value);
+
+ /* DECL may change value; purge caches. */
+ clear_cv_and_fold_caches ();
+
/* If the value is a constant, just put it in DECL_INITIAL. If DECL
is an automatic variable, the middle end will turn this into a
dynamic initialization later. */
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 64fccfe9b87..7e37c5cc2e6 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -5206,7 +5206,7 @@ On the MSP430 target these attributes can be used to specify whether
the function or variable should be placed into low memory, high
memory, or the placement should be left to the linker to decide. The
attributes are only significant if compiling for the MSP430X
-architecture.
+architecture in the large memory model.
The attributes work in conjunction with a linker script that has been
augmented to specify where to place sections with a @code{.lower} and
@@ -7537,15 +7537,30 @@ value will be retained across resets. The linker script being used to
create the application should ensure that persistent data is correctly
placed.
-@item lower
-@itemx upper
+@item upper
@itemx either
-@cindex @code{lower} variable attribute, MSP430
@cindex @code{upper} variable attribute, MSP430
@cindex @code{either} variable attribute, MSP430
These attributes are the same as the MSP430 function attributes of the
same name (@pxref{MSP430 Function Attributes}).
-These attributes can be applied to both functions and variables.
+
+@item lower
+@cindex @code{lower} variable attribute, MSP430
+This option behaves mostly the same as the MSP430 function attribute of the
+same name (@pxref{MSP430 Function Attributes}), but it has some additional
+functionality.
+
+If @option{-mdata-region=}@{@code{upper,either,none}@} has been passed, or
+the @code{section} attribute is applied to a variable, the compiler will
+generate 430X instructions to handle it. This is because the compiler has
+to assume that the variable could get placed in the upper memory region
+(above address 0xFFFF). Marking the variable with the @code{lower} attribute
+informs the compiler that the variable will be placed in lower memory so it
+is safe to use 430 instructions to handle it.
+
+In the case of the @code{section} attribute, the section name given
+will be used, and the @code{.lower} prefix will not be added.
+
@end table
@node Nvidia PTX Variable Attributes
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 4281ee7c614..20e10c01804 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -5578,21 +5578,20 @@ either specify @option{-Wextra -Wunused} (note that @option{-Wall} implies
@item -Wuninitialized
@opindex Wuninitialized
@opindex Wno-uninitialized
-Warn if an automatic variable is used without first being initialized
-or if a variable may be clobbered by a @code{setjmp} call. In C++,
-warn if a non-static reference or non-static @code{const} member
-appears in a class without constructors.
+Warn if an automatic variable is used without first being initialized.
+In C++, warn if a non-static reference or non-static @code{const}
+member appears in a class without constructors.
If you want to warn about code that uses the uninitialized value of the
variable in its own initializer, use the @option{-Winit-self} option.
-These warnings occur for individual uninitialized or clobbered
-elements of structure, union or array variables as well as for
-variables that are uninitialized or clobbered as a whole. They do
-not occur for variables or elements declared @code{volatile}. Because
-these warnings depend on optimization, the exact variables or elements
-for which there are warnings depends on the precise optimization
-options and version of GCC used.
+These warnings occur for individual uninitialized elements of
+structure, union or array variables as well as for variables that are
+uninitialized as a whole. They do not occur for variables or elements
+declared @code{volatile}. Because these warnings depend on
+optimization, the exact variables or elements for which there are
+warnings depend on the precise optimization options and version of GCC
+used.
Note that there may be no warning about a variable that is used only
to compute a value that itself is never used, because such
@@ -6477,13 +6476,14 @@ Do not warn whenever a local variable shadows an instance variable in an
Objective-C method.
@item -Wshadow=global
-@opindex Wshadow=local
+@opindex Wshadow=global
The default for @option{-Wshadow}. Warns for any (global) shadowing.
+This warning is enabled by @option{-Wshadow=global}.
@item -Wshadow=local
@opindex Wshadow=local
Warn when a local variable shadows another local variable or parameter.
-This warning is enabled by @option{-Wshadow=global}.
+This warning is enabled by @option{-Wshadow=local}.
@item -Wshadow=compatible-local
@opindex Wshadow=compatible-local
@@ -6515,8 +6515,10 @@ in place of the other, type checking will catch that and emit an error or
warning. So not warning (about shadowing) in this case will not lead to
undetected bugs. Use of this flag instead of @option{-Wshadow=local} can
possibly reduce the number of warnings triggered by intentional shadowing.
+Note that this does also mean that shadowing @code{const char *i} by
+@code{char *i} will not emit a warning.
-This warning is enabled by @option{-Wshadow=local}.
+This warning is enabled by @option{-Wshadow=compatible-local}.
@item -Wlarger-than=@var{byte-size}
@opindex Wlarger-than=
@@ -8346,6 +8348,7 @@ also turns on the following optimization flags:
-ffinite-loops @gol
-fgcse -fgcse-lm @gol
-fhoist-adjacent-loads @gol
+-finline-functions @gol
-finline-small-functions @gol
-findirect-inlining @gol
-fipa-bit-cp -fipa-cp -fipa-icf @gol
@@ -8379,7 +8382,6 @@ by @option{-O2} and also turns on the following optimization flags:
@c Please keep the following list alphabetized!
@gccoptlist{-fgcse-after-reload @gol
--finline-functions @gol
-fipa-cp-clone
-floop-interchange @gol
-floop-unroll-and-jam @gol
@@ -8559,7 +8561,7 @@ If all calls to a given function are integrated, and the function is
declared @code{static}, then the function is normally not output as
assembler code in its own right.
-Enabled at levels @option{-O3}, @option{-Os}. Also enabled
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}. Also enabled
by @option{-fprofile-use} and @option{-fauto-profile}.
@item -finline-functions-called-once
@@ -10807,12 +10809,12 @@ Do not allow the built-in functions @code{ceil}, @code{floor},
double} variants, to generate code that raises the ``inexact''
floating-point exception for noninteger arguments. ISO C99 and C11
allow these functions to raise the ``inexact'' exception, but ISO/IEC
-TS 18661-1:2014, the C bindings to IEEE 754-2008, does not allow these
-functions to do so.
+TS 18661-1:2014, the C bindings to IEEE 754-2008, as integrated into
+ISO C2X, does not allow these functions to do so.
The default is @option{-ffp-int-builtin-inexact}, allowing the
-exception to be raised. This option does nothing unless
-@option{-ftrapping-math} is in effect.
+exception to be raised, unless C2X or a later C standard is selected.
+This option does nothing unless @option{-ftrapping-math} is in effect.
Even if @option{-fno-fp-int-builtin-inexact} is used, if the functions
generate a call to a library function then the ``inexact'' exception
@@ -11175,19 +11177,30 @@ when modulo scheduling a loop. Larger values can exponentially increase
compilation time.
@item max-inline-insns-single
-Several parameters control the tree inliner used in GCC@.
-This number sets the maximum number of instructions (counted in GCC's
-internal representation) in a single function that the tree inliner
-considers for inlining. This only affects functions declared
-inline and methods implemented in a class declaration (C++).
+@item max-inline-insns-single-O2
+Several parameters control the tree inliner used in GCC@. This number sets the
+maximum number of instructions (counted in GCC's internal representation) in a
+single function that the tree inliner considers for inlining. This only
+affects functions declared inline and methods implemented in a class
+declaration (C++).
+
+For functions compiled with optimization levels
+@option{-O3} and @option{-Ofast} parameter @option{max-inline-insns-single} is
+applied. In other cases @option{max-inline-insns-single-O2} is applied.
+
@item max-inline-insns-auto
+@item max-inline-insns-auto-O2
When you use @option{-finline-functions} (included in @option{-O3}),
a lot of functions that would otherwise not be considered for inlining
by the compiler are investigated. To those functions, a different
(more restrictive) limit compared to functions declared inline can
be applied.
+For functions compiled with optimization levels
+@option{-O3} and @option{-Ofast} parameter @option{max-inline-insns-auto} is
+applied. In other cases @option{max-inline-insns-auto-O2} is applied.
+
@item max-inline-insns-small
This is bound applied to calls which are considered relevant with
@option{-finline-small-functions}.
@@ -11204,17 +11217,34 @@ function prologue and epilogue.
Extra time accounted by inliner for function overhead such as time needed to
execute function prologue and epilogue
+@item inline-heuristics-hint-percent
+@item inline-heuristics-hint-percent-O2
+The scale (in percents) applied to @option{inline-insns-single},
+@option{inline-insns-single-O2}, @option{inline-insns-auto},
+@option{inline-insns-auto-O2} when inline heuristics hints that inlining is
+very profitable (will enable later optimizations).
+
+For functions compiled with optimization levels
+@option{-O3} and @option{-Ofast} parameter
+@option{inline-heuristics-hint-percent} is applied. In other cases
+@option{inline-heuristics-hint-percent-O2} is applied.
+
@item uninlined-thunk-insns
@item uninlined-thunk-time
Same as @option{--param uninlined-function-insns} and
@option{--param uninlined-function-time} but applied to function thunks
@item inline-min-speedup
+@item inline-min-speedup-O2
When estimated performance improvement of caller + callee runtime exceeds this
threshold (in percent), the function can be inlined regardless of the limit on
@option{--param max-inline-insns-single} and @option{--param
max-inline-insns-auto}.
+For functions compiled with optimization levels
+@option{-O3} and @option{-Ofast} parameter @option{inline-min-speedup} is
+applied. In other cases @option{inline-min-speedup-O2} is applied.
+
@item large-function-insns
The limit specifying really large functions. For functions larger than this
limit after inlining, inlining is constrained by
@@ -11291,17 +11321,14 @@ recursion depth can be guessed from the probability that function recurses
via a given call expression. This parameter limits inlining only to call
expressions whose probability exceeds the given threshold (in percents).
+@item early-inlining-insns
@item early-inlining-insns-O2
Specify growth that the early inliner can make. In effect it increases
the amount of inlining for code having a large abstraction penalty.
-This is applied to functions compiled with @option{-O1} or @option{-O2}
-optimization levels.
-@item early-inlining-insns
-Specify growth that the early inliner can make. In effect it increases
-the amount of inlining for code having a large abstraction penalty.
-This is applied to functions compiled with @option{-O3} or @option{-Ofast}
-optimization levels.
+For functions compiled with optimization levels
+@option{-O3} and @option{-Ofast} parameter @option{early-inlining-insns} is
+applied. In other cases @option{early-inlining-insns-O2} is applied.
@item max-early-inliner-iterations
Limit of iterations of the early inliner. This basically bounds
diff --git a/gcc/expr.c b/gcc/expr.c
index 7a7070670ed..124144d9b1e 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -73,9 +73,10 @@ along with GCC; see the file COPYING3. If not see
int cse_not_expected;
static bool block_move_libcall_safe_for_call_parm (void);
-static bool emit_block_move_via_cpymem (rtx, rtx, rtx, unsigned, unsigned, HOST_WIDE_INT,
- unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT);
+static bool emit_block_move_via_pattern (rtx, rtx, rtx, unsigned, unsigned,
+ HOST_WIDE_INT, unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT, bool);
static void emit_block_move_via_loop (rtx, rtx, rtx, unsigned);
static void clear_by_pieces (rtx, unsigned HOST_WIDE_INT, unsigned int);
static rtx_insn *compress_float_constant (rtx, rtx);
@@ -559,7 +560,6 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp)
}
else
{
- scalar_mode intermediate;
rtx tmp;
int shift_amount;
@@ -1562,7 +1562,8 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method,
unsigned HOST_WIDE_INT min_size,
unsigned HOST_WIDE_INT max_size,
unsigned HOST_WIDE_INT probable_max_size,
- bool bail_out_libcall, bool *is_move_done)
+ bool bail_out_libcall, bool *is_move_done,
+ bool might_overlap)
{
int may_use_call;
rtx retval = 0;
@@ -1622,13 +1623,31 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method,
set_mem_size (y, const_size);
}
- if (CONST_INT_P (size) && can_move_by_pieces (INTVAL (size), align))
- move_by_pieces (x, y, INTVAL (size), align, RETURN_BEGIN);
- else if (emit_block_move_via_cpymem (x, y, size, align,
+ bool pieces_ok = CONST_INT_P (size)
+ && can_move_by_pieces (INTVAL (size), align);
+ bool pattern_ok = false;
+
+ if (!pieces_ok || might_overlap)
+ {
+ pattern_ok
+ = emit_block_move_via_pattern (x, y, size, align,
expected_align, expected_size,
- min_size, max_size, probable_max_size))
+ min_size, max_size, probable_max_size,
+ might_overlap);
+ if (!pattern_ok && might_overlap)
+ {
+ /* Do not try any of the other methods below as they are not safe
+ for overlapping moves. */
+ *is_move_done = false;
+ return retval;
+ }
+ }
+
+ if (pattern_ok)
;
- else if (may_use_call
+ else if (pieces_ok)
+ move_by_pieces (x, y, INTVAL (size), align, RETURN_BEGIN);
+ else if (may_use_call && !might_overlap
&& ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x))
&& ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (y)))
{
@@ -1645,7 +1664,8 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method,
retval = emit_block_copy_via_libcall (x, y, size,
method == BLOCK_OP_TAILCALL);
}
-
+ else if (might_overlap)
+ *is_move_done = false;
else
emit_block_move_via_loop (x, y, size, align);
@@ -1674,9 +1694,7 @@ emit_block_move (rtx x, rtx y, rtx size, enum block_op_methods method)
static bool
block_move_libcall_safe_for_call_parm (void)
{
-#if defined (REG_PARM_STACK_SPACE)
tree fn;
-#endif
/* If arguments are pushed on the stack, then they're safe. */
if (PUSH_ARGS)
@@ -1699,7 +1717,7 @@ block_move_libcall_safe_for_call_parm (void)
{
CUMULATIVE_ARGS args_so_far_v;
cumulative_args_t args_so_far;
- tree fn, arg;
+ tree arg;
fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
INIT_CUMULATIVE_ARGS (args_so_far_v, TREE_TYPE (fn), NULL_RTX, 0, 3);
@@ -1721,15 +1739,26 @@ block_move_libcall_safe_for_call_parm (void)
return true;
}
-/* A subroutine of emit_block_move. Expand a cpymem pattern;
- return true if successful. */
+/* A subroutine of emit_block_move. Expand a cpymem or movmem pattern;
+ return true if successful.
+
+ X is the destination of the copy or move.
+ Y is the source of the copy or move.
+ SIZE is the size of the block to be moved.
+
+ MIGHT_OVERLAP indicates this originated with expansion of a
+ builtin_memmove() and the source and destination blocks may
+ overlap.
+ */
static bool
-emit_block_move_via_cpymem (rtx x, rtx y, rtx size, unsigned int align,
- unsigned int expected_align, HOST_WIDE_INT expected_size,
- unsigned HOST_WIDE_INT min_size,
- unsigned HOST_WIDE_INT max_size,
- unsigned HOST_WIDE_INT probable_max_size)
+emit_block_move_via_pattern (rtx x, rtx y, rtx size, unsigned int align,
+ unsigned int expected_align,
+ HOST_WIDE_INT expected_size,
+ unsigned HOST_WIDE_INT min_size,
+ unsigned HOST_WIDE_INT max_size,
+ unsigned HOST_WIDE_INT probable_max_size,
+ bool might_overlap)
{
if (expected_align < align)
expected_align = align;
@@ -1752,7 +1781,11 @@ emit_block_move_via_cpymem (rtx x, rtx y, rtx size, unsigned int align,
FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT)
{
scalar_int_mode mode = mode_iter.require ();
- enum insn_code code = direct_optab_handler (cpymem_optab, mode);
+ enum insn_code code;
+ if (might_overlap)
+ code = direct_optab_handler (movmem_optab, mode);
+ else
+ code = direct_optab_handler (cpymem_optab, mode);
if (code != CODE_FOR_nothing
/* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT
@@ -4446,16 +4479,16 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size,
/* Get the address of the stack space.
In this case, we do not deal with EXTRA separately.
A single stack adjust will do. */
- poly_int64 offset;
+ poly_int64 const_args_so_far;
if (! args_addr)
{
temp = push_block (size, extra, where_pad == PAD_DOWNWARD);
extra = 0;
}
- else if (poly_int_rtx_p (args_so_far, &offset))
+ else if (poly_int_rtx_p (args_so_far, &const_args_so_far))
temp = memory_address (BLKmode,
plus_constant (Pmode, args_addr,
- skip + offset));
+ skip + const_args_so_far));
else
temp = memory_address (BLKmode,
plus_constant (Pmode,
@@ -4530,8 +4563,8 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size,
{
/* Scalar partly in registers. This case is only supported
for fixed-wdth modes. */
- int size = GET_MODE_SIZE (mode).to_constant ();
- size /= UNITS_PER_WORD;
+ int num_words = GET_MODE_SIZE (mode).to_constant ();
+ num_words /= UNITS_PER_WORD;
int i;
int not_stack;
/* # bytes of start of argument
@@ -4578,7 +4611,7 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size,
/* Loop over all the words allocated on the stack for this arg. */
/* We can do it by words, because any scalar bigger than a word
has a size a multiple of a word. */
- for (i = size - 1; i >= not_stack; i--)
+ for (i = num_words - 1; i >= not_stack; i--)
if (i >= not_stack + offset)
if (!emit_push_insn (operand_subword_force (x, i, mode),
word_mode, NULL_TREE, NULL_RTX, align, 0, NULL_RTX,
@@ -5241,8 +5274,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
}
else
{
- machine_mode to_mode
- = GET_MODE_INNER (GET_MODE (to_rtx));
+ to_mode = GET_MODE_INNER (to_mode);
rtx from_real
= simplify_gen_subreg (to_mode, result,
TYPE_MODE (TREE_TYPE (from)),
@@ -5261,7 +5293,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
else
{
concat_store_slow:;
- rtx temp = assign_stack_temp (to_mode,
+ rtx temp = assign_stack_temp (GET_MODE (to_rtx),
GET_MODE_SIZE (GET_MODE (to_rtx)));
write_complex_part (temp, XEXP (to_rtx, 0), false);
write_complex_part (temp, XEXP (to_rtx, 1), true);
@@ -6425,7 +6457,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
&& exp_size >= 0
&& bitpos + BITS_PER_WORD <= exp_size * BITS_PER_UNIT)
{
- tree type = TREE_TYPE (value);
+ type = TREE_TYPE (value);
if (TYPE_PRECISION (type) < BITS_PER_WORD)
{
@@ -6502,7 +6534,6 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
else
{
unsigned HOST_WIDE_INT idx;
- tree index, value;
HOST_WIDE_INT count = 0, zero_count = 0;
need_to_clear = ! const_bounds_p;
@@ -6791,7 +6822,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
icode = convert_optab_handler (vec_init_optab, mode, emode);
if (icode != CODE_FOR_nothing)
{
- unsigned int i, n = const_n_elts;
+ unsigned int n = const_n_elts;
if (emode != eltmode)
{
@@ -6799,8 +6830,8 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
vec_vec_init_p = true;
}
vector = rtvec_alloc (n);
- for (i = 0; i < n; i++)
- RTVEC_ELT (vector, i) = CONST0_RTX (emode);
+ for (unsigned int k = 0; k < n; k++)
+ RTVEC_ELT (vector, k) = CONST0_RTX (emode);
}
}
@@ -7121,7 +7152,7 @@ store_field (rtx target, poly_int64 bitsize, poly_int64 bitpos,
word size, we need to load the value (see again store_bit_field). */
if (GET_MODE (temp) == BLKmode && known_le (bitsize, BITS_PER_WORD))
{
- scalar_int_mode temp_mode = smallest_int_mode_for_size (bitsize);
+ temp_mode = smallest_int_mode_for_size (bitsize);
temp = extract_bit_field (temp, bitsize, 0, 1, NULL_RTX, temp_mode,
temp_mode, false, NULL);
}
@@ -8344,7 +8375,7 @@ expand_cond_expr_using_cmove (tree treeop0 ATTRIBUTE_UNUSED,
if (TREE_CODE (treeop0) == SSA_NAME
&& (srcstmt = get_def_for_expr_class (treeop0, tcc_comparison)))
{
- tree type = TREE_TYPE (gimple_assign_rhs1 (srcstmt));
+ type = TREE_TYPE (gimple_assign_rhs1 (srcstmt));
enum tree_code cmpcode = gimple_assign_rhs_code (srcstmt);
op00 = expand_normal (gimple_assign_rhs1 (srcstmt));
op01 = expand_normal (gimple_assign_rhs2 (srcstmt));
@@ -8354,7 +8385,7 @@ expand_cond_expr_using_cmove (tree treeop0 ATTRIBUTE_UNUSED,
}
else if (COMPARISON_CLASS_P (treeop0))
{
- tree type = TREE_TYPE (TREE_OPERAND (treeop0, 0));
+ type = TREE_TYPE (TREE_OPERAND (treeop0, 0));
enum tree_code cmpcode = TREE_CODE (treeop0);
op00 = expand_normal (TREE_OPERAND (treeop0, 0));
op01 = expand_normal (TREE_OPERAND (treeop0, 1));
@@ -9648,7 +9679,6 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
tree oprnd0 = treeop0;
tree oprnd1 = treeop1;
tree oprnd2 = treeop2;
- rtx op2;
expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
op2 = expand_normal (oprnd2);
@@ -9662,7 +9692,6 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
tree oprnd0 = treeop0;
tree oprnd1 = treeop1;
tree oprnd2 = treeop2;
- rtx op2;
expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
op2 = expand_normal (oprnd2);
@@ -9676,7 +9705,6 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
tree oprnd0 = treeop0;
tree oprnd1 = treeop1;
tree oprnd2 = treeop2;
- rtx op2;
this_optab = optab_for_tree_code (code, type, optab_default);
expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
@@ -9766,8 +9794,8 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
bitsize = TYPE_PRECISION (TREE_TYPE (treeop1));
else
bitsize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (treeop1)));
- rtx op0 = expand_normal (treeop0);
- rtx op1 = expand_normal (treeop1);
+ op0 = expand_normal (treeop0);
+ op1 = expand_normal (treeop1);
rtx dst = gen_reg_rtx (mode);
emit_move_insn (dst, op0);
store_bit_field (dst, bitsize, bitpos, 0, 0,
@@ -9966,7 +9994,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
{
rtx r;
location_t saved_loc = curr_insn_location ();
- location_t loc = gimple_location (g);
+ loc = gimple_location (g);
if (loc != UNKNOWN_LOCATION)
set_curr_insn_location (loc);
ops.code = gimple_assign_rhs_code (g);
@@ -10165,9 +10193,9 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
GET_MODE_PRECISION (TYPE_MODE (type)), we need to extend from
the former to the latter according to the signedness of the
type. */
- scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
+ scalar_int_mode int_mode = SCALAR_INT_TYPE_MODE (type);
temp = immed_wide_int_const
- (wi::to_wide (exp, GET_MODE_PRECISION (mode)), mode);
+ (wi::to_wide (exp, GET_MODE_PRECISION (int_mode)), int_mode);
return temp;
}
@@ -10242,9 +10270,9 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
/* Handle evaluating a complex constant in a CONCAT target. */
if (original_target && GET_CODE (original_target) == CONCAT)
{
- machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
rtx rtarg, itarg;
+ mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
rtarg = XEXP (original_target, 0);
itarg = XEXP (original_target, 1);
@@ -10548,14 +10576,14 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
if (tree_fits_uhwi_p (index1)
&& compare_tree_int (index1, TREE_STRING_LENGTH (init)) < 0)
{
- tree type = TREE_TYPE (TREE_TYPE (init));
- scalar_int_mode mode;
+ tree char_type = TREE_TYPE (TREE_TYPE (init));
+ scalar_int_mode char_mode;
- if (is_int_mode (TYPE_MODE (type), &mode)
- && GET_MODE_SIZE (mode) == 1)
+ if (is_int_mode (TYPE_MODE (char_type), &char_mode)
+ && GET_MODE_SIZE (char_mode) == 1)
return gen_int_mode (TREE_STRING_POINTER (init)
[TREE_INT_CST_LOW (index1)],
- mode);
+ char_mode);
}
}
}
@@ -10709,8 +10737,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
rtx op = read_complex_part (op0, i != 0);
if (GET_CODE (op) == SUBREG)
op = force_reg (GET_MODE (op), op);
- rtx temp = gen_lowpart_common (GET_MODE_INNER (mode1),
- op);
+ temp = gen_lowpart_common (GET_MODE_INNER (mode1), op);
if (temp)
op = temp;
else
@@ -12102,11 +12129,12 @@ do_store_flag (sepops ops, rtx target, machine_mode mode)
&& TREE_CODE (arg0) == SSA_NAME
&& TREE_CODE (arg1) == INTEGER_CST)
{
- enum tree_code code = maybe_optimize_mod_cmp (ops->code, &arg0, &arg1);
- if (code != ops->code)
+ enum tree_code new_code = maybe_optimize_mod_cmp (ops->code,
+ &arg0, &arg1);
+ if (new_code != ops->code)
{
struct separate_ops nops = *ops;
- nops.code = ops->code = code;
+ nops.code = ops->code = new_code;
nops.op0 = arg0;
nops.op1 = arg1;
nops.type = TREE_TYPE (arg0);
@@ -12209,7 +12237,7 @@ do_store_flag (sepops ops, rtx target, machine_mode mode)
&& integer_pow2p (gimple_assign_rhs2 (srcstmt)))
{
enum tree_code tcode = code == NE ? NE_EXPR : EQ_EXPR;
- tree type = lang_hooks.types.type_for_mode (mode, unsignedp);
+ type = lang_hooks.types.type_for_mode (mode, unsignedp);
tree temp = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg1),
gimple_assign_rhs1 (srcstmt),
gimple_assign_rhs2 (srcstmt));
diff --git a/gcc/expr.h b/gcc/expr.h
index 6eb70bf12f1..17c9163c351 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -116,7 +116,8 @@ extern rtx emit_block_move_hints (rtx, rtx, rtx, enum block_op_methods,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
bool bail_out_libcall = false,
- bool *is_move_done = NULL);
+ bool *is_move_done = NULL,
+ bool might_overlap = false);
extern rtx emit_block_cmp_hints (rtx, rtx, rtx, tree, rtx, bool,
by_pieces_constfn, void *);
extern bool emit_storent_insn (rtx to, rtx from);
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 63ee15bfc70..84ee818a49d 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,159 @@
+2019-10-05 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/47045
+ * decl.c (variable_decl): Do not search parent namespace for symbol.
+
+2019-10-05 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/91926
+ * trans-expr.c (gfc_conv_gfc_desc_to_cfi_desc): Correct the
+ assignment of the attribute field to account correctly for an
+ assumed shape dummy. Assign separately to the gfc and cfi
+ descriptors since the atribute can be different. Add btanch to
+ correctly handle missing optional dummies.
+
+2019-10-04 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran.91959
+ * fortran/decl.c (variable_decl): Re-arrange code for matching %FILL.
+
+2019-10-04 Tobias Burnus <tobias@codesourcery.com>
+
+ * error (error_print, gfc_format_decoder): Fix off-by one issue with %C.
+
+2019-10-03 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/91497
+ * simplify.c (gfc_simplify_dble, simplify_intconv, gfc_simplify_real,
+ gfc_simplify_sngl): Disable -Wconversion and -Wconversion-extra
+ warnings for explicit conversion of literal constants.
+
+2019-10-03 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * primary.c (match_real_constant): Remove shadowing local vars.
+ Rename local vars. Fix undefined behavior in loop termination.
+ (gfc_convert_to_structure_constructor): Rename local var.
+
+2019-10-03 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/84487
+ * trans-decl.c (gfc_get_symbol_decl): For __def_init, set
+ DECL_ARTIFICAL and do not set TREE_READONLY.
+
+2019-10-03 Mark Eggleston <mark.eggleston@codethink.com>
+
+ * array.c (check_element_type): Call gfc_typename with the gfc_expr
+ "expr" instead of its gfc_typespec "ts".
+ * check.c (gfc_check_co_reduce): Call gfc_typename with the gfc_expr
+ "a" instead of its gfc_typespec "ts".
+ (gfc_check_co_reduce): Call gfc_typename with the gfc_expr "a" instead
+ of its gfc_typespec "ts".
+ (gfc_check_eoshift): Call gfc_typename with the gfc_expr "array"
+ instead of its gfc_typespec ts.
+ (gfc_check_same_type_as): In two calls to gfc_typename use "a" and "b"
+ of type gfc_expr instead of the "ts" fields of "a" and "b"
+ * decl.c (variable_decl): Call gfc_typename with the gfc_expr
+ "initializer" instead of its gfc_typespec "ts".
+ * expr.c (gfc_check_assign): Use "rvalue" and "lvalue" of type gfc_expr
+ in calls to gfc_typename instead of their "ts" fields of type
+ gfc_typespec.
+ (gfc_check_pointer_assign): Use "rvalue" and "lvalue" of type gfc_expr
+ in calls to gfc_typename instead of their "ts" fields of type
+ gfc_typespec.
+ * gfortran.h: Add prototypes for gfc_dummy_typename and a new function
+ gfc_typename for gfc_expr *.
+ *interface.c (gfc_check_dummy_characteristics): Use gfc_dummy_typename
+ for the dummy variable.
+ (compare_parameter): Use gfc_dummy_typename for the formal argument.
+ Use "actual" of type gfc_expr in call to gfc_typename for the actual
+ argument.
+ * intrinsic.c (check_arglist): Use gfc_dummy_typename for the formal
+ argument. Use expressions of type gfc_expr from the argument list to
+ call gfc_typename.
+ (gfc_convert_type_warn): New local variable "is_char_constant" set if
+ the expression type is a character constant. At the "bad" label
+ determine source type name by calling gfc_typename with either "expr"
+ for character constants or "from_ts" and use that in the warning
+ messages instead of the original call to gfc_typename.
+ * misc.c (gfc_typename): New function for gfc_expr *, use for where
+ character types are possible it can get the character length from
+ gfc_expr for character literals.
+ (gfc_dummy_typename): New functionfor gfc_typespec *, if no character
+ length is present the character type is assumed and the appropriate
+ string is return otherwise it calls gfc_typename for gfc_typespec *.
+ (gfc_typespec): for character types construct the type name with length
+ and kind (if it is not default kind).
+
+2019-10-02 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/91784
+ * simplify.c (gfc_convert_constant): Simplify expression if the
+ expression type is EXPR_OP.
+
+2019-10-02 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/91785
+ * primary.c (gfc_match_varspec): Ensure an inquiry parameter has
+ it locus set.
+
+2019-10-02 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/91942
+ * io.c (match_vtag): Check for non-NULL result->symtree.
+ (match_out_tag): Check for invalid constant due to inquiry parameter.
+ (match_filepos): Instead of a syntax error, go to cleanup to get better
+ error messages.
+
+2019-10-02 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/91943
+ * match.c (gfc_match_call): BOZ cannot be an actual argument in
+ a subroutine reference.
+ * resolve.c (resolve_function): BOZ cannot be an actual argument in
+ a function reference.
+
+2019-10-01 Jan Hubicka <jh@suse.cz>
+
+ * module.c (load_commons): Initialize flags to 0 to silence
+ -Wmaybe-uninitialized warning.
+ (read_module): Likewise for n and comp_name.
+
+2019-10-02 Tobias Burnus <tobias@codesourcery.com>
+
+ * dump-parse-tree.c (show_omp_clauses): Handle OMP_LIST_USE_DEVICE_ADDR.
+ * gfortran.h (enum): Add OMP_LIST_USE_DEVICE_ADDR.
+ * openmp.c (omp_mask1): Likewise.
+ (gfc_match_omp_clauses): Match 'use_device_addr'.
+ (OMP_TARGET_DATA_CLAUSES): Add OMP_LIST_USE_DEVICE_ADDR.
+ (resolve_omp_clauses): Add it; add is_device_ptr checks.
+
+2019-10-02 Tobias Burnus <tobias@codesourcery.com>
+
+ * openmp.c (gfc_match_omp_clauses): Show a clause-parsing
+ error if none was rised before.
+ * parse.c (matcha, matcho): If error occurred after
+ OpenMP/OpenACC directive matched, do not try other directives.
+
+2019-10-02 Tobias Burnus <tobias@codesourcery.com>
+
+ * trans-openmp.c (gfc_omp_is_optional_argument): Fix coding
+ style.
+
+2019-10-02 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * f95-lang.c (LANG_HOOKS_OMP_IS_OPTIONAL_ARGUMENT): Define to
+ gfc_omp_is_optional_argument.
+ * trans-decl.c (create_function_arglist): Set
+ GFC_DECL_OPTIONAL_ARGUMENT in the generated decl if the parameter is
+ optional.
+ * trans-openmp.c (gfc_omp_is_optional_argument): New.
+ (gfc_omp_privatize_by_reference): Return true if the decl is an
+ optional pass-by-reference argument.
+ * trans.h (gfc_omp_is_optional_argument): New declaration.
+ (lang_decl): Add new optional_arg field.
+ (GFC_DECL_OPTIONAL_ARGUMENT): New macro.
+
+>>>>>>> .r276463
2019-10-01 David Malcolm <dmalcolm@redhat.com>
* error.c (gfc_diagnostic_starter): Clear the prefix before
diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c
index ba8a81655ed..3a504ebfea8 100644
--- a/gcc/fortran/array.c
+++ b/gcc/fortran/array.c
@@ -1358,7 +1358,7 @@ check_element_type (gfc_expr *expr, bool convert)
gfc_error ("Element in %s array constructor at %L is %s",
gfc_typename (&constructor_ts), &expr->where,
- gfc_typename (&expr->ts));
+ gfc_typename (expr));
cons_state = CONS_BAD;
return 1;
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index 98203bcd839..87a81969062 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -2266,7 +2266,7 @@ gfc_check_co_reduce (gfc_expr *a, gfc_expr *op, gfc_expr *result_image,
{
gfc_error ("The A argument at %L has type %s but the function passed as "
"OPERATOR at %L returns %s",
- &a->where, gfc_typename (&a->ts), &op->where,
+ &a->where, gfc_typename (a), &op->where,
gfc_typename (&sym->result->ts));
return false;
}
@@ -2276,7 +2276,7 @@ gfc_check_co_reduce (gfc_expr *a, gfc_expr *op, gfc_expr *result_image,
gfc_error ("The function passed as OPERATOR at %L has arguments of type "
"%s and %s but shall have type %s", &op->where,
gfc_typename (&formal->sym->ts),
- gfc_typename (&formal->next->sym->ts), gfc_typename (&a->ts));
+ gfc_typename (&formal->next->sym->ts), gfc_typename (a));
return false;
}
if (op->rank || attr.allocatable || attr.pointer || formal->sym->as
@@ -2844,7 +2844,7 @@ gfc_check_eoshift (gfc_expr *array, gfc_expr *shift, gfc_expr *boundary,
"of type %qs", gfc_current_intrinsic_arg[2]->name,
gfc_current_intrinsic, &array->where,
gfc_current_intrinsic_arg[0]->name,
- gfc_typename (&array->ts));
+ gfc_typename (array));
return false;
}
}
@@ -4808,7 +4808,7 @@ gfc_check_same_type_as (gfc_expr *a, gfc_expr *b)
"cannot be of type %s",
gfc_current_intrinsic_arg[0]->name,
gfc_current_intrinsic,
- &a->where, gfc_typename (&a->ts));
+ &a->where, gfc_typename (a));
return false;
}
@@ -4827,7 +4827,7 @@ gfc_check_same_type_as (gfc_expr *a, gfc_expr *b)
"cannot be of type %s",
gfc_current_intrinsic_arg[0]->name,
gfc_current_intrinsic,
- &b->where, gfc_typename (&b->ts));
+ &b->where, gfc_typename (b));
return false;
}
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 3ba61a08381..9b604c8e7c3 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -2441,6 +2441,7 @@ variable_decl (int elem)
match m;
bool t;
gfc_symbol *sym;
+ char c;
initializer = NULL;
as = NULL;
@@ -2454,40 +2455,45 @@ variable_decl (int elem)
name to be '%FILL' which gives it an anonymous (inaccessible) name. */
m = MATCH_NO;
gfc_gobble_whitespace ();
- if (gfc_peek_ascii_char () == '%')
+ c = gfc_peek_ascii_char ();
+ if (c == '%')
{
- gfc_next_ascii_char ();
+ gfc_next_ascii_char (); /* Burn % character. */
m = gfc_match ("fill");
- }
-
- if (m != MATCH_YES)
- {
- m = gfc_match_name (name);
- if (m != MATCH_YES)
- goto cleanup;
- }
-
- else
- {
- m = MATCH_ERROR;
- if (gfc_current_state () != COMP_STRUCTURE)
+ if (m == MATCH_YES)
{
- if (flag_dec_structure)
- gfc_error ("%qs not allowed outside STRUCTURE at %C", "%FILL");
- else
- gfc_error ("%qs at %C is a DEC extension, enable with "
+ if (gfc_current_state () != COMP_STRUCTURE)
+ {
+ if (flag_dec_structure)
+ gfc_error ("%qs not allowed outside STRUCTURE at %C", "%FILL");
+ else
+ gfc_error ("%qs at %C is a DEC extension, enable with "
"%<-fdec-structure%>", "%FILL");
- goto cleanup;
- }
+ m = MATCH_ERROR;
+ goto cleanup;
+ }
+
+ if (attr_seen)
+ {
+ gfc_error ("%qs entity cannot have attributes at %C", "%FILL");
+ m = MATCH_ERROR;
+ goto cleanup;
+ }
- if (attr_seen)
+ /* %FILL components are given invalid fortran names. */
+ snprintf (name, GFC_MAX_SYMBOL_LEN + 1, "%%FILL%u", fill_id++);
+ }
+ else
{
- gfc_error ("%qs entity cannot have attributes at %C", "%FILL");
- goto cleanup;
+ gfc_error ("Invalid character %qc in variable name at %C", c);
+ return MATCH_ERROR;
}
-
- /* %FILL components are given invalid fortran names. */
- snprintf (name, GFC_MAX_SYMBOL_LEN + 1, "%%FILL%u", fill_id++);
+ }
+ else
+ {
+ m = gfc_match_name (name);
+ if (m != MATCH_YES)
+ goto cleanup;
}
var_locus = gfc_current_locus;
@@ -2676,7 +2682,7 @@ variable_decl (int elem)
then we want to set the type & bail out. */
if (flag_cray_pointer && !gfc_comp_struct (gfc_current_state ()))
{
- gfc_find_symbol (name, gfc_current_ns, 1, &sym);
+ gfc_find_symbol (name, gfc_current_ns, 0, &sym);
if (sym != NULL && sym->attr.cray_pointee)
{
m = MATCH_YES;
@@ -2908,7 +2914,7 @@ variable_decl (int elem)
{
gfc_error ("Incompatible initialization between a derived type "
"entity and an entity with %qs type at %C",
- gfc_typename (&initializer->ts));
+ gfc_typename (initializer));
m = MATCH_ERROR;
goto cleanup;
}
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 513f211b68b..9d7b26f5f6a 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -1507,6 +1507,7 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
case OMP_LIST_CACHE: type = "CACHE"; break;
case OMP_LIST_IS_DEVICE_PTR: type = "IS_DEVICE_PTR"; break;
case OMP_LIST_USE_DEVICE_PTR: type = "USE_DEVICE_PTR"; break;
+ case OMP_LIST_USE_DEVICE_ADDR: type = "USE_DEVICE_ADDR"; break;
default:
gcc_unreachable ();
}
diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c
index a7c27f0c3fe..1019f17d73c 100644
--- a/gcc/fortran/error.c
+++ b/gcc/fortran/error.c
@@ -618,12 +618,18 @@ error_print (const char *type, const char *format0, va_list argp)
{
l2 = loc;
arg[pos].u.stringval = "(2)";
+ /* Point %C first offending character not the last good one. */
+ if (arg[pos].type == TYPE_CURRENTLOC)
+ l2->nextc++;
}
else
{
l1 = loc;
have_l1 = 1;
arg[pos].u.stringval = "(1)";
+ /* Point %C first offending character not the last good one. */
+ if (arg[pos].type == TYPE_CURRENTLOC)
+ l1->nextc++;
}
break;
@@ -963,6 +969,9 @@ gfc_format_decoder (pretty_printer *pp, text_info *text, const char *spec,
loc = va_arg (*text->args_ptr, locus *);
gcc_assert (loc->nextc - loc->lb->line >= 0);
unsigned int offset = loc->nextc - loc->lb->line;
+ if (*spec == 'C')
+ /* Point %C first offending character not the last good one. */
+ offset++;
/* If location[0] != UNKNOWN_LOCATION means that we already
processed one of %C/%L. */
int loc_num = text->get_location (0) == UNKNOWN_LOCATION ? 0 : 1;
@@ -1401,7 +1410,7 @@ gfc_internal_error (const char *gmsgid, ...)
void
gfc_clear_error (void)
{
- error_buffer.flag = 0;
+ error_buffer.flag = false;
warnings_not_errors = false;
gfc_clear_pp_buffer (pp_error_buffer);
}
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 5d3480eb4a5..9f638fe4dc3 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -3693,8 +3693,7 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform,
return true;
gfc_error ("BOZ literal constant near %L cannot be assigned to a "
- "%qs variable", &rvalue->where, gfc_typename (&lvalue->ts));
-
+ "%qs variable", &rvalue->where, gfc_typename (lvalue));
return false;
}
@@ -3726,7 +3725,7 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform,
where = lvalue->where.lb ? &lvalue->where : &rvalue->where;
gfc_error ("Incompatible types in DATA statement at %L; attempted "
"conversion of %s to %s", where,
- gfc_typename (&rvalue->ts), gfc_typename (&lvalue->ts));
+ gfc_typename (rvalue), gfc_typename (lvalue));
return false;
}
@@ -4139,8 +4138,7 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue,
else if (!suppress_type_test)
gfc_error ("Different types in pointer assignment at %L; "
"attempted assignment of %s to %s", &lvalue->where,
- gfc_typename (&rvalue->ts),
- gfc_typename (&lvalue->ts));
+ gfc_typename (rvalue), gfc_typename (lvalue));
return false;
}
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index 6b9f490d2bb..2467cd968af 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -113,6 +113,7 @@ static const struct attribute_spec gfc_attribute_table[] =
#undef LANG_HOOKS_TYPE_FOR_MODE
#undef LANG_HOOKS_TYPE_FOR_SIZE
#undef LANG_HOOKS_INIT_TS
+#undef LANG_HOOKS_OMP_IS_OPTIONAL_ARGUMENT
#undef LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE
#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
#undef LANG_HOOKS_OMP_REPORT_DECL
@@ -145,6 +146,7 @@ static const struct attribute_spec gfc_attribute_table[] =
#define LANG_HOOKS_TYPE_FOR_MODE gfc_type_for_mode
#define LANG_HOOKS_TYPE_FOR_SIZE gfc_type_for_size
#define LANG_HOOKS_INIT_TS gfc_init_ts
+#define LANG_HOOKS_OMP_IS_OPTIONAL_ARGUMENT gfc_omp_is_optional_argument
#define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE gfc_omp_privatize_by_reference
#define LANG_HOOKS_OMP_PREDETERMINED_SHARING gfc_omp_predetermined_sharing
#define LANG_HOOKS_OMP_REPORT_DECL gfc_omp_report_decl
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 6f7717d1134..d84d1fa7f7e 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1263,6 +1263,7 @@ enum
OMP_LIST_CACHE,
OMP_LIST_IS_DEVICE_PTR,
OMP_LIST_USE_DEVICE_PTR,
+ OMP_LIST_USE_DEVICE_ADDR,
OMP_LIST_NUM
};
@@ -2883,7 +2884,9 @@ void gfc_end_source_files (void);
void gfc_clear_ts (gfc_typespec *);
FILE *gfc_open_file (const char *);
const char *gfc_basic_typename (bt);
+const char *gfc_dummy_typename (gfc_typespec *);
const char *gfc_typename (gfc_typespec *);
+const char *gfc_typename (gfc_expr *);
const char *gfc_op2string (gfc_intrinsic_op);
const char *gfc_code2string (const mstring *, int);
int gfc_string2code (const mstring *, const char *);
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 08e4f063a67..3313e729db9 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -1330,7 +1330,8 @@ gfc_check_dummy_characteristics (gfc_symbol *s1, gfc_symbol *s2,
|| !compare_type_characteristics (s2, s1))
{
snprintf (errmsg, err_len, "Type mismatch in argument '%s' (%s/%s)",
- s1->name, gfc_typename (&s1->ts), gfc_typename (&s2->ts));
+ s1->name, gfc_dummy_typename (&s1->ts),
+ gfc_dummy_typename (&s2->ts));
return false;
}
if (!compare_rank (s1, s2))
@@ -2338,15 +2339,15 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
"and actual argument at %L (%s/%s).",
&actual->where,
&formal->declared_at,
- gfc_typename (&actual->ts),
- gfc_typename (&formal->ts));
+ gfc_typename (actual),
+ gfc_dummy_typename (&formal->ts));
formal->error = 1;
}
else
gfc_error_opt (0, "Type mismatch in argument %qs at %L; passed %s "
- "to %s", formal->name, where, gfc_typename (&actual->ts),
- gfc_typename (&formal->ts));
+ "to %s", formal->name, where, gfc_typename (actual),
+ gfc_dummy_typename (&formal->ts));
}
return false;
}
diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index 764e3500926..ac5af10a775 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -4363,11 +4363,12 @@ check_arglist (gfc_actual_arglist **ap, gfc_intrinsic_sym *sym,
if (!gfc_compare_types (&ts, &actual->expr->ts))
{
if (error_flag)
- gfc_error ("Type of argument %qs in call to %qs at %L should "
- "be %s, not %s", gfc_current_intrinsic_arg[i]->name,
- gfc_current_intrinsic, &actual->expr->where,
- gfc_typename (&formal->ts),
- gfc_typename (&actual->expr->ts));
+ gfc_error ("In call to %qs at %L, type mismatch in argument "
+ "%qs; pass %qs to %qs", gfc_current_intrinsic,
+ &actual->expr->where,
+ gfc_current_intrinsic_arg[i]->name,
+ gfc_typename (actual->expr),
+ gfc_dummy_typename (&formal->ts));
return false;
}
@@ -5076,6 +5077,8 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
gfc_expr *new_expr;
int rank;
mpz_t *shape;
+ bool is_char_constant = (expr->expr_type == EXPR_CONSTANT)
+ && (expr->ts.type == BT_CHARACTER);
from_ts = expr->ts; /* expr->ts gets clobbered */
@@ -5117,7 +5120,7 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
if ((gfc_option.warn_std & sym->standard) != 0)
{
gfc_warning_now (0, "Extension: Conversion from %s to %s at %L",
- gfc_typename (&from_ts), gfc_typename (ts),
+ gfc_typename (&from_ts), gfc_dummy_typename (ts),
&expr->where);
}
else if (wflag)
@@ -5179,7 +5182,7 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
/* If HOLLERITH is involved, all bets are off. */
if (warn_conversion)
gfc_warning_now (OPT_Wconversion, "Conversion from %s to %s at %L",
- gfc_typename (&from_ts), gfc_typename (ts),
+ gfc_typename (&from_ts), gfc_dummy_typename (ts),
&expr->where);
}
else
@@ -5231,15 +5234,17 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
return true;
bad:
+ const char *type_name = is_char_constant ? gfc_typename (expr)
+ : gfc_typename (&from_ts);
if (eflag == 1)
{
- gfc_error ("Cannot convert %s to %s at %L",
- gfc_typename (&from_ts), gfc_typename (ts), &expr->where);
+ gfc_error ("Cannot convert %s to %s at %L", type_name, gfc_typename (ts),
+ &expr->where);
return false;
}
- gfc_internal_error ("Cannot convert %qs to %qs at %L",
- gfc_typename (&from_ts), gfc_typename (ts),
+ gfc_internal_error ("Cannot convert %qs to %qs at %L", type_name,
+ gfc_typename (ts),
&expr->where);
/* Not reached */
}
diff --git a/gcc/fortran/io.c b/gcc/fortran/io.c
index 9ae06b1f5c4..b969a1a4738 100644
--- a/gcc/fortran/io.c
+++ b/gcc/fortran/io.c
@@ -1482,24 +1482,29 @@ match_vtag (const io_tag *tag, gfc_expr **v)
return MATCH_ERROR;
}
- if (result->symtree->n.sym->attr.intent == INTENT_IN)
+ if (result->symtree)
{
- gfc_error ("Variable %s cannot be INTENT(IN) at %C", tag->name);
- gfc_free_expr (result);
- return MATCH_ERROR;
- }
+ bool impure;
- bool impure = gfc_impure_variable (result->symtree->n.sym);
- if (impure && gfc_pure (NULL))
- {
- gfc_error ("Variable %s cannot be assigned in PURE procedure at %C",
- tag->name);
- gfc_free_expr (result);
- return MATCH_ERROR;
- }
+ if (result->symtree->n.sym->attr.intent == INTENT_IN)
+ {
+ gfc_error ("Variable %s cannot be INTENT(IN) at %C", tag->name);
+ gfc_free_expr (result);
+ return MATCH_ERROR;
+ }
+
+ impure = gfc_impure_variable (result->symtree->n.sym);
+ if (impure && gfc_pure (NULL))
+ {
+ gfc_error ("Variable %s cannot be assigned in PURE procedure at %C",
+ tag->name);
+ gfc_free_expr (result);
+ return MATCH_ERROR;
+ }
- if (impure)
- gfc_unset_implicit_pure (NULL);
+ if (impure)
+ gfc_unset_implicit_pure (NULL);
+ }
*v = result;
return MATCH_YES;
@@ -1515,7 +1520,16 @@ match_out_tag (const io_tag *tag, gfc_expr **result)
m = match_vtag (tag, result);
if (m == MATCH_YES)
- gfc_check_do_variable ((*result)->symtree);
+ {
+ if ((*result)->symtree)
+ gfc_check_do_variable ((*result)->symtree);
+
+ if ((*result)->expr_type == EXPR_CONSTANT)
+ {
+ gfc_error ("Expecting a variable at %L", &(*result)->where);
+ return MATCH_ERROR;
+ }
+ }
return m;
}
@@ -2845,7 +2859,7 @@ match_filepos (gfc_statement st, gfc_exec_op op)
m = match_file_element (fp);
if (m == MATCH_ERROR)
- goto syntax;
+ goto cleanup;
if (m == MATCH_NO)
{
m = gfc_match_expr (&fp->unit);
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index 83b11891241..4a31080a285 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -4984,6 +4984,16 @@ gfc_match_call (void)
goto syntax;
}
+ /* Walk the argument list looking for invalid BOZ. */
+ for (a = arglist; a; a = a->next)
+ if (a->expr && a->expr->ts.type == BT_BOZ)
+ {
+ gfc_error ("A BOZ literal constant at %L cannot appear as an actual "
+ "argument in a subroutine reference", &a->expr->where);
+ goto cleanup;
+ }
+
+
/* If any alternate return labels were found, construct a SELECT
statement that will jump to the right place. */
diff --git a/gcc/fortran/misc.c b/gcc/fortran/misc.c
index eed203dee02..97df9eea94e 100644
--- a/gcc/fortran/misc.c
+++ b/gcc/fortran/misc.c
@@ -129,6 +129,7 @@ gfc_typename (gfc_typespec *ts)
static int flag = 0;
char *buffer;
gfc_typespec *ts1;
+ gfc_charlen_t length = 0;
buffer = flag ? buffer1 : buffer2;
flag = !flag;
@@ -148,7 +149,13 @@ gfc_typename (gfc_typespec *ts)
sprintf (buffer, "LOGICAL(%d)", ts->kind);
break;
case BT_CHARACTER:
- sprintf (buffer, "CHARACTER(%d)", ts->kind);
+ if (ts->u.cl && ts->u.cl->length)
+ length = gfc_mpz_get_hwi (ts->u.cl->length->value.integer);
+ if (ts->kind == gfc_default_character_kind)
+ sprintf (buffer, "CHARACTER(" HOST_WIDE_INT_PRINT_DEC ")", length);
+ else
+ sprintf (buffer, "CHARACTER(" HOST_WIDE_INT_PRINT_DEC ",%d)", length,
+ ts->kind);
break;
case BT_HOLLERITH:
sprintf (buffer, "HOLLERITH");
@@ -186,6 +193,68 @@ gfc_typename (gfc_typespec *ts)
}
+const char *
+gfc_typename (gfc_expr *ex)
+{
+ /* 34 character buffer: 14 for "CHARACTER(n,4)", n can be upto 20 characters,
+ add 19 for the extra width and 1 for '\0' */
+ static char buffer1[34];
+ static char buffer2[34];
+ static bool flag = false;
+ char *buffer;
+ gfc_charlen_t length;
+ buffer = flag ? buffer1 : buffer2;
+ flag = !flag;
+
+ if (ex->ts.type == BT_CHARACTER)
+ {
+ if (ex->ts.u.cl && ex->ts.u.cl->length)
+ length = gfc_mpz_get_hwi (ex->ts.u.cl->length->value.integer);
+ else
+ length = ex->value.character.length;
+ if (ex->ts.kind == gfc_default_character_kind)
+ sprintf (buffer, "CHARACTER(" HOST_WIDE_INT_PRINT_DEC ")", length);
+ else
+ sprintf (buffer, "CHARACTER(" HOST_WIDE_INT_PRINT_DEC ",%d)", length,
+ ex->ts.kind);
+ return buffer;
+ }
+ return gfc_typename(&ex->ts);
+}
+
+/* The type of a dummy variable can also be CHARACTER(*). */
+
+const char *
+gfc_dummy_typename (gfc_typespec *ts)
+{
+ static char buffer1[15]; /* 15 for "CHARACTER(*,4)" + '\0'. */
+ static char buffer2[15];
+ static bool flag = false;
+ char *buffer;
+
+ buffer = flag ? buffer1 : buffer2;
+ flag = !flag;
+
+ if (ts->type == BT_CHARACTER)
+ {
+ bool has_length = false;
+ if (ts->u.cl)
+ has_length = ts->u.cl->length != NULL;
+ if (!has_length)
+ {
+ if (ts->kind == gfc_default_character_kind)
+ sprintf(buffer, "CHARACTER(*)");
+ else if (ts->kind < 10)
+ sprintf(buffer, "CHARACTER(*,%d)", ts->kind);
+ else
+ sprintf(buffer, "CHARACTER(*,?)");
+ return buffer;
+ }
+ }
+ return gfc_typename(ts);
+}
+
+
/* Given an mstring array and a code, locate the code in the table,
returning a pointer to the string. */
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 533445e2655..1ca15352e7e 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -4745,7 +4745,7 @@ load_commons (void)
while (peek_atom () != ATOM_RPAREN)
{
- int flags;
+ int flags = 0;
char* label;
mio_lparen ();
mio_internal_string (name);
@@ -5243,8 +5243,8 @@ read_module (void)
for (c = sym->components; c; c = c->next)
{
pointer_info *p;
- const char *comp_name;
- int n;
+ const char *comp_name = NULL;
+ int n = 0;
mio_lparen (); /* component opening. */
mio_integer (&n);
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index bda7f288989..7df7384c187 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -780,6 +780,7 @@ enum omp_mask1
OMP_CLAUSE_SIMD,
OMP_CLAUSE_THREADS,
OMP_CLAUSE_USE_DEVICE_PTR,
+ OMP_CLAUSE_USE_DEVICE_ADDR, /* Actually, OpenMP 5.0. */
OMP_CLAUSE_NOWAIT,
/* This must come last. */
OMP_MASK1_LAST
@@ -1849,6 +1850,11 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
("use_device_ptr (",
&c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES)
continue;
+ if ((mask & OMP_CLAUSE_USE_DEVICE_ADDR)
+ && gfc_match_omp_variable_list
+ ("use_device_addr (",
+ &c->lists[OMP_LIST_USE_DEVICE_ADDR], false) == MATCH_YES)
+ continue;
break;
case 'v':
/* VECTOR_LENGTH must be matched before VECTOR, because the latter
@@ -1922,6 +1928,8 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
if (gfc_match_omp_eos () != MATCH_YES)
{
+ if (!gfc_error_flag_test ())
+ gfc_error ("Failed to match clause at %C");
gfc_free_omp_clauses (c);
return MATCH_ERROR;
}
@@ -2477,7 +2485,7 @@ cleanup:
| OMP_CLAUSE_IS_DEVICE_PTR)
#define OMP_TARGET_DATA_CLAUSES \
(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
- | OMP_CLAUSE_USE_DEVICE_PTR)
+ | OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR)
#define OMP_TARGET_ENTER_DATA_CLAUSES \
(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \
| OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)
@@ -4006,7 +4014,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
= { "PRIVATE", "FIRSTPRIVATE", "LASTPRIVATE", "COPYPRIVATE", "SHARED",
"COPYIN", "UNIFORM", "ALIGNED", "LINEAR", "DEPEND", "MAP",
"TO", "FROM", "REDUCTION", "DEVICE_RESIDENT", "LINK", "USE_DEVICE",
- "CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR" };
+ "CACHE", "IS_DEVICE_PTR", "USE_DEVICE_PTR", "USE_DEVICE_ADDR" };
if (omp_clauses == NULL)
return;
@@ -4563,8 +4571,26 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
}
break;
case OMP_LIST_IS_DEVICE_PTR:
+ if (!n->sym->attr.dummy)
+ gfc_error ("Non-dummy object %qs in %s clause at %L",
+ n->sym->name, name, &n->where);
+ if (n->sym->attr.allocatable
+ || (n->sym->ts.type == BT_CLASS
+ && CLASS_DATA (n->sym)->attr.allocatable))
+ gfc_error ("ALLOCATABLE object %qs in %s clause at %L",
+ n->sym->name, name, &n->where);
+ if (n->sym->attr.pointer
+ || (n->sym->ts.type == BT_CLASS
+ && CLASS_DATA (n->sym)->attr.pointer))
+ gfc_error ("POINTER object %qs in %s clause at %L",
+ n->sym->name, name, &n->where);
+ if (n->sym->attr.value)
+ gfc_error ("VALUE object %qs in %s clause at %L",
+ n->sym->name, name, &n->where);
+ break;
case OMP_LIST_USE_DEVICE_PTR:
- /* FIXME: Handle these. */
+ case OMP_LIST_USE_DEVICE_ADDR:
+ /* FIXME: Handle OMP_LIST_USE_DEVICE_PTR. */
break;
default:
for (; n != NULL; n = n->next)
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 5bd04b839ce..4d343450555 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -609,13 +609,18 @@ decode_statement (void)
/* Like match and if spec_only, goto do_spec_only without actually
matching. */
+/* If the directive matched but the clauses failed, do not start
+ matching the next directive in the same switch statement. */
#define matcha(keyword, subr, st) \
do { \
+ match m2; \
if (spec_only && gfc_match (keyword) == MATCH_YES) \
goto do_spec_only; \
- else if (match_word (keyword, subr, &old_locus) \
+ else if ((m2 = match_word (keyword, subr, &old_locus)) \
== MATCH_YES) \
return st; \
+ else if (m2 == MATCH_ERROR) \
+ goto error_handling; \
else \
undo_new_statement (); \
} while (0)
@@ -711,6 +716,7 @@ decode_oacc_directive (void)
/* Directive not found or stored an error message.
Check and give up. */
+ error_handling:
if (gfc_error_check () == 0)
gfc_error_now ("Unclassifiable OpenACC directive at %C");
@@ -746,18 +752,23 @@ decode_oacc_directive (void)
/* Like match, but don't match anything if not -fopenmp
and if spec_only, goto do_spec_only without actually matching. */
+/* If the directive matched but the clauses failed, do not start
+ matching the next directive in the same switch statement. */
#define matcho(keyword, subr, st) \
do { \
+ match m2; \
if (!flag_openmp) \
; \
else if (spec_only && gfc_match (keyword) == MATCH_YES) \
goto do_spec_only; \
- else if (match_word (keyword, subr, &old_locus) \
+ else if ((m2 = match_word (keyword, subr, &old_locus)) \
== MATCH_YES) \
{ \
ret = st; \
goto finish; \
} \
+ else if (m2 == MATCH_ERROR) \
+ goto error_handling; \
else \
undo_new_statement (); \
} while (0)
@@ -1030,6 +1041,7 @@ decode_omp_directive (void)
not -fopenmp and simd_matched is false, i.e. if a directive other
than one marked with match has been seen. */
+ error_handling:
if (flag_openmp || simd_matched)
{
if (!gfc_error_check ())
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index e94ea821ba7..6b6c7d2481f 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -789,16 +789,17 @@ done:
if (warn_conversion_extra)
{
mpfr_t r;
- char *c, *p;
+ char *c1;
bool did_break;
- c = strchr (buffer, 'e');
- if (c == NULL)
- c = buffer + strlen(buffer);
+ c1 = strchr (buffer, 'e');
+ if (c1 == NULL)
+ c1 = buffer + strlen(buffer);
did_break = false;
- for (p = c - 1; p >= buffer; p--)
+ for (p = c1; p > buffer;)
{
+ p--;
if (*p == '.')
continue;
@@ -2331,6 +2332,8 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag,
if (tmp && tmp->type == REF_INQUIRY)
{
+ if (!primary->where.lb || !primary->where.nextc)
+ primary->where = gfc_current_locus;
gfc_simplify_expr (primary, 0);
if (primary->expr_type == EXPR_CONSTANT)
@@ -3097,21 +3100,21 @@ gfc_convert_to_structure_constructor (gfc_expr *e, gfc_symbol *sym, gfc_expr **c
&& actual->expr->ts.type == BT_CHARACTER
&& actual->expr->expr_type == EXPR_CONSTANT)
{
- ptrdiff_t c, e;
+ ptrdiff_t c, e1;
c = gfc_mpz_get_hwi (this_comp->ts.u.cl->length->value.integer);
- e = actual->expr->value.character.length;
+ e1 = actual->expr->value.character.length;
- if (c != e)
+ if (c != e1)
{
ptrdiff_t i, to;
gfc_char_t *dest;
dest = gfc_get_wide_string (c + 1);
- to = e < c ? e : c;
+ to = e1 < c ? e1 : c;
for (i = 0; i < to; i++)
dest[i] = actual->expr->value.character.string[i];
- for (i = e; i < c; i++)
+ for (i = e1; i < c; i++)
dest[i] = ' ';
dest[c] = '\0';
@@ -3120,11 +3123,11 @@ gfc_convert_to_structure_constructor (gfc_expr *e, gfc_symbol *sym, gfc_expr **c
actual->expr->value.character.length = c;
actual->expr->value.character.string = dest;
- if (warn_line_truncation && c < e)
+ if (warn_line_truncation && c < e1)
gfc_warning_now (OPT_Wcharacter_truncation,
"CHARACTER expression will be truncated "
"in constructor (%ld/%ld) at %L", (long int) c,
- (long int) e, &actual->expr->where);
+ (long int) e1, &actual->expr->where);
}
}
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index e8d05662514..20ecafd944e 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -3242,6 +3242,21 @@ resolve_function (gfc_expr *expr)
if (expr->expr_type != EXPR_FUNCTION)
return t;
+ /* Walk the argument list looking for invalid BOZ. */
+ if (expr->value.function.esym)
+ {
+ gfc_actual_arglist *a;
+
+ for (a = expr->value.function.actual; a; a = a->next)
+ if (a->expr && a->expr->ts.type == BT_BOZ)
+ {
+ gfc_error ("A BOZ literal constant at %L cannot appear as an "
+ "actual argument in a function reference",
+ &a->expr->where);
+ return false;
+ }
+ }
+
temp = need_full_assumed_size;
need_full_assumed_size = 0;
@@ -3965,7 +3980,7 @@ resolve_operator (gfc_expr *e)
}
sprintf (msg, _("Operand of unary numeric operator %%<%s%%> at %%L is %s"),
- gfc_op2string (e->value.op.op), gfc_typename (&e->ts));
+ gfc_op2string (e->value.op.op), gfc_typename (e));
goto bad_op;
case INTRINSIC_PLUS:
@@ -3987,8 +4002,8 @@ resolve_operator (gfc_expr *e)
else
sprintf (msg,
_("Operands of binary numeric operator %%<%s%%> at %%L are %s/%s"),
- gfc_op2string (e->value.op.op), gfc_typename (&op1->ts),
- gfc_typename (&op2->ts));
+ gfc_op2string (e->value.op.op), gfc_typename (op1),
+ gfc_typename (op2));
goto bad_op;
case INTRINSIC_CONCAT:
@@ -4002,7 +4017,7 @@ resolve_operator (gfc_expr *e)
sprintf (msg,
_("Operands of string concatenation operator at %%L are %s/%s"),
- gfc_typename (&op1->ts), gfc_typename (&op2->ts));
+ gfc_typename (op1), gfc_typename (op2));
goto bad_op;
case INTRINSIC_AND:
@@ -4044,8 +4059,8 @@ resolve_operator (gfc_expr *e)
}
sprintf (msg, _("Operands of logical operator %%<%s%%> at %%L are %s/%s"),
- gfc_op2string (e->value.op.op), gfc_typename (&op1->ts),
- gfc_typename (&op2->ts));
+ gfc_op2string (e->value.op.op), gfc_typename (op1),
+ gfc_typename (op2));
goto bad_op;
@@ -4067,7 +4082,7 @@ resolve_operator (gfc_expr *e)
}
sprintf (msg, _("Operand of .not. operator at %%L is %s"),
- gfc_typename (&op1->ts));
+ gfc_typename (op1));
goto bad_op;
case INTRINSIC_GT:
@@ -4153,7 +4168,7 @@ resolve_operator (gfc_expr *e)
msg = "Inequality comparison for %s at %L";
gfc_warning (OPT_Wcompare_reals, msg,
- gfc_typename (&op1->ts), &op1->where);
+ gfc_typename (op1), &op1->where);
}
}
@@ -4169,8 +4184,8 @@ resolve_operator (gfc_expr *e)
else
sprintf (msg,
_("Operands of comparison operator %%<%s%%> at %%L are %s/%s"),
- gfc_op2string (e->value.op.op), gfc_typename (&op1->ts),
- gfc_typename (&op2->ts));
+ gfc_op2string (e->value.op.op), gfc_typename (op1),
+ gfc_typename (op2));
goto bad_op;
@@ -4188,12 +4203,12 @@ resolve_operator (gfc_expr *e)
}
else if (op2 == NULL)
sprintf (msg, _("Operand of user operator %%<%s%%> at %%L is %s"),
- e->value.op.uop->name, gfc_typename (&op1->ts));
+ e->value.op.uop->name, gfc_typename (op1));
else
{
sprintf (msg, _("Operands of user operator %%<%s%%> at %%L are %s/%s"),
- e->value.op.uop->name, gfc_typename (&op1->ts),
- gfc_typename (&op2->ts));
+ e->value.op.uop->name, gfc_typename (op1),
+ gfc_typename (op2));
e->value.op.uop->op->sym->attr.referenced = 1;
}
@@ -8494,7 +8509,7 @@ resolve_select (gfc_code *code, bool select_type)
if (type != BT_LOGICAL && type != BT_INTEGER && type != BT_CHARACTER)
{
gfc_error ("Argument of SELECT statement at %L cannot be %s",
- &case_expr->where, gfc_typename (&case_expr->ts));
+ &case_expr->where, gfc_typename (case_expr));
/* Punt. Going on here just produce more garbage error messages. */
return;
@@ -8523,7 +8538,7 @@ resolve_select (gfc_code *code, bool select_type)
case_expr->ts.kind) != ARITH_OK)
gfc_warning (0, "Expression in CASE statement at %L is "
"not in the range of %s", &cp->low->where,
- gfc_typename (&case_expr->ts));
+ gfc_typename (case_expr));
if (cp->high
&& cp->low != cp->high
@@ -8531,7 +8546,7 @@ resolve_select (gfc_code *code, bool select_type)
case_expr->ts.kind) != ARITH_OK)
gfc_warning (0, "Expression in CASE statement at %L is "
"not in the range of %s", &cp->high->where,
- gfc_typename (&case_expr->ts));
+ gfc_typename (case_expr));
}
/* PR 19168 has a long discussion concerning a mismatch of the kinds
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 3d2fc0d956f..8c1577ec269 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -2189,11 +2189,22 @@ gfc_expr *
gfc_simplify_dble (gfc_expr *e)
{
gfc_expr *result = NULL;
+ int tmp1, tmp2;
if (e->expr_type != EXPR_CONSTANT)
return NULL;
+ /* For explicit conversion, turn off -Wconversion and -Wconversion-extra
+ warnings. */
+ tmp1 = warn_conversion;
+ tmp2 = warn_conversion_extra;
+ warn_conversion = warn_conversion_extra = 0;
+
result = gfc_convert_constant (e, BT_REAL, gfc_default_double_kind);
+
+ warn_conversion = tmp1;
+ warn_conversion_extra = tmp2;
+
if (result == &gfc_bad_expr)
return &gfc_bad_expr;
@@ -3572,6 +3583,7 @@ static gfc_expr *
simplify_intconv (gfc_expr *e, int kind, const char *name)
{
gfc_expr *result = NULL;
+ int tmp1, tmp2;
/* Convert BOZ to integer, and return without range checking. */
if (e->ts.type == BT_BOZ)
@@ -3585,7 +3597,17 @@ simplify_intconv (gfc_expr *e, int kind, const char *name)
if (e->expr_type != EXPR_CONSTANT)
return NULL;
+ /* For explicit conversion, turn off -Wconversion and -Wconversion-extra
+ warnings. */
+ tmp1 = warn_conversion;
+ tmp2 = warn_conversion_extra;
+ warn_conversion = warn_conversion_extra = 0;
+
result = gfc_convert_constant (e, BT_INTEGER, kind);
+
+ warn_conversion = tmp1;
+ warn_conversion_extra = tmp2;
+
if (result == &gfc_bad_expr)
return &gfc_bad_expr;
@@ -6472,7 +6494,7 @@ gfc_expr *
gfc_simplify_real (gfc_expr *e, gfc_expr *k)
{
gfc_expr *result = NULL;
- int kind;
+ int kind, tmp1, tmp2;
/* Convert BOZ to real, and return without range checking. */
if (e->ts.type == BT_BOZ)
@@ -6500,7 +6522,17 @@ gfc_simplify_real (gfc_expr *e, gfc_expr *k)
if (e->expr_type != EXPR_CONSTANT)
return NULL;
+ /* For explicit conversion, turn off -Wconversion and -Wconversion-extra
+ warnings. */
+ tmp1 = warn_conversion;
+ tmp2 = warn_conversion_extra;
+ warn_conversion = warn_conversion_extra = 0;
+
result = gfc_convert_constant (e, BT_REAL, kind);
+
+ warn_conversion = tmp1;
+ warn_conversion_extra = tmp2;
+
if (result == &gfc_bad_expr)
return &gfc_bad_expr;
@@ -7551,11 +7583,22 @@ gfc_expr *
gfc_simplify_sngl (gfc_expr *a)
{
gfc_expr *result;
+ int tmp1, tmp2;
if (a->expr_type != EXPR_CONSTANT)
return NULL;
+ /* For explicit conversion, turn off -Wconversion and -Wconversion-extra
+ warnings. */
+ tmp1 = warn_conversion;
+ tmp2 = warn_conversion_extra;
+ warn_conversion = warn_conversion_extra = 0;
+
result = gfc_real2real (a, gfc_default_real_kind);
+
+ warn_conversion = tmp1;
+ warn_conversion_extra = tmp2;
+
return range_check (result, "SNGL");
}
@@ -8508,10 +8551,10 @@ gfc_convert_constant (gfc_expr *e, bt type, int kind)
{
if (c->expr->expr_type == EXPR_ARRAY)
tmp = gfc_convert_constant (c->expr, type, kind);
- else if (c->expr->expr_type == EXPR_OP
- && c->expr->value.op.op == INTRINSIC_PARENTHESES)
+ else if (c->expr->expr_type == EXPR_OP)
{
- gfc_simplify_expr (c->expr, 1);
+ if (!gfc_simplify_expr (c->expr, 1))
+ return &gfc_bad_expr;
tmp = f (c->expr, kind);
}
else
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index c2c5d9d1b6a..b701f493440 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1911,9 +1911,13 @@ gfc_get_symbol_decl (gfc_symbol * sym)
if (sym->attr.associate_var)
GFC_DECL_ASSOCIATE_VAR_P (decl) = 1;
+ /* We no longer mark __def_init as read-only so it does not take up
+ space in the read-only section and dan go into the BSS instead,
+ see PR 84487. Marking this as artificial means that OpenMP will
+ treat this as predetermined shared. */
if (sym->attr.vtab
|| (sym->name[0] == '_' && gfc_str_startswith (sym->name, "__def_init")))
- TREE_READONLY (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
return decl;
}
@@ -2687,6 +2691,11 @@ create_function_arglist (gfc_symbol * sym)
&& (!f->sym->attr.proc_pointer
&& f->sym->attr.flavor != FL_PROCEDURE))
DECL_BY_REFERENCE (parm) = 1;
+ if (f->sym->attr.optional)
+ {
+ gfc_allocate_lang_decl (parm);
+ GFC_DECL_OPTIONAL_ARGUMENT (parm) = 1;
+ }
gfc_finish_decl (parm);
gfc_finish_decl_attrs (parm, &f->sym->attr);
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 61db4e39210..965ab7786a1 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -5202,7 +5202,9 @@ gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
tree gfc_desc_ptr;
tree type;
tree cond;
+ tree desc_attr;
int attribute;
+ int cfi_attribute;
symbol_attribute attr = gfc_expr_attr (e);
stmtblock_t block;
@@ -5211,12 +5213,20 @@ gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
attribute = 2;
if (!e->rank || gfc_get_full_arrayspec_from_expr (e))
{
- if (fsym->attr.pointer)
+ if (attr.pointer)
attribute = 0;
- else if (fsym->attr.allocatable)
+ else if (attr.allocatable)
attribute = 1;
}
+ /* If the formal argument is assumed shape and neither a pointer nor
+ allocatable, it is unconditionally CFI_attribute_other. */
+ if (fsym->as->type == AS_ASSUMED_SHAPE
+ && !fsym->attr.pointer && !fsym->attr.allocatable)
+ cfi_attribute = 2;
+ else
+ cfi_attribute = attribute;
+
if (e->rank != 0)
{
parmse->force_no_tmp = 1;
@@ -5283,11 +5293,12 @@ gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
parmse->expr, attr);
}
- /* Set the CFI attribute field. */
- tmp = gfc_conv_descriptor_attribute (parmse->expr);
+ /* Set the CFI attribute field through a temporary value for the
+ gfc attribute. */
+ desc_attr = gfc_conv_descriptor_attribute (parmse->expr);
tmp = fold_build2_loc (input_location, MODIFY_EXPR,
- void_type_node, tmp,
- build_int_cst (TREE_TYPE (tmp), attribute));
+ void_type_node, desc_attr,
+ build_int_cst (TREE_TYPE (desc_attr), cfi_attribute));
gfc_add_expr_to_block (&parmse->pre, tmp);
/* Now pass the gfc_descriptor by reference. */
@@ -5305,6 +5316,12 @@ gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
gfor_fndecl_gfc_to_cfi, 2, tmp, gfc_desc_ptr);
gfc_add_expr_to_block (&parmse->pre, tmp);
+ /* Now set the gfc descriptor attribute. */
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR,
+ void_type_node, desc_attr,
+ build_int_cst (TREE_TYPE (desc_attr), attribute));
+ gfc_add_expr_to_block (&parmse->pre, tmp);
+
/* The CFI descriptor is passed to the bind_C procedure. */
parmse->expr = cfi_desc_ptr;
@@ -5325,6 +5342,25 @@ gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
tmp = build_call_expr_loc (input_location,
gfor_fndecl_cfi_to_gfc, 2, gfc_desc_ptr, tmp);
gfc_prepend_expr_to_block (&parmse->post, tmp);
+
+ /* Deal with an optional dummy being passed to an optional formal arg
+ by finishing the pre and post blocks and making their execution
+ conditional on the dummy being present. */
+ if (fsym->attr.optional && e->expr_type == EXPR_VARIABLE
+ && e->symtree->n.sym->attr.optional)
+ {
+ cond = gfc_conv_expr_present (e->symtree->n.sym);
+ tmp = fold_build2 (MODIFY_EXPR, void_type_node,
+ cfi_desc_ptr,
+ build_int_cst (pvoid_type_node, 0));
+ tmp = build3_v (COND_EXPR, cond,
+ gfc_finish_block (&parmse->pre), tmp);
+ gfc_add_expr_to_block (&parmse->pre, tmp);
+ tmp = build3_v (COND_EXPR, cond,
+ gfc_finish_block (&parmse->post),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&parmse->post, tmp);
+ }
}
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index b4c77aebf4d..f83bab4850e 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -47,6 +47,16 @@ along with GCC; see the file COPYING3. If not see
int ompws_flags;
+/* True if OpenMP should treat this DECL as an optional argument. */
+
+bool
+gfc_omp_is_optional_argument (const_tree decl)
+{
+ return (TREE_CODE (decl) == PARM_DECL
+ && DECL_LANG_SPECIFIC (decl)
+ && GFC_DECL_OPTIONAL_ARGUMENT (decl));
+}
+
/* True if OpenMP should privatize what this DECL points to rather
than the DECL itself. */
@@ -59,6 +69,10 @@ gfc_omp_privatize_by_reference (const_tree decl)
&& (!DECL_ARTIFICIAL (decl) || TREE_CODE (decl) == PARM_DECL))
return true;
+ if (TREE_CODE (type) == POINTER_TYPE
+ && gfc_omp_is_optional_argument (decl))
+ return true;
+
if (TREE_CODE (type) == POINTER_TYPE)
{
/* Array POINTER/ALLOCATABLE have aggregate types, all user variables
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 6ebb71de152..405e88dd1c4 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -786,6 +786,7 @@ struct array_descr_info;
bool gfc_get_array_descr_info (const_tree, struct array_descr_info *);
/* In trans-openmp.c */
+bool gfc_omp_is_optional_argument (const_tree);
bool gfc_omp_privatize_by_reference (const_tree);
enum omp_clause_default_kind gfc_omp_predetermined_sharing (tree);
tree gfc_omp_report_decl (tree);
@@ -999,6 +1000,7 @@ struct GTY(()) lang_decl {
tree token, caf_offset;
unsigned int scalar_allocatable : 1;
unsigned int scalar_pointer : 1;
+ unsigned int optional_arg : 1;
};
@@ -1013,6 +1015,8 @@ struct GTY(()) lang_decl {
(DECL_LANG_SPECIFIC (node)->scalar_allocatable)
#define GFC_DECL_SCALAR_POINTER(node) \
(DECL_LANG_SPECIFIC (node)->scalar_pointer)
+#define GFC_DECL_OPTIONAL_ARGUMENT(node) \
+ (DECL_LANG_SPECIFIC (node)->optional_arg)
#define GFC_DECL_GET_SCALAR_ALLOCATABLE(node) \
(DECL_LANG_SPECIFIC (node) ? GFC_DECL_SCALAR_ALLOCATABLE (node) : 0)
#define GFC_DECL_GET_SCALAR_POINTER(node) \
diff --git a/gcc/generic-match-head.c b/gcc/generic-match-head.c
index b54e03552ba..fdc603977fc 100644
--- a/gcc/generic-match-head.c
+++ b/gcc/generic-match-head.c
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "vec-perm-indices.h"
#include "fold-const.h"
+#include "fold-const-call.h"
#include "stor-layout.h"
#include "tree-dfa.h"
#include "builtins.h"
diff --git a/gcc/genmatch.c b/gcc/genmatch.c
index cede432cdc9..7db1f135840 100644
--- a/gcc/genmatch.c
+++ b/gcc/genmatch.c
@@ -1022,10 +1022,10 @@ commutate (operand *op, vec<vec<user_id *> > &for_vec)
for (unsigned i = 0; i < result.length (); ++i)
{
expr *ne = new expr (e);
- if (operator_id *p = dyn_cast <operator_id *> (ne->operation))
+ if (operator_id *r = dyn_cast <operator_id *> (ne->operation))
{
- if (comparison_code_p (p->code))
- ne->operation = swap_tree_comparison (p);
+ if (comparison_code_p (r->code))
+ ne->operation = swap_tree_comparison (r);
}
else if (user_id *p = dyn_cast <user_id *> (ne->operation))
{
@@ -1279,7 +1279,7 @@ lower_cond (operand *o)
|| (is_a <expr *> (e->ops[0])
&& as_a <expr *> (e->ops[0])->ops.length () == 2)))
{
- expr *ne = new expr (e);
+ ne = new expr (e);
for (unsigned j = 0; j < result[i].length (); ++j)
ne->append_op (result[i][j]);
if (capture *c = dyn_cast <capture *> (ne->ops[0]))
@@ -1637,10 +1637,10 @@ public:
unsigned pos);
dt_node *append_simplify (simplify *, unsigned, dt_operand **);
- virtual void gen (FILE *, int, bool) {}
+ virtual void gen (FILE *, int, bool, int) {}
- void gen_kids (FILE *, int, bool);
- void gen_kids_1 (FILE *, int, bool,
+ void gen_kids (FILE *, int, bool, int);
+ void gen_kids_1 (FILE *, int, bool, int,
vec<dt_operand *>, vec<dt_operand *>, vec<dt_operand *>,
vec<dt_operand *>, vec<dt_operand *>, vec<dt_node *>);
@@ -1663,11 +1663,11 @@ public:
: dt_node (type, parent_), op (op_), match_dop (match_dop_),
pos (pos_), value_match (false), for_id (current_id) {}
- void gen (FILE *, int, bool);
+ void gen (FILE *, int, bool, int);
unsigned gen_predicate (FILE *, int, const char *, bool);
unsigned gen_match_op (FILE *, int, const char *, bool);
- unsigned gen_gimple_expr (FILE *, int);
+ unsigned gen_gimple_expr (FILE *, int, int);
unsigned gen_generic_expr (FILE *, int, const char *);
char *get_name (char *);
@@ -1689,7 +1689,7 @@ public:
indexes (indexes_), info (NULL) {}
void gen_1 (FILE *, int, bool, operand *);
- void gen (FILE *f, int, bool);
+ void gen (FILE *f, int, bool, int);
};
template<>
@@ -1987,9 +1987,9 @@ decision_tree::insert_operand (dt_node *p, operand *o, dt_operand **indexes,
if (elm == 0)
{
- dt_operand temp (dt_node::DT_MATCH, 0, match_op, 0, 0);
- temp.value_match = c->value_match;
- elm = decision_tree::find_node (p->kids, &temp);
+ dt_operand match (dt_node::DT_MATCH, 0, match_op, 0, 0);
+ match.value_match = c->value_match;
+ elm = decision_tree::find_node (p->kids, &match);
}
}
else
@@ -2202,7 +2202,7 @@ capture_info::walk_match (operand *o, unsigned toplevel_arg,
for (unsigned i = 0; i < e->ops.length (); ++i)
{
bool cond_p = conditional_p;
- bool cond_expr_cond_p = false;
+ bool expr_cond_p = false;
if (i != 0 && *e->operation == COND_EXPR)
cond_p = true;
else if (*e->operation == TRUTH_ANDIF_EXPR
@@ -2211,8 +2211,8 @@ capture_info::walk_match (operand *o, unsigned toplevel_arg,
if (i == 0
&& (*e->operation == COND_EXPR
|| *e->operation == VEC_COND_EXPR))
- cond_expr_cond_p = true;
- walk_match (e->ops[i], toplevel_arg, cond_p, cond_expr_cond_p);
+ expr_cond_p = true;
+ walk_match (e->ops[i], toplevel_arg, cond_p, expr_cond_p);
}
}
else if (is_a <predicate *> (o))
@@ -2270,42 +2270,42 @@ capture_info::walk_result (operand *o, bool conditional_p, operand *result)
walk_result (e->ops[i], cond_p, result);
}
}
- else if (if_expr *e = dyn_cast <if_expr *> (o))
+ else if (if_expr *ie = dyn_cast <if_expr *> (o))
{
/* 'if' conditions should be all fine. */
- if (e->trueexpr == result)
+ if (ie->trueexpr == result)
{
- walk_result (e->trueexpr, false, result);
+ walk_result (ie->trueexpr, false, result);
return true;
}
- if (e->falseexpr == result)
+ if (ie->falseexpr == result)
{
- walk_result (e->falseexpr, false, result);
+ walk_result (ie->falseexpr, false, result);
return true;
}
bool res = false;
- if (is_a <if_expr *> (e->trueexpr)
- || is_a <with_expr *> (e->trueexpr))
- res |= walk_result (e->trueexpr, false, result);
- if (e->falseexpr
- && (is_a <if_expr *> (e->falseexpr)
- || is_a <with_expr *> (e->falseexpr)))
- res |= walk_result (e->falseexpr, false, result);
+ if (is_a <if_expr *> (ie->trueexpr)
+ || is_a <with_expr *> (ie->trueexpr))
+ res |= walk_result (ie->trueexpr, false, result);
+ if (ie->falseexpr
+ && (is_a <if_expr *> (ie->falseexpr)
+ || is_a <with_expr *> (ie->falseexpr)))
+ res |= walk_result (ie->falseexpr, false, result);
return res;
}
- else if (with_expr *e = dyn_cast <with_expr *> (o))
+ else if (with_expr *we = dyn_cast <with_expr *> (o))
{
- bool res = (e->subexpr == result);
+ bool res = (we->subexpr == result);
if (res
- || is_a <if_expr *> (e->subexpr)
- || is_a <with_expr *> (e->subexpr))
- res |= walk_result (e->subexpr, false, result);
+ || is_a <if_expr *> (we->subexpr)
+ || is_a <with_expr *> (we->subexpr))
+ res |= walk_result (we->subexpr, false, result);
if (res)
- walk_c_expr (e->with);
+ walk_c_expr (we->with);
return res;
}
- else if (c_expr *e = dyn_cast <c_expr *> (o))
- walk_c_expr (e);
+ else if (c_expr *ce = dyn_cast <c_expr *> (o))
+ walk_c_expr (ce);
else
gcc_unreachable ();
@@ -2347,14 +2347,14 @@ capture_info::walk_c_expr (c_expr *e)
|| n->type == CPP_NAME)
&& !(n->flags & PREV_WHITE))
{
- const char *id;
+ const char *id1;
if (n->type == CPP_NUMBER)
- id = (const char *)n->val.str.text;
+ id1 = (const char *)n->val.str.text;
else
- id = (const char *)CPP_HASHNODE (n->val.node.node)->ident.str;
- unsigned *where = e->capture_ids->get(id);
+ id1 = (const char *)CPP_HASHNODE (n->val.node.node)->ident.str;
+ unsigned *where = e->capture_ids->get(id1);
if (! where)
- fatal_at (n, "unknown capture id '%s'", id);
+ fatal_at (n, "unknown capture id '%s'", id1);
info[info[*where].same_as].force_no_side_effects_p = true;
if (verbose >= 1
&& !gimple)
@@ -2452,7 +2452,8 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
|| *opr == IMAGPART_EXPR)
{
/* __real and __imag use the component type of its operand. */
- sprintf (optype, "TREE_TYPE (TREE_TYPE (ops%d[0]))", depth);
+ snprintf (optype, sizeof (optype), "TREE_TYPE (TREE_TYPE (_o%d[0]))",
+ depth);
type = optype;
}
else if (is_a <operator_id *> (opr)
@@ -2464,7 +2465,7 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
type = in_type;
else
{
- sprintf (optype, "boolean_type_node");
+ snprintf (optype, sizeof (optype), "boolean_type_node");
type = optype;
}
in_type = NULL;
@@ -2474,13 +2475,13 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
|| strncmp (opr->id, "CFN_COND_", 9) == 0)
{
/* Conditions are of the same type as their first alternative. */
- sprintf (optype, "TREE_TYPE (ops%d[1])", depth);
+ snprintf (optype, sizeof (optype), "TREE_TYPE (_o%d[1])", depth);
type = optype;
}
else
{
/* Other operations are of the same type as their first operand. */
- sprintf (optype, "TREE_TYPE (ops%d[0])", depth);
+ snprintf (optype, sizeof (optype), "TREE_TYPE (_o%d[0])", depth);
type = optype;
}
if (!type)
@@ -2488,17 +2489,18 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
fprintf_indent (f, indent, "{\n");
indent += 2;
- fprintf_indent (f, indent, "tree ops%d[%u], res;\n", depth, ops.length ());
+ fprintf_indent (f, indent,
+ "tree _o%d[%u], _r%d;\n", depth, ops.length (), depth);
char op0type[64];
- snprintf (op0type, 64, "TREE_TYPE (ops%d[0])", depth);
+ snprintf (op0type, sizeof (op0type), "TREE_TYPE (_o%d[0])", depth);
for (unsigned i = 0; i < ops.length (); ++i)
{
- char dest[32];
- snprintf (dest, 32, "ops%d[%u]", depth, i);
- const char *optype
+ char dest1[32];
+ snprintf (dest1, sizeof (dest1), "_o%d[%u]", depth, i);
+ const char *optype1
= get_operand_type (opr, i, in_type, expr_type,
i == 0 ? NULL : op0type);
- ops[i]->gen_transform (f, indent, dest, gimple, depth + 1, optype,
+ ops[i]->gen_transform (f, indent, dest1, gimple, depth + 1, optype1,
cinfo, indexes,
(*opr == COND_EXPR
|| *opr == VEC_COND_EXPR) && i == 0 ? 1 : 2);
@@ -2515,10 +2517,11 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
if (*opr == CONVERT_EXPR)
{
fprintf_indent (f, indent,
- "if (%s != TREE_TYPE (ops%d[0])\n",
+ "if (%s != TREE_TYPE (_o%d[0])\n",
type, depth);
fprintf_indent (f, indent,
- " && !useless_type_conversion_p (%s, TREE_TYPE (ops%d[0])))\n",
+ " && !useless_type_conversion_p (%s, TREE_TYPE "
+ "(_o%d[0])))\n",
type, depth);
fprintf_indent (f, indent + 2, "{\n");
indent += 4;
@@ -2529,46 +2532,48 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
fprintf_indent (f, indent, "gimple_match_op tem_op "
"(res_op->cond.any_else (), %s, %s", opr_name, type);
for (unsigned i = 0; i < ops.length (); ++i)
- fprintf (f, ", ops%d[%u]", depth, i);
+ fprintf (f, ", _o%d[%u]", depth, i);
fprintf (f, ");\n");
fprintf_indent (f, indent,
"gimple_resimplify%d (lseq, &tem_op, valueize);\n",
ops.length ());
fprintf_indent (f, indent,
- "res = maybe_push_res_to_seq (&tem_op, lseq);\n");
+ "_r%d = maybe_push_res_to_seq (&tem_op, lseq);\n",
+ depth);
fprintf_indent (f, indent,
- "if (!res) return false;\n");
+ "if (!_r%d) return false;\n",
+ depth);
if (*opr == CONVERT_EXPR)
{
indent -= 4;
fprintf_indent (f, indent, " }\n");
fprintf_indent (f, indent, "else\n");
- fprintf_indent (f, indent, " res = ops%d[0];\n", depth);
+ fprintf_indent (f, indent, " _r%d = _o%d[0];\n", depth, depth);
}
}
else
{
if (*opr == CONVERT_EXPR)
{
- fprintf_indent (f, indent, "if (TREE_TYPE (ops%d[0]) != %s)\n",
+ fprintf_indent (f, indent, "if (TREE_TYPE (_o%d[0]) != %s)\n",
depth, type);
indent += 2;
}
if (opr->kind == id_base::CODE)
- fprintf_indent (f, indent, "res = fold_build%d_loc (loc, %s, %s",
- ops.length(), opr_name, type);
+ fprintf_indent (f, indent, "_r%d = fold_build%d_loc (loc, %s, %s",
+ depth, ops.length(), opr_name, type);
else
{
fprintf_indent (f, indent, "{\n");
- fprintf_indent (f, indent, " res = maybe_build_call_expr_loc (loc, "
- "%s, %s, %d", opr_name, type, ops.length());
+ fprintf_indent (f, indent, " _r%d = maybe_build_call_expr_loc (loc, "
+ "%s, %s, %d", depth, opr_name, type, ops.length());
}
for (unsigned i = 0; i < ops.length (); ++i)
- fprintf (f, ", ops%d[%u]", depth, i);
+ fprintf (f, ", _o%d[%u]", depth, i);
fprintf (f, ");\n");
if (opr->kind != id_base::CODE)
{
- fprintf_indent (f, indent, " if (!res)\n");
+ fprintf_indent (f, indent, " if (!_r%d)\n", depth);
fprintf_indent (f, indent, " return NULL_TREE;\n");
fprintf_indent (f, indent, "}\n");
}
@@ -2576,10 +2581,10 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
{
indent -= 2;
fprintf_indent (f, indent, "else\n");
- fprintf_indent (f, indent, " res = ops%d[0];\n", depth);
+ fprintf_indent (f, indent, " _r%d = _o%d[0];\n", depth, depth);
}
}
- fprintf_indent (f, indent, "%s = res;\n", dest);
+ fprintf_indent (f, indent, "%s = _r%d;\n", dest, depth);
indent -= 2;
fprintf_indent (f, indent, "}\n");
}
@@ -2670,7 +2675,7 @@ capture::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
if (indexes[where] == 0)
{
char buf[20];
- sprintf (buf, "captures[%u]", where);
+ snprintf (buf, sizeof (buf), "captures[%u]", where);
what->gen_transform (f, indent, buf, gimple, depth, in_type,
cinfo, NULL);
}
@@ -2725,11 +2730,11 @@ dt_operand::get_name (char *name)
if (! parent)
sprintf (name, "t");
else if (parent->level == 1)
- sprintf (name, "op%u", pos);
+ sprintf (name, "_p%u", pos);
else if (parent->type == dt_node::DT_MATCH)
return as_a <dt_operand *> (parent)->get_name (name);
else
- sprintf (name, "o%u%u", parent->level, pos);
+ sprintf (name, "_q%u%u", parent->level, pos);
return name;
}
@@ -2739,9 +2744,9 @@ void
dt_operand::gen_opname (char *name, unsigned pos)
{
if (! parent)
- sprintf (name, "op%u", pos);
+ sprintf (name, "_p%u", pos);
else
- sprintf (name, "o%u%u", level, pos);
+ sprintf (name, "_q%u%u", level, pos);
}
/* Generate matching code for the decision tree operand which is
@@ -2793,7 +2798,7 @@ dt_operand::gen_match_op (FILE *f, int indent, const char *opname, bool)
/* Generate GIMPLE matching code for the decision tree operand. */
unsigned
-dt_operand::gen_gimple_expr (FILE *f, int indent)
+dt_operand::gen_gimple_expr (FILE *f, int indent, int depth)
{
expr *e = static_cast<expr *> (op);
id_base *id = e->operation;
@@ -2825,8 +2830,8 @@ dt_operand::gen_gimple_expr (FILE *f, int indent)
else
fprintf_indent (f, indent,
"tree %s = TREE_OPERAND "
- "(gimple_assign_rhs1 (def), %i);\n",
- child_opname, i);
+ "(gimple_assign_rhs1 (_a%d), %i);\n",
+ child_opname, depth, i);
fprintf_indent (f, indent,
"if ((TREE_CODE (%s) == SSA_NAME\n",
child_opname);
@@ -2844,13 +2849,13 @@ dt_operand::gen_gimple_expr (FILE *f, int indent)
}
else
fprintf_indent (f, indent,
- "tree %s = gimple_assign_rhs%u (def);\n",
- child_opname, i + 1);
+ "tree %s = gimple_assign_rhs%u (_a%d);\n",
+ child_opname, i + 1, depth);
}
else
fprintf_indent (f, indent,
- "tree %s = gimple_call_arg (def, %u);\n",
- child_opname, i);
+ "tree %s = gimple_call_arg (_c%d, %u);\n",
+ child_opname, depth, i);
fprintf_indent (f, indent,
"%s = do_valueize (valueize, %s);\n",
child_opname, child_opname);
@@ -2902,7 +2907,7 @@ dt_operand::gen_generic_expr (FILE *f, int indent, const char *opname)
/* Generate matching code for the children of the decision tree node. */
void
-dt_node::gen_kids (FILE *f, int indent, bool gimple)
+dt_node::gen_kids (FILE *f, int indent, bool gimple, int depth)
{
auto_vec<dt_operand *> gimple_exprs;
auto_vec<dt_operand *> generic_exprs;
@@ -2953,10 +2958,10 @@ dt_node::gen_kids (FILE *f, int indent, bool gimple)
Like DT_TRUE, DT_MATCH serves as a barrier as it can cause
dependent matches to get out-of-order. Generate code now
for what we have collected sofar. */
- gen_kids_1 (f, indent, gimple, gimple_exprs, generic_exprs,
+ gen_kids_1 (f, indent, gimple, depth, gimple_exprs, generic_exprs,
fns, generic_fns, preds, others);
/* And output the true operand itself. */
- kids[i]->gen (f, indent, gimple);
+ kids[i]->gen (f, indent, gimple, depth);
gimple_exprs.truncate (0);
generic_exprs.truncate (0);
fns.truncate (0);
@@ -2969,14 +2974,14 @@ dt_node::gen_kids (FILE *f, int indent, bool gimple)
}
/* Generate code for the remains. */
- gen_kids_1 (f, indent, gimple, gimple_exprs, generic_exprs,
+ gen_kids_1 (f, indent, gimple, depth, gimple_exprs, generic_exprs,
fns, generic_fns, preds, others);
}
/* Generate matching code for the children of the decision tree node. */
void
-dt_node::gen_kids_1 (FILE *f, int indent, bool gimple,
+dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth,
vec<dt_operand *> gimple_exprs,
vec<dt_operand *> generic_exprs,
vec<dt_operand *> fns,
@@ -3010,20 +3015,23 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple,
if (exprs_len || fns_len)
{
+ depth++;
fprintf_indent (f, indent,
"case SSA_NAME:\n");
fprintf_indent (f, indent,
- " if (gimple *def_stmt = get_def (valueize, %s))\n",
- kid_opname);
+ " if (gimple *_d%d = get_def (valueize, %s))\n",
+ depth, kid_opname);
fprintf_indent (f, indent,
" {\n");
indent += 6;
if (exprs_len)
{
fprintf_indent (f, indent,
- "if (gassign *def = dyn_cast <gassign *> (def_stmt))\n");
+ "if (gassign *_a%d = dyn_cast <gassign *> (_d%d))\n",
+ depth, depth);
fprintf_indent (f, indent,
- " switch (gimple_assign_rhs_code (def))\n");
+ " switch (gimple_assign_rhs_code (_a%d))\n",
+ depth);
indent += 4;
fprintf_indent (f, indent, "{\n");
for (unsigned i = 0; i < exprs_len; ++i)
@@ -3035,7 +3043,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple,
else
fprintf_indent (f, indent, "case %s:\n", op->id);
fprintf_indent (f, indent, " {\n");
- gimple_exprs[i]->gen (f, indent + 4, true);
+ gimple_exprs[i]->gen (f, indent + 4, true, depth);
fprintf_indent (f, indent, " break;\n");
fprintf_indent (f, indent, " }\n");
}
@@ -3047,11 +3055,11 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple,
if (fns_len)
{
fprintf_indent (f, indent,
- "%sif (gcall *def = dyn_cast <gcall *>"
- " (def_stmt))\n",
- exprs_len ? "else " : "");
+ "%sif (gcall *_c%d = dyn_cast <gcall *> (_d%d))\n",
+ exprs_len ? "else " : "", depth, depth);
fprintf_indent (f, indent,
- " switch (gimple_call_combined_fn (def))\n");
+ " switch (gimple_call_combined_fn (_c%d))\n",
+ depth);
indent += 4;
fprintf_indent (f, indent, "{\n");
@@ -3060,7 +3068,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple,
expr *e = as_a <expr *>(fns[i]->op);
fprintf_indent (f, indent, "case %s:\n", e->operation->id);
fprintf_indent (f, indent, " {\n");
- fns[i]->gen (f, indent + 4, true);
+ fns[i]->gen (f, indent + 4, true, depth);
fprintf_indent (f, indent, " break;\n");
fprintf_indent (f, indent, " }\n");
}
@@ -3071,6 +3079,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple,
}
indent -= 6;
+ depth--;
fprintf_indent (f, indent, " }\n");
/* See if there is SSA_NAME among generic_exprs and if yes, emit it
here rather than in the next loop. */
@@ -3081,7 +3090,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple,
if (*op == SSA_NAME && (exprs_len || fns_len))
{
fprintf_indent (f, indent + 4, "{\n");
- generic_exprs[i]->gen (f, indent + 6, gimple);
+ generic_exprs[i]->gen (f, indent + 6, gimple, depth);
fprintf_indent (f, indent + 4, "}\n");
}
}
@@ -3101,7 +3110,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple,
else
fprintf_indent (f, indent, "case %s:\n", op->id);
fprintf_indent (f, indent, " {\n");
- generic_exprs[i]->gen (f, indent + 4, gimple);
+ generic_exprs[i]->gen (f, indent + 4, gimple, depth);
fprintf_indent (f, indent, " break;\n");
fprintf_indent (f, indent, " }\n");
}
@@ -3124,7 +3133,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple,
fprintf_indent (f, indent, "case %s:\n", e->operation->id);
fprintf_indent (f, indent, " {\n");
- generic_fns[j]->gen (f, indent + 4, false);
+ generic_fns[j]->gen (f, indent + 4, false, depth);
fprintf_indent (f, indent, " break;\n");
fprintf_indent (f, indent, " }\n");
}
@@ -3163,20 +3172,20 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple,
fprintf_indent (f, indent + 4, "tree %s = %s_pops[%d];\n",
child_opname, kid_opname, j);
}
- preds[i]->gen_kids (f, indent + 4, gimple);
+ preds[i]->gen_kids (f, indent + 4, gimple, depth);
fprintf (f, "}\n");
indent -= 2;
fprintf_indent (f, indent, "}\n");
}
for (unsigned i = 0; i < others.length (); ++i)
- others[i]->gen (f, indent, gimple);
+ others[i]->gen (f, indent, gimple, depth);
}
/* Generate matching code for the decision tree operand. */
void
-dt_operand::gen (FILE *f, int indent, bool gimple)
+dt_operand::gen (FILE *f, int indent, bool gimple, int depth)
{
char opname[20];
get_name (opname);
@@ -3192,7 +3201,7 @@ dt_operand::gen (FILE *f, int indent, bool gimple)
case operand::OP_EXPR:
if (gimple)
- n_braces = gen_gimple_expr (f, indent);
+ n_braces = gen_gimple_expr (f, indent, depth);
else
n_braces = gen_generic_expr (f, indent, opname);
break;
@@ -3208,7 +3217,7 @@ dt_operand::gen (FILE *f, int indent, bool gimple)
gcc_unreachable ();
indent += 4 * n_braces;
- gen_kids (f, indent, gimple);
+ gen_kids (f, indent, gimple, depth);
for (unsigned i = 0; i < n_braces; ++i)
{
@@ -3276,7 +3285,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
if (cinfo.force_no_side_effects & (1 << i))
{
fprintf_indent (f, indent,
- "if (TREE_SIDE_EFFECTS (op%d)) return NULL_TREE;\n",
+ "if (TREE_SIDE_EFFECTS (_p%d)) return NULL_TREE;\n",
i);
if (verbose >= 1)
warning_at (as_a <expr *> (s->match)->ops[i]->location,
@@ -3381,9 +3390,9 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
{
char dest[32];
if (is_predicate)
- snprintf (dest, 32, "res_ops[%d]", j);
+ snprintf (dest, sizeof (dest), "res_ops[%d]", j);
else
- snprintf (dest, 32, "res_op->ops[%d]", j);
+ snprintf (dest, sizeof (dest), "res_op->ops[%d]", j);
const char *optype
= get_operand_type (opr, j,
"type", e->expr_type,
@@ -3468,11 +3477,11 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
{
char dest[32];
if (is_predicate)
- snprintf (dest, 32, "res_ops[%d]", j);
+ snprintf (dest, sizeof (dest), "res_ops[%d]", j);
else
{
fprintf_indent (f, indent, "tree res_op%d;\n", j);
- snprintf (dest, 32, "res_op%d", j);
+ snprintf (dest, sizeof (dest), "res_op%d", j);
}
const char *optype
= get_operand_type (opr, j,
@@ -3486,24 +3495,24 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
fprintf_indent (f, indent, "return true;\n");
else
{
- fprintf_indent (f, indent, "tree res;\n");
+ fprintf_indent (f, indent, "tree _r;\n");
/* Re-fold the toplevel result. Use non_lvalue to
- build NON_LVALUE_EXPRs so they get properly
+ build NON_LVALUE_EXPRs so they get properly
ignored when in GIMPLE form. */
if (*opr == NON_LVALUE_EXPR)
fprintf_indent (f, indent,
- "res = non_lvalue_loc (loc, res_op0);\n");
+ "_r = non_lvalue_loc (loc, res_op0);\n");
else
{
if (is_a <operator_id *> (opr))
fprintf_indent (f, indent,
- "res = fold_build%d_loc (loc, %s, type",
+ "_r = fold_build%d_loc (loc, %s, type",
e->ops.length (),
*e->operation == CONVERT_EXPR
? "NOP_EXPR" : e->operation->id);
else
fprintf_indent (f, indent,
- "res = maybe_build_call_expr_loc (loc, "
+ "_r = maybe_build_call_expr_loc (loc, "
"%s, type, %d", e->operation->id,
e->ops.length());
for (unsigned j = 0; j < e->ops.length (); ++j)
@@ -3511,7 +3520,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
fprintf (f, ");\n");
if (!is_a <operator_id *> (opr))
{
- fprintf_indent (f, indent, "if (!res)\n");
+ fprintf_indent (f, indent, "if (!_r)\n");
fprintf_indent (f, indent, " return NULL_TREE;\n");
}
}
@@ -3521,8 +3530,8 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
|| result->type == operand::OP_C_EXPR)
{
- fprintf_indent (f, indent, "tree res;\n");
- result->gen_transform (f, indent, "res", false, 1, "type",
+ fprintf_indent (f, indent, "tree _r;\n");
+ result->gen_transform (f, indent, "_r", false, 1, "type",
&cinfo, indexes);
}
else
@@ -3543,12 +3552,12 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
"if (TREE_SIDE_EFFECTS (captures[%d]))\n",
i);
fprintf_indent (f, indent + 2,
- "res = build2_loc (loc, COMPOUND_EXPR, type, "
- "fold_ignored_result (captures[%d]), res);\n",
+ "_r = build2_loc (loc, COMPOUND_EXPR, type, "
+ "fold_ignored_result (captures[%d]), _r);\n",
i);
}
}
- fprintf_indent (f, indent, "return res;\n");
+ fprintf_indent (f, indent, "return _r;\n");
}
}
}
@@ -3558,7 +3567,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
that is not part of the decision tree (simplify->match). */
void
-dt_simplify::gen (FILE *f, int indent, bool gimple)
+dt_simplify::gen (FILE *f, int indent, bool gimple, int depth ATTRIBUTE_UNUSED)
{
fprintf_indent (f, indent, "{\n");
indent += 2;
@@ -3597,7 +3606,7 @@ dt_simplify::gen (FILE *f, int indent, bool gimple)
fprintf_indent (f, indent, "tree res = %s (loc, type",
info->fname);
for (unsigned i = 0; i < as_a <expr *> (s->match)->ops.length (); ++i)
- fprintf (f, ", op%d", i);
+ fprintf (f, ", _p%d", i);
fprintf (f, ", captures");
for (unsigned i = 0; i < s->for_subst_vec.length (); ++i)
{
@@ -3764,7 +3773,7 @@ decision_tree::gen (FILE *f, bool gimple)
(*iter).second->fname);
for (unsigned i = 0;
i < as_a <expr *>(s->s->s->match)->ops.length (); ++i)
- fprintf (f, " tree ARG_UNUSED (op%d),", i);
+ fprintf (f, " tree ARG_UNUSED (_p%d),", i);
fprintf (f, " tree *captures\n");
}
for (unsigned i = 0; i < s->s->s->for_subst_vec.length (); ++i)
@@ -3792,9 +3801,9 @@ decision_tree::gen (FILE *f, bool gimple)
for (unsigned n = 1; n <= 5; ++n)
{
/* First generate split-out functions. */
- for (unsigned i = 0; i < root->kids.length (); i++)
+ for (unsigned j = 0; j < root->kids.length (); j++)
{
- dt_operand *dop = static_cast<dt_operand *>(root->kids[i]);
+ dt_operand *dop = static_cast<dt_operand *>(root->kids[j]);
expr *e = static_cast<expr *>(dop->op);
if (e->ops.length () != n
/* Builtin simplifications are somewhat premature on
@@ -3820,10 +3829,10 @@ decision_tree::gen (FILE *f, bool gimple)
"tree_code ARG_UNUSED (code), const tree ARG_UNUSED (type)",
e->operation->id);
for (unsigned i = 0; i < n; ++i)
- fprintf (f, ", tree op%d", i);
+ fprintf (f, ", tree _p%d", i);
fprintf (f, ")\n");
fprintf (f, "{\n");
- dop->gen_kids (f, 2, gimple);
+ dop->gen_kids (f, 2, gimple, 0);
if (gimple)
fprintf (f, " return false;\n");
else
@@ -3843,7 +3852,7 @@ decision_tree::gen (FILE *f, bool gimple)
"generic_simplify (location_t loc, enum tree_code code, "
"const tree type ATTRIBUTE_UNUSED");
for (unsigned i = 0; i < n; ++i)
- fprintf (f, ", tree op%d", i);
+ fprintf (f, ", tree _p%d", i);
fprintf (f, ")\n");
fprintf (f, "{\n");
@@ -3879,8 +3888,8 @@ decision_tree::gen (FILE *f, bool gimple)
else
fprintf (f, " return generic_simplify_%s (loc, code, type",
e->operation->id);
- for (unsigned i = 0; i < n; ++i)
- fprintf (f, ", op%d", i);
+ for (unsigned j = 0; j < n; ++j)
+ fprintf (f, ", _p%d", j);
fprintf (f, ");\n");
}
fprintf (f, " default:;\n"
@@ -3909,7 +3918,7 @@ write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple)
if (!gimple)
fprintf_indent (f, 2, "if (TREE_SIDE_EFFECTS (t)) return false;\n");
- dt.root->gen_kids (f, 2, gimple);
+ dt.root->gen_kids (f, 2, gimple, 0);
fprintf_indent (f, 2, "return false;\n"
"}\n");
@@ -4114,7 +4123,7 @@ parser::get_internal_capture_id ()
/* Big enough for a 32-bit UINT_MAX plus prefix. */
char id[13];
bool existed;
- sprintf (id, "__%u", newid);
+ snprintf (id, sizeof (id), "__%u", newid);
capture_ids->get_or_insert (xstrdup (id), &existed);
if (existed)
fatal ("reserved capture id '%s' already used", id);
@@ -4261,11 +4270,11 @@ parser::parse_expr ()
{
if (*sp == 'c')
{
- if (operator_id *p
+ if (operator_id *o
= dyn_cast<operator_id *> (e->operation))
{
- if (!commutative_tree_code (p->code)
- && !comparison_code_p (p->code))
+ if (!commutative_tree_code (o->code)
+ && !comparison_code_p (o->code))
fatal_at (token, "operation is not commutative");
}
else if (user_id *p = dyn_cast<user_id *> (e->operation))
@@ -4313,7 +4322,7 @@ parser::parse_expr ()
op = e;
do
{
- const cpp_token *token = peek ();
+ token = peek ();
if (token->type == CPP_CLOSE_PAREN)
{
if (e->operation->nargs != -1
@@ -4424,17 +4433,17 @@ parser::parse_op ()
id_base *opr = get_operator (id);
if (!opr)
fatal_at (token, "expected predicate name");
- if (operator_id *code = dyn_cast <operator_id *> (opr))
+ if (operator_id *code1 = dyn_cast <operator_id *> (opr))
{
- if (code->nargs != 0)
+ if (code1->nargs != 0)
fatal_at (token, "using an operator with operands as predicate");
/* Parse the zero-operand operator "predicates" as
expression. */
op = new expr (opr, token->src_loc);
}
- else if (user_id *code = dyn_cast <user_id *> (opr))
+ else if (user_id *code2 = dyn_cast <user_id *> (opr))
{
- if (code->nargs != 0)
+ if (code2->nargs != 0)
fatal_at (token, "using an operator with operands as predicate");
/* Parse the zero-operand operator "predicates" as
expression. */
@@ -4859,7 +4868,7 @@ parser::parse_if (location_t)
active_ifs.safe_push (ifexpr);
while (1)
{
- const cpp_token *token = peek ();
+ token = peek ();
if (token->type == CPP_CLOSE_PAREN)
break;
@@ -4910,14 +4919,14 @@ parser::parse_pattern ()
with_args = true;
}
const char *name = get_ident ();
- id_base *id = get_operator (name);
+ id_base *id1 = get_operator (name);
predicate_id *p;
- if (!id)
+ if (!id1)
{
p = add_predicate (name);
user_predicates.safe_push (p);
}
- else if ((p = dyn_cast <predicate_id *> (id)))
+ else if ((p = dyn_cast <predicate_id *> (id1)))
;
else
fatal_at (token, "cannot add a match to a non-predicate ID");
@@ -5160,12 +5169,12 @@ add_operator (VIEW_CONVERT2, "view_convert2", "tcc_unary", 1);
lower (pred->matchers, gimple);
if (verbose == 2)
- for (unsigned i = 0; i < pred->matchers.length (); ++i)
- print_matches (pred->matchers[i]);
+ for (unsigned j = 0; j < pred->matchers.length (); ++j)
+ print_matches (pred->matchers[j]);
decision_tree dt;
- for (unsigned i = 0; i < pred->matchers.length (); ++i)
- dt.insert (pred->matchers[i], i);
+ for (unsigned j = 0; j < pred->matchers.length (); ++j)
+ dt.insert (pred->matchers[j], j);
if (verbose == 2)
dt.print (stderr);
diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
index 4082828e198..1738af186d7 100644
--- a/gcc/gimple-expr.c
+++ b/gcc/gimple-expr.c
@@ -574,6 +574,7 @@ gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
|| TREE_CODE (cond) == TRUTH_NOT_EXPR
|| is_gimple_min_invariant (cond)
|| SSA_VAR_P (cond));
+ gcc_checking_assert (!tree_could_throw_p (cond));
extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
@@ -605,17 +606,33 @@ is_gimple_lvalue (tree t)
|| TREE_CODE (t) == BIT_FIELD_REF);
}
-/* Return true if T is a GIMPLE condition. */
+/* Helper for is_gimple_condexpr and is_gimple_condexpr_for_cond. */
-bool
-is_gimple_condexpr (tree t)
+static bool
+is_gimple_condexpr_1 (tree t, bool allow_traps)
{
return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
- && !tree_could_throw_p (t)
+ && (allow_traps || !tree_could_throw_p (t))
&& is_gimple_val (TREE_OPERAND (t, 0))
&& is_gimple_val (TREE_OPERAND (t, 1))));
}
+/* Return true if T is a GIMPLE condition. */
+
+bool
+is_gimple_condexpr (tree t)
+{
+ return is_gimple_condexpr_1 (t, true);
+}
+
+/* Like is_gimple_condexpr, but does not allow T to trap. */
+
+bool
+is_gimple_condexpr_for_cond (tree t)
+{
+ return is_gimple_condexpr_1 (t, false);
+}
+
/* Return true if T is a gimple address. */
bool
diff --git a/gcc/gimple-expr.h b/gcc/gimple-expr.h
index 1ad1432bd17..0925aeb0f57 100644
--- a/gcc/gimple-expr.h
+++ b/gcc/gimple-expr.h
@@ -41,6 +41,7 @@ extern void gimple_cond_get_ops_from_tree (tree, enum tree_code *, tree *,
tree *);
extern bool is_gimple_lvalue (tree);
extern bool is_gimple_condexpr (tree);
+extern bool is_gimple_condexpr_for_cond (tree);
extern bool is_gimple_address (const_tree);
extern bool is_gimple_invariant_address (const_tree);
extern bool is_gimple_ip_invariant_address (const_tree);
diff --git a/gcc/gimple-iterator.h b/gcc/gimple-iterator.h
index ee6f5b1f54d..ccd93d936be 100644
--- a/gcc/gimple-iterator.h
+++ b/gcc/gimple-iterator.h
@@ -325,28 +325,31 @@ gsi_one_nondebug_before_end_p (gimple_stmt_iterator i)
return gsi_end_p (i);
}
-/* Iterates I statement iterator to the next non-virtual statement. */
+/* Advance I statement iterator to the next non-virtual GIMPLE_PHI
+ statement. */
static inline void
gsi_next_nonvirtual_phi (gphi_iterator *i)
{
- gphi *phi;
-
- if (gsi_end_p (*i))
- return;
-
- phi = i->phi ();
- gcc_assert (phi != NULL);
-
- while (virtual_operand_p (gimple_phi_result (phi)))
+ do
{
gsi_next (i);
+ }
+ while (!gsi_end_p (*i) && virtual_operand_p (gimple_phi_result (i->phi ())));
+}
- if (gsi_end_p (*i))
- return;
+/* Return a new iterator pointing to the first non-virtual phi statement in
+ basic block BB. */
- phi = i->phi ();
- }
+static inline gphi_iterator
+gsi_start_nonvirtual_phis (basic_block bb)
+{
+ gphi_iterator i = gsi_start_phis (bb);
+
+ if (!gsi_end_p (i) && virtual_operand_p (gimple_phi_result (i.phi ())))
+ gsi_next_nonvirtual_phi (&i);
+
+ return i;
}
/* Return the basic block associated with this iterator. */
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index 5abaa7d18d8..270159b518d 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -159,7 +159,10 @@
#include "gimple-fold.h"
#include "stor-layout.h"
#include "timevar.h"
+#include "cfganal.h"
+#include "cfgcleanup.h"
#include "tree-cfg.h"
+#include "except.h"
#include "tree-eh.h"
#include "target.h"
#include "gimplify-me.h"
@@ -1375,13 +1378,15 @@ public:
/* True if ops have been swapped and thus ops[1] represents
rhs1 of BIT_{AND,IOR,XOR}_EXPR and ops[0] represents rhs2. */
bool ops_swapped_p;
+ /* The index number of the landing pad, or 0 if there is none. */
+ int lp_nr;
/* Operands. For BIT_*_EXPR rhs_code both operands are used, otherwise
just the first one. */
store_operand_info ops[2];
store_immediate_info (unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
gimple *, unsigned int, enum tree_code,
- struct symbolic_number &, gimple *, bool,
+ struct symbolic_number &, gimple *, bool, int,
const store_operand_info &,
const store_operand_info &);
};
@@ -1396,11 +1401,13 @@ store_immediate_info::store_immediate_info (unsigned HOST_WIDE_INT bs,
struct symbolic_number &nr,
gimple *ins_stmtp,
bool bitnotp,
+ int nr2,
const store_operand_info &op0r,
const store_operand_info &op1r)
: bitsize (bs), bitpos (bp), bitregion_start (brs), bitregion_end (bre),
stmt (st), order (ord), rhs_code (rhscode), n (nr),
- ins_stmt (ins_stmtp), bit_not_p (bitnotp), ops_swapped_p (false)
+ ins_stmt (ins_stmtp), bit_not_p (bitnotp), ops_swapped_p (false),
+ lp_nr (nr2)
#if __cplusplus >= 201103L
, ops { op0r, op1r }
{
@@ -1435,6 +1442,7 @@ public:
bool bit_insertion;
bool only_constants;
unsigned int first_nonmergeable_order;
+ int lp_nr;
auto_vec<store_immediate_info *> stores;
/* We record the first and last original statements in the sequence because
@@ -1862,6 +1870,7 @@ merged_store_group::merged_store_group (store_immediate_info *info)
bit_insertion = false;
only_constants = info->rhs_code == INTEGER_CST;
first_nonmergeable_order = ~0U;
+ lp_nr = info->lp_nr;
unsigned HOST_WIDE_INT align_bitpos = 0;
get_object_alignment_1 (gimple_assign_lhs (info->stmt),
&align, &align_bitpos);
@@ -1904,6 +1913,9 @@ merged_store_group::can_be_merged_into (store_immediate_info *info)
if (info->rhs_code == LROTATE_EXPR)
return false;
+ if (info->lp_nr != lp_nr)
+ return false;
+
/* The canonical case. */
if (info->rhs_code == stores[0]->rhs_code)
return true;
@@ -2173,10 +2185,10 @@ private:
decisions when going out of SSA). */
imm_store_chain_info *m_stores_head;
- void process_store (gimple *);
- bool terminate_and_process_all_chains ();
+ bool process_store (gimple *);
+ bool terminate_and_process_chain (imm_store_chain_info *);
bool terminate_all_aliasing_chains (imm_store_chain_info **, gimple *);
- bool terminate_and_release_chain (imm_store_chain_info *);
+ bool terminate_and_process_all_chains ();
}; // class pass_store_merging
/* Terminate and process all recorded chains. Return true if any changes
@@ -2187,16 +2199,14 @@ pass_store_merging::terminate_and_process_all_chains ()
{
bool ret = false;
while (m_stores_head)
- ret |= terminate_and_release_chain (m_stores_head);
+ ret |= terminate_and_process_chain (m_stores_head);
gcc_assert (m_stores.is_empty ());
- gcc_assert (m_stores_head == NULL);
-
return ret;
}
/* Terminate all chains that are affected by the statement STMT.
CHAIN_INFO is the chain we should ignore from the checks if
- non-NULL. */
+ non-NULL. Return true if any changes were made. */
bool
pass_store_merging::terminate_all_aliasing_chains (imm_store_chain_info
@@ -2233,8 +2243,7 @@ pass_store_merging::terminate_all_aliasing_chains (imm_store_chain_info
fprintf (dump_file, "stmt causes chain termination:\n");
print_gimple_stmt (dump_file, stmt, 0);
}
- terminate_and_release_chain (cur);
- ret = true;
+ ret |= terminate_and_process_chain (cur);
break;
}
}
@@ -2248,7 +2257,7 @@ pass_store_merging::terminate_all_aliasing_chains (imm_store_chain_info
entry is removed after the processing in any case. */
bool
-pass_store_merging::terminate_and_release_chain (imm_store_chain_info *chain_info)
+pass_store_merging::terminate_and_process_chain (imm_store_chain_info *chain_info)
{
bool ret = chain_info->terminate_and_process_chain ();
m_stores.remove (chain_info->base_addr);
@@ -2257,9 +2266,9 @@ pass_store_merging::terminate_and_release_chain (imm_store_chain_info *chain_inf
}
/* Return true if stmts in between FIRST (inclusive) and LAST (exclusive)
- may clobber REF. FIRST and LAST must be in the same basic block and
- have non-NULL vdef. We want to be able to sink load of REF across
- stores between FIRST and LAST, up to right before LAST. */
+ may clobber REF. FIRST and LAST must have non-NULL vdef. We want to
+ be able to sink load of REF across stores between FIRST and LAST, up
+ to right before LAST. */
bool
stmts_may_clobber_ref_p (gimple *first, gimple *last, tree ref)
@@ -2270,7 +2279,10 @@ stmts_may_clobber_ref_p (gimple *first, gimple *last, tree ref)
tree vop = gimple_vdef (last);
gimple *stmt;
- gcc_checking_assert (gimple_bb (first) == gimple_bb (last));
+ /* Return true conservatively if the basic blocks are different. */
+ if (gimple_bb (first) != gimple_bb (last))
+ return true;
+
do
{
stmt = SSA_NAME_DEF_STMT (vop);
@@ -2286,6 +2298,7 @@ stmts_may_clobber_ref_p (gimple *first, gimple *last, tree ref)
vop = gimple_vuse (stmt);
}
while (stmt != first);
+
return false;
}
@@ -2759,7 +2772,9 @@ imm_store_chain_info::coalesce_immediate_stores ()
merged_store->start + merged_store->width - 1))
{
/* Only allow overlapping stores of constants. */
- if (info->rhs_code == INTEGER_CST && merged_store->only_constants)
+ if (info->rhs_code == INTEGER_CST
+ && merged_store->only_constants
+ && info->lp_nr == merged_store->lp_nr)
{
unsigned int last_order
= MAX (merged_store->last_order, info->order);
@@ -4152,6 +4167,9 @@ imm_store_chain_info::output_merged_store (merged_store_group *group)
gimple_set_vuse (stmt, new_vuse);
gimple_seq_add_stmt_without_update (&seq, stmt);
+ if (group->lp_nr && stmt_could_throw_p (cfun, stmt))
+ add_stmt_to_eh_lp (stmt, group->lp_nr);
+
tree new_vdef;
if (i < split_stores.length () - 1)
new_vdef = make_ssa_name (gimple_vop (cfun), stmt);
@@ -4175,7 +4193,63 @@ imm_store_chain_info::output_merged_store (merged_store_group *group)
if (dump_flags & TDF_DETAILS)
print_gimple_seq (dump_file, seq, 0, TDF_VOPS | TDF_MEMSYMS);
}
- gsi_insert_seq_after (&last_gsi, seq, GSI_SAME_STMT);
+
+ if (group->lp_nr > 0)
+ {
+ /* We're going to insert a sequence of (potentially) throwing stores
+ into an active EH region. This means that we're going to create
+ new basic blocks with EH edges pointing to the post landing pad
+ and, therefore, to have to update its PHI nodes, if any. For the
+ virtual PHI node, we're going to use the VDEFs created above, but
+ for the other nodes, we need to record the original reaching defs. */
+ eh_landing_pad lp = get_eh_landing_pad_from_number (group->lp_nr);
+ basic_block lp_bb = label_to_block (cfun, lp->post_landing_pad);
+ basic_block last_bb = gimple_bb (group->last_stmt);
+ edge last_edge = find_edge (last_bb, lp_bb);
+ auto_vec<tree, 16> last_defs;
+ gphi_iterator gpi;
+ for (gpi = gsi_start_phis (lp_bb); !gsi_end_p (gpi); gsi_next (&gpi))
+ {
+ gphi *phi = gpi.phi ();
+ tree last_def;
+ if (virtual_operand_p (gimple_phi_result (phi)))
+ last_def = NULL_TREE;
+ else
+ last_def = gimple_phi_arg_def (phi, last_edge->dest_idx);
+ last_defs.safe_push (last_def);
+ }
+
+ /* Do the insertion. Then, if new basic blocks have been created in the
+ process, rewind the chain of VDEFs create above to walk the new basic
+ blocks and update the corresponding arguments of the PHI nodes. */
+ update_modified_stmts (seq);
+ if (gimple_find_sub_bbs (seq, &last_gsi))
+ while (last_vdef != gimple_vuse (group->last_stmt))
+ {
+ gimple *stmt = SSA_NAME_DEF_STMT (last_vdef);
+ if (stmt_could_throw_p (cfun, stmt))
+ {
+ edge new_edge = find_edge (gimple_bb (stmt), lp_bb);
+ unsigned int i;
+ for (gpi = gsi_start_phis (lp_bb), i = 0;
+ !gsi_end_p (gpi);
+ gsi_next (&gpi), i++)
+ {
+ gphi *phi = gpi.phi ();
+ tree new_def;
+ if (virtual_operand_p (gimple_phi_result (phi)))
+ new_def = last_vdef;
+ else
+ new_def = last_defs[i];
+ add_phi_arg (phi, new_def, new_edge, UNKNOWN_LOCATION);
+ }
+ }
+ last_vdef = gimple_vuse (stmt);
+ }
+ }
+ else
+ gsi_insert_seq_after (&last_gsi, seq, GSI_SAME_STMT);
+
for (int j = 0; j < 2; ++j)
if (load_seq[j])
gsi_insert_seq_after (&load_gsi[j], load_seq[j], GSI_SAME_STMT);
@@ -4206,6 +4280,8 @@ imm_store_chain_info::output_merged_stores ()
gimple *stmt = store->stmt;
gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
gsi_remove (&gsi, true);
+ if (store->lp_nr)
+ remove_stmt_from_eh_lp (stmt);
if (stmt != merged_store->last_stmt)
{
unlink_stmt_vdef (stmt);
@@ -4258,14 +4334,22 @@ imm_store_chain_info::terminate_and_process_chain ()
static bool
lhs_valid_for_store_merging_p (tree lhs)
{
- tree_code code = TREE_CODE (lhs);
-
- if (code == ARRAY_REF || code == ARRAY_RANGE_REF || code == MEM_REF
- || code == COMPONENT_REF || code == BIT_FIELD_REF
- || DECL_P (lhs))
+ if (DECL_P (lhs))
return true;
- return false;
+ switch (TREE_CODE (lhs))
+ {
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ case BIT_FIELD_REF:
+ case COMPONENT_REF:
+ case MEM_REF:
+ return true;
+ default:
+ return false;
+ }
+
+ gcc_unreachable ();
}
/* Return true if the tree RHS is a constant we want to consider
@@ -4286,6 +4370,40 @@ rhs_valid_for_store_merging_p (tree rhs)
&& native_encode_expr (rhs, NULL, size) != 0);
}
+/* Adjust *PBITPOS, *PBITREGION_START and *PBITREGION_END by BYTE_OFF bytes
+ and return true on success or false on failure. */
+
+static bool
+adjust_bit_pos (poly_offset_int byte_off,
+ poly_int64 *pbitpos,
+ poly_uint64 *pbitregion_start,
+ poly_uint64 *pbitregion_end)
+{
+ poly_offset_int bit_off = byte_off << LOG2_BITS_PER_UNIT;
+ bit_off += *pbitpos;
+
+ if (known_ge (bit_off, 0) && bit_off.to_shwi (pbitpos))
+ {
+ if (maybe_ne (*pbitregion_end, 0U))
+ {
+ bit_off = byte_off << LOG2_BITS_PER_UNIT;
+ bit_off += *pbitregion_start;
+ if (bit_off.to_uhwi (pbitregion_start))
+ {
+ bit_off = byte_off << LOG2_BITS_PER_UNIT;
+ bit_off += *pbitregion_end;
+ if (!bit_off.to_uhwi (pbitregion_end))
+ *pbitregion_end = 0;
+ }
+ else
+ *pbitregion_end = 0;
+ }
+ return true;
+ }
+ else
+ return false;
+}
+
/* If MEM is a memory reference usable for store merging (either as
store destination or for loads), return the non-NULL base_addr
and set *PBITSIZE, *PBITPOS, *PBITREGION_START and *PBITREGION_END.
@@ -4330,27 +4448,8 @@ mem_valid_for_store_merging (tree mem, poly_uint64 *pbitsize,
PR 23684 and this way we can catch more chains. */
else if (TREE_CODE (base_addr) == MEM_REF)
{
- poly_offset_int byte_off = mem_ref_offset (base_addr);
- poly_offset_int bit_off = byte_off << LOG2_BITS_PER_UNIT;
- bit_off += bitpos;
- if (known_ge (bit_off, 0) && bit_off.to_shwi (&bitpos))
- {
- if (maybe_ne (bitregion_end, 0U))
- {
- bit_off = byte_off << LOG2_BITS_PER_UNIT;
- bit_off += bitregion_start;
- if (bit_off.to_uhwi (&bitregion_start))
- {
- bit_off = byte_off << LOG2_BITS_PER_UNIT;
- bit_off += bitregion_end;
- if (!bit_off.to_uhwi (&bitregion_end))
- bitregion_end = 0;
- }
- else
- bitregion_end = 0;
- }
- }
- else
+ if (!adjust_bit_pos (mem_ref_offset (base_addr), &bitpos,
+ &bitregion_start, &bitregion_end))
return NULL_TREE;
base_addr = TREE_OPERAND (base_addr, 0);
}
@@ -4363,14 +4462,7 @@ mem_valid_for_store_merging (tree mem, poly_uint64 *pbitsize,
base_addr = build_fold_addr_expr (base_addr);
}
- if (known_eq (bitregion_end, 0U))
- {
- bitregion_start = round_down_to_byte_boundary (bitpos);
- bitregion_end = bitpos;
- bitregion_end = round_up_to_byte_boundary (bitregion_end + bitsize);
- }
-
- if (offset != NULL_TREE)
+ if (offset)
{
/* If the access is variable offset then a base decl has to be
address-taken to be able to emit pointer-based stores to it.
@@ -4378,14 +4470,26 @@ mem_valid_for_store_merging (tree mem, poly_uint64 *pbitsize,
base up to the first variable part and then wrapping that inside
a BIT_FIELD_REF. */
tree base = get_base_address (base_addr);
- if (! base
- || (DECL_P (base) && ! TREE_ADDRESSABLE (base)))
+ if (!base || (DECL_P (base) && !TREE_ADDRESSABLE (base)))
return NULL_TREE;
+ /* Similarly to above for the base, remove constant from the offset. */
+ if (TREE_CODE (offset) == PLUS_EXPR
+ && TREE_CODE (TREE_OPERAND (offset, 1)) == INTEGER_CST
+ && adjust_bit_pos (wi::to_poly_offset (TREE_OPERAND (offset, 1)),
+ &bitpos, &bitregion_start, &bitregion_end))
+ offset = TREE_OPERAND (offset, 0);
+
base_addr = build2 (POINTER_PLUS_EXPR, TREE_TYPE (base_addr),
base_addr, offset);
}
+ if (known_eq (bitregion_end, 0U))
+ {
+ bitregion_start = round_down_to_byte_boundary (bitpos);
+ bitregion_end = round_up_to_byte_boundary (bitpos + bitsize);
+ }
+
*pbitsize = bitsize;
*pbitpos = bitpos;
*pbitregion_start = bitregion_start;
@@ -4448,10 +4552,24 @@ handled_load (gimple *stmt, store_operand_info *op,
return false;
}
+/* Return the index number of the landing pad for STMT, if any. */
+
+static int
+lp_nr_for_store (gimple *stmt)
+{
+ if (!cfun->can_throw_non_call_exceptions || !cfun->eh)
+ return 0;
+
+ if (!stmt_could_throw_p (cfun, stmt))
+ return 0;
+
+ return lookup_stmt_eh_lp (stmt);
+}
+
/* Record the store STMT for store merging optimization if it can be
- optimized. */
+ optimized. Return true if any changes were made. */
-void
+bool
pass_store_merging::process_store (gimple *stmt)
{
tree lhs = gimple_assign_lhs (stmt);
@@ -4462,7 +4580,7 @@ pass_store_merging::process_store (gimple *stmt)
= mem_valid_for_store_merging (lhs, &bitsize, &bitpos,
&bitregion_start, &bitregion_end);
if (known_eq (bitsize, 0U))
- return;
+ return false;
bool invalid = (base_addr == NULL_TREE
|| (maybe_gt (bitsize,
@@ -4604,15 +4722,13 @@ pass_store_merging::process_store (gimple *stmt)
|| !bitpos.is_constant (&const_bitpos)
|| !bitregion_start.is_constant (&const_bitregion_start)
|| !bitregion_end.is_constant (&const_bitregion_end))
- {
- terminate_all_aliasing_chains (NULL, stmt);
- return;
- }
+ return terminate_all_aliasing_chains (NULL, stmt);
if (!ins_stmt)
memset (&n, 0, sizeof (n));
class imm_store_chain_info **chain_info = NULL;
+ bool ret = false;
if (base_addr)
chain_info = m_stores.get (base_addr);
@@ -4624,14 +4740,15 @@ pass_store_merging::process_store (gimple *stmt)
const_bitregion_start,
const_bitregion_end,
stmt, ord, rhs_code, n, ins_stmt,
- bit_not_p, ops[0], ops[1]);
+ bit_not_p, lp_nr_for_store (stmt),
+ ops[0], ops[1]);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Recording immediate store from stmt:\n");
print_gimple_stmt (dump_file, stmt, 0);
}
(*chain_info)->m_store_info.safe_push (info);
- terminate_all_aliasing_chains (chain_info, stmt);
+ ret |= terminate_all_aliasing_chains (chain_info, stmt);
/* If we reach the limit of stores to merge in a chain terminate and
process the chain now. */
if ((*chain_info)->m_store_info.length ()
@@ -4640,13 +4757,13 @@ pass_store_merging::process_store (gimple *stmt)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
"Reached maximum number of statements to merge:\n");
- terminate_and_release_chain (*chain_info);
+ ret |= terminate_and_process_chain (*chain_info);
}
- return;
+ return ret;
}
/* Store aliases any existing chain? */
- terminate_all_aliasing_chains (NULL, stmt);
+ ret |= terminate_all_aliasing_chains (NULL, stmt);
/* Start a new chain. */
class imm_store_chain_info *new_chain
= new imm_store_chain_info (m_stores_head, base_addr);
@@ -4654,7 +4771,8 @@ pass_store_merging::process_store (gimple *stmt)
const_bitregion_start,
const_bitregion_end,
stmt, 0, rhs_code, n, ins_stmt,
- bit_not_p, ops[0], ops[1]);
+ bit_not_p, lp_nr_for_store (stmt),
+ ops[0], ops[1]);
new_chain->m_store_info.safe_push (info);
m_stores.put (base_addr, new_chain);
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -4665,6 +4783,52 @@ pass_store_merging::process_store (gimple *stmt)
print_generic_expr (dump_file, base_addr);
fprintf (dump_file, "\n");
}
+ return ret;
+}
+
+/* Return true if STMT is a store valid for store merging. */
+
+static bool
+store_valid_for_store_merging_p (gimple *stmt)
+{
+ return gimple_assign_single_p (stmt)
+ && gimple_vdef (stmt)
+ && lhs_valid_for_store_merging_p (gimple_assign_lhs (stmt))
+ && !gimple_has_volatile_ops (stmt);
+}
+
+enum basic_block_status { BB_INVALID, BB_VALID, BB_EXTENDED_VALID };
+
+/* Return the status of basic block BB wrt store merging. */
+
+static enum basic_block_status
+get_status_for_store_merging (basic_block bb)
+{
+ unsigned int num_statements = 0;
+ gimple_stmt_iterator gsi;
+ edge e;
+
+ for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+
+ if (is_gimple_debug (stmt))
+ continue;
+
+ if (store_valid_for_store_merging_p (stmt) && ++num_statements >= 2)
+ break;
+ }
+
+ if (num_statements == 0)
+ return BB_INVALID;
+
+ if (cfun->can_throw_non_call_exceptions && cfun->eh
+ && store_valid_for_store_merging_p (gimple_seq_last_stmt (bb_seq (bb)))
+ && (e = find_fallthru_edge (bb->succs))
+ && e->dest == bb->next_bb)
+ return BB_EXTENDED_VALID;
+
+ return num_statements >= 2 ? BB_VALID : BB_INVALID;
}
/* Entry point for the pass. Go over each basic block recording chains of
@@ -4677,26 +4841,28 @@ pass_store_merging::execute (function *fun)
{
basic_block bb;
hash_set<gimple *> orig_stmts;
+ bool changed = false, open_chains = false;
+
+ /* If the function can throw and catch non-call exceptions, we'll be trying
+ to merge stores across different basic blocks so we need to first unsplit
+ the EH edges in order to streamline the CFG of the function. */
+ if (cfun->can_throw_non_call_exceptions && cfun->eh)
+ unsplit_eh_edges ();
calculate_dominance_info (CDI_DOMINATORS);
FOR_EACH_BB_FN (bb, fun)
{
+ const basic_block_status bb_status = get_status_for_store_merging (bb);
gimple_stmt_iterator gsi;
- unsigned HOST_WIDE_INT num_statements = 0;
- /* Record the original statements so that we can keep track of
- statements emitted in this pass and not re-process new
- statements. */
- for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- if (is_gimple_debug (gsi_stmt (gsi)))
- continue;
- if (++num_statements >= 2)
- break;
+ if (open_chains && (bb_status == BB_INVALID || !single_pred_p (bb)))
+ {
+ changed |= terminate_and_process_all_chains ();
+ open_chains = false;
}
- if (num_statements < 2)
+ if (bb_status == BB_INVALID)
continue;
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -4715,19 +4881,37 @@ pass_store_merging::execute (function *fun)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Volatile access terminates "
"all chains\n");
- terminate_and_process_all_chains ();
+ changed |= terminate_and_process_all_chains ();
+ open_chains = false;
continue;
}
- if (gimple_assign_single_p (stmt) && gimple_vdef (stmt)
- && !stmt_can_throw_internal (cfun, stmt)
- && lhs_valid_for_store_merging_p (gimple_assign_lhs (stmt)))
- process_store (stmt);
+ if (store_valid_for_store_merging_p (stmt))
+ changed |= process_store (stmt);
else
- terminate_all_aliasing_chains (NULL, stmt);
+ changed |= terminate_all_aliasing_chains (NULL, stmt);
+ }
+
+ if (bb_status == BB_EXTENDED_VALID)
+ open_chains = true;
+ else
+ {
+ changed |= terminate_and_process_all_chains ();
+ open_chains = false;
}
- terminate_and_process_all_chains ();
}
+
+ if (open_chains)
+ changed |= terminate_and_process_all_chains ();
+
+ /* If the function can throw and catch non-call exceptions and something
+ changed during the pass, then the CFG has (very likely) changed too. */
+ if (cfun->can_throw_non_call_exceptions && cfun->eh && changed)
+ {
+ free_dominance_info (CDI_DOMINATORS);
+ return TODO_cleanup_cfg;
+ }
+
return 0;
}
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 8e828a5f169..a874c29454c 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -2149,10 +2149,22 @@ gimple_could_trap_p_1 (gimple *s, bool include_mem, bool include_stores)
return false;
case GIMPLE_ASSIGN:
- t = gimple_expr_type (s);
op = gimple_assign_rhs_code (s);
+
+ /* For COND_EXPR and VEC_COND_EXPR only the condition may trap. */
+ if (op == COND_EXPR || op == VEC_COND_EXPR)
+ return tree_could_trap_p (gimple_assign_rhs1 (s));
+
+ /* For comparisons we need to check rhs operand types instead of rhs type
+ (which is BOOLEAN_TYPE). */
+ if (TREE_CODE_CLASS (op) == tcc_comparison)
+ t = TREE_TYPE (gimple_assign_rhs1 (s));
+ else
+ t = gimple_expr_type (s);
+
if (get_gimple_rhs_class (op) == GIMPLE_BINARY_RHS)
div = gimple_assign_rhs2 (s);
+
return (operation_could_trap_p (op, FLOAT_TYPE_P (t),
(INTEGRAL_TYPE_P (t)
&& TYPE_OVERFLOW_TRAPS (t)),
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 88d6571976f..836706961f3 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4142,8 +4142,8 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
/* Now do the normal gimplification. */
/* Gimplify condition. */
- ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL, is_gimple_condexpr,
- fb_rvalue);
+ ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
+ is_gimple_condexpr_for_cond, fb_rvalue);
if (ret == GS_ERROR)
return GS_ERROR;
gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
@@ -12976,6 +12976,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
else if (gimple_test_f == is_gimple_val
|| gimple_test_f == is_gimple_call_addr
|| gimple_test_f == is_gimple_condexpr
+ || gimple_test_f == is_gimple_condexpr_for_cond
|| gimple_test_f == is_gimple_mem_rhs
|| gimple_test_f == is_gimple_mem_rhs_or_call
|| gimple_test_f == is_gimple_reg_rhs
diff --git a/gcc/ginclude/stdint-gcc.h b/gcc/ginclude/stdint-gcc.h
index 83b03b26ee6..e9dc04e71e4 100644
--- a/gcc/ginclude/stdint-gcc.h
+++ b/gcc/ginclude/stdint-gcc.h
@@ -260,8 +260,9 @@ typedef __UINTMAX_TYPE__ uintmax_t;
#endif /* (!defined __cplusplus || __cplusplus >= 201103L
|| defined __STDC_CONSTANT_MACROS) */
-#ifdef __STDC_WANT_IEC_60559_BFP_EXT__
-/* TS 18661-1 widths of integer types. */
+#if (defined __STDC_WANT_IEC_60559_BFP_EXT__ \
+ || (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L))
+/* TS 18661-1 / C2X widths of integer types. */
#ifdef __INT8_TYPE__
# undef INT8_WIDTH
diff --git a/gcc/glimits.h b/gcc/glimits.h
index 0cddf0f9dcc..1909344293d 100644
--- a/gcc/glimits.h
+++ b/gcc/glimits.h
@@ -123,8 +123,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
# define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1ULL)
#endif
-#ifdef __STDC_WANT_IEC_60559_BFP_EXT__
-/* TS 18661-1 widths of integer types. */
+#if (defined __STDC_WANT_IEC_60559_BFP_EXT__ \
+ || (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L))
+/* TS 18661-1 / C2X widths of integer types. */
# undef CHAR_WIDTH
# define CHAR_WIDTH __SCHAR_WIDTH__
# undef SCHAR_WIDTH
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index f7c45eeb0d3..1508eb16650 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-07faafda5fbd66a710153814f30d93c91461e7cb
+ddfb845fad1f2e8b84383f262ed5ea5be7b3e35a
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/ast-dump.cc b/gcc/go/gofrontend/ast-dump.cc
index b20f7e4e725..a3cbda9debc 100644
--- a/gcc/go/gofrontend/ast-dump.cc
+++ b/gcc/go/gofrontend/ast-dump.cc
@@ -135,11 +135,11 @@ Ast_dump_traverse_blocks_and_functions::function(Named_object* no)
{
if (it != res->begin())
this->ast_dump_context_->ostream() << ",";
- Named_object* no = (*it);
+ Named_object* rno = (*it);
- this->ast_dump_context_->ostream() << no->name() << " ";
- go_assert(no->is_result_variable());
- Result_variable* resvar = no->result_var_value();
+ this->ast_dump_context_->ostream() << rno->name() << " ";
+ go_assert(rno->is_result_variable());
+ Result_variable* resvar = rno->result_var_value();
this->ast_dump_context_->dump_type(resvar->type());
diff --git a/gcc/go/gofrontend/escape.cc b/gcc/go/gofrontend/escape.cc
index bfd1a39d7e4..f8e07f73cd2 100644
--- a/gcc/go/gofrontend/escape.cc
+++ b/gcc/go/gofrontend/escape.cc
@@ -1541,7 +1541,6 @@ Escape_analysis_assign::expression(Expression** pexpr)
if (debug_level > 1)
{
- Node* n = Node::make_node(*pexpr);
std::string fn_name = this->context_->current_function_name();
go_debug((*pexpr)->location(), "[%d] %s esc: %s",
this->context_->loop_depth(), fn_name.c_str(),
diff --git a/gcc/go/gofrontend/export.cc b/gcc/go/gofrontend/export.cc
index 32ab4982091..5aaa207ff5f 100644
--- a/gcc/go/gofrontend/export.cc
+++ b/gcc/go/gofrontend/export.cc
@@ -249,6 +249,14 @@ Collect_export_references::expression(Expression** pexpr)
return TRAVERSE_CONTINUE;
}
+ const Named_object* nco = expr->named_constant();
+ if (nco != 0 && nco->package() == NULL)
+ {
+ const Named_constant *nc = nco->const_value();
+ Type::traverse(nc->type(), this);
+ return TRAVERSE_CONTINUE;
+ }
+
return TRAVERSE_CONTINUE;
}
@@ -322,6 +330,10 @@ Collect_export_references::type(Type* type)
if (type->is_void_type())
return TRAVERSE_SKIP_COMPONENTS;
+ // Skip the nil type, turns up in function bodies.
+ if (type->is_nil_type())
+ return TRAVERSE_SKIP_COMPONENTS;
+
// Skip abstract types. We should never see these in real code,
// only in things like const declarations.
if (type->is_abstract())
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index a72ba243f37..b614921cf39 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -3234,6 +3234,10 @@ class Const_expression : public Expression
named_object()
{ return this->constant_; }
+ const Named_object*
+ named_object() const
+ { return this->constant_; }
+
// Check that the initializer does not refer to the constant itself.
void
check_for_init_loop();
@@ -4104,9 +4108,11 @@ Type_conversion_expression::do_get_backend(Translate_context* context)
x = mpz_get_ui(intval);
else
{
- char* s = mpz_get_str(NULL, 16, intval);
+ char* ms = mpz_get_str(NULL, 16, intval);
go_warning_at(loc, 0,
- "unicode code point 0x%s out of range in string", s);
+ "unicode code point 0x%s out of range in string",
+ ms);
+ free(ms);
x = 0xfffd;
}
Lex::append_char(x, true, &s, loc);
@@ -8016,14 +8022,14 @@ Bound_method_expression::do_flatten(Gogo* gogo, Named_object*,
Expression* ret = Expression::make_struct_composite_literal(st, vals, loc);
ret = Expression::make_heap_expression(ret, loc);
- Node* n = Node::make_node(this);
- if ((n->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
+ Node* node = Node::make_node(this);
+ if ((node->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
ret->heap_expression()->set_allocate_on_stack();
else if (gogo->compiling_runtime()
&& gogo->package_name() == "runtime"
&& !saw_errors())
go_error_at(loc, "%s escapes to heap, not allowed in runtime",
- n->ast_format(gogo).c_str());
+ node->ast_format(gogo).c_str());
// If necessary, check whether the expression or any embedded
// pointers are nil.
@@ -8741,8 +8747,6 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter)
Expression::make_nil(loc));
else
{
- Numeric_constant nclen;
- unsigned long vlen;
if (len_arg->numeric_constant_value(&nclen)
&& nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID
&& vlen <= Map_type::bucket_size)
@@ -9053,8 +9057,7 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
else
{
Type* int32_type = Type::lookup_integer_type("int32");
- Expression* zero =
- Expression::make_integer_ul(0, int32_type, loc);
+ zero = Expression::make_integer_ul(0, int32_type, loc);
call = Runtime::make_call(Runtime::BUILTIN_MEMSET, loc, 3, a1,
zero, a2);
}
@@ -9064,15 +9067,12 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
// For a slice containing pointers, growslice already zeroed
// the memory. We only need to zero in non-growing case.
// Note: growslice does not zero the memory in non-pointer case.
- Expression* left =
- Expression::make_temporary_reference(ntmp, loc);
- left = Expression::make_cast(uint_type, left, loc);
- Expression* right =
- Expression::make_temporary_reference(c1tmp, loc);
- right = Expression::make_cast(uint_type, right, loc);
- Expression* cond =
- Expression::make_binary(OPERATOR_GT, left, right, loc);
- Expression* zero = Expression::make_integer_ul(0, int_type, loc);
+ ref = Expression::make_temporary_reference(ntmp, loc);
+ ref = Expression::make_cast(uint_type, ref, loc);
+ ref2 = Expression::make_temporary_reference(c1tmp, loc);
+ ref2 = Expression::make_cast(uint_type, ref2, loc);
+ cond = Expression::make_binary(OPERATOR_GT, ref, ref2, loc);
+ zero = Expression::make_integer_ul(0, int_type, loc);
call = Expression::make_conditional(cond, call, zero, loc);
}
}
@@ -10877,9 +10877,7 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
if (this->result_count() > 1 && this->call_temp_ == NULL)
{
Struct_field_list* sfl = new Struct_field_list();
- Function_type* fntype = this->get_function_type();
const Typed_identifier_list* results = fntype->results();
- Location loc = this->location();
int i = 0;
char buf[20];
@@ -12295,10 +12293,10 @@ Call_expression::do_get_backend(Translate_context* context)
}
else
{
- Expression* first_arg;
- fn = this->interface_method_function(interface_method, &first_arg,
+ Expression* arg0;
+ fn = this->interface_method_function(interface_method, &arg0,
location);
- fn_args[0] = first_arg->get_backend(context);
+ fn_args[0] = arg0->get_backend(context);
}
Bexpression* bclosure = NULL;
@@ -16453,11 +16451,11 @@ Composite_literal_expression::lower_array(Type* type)
traverse_order = new std::vector<unsigned long>();
traverse_order->reserve(v.size());
- for (V::const_iterator p = v.begin(); p != v.end(); ++p)
+ for (V::const_iterator pv = v.begin(); pv != v.end(); ++pv)
{
- indexes->push_back(p->index);
- vals->push_back(p->expr);
- traverse_order->push_back(p->traversal_order);
+ indexes->push_back(pv->index);
+ vals->push_back(pv->expr);
+ traverse_order->push_back(pv->traversal_order);
}
}
@@ -16788,6 +16786,15 @@ Expression::is_local_variable() const
|| (no->is_variable() && !no->var_value()->is_global()));
}
+const Named_object*
+Expression::named_constant() const
+{
+ if (this->classification() != EXPRESSION_CONST_REFERENCE)
+ return NULL;
+ const Const_expression* ce = static_cast<const Const_expression*>(this);
+ return ce->named_object();
+}
+
// Class Type_guard_expression.
// Traversal.
@@ -17771,9 +17778,9 @@ Interface_info_expression::do_type()
Interface_type* itype = this->iface_->type()->interface_type();
- Hashtable::const_iterator p = result_types.find(itype);
- if (p != result_types.end())
- return p->second;
+ Hashtable::const_iterator pr = result_types.find(itype);
+ if (pr != result_types.end())
+ return pr->second;
Type* pdt = Type::make_type_descriptor_ptr_type();
if (itype->is_empty())
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 2e3d1e0ccf6..a0370e1ac9b 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -587,6 +587,11 @@ class Expression
boolean_constant_value(bool* val) const
{ return this->do_boolean_constant_value(val); }
+ // If this is a const reference expression, return the named
+ // object to which the expression refers, otherwise return NULL.
+ const Named_object*
+ named_constant() const;
+
// This is called if the value of this expression is being
// discarded. This issues warnings about computed values being
// unused. This returns true if all is well, false if it issued an
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index e7af673c8df..a79cfc3a9a7 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -518,11 +518,11 @@ Gogo::import_package(const std::string& filename,
else if (ln == ".")
{
Bindings* bindings = package->bindings();
- for (Bindings::const_declarations_iterator p =
+ for (Bindings::const_declarations_iterator pd =
bindings->begin_declarations();
- p != bindings->end_declarations();
- ++p)
- this->add_dot_import_object(p->second);
+ pd != bindings->end_declarations();
+ ++pd)
+ this->add_dot_import_object(pd->second);
std::string dot_alias = "." + package->package_name();
package->add_alias(dot_alias, location);
}
@@ -678,8 +678,8 @@ Gogo::recompute_init_priorities()
pci != ii->precursors().end();
++pci)
{
- Import_init* ii = this->lookup_init(*pci);
- nonroots.insert(ii);
+ Import_init* ii_init = this->lookup_init(*pci);
+ nonroots.insert(ii_init);
}
}
@@ -2613,11 +2613,11 @@ Gogo::define_global_names()
{
if (no->type_declaration_value()->has_methods())
{
- for (std::vector<Named_object*>::const_iterator p =
+ for (std::vector<Named_object*>::const_iterator pm =
no->type_declaration_value()->methods()->begin();
- p != no->type_declaration_value()->methods()->end();
- p++)
- go_error_at((*p)->location(),
+ pm != no->type_declaration_value()->methods()->end();
+ pm++)
+ go_error_at((*pm)->location(),
"may not define methods on non-local type");
}
no->set_type_value(global_no->type_value());
@@ -6550,8 +6550,8 @@ Function::build(Gogo* gogo, Named_object* named_function)
// Build the backend representation for all the statements in the
// function.
- Translate_context context(gogo, named_function, NULL, NULL);
- Bblock* code_block = this->block_->get_backend(&context);
+ Translate_context bcontext(gogo, named_function, NULL, NULL);
+ Bblock* code_block = this->block_->get_backend(&bcontext);
// Initialize variables if necessary.
Translate_context icontext(gogo, named_function, this->block_,
@@ -6608,8 +6608,8 @@ Function::build(Gogo* gogo, Named_object* named_function)
// If we created a descriptor for the function, make sure we emit it.
if (this->descriptor_ != NULL)
{
- Translate_context context(gogo, NULL, NULL, NULL);
- this->descriptor_->get_backend(&context);
+ Translate_context dcontext(gogo, NULL, NULL, NULL);
+ this->descriptor_->get_backend(&dcontext);
}
}
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index 52371b2b032..e50af616421 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -836,7 +836,7 @@ Parse::parameter_list(bool* is_varargs)
{
std::string name = token->identifier();
bool is_exported = token->is_identifier_exported();
- Location location = token->location();
+ Location id_location = token->location();
token = this->advance_token();
if (!token->is_op(OPERATOR_COMMA))
{
@@ -861,7 +861,7 @@ Parse::parameter_list(bool* is_varargs)
}
this->unget_token(Token::make_identifier_token(name, is_exported,
- location));
+ id_location));
}
else
{
@@ -872,15 +872,15 @@ Parse::parameter_list(bool* is_varargs)
// commas as we can.
std::string id_name = this->gogo_->pack_hidden_name(name,
is_exported);
- ret->push_back(Typed_identifier(id_name, NULL, location));
+ ret->push_back(Typed_identifier(id_name, NULL, id_location));
bool just_saw_comma = true;
while (this->advance_token()->is_identifier())
{
name = this->peek_token()->identifier();
is_exported = this->peek_token()->is_identifier_exported();
- location = this->peek_token()->location();
+ id_location = this->peek_token()->location();
id_name = this->gogo_->pack_hidden_name(name, is_exported);
- ret->push_back(Typed_identifier(id_name, NULL, location));
+ ret->push_back(Typed_identifier(id_name, NULL, id_location));
if (!this->advance_token()->is_op(OPERATOR_COMMA))
{
just_saw_comma = false;
@@ -909,7 +909,7 @@ Parse::parameter_list(bool* is_varargs)
// names.
parameters_have_names = false;
this->unget_token(Token::make_identifier_token(name, is_exported,
- location));
+ id_location));
ret->pop_back();
just_saw_comma = true;
}
@@ -2808,7 +2808,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
{
std::string identifier = token->identifier();
bool is_exported = token->is_identifier_exported();
- Location location = token->location();
+ Location id_location = token->location();
if (this->advance_token()->is_op(OPERATOR_COLON))
{
@@ -2820,14 +2820,14 @@ Parse::composite_lit(Type* type, int depth, Location location)
Gogo* gogo = this->gogo_;
val = this->id_to_expression(gogo->pack_hidden_name(identifier,
is_exported),
- location, false);
+ id_location, false);
is_name = true;
}
else
{
this->unget_token(Token::make_identifier_token(identifier,
is_exported,
- location));
+ id_location));
val = this->expression(PRECEDENCE_NORMAL, false, true, NULL,
NULL);
}
@@ -2923,14 +2923,14 @@ Parse::composite_lit(Type* type, int depth, Location location)
go_error_at(this->location(), "expected %<,%> or %<}%>");
this->gogo_->mark_locals_used();
- int depth = 0;
+ int edepth = 0;
while (!token->is_eof()
- && (depth > 0 || !token->is_op(OPERATOR_RCURLY)))
+ && (edepth > 0 || !token->is_op(OPERATOR_RCURLY)))
{
if (token->is_op(OPERATOR_LCURLY))
- ++depth;
+ ++edepth;
else if (token->is_op(OPERATOR_RCURLY))
- --depth;
+ --edepth;
token = this->advance_token();
}
if (token->is_op(OPERATOR_RCURLY))
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index 3dc394ab32b..f52b33d665c 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -2938,7 +2938,7 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name)
go_assert(call_statement->classification() == STATEMENT_EXPRESSION);
Expression_statement* es =
static_cast<Expression_statement*>(call_statement);
- Call_expression* ce = es->expr()->call_expression();
+ ce = es->expr()->call_expression();
if (ce == NULL)
go_assert(saw_errors());
else
@@ -5972,10 +5972,11 @@ Select_statement::lower_two_case(Block* b)
// if selectnbrecv2(&lhs, &ok, chan) { body } else { default body }
Type* booltype = Type::make_boolean_type();
- Temporary_statement* ts = Statement::make_temporary(booltype, NULL, loc);
- b->add_statement(ts);
+ Temporary_statement* okts = Statement::make_temporary(booltype, NULL,
+ loc);
+ b->add_statement(okts);
- okref = Expression::make_temporary_reference(ts, loc);
+ okref = Expression::make_temporary_reference(okts, loc);
Expression* okaddr = Expression::make_unary(OPERATOR_AND, okref, loc);
call = Runtime::make_call(Runtime::SELECTNBRECV2, loc, 3, addr, okaddr,
chanref);
@@ -6595,7 +6596,7 @@ For_range_statement::lower_range_array(Gogo* gogo,
iter_init = new Block(body_block, loc);
ref = Expression::make_temporary_reference(range_temp, loc);
- Expression* ref2 = Expression::make_temporary_reference(index_temp, loc);
+ ref2 = Expression::make_temporary_reference(index_temp, loc);
Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
tref = Expression::make_temporary_reference(value_temp, loc);
@@ -6693,7 +6694,7 @@ For_range_statement::lower_range_slice(Gogo* gogo,
iter_init = new Block(body_block, loc);
ref = Expression::make_temporary_reference(for_temp, loc);
- Expression* ref2 = Expression::make_temporary_reference(index_temp, loc);
+ ref2 = Expression::make_temporary_reference(index_temp, loc);
Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
tref = Expression::make_temporary_reference(value_temp, loc);
@@ -7179,9 +7180,9 @@ For_range_statement::lower_array_range_clear(Gogo* gogo,
else
{
Type* int32_type = Type::lookup_integer_type("int32");
- Expression* zero = Expression::make_integer_ul(0, int32_type, loc);
+ Expression* zero32 = Expression::make_integer_ul(0, int32_type, loc);
call = Runtime::make_call(Runtime::BUILTIN_MEMSET, loc, 3, ptr_arg,
- zero, sz_arg);
+ zero32, sz_arg);
}
Statement* cs3 = Statement::make_statement(call, true);
b->add_statement(cs3);
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index eeae9fa4c0e..e02b832df14 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -6410,12 +6410,11 @@ Struct_type::do_type_descriptor(Gogo* gogo, Named_type* name)
fvals->push_back(Expression::make_nil(bloc));
else
{
- std::string n;
if (is_embedded_builtin)
n = gogo->package_name();
else
n = Gogo::hidden_name_pkgpath(pf->field_name());
- Expression* s = Expression::make_string(n, bloc);
+ s = Expression::make_string(n, bloc);
fvals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
}
@@ -6429,7 +6428,7 @@ Struct_type::do_type_descriptor(Gogo* gogo, Named_type* name)
fvals->push_back(Expression::make_nil(bloc));
else
{
- Expression* s = Expression::make_string(pf->tag(), bloc);
+ s = Expression::make_string(pf->tag(), bloc);
fvals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
}
@@ -6635,22 +6634,22 @@ Struct_type::do_reflection(Gogo* gogo, std::string* ret) const
{
const std::string& tag(p->tag());
ret->append(" \"");
- for (std::string::const_iterator p = tag.begin();
- p != tag.end();
- ++p)
+ for (std::string::const_iterator pt = tag.begin();
+ pt != tag.end();
+ ++pt)
{
- if (*p == '\0')
+ if (*pt == '\0')
ret->append("\\x00");
- else if (*p == '\n')
+ else if (*pt == '\n')
ret->append("\\n");
- else if (*p == '\t')
+ else if (*pt == '\t')
ret->append("\\t");
- else if (*p == '"')
+ else if (*pt == '"')
ret->append("\\\"");
- else if (*p == '\\')
+ else if (*pt == '\\')
ret->append("\\\\");
else
- ret->push_back(*p);
+ ret->push_back(*pt);
}
ret->push_back('"');
}
@@ -7197,11 +7196,11 @@ Array_type::verify_length()
return false;
case Numeric_constant::NC_UL_BIG:
{
- mpz_t val;
- if (!nc.to_int(&val))
+ mpz_t mval;
+ if (!nc.to_int(&mval))
go_unreachable();
- unsigned int bits = mpz_sizeinbase(val, 2);
- mpz_clear(val);
+ unsigned int bits = mpz_sizeinbase(mval, 2);
+ mpz_clear(mval);
if (bits >= tbits)
{
go_error_at(this->length_->location(), "array bound overflows");
@@ -7704,6 +7703,7 @@ Array_type::do_export(Export* exp) const
}
char* s = mpz_get_str(NULL, 10, val);
exp->write_string(s);
+ free(s);
exp->write_string(" ");
mpz_clear(val);
}
@@ -9752,7 +9752,7 @@ Interface_type::do_import(Import* imp)
parameters = new Typed_identifier_list;
while (true)
{
- std::string name = imp->read_name();
+ std::string pname = imp->read_name();
imp->require_c_string(" ");
if (imp->match_c_string("..."))
@@ -9764,7 +9764,7 @@ Interface_type::do_import(Import* imp)
Type* ptype = imp->read_type();
if (is_varargs)
ptype = Type::make_array_type(ptype, NULL);
- parameters->push_back(Typed_identifier(name, ptype,
+ parameters->push_back(Typed_identifier(pname, ptype,
imp->location()));
if (imp->peek_char() != ',')
break;
@@ -9791,10 +9791,10 @@ Interface_type::do_import(Import* imp)
imp->advance(1);
while (true)
{
- std::string name = imp->read_name();
+ std::string rname = imp->read_name();
imp->require_c_string(" ");
Type* rtype = imp->read_type();
- results->push_back(Typed_identifier(name, rtype,
+ results->push_back(Typed_identifier(rname, rtype,
imp->location()));
if (imp->peek_char() != ',')
break;
diff --git a/gcc/hash-map.h b/gcc/hash-map.h
index ba20fe79f23..73ce6a1dc66 100644
--- a/gcc/hash-map.h
+++ b/gcc/hash-map.h
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
removed. Objects of hash_map type are copy-constructible but not
assignable. */
+const size_t default_hash_map_size = 13;
template<typename KeyId, typename Value,
typename Traits /* = simple_hashmap_traits<default_hash_traits<Key>,
Value> */>
@@ -129,7 +130,7 @@ class GTY((user)) hash_map
};
public:
- explicit hash_map (size_t n = 13, bool ggc = false,
+ explicit hash_map (size_t n = default_hash_map_size, bool ggc = false,
bool sanitize_eq_and_hash = true,
bool gather_mem_stats = GATHER_STATISTICS
CXX_MEM_STAT_INFO)
@@ -146,7 +147,7 @@ public:
HASH_MAP_ORIGIN PASS_MEM_STAT) {}
/* Create a hash_map in ggc memory. */
- static hash_map *create_ggc (size_t size,
+ static hash_map *create_ggc (size_t size = default_hash_map_size,
bool gather_mem_stats = GATHER_STATISTICS
CXX_MEM_STAT_INFO)
{
@@ -326,4 +327,46 @@ gt_pch_nx (hash_map<K, V, H> *h, gt_pointer_operator op, void *cookie)
op (&h->m_table.m_entries, cookie);
}
+enum hm_alloc { hm_heap = false, hm_ggc = true };
+template<bool ggc, typename K, typename V, typename H>
+inline hash_map<K,V,H> *
+hash_map_maybe_create (hash_map<K,V,H> *&h,
+ size_t size = default_hash_map_size)
+{
+ if (!h)
+ {
+ if (ggc)
+ h = hash_map<K,V,H>::create_ggc (size);
+ else
+ h = new hash_map<K,V,H> (size);
+ }
+ return h;
+}
+
+/* Like h->get, but handles null h. */
+template<typename K, typename V, typename H>
+inline V*
+hash_map_safe_get (hash_map<K,V,H> *h, const K& k)
+{
+ return h ? h->get (k) : NULL;
+}
+
+/* Like h->get, but handles null h. */
+template<bool ggc, typename K, typename V, typename H>
+inline V&
+hash_map_safe_get_or_insert (hash_map<K,V,H> *&h, const K& k, bool *e = NULL,
+ size_t size = default_hash_map_size)
+{
+ return hash_map_maybe_create<ggc> (h, size)->get_or_insert (k, e);
+}
+
+/* Like h->put, but handles null h. */
+template<bool ggc, typename K, typename V, typename H>
+inline bool
+hash_map_safe_put (hash_map<K,V,H> *&h, const K& k, const V& v,
+ size_t size = default_hash_map_size)
+{
+ return hash_map_maybe_create<ggc> (h, size)->put (k, v);
+}
+
#endif
diff --git a/gcc/hash-table.c b/gcc/hash-table.c
index e3b5d3da09e..3520c3bb596 100644
--- a/gcc/hash-table.c
+++ b/gcc/hash-table.c
@@ -78,7 +78,7 @@ struct prime_ent const prime_tab[] = {
unsigned int hash_table_sanitize_eq_limit;
/* The following function returns an index into the above table of the
- nearest prime number which is greater than N, and near a power of two. */
+ nearest prime number which is at least N, and near a power of two. */
unsigned int
hash_table_higher_prime_index (unsigned long n)
diff --git a/gcc/hash-table.h b/gcc/hash-table.h
index 0e95f5b4042..ba5d64fb7a3 100644
--- a/gcc/hash-table.h
+++ b/gcc/hash-table.h
@@ -842,9 +842,8 @@ hash_table<Descriptor, Lazy, Allocator>::empty_slow ()
size_t size = m_size;
size_t nsize = size;
value_type *entries = m_entries;
- int i;
- for (i = size - 1; i >= 0; i--)
+ for (size_t i = size - 1; i < size; i--)
if (!is_empty (entries[i]) && !is_deleted (entries[i]))
Descriptor::remove (entries[i]);
@@ -856,8 +855,9 @@ hash_table<Descriptor, Lazy, Allocator>::empty_slow ()
if (nsize != size)
{
- int nindex = hash_table_higher_prime_index (nsize);
- int nsize = prime_tab[nindex].prime;
+ unsigned int nindex = hash_table_higher_prime_index (nsize);
+
+ nsize = prime_tab[nindex].prime;
if (!m_ggc)
Allocator <value_type> ::data_free (m_entries);
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index e0c9522057a..8bc6f53cb38 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -3358,6 +3358,16 @@ bb_ok_for_noce_convert_multiple_sets (basic_block test_bb)
return count > 1 && count <= param;
}
+/* Compute average of two given costs weighted by relative probabilities
+ of respective basic blocks in an IF-THEN-ELSE. E is the IF-THEN edge.
+ With P as the probability to take the IF-THEN branch, return
+ P * THEN_COST + (1 - P) * ELSE_COST. */
+static unsigned
+average_cost (unsigned then_cost, unsigned else_cost, edge e)
+{
+ return else_cost + e->probability.apply ((signed) (then_cost - else_cost));
+}
+
/* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
it without using conditional execution. Return TRUE if we were successful
at converting the block. */
@@ -3413,10 +3423,9 @@ noce_process_if_block (struct noce_if_info *if_info)
&if_info->else_simple))
return false;
- if (else_bb == NULL)
- if_info->original_cost += then_cost;
- else if (speed_p)
- if_info->original_cost += MIN (then_cost, else_cost);
+ if (speed_p)
+ if_info->original_cost += average_cost (then_cost, else_cost,
+ find_edge (test_bb, then_bb));
else
if_info->original_cost += then_cost + else_cost;
diff --git a/gcc/ifcvt.h b/gcc/ifcvt.h
index 153ad961b2c..40ad744bfc2 100644
--- a/gcc/ifcvt.h
+++ b/gcc/ifcvt.h
@@ -97,8 +97,8 @@ struct noce_if_info
/* An estimate of the original costs. When optimizing for size, this is the
combined cost of COND, JUMP and the costs for THEN_BB and ELSE_BB.
- When optimizing for speed, we use the costs of COND plus the minimum of
- the costs for THEN_BB and ELSE_BB, as computed in the next field. */
+ When optimizing for speed, we use the costs of COND plus weighted average
+ of the costs for THEN_BB and ELSE_BB, as computed in the next field. */
unsigned int original_cost;
/* Maximum permissible cost for the unconditional sequence we should
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 67664ec8c07..045072e02ec 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -5304,4 +5304,5 @@ ipa_cp_c_finalize (void)
max_count = profile_count::uninitialized ();
overall_size = 0;
max_new_size = 0;
+ ipcp_free_transformation_sum ();
}
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index 3423c4052db..6c651a38705 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -986,8 +986,8 @@ warn_types_mismatch (tree t1, tree t2, location_t loc1, location_t loc2)
|| (type_with_linkage_p (TYPE_MAIN_VARIANT (t2))
&& type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t2))))
{
- if (type_with_linkage_p (TYPE_MAIN_VARIANT (t1))
- && !type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t1)))
+ if (!type_with_linkage_p (TYPE_MAIN_VARIANT (t1))
+ || !type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t1)))
{
std::swap (t1, t2);
std::swap (loc_t1, loc_t2);
diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c
index 009aeb487dd..8bf0f7c6dd5 100644
--- a/gcc/ipa-icf.c
+++ b/gcc/ipa-icf.c
@@ -1688,13 +1688,10 @@ sem_function::compare_phi_node (basic_block bb1, basic_block bb2)
gcc_assert (bb1 != NULL);
gcc_assert (bb2 != NULL);
- si2 = gsi_start_phis (bb2);
- for (si1 = gsi_start_phis (bb1); !gsi_end_p (si1);
- gsi_next (&si1))
+ si2 = gsi_start_nonvirtual_phis (bb2);
+ for (si1 = gsi_start_nonvirtual_phis (bb1); !gsi_end_p (si1);
+ gsi_next_nonvirtual_phi (&si1))
{
- gsi_next_nonvirtual_phi (&si1);
- gsi_next_nonvirtual_phi (&si2);
-
if (gsi_end_p (si1) && gsi_end_p (si2))
break;
@@ -1731,7 +1728,7 @@ sem_function::compare_phi_node (basic_block bb1, basic_block bb2)
return return_false ();
}
- gsi_next (&si2);
+ gsi_next_nonvirtual_phi (&si2);
}
return true;
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index c8689c7d9a8..681801a9aec 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -390,6 +390,50 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
return inlinable;
}
+/* Return inlining_insns_single limit for function N. If HINT is true
+ scale up the bound. */
+
+static int
+inline_insns_single (cgraph_node *n, bool hint)
+{
+ if (opt_for_fn (n->decl, optimize) >= 3)
+ {
+ if (hint)
+ return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SINGLE)
+ * PARAM_VALUE (PARAM_INLINE_HEURISTICS_HINT_PERCENT) / 100;
+ return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SINGLE);
+ }
+ else
+ {
+ if (hint)
+ return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SINGLE_O2)
+ * PARAM_VALUE (PARAM_INLINE_HEURISTICS_HINT_PERCENT_O2) / 100;
+ return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SINGLE_O2);
+ }
+}
+
+/* Return inlining_insns_auto limit for function N. If HINT is true
+ scale up the bound. */
+
+static int
+inline_insns_auto (cgraph_node *n, bool hint)
+{
+ if (opt_for_fn (n->decl, optimize) >= 3)
+ {
+ if (hint)
+ return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO)
+ * PARAM_VALUE (PARAM_INLINE_HEURISTICS_HINT_PERCENT) / 100;
+ return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO);
+ }
+ else
+ {
+ if (hint)
+ return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO_O2)
+ * PARAM_VALUE (PARAM_INLINE_HEURISTICS_HINT_PERCENT_O2) / 100;
+ return PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO_O2);
+ }
+}
+
/* Decide if we can inline the edge and possibly update
inline_failed reason.
We check whether inlining is possible at all and whether
@@ -532,8 +576,8 @@ can_inline_edge_by_limits_p (struct cgraph_edge *e, bool report,
int growth = estimate_edge_growth (e);
if (growth > PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SIZE)
&& (!DECL_DECLARED_INLINE_P (callee->decl)
- && growth >= MAX (MAX_INLINE_INSNS_SINGLE,
- MAX_INLINE_INSNS_AUTO)))
+ && growth >= MAX (inline_insns_single (caller, false),
+ inline_insns_auto (caller, false))))
{
e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
inlinable = false;
@@ -745,9 +789,14 @@ big_speedup_p (struct cgraph_edge *e)
sreal spec_time = estimate_edge_time (e, &unspec_time);
sreal time = compute_uninlined_call_time (e, unspec_time);
sreal inlined_time = compute_inlined_call_time (e, spec_time);
+ cgraph_node *caller = e->caller->global.inlined_to
+ ? e->caller->global.inlined_to
+ : e->caller;
+ int limit = opt_for_fn (caller->decl, optimize) >= 3
+ ? PARAM_VALUE (PARAM_INLINE_MIN_SPEEDUP)
+ : PARAM_VALUE (PARAM_INLINE_MIN_SPEEDUP_O2);
- if ((time - inlined_time) * 100
- > (sreal) (time * PARAM_VALUE (PARAM_INLINE_MIN_SPEEDUP)))
+ if ((time - inlined_time) * 100 > time * limit)
return true;
return false;
}
@@ -774,49 +823,60 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
want_inline = false;
}
/* Do fast and conservative check if the function can be good
- inline candidate. At the moment we allow inline hints to
- promote non-inline functions to inline and we increase
- MAX_INLINE_INSNS_SINGLE 16-fold for inline functions. */
+ inline candidate. */
else if ((!DECL_DECLARED_INLINE_P (callee->decl)
&& (!e->count.ipa ().initialized_p () || !e->maybe_hot_p ()))
&& ipa_fn_summaries->get (callee)->min_size
- ipa_call_summaries->get (e)->call_stmt_size
- > MAX (MAX_INLINE_INSNS_SINGLE, MAX_INLINE_INSNS_AUTO))
+ > inline_insns_auto (e->caller, true))
{
- e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
+ if (opt_for_fn (e->caller->decl, optimize) >= 3)
+ e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
+ else
+ e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_O2_LIMIT;
want_inline = false;
}
else if ((DECL_DECLARED_INLINE_P (callee->decl)
|| e->count.ipa ().nonzero_p ())
&& ipa_fn_summaries->get (callee)->min_size
- ipa_call_summaries->get (e)->call_stmt_size
- > 16 * MAX_INLINE_INSNS_SINGLE)
+ > inline_insns_single (e->caller, true))
{
- e->inline_failed = (DECL_DECLARED_INLINE_P (callee->decl)
- ? CIF_MAX_INLINE_INSNS_SINGLE_LIMIT
- : CIF_MAX_INLINE_INSNS_AUTO_LIMIT);
+ if (opt_for_fn (e->caller->decl, optimize) >= 3)
+ e->inline_failed = (DECL_DECLARED_INLINE_P (callee->decl)
+ ? CIF_MAX_INLINE_INSNS_SINGLE_LIMIT
+ : CIF_MAX_INLINE_INSNS_AUTO_LIMIT);
+ else
+ e->inline_failed = (DECL_DECLARED_INLINE_P (callee->decl)
+ ? CIF_MAX_INLINE_INSNS_SINGLE_O2_LIMIT
+ : CIF_MAX_INLINE_INSNS_AUTO_O2_LIMIT);
want_inline = false;
}
else
{
int growth = estimate_edge_growth (e);
ipa_hints hints = estimate_edge_hints (e);
- int big_speedup = -1; /* compute this lazily */
+ bool apply_hints = (hints & (INLINE_HINT_indirect_call
+ | INLINE_HINT_known_hot
+ | INLINE_HINT_loop_iterations
+ | INLINE_HINT_loop_stride));
if (growth <= PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SIZE))
;
/* Apply MAX_INLINE_INSNS_SINGLE limit. Do not do so when
- hints suggests that inlining given function is very profitable. */
+ hints suggests that inlining given function is very profitable.
+ Avoid computation of big_speedup_p when not necessary to change
+ outcome of decision. */
else if (DECL_DECLARED_INLINE_P (callee->decl)
- && growth >= MAX_INLINE_INSNS_SINGLE
- && (growth >= MAX_INLINE_INSNS_SINGLE * 16
- || (!(hints & (INLINE_HINT_indirect_call
- | INLINE_HINT_known_hot
- | INLINE_HINT_loop_iterations
- | INLINE_HINT_loop_stride))
- && !(big_speedup = big_speedup_p (e)))))
+ && growth >= inline_insns_single (e->caller, apply_hints)
+ && (apply_hints
+ || growth >= inline_insns_single (e->caller, true)
+ || !big_speedup_p (e)))
{
- e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT;
+ if (opt_for_fn (e->caller->decl, optimize) >= 3)
+ e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT;
+ else
+ e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_O2_LIMIT;
want_inline = false;
}
else if (!DECL_DECLARED_INLINE_P (callee->decl)
@@ -824,43 +884,38 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
&& growth >= PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SMALL))
{
/* growth_likely_positive is expensive, always test it last. */
- if (growth >= MAX_INLINE_INSNS_SINGLE
+ if (growth >= inline_insns_single (e->caller, false)
|| growth_likely_positive (callee, growth))
{
- e->inline_failed = CIF_NOT_DECLARED_INLINED;
+ e->inline_failed = CIF_NOT_DECLARED_INLINED;
want_inline = false;
- }
+ }
}
- /* Apply MAX_INLINE_INSNS_AUTO limit for functions not declared inline
- Upgrade it to MAX_INLINE_INSNS_SINGLE when hints suggests that
- inlining given function is very profitable. */
+ /* Apply MAX_INLINE_INSNS_AUTO limit for functions not declared inline.
+ Bypass the limit when speedup seems big. */
else if (!DECL_DECLARED_INLINE_P (callee->decl)
- && !(hints & INLINE_HINT_known_hot)
- && growth >= ((hints & (INLINE_HINT_indirect_call
- | INLINE_HINT_loop_iterations
- | INLINE_HINT_loop_stride))
- ? MAX (MAX_INLINE_INSNS_AUTO,
- MAX_INLINE_INSNS_SINGLE)
- : MAX_INLINE_INSNS_AUTO)
- && !(big_speedup == -1 ? big_speedup_p (e) : big_speedup))
+ && growth >= inline_insns_auto (e->caller, apply_hints)
+ && (apply_hints
+ || growth >= inline_insns_auto (e->caller, true)
+ || !big_speedup_p (e)))
{
/* growth_likely_positive is expensive, always test it last. */
- if (growth >= MAX_INLINE_INSNS_SINGLE
+ if (growth >= inline_insns_single (e->caller, false)
|| growth_likely_positive (callee, growth))
{
- e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
+ if (opt_for_fn (e->caller->decl, optimize) >= 3)
+ e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
+ else
+ e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_O2_LIMIT;
want_inline = false;
- }
+ }
}
/* If call is cold, do not inline when function body would grow. */
else if (!e->maybe_hot_p ()
- && (growth >= MAX_INLINE_INSNS_SINGLE
+ && (growth >= inline_insns_single (e->caller, false)
|| growth_likely_positive (callee, growth)))
{
- if (e->count.ipa () == profile_count::zero ())
- e->inline_failed = CIF_NEVER_CALL;
- else
- e->inline_failed = CIF_UNLIKELY_CALL;
+ e->inline_failed = CIF_UNLIKELY_CALL;
want_inline = false;
}
}
@@ -1131,7 +1186,7 @@ edge_badness (struct cgraph_edge *edge, bool dump)
if (need_more_work)
noninline_callee ();
}
- Withhout panilizing this case, we usually inline noninline_callee
+ Withhout penalizing this case, we usually inline noninline_callee
into the inline_caller because overall_growth is small preventing
further inlining of inline_caller.
@@ -1161,12 +1216,13 @@ edge_badness (struct cgraph_edge *edge, bool dump)
int caller_growth = caller_info->growth;
/* Only apply the penalty when caller looks like inline candidate,
- and it is not called once and. */
+ and it is not called once. */
if (!caller_info->single_caller && overall_growth < caller_growth
&& caller_info->inlinable
&& caller_info->size
< (DECL_DECLARED_INLINE_P (caller->decl)
- ? MAX_INLINE_INSNS_SINGLE : MAX_INLINE_INSNS_AUTO))
+ ? inline_insns_single (caller, false)
+ : inline_insns_auto (caller, false)))
{
if (dump)
fprintf (dump_file,
@@ -1187,7 +1243,7 @@ edge_badness (struct cgraph_edge *edge, bool dump)
overall_growth += 256 * 256 - 256;
denominator *= overall_growth;
}
- denominator *= ipa_fn_summaries->get (caller)->self_size + growth;
+ denominator *= ipa_fn_summaries->get (caller)->size + growth;
badness = - numerator / denominator;
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 25a108d5824..5020f4a44d5 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -3758,6 +3758,18 @@ ipcp_transformation_initialize (void)
ipcp_transformation_sum = ipcp_transformation_t::create_ggc (symtab);
}
+/* Release the IPA CP transformation summary. */
+
+void
+ipcp_free_transformation_sum (void)
+{
+ if (!ipcp_transformation_sum)
+ return;
+
+ ipcp_transformation_sum->release ();
+ ipcp_transformation_sum = NULL;
+}
+
/* Set the aggregate replacements of NODE to be AGGVALS. */
void
@@ -5097,6 +5109,19 @@ ipcp_update_bits (struct cgraph_node *node)
}
}
+bool
+ipa_vr::nonzero_p (tree expr_type) const
+{
+ if (type == VR_ANTI_RANGE && wi::eq_p (min, 0) && wi::eq_p (max, 0))
+ return true;
+
+ unsigned prec = TYPE_PRECISION (expr_type);
+ return (type == VR_RANGE
+ && TYPE_UNSIGNED (expr_type)
+ && wi::eq_p (min, wi::one (prec))
+ && wi::eq_p (max, wi::max_value (prec, TYPE_SIGN (expr_type))));
+}
+
/* Update value range of formal parameters as described in
ipcp_transformation. */
@@ -5169,9 +5194,7 @@ ipcp_update_vr (struct cgraph_node *node)
TYPE_SIGN (type)));
}
else if (POINTER_TYPE_P (TREE_TYPE (ddef))
- && vr[i].type == VR_ANTI_RANGE
- && wi::eq_p (vr[i].min, 0)
- && wi::eq_p (vr[i].max, 0))
+ && vr[i].nonzero_p (TREE_TYPE (ddef)))
{
if (dump_file)
fprintf (dump_file, "Setting nonnull for %u\n", i);
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index 30948fb8854..eb3397a6d81 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -165,6 +165,7 @@ public:
enum value_range_kind type;
wide_int min;
wide_int max;
+ bool nonzero_p (tree) const;
};
/* A jump function for a callsite represents the values passed as actual
@@ -561,6 +562,7 @@ struct GTY(()) ipcp_transformation
void ipa_set_node_agg_value_chain (struct cgraph_node *node,
struct ipa_agg_replacement_value *aggvals);
void ipcp_transformation_initialize (void);
+void ipcp_free_transformation_sum (void);
/* ipa_edge_args stores information related to a callsite and particularly its
arguments. It can be accessed by the IPA_EDGE_REF macro. */
diff --git a/gcc/ira-color.c b/gcc/ira-color.c
index ce5141bd48f..e38c167ebc4 100644
--- a/gcc/ira-color.c
+++ b/gcc/ira-color.c
@@ -1372,6 +1372,7 @@ update_costs_from_allocno (ira_allocno_t allocno, int hard_regno,
e.g. DImode for AREG on x86. For such cases the
register move cost will be maximal. */
mode = narrower_subreg_mode (mode, ALLOCNO_MODE (cp->second));
+ ira_init_register_move_cost_if_necessary (mode);
cost = (cp->second == allocno
? ira_register_move_cost[mode][rclass][aclass]
diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c
index cce73a1c3d4..098b0e73953 100644
--- a/gcc/ira-lives.c
+++ b/gcc/ira-lives.c
@@ -633,9 +633,28 @@ check_and_make_def_use_conflict (rtx dreg, rtx orig_dreg,
/* Check and make if necessary conflicts for definition DEF of class
DEF_CL of the current insn with input operands. Process only
- constraints of alternative ALT. */
+ constraints of alternative ALT.
+
+ One of three things is true when this function is called:
+
+ (1) DEF is an earlyclobber for alternative ALT. Input operands then
+ conflict with DEF in ALT unless they explicitly match DEF via 0-9
+ constraints.
+
+ (2) DEF matches (via 0-9 constraints) an operand that is an
+ earlyclobber for alternative ALT. Other input operands then
+ conflict with DEF in ALT.
+
+ (3) [FOR_TIE_P] Some input operand X matches DEF for alternative ALT.
+ Input operands with a different value from X then conflict with
+ DEF in ALT.
+
+ However, there's still a judgement call to make when deciding
+ whether a conflict in ALT is important enough to be reflected
+ in the pan-alternative allocno conflict set. */
static void
-check_and_make_def_conflict (int alt, int def, enum reg_class def_cl)
+check_and_make_def_conflict (int alt, int def, enum reg_class def_cl,
+ bool for_tie_p)
{
int use, use_match;
ira_allocno_t a;
@@ -669,14 +688,40 @@ check_and_make_def_conflict (int alt, int def, enum reg_class def_cl)
if (use == def || recog_data.operand_type[use] == OP_OUT)
continue;
+ /* An earlyclobber on DEF doesn't apply to an input operand X if X
+ explicitly matches DEF, but it applies to other input operands
+ even if they happen to be the same value as X.
+
+ In contrast, if an input operand X is tied to a non-earlyclobber
+ DEF, there's no conflict with other input operands that have the
+ same value as X. */
+ if (op_alt[use].matches == def
+ || (for_tie_p
+ && rtx_equal_p (recog_data.operand[use],
+ recog_data.operand[op_alt[def].matched])))
+ continue;
+
if (op_alt[use].anything_ok)
use_cl = ALL_REGS;
else
use_cl = op_alt[use].cl;
+ if (use_cl == NO_REGS)
+ continue;
+
+ /* If DEF is simply a tied operand, ignore cases in which this
+ alternative requires USE to have a likely-spilled class.
+ Adding a conflict would just constrain USE further if DEF
+ happens to be allocated first. */
+ if (for_tie_p && targetm.class_likely_spilled_p (use_cl))
+ continue;
/* If there's any alternative that allows USE to match DEF, do not
record a conflict. If that causes us to create an invalid
- instruction due to the earlyclobber, reload must fix it up. */
+ instruction due to the earlyclobber, reload must fix it up.
+
+ Likewise, if we're treating a tied DEF like a partial earlyclobber,
+ do not record a conflict if there's another alternative in which
+ DEF is neither tied nor earlyclobber. */
for (alt1 = 0; alt1 < recog_data.n_alternatives; alt1++)
{
if (!TEST_BIT (preferred_alternatives, alt1))
@@ -691,6 +736,12 @@ check_and_make_def_conflict (int alt, int def, enum reg_class def_cl)
&& recog_data.constraints[use - 1][0] == '%'
&& op_alt1[use - 1].matches == def))
break;
+ if (for_tie_p
+ && !op_alt1[def].earlyclobber
+ && op_alt1[def].matched < 0
+ && alternative_class (op_alt1, def) != NO_REGS
+ && alternative_class (op_alt1, use) != NO_REGS)
+ break;
}
if (alt1 < recog_data.n_alternatives)
@@ -701,8 +752,7 @@ check_and_make_def_conflict (int alt, int def, enum reg_class def_cl)
if ((use_match = op_alt[use].matches) >= 0)
{
- if (use_match == def)
- continue;
+ gcc_checking_assert (use_match != def);
if (op_alt[use_match].anything_ok)
use_cl = ALL_REGS;
@@ -717,7 +767,11 @@ check_and_make_def_conflict (int alt, int def, enum reg_class def_cl)
/* Make conflicts of early clobber pseudo registers of the current
insn with its inputs. Avoid introducing unnecessary conflicts by
checking classes of the constraints and pseudos because otherwise
- significant code degradation is possible for some targets. */
+ significant code degradation is possible for some targets.
+
+ For these purposes, tying an input to an output makes that output act
+ like an earlyclobber for inputs with a different value, since the output
+ register then has a predetermined purpose on input to the instruction. */
static void
make_early_clobber_and_input_conflicts (void)
{
@@ -732,15 +786,19 @@ make_early_clobber_and_input_conflicts (void)
if (TEST_BIT (preferred_alternatives, alt))
for (def = 0; def < n_operands; def++)
{
- def_cl = NO_REGS;
- if (op_alt[def].earlyclobber)
+ if (op_alt[def].anything_ok)
+ def_cl = ALL_REGS;
+ else
+ def_cl = op_alt[def].cl;
+ if (def_cl != NO_REGS)
{
- if (op_alt[def].anything_ok)
- def_cl = ALL_REGS;
- else
- def_cl = op_alt[def].cl;
- check_and_make_def_conflict (alt, def, def_cl);
+ if (op_alt[def].earlyclobber)
+ check_and_make_def_conflict (alt, def, def_cl, false);
+ else if (op_alt[def].matched >= 0
+ && !targetm.class_likely_spilled_p (def_cl))
+ check_and_make_def_conflict (alt, def, def_cl, true);
}
+
if ((def_match = op_alt[def].matches) >= 0
&& (op_alt[def_match].earlyclobber
|| op_alt[def].earlyclobber))
@@ -749,7 +807,7 @@ make_early_clobber_and_input_conflicts (void)
def_cl = ALL_REGS;
else
def_cl = op_alt[def_match].cl;
- check_and_make_def_conflict (alt, def, def_cl);
+ check_and_make_def_conflict (alt, def, def_cl, false);
}
}
}
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index a059841b3df..55d5fe01495 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -236,6 +236,7 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
#define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL lhd_warn_unused_global_decl
#define LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS NULL
#define LANG_HOOKS_DECL_OK_FOR_SIBCALL lhd_decl_ok_for_sibcall
+#define LANG_HOOKS_OMP_IS_OPTIONAL_ARGUMENT hook_bool_const_tree_false
#define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE hook_bool_const_tree_false
#define LANG_HOOKS_OMP_PREDETERMINED_SHARING lhd_omp_predetermined_sharing
#define LANG_HOOKS_OMP_REPORT_DECL lhd_pass_through_t
@@ -261,6 +262,7 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, \
LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS, \
LANG_HOOKS_DECL_OK_FOR_SIBCALL, \
+ LANG_HOOKS_OMP_IS_OPTIONAL_ARGUMENT, \
LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE, \
LANG_HOOKS_OMP_PREDETERMINED_SHARING, \
LANG_HOOKS_OMP_REPORT_DECL, \
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index a45579b3325..9d2714a5b1d 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -222,6 +222,9 @@ struct lang_hooks_for_decls
/* True if this decl may be called via a sibcall. */
bool (*ok_for_sibcall) (const_tree);
+ /* True if OpenMP should treat DECL as a Fortran optional argument. */
+ bool (*omp_is_optional_argument) (const_tree);
+
/* True if OpenMP should privatize what this DECL points to rather
than the DECL itself. */
bool (*omp_privatize_by_reference) (const_tree);
diff --git a/gcc/lra-lives.c b/gcc/lra-lives.c
index 389a79d701d..1d1525ca2e5 100644
--- a/gcc/lra-lives.c
+++ b/gcc/lra-lives.c
@@ -281,7 +281,8 @@ static void
make_hard_regno_live (int regno)
{
lra_assert (HARD_REGISTER_NUM_P (regno));
- if (TEST_HARD_REG_BIT (hard_regs_live, regno))
+ if (TEST_HARD_REG_BIT (hard_regs_live, regno)
+ || TEST_HARD_REG_BIT (eliminable_regset, regno))
return;
SET_HARD_REG_BIT (hard_regs_live, regno);
sparseset_set_bit (start_living, regno);
@@ -295,6 +296,9 @@ make_hard_regno_live (int regno)
static void
make_hard_regno_dead (int regno)
{
+ if (TEST_HARD_REG_BIT (eliminable_regset, regno))
+ return;
+
lra_assert (HARD_REGISTER_NUM_P (regno));
unsigned int i;
EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index a73cbc4ca9f..e4102320795 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,7 @@
+2019-10-04 Joseph Myers <joseph@codesourcery.com>
+
+ * lto-lang.c (flag_isoc2x): New variable.
+
2019-09-18 Richard Biener <rguenther@suse.de>
PR lto/91763
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index 414eaf2075a..0d781da5768 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -247,6 +247,7 @@ static GTY(()) tree signed_size_type_node;
int flag_isoc94;
int flag_isoc99;
int flag_isoc11;
+int flag_isoc2x;
/* Attribute handlers. */
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 005ec80e89d..64ac213fbac 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -244,11 +244,11 @@ class opt_mode
public:
enum from_int { dummy = MAX_MACHINE_MODE };
- ALWAYS_INLINE opt_mode () : m_mode (E_VOIDmode) {}
- ALWAYS_INLINE opt_mode (const T &m) : m_mode (m) {}
+ ALWAYS_INLINE CONSTEXPR opt_mode () : m_mode (E_VOIDmode) {}
+ ALWAYS_INLINE CONSTEXPR opt_mode (const T &m) : m_mode (m) {}
template<typename U>
- ALWAYS_INLINE opt_mode (const U &m) : m_mode (T (m)) {}
- ALWAYS_INLINE opt_mode (from_int m) : m_mode (machine_mode (m)) {}
+ ALWAYS_INLINE CONSTEXPR opt_mode (const U &m) : m_mode (T (m)) {}
+ ALWAYS_INLINE CONSTEXPR opt_mode (from_int m) : m_mode (machine_mode (m)) {}
machine_mode else_void () const;
machine_mode else_blk () const { return else_mode (BLKmode); }
@@ -324,8 +324,12 @@ struct pod_mode
typedef typename T::measurement_type measurement_type;
machine_mode m_mode;
- ALWAYS_INLINE operator machine_mode () const { return m_mode; }
- ALWAYS_INLINE operator T () const { return from_int (m_mode); }
+ ALWAYS_INLINE CONSTEXPR
+ operator machine_mode () const { return m_mode; }
+
+ ALWAYS_INLINE CONSTEXPR
+ operator T () const { return from_int (m_mode); }
+
ALWAYS_INLINE pod_mode &operator = (const T &m) { m_mode = m; return *this; }
};
@@ -403,8 +407,11 @@ public:
typedef unsigned short measurement_type;
ALWAYS_INLINE scalar_int_mode () {}
- ALWAYS_INLINE scalar_int_mode (from_int m) : m_mode (machine_mode (m)) {}
- ALWAYS_INLINE operator machine_mode () const { return m_mode; }
+
+ ALWAYS_INLINE CONSTEXPR
+ scalar_int_mode (from_int m) : m_mode (machine_mode (m)) {}
+
+ ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
static bool includes_p (machine_mode);
@@ -428,8 +435,11 @@ public:
typedef unsigned short measurement_type;
ALWAYS_INLINE scalar_float_mode () {}
- ALWAYS_INLINE scalar_float_mode (from_int m) : m_mode (machine_mode (m)) {}
- ALWAYS_INLINE operator machine_mode () const { return m_mode; }
+
+ ALWAYS_INLINE CONSTEXPR
+ scalar_float_mode (from_int m) : m_mode (machine_mode (m)) {}
+
+ ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
static bool includes_p (machine_mode);
@@ -453,11 +463,20 @@ public:
typedef unsigned short measurement_type;
ALWAYS_INLINE scalar_mode () {}
- ALWAYS_INLINE scalar_mode (from_int m) : m_mode (machine_mode (m)) {}
- ALWAYS_INLINE scalar_mode (const scalar_int_mode &m) : m_mode (m) {}
- ALWAYS_INLINE scalar_mode (const scalar_float_mode &m) : m_mode (m) {}
- ALWAYS_INLINE scalar_mode (const scalar_int_mode_pod &m) : m_mode (m) {}
- ALWAYS_INLINE operator machine_mode () const { return m_mode; }
+
+ ALWAYS_INLINE CONSTEXPR
+ scalar_mode (from_int m) : m_mode (machine_mode (m)) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ scalar_mode (const scalar_int_mode &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ scalar_mode (const scalar_float_mode &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ scalar_mode (const scalar_int_mode_pod &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
static bool includes_p (machine_mode);
@@ -494,8 +513,11 @@ public:
typedef unsigned short measurement_type;
ALWAYS_INLINE complex_mode () {}
- ALWAYS_INLINE complex_mode (from_int m) : m_mode (machine_mode (m)) {}
- ALWAYS_INLINE operator machine_mode () const { return m_mode; }
+
+ ALWAYS_INLINE CONSTEXPR
+ complex_mode (from_int m) : m_mode (machine_mode (m)) {}
+
+ ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
static bool includes_p (machine_mode);
@@ -764,14 +786,29 @@ public:
typedef unsigned short measurement_type;
ALWAYS_INLINE fixed_size_mode () {}
- ALWAYS_INLINE fixed_size_mode (from_int m) : m_mode (machine_mode (m)) {}
- ALWAYS_INLINE fixed_size_mode (const scalar_mode &m) : m_mode (m) {}
- ALWAYS_INLINE fixed_size_mode (const scalar_int_mode &m) : m_mode (m) {}
- ALWAYS_INLINE fixed_size_mode (const scalar_float_mode &m) : m_mode (m) {}
- ALWAYS_INLINE fixed_size_mode (const scalar_mode_pod &m) : m_mode (m) {}
- ALWAYS_INLINE fixed_size_mode (const scalar_int_mode_pod &m) : m_mode (m) {}
- ALWAYS_INLINE fixed_size_mode (const complex_mode &m) : m_mode (m) {}
- ALWAYS_INLINE operator machine_mode () const { return m_mode; }
+
+ ALWAYS_INLINE CONSTEXPR
+ fixed_size_mode (from_int m) : m_mode (machine_mode (m)) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ fixed_size_mode (const scalar_mode &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ fixed_size_mode (const scalar_int_mode &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ fixed_size_mode (const scalar_float_mode &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ fixed_size_mode (const scalar_mode_pod &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ fixed_size_mode (const scalar_int_mode_pod &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ fixed_size_mode (const complex_mode &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
static bool includes_p (machine_mode);
diff --git a/gcc/match.pd b/gcc/match.pd
index 23ce376802f..e3ac06c8ef5 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3726,8 +3726,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(cmp { tem; } @1)))))
/* Fold comparisons against built-in math functions. */
- (if (flag_unsafe_math_optimizations
- && ! flag_errno_math)
+ (if (flag_unsafe_math_optimizations && ! flag_errno_math)
(for sq (SQRT)
(simplify
(cmp (sq @0) REAL_CST@1)
@@ -3762,56 +3761,108 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
if x is negative or NaN. Due to -funsafe-math-optimizations,
the results for other x follow from natural arithmetic. */
(cmp @0 @1)))
- (if (cmp == GT_EXPR || cmp == GE_EXPR)
+ (if ((cmp == LT_EXPR
+ || cmp == LE_EXPR
+ || cmp == GT_EXPR
+ || cmp == GE_EXPR)
+ && !REAL_VALUE_ISNAN (TREE_REAL_CST (@1))
+ /* Give up for -frounding-math. */
+ && !HONOR_SIGN_DEPENDENT_ROUNDING (TREE_TYPE (@0)))
(with
{
- REAL_VALUE_TYPE c2;
+ REAL_VALUE_TYPE c2;
+ enum tree_code ncmp = cmp;
+ const real_format *fmt
+ = REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@0)));
real_arithmetic (&c2, MULT_EXPR,
&TREE_REAL_CST (@1), &TREE_REAL_CST (@1));
- real_convert (&c2, TYPE_MODE (TREE_TYPE (@0)), &c2);
- }
- (if (REAL_VALUE_ISINF (c2))
- /* sqrt(x) > y is x == +Inf, when y is very large. */
- (if (HONOR_INFINITIES (@0))
- (eq @0 { build_real (TREE_TYPE (@0), c2); })
- { constant_boolean_node (false, type); })
- /* sqrt(x) > c is the same as x > c*c. */
- (cmp @0 { build_real (TREE_TYPE (@0), c2); }))))
- (if (cmp == LT_EXPR || cmp == LE_EXPR)
- (with
- {
- REAL_VALUE_TYPE c2;
- real_arithmetic (&c2, MULT_EXPR,
- &TREE_REAL_CST (@1), &TREE_REAL_CST (@1));
- real_convert (&c2, TYPE_MODE (TREE_TYPE (@0)), &c2);
+ real_convert (&c2, fmt, &c2);
+ /* See PR91734: if c2 is inexact and sqrt(c2) < c (or sqrt(c2) >= c),
+ then change LT_EXPR into LE_EXPR or GE_EXPR into GT_EXPR. */
+ if (!REAL_VALUE_ISINF (c2))
+ {
+ tree c3 = fold_const_call (CFN_SQRT, TREE_TYPE (@0),
+ build_real (TREE_TYPE (@0), c2));
+ if (c3 == NULL_TREE || TREE_CODE (c3) != REAL_CST)
+ ncmp = ERROR_MARK;
+ else if ((cmp == LT_EXPR || cmp == GE_EXPR)
+ && real_less (&TREE_REAL_CST (c3), &TREE_REAL_CST (@1)))
+ ncmp = cmp == LT_EXPR ? LE_EXPR : GT_EXPR;
+ else if ((cmp == LE_EXPR || cmp == GT_EXPR)
+ && real_less (&TREE_REAL_CST (@1), &TREE_REAL_CST (c3)))
+ ncmp = cmp == LE_EXPR ? LT_EXPR : GE_EXPR;
+ else
+ {
+ /* With rounding to even, sqrt of up to 3 different values
+ gives the same normal result, so in some cases c2 needs
+ to be adjusted. */
+ REAL_VALUE_TYPE c2alt, tow;
+ if (cmp == LT_EXPR || cmp == GE_EXPR)
+ tow = dconst0;
+ else
+ real_inf (&tow);
+ real_nextafter (&c2alt, fmt, &c2, &tow);
+ real_convert (&c2alt, fmt, &c2alt);
+ if (REAL_VALUE_ISINF (c2alt))
+ ncmp = ERROR_MARK;
+ else
+ {
+ c3 = fold_const_call (CFN_SQRT, TREE_TYPE (@0),
+ build_real (TREE_TYPE (@0), c2alt));
+ if (c3 == NULL_TREE || TREE_CODE (c3) != REAL_CST)
+ ncmp = ERROR_MARK;
+ else if (real_equal (&TREE_REAL_CST (c3),
+ &TREE_REAL_CST (@1)))
+ c2 = c2alt;
+ }
+ }
+ }
}
- (if (REAL_VALUE_ISINF (c2))
- (switch
- /* sqrt(x) < y is always true, when y is a very large
- value and we don't care about NaNs or Infinities. */
- (if (! HONOR_NANS (@0) && ! HONOR_INFINITIES (@0))
- { constant_boolean_node (true, type); })
- /* sqrt(x) < y is x != +Inf when y is very large and we
- don't care about NaNs. */
- (if (! HONOR_NANS (@0))
- (ne @0 { build_real (TREE_TYPE (@0), c2); }))
- /* sqrt(x) < y is x >= 0 when y is very large and we
- don't care about Infinities. */
- (if (! HONOR_INFINITIES (@0))
- (ge @0 { build_real (TREE_TYPE (@0), dconst0); }))
- /* sqrt(x) < y is x >= 0 && x != +Inf, when y is large. */
- (if (GENERIC)
- (truth_andif
- (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
- (ne @0 { build_real (TREE_TYPE (@0), c2); }))))
- /* sqrt(x) < c is the same as x < c*c, if we ignore NaNs. */
- (if (! HONOR_NANS (@0))
- (cmp @0 { build_real (TREE_TYPE (@0), c2); })
- /* sqrt(x) < c is the same as x >= 0 && x < c*c. */
- (if (GENERIC)
- (truth_andif
- (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
- (cmp @0 { build_real (TREE_TYPE (@0), c2); })))))))))
+ (if (cmp == GT_EXPR || cmp == GE_EXPR)
+ (if (REAL_VALUE_ISINF (c2))
+ /* sqrt(x) > y is x == +Inf, when y is very large. */
+ (if (HONOR_INFINITIES (@0))
+ (eq @0 { build_real (TREE_TYPE (@0), c2); })
+ { constant_boolean_node (false, type); })
+ /* sqrt(x) > c is the same as x > c*c. */
+ (if (ncmp != ERROR_MARK)
+ (if (ncmp == GE_EXPR)
+ (ge @0 { build_real (TREE_TYPE (@0), c2); })
+ (gt @0 { build_real (TREE_TYPE (@0), c2); }))))
+ /* else if (cmp == LT_EXPR || cmp == LE_EXPR) */
+ (if (REAL_VALUE_ISINF (c2))
+ (switch
+ /* sqrt(x) < y is always true, when y is a very large
+ value and we don't care about NaNs or Infinities. */
+ (if (! HONOR_NANS (@0) && ! HONOR_INFINITIES (@0))
+ { constant_boolean_node (true, type); })
+ /* sqrt(x) < y is x != +Inf when y is very large and we
+ don't care about NaNs. */
+ (if (! HONOR_NANS (@0))
+ (ne @0 { build_real (TREE_TYPE (@0), c2); }))
+ /* sqrt(x) < y is x >= 0 when y is very large and we
+ don't care about Infinities. */
+ (if (! HONOR_INFINITIES (@0))
+ (ge @0 { build_real (TREE_TYPE (@0), dconst0); }))
+ /* sqrt(x) < y is x >= 0 && x != +Inf, when y is large. */
+ (if (GENERIC)
+ (truth_andif
+ (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
+ (ne @0 { build_real (TREE_TYPE (@0), c2); }))))
+ /* sqrt(x) < c is the same as x < c*c, if we ignore NaNs. */
+ (if (ncmp != ERROR_MARK && ! HONOR_NANS (@0))
+ (if (ncmp == LT_EXPR)
+ (lt @0 { build_real (TREE_TYPE (@0), c2); })
+ (le @0 { build_real (TREE_TYPE (@0), c2); }))
+ /* sqrt(x) < c is the same as x >= 0 && x < c*c. */
+ (if (ncmp != ERROR_MARK && GENERIC)
+ (if (ncmp == LT_EXPR)
+ (truth_andif
+ (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
+ (lt @0 { build_real (TREE_TYPE (@0), c2); }))
+ (truth_andif
+ (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
+ (le @0 { build_real (TREE_TYPE (@0), c2); })))))))))))
/* Transform sqrt(x) cmp sqrt(y) -> x cmp y. */
(simplify
(cmp (sq @0) (sq @1))
@@ -4922,6 +4973,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(rdiv (SIN:s @0) (COS:s @0))
(TAN @0))
+ /* Simplify sinh(x) / cosh(x) -> tanh(x). */
+ (simplify
+ (rdiv (SINH:s @0) (COSH:s @0))
+ (TANH @0))
+
/* Simplify cos(x) / sin(x) -> 1 / tan(x). */
(simplify
(rdiv (COS:s @0) (SIN:s @0))
diff --git a/gcc/omp-general.c b/gcc/omp-general.c
index 66be94f6ff9..5ef6e251698 100644
--- a/gcc/omp-general.c
+++ b/gcc/omp-general.c
@@ -48,6 +48,14 @@ omp_find_clause (tree clauses, enum omp_clause_code kind)
return NULL_TREE;
}
+/* Return true if DECL is a Fortran optional argument. */
+
+bool
+omp_is_optional_argument (tree decl)
+{
+ return lang_hooks.decls.omp_is_optional_argument (decl);
+}
+
/* Return true if DECL is a reference type. */
bool
diff --git a/gcc/omp-general.h b/gcc/omp-general.h
index 80d42aff3c8..bbaa7b11707 100644
--- a/gcc/omp-general.h
+++ b/gcc/omp-general.h
@@ -73,6 +73,7 @@ struct omp_for_data
#define OACC_FN_ATTRIB "oacc function"
extern tree omp_find_clause (tree clauses, enum omp_clause_code kind);
+extern bool omp_is_optional_argument (tree decl);
extern bool omp_is_reference (tree decl);
extern void omp_adjust_for_condition (location_t loc, enum tree_code *cond_code,
tree *n2, tree v, tree step);
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 5db182c6841..ca7dfdb83a1 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -11395,7 +11395,8 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
{
gcc_assert (is_gimple_omp_oacc (ctx->stmt));
if (omp_is_reference (new_var)
- && TREE_CODE (TREE_TYPE (new_var)) != POINTER_TYPE)
+ && (TREE_CODE (TREE_TYPE (new_var)) != POINTER_TYPE
+ || DECL_BY_REFERENCE (var)))
{
/* Create a local object to hold the instance
value. */
@@ -11869,7 +11870,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
var = build_fold_addr_expr (var);
else
{
- if (omp_is_reference (ovar))
+ if (omp_is_reference (ovar) || omp_is_optional_argument (ovar))
{
type = TREE_TYPE (type);
if (TREE_CODE (type) != ARRAY_TYPE
diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
index 8157798cc71..a5ecbf075b5 100644
--- a/gcc/optabs-tree.c
+++ b/gcc/optabs-tree.c
@@ -23,7 +23,10 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "target.h"
#include "insn-codes.h"
+#include "rtl.h"
#include "tree.h"
+#include "memmodel.h"
+#include "optabs.h"
#include "optabs-tree.h"
#include "stor-layout.h"
@@ -329,6 +332,31 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
return false;
}
+/* Return true iff vcond_optab/vcondu_optab can handle a vector
+ comparison for code CODE, comparing operands of type CMP_OP_TYPE and
+ producing a result of type VALUE_TYPE. */
+
+static bool
+vcond_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
+{
+ return can_vcond_compare_p (get_rtx_code (code, TYPE_UNSIGNED (cmp_op_type)),
+ TYPE_MODE (value_type), TYPE_MODE (cmp_op_type));
+}
+
+/* Return true iff vcondeq_optab can handle a vector comparison for code CODE,
+ comparing operands of type CMP_OP_TYPE and producing a result of type
+ VALUE_TYPE. */
+
+static bool
+vcond_eq_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
+{
+ if (code != EQ_EXPR && code != NE_EXPR)
+ return false;
+
+ return get_vcond_eq_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type))
+ != CODE_FOR_nothing;
+}
+
/* Return TRUE iff, appropriate vector insns are available
for vector cond expr with vector type VALUE_TYPE and a comparison
with operand vector types in CMP_OP_TYPE. */
@@ -347,14 +375,13 @@ expand_vec_cond_expr_p (tree value_type, tree cmp_op_type, enum tree_code code)
|| maybe_ne (GET_MODE_NUNITS (value_mode), GET_MODE_NUNITS (cmp_op_mode)))
return false;
- if (get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
- TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing
- && ((code != EQ_EXPR && code != NE_EXPR)
- || get_vcond_eq_icode (TYPE_MODE (value_type),
- TYPE_MODE (cmp_op_type)) == CODE_FOR_nothing))
+ if (TREE_CODE_CLASS (code) != tcc_comparison)
+ /* This may happen, for example, if code == SSA_NAME, in which case we
+ cannot be certain whether a vector insn is available. */
return false;
- return true;
+ return vcond_icode_p (value_type, cmp_op_type, code)
+ || vcond_eq_icode_p (value_type, cmp_op_type, code);
}
/* Use the current target and options to initialize
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 35921e691f9..d6701df158c 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -3819,6 +3819,25 @@ can_compare_p (enum rtx_code code, machine_mode mode,
return 0;
}
+/* Return whether the backend can emit a vector comparison for code CODE,
+ comparing operands of mode CMP_OP_MODE and producing a result with
+ VALUE_MODE. */
+
+bool
+can_vcond_compare_p (enum rtx_code code, machine_mode value_mode,
+ machine_mode cmp_op_mode)
+{
+ enum insn_code icode;
+ bool unsigned_p = (code == LTU || code == LEU || code == GTU || code == GEU);
+ rtx reg1 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 1);
+ rtx reg2 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 2);
+ rtx test = alloca_rtx_fmt_ee (code, value_mode, reg1, reg2);
+
+ return (icode = get_vcond_icode (value_mode, cmp_op_mode, unsigned_p))
+ != CODE_FOR_nothing
+ && insn_operand_matches (icode, 3, test);
+}
+
/* This function is called when we are going to emit a compare instruction that
compares the values found in X and Y, using the rtl operator COMPARISON.
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 897bb5d4443..b1348ce85c9 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -242,6 +242,12 @@ enum can_compare_purpose
(without splitting it into pieces). */
extern int can_compare_p (enum rtx_code, machine_mode,
enum can_compare_purpose);
+
+/* Return whether the backend can emit a vector comparison for code CODE,
+ comparing operands of mode CMP_OP_MODE and producing a result with
+ VALUE_MODE. */
+extern bool can_vcond_compare_p (enum rtx_code, machine_mode, machine_mode);
+
extern rtx prepare_operand (enum insn_code, rtx, int, machine_mode,
machine_mode, int);
/* Emit a pair of rtl insns to compare two rtx's and to jump
diff --git a/gcc/opts.c b/gcc/opts.c
index efd75aade6c..2df03519192 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -527,6 +527,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_2_PLUS, OPT_ftree_tail_merge, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_vrp, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_CHEAP },
+ { OPT_LEVELS_2_PLUS, OPT_finline_functions, NULL, 1 },
/* -O2 and -Os optimizations. */
{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_functions, NULL, 1 },
@@ -542,9 +543,6 @@ static const struct default_options default_options_table[] =
#endif
/* -O3 and -Os optimizations. */
- /* Inlining of functions reducing size is a good idea with -Os
- regardless of them being declared inline. */
- { OPT_LEVELS_3_PLUS_AND_SIZE, OPT_finline_functions, NULL, 1 },
/* -O3 optimizations. */
{ OPT_LEVELS_3_PLUS, OPT_fgcse_after_reload, NULL, 1 },
diff --git a/gcc/params.def b/gcc/params.def
index 0acf29b6c4d..4cb48d9ab5b 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -51,8 +51,13 @@ DEFPARAM (PARAM_PREDICTABLE_BRANCH_OUTCOME,
DEFPARAM (PARAM_INLINE_MIN_SPEEDUP,
"inline-min-speedup",
+ "The minimal estimated speedup allowing inliner to ignore inline-insns-single and inline-insns-auto with -O3 and -Ofast.",
+ 15, 0, 100)
+
+DEFPARAM (PARAM_INLINE_MIN_SPEEDUP_O2,
+ "inline-min-speedup-O2",
"The minimal estimated speedup allowing inliner to ignore inline-insns-single and inline-insns-auto.",
- 15, 0, 0)
+ 30, 0, 100)
/* The single function inlining limit. This is the maximum size
of a function counted in internal gcc instructions (not in
@@ -67,9 +72,14 @@ DEFPARAM (PARAM_INLINE_MIN_SPEEDUP,
gets decreased. */
DEFPARAM (PARAM_MAX_INLINE_INSNS_SINGLE,
"max-inline-insns-single",
- "The maximum number of instructions in a single function eligible for inlining.",
+ "The maximum number of instructions in a single function eligible for inlining with -O3 and -Ofast.",
200, 0, 0)
+DEFPARAM (PARAM_MAX_INLINE_INSNS_SINGLE_O2,
+ "max-inline-insns-single-O2",
+ "The maximum number of instructions in a single function eligible for inlining.",
+ 30, 0, 0)
+
/* The single function inlining limit for functions that are
inlined by virtue of -finline-functions (-O3).
This limit should be chosen to be below or equal to the limit
@@ -79,14 +89,29 @@ DEFPARAM (PARAM_MAX_INLINE_INSNS_SINGLE,
The default value is 30. */
DEFPARAM (PARAM_MAX_INLINE_INSNS_AUTO,
"max-inline-insns-auto",
- "The maximum number of instructions when automatically inlining.",
+ "The maximum number of instructions when automatically inlining with -O3 and -Ofast.",
30, 0, 0)
+DEFPARAM (PARAM_MAX_INLINE_INSNS_AUTO_O2,
+ "max-inline-insns-auto-O2",
+ "The maximum number of instructions when automatically inlining.",
+ 15, 0, 0)
+
DEFPARAM (PARAM_MAX_INLINE_INSNS_SMALL,
"max-inline-insns-small",
"The maximum number of instructions when automatically inlining small functions.",
0, 0, 0)
+DEFPARAM (PARAM_INLINE_HEURISTICS_HINT_PERCENT,
+ "inline-heuristics-hint-percent",
+ "The scale (in percents) applied to inline-insns-single and auto limits when heuristics hints that inlining is very profitable with -O3 and -Ofast.",
+ 1600, 100, 1000000)
+
+DEFPARAM (PARAM_INLINE_HEURISTICS_HINT_PERCENT_O2,
+ "inline-heuristics-hint-percent-O2",
+ "The scale (in percents) applied to inline-insns-single and auto limits when heuristics hints that inlining is very profitable.",
+ 200, 100, 1000000)
+
DEFPARAM (PARAM_MAX_INLINE_INSNS_SIZE,
"max-inline-insns-size",
"The maximum number of instructions when inlining for size.",
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index b538b00459a..fc31485384b 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -185,12 +185,13 @@ range_operator::op2_range (value_range_base &r ATTRIBUTE_UNUSED,
}
-// Called when there is either an overflow OR an underflow... which
-// means an anti range must be created to compensate. This does not
-// cover the case where there are 2 possible overflows, or none.
+// Create and return a range from a pair of wide-ints that are known
+// to have overflowed (or underflowed).
static value_range_base
-adjust_overflow_bound (tree type, const wide_int &wmin, const wide_int &wmax)
+value_range_from_overflowed_bounds (tree type,
+ const wide_int &wmin,
+ const wide_int &wmax)
{
const signop sgn = TYPE_SIGN (type);
const unsigned int prec = TYPE_PRECISION (type);
@@ -216,15 +217,15 @@ adjust_overflow_bound (tree type, const wide_int &wmin, const wide_int &wmax)
return value_range_base (VR_ANTI_RANGE, type, tmin, tmax);
}
-// Given a newly calculated lbound and ubound, examine their
-// respective overflow bits to determine how to create a range.
-// Return said range.
+// Create and return a range from a pair of wide-ints. MIN_OVF and
+// MAX_OVF describe any overflow that might have occurred while
+// calculating WMIN and WMAX respectively.
static value_range_base
-create_range_with_overflow (tree type,
- const wide_int &wmin, const wide_int &wmax,
- wi::overflow_type min_ovf = wi::OVF_NONE,
- wi::overflow_type max_ovf = wi::OVF_NONE)
+value_range_with_overflow (tree type,
+ const wide_int &wmin, const wide_int &wmax,
+ wi::overflow_type min_ovf = wi::OVF_NONE,
+ wi::overflow_type max_ovf = wi::OVF_NONE)
{
const signop sgn = TYPE_SIGN (type);
const unsigned int prec = TYPE_PRECISION (type);
@@ -255,7 +256,7 @@ create_range_with_overflow (tree type,
if ((min_ovf == wi::OVF_UNDERFLOW && max_ovf == wi::OVF_NONE)
|| (max_ovf == wi::OVF_OVERFLOW && min_ovf == wi::OVF_NONE))
- return adjust_overflow_bound (type, wmin, wmax);
+ return value_range_from_overflowed_bounds (type, wmin, wmax);
// Other underflow and/or overflow, drop to VR_VARYING.
return value_range_base (type);
@@ -282,9 +283,9 @@ create_range_with_overflow (tree type,
}
}
-// Like above, but canonicalize the case where the bounds are swapped
-// and overflow may wrap. In which case, we transform [10,5] into
-// [MIN,5][10,MAX].
+// Create and return a range from a pair of wide-ints. Canonicalize
+// the case where the bounds are swapped. In which case, we transform
+// [10,5] into [MIN,5][10,MAX].
static inline value_range_base
create_possibly_reversed_range (tree type,
@@ -293,7 +294,7 @@ create_possibly_reversed_range (tree type,
signop s = TYPE_SIGN (type);
// If the bounds are swapped, treat the result as if an overflow occured.
if (wi::gt_p (new_lb, new_ub, s))
- return adjust_overflow_bound (type, new_lb, new_ub);
+ return value_range_from_overflowed_bounds (type, new_lb, new_ub);
// Otherwise its just a normal range.
return value_range_base (type, new_lb, new_ub);
@@ -907,7 +908,7 @@ operator_plus::wi_fold (tree type,
signop s = TYPE_SIGN (type);
wide_int new_lb = wi::add (lh_lb, rh_lb, s, &ov_lb);
wide_int new_ub = wi::add (lh_ub, rh_ub, s, &ov_ub);
- return create_range_with_overflow (type, new_lb, new_ub, ov_lb, ov_ub);
+ return value_range_with_overflow (type, new_lb, new_ub, ov_lb, ov_ub);
}
bool
@@ -954,7 +955,7 @@ operator_minus::wi_fold (tree type,
signop s = TYPE_SIGN (type);
wide_int new_lb = wi::sub (lh_lb, rh_ub, s, &ov_lb);
wide_int new_ub = wi::sub (lh_ub, rh_lb, s, &ov_ub);
- return create_range_with_overflow (type, new_lb, new_ub, ov_lb, ov_ub);
+ return value_range_with_overflow (type, new_lb, new_ub, ov_lb, ov_ub);
}
bool
@@ -994,7 +995,7 @@ operator_min::wi_fold (tree type,
signop s = TYPE_SIGN (type);
wide_int new_lb = wi::min (lh_lb, rh_lb, s);
wide_int new_ub = wi::min (lh_ub, rh_ub, s);
- return create_range_with_overflow (type, new_lb, new_ub);
+ return value_range_with_overflow (type, new_lb, new_ub);
}
@@ -1016,7 +1017,7 @@ operator_max::wi_fold (tree type,
signop s = TYPE_SIGN (type);
wide_int new_lb = wi::max (lh_lb, rh_lb, s);
wide_int new_ub = wi::max (lh_ub, rh_ub, s);
- return create_range_with_overflow (type, new_lb, new_ub);
+ return value_range_with_overflow (type, new_lb, new_ub);
}
@@ -1087,7 +1088,7 @@ cross_product_operator::wi_cross_product (tree type,
// Choose min and max from the ordered pairs.
wide_int res_lb = wi::min (cp1, cp3, sign);
wide_int res_ub = wi::max (cp2, cp4, sign);
- return create_range_with_overflow (type, res_lb, res_ub);
+ return value_range_with_overflow (type, res_lb, res_ub);
}
@@ -1832,7 +1833,7 @@ wi_optimize_and_or (value_range_base &r,
}
else
gcc_unreachable ();
- r = create_range_with_overflow (type, res_lb, res_ub);
+ r = value_range_with_overflow (type, res_lb, res_ub);
return true;
}
@@ -1932,7 +1933,7 @@ operator_bitwise_and::wi_fold (tree type,
if (wi::gt_p (new_lb, new_ub,sign))
return value_range_base (type);
- return create_range_with_overflow (type, new_lb, new_ub);
+ return value_range_with_overflow (type, new_lb, new_ub);
}
bool
@@ -2070,7 +2071,7 @@ operator_bitwise_or::wi_fold (tree type,
if (wi::gt_p (new_lb, new_ub,sign))
return value_range_base (type);
- return create_range_with_overflow (type, new_lb, new_ub);
+ return value_range_with_overflow (type, new_lb, new_ub);
}
bool
@@ -2132,7 +2133,7 @@ operator_bitwise_xor::wi_fold (tree type,
// If the range has all positive or all negative values, the result
// is better than VARYING.
if (wi::lt_p (new_lb, 0, sign) || wi::ge_p (new_ub, 0, sign))
- return create_range_with_overflow (type, new_lb, new_ub);
+ return value_range_with_overflow (type, new_lb, new_ub);
return value_range_base (type);
}
@@ -2186,7 +2187,7 @@ operator_trunc_mod::wi_fold (tree type,
tmp = wi::zero (prec);
new_ub = wi::min (new_ub, tmp, sign);
- return create_range_with_overflow (type, new_lb, new_ub);
+ return value_range_with_overflow (type, new_lb, new_ub);
}
@@ -2909,10 +2910,14 @@ range_tests ()
// If a range is in any way outside of the range for the converted
// to range, default to the range for the new type.
- r1 = value_range_base (integer_zero_node, maxint);
- range_cast (r1, short_integer_type_node);
- ASSERT_TRUE (r1.lower_bound () == wi::to_wide (minshort)
- && r1.upper_bound() == wi::to_wide (maxshort));
+ if (TYPE_PRECISION (TREE_TYPE (maxint))
+ > TYPE_PRECISION (short_integer_type_node))
+ {
+ r1 = value_range_base (integer_zero_node, maxint);
+ range_cast (r1, short_integer_type_node);
+ ASSERT_TRUE (r1.lower_bound () == wi::to_wide (minshort)
+ && r1.upper_bound() == wi::to_wide (maxshort));
+ }
// (unsigned char)[-5,-1] => [251,255].
r0 = rold = value_range_base (SCHAR (-5), SCHAR (-1));
@@ -3019,11 +3024,15 @@ range_tests ()
// "NOT 0 at signed 32-bits" ==> [-MIN_32,-1][1, +MAX_32]. This is
// is outside of the range of a smaller range, return the full
// smaller range.
- r0 = range_nonzero (integer_type_node);
- range_cast (r0, short_integer_type_node);
- r1 = value_range_base (TYPE_MIN_VALUE (short_integer_type_node),
- TYPE_MAX_VALUE (short_integer_type_node));
- ASSERT_TRUE (r0 == r1);
+ if (TYPE_PRECISION (integer_type_node)
+ > TYPE_PRECISION (short_integer_type_node))
+ {
+ r0 = range_nonzero (integer_type_node);
+ range_cast (r0, short_integer_type_node);
+ r1 = value_range_base (TYPE_MIN_VALUE (short_integer_type_node),
+ TYPE_MAX_VALUE (short_integer_type_node));
+ ASSERT_TRUE (r0 == r1);
+ }
// Casting NONZERO from a narrower signed to a wider signed.
//
diff --git a/gcc/reginfo.c b/gcc/reginfo.c
index 6bed844ac94..9813bab025c 100644
--- a/gcc/reginfo.c
+++ b/gcc/reginfo.c
@@ -731,8 +731,8 @@ globalize_reg (tree decl, int i)
if (i != STACK_POINTER_REGNUM)
{
SET_HARD_REG_BIT (regs_invalidated_by_call, i);
- for (unsigned int i = 0; i < NUM_ABI_IDS; ++i)
- function_abis[i].add_full_reg_clobber (i);
+ for (unsigned int j = 0; j < NUM_ABI_IDS; ++j)
+ function_abis[j].add_full_reg_clobber (i);
}
/* If already fixed, nothing else to do. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 834ee454f9a..4555fc87f9f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,329 @@
+2019-10-08 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/torture/builtin-fp-int-inexact-c2x.c: New test.
+
+2019-10-07 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * gcc.target/msp430/430x-insns.c: New test.
+ * gcc.target/msp430/data-attributes-2.c: Remove dg-warning
+ directives for conflicts between the "section" and "lower" attributes.
+ * gcc.target/msp430/msp430.exp
+ (check_effective_target_msp430_region_not_lower): New.
+ (check_effective_target_msp430_region_lower): New.
+ * gcc.target/msp430/object-attributes-430.c: New test.
+ * gcc.target/msp430/object-attributes-default.c: New test.
+ * gcc.target/msp430/object-attributes-mlarge-any-region.c: New test.
+ * gcc.target/msp430/object-attributes-mlarge.c: New test.
+
+2019-10-07 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.target/i386/pr71801.c (uuidcache_init): Fix up size of d array.
+
+2019-10-07 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/diagnostic/not-a-function-template-1.C: New.
+ * g++.dg/template/crash107.C: Adjust expected location.
+ * g++.dg/template/dependent-expr1.C: Check locations.
+ * g++.dg/template/error17.C: Check location.
+
+2019-10-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/91994
+ * gcc.target/i386/pr91994.c: New test.
+
+2019-10-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/91975
+ * g++.dg/tree-ssa/ivopts-3.C: Adjust.
+ * gcc.dg/vect/vect-profile-1.c: Disable cunrolli.
+ * gcc.dg/vect/vect-double-reduc-6.c: Disable unrolling of
+ the innermost loop.
+ * gcc.dg/vect/vect-93.c: Likewise.
+ * gcc.dg/vect/vect-105.c: Likewise.
+ * gcc.dg/vect/pr79920.c: Likewise.
+ * gcc.dg/vect/no-vfa-vect-102.c: Likewise.
+ * gcc.dg/vect/no-vfa-vect-101.c: Likewise.
+ * gcc.dg/vect/pr83202-1.c: Operate on a larger array.
+ * gfortran.dg/vect/vect-8.f90: Likewise.
+ * gcc.dg/tree-ssa/cunroll-2.c: Scan early unrolling dump instead
+ of late one.
+
+2019-10-05 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/47045
+ * gfortran.dg/pr47054_1.f90: New test
+ * gfortran.dg/pr47054_2.f90: Ditto.
+
+2019-10-05 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/91497
+ * gfortran.dg/pr91497.f90: Run on i?86-*-* and x86_64-*-* only.
+
+2019-10-05 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/91926
+ * gfortran.dg/ISO_Fortran_binding_13.f90 : New test.
+ * gfortran.dg/ISO_Fortran_binding_13.c : Additional source.
+ * gfortran.dg/ISO_Fortran_binding_14.f90 : New test.
+
+2019-10-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/91369 - Implement P0784R7: constexpr new
+ * g++.dg/cpp0x/constexpr-delete2.C: Adjust expected diagnostics for
+ c++2a.
+ * g++.dg/cpp0x/locations1.C: Only expect constexpr ~S() diagnostics
+ in c++17_down, adjust expected wording.
+ * g++.dg/cpp1y/constexpr-new.C: Only expect diagnostics in c++17_down.
+ * g++.dg/cpp2a/constexpr-dtor1.C: New test.
+ * g++.dg/cpp2a/constexpr-dtor2.C: New test.
+ * g++.dg/cpp2a/constexpr-dtor3.C: New test.
+ * g++.dg/cpp2a/constexpr-new1.C: New test.
+ * g++.dg/cpp2a/constexpr-new2.C: New test.
+ * g++.dg/cpp2a/constexpr-new3.C: New test.
+ * g++.dg/cpp2a/constexpr-new4.C: New test.
+ * g++.dg/cpp2a/feat-cxx2a.C: Add __cpp_constinit and
+ __cpp_constexpr_dynamic_alloc tests. Tweak __cpp_* tests for c++2a
+ features to use style like older features, including #ifdef test.
+ * g++.dg/ext/is_literal_type3.C: New test.
+
+ PR tree-optimization/91734
+ * gcc.dg/pr91734.c: New test.
+
+2019-10-04 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/82752
+ * gcc.dg/format/c2x-strftime-1.c: New test.
+
+2019-10-04 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/91977
+ * gcc.dg/Wstringop-overflow-18.c: New test.
+
+2019-10-04 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/Wstringop-overflow-17.c: New test.
+
+2019-10-04 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran.91959
+ * gfortran.dg/pr91959.f90: New test.
+
+2019-10-04 Rafael Tsuha <rafael.tsuha@usp.br>
+
+ * gcc.dg/sinhovercosh-1.c: New test.
+
+2019-10-04 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/c11-builtins-1.c, gcc.dg/c2x-builtins-1.c,
+ gcc.dg/dfp/c2x-builtins-dfp-1.c: New tests.
+
+2019-10-04 Mark Eggleston <mark.eggleston@codethink.com>
+
+ * gfortran.dg/auto_in_equiv_1.f90: Replaced.
+ * gfortran.dg/auto_in_equiv_2.f90: Replaced.
+ * gfortran.dg/auto_in_equiv_3.f90: Deleted.
+
+2019-10-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/torture/simd-abi-8.c: Use -mlittle-endian.
+ Check that there are no Q register saves or restores.
+
+2019-10-04 Richard Biener <rguenther@suse.de>
+
+ * gcc.c-torture/execute/loop-3.c: Fix undefined behavior.
+
+2019-10-04 Yuliang Wang <yuliang.wang@arm.com>
+
+ * gcc.target/aarch64/sve2/shracc_1.c: Tighten scan-assembler-nots
+ to avoid matching scalar code.
+
+2019-10-04 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/use_without_only_1.f90: Update column num in dg-warning.
+
+2019-10-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/71504
+ * g++.dg/cpp0x/constexpr-array21.C: New test.
+ * g++.dg/cpp1y/constexpr-array7.C: New test.
+ * g++.dg/cpp1z/constexpr-array1.C: New test.
+
+2019-10-04 Jason Merrill <jason@redhat.com>
+
+ PR c++/71504
+ * g++.dg/cpp0x/constexpr-array20.C: New test.
+
+2019-10-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/91974
+ * g++.dg/cpp1z/eval-order5.C: New test.
+
+2019-10-03 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/91497
+ * gfortran.dg/pr91497.f90: New test.
+
+2019-10-03 Jan Hubicka <hubicka@ucw.cz>
+
+ * g++.dg/tree-ssa/pr61034.C: Add --param max-inline-insns-single-O2=200.
+
+2019-10-03 Dragan Mladjenovic <dmladjenovic@wavecomp.com>
+
+ PR target/91769
+ * gcc.target/mips/pr91769.c: New test.
+
+2019-10-03 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * g++.dg/cpp0x/gen-attrs-67.C: Expect constructor priorities error
+ on any !init_priority target.
+
+2019-10-03 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/84487
+ * gfortran.dg/typebound_call_22.f03: xfail.
+
+2019-10-03 Mark Eggleston <mark.eggleston@codethink.com>
+
+ * gfortran.dg/bad_operands.f90: New test.
+ * gfortran.dg/character mismatch.f90: New test.
+ * gfortran.dg/compare_interfaces.f90: New test.
+ * gfortran.dg/hollerith_to_char_parameter_1.f90: New test.
+ * gfortran.dg/hollerith_to_char_parameter_2.f90: New test.
+ * gfortran.dg/widechar_intrinsics_1.f90: Checked for specific character
+ type names instead of "Type of argument".
+ * gfortran.dg/widechar_intrinsics_2.f90: Checked for specific character
+ type names instead of "Type of argument".
+ * gfortran.dg/widechar_intrinsics_3.f90: Checked for specific character
+ type names instead of "Type of argument".
+
+2019-10-02 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/cr-decimal-dig-2.c: New test.
+ * gcc.dg/limits-width-2.c: New test. Based on limits-width-1.c.
+ * gcc.dg/stdint-width-2.c: New test. Based on stdint-width-1.c.
+
+2019-10-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/diagnostic/integral-array-size-1.C: New.
+ * g++.dg/cpp0x/alias-decl-1.C: Test location(s) too.
+ * g++.dg/init/new43.C: Likewise.
+ * g++.dg/lookup/friend12.C: Likewise.
+ * g++.dg/lookup/pr79766.C: Likewise.
+ * g++.dg/lookup/pr84375.C: Likewise.
+ * g++.dg/other/new-size-type.C: Likewise.
+
+2019-10-03 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/ext/constexpr-attr-cleanup1.C: New test.
+
+2019-10-02 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/80936
+ * gcc.dg/Wnonnull-2.c: New test.
+ * gcc.dg/Wnonnull-3.c: New test.
+ * gcc.dg/nonnull-3.c: Expect more warnings.
+
+2019-10-02 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/91784
+ * gfortran.dg/pr91784.f90: New test.
+
+2019-10-02 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/91785
+ * gfortran.dg/pr91785.f90: New test.
+
+2019-10-02 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/91942
+ * gfortran.dg/pr91587.f90: Update dg-error regex.
+ * gfortran.dg/pr91942.f90: New test.
+
+2019-10-02 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/91943
+ gfortran.dg/pr91943.f90
+
+2019-10-02 Jan Hubicka <hubicka@ucw.cz>
+
+ * g++.dg/tree-ssa/pr53844.C: Add -fno-inline-functions --param
+ max-inline-insns-single-O2=200.
+ * gcc.c-torture/execute/builtins/builtins.exp: Add
+ -fno-inline-functions to additional_flags.
+ * gcc.dg/ipa/inline-7.c: Add -fno-inline-functions.
+ * gcc.dg/optimize-bswapsi-5.c: Add -fno-inline-functions.
+ * gcc.dg/tree-ssa/ssa-thread-12.c: Add --param
+ early-inlining-insns-O2=14 -fno-inline-functions; revert previous
+ change.
+ * gcc.dg/winline-3.c: Use --param max-inline-insns-single-O2=1
+ --param inline-min-speedup-O2=100
+ instead of --param max-inline-insns-single=1 --param
+ inline-min-speedup=100
+
+2019-10-02 Alexander Monakov <amonakov@ispras.ru>
+
+ PR rtl-optimization/87047
+ * gcc.dg/pr87047.c: New test.
+
+2019-10-02 Martin Jambor <mjambor@suse.cz>
+
+ PR testsuite/91842
+ * gcc.dg/ipa/ipa-sra-19.c: Skip on powerpc.
+
+2019-10-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/opt82.adb: New test.
+ * gnat.dg/opt82_pkg.ads: New helper.
+
+2019-10-02 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/mips/call-clobbered-3.c: Remove skip for -Os.
+ * gcc.target/mips/call-clobbered-4.c: Delete.
+
+2019-10-02 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/gomp/is_device_ptr-1.f90: New.
+
+2019-10-02 Richard Biener <rguenther@suse.de>
+
+ PR c++/91606
+ * g++.dg/torture/pr91606.C: New testcase.
+
+2019-10-02 Tobias Burnus <tobias@codesourcery.com>
+
+ * gfortran.dg/goacc/asyncwait-1.f95: Handle new error message.
+ * gfortran.dg/goacc/asyncwait-2.f95: Likewise.
+ * gfortran.dg/goacc/asyncwait-3.f95: Likewise.
+ * gfortran.dg/goacc/asyncwait-4.f95: Likewise.
+ * gfortran.dg/goacc/default-2.f: Likewise.
+ * gfortran.dg/goacc/enter-exit-data.f95: Likewise.
+ * gfortran.dg/goacc/if.f95: Likewise.
+ * gfortran.dg/goacc/list.f95: Likewise.
+ * gfortran.dg/goacc/literal.f95: Likewise.
+ * gfortran.dg/goacc/loop-2-kernels-tile.f95: Likewise.
+ * gfortran.dg/goacc/loop-2-parallel-tile.f95: Likewise.
+ * gfortran.dg/goacc/loop-7.f95: Likewise.
+ * gfortran.dg/goacc/parallel-kernels-clauses.f95: Likewise.
+ * gfortran.dg/goacc/routine-6.f90: Likewise.
+ * gfortran.dg/goacc/several-directives.f95: Likewise.
+ * gfortran.dg/goacc/sie.f95: Likewise.
+ * gfortran.dg/goacc/tile-1.f90: Likewise.
+ * gfortran.dg/goacc/update-if_present-2.f90: Likewise.
+ * gfortran.dg/gomp/declare-simd-1.f90: Likewise.
+ * gfortran.dg/gomp/pr29759.f90: Likewise.
+
+2019-10-02 Tobias Burnus <tobias@codesourcery.com>
+
+ * libgomp/testsuite/libgomp.fortran/use_device_ptr-optional-1.f90: New.
+
+2019-10-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/91940
+ * gcc.dg/vect/vect-bswap16.c: Add -msse4 on x86, run on all targets,
+ expect vectorized 1 loops message on both vect_bswap and sse4_runtime
+ targets.
+ * gcc.dg/vect/vect-bswap16a.c: New test.
+
2019-10-02 Joseph Myers <joseph@codesourcery.com>
* gcc.dg/asm-scope-1.c, gcc.dg/cpp/c11-scope-1.c,
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
index 43284d76978..24b05209223 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
@@ -12,5 +12,5 @@ template<class U> struct Ptr<U*> {}; // { dg-error "specialization" }
struct A {
using A = int; // { dg-error "11:ISO C\\+\\+ forbids nested type .A." }
-// { dg-error "same name as" "" { target c++11 } .-1 }
+// { dg-error "11:.using A = int. has the same name as" "" { target c++11 } .-1 }
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array20.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array20.C
new file mode 100644
index 00000000000..217bbf4efb7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array20.C
@@ -0,0 +1,15 @@
+// PR c++/71504
+// { dg-do compile { target c++11 } }
+
+enum E { e };
+
+constexpr bool arr[1][1] = {{true}};
+
+template<E x, E y>
+void check() {
+ static_assert(arr[x][y], "");
+}
+
+int main() {
+ check<e, e>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array21.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array21.C
new file mode 100644
index 00000000000..e085098445a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array21.C
@@ -0,0 +1,27 @@
+// PR c++/71504
+// { dg-do compile { target c++11 } }
+
+typedef const char A4 [10];
+
+constexpr A4 a [] = { "123", "123456", "123456789" };
+
+constexpr int len (const char *s)
+{
+ return *s ? 1 + len (s + 1) : 0;
+}
+
+constexpr const char *s = a[0];
+constexpr const char *t = (a + 2)[-2];
+
+constexpr int n0 = len (s);
+constexpr int n1 = len (t);
+
+constexpr int n2 = len (a[0]);
+constexpr int n3 = len ((a + 2)[-2]);
+
+#define A(e) static_assert ((e), #e)
+
+A (n0 == 3);
+A (n0 == n1);
+A (n0 == n2);
+A (n0 == n3);
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-delete2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-delete2.C
index 4a453a4d361..999f9b7851e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-delete2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-delete2.C
@@ -5,8 +5,9 @@ struct A { ~A(); };
constexpr int f(int i) { return i; }
constexpr int g(A* ap)
{
- return f((delete[] ap, 42)); // { dg-message "" }
+ return f((delete[] ap, 42)); // { dg-message "" "" { target c++17_down } }
}
A a;
constexpr int i = g(&a); // { dg-error "" }
+ // { dg-message "in 'constexpr' expansion of" "" { target c++2a } .-1 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-67.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-67.C
index 5d151cc1bdc..3dd3a1fdc7e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-67.C
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-67.C
@@ -8,4 +8,4 @@
[[nodiscard()]] int f4(); // { dg-error ".nodiscard. attribute does not take any arguments" }
[[gnu::noinline()]] int f5(); // { dg-error ".noinline. attribute does not take any arguments" }
[[gnu::constructor]] int f6();
-[[gnu::constructor(101)]] int f7(); // { dg-error "constructor priorities are not supported" "" { target *-*-darwin* } }
+[[gnu::constructor(101)]] int f7(); // { dg-error "constructor priorities are not supported" "" { target { ! init_priority } } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/locations1.C b/gcc/testsuite/g++.dg/cpp0x/locations1.C
index 6de0368fcbc..62a72ea2804 100644
--- a/gcc/testsuite/g++.dg/cpp0x/locations1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/locations1.C
@@ -11,7 +11,7 @@ struct S
{
virtual S(); // { dg-error "3:constructors cannot be declared .virtual." }
constexpr int s = 1; // { dg-error "3:non-static data member .s. declared .constexpr." }
- constexpr ~S(); // { dg-error "3:a destructor cannot be .constexpr." }
+ constexpr ~S(); // { dg-error "3:'constexpr' destructors only available with" "" { target c++17_down } }
};
typedef constexpr int my_int; // { dg-error "9:.constexpr. cannot appear in a typedef declaration" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-array7.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-array7.C
new file mode 100644
index 00000000000..30bd8fd023b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-array7.C
@@ -0,0 +1,16 @@
+// PR c++/71504
+// { dg-do compile { target c++14 } }
+
+template <typename A>
+constexpr auto
+sum (A const &a)
+{
+ int tot = 0;
+ for (auto &row : a)
+ for (auto elem : row)
+ tot += elem;
+ return tot;
+}
+
+constexpr int const a22[2][2] = {{1,2},{3,4}};
+static_assert (sum(a22) == 10, "badsum");
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C
index 9e300b9a866..90cb42595c4 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C
@@ -4,7 +4,7 @@ constexpr int *f4(bool b) {
if (b) {
return nullptr;
} else {
- return new int{42}; // { dg-error "call to non-.constexpr." }
+ return new int{42}; // { dg-error "call to non-.constexpr." "" { target c++17_down } }
}
}
static_assert(f4(true) == nullptr, "");
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-array1.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-array1.C
new file mode 100644
index 00000000000..02435d505de
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-array1.C
@@ -0,0 +1,46 @@
+// PR c++/71504
+// { dg-do compile { target c++17 } }
+
+typedef __SIZE_TYPE__ size_t;
+template <typename T, T v>
+struct integral_constant
+{
+ static constexpr T value = v;
+ typedef T value_type;
+ typedef integral_constant<T, v> type;
+ constexpr operator value_type () const noexcept { return value; }
+ constexpr value_type operator() () const noexcept { return value; }
+};
+template <typename T, T v>
+constexpr T integral_constant<T, v>::value;
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+template <typename>
+struct is_array : public false_type { };
+template <typename T, size_t s>
+struct is_array<T[s]> : public true_type { };
+template <typename T>
+struct is_array<T[]> : public true_type { };
+template <bool, typename, typename>
+struct conditional;
+template <bool C, typename T, typename F>
+struct conditional { typedef T type; };
+template <typename T, typename F>
+struct conditional<false, T, F> { typedef F type; };
+template <typename T>
+struct array_ref;
+template <typename T>
+using ref_t = typename conditional<is_array<T>::value, array_ref<T>, T&>::type;
+template <typename T, unsigned N>
+struct array_ref<T[N]>
+{
+ T *a;
+ using const_reference = const ref_t<T>;
+ constexpr const_reference operator[] (unsigned I) const { return {a[I]}; }
+};
+template <typename A>
+array_ref (A&) -> array_ref<A>;
+constexpr int a2[2] = {1,2};
+static_assert (array_ref{a2}[0] == 1);
+constexpr int a22[2][2] = {{1,2},{3,4}};
+static_assert (array_ref{a22}[0][0] == 1);
diff --git a/gcc/testsuite/g++.dg/cpp1z/eval-order5.C b/gcc/testsuite/g++.dg/cpp1z/eval-order5.C
new file mode 100644
index 00000000000..a8f06ed421a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/eval-order5.C
@@ -0,0 +1,31 @@
+// PR c++/91974
+// { dg-do run }
+// { dg-options "-fstrong-eval-order" }
+
+extern "C" void abort ();
+
+bool ok = false;
+
+void
+foo (int x)
+{
+ if (x != 0)
+ abort ();
+ ok = true;
+}
+
+void
+bar (int)
+{
+ abort ();
+}
+
+int
+main ()
+{
+ typedef void (*T) (int);
+ T fn = foo;
+ fn ((fn = bar, 0));
+ if (fn != bar || !ok)
+ abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor1.C
new file mode 100644
index 00000000000..a2ea6bfb338
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor1.C
@@ -0,0 +1,9 @@
+// P0784R7
+// { dg-do compile { target c++11 } }
+
+struct S
+{
+ constexpr S () : s (0) {}
+ constexpr ~S () {} // { dg-error "'constexpr' destructors only available with" "" { target c++17_down } }
+ int s;
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor2.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor2.C
new file mode 100644
index 00000000000..397cfb0f1a1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor2.C
@@ -0,0 +1,66 @@
+// P0784R7
+// { dg-do compile { target c++2a } }
+
+struct S
+{
+ constexpr S () : r (4), s (3) { --r; s -= 2; }
+ constexpr ~S () { if (s == 1) s = 0; else asm (""); if (s == 0 && r == 3) r = 0; else asm (""); }
+ int r, s;
+};
+struct T : public S
+{
+ constexpr T () : t (2) {}
+ int t;
+ S u;
+};
+struct U : public S
+{
+ constexpr U (int x) : u (x) {}
+ constexpr ~U () = default;
+ int u;
+ S v;
+};
+
+constexpr S a;
+constexpr T b;
+constexpr U c = 3;
+static_assert (a.s == 1 && a.r == 3);
+static_assert (b.s == 1 && b.r == 3 && b.t == 2 && b.u.s == 1 && b.u.r == 3);
+static_assert (c.s == 1 && c.r == 3 && c.u == 3 && c.v.s == 1 && c.v.r == 3);
+
+void
+foo ()
+{
+ static constexpr S d;
+ static constexpr T e;
+ static constexpr U f = 4;
+ static_assert (d.s == 1 && d.r == 3);
+ static_assert (e.s == 1 && e.r == 3 && e.t == 2 && e.u.s == 1 && e.u.r == 3);
+ static_assert (f.s == 1 && f.r == 3 && f.u == 4 && f.v.s == 1 && f.v.r == 3);
+ if (1)
+ {
+ constexpr S g;
+ constexpr T h;
+ constexpr U i = 5;
+ static_assert (g.s == 1 && g.r == 3);
+ static_assert (h.s == 1 && h.r == 3 && h.t == 2 && h.u.s == 1 && h.u.r == 3);
+ static_assert (i.s == 1 && i.r == 3 && i.u == 5 && i.v.s == 1 && i.v.r == 3);
+ }
+}
+
+constexpr bool
+bar ()
+{
+ S j;
+ T k;
+ U l = 6;
+ if (j.s != 1 || j.r != 3)
+ return false;
+ if (k.s != 1 || k.r != 3 || k.t != 2 || k.u.s != 1 || k.u.r != 3)
+ return false;
+ if (l.s != 1 || l.r != 3 || l.u != 6 || l.v.s != 1 || l.v.r != 3)
+ return false;
+ return true;
+}
+
+static_assert (bar ());
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C
new file mode 100644
index 00000000000..dcfa4e6caf2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C
@@ -0,0 +1,185 @@
+// P0784R7
+// { dg-do compile { target c++2a } }
+
+struct S
+{
+ constexpr S () : s (0) {}
+ constexpr ~S () {}
+ int s;
+};
+struct T // { dg-message "'T' is not literal because" }
+{ // { dg-message "'T' does not have 'constexpr' destructor" "" { target *-*-* } .-1 }
+ constexpr T () : t (0) {}
+ ~T () {} // { dg-message "defaulted destructor calls non-'constexpr' 'T::~T\\(\\)'" }
+ int t;
+};
+struct U : public S
+{
+ constexpr U () : u (0) {}
+ constexpr ~U () = default; // { dg-error "explicitly defaulted function 'constexpr U::~U\\(\\)' cannot be declared 'constexpr' because the implicit declaration is not 'constexpr'" }
+ int u;
+ T t;
+};
+struct V : virtual public S
+{
+ V () : v (0) {}
+ constexpr ~V () = default; // { dg-error "explicitly defaulted function 'constexpr V::~V\\(\\)' cannot be declared 'constexpr' because the implicit declaration is not 'constexpr'" }
+ int v;
+};
+struct W0
+{
+ constexpr W0 () : w (0) {}
+ constexpr W0 (int x) : w (x) {}
+ constexpr ~W0 () { if (w == 5) asm (""); w = 3; }
+ int w;
+};
+struct W1
+{
+ constexpr W1 () : w (0) {}
+ constexpr W1 (int x) : w (x) {}
+ constexpr ~W1 () { if (w == 5) asm (""); w = 3; } // { dg-error "inline assembly is not a constant expression" }
+ // { dg-message "only unevaluated inline assembly is allowed in a 'constexpr' function" "" { target *-*-* } .-1 }
+ int w;
+};
+struct W2
+{
+ constexpr W2 () : w (0) {}
+ constexpr W2 (int x) : w (x) {}
+ constexpr ~W2 () { if (w == 5) asm (""); w = 3; } // { dg-error "inline assembly is not a constant expression" }
+ // { dg-message "only unevaluated inline assembly is allowed in a 'constexpr' function" "" { target *-*-* } .-1 }
+ int w;
+};
+struct W3
+{
+ constexpr W3 () : w (0) {}
+ constexpr W3 (int x) : w (x) {}
+ constexpr ~W3 () { if (w == 5) asm (""); w = 3; } // { dg-error "inline assembly is not a constant expression" }
+ // { dg-message "only unevaluated inline assembly is allowed in a 'constexpr' function" "" { target *-*-* } .-1 }
+ int w;
+};
+struct W4
+{
+ constexpr W4 () : w (0) {}
+ constexpr W4 (int x) : w (x) {}
+ constexpr ~W4 () { if (w == 5) asm (""); w = 3; } // { dg-error "inline assembly is not a constant expression" }
+ // { dg-message "only unevaluated inline assembly is allowed in a 'constexpr' function" "" { target *-*-* } .-1 }
+ int w;
+};
+struct W5
+{
+ constexpr W5 () : w (0) {}
+ constexpr W5 (int x) : w (x) {}
+ constexpr ~W5 () { if (w == 5) asm (""); w = 3; } // { dg-error "inline assembly is not a constant expression" }
+ // { dg-message "only unevaluated inline assembly is allowed in a 'constexpr' function" "" { target *-*-* } .-1 }
+ int w;
+};
+struct W6
+{
+ constexpr W6 () : w (0) {}
+ constexpr W6 (int x) : w (x) {}
+ constexpr ~W6 () { if (w == 5) asm (""); w = 3; } // { dg-error "inline assembly is not a constant expression" }
+ // { dg-message "only unevaluated inline assembly is allowed in a 'constexpr' function" "" { target *-*-* } .-1 }
+ int w;
+};
+struct W7
+{
+ constexpr W7 () : w (0) {}
+ constexpr W7 (int x) : w (x) {}
+ constexpr ~W7 () { if (w == 5) asm (""); w = 3; } // { dg-error "inline assembly is not a constant expression" }
+ // { dg-message "only unevaluated inline assembly is allowed in a 'constexpr' function" "" { target *-*-* } .-1 }
+ int w;
+};
+struct W8
+{
+ constexpr W8 () : w (0) {}
+ constexpr W8 (int x) : w (x) {}
+ constexpr ~W8 () { if (w == 5) asm (""); w = 3; } // { dg-error "inline assembly is not a constant expression" }
+ // { dg-message "only unevaluated inline assembly is allowed in a 'constexpr' function" "" { target *-*-* } .-1 }
+ int w;
+};
+struct X : public T
+{
+ constexpr X () : x (0) {}
+ constexpr ~X () = default; // { dg-error "explicitly defaulted function 'constexpr X::~X\\(\\)' cannot be declared 'constexpr' because the implicit declaration is not 'constexpr'" }
+ int x;
+};
+constexpr S s;
+constexpr T t; // { dg-error "the type 'const T' of 'constexpr' variable 't' is not literal" }
+constexpr W0 w1;
+constexpr W0 w2 = 12;
+constexpr W1 w3 = 5; // { dg-message "in 'constexpr' expansion of" }
+constexpr W0 w4[3] = { 1, 2, 3 };
+constexpr W2 w5[3] = { 4, 5, 6 }; // { dg-message "in 'constexpr' expansion of" }
+
+void
+f1 ()
+{
+ constexpr S s2;
+ constexpr W0 w6;
+ constexpr W0 w7 = 12;
+ constexpr W3 w8 = 5; // { dg-message "in 'constexpr' expansion of" }
+ constexpr W0 w9[3] = { 1, 2, 3 };
+ constexpr W4 w10[3] = { 4, 5, 6 }; // { dg-message "in 'constexpr' expansion of" }
+}
+
+constexpr int
+f2 ()
+{
+ constexpr S s3;
+ constexpr W0 w11;
+ constexpr W0 w12 = 12;
+ constexpr W5 w13 = 5; // { dg-message "in 'constexpr' expansion of" }
+ constexpr W0 w14[3] = { 1, 2, 3 };
+ constexpr W6 w15[3] = { 4, 5, 6 }; // { dg-message "in 'constexpr' expansion of" }
+ return 0;
+}
+
+constexpr int
+f3 ()
+{
+ S s3;
+ W0 w11;
+ W0 w12 = 12;
+ W0 w14[3] = { 1, 2, 3 };
+ return 0;
+}
+
+constexpr int x3 = f3 ();
+
+constexpr int
+f4 ()
+{
+ W7 w13 = 5;
+ return 0;
+}
+
+constexpr int x4 = f4 (); // { dg-message "in 'constexpr' expansion of" }
+
+constexpr int
+f5 ()
+{
+ W8 w15[3] = { 4, 5, 6 }; // { dg-message "in 'constexpr' expansion of" }
+ return 0;
+}
+
+constexpr int x5 = f5 (); // { dg-message "in 'constexpr' expansion of" }
+
+void
+f6 ()
+{
+ constexpr T t2; // { dg-error "the type 'const T' of 'constexpr' variable 't2' is not literal" }
+}
+
+constexpr int
+f7 ()
+{
+ constexpr T t3; // { dg-error "the type 'const T' of 'constexpr' variable 't3' is not literal" }
+ return 0;
+}
+
+constexpr int
+f8 ()
+{
+ T t4; // { dg-error "variable 't4' of non-literal type 'T' in 'constexpr' function" }
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new1.C
new file mode 100644
index 00000000000..873edd4d231
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new1.C
@@ -0,0 +1,39 @@
+// P0784R7
+// { dg-do compile { target c++2a } }
+
+struct S { constexpr S () : s (5) {} constexpr S (int x) : s (x) {} int s; };
+
+constexpr bool
+foo ()
+{
+ int r = 0;
+ S *p = new S ();
+ p->s += 3;
+ r += p->s;
+ delete p;
+ p = new S (12);
+ p->s = p->s * 2;
+ r += p->s;
+ delete p;
+ int *q = new int;
+ *q = 25;
+ r += *q;
+ delete q;
+ q = new int (1);
+ r += *q;
+ if (!q)
+ return false;
+ delete q;
+ q = new int[5]{1,2,3,4,5};
+ r += q[0] + q[4];
+ delete[] q;
+ q = new int[4];
+ q[0] = 6;
+ q[1] = 7;
+ q[3] = 8;
+ r += q[0] + q[1] + q[3];
+ delete[] q;
+ return r == 5 + 3 + 2 * 12 + 25 + 1 + 1 + 5 + 6 + 7 + 8;
+}
+constexpr bool a = foo ();
+static_assert (a);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new2.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new2.C
new file mode 100644
index 00000000000..be5496293b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new2.C
@@ -0,0 +1,21 @@
+// P0784R7
+// { dg-do compile { target c++2a } }
+
+template <int N>
+constexpr bool
+foo (const char (&x)[N])
+{
+ int **p = new int *[N];
+ for (int i = 0; i < N; i++)
+ p[i] = new int (x[i]);
+ for (int i = 0; i < N; i++)
+ if (*p[i] != x[i])
+ return false;
+ for (int i = 0; i < N; ++i)
+ delete p[i];
+ delete[] p;
+ return true;
+}
+
+constexpr bool a = foo ("foobar");
+static_assert (a);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C
new file mode 100644
index 00000000000..3380df74468
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C
@@ -0,0 +1,73 @@
+// P0784R7
+// { dg-do compile { target c++2a } }
+
+constexpr int *
+f1 ()
+{
+ return new int (2); // { dg-error "is not a constant expression because it refers to a result of" }
+}
+
+constexpr auto v1 = f1 ();
+
+constexpr bool
+f2 ()
+{
+ int *p = new int (3); // { dg-error "is not a constant expression because allocated storage has not been deallocated" }
+ return false;
+}
+
+constexpr auto v2 = f2 ();
+
+constexpr bool
+f3 ()
+{
+ int *p = new int (3);
+ int *q = p;
+ delete p;
+ delete q; // { dg-error "deallocation of already deallocated storage" }
+ return false;
+}
+
+constexpr auto v3 = f3 (); // { dg-message "in 'constexpr' expansion of" }
+
+constexpr bool
+f4 (int *p)
+{
+ delete p; // { dg-error "deallocation of storage that was not previously allocated" }
+ return false;
+}
+
+int q;
+constexpr auto v4 = f4 (&q); // { dg-message "in 'constexpr' expansion of" }
+
+constexpr bool
+f5 ()
+{
+ int *p = new int; // { dg-message "allocated here" }
+ return *p == 1;
+}
+
+constexpr auto v5 = f5 (); // { dg-error "the content of uninitialized storage is not usable in a constant expression" }
+ // { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 }
+
+constexpr bool
+f6 ()
+{
+ int *p = new int (2); // { dg-message "allocated here" }
+ int *q = p;
+ delete p;
+ return *q == 2;
+}
+
+constexpr auto v6 = f6 (); // { dg-error "use of allocated storage after deallocation in a constant expression" }
+ // { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 }
+
+constexpr int *
+f7 ()
+{
+ int *p = new int (2); // { dg-error "is not a constant expression because it refers to a result of" }
+ delete p;
+ return p;
+}
+
+constexpr auto v7 = f7 ();
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new4.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new4.C
new file mode 100644
index 00000000000..6cac9835463
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new4.C
@@ -0,0 +1,29 @@
+// P0784R7
+// { dg-do compile { target c++2a } }
+
+struct S
+{
+ constexpr S () : s (0) { s++; }
+ constexpr S (int x) : s (x) { s += 2; }
+ constexpr ~S () { if (s != 35) asm (""); s = 5; }
+ int s;
+};
+
+constexpr bool
+foo ()
+{
+ S *p = new S (7);
+ if (p->s != 9) return false;
+ p->s = 35;
+ delete p;
+ p = new S[3] { 11, 13, 15 };
+ if (p[0].s != 13 || p[1].s != 15 || p[2].s != 17) return false;
+ p[0].s = 35;
+ p[2].s = 35;
+ p[1].s = 35;
+ delete[] p;
+ return true;
+}
+
+constexpr bool a = foo ();
+static_assert (a);
diff --git a/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C b/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
index 086109adbf2..2b9cfd0effc 100644
--- a/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
+++ b/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
@@ -430,16 +430,34 @@
// C++20 features
-#if __cpp_conditional_explicit != 201806
-# error "__cpp_conditional_explicit != 201806"
+#ifndef __cpp_conditional_explicit
+# error "__cpp_conditional_explicit"
+#elif __cpp_conditional_explicit != 201806
+# error "__cpp_conditional_explicit != 201806"
#endif
-#if __cpp_nontype_template_parameter_class != 201806
-# error "__cpp_nontype_template_parameter_class != 201806"
+#ifndef __cpp_nontype_template_parameter_class
+# error "__cpp_nontype_template_parameter_class"
+#elif __cpp_nontype_template_parameter_class != 201806
+# error "__cpp_nontype_template_parameter_class != 201806"
#endif
-#if __cpp_impl_destroying_delete != 201806
-# error "__cpp_impl_destroying_delete != 201806"
+#ifndef __cpp_impl_destroying_delete
+# error "__cpp_impl_destroying_delete"
+#elif __cpp_impl_destroying_delete != 201806
+# error "__cpp_impl_destroying_delete != 201806"
+#endif
+
+#ifndef __cpp_constinit
+# error "__cpp_constinit"
+#elif __cpp_constinit != 201907
+# error "__cpp_constinit != 201907"
+#endif
+
+#ifndef __cpp_constexpr_dynamic_alloc
+# error "__cpp_constexpr_dynamic_alloc"
+#elif __cpp_constexpr_dynamic_alloc != 201907
+# error "__cpp_constexpr_dynamic_alloc != 201907"
#endif
#ifdef __has_cpp_attribute
@@ -484,8 +502,6 @@
# error "__has_cpp_attribute"
#endif
-// C++2A features:
-
#ifndef __cpp_char8_t
# error "__cpp_char8_t"
#elif __cpp_char8_t != 201811
diff --git a/gcc/testsuite/g++.dg/diagnostic/integral-array-size-1.C b/gcc/testsuite/g++.dg/diagnostic/integral-array-size-1.C
new file mode 100644
index 00000000000..31d67c58d61
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/integral-array-size-1.C
@@ -0,0 +1,7 @@
+template<typename T>
+void foo(T a)
+{
+ new int[a]; // { dg-error "11:size in array new must have integral type" }
+}
+
+template void foo(float);
diff --git a/gcc/testsuite/g++.dg/diagnostic/not-a-function-template-1.C b/gcc/testsuite/g++.dg/diagnostic/not-a-function-template-1.C
new file mode 100644
index 00000000000..caf8afa2697
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/not-a-function-template-1.C
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++14 } }
+
+template<typename> int A; // { dg-message "24:variable template" }
+
+template int A<>(); // { dg-error "14:template<class>" }
+
+struct B {
+ friend int A<>(); // { dg-error "14:specialization" }
+};
diff --git a/gcc/testsuite/g++.dg/ext/constexpr-attr-cleanup1.C b/gcc/testsuite/g++.dg/ext/constexpr-attr-cleanup1.C
new file mode 100644
index 00000000000..2c4f61ac44b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/constexpr-attr-cleanup1.C
@@ -0,0 +1,30 @@
+// { dg-do compile { target c++2a } }
+
+constexpr void
+cleanup (int *x)
+{
+ if (x)
+ asm (""); // { dg-error "inline assembly is not a constant expression" }
+} // { dg-message "only unevaluated inline assembly is allowed in a 'constexpr' function" "" { target *-*-* } .-1 }
+
+constexpr void
+cleanup2 (int *x)
+{
+}
+
+constexpr bool
+foo ()
+{
+ int a __attribute__((cleanup (cleanup))) = 1;
+ return true;
+}
+
+constexpr bool
+bar ()
+{
+ int a __attribute__((cleanup (cleanup2))) = 1;
+ return true;
+}
+
+constexpr auto x = foo (); // { dg-message "in 'constexpr' expansion of" }
+constexpr auto y = bar ();
diff --git a/gcc/testsuite/g++.dg/ext/is_literal_type3.C b/gcc/testsuite/g++.dg/ext/is_literal_type3.C
new file mode 100644
index 00000000000..22d8494a2b4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_literal_type3.C
@@ -0,0 +1,26 @@
+// { dg-do compile { target c++11 } }
+
+struct S {
+ constexpr S () : n{} { }
+ ~S () { n = 1; }
+ int n;
+};
+
+static_assert(!__is_literal_type(S), "");
+
+#ifdef __cpp_constexpr_dynamic_alloc
+struct T {
+ constexpr T () : n{} { }
+ constexpr ~T () { n = 1; }
+ int n;
+};
+
+static_assert(__is_literal_type(T), "");
+
+struct U : public T {
+ constexpr U () : u{} { }
+ int u;
+};
+
+static_assert(__is_literal_type(U), "");
+#endif
diff --git a/gcc/testsuite/g++.dg/init/new43.C b/gcc/testsuite/g++.dg/init/new43.C
index e2ad67d8307..880e330907f 100644
--- a/gcc/testsuite/g++.dg/init/new43.C
+++ b/gcc/testsuite/g++.dg/init/new43.C
@@ -30,36 +30,36 @@ void test_literal ()
B b;
// Verify integer literal.
- p = new char [-1]; // { dg-error "size .-1. of array is negative" }
- p = new char [2][-3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new char [-4][5]; // { dg-error "size .-4. of array is negative" }
- p = new char [-6][-7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new (p) char [-1]; // { dg-error "size .-1. of array is negative" }
- p = new (p) char [2][-3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new (p) char [-4][5]; // { dg-error "size .-4. of array is negative" }
- p = new (p) char [-6][-7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new (p) A [-1]; // { dg-error "size .-1. of array is negative" }
- p = new (p) A [2][-3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new (p) A [-4][5]; // { dg-error "size .-4. of array is negative" }
- p = new (p) A [-6][-7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new (p) B [-1]; // { dg-error "size .-1. of array is negative" }
- p = new (p) B [2][-3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new (p) B [-4][5]; // { dg-error "size .-4. of array is negative" }
- p = new (p) B [-6][-7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new (&b) B [-1]; // { dg-error "size .-1. of array is negative" }
- p = new (&b) B [2][-3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new (&b) B [-4][5]; // { dg-error "size .-4. of array is negative" }
- p = new (&b) B [-6][-7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new char [1 - 2]; // { dg-error "size .-1. of array is negative" }
- p = new (p) char [2 - 3]; // { dg-error "size .-1. of array is negative" }
- p = new A [2 < 1 ? -1 : -2]; // { dg-error "size .-2. of array is negative" }
- p = new (p) B [2 - 3 * 2]; // { dg-error "size .-4. of array is negative" }
- p = new (&b) B [1][2 - 3 * 2];// { dg-error "size .-4. of array|narrowing conversion" }
+ p = new char [-1]; // { dg-error "19:size .-1. of array is negative" }
+ p = new char [2][-3]; // { dg-error "22:size .-3. of array|narrowing conversion" }
+ p = new char [-4][5]; // { dg-error "19:size .-4. of array is negative" }
+ p = new char [-6][-7]; // { dg-error "19:size .-6. of array|narrowing conversion" }
+ // { dg-error "23:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new (p) char [-1]; // { dg-error "23:size .-1. of array is negative" }
+ p = new (p) char [2][-3]; // { dg-error "26:size .-3. of array|narrowing conversion" }
+ p = new (p) char [-4][5]; // { dg-error "23:size .-4. of array is negative" }
+ p = new (p) char [-6][-7]; // { dg-error "23:size .-6. of array|narrowing conversion" }
+ // { dg-error "27:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new (p) A [-1]; // { dg-error "20:size .-1. of array is negative" }
+ p = new (p) A [2][-3]; // { dg-error "23:size .-3. of array|narrowing conversion" }
+ p = new (p) A [-4][5]; // { dg-error "20:size .-4. of array is negative" }
+ p = new (p) A [-6][-7]; // { dg-error "20:size .-6. of array|narrowing conversion" }
+ // { dg-error "24:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new (p) B [-1]; // { dg-error "20:size .-1. of array is negative" }
+ p = new (p) B [2][-3]; // { dg-error "23:size .-3. of array|narrowing conversion" }
+ p = new (p) B [-4][5]; // { dg-error "20:size .-4. of array is negative" }
+ p = new (p) B [-6][-7]; // { dg-error "size .-6. of array|narrowing conversion" }
+ // { dg-error "24:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new (&b) B [-1]; // { dg-error "21:size .-1. of array is negative" }
+ p = new (&b) B [2][-3]; // { dg-error "24:size .-3. of array|narrowing conversion" }
+ p = new (&b) B [-4][5]; // { dg-error "21:size .-4. of array is negative" }
+ p = new (&b) B [-6][-7]; // { dg-error "21:size .-6. of array|narrowing conversion" }
+ // { dg-error "25:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new char [1 - 2]; // { dg-error "21:size .-1. of array is negative" }
+ p = new (p) char [2 - 3]; // { dg-error "25:size .-1. of array is negative" }
+ p = new A [2 < 1 ? -1 : -2]; // { dg-error "22:size .-2. of array is negative" }
+ p = new (p) B [2 - 3 * 2]; // { dg-error "22:size .-4. of array is negative" }
+ p = new (&b) B [1][2 - 3 * 2];// { dg-error "26:size .-4. of array|narrowing conversion" }
}
void test_constant_expression ()
@@ -78,36 +78,36 @@ void test_constant_expression ()
static const int i7 = -7;
// Verify constant expression.
- p = new char [i1]; // { dg-error "size .-1. of array is negative" }
- p = new char [2][i3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new char [i4][5]; // { dg-error "size .-4. of array is negative" }
- p = new char [i6][i7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new (p) char [i1]; // { dg-error "size .-1. of array is negative" }
- p = new (p) char [2][i3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new (p) char [i4][5]; // { dg-error "size .-4. of array is negative" }
- p = new (p) char [i6][i7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new (p) A [i1]; // { dg-error "size .-1. of array is negative" }
- p = new (p) A [2][i3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new (p) A [i4][5]; // { dg-error "size .-4. of array is negative" }
- p = new (p) A [i6][i7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new (p) B [i1]; // { dg-error "size .-1. of array is negative" }
- p = new (p) B [2][i3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new (p) B [i4][5]; // { dg-error "size .-4. of array is negative" }
- p = new (p) B [i6][i7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new (&b) B [i1]; // { dg-error "size .-1. of array is negative" }
- p = new (&b) B [2][i3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new (&b) B [i4][5]; // { dg-error "size .-4. of array is negative" }
- p = new (&b) B [i6][i7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new short [i1 - 2]; // { dg-error "size .-3. of array is negative" }
- p = new (p) bool [i2 - 3]; // { dg-error "size .-5. of array is negative" }
- p = new A [2 < 1 ? i1 : i2]; // { dg-error "size .-2. of array is negative" }
- p = new (p) B [2 + i3 * 2]; // { dg-error "size .-4. of array is negative" }
- p = new (&b) B [1][i1 - 3 * 2];// { dg-error "size .-7. of array|narrowing conversion" }
+ p = new char [i1]; // { dg-error "19:size .-1. of array is negative" }
+ p = new char [2][i3]; // { dg-error "22:size .-3. of array|narrowing conversion" }
+ p = new char [i4][5]; // { dg-error "19:size .-4. of array is negative" }
+ p = new char [i6][i7]; // { dg-error "19:size .-6. of array|narrowing conversion" }
+ // { dg-error "23:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new (p) char [i1]; // { dg-error "23:size .-1. of array is negative" }
+ p = new (p) char [2][i3]; // { dg-error "26:size .-3. of array|narrowing conversion" }
+ p = new (p) char [i4][5]; // { dg-error "23:size .-4. of array is negative" }
+ p = new (p) char [i6][i7]; // { dg-error "23:size .-6. of array|narrowing conversion" }
+ // { dg-error "27:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new (p) A [i1]; // { dg-error "20:size .-1. of array is negative" }
+ p = new (p) A [2][i3]; // { dg-error "23:size .-3. of array|narrowing conversion" }
+ p = new (p) A [i4][5]; // { dg-error "20:size .-4. of array is negative" }
+ p = new (p) A [i6][i7]; // { dg-error "20:size .-6. of array|narrowing conversion" }
+ // { dg-error "24:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new (p) B [i1]; // { dg-error "20:size .-1. of array is negative" }
+ p = new (p) B [2][i3]; // { dg-error "23:size .-3. of array|narrowing conversion" }
+ p = new (p) B [i4][5]; // { dg-error "20:size .-4. of array is negative" }
+ p = new (p) B [i6][i7]; // { dg-error "20:size .-6. of array|narrowing conversion" }
+ // { dg-error "24:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new (&b) B [i1]; // { dg-error "21:size .-1. of array is negative" }
+ p = new (&b) B [2][i3]; // { dg-error "24:size .-3. of array|narrowing conversion" }
+ p = new (&b) B [i4][5]; // { dg-error "21:size .-4. of array is negative" }
+ p = new (&b) B [i6][i7]; // { dg-error "21:size .-6. of array|narrowing conversion" }
+ // { dg-error "25:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new short [i1 - 2]; // { dg-error "23:size .-3. of array is negative" }
+ p = new (p) bool [i2 - 3]; // { dg-error "26:size .-5. of array is negative" }
+ p = new A [2 < 1 ? i1 : i2]; // { dg-error "22:size .-2. of array is negative" }
+ p = new (p) B [2 + i3 * 2]; // { dg-error "22:size .-4. of array is negative" }
+ p = new (&b) B [1][i1 - 3 * 2];// { dg-error "27:size .-7. of array|narrowing conversion" }
}
void test_constexpr ()
@@ -131,36 +131,36 @@ void test_constexpr ()
#endif
// Verify constant expression.
- p = new char [s1]; // { dg-error "size .-1. of array is negative" }
- p = new char [2][s3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new char [s4][5]; // { dg-error "size .-4. of array is negative" }
- p = new char [s6][s7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new (p) char [s1]; // { dg-error "size .-1. of array is negative" }
- p = new (p) char [2][s3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new (p) char [s4][5]; // { dg-error "size .-4. of array is negative" }
- p = new (p) char [s6][s7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new (p) A [s1]; // { dg-error "size .-1. of array is negative" }
- p = new (p) A [2][s3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new (p) A [s4][5]; // { dg-error "size .-4. of array is negative" }
- p = new (p) A [s6][s7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new (p) B [s1]; // { dg-error "size .-1. of array is negative" }
- p = new (p) B [2][s3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new (p) B [s4][5]; // { dg-error "size .-4. of array is negative" }
- p = new (p) B [s6][s7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new (&b) B [s1]; // { dg-error "size .-1. of array is negative" }
- p = new (&b) B [2][s3]; // { dg-error "size .-3. of array|narrowing conversion" }
- p = new (&b) B [s4][5]; // { dg-error "size .-4. of array is negative" }
- p = new (&b) B [s6][s7]; // { dg-error "size .-\[67\]. of array|narrowing conversion" }
-
- p = new int [s1 + s2]; // { dg-error "size .-3. of array is negative" }
- p = new (p) long [2 * s3]; // { dg-error "size .-6. of array is negative" }
+ p = new char [s1]; // { dg-error "19:size .-1. of array is negative" }
+ p = new char [2][s3]; // { dg-error "22:size .-3. of array|narrowing conversion" }
+ p = new char [s4][5]; // { dg-error "19:size .-4. of array is negative" }
+ p = new char [s6][s7]; // { dg-error "19:size .-6. of array|narrowing conversion" }
+ // { dg-error "23:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new (p) char [s1]; // { dg-error "23:size .-1. of array is negative" }
+ p = new (p) char [2][s3]; // { dg-error "26:size .-3. of array|narrowing conversion" }
+ p = new (p) char [s4][5]; // { dg-error "23:size .-4. of array is negative" }
+ p = new (p) char [s6][s7]; // { dg-error "23:size .-6. of array|narrowing conversion" }
+ // { dg-error "27:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new (p) A [s1]; // { dg-error "20:size .-1. of array is negative" }
+ p = new (p) A [2][s3]; // { dg-error "23:size .-3. of array|narrowing conversion" }
+ p = new (p) A [s4][5]; // { dg-error "20:size .-4. of array is negative" }
+ p = new (p) A [s6][s7]; // { dg-error "20:size .-6. of array|narrowing conversion" }
+ // { dg-error "24:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new (p) B [s1]; // { dg-error "20:size .-1. of array is negative" }
+ p = new (p) B [2][s3]; // { dg-error "23:size .-3. of array|narrowing conversion" }
+ p = new (p) B [s4][5]; // { dg-error "20:size .-4. of array is negative" }
+ p = new (p) B [s6][s7]; // { dg-error "20:size .-6. of array|narrowing conversion" }
+ // { dg-error "24:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new (&b) B [s1]; // { dg-error "21:size .-1. of array is negative" }
+ p = new (&b) B [2][s3]; // { dg-error "24:size .-3. of array|narrowing conversion" }
+ p = new (&b) B [s4][5]; // { dg-error "21:size .-4. of array is negative" }
+ p = new (&b) B [s6][s7]; // { dg-error "21:size .-6. of array|narrowing conversion" }
+ // { dg-error "25:size .-7. of array" "" { target *-*-* } .-1 }
+ p = new int [s1 + s2]; // { dg-error "21:size .-3. of array is negative" }
+ p = new (p) long [2 * s3]; // { dg-error "25:size .-6. of array is negative" }
p = new A [s2 < s1 ? s1 : s2]; // { dg-error "size .-1. of array is negative" }
- p = new (p) B [s7 - s2 * 2]; // { dg-error "size .-3. of array is negative" }
- p = new (&b) B [9][s4 - s1 * 2]; // { dg-error "size .-2. of array|narrowing conversion" }
+ p = new (p) B [s7 - s2 * 2]; // { dg-error "23:size .-3. of array is negative" }
+ p = new (&b) B [9][s4 - s1 * 2]; // { dg-error "27:size .-2. of array|narrowing conversion" }
}
/* Prune out pedantic warnins (turned into errors via -pedantic-errors).
diff --git a/gcc/testsuite/g++.dg/lookup/friend12.C b/gcc/testsuite/g++.dg/lookup/friend12.C
index eb61fb52378..612b0da0299 100644
--- a/gcc/testsuite/g++.dg/lookup/friend12.C
+++ b/gcc/testsuite/g++.dg/lookup/friend12.C
@@ -5,6 +5,6 @@ void foo()
extern void bar (int); // not the bar we are looking for
struct A
{
- friend void bar(); // { dg-error "without prior local declaration" }
+ friend void bar(); // { dg-error "17:friend declaration .void bar\\(\\). in local class without prior local declaration" }
};
}
diff --git a/gcc/testsuite/g++.dg/lookup/pr79766.C b/gcc/testsuite/g++.dg/lookup/pr79766.C
index de9bbb5fab9..09f09fa67d4 100644
--- a/gcc/testsuite/g++.dg/lookup/pr79766.C
+++ b/gcc/testsuite/g++.dg/lookup/pr79766.C
@@ -24,6 +24,6 @@ void ::R () // OK -> Z::R
void S ();
-void ::S () // { dg-error "explicit qualification" }
+void ::S () // { dg-error "6:explicit qualification" }
{
}
diff --git a/gcc/testsuite/g++.dg/lookup/pr84375.C b/gcc/testsuite/g++.dg/lookup/pr84375.C
index 24cdcb2c407..1b086e15694 100644
--- a/gcc/testsuite/g++.dg/lookup/pr84375.C
+++ b/gcc/testsuite/g++.dg/lookup/pr84375.C
@@ -4,6 +4,6 @@ void foo()
{
struct A
{
- friend void A(); // { dg-error "local class without prior local" }
+ friend void A(); // { dg-error "17:friend declaration .void A\\(\\). in local class without prior local" }
};
}
diff --git a/gcc/testsuite/g++.dg/other/new-size-type.C b/gcc/testsuite/g++.dg/other/new-size-type.C
index a99d747026a..3411641e041 100644
--- a/gcc/testsuite/g++.dg/other/new-size-type.C
+++ b/gcc/testsuite/g++.dg/other/new-size-type.C
@@ -5,5 +5,5 @@
const char*
foo()
{
- return new char[~static_cast<size_t>(0)];// { dg-error "exceeds maximum object size" }
+ return new char[~static_cast<size_t>(0)];// { dg-error "21:exceeds maximum object size" }
}
diff --git a/gcc/testsuite/g++.dg/template/crash107.C b/gcc/testsuite/g++.dg/template/crash107.C
index cecf9013244..3b0b4e8211f 100644
--- a/gcc/testsuite/g++.dg/template/crash107.C
+++ b/gcc/testsuite/g++.dg/template/crash107.C
@@ -6,8 +6,8 @@
template<typename FP_> struct Vec { // { dg-message "note" }
Vec& operator^=(Vec& rhs) {
union {
- struct {FP_ x,y,z;};
- }; // { dg-error "anonymous struct" }
+ struct {FP_ x,y,z;}; // { dg-error "20:anonymous struct" }
+ };
X = y*rhs.z() - z*rhs.y(); // { dg-error "not declared|no member" }
}
Vec& operator^(Vec& rhs) {
diff --git a/gcc/testsuite/g++.dg/template/dependent-expr1.C b/gcc/testsuite/g++.dg/template/dependent-expr1.C
index 79649861ba4..eda7526e1b1 100644
--- a/gcc/testsuite/g++.dg/template/dependent-expr1.C
+++ b/gcc/testsuite/g++.dg/template/dependent-expr1.C
@@ -19,11 +19,11 @@ namespace std
Foo (sizeof (x));
Foo (__alignof__ (I));
Foo (__alignof__ (x));
- Foo (x->~I ()); // { dg-error "" }
+ Foo (x->~I ()); // { dg-error "16:invalid" }
// Foo (typeid (I));
- Foo (delete x); // { dg-error "" }
- Foo (delete[] x); // { dg-error "" }
- Foo (throw x); // { dg-error "" }
+ Foo (delete x); // { dg-error "10:invalid" }
+ Foo (delete[] x); // { dg-error "10:invalid" }
+ Foo (throw x); // { dg-error "10:invalid" }
}
}
diff --git a/gcc/testsuite/g++.dg/template/error17.C b/gcc/testsuite/g++.dg/template/error17.C
index 30a693f84d1..5b3281a1779 100644
--- a/gcc/testsuite/g++.dg/template/error17.C
+++ b/gcc/testsuite/g++.dg/template/error17.C
@@ -5,5 +5,5 @@ void
foo()
{
union { struct { }; }; // { dg-error "prohibits anonymous struct" "anon" }
- // { dg-error "not inside" "not inside" { target *-*-* } .-1 }
+ // { dg-error "18:anonymous struct not inside" "not inside" { target *-*-* } .-1 }
}
diff --git a/gcc/testsuite/g++.dg/torture/pr91606.C b/gcc/testsuite/g++.dg/torture/pr91606.C
new file mode 100644
index 00000000000..37a05a5e3a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr91606.C
@@ -0,0 +1,109 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fstrict-aliasing" } */
+
+#include <cstdlib>
+#include <array>
+#include <type_traits>
+
+template <typename T1, typename T2>
+struct variant
+{
+ constexpr variant(T1 arg)
+ : f1(arg),
+ index(0)
+ {}
+
+ constexpr variant(T2 arg)
+ : f2(arg),
+ index(1)
+ {}
+
+ union
+ {
+ T1 f1;
+ T2 f2;
+ };
+ std::size_t index = 0;
+};
+
+template <typename T1, typename T2>
+constexpr const T1* get_if(const variant<T1, T2>* v)
+{
+ if (v->index != 0)
+ {
+ return nullptr;
+ }
+ return &v->f1;
+}
+
+template <typename T2, typename T1>
+constexpr const T2* get_if(const variant<T1, T2>* v)
+{
+ if (v->index != 1)
+ {
+ return nullptr;
+ }
+ return &v->f2;
+}
+
+template <typename T, size_t N>
+struct my_array
+{
+ constexpr const T* begin() const
+ {
+ return data;
+ }
+
+ constexpr const T* end() const
+ {
+ return data + N;
+ }
+
+ T data[N];
+};
+
+template <typename ...Ts>
+constexpr auto get_array_of_variants(Ts ...ptrs)
+{
+ return std::array<variant<std::decay_t<Ts>...>, sizeof...(Ts)>{ ptrs... };
+}
+
+template <typename T>
+constexpr auto get_member_functions();
+
+template <typename Member, typename Class>
+constexpr int getFuncId(Member (Class::*memFuncPtr))
+{
+ int idx = 0u;
+ for (auto &anyFunc : get_member_functions<Class>())
+ {
+ if (auto *specificFunc = get_if<Member (Class::*)>(&anyFunc))
+ {
+ if (*specificFunc == memFuncPtr)
+ {
+ return idx;
+ }
+ }
+ ++idx;
+ }
+ std::abort();
+}
+
+struct MyStruct
+{
+ void fun1(int /*a*/) {}
+
+ int fun2(char /*b*/, short /*c*/, bool /*d*/) { return 0; }
+
+};
+
+template <>
+constexpr auto get_member_functions<MyStruct>()
+{
+ return get_array_of_variants(&MyStruct::fun1, &MyStruct::fun2);
+}
+
+int main()
+{
+ return getFuncId(&MyStruct::fun1);
+}
diff --git a/gcc/testsuite/g++.dg/tree-ssa/ivopts-3.C b/gcc/testsuite/g++.dg/tree-ssa/ivopts-3.C
index 07ff1b770f8..6760a5b1851 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/ivopts-3.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/ivopts-3.C
@@ -70,6 +70,8 @@ int main ( int , char** ) {
return 0;
}
-// Verify that on x86_64 and i?86 we use a single IV for the innermost loop
+// Verify that on x86_64 and i?86 we unroll the innsermost loop and
+// use three IVs for the then innermost loop
-// { dg-final { scan-tree-dump "Selected IV set for loop \[0-9\]* at \[^ \]*:64, 3 avg niters, 1 IVs" "ivopts" { target x86_64-*-* i?86-*-* } } }
+// { dg-final { scan-tree-dump "Selected IV set for loop \[0-9\]* at \[^ \]*:63, 127 avg niters, 3 IVs" "ivopts" { target x86_64-*-* i?86-*-* } } }
+// { dg-final { scan-tree-dump-not "Selected IV set for loop \[0-9\]* at \[^ \]*:64" "ivopts" { target x86_64-*-* i?86-*-* } } }
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr53844.C b/gcc/testsuite/g++.dg/tree-ssa/pr53844.C
index 954cc71b439..ab9879f6a18 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr53844.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr53844.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-O2 -fdump-tree-optimized-vops" }
+// { dg-options "-O2 -fdump-tree-optimized-vops -fno-inline-functions --param max-inline-insns-single-O2=200" }
struct VBase;
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr61034.C b/gcc/testsuite/g++.dg/tree-ssa/pr61034.C
index 2e3dfecacb4..6a76adb5b80 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr61034.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr61034.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-O2 -fdump-tree-fre3 -fdump-tree-optimized -fdelete-null-pointer-checks --param early-inlining-insns-O2=14" }
+// { dg-options "-O2 -fdump-tree-fre3 -fdump-tree-optimized -fdelete-null-pointer-checks --param early-inlining-insns-O2=14 --param max-inline-insns-single-O2=200" }
#define assume(x) if(!(x))__builtin_unreachable()
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp b/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp
index d62f78c7a6c..e9d3c9aab7d 100644
--- a/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp
@@ -37,7 +37,7 @@ load_lib c-torture.exp
torture-init
set-torture-options $C_TORTURE_OPTIONS {{}} $LTO_TORTURE_OPTIONS
-set additional_flags "-fno-tree-dse -fno-tree-loop-distribute-patterns -fno-tracer -fno-ipa-ra"
+set additional_flags "-fno-tree-dse -fno-tree-loop-distribute-patterns -fno-tracer -fno-ipa-ra -fno-inline-functions"
if [istarget "powerpc-*-darwin*"] {
lappend additional_flags "-Wl,-multiply_defined,suppress"
}
diff --git a/gcc/testsuite/gcc.c-torture/execute/loop-3.c b/gcc/testsuite/gcc.c-torture/execute/loop-3.c
index e314a01b1f1..33eb18826fd 100644
--- a/gcc/testsuite/gcc.c-torture/execute/loop-3.c
+++ b/gcc/testsuite/gcc.c-torture/execute/loop-3.c
@@ -13,7 +13,7 @@ f (m)
i = m;
do
{
- g (i * INT_MAX / 2);
+ g ((int)((unsigned)i * INT_MAX) / 2);
}
while (--i > 0);
}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-18.c b/gcc/testsuite/gcc.dg/Warray-bounds-18.c
index 888fb80e7b9..092363aea31 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-18.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-18.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -Warray-bounds" } */
+/* { dg-options "-O2 -Warray-bounds -Wno-stringop-overflow" } */
typedef struct
{
diff --git a/gcc/testsuite/gcc.dg/Wnonnull-2.c b/gcc/testsuite/gcc.dg/Wnonnull-2.c
new file mode 100644
index 00000000000..d870473d5a9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wnonnull-2.c
@@ -0,0 +1,55 @@
+/* PR middle-end/80936 - bcmp, bcopy, and bzero not declared nonnull
+ Verify that -Wnonnull is issued for calls with constant null pointers
+ with no optimization.
+ { dg-do compile }
+ { dg-options "-O0 -Wall" } */
+
+void zero0 (void *p, unsigned n)
+{
+ __builtin_memset (0, 0, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+void zero1 (void *p, unsigned n)
+{
+ __builtin_bzero (0, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+void copy0 (void *p, const void *q, unsigned n)
+{
+ __builtin_memcpy (0, q, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+void copy1 (void *p, const void *q, unsigned n)
+{
+ __builtin_memcpy (0, q, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+void copy2 (void *p, const void *q, unsigned n)
+{
+ __builtin_bcopy (q, 0, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+void copy3 (void *p, const void *q, unsigned n)
+{
+ __builtin_bcopy (q, 0, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+int cmp0 (const void *p, const void *q, unsigned n)
+{
+ return __builtin_memcmp (0, q, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+int cmp1 (const void *p, const void *q, unsigned n)
+{
+ return __builtin_memcmp (0, q, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+int cmp2 (const void *p, const void *q, unsigned n)
+{
+ return __builtin_bcmp (0, q, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+int cmp3 (const void *p, const void *q, unsigned n)
+{
+ return __builtin_bcmp (p, 0, n); // { dg-warning "\\\[-Wnonnull]" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wnonnull-3.c b/gcc/testsuite/gcc.dg/Wnonnull-3.c
new file mode 100644
index 00000000000..ad016df9331
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wnonnull-3.c
@@ -0,0 +1,71 @@
+/* PR middle-end/80936 - bcmp, bcopy, and bzero not declared nonnull
+ Verify that with optimization, -Wnonnull is issued for calls with
+ non-constant arguments determined to be null.
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+#define NOIPA __attribute__ ((noipa))
+
+NOIPA void zero0 (void *p, unsigned n)
+{
+ if (p == 0)
+ __builtin_memset (p, 0, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+NOIPA void zero1 (void *p, unsigned n)
+{
+ if (p == 0)
+ __builtin_bzero (p, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+NOIPA void copy0 (void *p, const void *q, unsigned n)
+{
+ if (p == 0)
+ __builtin_memcpy (p, q, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+NOIPA void copy1 (void *p, const void *q, unsigned n)
+{
+ if (q == 0)
+ __builtin_memcpy (p, q, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+NOIPA void copy2 (void *p, const void *q, unsigned n)
+{
+ if (p == 0)
+ __builtin_bcopy (q, p, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+NOIPA void copy3 (void *p, const void *q, unsigned n)
+{
+ if (q == 0)
+ __builtin_bcopy (q, p, n); // { dg-warning "\\\[-Wnonnull]" }
+}
+
+NOIPA int cmp0 (const void *p, const void *q, unsigned n)
+{
+ if (p == 0)
+ return __builtin_memcmp (p, q, n); // { dg-warning "\\\[-Wnonnull]" }
+ return 0;
+}
+
+NOIPA int cmp1 (const void *p, const void *q, unsigned n)
+{
+ if (q == 0)
+ return __builtin_memcmp (p, q, n); // { dg-warning "\\\[-Wnonnull]" }
+ return 0;
+}
+
+NOIPA int cmp2 (const void *p, const void *q, unsigned n)
+{
+ if (p == 0)
+ return __builtin_bcmp (p, q, n); // { dg-warning "\\\[-Wnonnull]" }
+ return 0;
+}
+
+NOIPA int cmp3 (const void *p, const void *q, unsigned n)
+{
+ if (q == 0)
+ return __builtin_bcmp (p, q, n); // { dg-warning "\\\[-Wnonnull]" }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-17.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-17.c
new file mode 100644
index 00000000000..de22c98c753
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-17.c
@@ -0,0 +1,20 @@
+/* Test to verify that -Wstringop-overflow mentions the referenced object
+ i.
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+static void copy_n (char *d, const char *s, int n)
+{
+ while (n--)
+ *d++ = *s++;
+ *d = 0; // { dg-warning "writing 1 byte into a region of size 0" }
+}
+
+void sink (void*);
+
+void call_copy_n (const char *s)
+{
+ char a[3]; // { dg-message "destination object declared here" }
+ copy_n (a, "1234567", 7);
+ sink (a);
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-18.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-18.c
new file mode 100644
index 00000000000..7866b585b84
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-18.c
@@ -0,0 +1,239 @@
+/* PR middle-end/91977 - missing -Wstringop-overflow on memcpy into
+ a pointer plus offset
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
+
+#define NOIPA __attribute__ ((noipa))
+#define CONCAT(a, b) a ## b
+#define CAT(a, b) CONCAT (a, b)
+
+#define S3 "123"
+#define S4 "1234"
+
+char a1[1], a2[2], a3[3], a4[4], a5[5], a6[6], a7[7], a8[8];
+char b1[1], b2[2], b3[3], b4[4], b5[5], b6[6], b7[7], b8[8];
+
+#define T(dst, src, off, n) \
+ NOIPA void CAT (test_on_line_, __LINE__) (const void *s) \
+ { \
+ __builtin_memcpy (dst + off, src, n); \
+ } typedef void dummy_type
+
+T (a4, s, 0, 1);
+T (a4, s, 1, 1);
+T (a4, s, 2, 1);
+T (a4, s, 3, 1);
+T (a4, s, 4, 1); // { dg-warning "writing 1 byte into a region of size 0" }
+
+T (a4, s, 0, 2);
+T (a4, s, 1, 2);
+T (a4, s, 2, 2);
+T (a4, s, 3, 2); // { dg-warning "writing 2 bytes into a region of size 1" }
+T (a4, s, 4, 2); // { dg-warning "writing 2 bytes into a region of size 0" }
+
+T (a4, s, 0, 3);
+T (a4, s, 1, 3);
+T (a4, s, 2, 3); // { dg-warning "writing 3 bytes into a region of size 2" }
+T (a4, s, 3, 3); // { dg-warning "writing 3 bytes into a region of size 1" }
+T (a4, s, 4, 3); // { dg-warning "writing 3 bytes into a region of size 0" }
+
+T (a4, s, 0, 4);
+T (a4, s, 1, 4); // { dg-warning "writing 4 bytes into a region of size 3" }
+T (a4, s, 2, 4); // { dg-warning "writing 4 bytes into a region of size 2" }
+T (a4, s, 3, 4); // { dg-warning "writing 4 bytes into a region of size 1" }
+T (a4, s, 4, 4); // { dg-warning "writing 4 bytes into a region of size 0" }
+
+T (a7, s, 3, 3);
+T (a7, s, 4, 3);
+T (a7, s, 5, 3); // { dg-warning "writing 3 bytes into a region of size 2" }
+T (a7, s, 6, 3); // { dg-warning "writing 3 bytes into a region of size 1" }
+T (a7, s, 7, 3); // { dg-warning "writing 3 bytes into a region of size 0" }
+
+T (a7, s, 3, 4);
+T (a7, s, 4, 4); // { dg-warning "writing 4 bytes into a region of size 3" }
+T (a7, s, 5, 4); // { dg-warning "writing 4 bytes into a region of size 2" }
+T (a7, s, 6, 4); // { dg-warning "writing 4 bytes into a region of size 1" }
+T (a7, s, 7, 4); // { dg-warning "writing 4 bytes into a region of size 0" }
+
+T (a7, s, 1, 6);
+T (a7, s, 2, 6); // { dg-warning "writing 6 bytes into a region of size 5" }
+T (a7, s, 3, 6); // { dg-warning "writing 6 bytes into a region of size 4" }
+T (a7, s, 4, 6); // { dg-warning "writing 6 bytes into a region of size 3" }
+T (a7, s, 5, 6); // { dg-warning "writing 6 bytes into a region of size 2" }
+T (a7, s, 6, 6); // { dg-warning "writing 6 bytes into a region of size 1" }
+T (a7, s, 7, 6); // { dg-warning "writing 6 bytes into a region of size 0" }
+
+T (a8, s, 1, 7);
+T (a8, s, 2, 7); // { dg-warning "writing 7 bytes into a region of size 6" }
+T (a8, s, 3, 7); // { dg-warning "writing 7 bytes into a region of size 5" }
+T (a8, s, 4, 7); // { dg-warning "writing 7 bytes into a region of size 4" }
+T (a8, s, 5, 7); // { dg-warning "writing 7 bytes into a region of size 3" }
+T (a8, s, 6, 7); // { dg-warning "writing 7 bytes into a region of size 2" }
+T (a8, s, 7, 7); // { dg-warning "writing 7 bytes into a region of size 1" }
+T (a8, s, 8, 7); // { dg-warning "writing 7 bytes into a region of size 0" }
+
+#undef T
+#define T(dst, src, off, n) \
+ NOIPA void CAT (test_on_line_, __LINE__) (const void *s) \
+ { \
+ char *d = dst + off; \
+ __builtin_memcpy (d, src, n); \
+ } typedef void dummy_type
+
+T (a4, s, 0, 1);
+T (a4, s, 1, 1);
+T (a4, s, 2, 1);
+T (a4, s, 3, 1);
+T (a4, s, 4, 1); // { dg-warning "writing 1 byte into a region of size 0" }
+
+T (a4, s, 0, 2);
+T (a4, s, 1, 2);
+T (a4, s, 2, 2);
+T (a4, s, 3, 2); // { dg-warning "writing 2 bytes into a region of size 1" }
+T (a4, s, 4, 2); // { dg-warning "writing 2 bytes into a region of size 0" }
+
+T (a4, s, 0, 3);
+T (a4, s, 1, 3);
+T (a4, s, 2, 3); // { dg-warning "writing 3 bytes into a region of size 2" }
+T (a4, s, 3, 3); // { dg-warning "writing 3 bytes into a region of size 1" }
+T (a4, s, 4, 3); // { dg-warning "writing 3 bytes into a region of size 0" }
+
+T (a4, s, 0, 4);
+T (a4, s, 1, 4); // { dg-warning "writing 4 bytes into a region of size 3" }
+T (a4, s, 2, 4); // { dg-warning "writing 4 bytes into a region of size 2" }
+T (a4, s, 3, 4); // { dg-warning "writing 4 bytes into a region of size 1" }
+T (a4, s, 4, 4); // { dg-warning "writing 4 bytes into a region of size 0" }
+
+T (a7, s, 3, 3);
+T (a7, s, 4, 3);
+T (a7, s, 5, 3); // { dg-warning "writing 3 bytes into a region of size 2" }
+T (a7, s, 6, 3); // { dg-warning "writing 3 bytes into a region of size 1" }
+T (a7, s, 7, 3); // { dg-warning "writing 3 bytes into a region of size 0" }
+
+T (a7, s, 3, 4);
+T (a7, s, 4, 4); // { dg-warning "writing 4 bytes into a region of size 3" }
+T (a7, s, 5, 4); // { dg-warning "writing 4 bytes into a region of size 2" }
+T (a7, s, 6, 4); // { dg-warning "writing 4 bytes into a region of size 1" }
+T (a7, s, 7, 4); // { dg-warning "writing 4 bytes into a region of size 0" }
+
+T (a7, s, 1, 6);
+T (a7, s, 2, 6); // { dg-warning "writing 6 bytes into a region of size 5" }
+T (a7, s, 3, 6); // { dg-warning "writing 6 bytes into a region of size 4" }
+T (a7, s, 4, 6); // { dg-warning "writing 6 bytes into a region of size 3" }
+T (a7, s, 5, 6); // { dg-warning "writing 6 bytes into a region of size 2" }
+T (a7, s, 6, 6); // { dg-warning "writing 6 bytes into a region of size 1" }
+T (a7, s, 7, 6); // { dg-warning "writing 6 bytes into a region of size 0" }
+
+#undef T
+#define T(dst, src, init, off, n) \
+ NOIPA void CAT (test_on_line_, __LINE__) (void) \
+ { \
+ __builtin_strcpy (src, init); \
+ char *d = dst + off; \
+ __builtin_memcpy (d, src, n); \
+ } typedef void dummy_type
+
+
+T (a6, b6, S4, 0, 4);
+T (a6, b6, S4, 1, 4);
+T (a6, b6, S4, 2, 4);
+T (a6, b6, S4, 3, 4); // { dg-warning "writing 4 bytes into a region of size 3" } */
+T (a6, b6, S4, 4, 4); // { dg-warning "writing 4 bytes into a region of size 2" } */
+T (a6, b6, S4, 5, 4); // { dg-warning "writing 4 bytes into a region of size 1" } */
+T (a6, b6, S4, 6, 4); // { dg-warning "writing 4 bytes into a region of size 0" } */
+
+T (a7, b7, S4, 0, 4);
+T (a7, b7, S4, 1, 4);
+T (a7, b7, S4, 2, 4);
+T (a7, b7, S4, 3, 4);
+T (a7, b7, S4, 4, 4); // { dg-warning "writing 4 bytes into a region of size 3" } */
+T (a7, b7, S4, 5, 4); // { dg-warning "writing 4 bytes into a region of size 2" } */
+T (a7, b7, S4, 6, 4); // { dg-warning "writing 4 bytes into a region of size 1" } */
+T (a7, b7, S4, 7, 4); // { dg-warning "writing 4 bytes into a region of size 0" } */
+
+T (a8, b4, S3, 0, 4);
+T (a8, b4, S3, 1, 4);
+T (a8, b4, S3, 2, 4);
+T (a8, b4, S3, 3, 4);
+T (a8, b4, S3, 4, 4);
+T (a8, b4, S3, 5, 4); // { dg-warning "writing 4 bytes into a region of size 3" } */
+T (a8, b4, S3, 6, 4); // { dg-warning "writing 4 bytes into a region of size 2" } */
+T (a8, b4, S3, 7, 4); // { dg-warning "writing 4 bytes into a region of size 1" } */
+T (a8, b4, S3, 8, 4); // { dg-warning "writing 4 bytes into a region of size 0" } */
+
+T (a8, b8, S3, 0, 4);
+T (a8, b8, S3, 1, 4);
+T (a8, b8, S3, 2, 4);
+T (a8, b8, S3, 3, 4);
+T (a8, b8, S3, 4, 4);
+T (a8, b8, S3, 5, 4); // { dg-warning "writing 4 bytes into a region of size 3" } */
+T (a8, b8, S3, 6, 4); // { dg-warning "writing 4 bytes into a region of size 2" } */
+T (a8, b8, S3, 7, 4); // { dg-warning "writing 4 bytes into a region of size 1" } */
+T (a8, b8, S3, 8, 4); // { dg-warning "writing 4 bytes into a region of size 0" } */
+
+T (a8, b8, S4, 0, 4);
+T (a8, b8, S4, 1, 4);
+T (a8, b8, S4, 2, 4);
+T (a8, b8, S4, 3, 4);
+T (a8, b8, S4, 4, 4);
+T (a8, b8, S4, 5, 4); // { dg-warning "writing 4 bytes into a region of size 3" } */
+T (a8, b8, S4, 6, 4); // { dg-warning "writing 4 bytes into a region of size 2" } */
+T (a8, b8, S4, 7, 4); // { dg-warning "writing 4 bytes into a region of size 1" } */
+T (a8, b8, S4, 8, 4); // { dg-warning "writing 4 bytes into a region of size 0" } */
+
+T (a8, b8, S4, 0, 5);
+T (a8, b8, S4, 1, 5);
+T (a8, b8, S4, 2, 5);
+T (a8, b8, S4, 3, 5);
+T (a8, b8, S4, 4, 5); // { dg-warning "writing 5 bytes into a region of size 4" } */
+T (a8, b8, S4, 5, 5); // { dg-warning "writing 5 bytes into a region of size 3" } */
+T (a8, b8, S4, 6, 5); // { dg-warning "writing 5 bytes into a region of size 2" } */
+T (a8, b8, S4, 7, 5); // { dg-warning "writing 5 bytes into a region of size 1" } */
+T (a8, b8, S4, 8, 5); // { dg-warning "writing 5 bytes into a region of size 0" } */
+
+T (a8, b8, S4, 0, 6);
+T (a8, b8, S4, 1, 6);
+T (a8, b8, S4, 2, 6);
+T (a8, b8, S4, 3, 6); // { dg-warning "writing 6 bytes into a region of size 5" } */
+T (a8, b8, S4, 4, 6); // { dg-warning "writing 6 bytes into a region of size 4" } */
+T (a8, b8, S4, 5, 6); // { dg-warning "writing 6 bytes into a region of size 3" } */
+T (a8, b8, S4, 6, 6); // { dg-warning "writing 6 bytes into a region of size 2" } */
+T (a8, b8, S4, 7, 6); // { dg-warning "writing 6 bytes into a region of size 1" } */
+T (a8, b8, S4, 8, 6); // { dg-warning "writing 6 bytes into a region of size 0" } */
+
+
+#undef T
+#define T(dst, init, off, n) \
+ NOIPA void CAT (test_on_line_, __LINE__) (char *src) \
+ { \
+ __builtin_strcpy (src, init); \
+ char *d = dst + off; \
+ __builtin_memcpy (d, src, n); \
+ } typedef void dummy_type
+
+T (a6, S4, 0, 4);
+T (a6, S4, 1, 4);
+T (a6, S4, 2, 4);
+T (a6, S4, 3, 4); // { dg-warning "writing 4 bytes into a region of size 3" } */
+T (a6, S4, 4, 4); // { dg-warning "writing 4 bytes into a region of size 2" } */
+T (a6, S4, 5, 4); // { dg-warning "writing 4 bytes into a region of size 1" } */
+T (a6, S4, 6, 4); // { dg-warning "writing 4 bytes into a region of size 0" } */
+
+T (a7, S4, 0, 4);
+T (a7, S4, 1, 4);
+T (a7, S4, 2, 4);
+T (a7, S4, 3, 4);
+T (a7, S4, 4, 4); // { dg-warning "writing 4 bytes into a region of size 3" } */
+T (a7, S4, 5, 4); // { dg-warning "writing 4 bytes into a region of size 2" } */
+T (a7, S4, 6, 4); // { dg-warning "writing 4 bytes into a region of size 1" } */
+T (a7, S4, 7, 4); // { dg-warning "writing 4 bytes into a region of size 0" } */
+
+T (a8, S3, 0, 4);
+T (a8, S3, 1, 4);
+T (a8, S3, 2, 4);
+T (a8, S3, 3, 4);
+T (a8, S3, 4, 4);
+T (a8, S3, 5, 4); // { dg-warning "writing 4 bytes into a region of size 3" } */
+T (a8, S3, 6, 4); // { dg-warning "writing 4 bytes into a region of size 2" } */
+T (a8, S3, 7, 4); // { dg-warning "writing 4 bytes into a region of size 1" } */
+T (a8, S3, 8, 4); // { dg-warning "writing 4 bytes into a region of size 0" } */
diff --git a/gcc/testsuite/gcc.dg/c11-builtins-1.c b/gcc/testsuite/gcc.dg/c11-builtins-1.c
new file mode 100644
index 00000000000..bfadf704714
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-builtins-1.c
@@ -0,0 +1,19 @@
+/* Test C11 built-in functions: test functions new in C2x are not
+ declared as built-in for C11. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11" } */
+
+int exp10 (void);
+int exp10f (void);
+int exp10l (void);
+int fabsd32 (void);
+int fabsd64 (void);
+int fabsd128 (void);
+int nand32 (void);
+int nand64 (void);
+int nand128 (void);
+int roundeven (void);
+int roundevenf (void);
+int roundevenl (void);
+int strdup (void);
+int strndup (void);
diff --git a/gcc/testsuite/gcc.dg/c2x-builtins-1.c b/gcc/testsuite/gcc.dg/c2x-builtins-1.c
new file mode 100644
index 00000000000..74760592cf8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-builtins-1.c
@@ -0,0 +1,13 @@
+/* Test C2x built-in functions: test functions new in C2x are indeed
+ declared as built-in as expected. Non-DFP tests. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x" } */
+
+int exp10 (void); /* { dg-warning "conflicting types for built-in function" } */
+int exp10f (void); /* { dg-warning "conflicting types for built-in function" } */
+int exp10l (void); /* { dg-warning "conflicting types for built-in function" } */
+int roundeven (void); /* { dg-warning "conflicting types for built-in function" } */
+int roundevenf (void); /* { dg-warning "conflicting types for built-in function" } */
+int roundevenl (void); /* { dg-warning "conflicting types for built-in function" } */
+int strdup (void); /* { dg-warning "conflicting types for built-in function" } */
+int strndup (void); /* { dg-warning "conflicting types for built-in function" } */
diff --git a/gcc/testsuite/gcc.dg/cr-decimal-dig-2.c b/gcc/testsuite/gcc.dg/cr-decimal-dig-2.c
new file mode 100644
index 00000000000..42e79d545cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cr-decimal-dig-2.c
@@ -0,0 +1,10 @@
+/* Test TS 18661-1 CR_DECIMAL_DIG: not in C2X without
+ __STDC_WANT_IEC_60559_BFP_EXT__ defined. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x" } */
+
+#include <float.h>
+
+#ifdef CR_DECIMAL_DIG
+#error "CR_DECIMAL_DIG defined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/dfp/c2x-builtins-dfp-1.c b/gcc/testsuite/gcc.dg/dfp/c2x-builtins-dfp-1.c
new file mode 100644
index 00000000000..88b8b334e71
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/c2x-builtins-dfp-1.c
@@ -0,0 +1,11 @@
+/* Test C2x built-in functions: test functions new in C2x are indeed
+ declared as built-in as expected. DFP tests. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x" } */
+
+int fabsd32 (void); /* { dg-warning "conflicting types for built-in function" } */
+int fabsd64 (void); /* { dg-warning "conflicting types for built-in function" } */
+int fabsd128 (void); /* { dg-warning "conflicting types for built-in function" } */
+int nand32 (void); /* { dg-warning "conflicting types for built-in function" } */
+int nand64 (void); /* { dg-warning "conflicting types for built-in function" } */
+int nand128 (void); /* { dg-warning "conflicting types for built-in function" } */
diff --git a/gcc/testsuite/gcc.dg/format/c2x-strftime-1.c b/gcc/testsuite/gcc.dg/format/c2x-strftime-1.c
new file mode 100644
index 00000000000..c6e7619e8a4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/c2x-strftime-1.c
@@ -0,0 +1,15 @@
+/* Test for strftime formats. Formats using C2x features. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic -Wformat" } */
+
+#include "format.h"
+
+void
+foo (char *s, size_t m, const struct tm *tp)
+{
+ strftime (s, m, "%Ob", tp);
+ strftime (s, m, "%OB", tp);
+ /* It's not clear that %h equivalence to %b means %Oh is equivalent
+ to %Ob; here we expect %Oh to be diagnosed. */
+ strftime (s, m, "%Oh", tp); /* { dg-warning "flag|modifier" "bad %Oh" } */
+}
diff --git a/gcc/testsuite/gcc.dg/ipa/inline-7.c b/gcc/testsuite/gcc.dg/ipa/inline-7.c
index 7dabb14f6b1..7c649114151 100644
--- a/gcc/testsuite/gcc.dg/ipa/inline-7.c
+++ b/gcc/testsuite/gcc.dg/ipa/inline-7.c
@@ -1,6 +1,6 @@
/* Check that early inliner works out that a is empty of parameter 0. */
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-einline-optimized -fopt-info-inline -fno-partial-inlining" } */
+/* { dg-options "-O2 -fdump-tree-einline-optimized -fopt-info-inline -fno-partial-inlining -fno-inline-functions" } */
void t(void);
int a (int b)
{
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-19.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-19.c
index adebaa5f5e1..d219411d8ba 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-sra-19.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-19.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
+/* { dg-skip-if "" { powerpc*-*-* } } */
typedef int __attribute__((__vector_size__(16))) vectype;
diff --git a/gcc/testsuite/gcc.dg/limits-width-2.c b/gcc/testsuite/gcc.dg/limits-width-2.c
new file mode 100644
index 00000000000..a3c38958ae4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/limits-width-2.c
@@ -0,0 +1,54 @@
+/* Test C2X width macros in <limits.h>. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x" } */
+
+#include <limits.h>
+
+#define CHECK_WIDTH(TYPE, MAX, WIDTH) \
+ _Static_assert ((MAX >> ((TYPE) -1 < 0 ? (WIDTH - 2) : (WIDTH - 1))) == 1, \
+ "width must match type")
+
+#ifndef CHAR_WIDTH
+# error "missing CHAR_WIDTH"
+#endif
+CHECK_WIDTH (char, CHAR_MAX, CHAR_WIDTH);
+#ifndef SCHAR_WIDTH
+# error "missing SCHAR_WIDTH"
+#endif
+CHECK_WIDTH (signed char, SCHAR_MAX, SCHAR_WIDTH);
+#ifndef UCHAR_WIDTH
+# error "missing UCHAR_WIDTH"
+#endif
+CHECK_WIDTH (unsigned char, UCHAR_MAX, UCHAR_WIDTH);
+#ifndef SHRT_WIDTH
+# error "missing SHRT_WIDTH"
+#endif
+CHECK_WIDTH (signed short, SHRT_MAX, SHRT_WIDTH);
+#ifndef USHRT_WIDTH
+# error "missing USHRT_WIDTH"
+#endif
+CHECK_WIDTH (unsigned short, USHRT_MAX, USHRT_WIDTH);
+#ifndef INT_WIDTH
+# error "missing INT_WIDTH"
+#endif
+CHECK_WIDTH (signed int, INT_MAX, INT_WIDTH);
+#ifndef UINT_WIDTH
+# error "missing UINT_WIDTH"
+#endif
+CHECK_WIDTH (unsigned int, UINT_MAX, UINT_WIDTH);
+#ifndef LONG_WIDTH
+# error "missing LONG_WIDTH"
+#endif
+CHECK_WIDTH (signed long, LONG_MAX, LONG_WIDTH);
+#ifndef ULONG_WIDTH
+# error "missing ULONG_WIDTH"
+#endif
+CHECK_WIDTH (unsigned long, ULONG_MAX, ULONG_WIDTH);
+#ifndef LLONG_WIDTH
+# error "missing LLONG_WIDTH"
+#endif
+CHECK_WIDTH (signed long long, LLONG_MAX, LLONG_WIDTH);
+#ifndef ULLONG_WIDTH
+# error "missing ULLONG_WIDTH"
+#endif
+CHECK_WIDTH (unsigned long long, ULLONG_MAX, ULLONG_WIDTH);
diff --git a/gcc/testsuite/gcc.dg/nonnull-3.c b/gcc/testsuite/gcc.dg/nonnull-3.c
index 6f7bc4f4295..c52fe2c830c 100644
--- a/gcc/testsuite/gcc.dg/nonnull-3.c
+++ b/gcc/testsuite/gcc.dg/nonnull-3.c
@@ -9,11 +9,11 @@
void
foo (void *p, char *s)
{
- __builtin_bzero (NULL, 0);
- __builtin_bcopy (NULL, p, 0);
- __builtin_bcopy (p, NULL, 0);
- __builtin_bcmp (NULL, p, 0);
- __builtin_bcmp (p, NULL, 0);
+ __builtin_bzero (NULL, 0); /* { dg-warning "null" "pr80936" } */
+ __builtin_bcopy (NULL, p, 0); /* { dg-warning "null" "pr80936" } */
+ __builtin_bcopy (p, NULL, 0); /* { dg-warning "null" "pr80936" } */
+ __builtin_bcmp (NULL, p, 0); /* { dg-warning "null" "pr80936" } */
+ __builtin_bcmp (p, NULL, 0); /* { dg-warning "null" "pr80936" } */
__builtin_index (NULL, 16); /* { dg-warning "null" "null pointer check" } */
__builtin_rindex (NULL, 16); /* { dg-warning "null" "null pointer check" } */
diff --git a/gcc/testsuite/gcc.dg/optimize-bswapsi-5.c b/gcc/testsuite/gcc.dg/optimize-bswapsi-5.c
index 5819fd7193c..b4d8b9a8dd9 100644
--- a/gcc/testsuite/gcc.dg/optimize-bswapsi-5.c
+++ b/gcc/testsuite/gcc.dg/optimize-bswapsi-5.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target bswap } */
-/* { dg-options "-O2 -fdump-tree-bswap" } */
+/* { dg-options "-O2 -fdump-tree-bswap -fno-inline-functions" } */
/* { dg-additional-options "-march=z900" { target s390-*-* } } */
struct L { unsigned int l[2]; };
diff --git a/gcc/testsuite/gcc.dg/pr87047.c b/gcc/testsuite/gcc.dg/pr87047.c
new file mode 100644
index 00000000000..cb26ea4deab
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87047.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && { ! ia32 } } } } */
+/* { dg-options "-fdump-rtl-ce1 -O2" } */
+
+typedef unsigned long long uint64_t;
+
+static uint64_t umulh(uint64_t a, uint64_t b)
+{
+ return (unsigned __int128)a*b >> 64;
+}
+
+uint64_t f(uint64_t a, uint64_t b, int c)
+{
+ if (c)
+ a = umulh(a, (b-umulh(a,b))<<44) << 1;
+ return a;
+}
+
+/* { dg-final { scan-rtl-dump "0 true changes made" "ce1" } } */
+/* { dg-final { scan-assembler-not "cmov" } } */
diff --git a/gcc/testsuite/gcc.dg/pr91734.c b/gcc/testsuite/gcc.dg/pr91734.c
new file mode 100644
index 00000000000..1cc3e40ccbc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr91734.c
@@ -0,0 +1,97 @@
+/* PR tree-optimization/91734 */
+/* { dg-do run } */
+/* { dg-add-options ieee } */
+/* { dg-additional-options "-O2 -std=gnu99" } */
+
+__attribute__((noipa, optimize ("Ofast"))) int
+f1 (float x)
+{
+ return __builtin_sqrtf (x) < __FLT_MIN__;
+}
+
+__attribute__((noipa, optimize ("Ofast"))) int
+f2 (float x)
+{
+ return __builtin_sqrtf (x) < 0x1.2dd3d0p-65f;
+}
+
+__attribute__((noipa, optimize ("Ofast"))) int
+f3 (float x)
+{
+ return __builtin_sqrtf (x) >= 0x1.2dd3d0p-65f;
+}
+
+__attribute__((noipa, optimize ("Ofast"))) int
+f4 (float x)
+{
+ return __builtin_sqrtf (x) >= 0x1.5642e6p+54f;
+}
+
+__attribute__((noipa, optimize ("Ofast"))) int
+f5 (float x)
+{
+ return __builtin_sqrtf (x) > 0x1.5642e6p+54f;
+}
+
+__attribute__((noipa, optimize ("Ofast"))) int
+f6 (float x)
+{
+ return __builtin_sqrtf (x) < 0x1.4da1cp-19f;
+}
+
+__attribute__((noipa, optimize ("Ofast"))) int
+f7 (float x)
+{
+ return __builtin_sqrtf (x) <= 0x1.4da1cp-19f;
+}
+
+__attribute__((noipa, optimize ("Ofast"))) int
+f8 (float x)
+{
+ return __builtin_sqrtf (x) < 0x1.50cb62p-65f;
+}
+
+__attribute__((noipa, optimize ("Ofast"))) int
+f9 (float x)
+{
+ return __builtin_sqrtf (x) <= 0x1.4fc00cp-73f;
+}
+
+__attribute__((noipa, optimize ("Ofast"))) int
+f10 (float x)
+{
+ return __builtin_sqrtf (x) < 0x1.001002p+0f;
+}
+
+int
+main ()
+{
+ if (__FLT_RADIX__ != 2
+ || __FLT_MANT_DIG__ != 24
+ || __FLT_MIN_EXP__ != -125
+ || __FLT_MAX_EXP__ != 128
+ || __FLT_HAS_DENORM__ != 1
+ || __FLT_HAS_INFINITY__ != 1)
+ return 0;
+ if (!f1 (0.0f) || f1 (0x1.0p-149f))
+ __builtin_abort ();
+ if (!f2 (0x1.63dbc0p-130f))
+ __builtin_abort ();
+ if (f3 (0x1.63dbc0p-130f))
+ __builtin_abort ();
+ if (!f4 (0x1.c996d0p+108f) || !f4 (0x1.c996cep+108f) || f4 (0x1.c996ccp+108f))
+ __builtin_abort ();
+ if (f5 (0x1.c996d0p+108f) || f5 (0x1.c996d2p+108f) || !f5 (0x1.c996d4p+108f))
+ __builtin_abort ();
+ if (!f6 (0x1.b2ce3p-38f) || f6 (0x1.b2ce32p-38f) || f6 (0x1.b2ce34p-38f))
+ __builtin_abort ();
+ if (!f7 (0x1.b2ce3p-38f) || !f7 (0x1.b2ce34p-38f) || !f7 (0x1.b2ce36p-38f) || f7 (0x1.b2ce38p-38f))
+ __builtin_abort ();
+ if (!f8 (0x1.bb166p-130f) || !f8 (0x1.bb168p-130f) || f8 (0x1.bb16ap-130f) || f8 (0x1.bb16cp-130f))
+ __builtin_abort ();
+ if (!f9 (0x1.8p-146f) || !f9 (0x1.ap-146f) || f9 (0x1.cp-146f) || f9 (0x1.ep-146f))
+ __builtin_abort ();
+ if (f10 (0x1.002004p+0f))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sinhovercosh-1.c b/gcc/testsuite/gcc.dg/sinhovercosh-1.c
new file mode 100644
index 00000000000..7e510727af8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sinhovercosh-1.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-optimized" } */
+
+extern float sinhf (float);
+extern float coshf (float);
+extern float tanhf (float);
+extern float sqrtf (float);
+extern double sinh (double);
+extern double cosh (double);
+extern double sqrt (double);
+extern double tanh (double);
+extern long double sinhl (long double);
+extern long double coshl (long double);
+extern long double tanhl (long double);
+extern long double sqrtl (long double);
+
+double __attribute__ ((noinline))
+sinhovercosh_ (double x)
+{
+ return sinh (x) / cosh (x);
+}
+
+float __attribute__ ((noinline))
+sinhfovercoshf_(float x)
+{
+ return sinhf (x) / coshf (x);
+}
+
+long double __attribute__ ((noinline))
+sinhlovercoshl_ (long double x)
+{
+ return sinhl (x) / coshl (x);
+}
+
+/* There must be no calls to sinh, cosh, or atanh */
+/* {dg-final { scan-tree-dump-not "sinh " "optimized" } } */
+/* {dg-final { scan-tree-dump-not "cosh " "optimized" } } */
+/* {dg-final { scan-tree-dump-not "sinfh " "optimized" } } */
+/* {dg-final { scan-tree-dump-not "cosfh " "optimized" } } */
+/* {dg-final { scan-tree-dump-not "sinlh " "optimized" } } */
+/* {dg-final { scan-tree-dump-not "coslh " "optimized" } } */
+/* {dg-final { scan-tree-dump-times "tanh " "1" "optimized" }} */
+/* {dg-final { scan-tree-dump-times "tanhl " "1" "optimized" }} */
+/* {dg-final { scan-tree-dump-times "tanhf " "1" "optimized" }} */
+
diff --git a/gcc/testsuite/gcc.dg/stdint-width-2.c b/gcc/testsuite/gcc.dg/stdint-width-2.c
new file mode 100644
index 00000000000..9838cb27612
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/stdint-width-2.c
@@ -0,0 +1,175 @@
+/* Test C2X width macros in <stdint.h>. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -ffreestanding" } */
+/* { dg-additional-options "-DSIGNAL_SUPPRESS" { target { ! signal } } } */
+
+#include <stddef.h>
+#include <stdint.h>
+#ifndef SIGNAL_SUPPRESS
+#include <signal.h>
+#endif
+typedef __WINT_TYPE__ wint_t;
+
+#define CHECK_WIDTH(TYPE, MAX, WIDTH) \
+ _Static_assert ((MAX >> ((TYPE) -1 < 0 ? (WIDTH - 2) : (WIDTH - 1))) == 1, \
+ "width must match type")
+
+#ifdef INT8_MAX
+# ifndef INT8_WIDTH
+# error "missing INT8_WIDTH"
+# endif
+CHECK_WIDTH (int8_t, INT8_MAX, INT8_WIDTH);
+#endif
+#ifdef INT16_MAX
+# ifndef INT16_WIDTH
+# error "missing INT16_WIDTH"
+# endif
+CHECK_WIDTH (int16_t, INT16_MAX, INT16_WIDTH);
+#endif
+#ifdef INT32_MAX
+# ifndef INT32_WIDTH
+# error "missing INT32_WIDTH"
+# endif
+CHECK_WIDTH (int32_t, INT32_MAX, INT32_WIDTH);
+#endif
+#ifdef INT64_MAX
+# ifndef INT64_WIDTH
+# error "missing INT64_WIDTH"
+# endif
+CHECK_WIDTH (int64_t, INT64_MAX, INT64_WIDTH);
+#endif
+#ifdef UINT8_MAX
+# ifndef UINT8_WIDTH
+# error "missing UINT8_WIDTH"
+# endif
+CHECK_WIDTH (uint8_t, UINT8_MAX, UINT8_WIDTH);
+#endif
+#ifdef UINT16_MAX
+# ifndef UINT16_WIDTH
+# error "missing UINT16_WIDTH"
+# endif
+CHECK_WIDTH (uint16_t, UINT16_MAX, UINT16_WIDTH);
+#endif
+#ifdef UINT32_MAX
+# ifndef UINT32_WIDTH
+# error "missing UINT32_WIDTH"
+# endif
+CHECK_WIDTH (uint32_t, UINT32_MAX, UINT32_WIDTH);
+#endif
+#ifdef UINT64_MAX
+# ifndef UINT64_WIDTH
+# error "missing UINT64_WIDTH"
+# endif
+CHECK_WIDTH (uint64_t, UINT64_MAX, UINT64_WIDTH);
+#endif
+
+#ifndef INT_LEAST8_WIDTH
+# error "missing INT_LEAST8_WIDTH"
+#endif
+CHECK_WIDTH (int_least8_t, INT_LEAST8_MAX, INT_LEAST8_WIDTH);
+#ifndef INT_LEAST16_WIDTH
+# error "missing INT_LEAST16_WIDTH"
+#endif
+CHECK_WIDTH (int_least16_t, INT_LEAST16_MAX, INT_LEAST16_WIDTH);
+#ifndef INT_LEAST32_WIDTH
+# error "missing INT_LEAST32_WIDTH"
+#endif
+CHECK_WIDTH (int_least32_t, INT_LEAST32_MAX, INT_LEAST32_WIDTH);
+#ifndef INT_LEAST64_WIDTH
+# error "missing INT_LEAST64_WIDTH"
+#endif
+CHECK_WIDTH (int_least64_t, INT_LEAST64_MAX, INT_LEAST64_WIDTH);
+#ifndef INT_LEAST8_WIDTH
+# error "missing INT_LEAST8_WIDTH"
+#endif
+CHECK_WIDTH (uint_least8_t, UINT_LEAST8_MAX, UINT_LEAST8_WIDTH);
+#ifndef UINT_LEAST16_WIDTH
+# error "missing UINT_LEAST16_WIDTH"
+#endif
+CHECK_WIDTH (uint_least16_t, UINT_LEAST16_MAX, UINT_LEAST16_WIDTH);
+#ifndef UINT_LEAST32_WIDTH
+# error "missing UINT_LEAST32_WIDTH"
+#endif
+CHECK_WIDTH (uint_least32_t, UINT_LEAST32_MAX, UINT_LEAST32_WIDTH);
+#ifndef UINT_LEAST64_WIDTH
+# error "missing UINT_LEAST64_WIDTH"
+#endif
+CHECK_WIDTH (uint_least64_t, UINT_LEAST64_MAX, UINT_LEAST64_WIDTH);
+
+#ifndef INT_FAST8_WIDTH
+# error "missing INT_FAST8_WIDTH"
+#endif
+CHECK_WIDTH (int_fast8_t, INT_FAST8_MAX, INT_FAST8_WIDTH);
+#ifndef INT_FAST16_WIDTH
+# error "missing INT_FAST16_WIDTH"
+#endif
+CHECK_WIDTH (int_fast16_t, INT_FAST16_MAX, INT_FAST16_WIDTH);
+#ifndef INT_FAST32_WIDTH
+# error "missing INT_FAST32_WIDTH"
+#endif
+CHECK_WIDTH (int_fast32_t, INT_FAST32_MAX, INT_FAST32_WIDTH);
+#ifndef INT_FAST64_WIDTH
+# error "missing INT_FAST64_WIDTH"
+#endif
+CHECK_WIDTH (int_fast64_t, INT_FAST64_MAX, INT_FAST64_WIDTH);
+#ifndef INT_FAST8_WIDTH
+# error "missing INT_FAST8_WIDTH"
+#endif
+CHECK_WIDTH (uint_fast8_t, UINT_FAST8_MAX, UINT_FAST8_WIDTH);
+#ifndef UINT_FAST16_WIDTH
+# error "missing UINT_FAST16_WIDTH"
+#endif
+CHECK_WIDTH (uint_fast16_t, UINT_FAST16_MAX, UINT_FAST16_WIDTH);
+#ifndef UINT_FAST32_WIDTH
+# error "missing UINT_FAST32_WIDTH"
+#endif
+CHECK_WIDTH (uint_fast32_t, UINT_FAST32_MAX, UINT_FAST32_WIDTH);
+#ifndef UINT_FAST64_WIDTH
+# error "missing UINT_FAST64_WIDTH"
+#endif
+CHECK_WIDTH (uint_fast64_t, UINT_FAST64_MAX, UINT_FAST64_WIDTH);
+
+#ifdef INTPTR_MAX
+# ifndef INTPTR_WIDTH
+# error "missing INTPTR_WIDTH"
+# endif
+CHECK_WIDTH (intptr_t, INTPTR_MAX, INTPTR_WIDTH);
+#endif
+#ifdef UINTPTR_MAX
+# ifndef UINTPTR_WIDTH
+# error "missing UINTPTR_WIDTH"
+# endif
+CHECK_WIDTH (uintptr_t, UINTPTR_MAX, UINTPTR_WIDTH);
+#endif
+
+#ifndef INTMAX_WIDTH
+# error "missing INTMAX_WIDTH"
+#endif
+CHECK_WIDTH (intmax_t, INTMAX_MAX, INTMAX_WIDTH);
+#ifndef UINTMAX_WIDTH
+# error "missing UINTMAX_WIDTH"
+#endif
+CHECK_WIDTH (uintmax_t, UINTMAX_MAX, UINTMAX_WIDTH);
+
+#ifndef PTRDIFF_WIDTH
+# error "missing PTRDIFF_WIDTH"
+#endif
+CHECK_WIDTH (ptrdiff_t, PTRDIFF_MAX, PTRDIFF_WIDTH);
+#ifndef SIGNAL_SUPPRESS
+# ifndef SIG_ATOMIC_WIDTH
+# error "missing SIG_ATOMIC_WIDTH"
+# endif
+CHECK_WIDTH (sig_atomic_t, SIG_ATOMIC_MAX, SIG_ATOMIC_WIDTH);
+#endif
+#ifndef SIZE_WIDTH
+# error "missing SIZE_WIDTH"
+#endif
+CHECK_WIDTH (size_t, SIZE_MAX, SIZE_WIDTH);
+#ifndef WCHAR_WIDTH
+# error "missing WCHAR_WIDTH"
+#endif
+CHECK_WIDTH (wchar_t, WCHAR_MAX, WCHAR_WIDTH);
+#ifndef WINT_WIDTH
+# error "missing WINT_WIDTH"
+#endif
+CHECK_WIDTH (wint_t, WINT_MAX, WINT_WIDTH);
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-fp-int-inexact-c2x.c b/gcc/testsuite/gcc.dg/torture/builtin-fp-int-inexact-c2x.c
new file mode 100644
index 00000000000..039cb5392fe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/builtin-fp-int-inexact-c2x.c
@@ -0,0 +1,7 @@
+/* Test C2X enables -fno-fp-int-builtin-inexact. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x" } */
+/* { dg-add-options c99_runtime } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include "builtin-fp-int-inexact.c"
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cunroll-2.c b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-2.c
index b1d1c7d3d85..ae3fec99749 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/cunroll-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -fdump-tree-cunroll-details" } */
+/* { dg-options "-O3 -fdump-tree-cunrolli-details" } */
int a[2];
int test2 (void);
void
@@ -14,4 +14,4 @@ test(int c)
}
}
/* We are not able to get rid of the final conditional because the loop has two exits. */
-/* { dg-final { scan-tree-dump "loop with 1 iterations completely unrolled" "cunroll"} } */
+/* { dg-final { scan-tree-dump "loop with 2 iterations completely unrolled" "cunrolli"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c
index 1bf79fc68b1..fff731e8cfc 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-thread2-details -fdump-tree-thread3-details -fdump-tree-thread4-details -fno-finite-loops" } */
+/* { dg-options "-O2 -fdump-tree-thread2-details -fdump-tree-thread3-details -fdump-tree-thread4-details -fno-finite-loops --param early-inlining-insns-O2=14 -fno-inline-functions" } */
/* { dg-final { scan-tree-dump "FSM" "thread2" } } */
/* { dg-final { scan-tree-dump "FSM" "thread3" } } */
/* { dg-final { scan-tree-dump "FSM" "thread4" { xfail *-*-* } } } */
@@ -56,7 +56,7 @@ bmp_iter_and_compl (bitmap_iterator * bi, unsigned *bit_no)
}
extern int VEC_int_base_length (VEC_int_base *);
-static __inline__ bitmap
+bitmap
compute_idf (bitmap def_blocks, bitmap_head * dfs)
{
bitmap_iterator bi;
diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-101.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-101.c
index 91eb28218bd..ce934279ddf 100644
--- a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-101.c
+++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-101.c
@@ -22,6 +22,7 @@ int main1 (int x, int y) {
p = (struct extraction *) malloc (sizeof (struct extraction));
/* Not vectorizable: different unknown offset. */
+#pragma GCC unroll 0
for (i = 0; i < N; i++)
{
*((int *)p + x + i) = a[i];
diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-102.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-102.c
index 51f62788dbf..d9e0529e73f 100644
--- a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-102.c
+++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-102.c
@@ -28,6 +28,7 @@ int main1 (int x, int y) {
}
/* Not vectorizable: distance 1. */
+#pragma GCC unroll 0
for (i = 0; i < N - 1; i++)
{
*((int *)p + x + i + 1) = *((int *)p + x + i);
diff --git a/gcc/testsuite/gcc.dg/vect/pr79920.c b/gcc/testsuite/gcc.dg/vect/pr79920.c
index 276a2806f0c..38e0fef779a 100644
--- a/gcc/testsuite/gcc.dg/vect/pr79920.c
+++ b/gcc/testsuite/gcc.dg/vect/pr79920.c
@@ -14,6 +14,7 @@ compute_integral (double w_1[18])
for (int ip_1 = 0; ip_1 < 2; ++ip_1)
{
+#pragma GCC unroll 0
for (int i_0 = 0; i_0 < 6; ++i_0)
t33[ip_1][i_0] = ((w_1[i_0*3] * t32[ip_1][0])
+ (w_1[i_0*3+2] * t32[ip_1][2]));
diff --git a/gcc/testsuite/gcc.dg/vect/pr83202-1.c b/gcc/testsuite/gcc.dg/vect/pr83202-1.c
index 33c83de29b8..ac12f079839 100644
--- a/gcc/testsuite/gcc.dg/vect/pr83202-1.c
+++ b/gcc/testsuite/gcc.dg/vect/pr83202-1.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-require-effective-target vect_double } */
-void test(double data[8][8])
+void test(double data[16][16])
{
- for (int i = 0; i < 8; i++)
+ for (int i = 0; i < 16; i++)
{
for (int j = 0; j < i; j+=4)
{
diff --git a/gcc/testsuite/gcc.dg/vect/vect-105.c b/gcc/testsuite/gcc.dg/vect/vect-105.c
index 0024457f9e2..17b6e89d8f6 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-105.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-105.c
@@ -35,6 +35,7 @@ int main1 (int x) {
/* Vectorizable: distance > number of iterations. */
for (i = 1; i < N; i++)
{
+#pragma GCC unroll 0
for (j = 0; j < N; j++)
{
*((int *)p + x + i + j) = *((int *)p + x + i + j + 5);
diff --git a/gcc/testsuite/gcc.dg/vect/vect-93.c b/gcc/testsuite/gcc.dg/vect/vect-93.c
index 397c2ed05aa..c3e12783b2c 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-93.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-93.c
@@ -29,6 +29,7 @@ main1 (float *pa)
abort ();
}
+#pragma GCC unroll 0
for (i = 1; i <= N2; i++)
{
pa[i] = 3.0;
diff --git a/gcc/testsuite/gcc.dg/vect/vect-bswap16.c b/gcc/testsuite/gcc.dg/vect/vect-bswap16.c
index 3c98b07e425..d29b352b832 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-bswap16.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-bswap16.c
@@ -1,4 +1,4 @@
-/* { dg-require-effective-target vect_bswap } */
+/* { dg-additional-options "-msse4" { target sse4_runtime } } */
#include "tree-vect.h"
@@ -39,4 +39,4 @@ main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_bswap || sse4_runtime } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-bswap16a.c b/gcc/testsuite/gcc.dg/vect/vect-bswap16a.c
new file mode 100644
index 00000000000..730dc4e8352
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-bswap16a.c
@@ -0,0 +1,5 @@
+/* { dg-additional-options "-msse2 -mno-sse3" { target sse2_runtime } } */
+
+#include "vect-bswap16.c"
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_shift } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-double-reduc-6.c b/gcc/testsuite/gcc.dg/vect/vect-double-reduc-6.c
index 3a4f087da81..85aec1bf609 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-double-reduc-6.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-double-reduc-6.c
@@ -19,6 +19,7 @@ foo ()
{
sum = 1;
for (j = 0; j < K; j++)
+#pragma GCC unroll 0
for (i = 0; i < K; i++)
sum *= in[i+k][j];
out[k] = sum;
diff --git a/gcc/testsuite/gcc.dg/vect/vect-profile-1.c b/gcc/testsuite/gcc.dg/vect/vect-profile-1.c
index 93d7ad13147..922f965806f 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-profile-1.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-profile-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target vect_int } */
-/* { dg-additional-options "-fdump-tree-vect-details-blocks" } */
+/* { dg-additional-options "-fdump-tree-vect-details-blocks -fdisable-tree-cunrolli" } */
/* At least one of these should correspond to a full vector. */
diff --git a/gcc/testsuite/gcc.dg/winline-3.c b/gcc/testsuite/gcc.dg/winline-3.c
index 7b7c8c5b9eb..7043a276025 100644
--- a/gcc/testsuite/gcc.dg/winline-3.c
+++ b/gcc/testsuite/gcc.dg/winline-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Winline -O2 --param max-inline-insns-single=1 --param inline-min-speedup=100 -fgnu89-inline" } */
+/* { dg-options "-Winline -O2 --param max-inline-insns-single-O2=1 --param inline-min-speedup-O2=100 -fgnu89-inline" } */
void big (void);
inline int q(void) /* { dg-warning "max-inline-insns-single" } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/shracc_1.c b/gcc/testsuite/gcc.target/aarch64/sve2/shracc_1.c
index 5535c7dded6..8111237d5a5 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve2/shracc_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/shracc_1.c
@@ -24,9 +24,9 @@ SHRACC (uint64_t, 53);
/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 8 "vect" } } */
-/* { dg-final { scan-assembler-not {\tasr\t} } } */
-/* { dg-final { scan-assembler-not {\tlsr\t} } } */
-/* { dg-final { scan-assembler-not {\tadd\t} } } */
+/* { dg-final { scan-assembler-not {\tasr\tz[0-9]+\.[bhsd]} } } */
+/* { dg-final { scan-assembler-not {\tlsr\tz[0-9]+\.[bhsd]} } } */
+/* { dg-final { scan-assembler-not {\tadd\tz[0-9]+\.[bhsd]} } } */
/* { dg-final { scan-assembler-times {\tssra\tz[0-9]+\.b, z[0-9]+\.b, #5\n} 1 } } */
/* { dg-final { scan-assembler-times {\tssra\tz[0-9]+\.h, z[0-9]+\.h, #14\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-8.c b/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-8.c
index 6463f6c5066..f3be8e76eae 100644
--- a/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-8.c
+++ b/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-8.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99 -mlittle-endian" } */
/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
#include <arm_neon.h>
@@ -18,3 +18,5 @@ g (int64x2x4_t *ptr)
/* { dg-final { scan-assembler-times {\tld1\t} 1 } } */
/* { dg-final { scan-assembler-times {\tst1\t} 1 } } */
+/* { dg-final { scan-assembler-not {\tld[pr]\tq} } } */
+/* { dg-final { scan-assembler-not {\tst[pr]\tq} } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr71801.c b/gcc/testsuite/gcc.target/i386/pr71801.c
index 6c87522f31d..4f1cb190233 100644
--- a/gcc/testsuite/gcc.target/i386/pr71801.c
+++ b/gcc/testsuite/gcc.target/i386/pr71801.c
@@ -16,7 +16,7 @@ static int get_label_uuid(char *p1) {
}
void uuidcache_addentry(char *p1) { __builtin_memcpy(&c, p1, sizeof(c)); }
void uuidcache_init() {
- char d[1];
+ char d[sizeof(a) + sizeof(c)];
get_label_uuid(d);
uuidcache_addentry(d);
}
diff --git a/gcc/testsuite/gcc.target/i386/pr91994.c b/gcc/testsuite/gcc.target/i386/pr91994.c
new file mode 100644
index 00000000000..033be68e7d0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr91994.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx } */
+/* { dg-options "-O2 -mavx -mvzeroupper" } */
+
+#include "avx-check.h"
+
+#include <immintrin.h>
+
+__m256i x1, x2, x3;
+
+__attribute__ ((noinline))
+static void
+foo (void)
+{
+ x1 = x2;
+}
+
+void
+bar (void)
+{
+ __m256i x = x1;
+ foo ();
+ x3 = x;
+}
+
+__attribute__ ((noinline))
+void
+avx_test (void)
+{
+ __m256i x = _mm256_set1_epi8 (3);
+ x1 = x;
+ bar ();
+ if (__builtin_memcmp (&x3, &x, sizeof (x)))
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.target/mips/call-clobbered-3.c b/gcc/testsuite/gcc.target/mips/call-clobbered-3.c
index fce4d991245..3a9e8d883fc 100644
--- a/gcc/testsuite/gcc.target/mips/call-clobbered-3.c
+++ b/gcc/testsuite/gcc.target/mips/call-clobbered-3.c
@@ -1,7 +1,5 @@
/* Check that we handle call-clobbered FPRs correctly. */
/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
-/* Refer to call-clobbered-4.c to see the expected output from -Os builds. */
-/* { dg-skip-if "uses callee-saved GPR" { *-*-* } { "-Os" } { "" } } */
/* { dg-options "-mabi=32 -modd-spreg -mfpxx -ffixed-f0 -ffixed-f1 -ffixed-f2 -ffixed-f3 -ffixed-f4 -ffixed-f5 -ffixed-f6 -ffixed-f7 -ffixed-f8 -ffixed-f9 -ffixed-f10 -ffixed-f11 -ffixed-f12 -ffixed-f13 -ffixed-f14 -ffixed-f15 -ffixed-f16 -ffixed-f17 -ffixed-f18 -ffixed-f19 -ffixed-f20 -ffixed-f22 -ffixed-f24 -ffixed-f26 -ffixed-f28 -ffixed-f30" } */
void bar (void);
diff --git a/gcc/testsuite/gcc.target/mips/call-clobbered-4.c b/gcc/testsuite/gcc.target/mips/call-clobbered-4.c
deleted file mode 100644
index 51498b8fa28..00000000000
--- a/gcc/testsuite/gcc.target/mips/call-clobbered-4.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Check that we handle call-clobbered FPRs correctly.
- This test differs from call-clobbered-3.c because when optimising for size
- a callee-saved GPR is used for 'b' to cross the call. */
-/* { dg-skip-if "code quality test" { *-*-* } { "*" } { "-Os" } } */
-/* { dg-options "-mabi=32 -modd-spreg -mfpxx -ffixed-f0 -ffixed-f1 -ffixed-f2 -ffixed-f3 -ffixed-f4 -ffixed-f5 -ffixed-f6 -ffixed-f7 -ffixed-f8 -ffixed-f9 -ffixed-f10 -ffixed-f11 -ffixed-f12 -ffixed-f13 -ffixed-f14 -ffixed-f15 -ffixed-f16 -ffixed-f17 -ffixed-f18 -ffixed-f19 -ffixed-f20 -ffixed-f22 -ffixed-f24 -ffixed-f26 -ffixed-f28 -ffixed-f30" } */
-
-void bar (void);
-float a;
-float
-foo ()
-{
- float b = a + 1.0f;
- bar();
- return b;
-}
-/* { dg-final { scan-assembler-times "lwc1" 4 } } */
-/* { dg-final { scan-assembler-times "swc1" 2 } } */
-/* { dg-final { scan-assembler-times "mtc" 1 } } */
-/* { dg-final { scan-assembler-times "mfc" 1 } } */
-/* { dg-final { scan-assembler-not "mthc" } } */
-/* { dg-final { scan-assembler-not "mfhc" } } */
-/* { dg-final { scan-assembler-not "ldc1" } } */
-/* { dg-final { scan-assembler-not "sdc1" } } */
diff --git a/gcc/testsuite/gcc.target/mips/pr91769.c b/gcc/testsuite/gcc.target/mips/pr91769.c
new file mode 100644
index 00000000000..c9ad70d7f75
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/pr91769.c
@@ -0,0 +1,19 @@
+/* PR target/91769 */
+/* { dg-do compile } */
+/* { dg-skip-if "naming registers makes this a code quality test" { *-*-* } { "-O0" "-g" } { "" } } */
+/* { dg-options "-EL -mgp32 -mhard-float" } */
+
+NOCOMPRESSION double
+foo (void)
+{
+ register double* pf __asm__ ("$a1");
+ __asm__ __volatile__ ("":"=r"(pf));
+ double f = *pf;
+
+ if (f != f)
+ f = -f;
+ return f;
+}
+
+/* { dg-final { scan-assembler-not "lw\t\\\$4,0\\(\\\$5\\)\n\tlw\t\\\$5,4\\(\\\$5\\)\n\tldc1\t\\\$.*,0\\(\\\$5\\)" } } */
+/* { dg-final { scan-assembler "lw\t\\\$4,0\\(\\\$5\\)\n\tlw\t\\\$5,4\\(\\\$5\\)\n\tmtc1\t\\\$4,\\\$.*\n\tmthc1\t\\\$5,\\\$.*" } } */
diff --git a/gcc/testsuite/gcc.target/msp430/430x-insns.c b/gcc/testsuite/gcc.target/msp430/430x-insns.c
new file mode 100644
index 00000000000..a67f778371a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/430x-insns.c
@@ -0,0 +1,1646 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-mcpu=msp430" "-mcpu=430" "-msmall" } { "" } } */
+/* { dg-options "-O1 -mlarge" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* The purpose of this test is to check that all insn patters in msp430.md
+ which use the "Yx" constraint work as expected.
+ So when both of the operands are in lower memory, a 430 instruction is
+ generated, and when at least one of the operands might be in upper memory,
+ a 430X instruction is generated.
+ We do not need to extensively test the situation where one of the operands
+ in an insn is not a mem (i.e. it is a register or immediate). A single test
+ will verify that the constraint correctly assumes that a reg
+ or immediate does not itself require a 430X instruction. */
+
+typedef char qi;
+typedef int hi;
+/* For insns which use the QHI mode iterator (therefore accepting QI, HI and
+ PSI modes), we also check the PSImode version. All insns should be 430x
+ in that case. */
+typedef __int20 psi;
+typedef long si;
+
+#define ATTR_EITHER __attribute__((either))
+#define ATTR_LOWER __attribute__((lower))
+
+/* Use these to generate 430X insns. */
+qi ATTR_EITHER eqi1, eqi2, eqi3, eqi4, eqi5, eqi6;
+hi ATTR_EITHER ehi1, ehi2, ehi3, ehi4, ehi5, ehi6;
+psi ATTR_EITHER epsi1, epsi2, epsi3, epsi4, epsi5, epsi6;
+si ATTR_EITHER esi1, esi2, esi3, esi4, esi5, esi6;
+
+/* Use these to generate 430 insns. */
+qi ATTR_LOWER lqi1, lqi2, lqi3, lqi4, lqi5, lqi6;
+hi ATTR_LOWER lhi1, lhi2, lhi3, lhi4, lhi5, lhi6;
+psi ATTR_LOWER lpsi1, lpsi2, lpsi3, lpsi4, lpsi5, lpsi6;
+si ATTR_LOWER lsi1, lsi2, lsi3, lsi4, lsi5, lsi6;
+
+/* The default data region is "lower", so these behave the same as the above
+ "l*" variables unless -mdata-region={upper,either,none} is passed. */
+qi qi1, qi2, qi3, qi4, qi5, qi6;
+hi hi1, hi2, hi3, hi4, hi5, hi6;
+psi psi1, psi2, psi3, psi4, psi5, psi6;
+si si1, si2, si3, si4, si5, si6;
+
+qi use_qi(qi a);
+hi use_hi(hi a);
+psi use_psi(psi a);
+si use_si(si a);
+
+#define USE_MODE(MODE) use_ ## MODE
+#define USE_MODE_N(MODE,N) use_ ## N ## MODE
+
+#define E_VAR(MODE,N) e ## MODE ## N
+#define L_VAR(MODE,N) l ## MODE ## N
+#define VAR(MODE,N) MODE ## N
+
+#define REG_VAR(MODE,N) MODE ## r ## N
+
+/* Verify that a register operand does not influence whether a 430X instruction
+ is used or not. */
+/*
+** register_operand: { target msp430_region_lower }
+** ...
+** MOV.B &lqi1, R12
+** ...
+** MOV.B &qi1, R12
+** ...
+** MOVX.B &eqi1, R12
+** ...
+*/
+/*
+** register_operand: { target msp430_region_not_lower }
+** ...
+** MOV.B &lqi1, R12
+** ...
+** MOVX.B &qi1, R12
+** ...
+** MOVX.B &eqi1, R12
+** ...
+*/
+
+void
+register_operand (void)
+{
+ use_qi (lqi1);
+ use_qi (qi1);
+ use_qi (eqi1);
+}
+
+/* Verify that an immediate operand does not influence whether a 430X instruction
+ is used or not. */
+/*
+** immediate_operand: { target msp430_region_lower }
+** ...
+** MOV.B #1, &lqi1
+** MOV.B #2, &qi1
+** MOVX.B #3, &eqi1
+** ...
+*/
+/*
+** immediate_operand: { target msp430_region_not_lower }
+** ...
+** MOV.B #1, &lqi1
+** MOVX.B #2, &qi1
+** MOVX.B #3, &eqi1
+** ...
+*/
+void
+immediate_operand (void)
+{
+ lqi1 = 1;
+ qi1 = 2;
+ eqi1 = 3;
+}
+
+/* Verify that variables marked with the noinit, persistent, section and lower
+ attributes have the appropriate format instructions generated to handle
+ them. */
+int __attribute__((persistent)) pp = 10;
+int __attribute__((noinit)) nn;
+int __attribute__((section(".data.foo"))) s;
+int __attribute__((section(".data.foo"),lower)) sl1;
+int __attribute__((lower,section(".data.foo"))) sl2;
+
+/*
+** attrs:
+** ...
+** MOVX.W #1, &pp
+** MOV.W #2, &nn
+** MOVX.W #3, &s
+** MOV.W #4, &sl1
+** MOV.W #5, &sl2
+** ...
+*/
+void
+attrs (void)
+{
+ pp = 1;
+ nn = 2;
+ s = 3;
+ sl1 = 4;
+ sl2 = 5;
+}
+
+#define MOV_INSNS(MODE) \
+ E_VAR(MODE, 1) = E_VAR(MODE, 2); \
+ E_VAR(MODE, 3) = L_VAR(MODE, 1); \
+ E_VAR(MODE, 4) = VAR(MODE, 1); \
+ L_VAR(MODE, 4) = E_VAR(MODE, 5); \
+ VAR(MODE, 5) = E_VAR(MODE, 6); \
+ L_VAR(MODE, 2) = L_VAR(MODE, 3); \
+ L_VAR(MODE, 5) = VAR(MODE, 2); \
+ VAR(MODE, 3) = VAR(MODE, 4); \
+ VAR(MODE, 6) = L_VAR(MODE, 6);
+
+
+/*
+** movqi: { target msp430_region_lower }
+** ...
+** MOVX.B &eqi2, &eqi1
+** MOVX.B &lqi1, &eqi3
+** MOVX.B &qi1, &eqi4
+** MOVX.B &eqi5, &lqi4
+** MOVX.B &eqi6, &qi5
+** MOV.B &lqi3, &lqi2
+** MOV.B &qi2, &lqi5
+** MOV.B &qi4, &qi3
+** MOV.B &lqi6, &qi6
+** ...
+*/
+/*
+** movqi: { target msp430_region_not_lower }
+** ...
+** MOVX.B &eqi2, &eqi1
+** MOVX.B &lqi1, &eqi3
+** MOVX.B &qi1, &eqi4
+** MOVX.B &eqi5, &lqi4
+** MOVX.B &eqi6, &qi5
+** MOV.B &lqi3, &lqi2
+** MOVX.B &qi2, &lqi5
+** MOVX.B &qi4, &qi3
+** MOVX.B &lqi6, &qi6
+** ...
+*/
+void
+movqi (void)
+{
+ MOV_INSNS (qi)
+}
+
+/*
+** movhi: { target msp430_region_lower }
+** ...
+** MOVX.W &ehi2, &ehi1
+** MOVX.W &lhi1, &ehi3
+** MOVX.W &hi1, &ehi4
+** MOVX.W &ehi5, &lhi4
+** MOVX.W &ehi6, &hi5
+** MOV.W &lhi3, &lhi2
+** MOV.W &hi2, &lhi5
+** MOV.W &hi4, &hi3
+** MOV.W &lhi6, &hi6
+** ...
+*/
+/*
+** movhi: { target msp430_region_not_lower }
+** ...
+** MOVX.W &ehi2, &ehi1
+** MOVX.W &lhi1, &ehi3
+** MOVX.W &hi1, &ehi4
+** MOVX.W &ehi5, &lhi4
+** MOVX.W &ehi6, &hi5
+** MOV.W &lhi3, &lhi2
+** MOVX.W &hi2, &lhi5
+** MOVX.W &hi4, &hi3
+** MOVX.W &lhi6, &hi6
+** ...
+*/
+void
+movhi (void)
+{
+ MOV_INSNS (hi)
+}
+
+/* There is no specific movsi3 pattern defined for msp430, but we check
+ this is synthesized correctly anyway. */
+/*
+** movsi: { target msp430_region_lower }
+** ...
+** MOVX.W &esi2, &esi1
+** MOVX.W &esi2\+2, &esi1\+2
+** MOVX.W &lsi1, &esi3
+** MOVX.W &lsi1\+2, &esi3\+2
+** MOVX.W &si1, &esi4
+** MOVX.W &si1\+2, &esi4\+2
+** MOVX.W &esi5, &lsi4
+** MOVX.W &esi5\+2, &lsi4\+2
+** MOVX.W &esi6, &si5
+** MOVX.W &esi6\+2, &si5\+2
+** MOV.W &lsi3, &lsi2
+** MOV.W &lsi3\+2, &lsi2\+2
+** MOV.W &si2, &lsi5
+** MOV.W &si2\+2, &lsi5\+2
+** MOV.W &si4, &si3
+** MOV.W &si4\+2, &si3\+2
+** MOV.W &lsi6, &si6
+** MOV.W &lsi6\+2, &si6\+2
+** ...
+*/
+/*
+** movsi: { target msp430_region_not_lower }
+** ...
+** MOVX.W &esi2, &esi1
+** MOVX.W &esi2\+2, &esi1\+2
+** MOVX.W &lsi1, &esi3
+** MOVX.W &lsi1\+2, &esi3\+2
+** MOVX.W &si1, &esi4
+** MOVX.W &si1\+2, &esi4\+2
+** MOVX.W &esi5, &lsi4
+** MOVX.W &esi5\+2, &lsi4\+2
+** MOVX.W &esi6, &si5
+** MOVX.W &esi6\+2, &si5\+2
+** MOV.W &lsi3, &lsi2
+** MOV.W &lsi3\+2, &lsi2\+2
+** MOVX.W &si2, &lsi5
+** MOVX.W &si2\+2, &lsi5\+2
+** MOVX.W &si4, &si3
+** MOVX.W &si4\+2, &si3\+2
+** MOVX.W &lsi6, &si6
+** MOVX.W &lsi6\+2, &si6\+2
+** ...
+*/
+void
+movsi (void)
+{
+ MOV_INSNS (si)
+}
+
+#define ADD_INSNS(MODE) \
+ E_VAR(MODE,1) += E_VAR(MODE,2); \
+ E_VAR(MODE,3) += L_VAR(MODE,1); \
+ E_VAR(MODE,4) += VAR(MODE,1); \
+ L_VAR(MODE,2) += E_VAR(MODE,5); \
+ VAR(MODE,3) += E_VAR(MODE,6); \
+ L_VAR(MODE,3) += L_VAR(MODE,4); \
+ L_VAR(MODE,5) += VAR(MODE,2); \
+ VAR(MODE,4) += L_VAR(MODE,6); \
+ VAR(MODE,5) += VAR(MODE,6);
+
+/*
+** addqi3: { target msp430_region_lower }
+** ...
+** ADDX.B &eqi2, &eqi1
+** ADDX.B &lqi1, &eqi3
+** ADDX.B &qi1, &eqi4
+** ADDX.B &eqi5, &lqi2
+** ADDX.B &eqi6, &qi3
+** ADD.B &lqi4, &lqi3
+** ADD.B &qi2, &lqi5
+** ADD.B &lqi6, &qi4
+** ADD.B &qi6, &qi5
+** ...
+*/
+/*
+** addqi3: { target msp430_region_not_lower }
+** ...
+** ADDX.B &eqi2, &eqi1
+** ADDX.B &lqi1, &eqi3
+** ADDX.B &qi1, &eqi4
+** ADDX.B &eqi5, &lqi2
+** ADDX.B &eqi6, &qi3
+** ADD.B &lqi4, &lqi3
+** ADDX.B &qi2, &lqi5
+** ADDX.B &lqi6, &qi4
+** ADDX.B &qi6, &qi5
+** ...
+*/
+void
+addqi3 (void)
+{
+ ADD_INSNS(qi)
+}
+
+/*
+** addhi3: { target msp430_region_lower }
+** ...
+** ADDX.W &ehi2, &ehi1
+** ADDX.W &lhi1, &ehi3
+** ADDX.W &hi1, &ehi4
+** ADDX.W &ehi5, &lhi2
+** ADDX.W &ehi6, &hi3
+** ADD.W &lhi4, &lhi3
+** ADD.W &hi2, &lhi5
+** ADD.W &lhi6, &hi4
+** ADD.W &hi6, &hi5
+** ...
+*/
+/*
+** addhi3: { target msp430_region_not_lower }
+** ...
+** ADDX.W &ehi2, &ehi1
+** ADDX.W &lhi1, &ehi3
+** ADDX.W &hi1, &ehi4
+** ADDX.W &ehi5, &lhi2
+** ADDX.W &ehi6, &hi3
+** ADD.W &lhi4, &lhi3
+** ADDX.W &hi2, &lhi5
+** ADDX.W &lhi6, &hi4
+** ADDX.W &hi6, &hi5
+** ...
+*/
+void
+addhi3 (void)
+{
+ ADD_INSNS(hi)
+}
+
+/*
+** addsi3: { target msp430_region_lower }
+** ...
+** ADDX &esi2, &esi1 { ADDCX &esi2\+2, &esi1\+2
+** ADDX &lsi1, &esi3 { ADDCX &lsi1\+2, &esi3\+2
+** ADDX &si1, &esi4 { ADDCX &si1\+2, &esi4\+2
+** ADDX &esi5, &lsi2 { ADDCX &esi5\+2, &lsi2\+2
+** ADDX &esi6, &si3 { ADDCX &esi6\+2, &si3\+2
+** ADD &lsi4, &lsi3 { ADDC &lsi4\+2, &lsi3\+2
+** ADD &si2, &lsi5 { ADDC &si2\+2, &lsi5\+2
+** ADD &lsi6, &si4 { ADDC &lsi6\+2, &si4\+2
+** ADD &si6, &si5 { ADDC &si6\+2, &si5\+2
+** ...
+*/
+/*
+** addsi3: { target msp430_region_not_lower }
+** ...
+** ADDX &esi2, &esi1 { ADDCX &esi2\+2, &esi1\+2
+** ADDX &lsi1, &esi3 { ADDCX &lsi1\+2, &esi3\+2
+** ADDX &si1, &esi4 { ADDCX &si1\+2, &esi4\+2
+** ADDX &esi5, &lsi2 { ADDCX &esi5\+2, &lsi2\+2
+** ADDX &esi6, &si3 { ADDCX &esi6\+2, &si3\+2
+** ADD &lsi4, &lsi3 { ADDC &lsi4\+2, &lsi3\+2
+** ADDX &si2, &lsi5 { ADDCX &si2\+2, &lsi5\+2
+** ADDX &lsi6, &si4 { ADDCX &lsi6\+2, &si4\+2
+** ADDX &si6, &si5 { ADDCX &si6\+2, &si5\+2
+** ...
+*/
+void
+addsi3 (void)
+{
+ ADD_INSNS(si)
+}
+
+#define SUB_INSNS(MODE) \
+ E_VAR(MODE,1) -= E_VAR(MODE,2); \
+ E_VAR(MODE,3) -= L_VAR(MODE,1); \
+ E_VAR(MODE,4) -= VAR(MODE,1); \
+ L_VAR(MODE,2) -= E_VAR(MODE,5); \
+ VAR(MODE,3) -= E_VAR(MODE,6); \
+ L_VAR(MODE,3) -= L_VAR(MODE,4); \
+ L_VAR(MODE,5) -= VAR(MODE,2); \
+ VAR(MODE,4) -= L_VAR(MODE,6); \
+ VAR(MODE,5) -= VAR(MODE,6);
+
+/*
+** subqi3: { target msp430_region_lower }
+** ...
+** SUBX.B &eqi2, &eqi1
+** SUBX.B &lqi1, &eqi3
+** SUBX.B &qi1, &eqi4
+** SUBX.B &eqi5, &lqi2
+** SUBX.B &eqi6, &qi3
+** SUB.B &lqi4, &lqi3
+** SUB.B &qi2, &lqi5
+** SUB.B &lqi6, &qi4
+** SUB.B &qi6, &qi5
+** ...
+*/
+/*
+** subqi3: { target msp430_region_not_lower }
+** ...
+** SUBX.B &eqi2, &eqi1
+** SUBX.B &lqi1, &eqi3
+** SUBX.B &qi1, &eqi4
+** SUBX.B &eqi5, &lqi2
+** SUBX.B &eqi6, &qi3
+** SUB.B &lqi4, &lqi3
+** SUBX.B &qi2, &lqi5
+** SUBX.B &lqi6, &qi4
+** SUBX.B &qi6, &qi5
+** ...
+*/
+void
+subqi3 (void)
+{
+ SUB_INSNS(qi)
+}
+
+/*
+** subhi3: { target msp430_region_lower }
+** ...
+** SUBX.W &ehi2, &ehi1
+** SUBX.W &lhi1, &ehi3
+** SUBX.W &hi1, &ehi4
+** SUBX.W &ehi5, &lhi2
+** SUBX.W &ehi6, &hi3
+** SUB.W &lhi4, &lhi3
+** SUB.W &hi2, &lhi5
+** SUB.W &lhi6, &hi4
+** SUB.W &hi6, &hi5
+** ...
+*/
+/*
+** subhi3: { target msp430_region_not_lower }
+** ...
+** SUBX.W &ehi2, &ehi1
+** SUBX.W &lhi1, &ehi3
+** SUBX.W &hi1, &ehi4
+** SUBX.W &ehi5, &lhi2
+** SUBX.W &ehi6, &hi3
+** SUB.W &lhi4, &lhi3
+** SUBX.W &hi2, &lhi5
+** SUBX.W &lhi6, &hi4
+** SUBX.W &hi6, &hi5
+** ...
+*/
+void
+subhi3 (void)
+{
+ SUB_INSNS(hi)
+}
+
+/*
+** subsi3: { target msp430_region_lower }
+** ...
+** SUBX &esi2, &esi1 { SUBCX &esi2\+2, &esi1\+2
+** SUBX &lsi1, &esi3 { SUBCX &lsi1\+2, &esi3\+2
+** SUBX &si1, &esi4 { SUBCX &si1\+2, &esi4\+2
+** SUBX &esi5, &lsi2 { SUBCX &esi5\+2, &lsi2\+2
+** SUBX &esi6, &si3 { SUBCX &esi6\+2, &si3\+2
+** SUB &lsi4, &lsi3 { SUBC &lsi4\+2, &lsi3\+2
+** SUB &si2, &lsi5 { SUBC &si2\+2, &lsi5\+2
+** SUB &lsi6, &si4 { SUBC &lsi6\+2, &si4\+2
+** SUB &si6, &si5 { SUBC &si6\+2, &si5\+2
+** ...
+*/
+/*
+** subsi3: { target msp430_region_not_lower }
+** ...
+** SUBX &esi2, &esi1 { SUBCX &esi2\+2, &esi1\+2
+** SUBX &lsi1, &esi3 { SUBCX &lsi1\+2, &esi3\+2
+** SUBX &si1, &esi4 { SUBCX &si1\+2, &esi4\+2
+** SUBX &esi5, &lsi2 { SUBCX &esi5\+2, &lsi2\+2
+** SUBX &esi6, &si3 { SUBCX &esi6\+2, &si3\+2
+** SUB &lsi4, &lsi3 { SUBC &lsi4\+2, &lsi3\+2
+** SUBX &si2, &lsi5 { SUBCX &si2\+2, &lsi5\+2
+** SUBX &lsi6, &si4 { SUBCX &lsi6\+2, &si4\+2
+** SUBX &si6, &si5 { SUBCX &si6\+2, &si5\+2
+** ...
+*/
+void
+subsi3 (void)
+{
+ SUB_INSNS(si)
+}
+
+#define BIC_INSN(MODE) \
+ E_VAR(MODE,1) &= (E_VAR(MODE,2) ^ E_VAR(MODE,1)); \
+ E_VAR(MODE,3) &= (L_VAR(MODE,1) ^ E_VAR(MODE,3)); \
+ E_VAR(MODE,4) &= (VAR(MODE,1) ^ E_VAR(MODE,4)); \
+ L_VAR(MODE,2) &= (E_VAR(MODE,5) ^ L_VAR(MODE,2)); \
+ VAR(MODE,2) &= (E_VAR(MODE,6) ^ VAR(MODE,2)); \
+ L_VAR(MODE,3) &= (L_VAR(MODE,4) ^ L_VAR(MODE,3)); \
+ L_VAR(MODE,5) &= (VAR(MODE,3) ^ L_VAR(MODE,5)); \
+ VAR(MODE,4) &= (L_VAR(MODE,6) ^ VAR(MODE,4)); \
+ VAR(MODE,5) &= (VAR(MODE,6) ^ VAR(MODE,5)); \
+
+/*
+** bicqi3: { target msp430_region_lower }
+** ...
+** BICX.B &eqi2, &eqi1
+** BICX.B &lqi1, &eqi3
+** BICX.B &qi1, &eqi4
+** BICX.B &eqi5, &lqi2
+** BICX.B &eqi6, &qi2
+** BIC.B &lqi4, &lqi3
+** BIC.B &qi3, &lqi5
+** BIC.B &lqi6, &qi4
+** BIC.B &qi6, &qi5
+** ...
+*/
+/*
+** bicqi3: { target msp430_region_not_lower }
+** ...
+** BICX.B &eqi2, &eqi1
+** BICX.B &lqi1, &eqi3
+** BICX.B &qi1, &eqi4
+** BICX.B &eqi5, &lqi2
+** BICX.B &eqi6, &qi2
+** BIC.B &lqi4, &lqi3
+** BICX.B &qi3, &lqi5
+** BICX.B &lqi6, &qi4
+** BICX.B &qi6, &qi5
+** ...
+*/
+void
+bicqi3 (void)
+{
+ BIC_INSN(qi)
+}
+
+/*
+** bichi3: { target msp430_region_lower }
+** ...
+** BICX.W &ehi2, &ehi1
+** BICX.W &lhi1, &ehi3
+** BICX.W &hi1, &ehi4
+** BICX.W &ehi5, &lhi2
+** BICX.W &ehi6, &hi2
+** BIC.W &lhi4, &lhi3
+** BIC.W &hi3, &lhi5
+** BIC.W &lhi6, &hi4
+** BIC.W &hi6, &hi5
+** ...
+*/
+/*
+** bichi3: { target msp430_region_not_lower }
+** ...
+** BICX.W &ehi2, &ehi1
+** BICX.W &lhi1, &ehi3
+** BICX.W &hi1, &ehi4
+** BICX.W &ehi5, &lhi2
+** BICX.W &ehi6, &hi2
+** BIC.W &lhi4, &lhi3
+** BICX.W &hi3, &lhi5
+** BICX.W &lhi6, &hi4
+** BICX.W &hi6, &hi5
+** ...
+*/
+void
+bichi3 (void)
+{
+ BIC_INSN(hi)
+}
+
+/*
+** bicpsi3:
+** ...
+** BICX.A &epsi2, &epsi1
+** BICX.A &lpsi1, &epsi3
+** BICX.A &psi1, &epsi4
+** BICX.A &epsi5, &lpsi2
+** BICX.A &epsi6, &psi2
+** BICX.A &lpsi4, &lpsi3
+** BICX.A &psi3, &lpsi5
+** BICX.A &lpsi6, &psi4
+** BICX.A &psi6, &psi5
+** ...
+*/
+void
+bicpsi3 (void)
+{
+ BIC_INSN(psi)
+}
+
+/* There is no specific bicsi3 pattern defined for msp430, but we check
+ this is synthesized correctly anyway. */
+/*
+** bicsi3: { target msp430_region_lower }
+** ...
+** BICX.W &esi2, &esi1
+** BICX.W &esi2\+2, &esi1\+2
+** BICX.W &lsi1, &esi3
+** BICX.W &lsi1\+2, &esi3\+2
+** BICX.W &si1, &esi4
+** BICX.W &si1\+2, &esi4\+2
+** BICX.W &esi5, &lsi2
+** BICX.W &esi5\+2, &lsi2\+2
+** BICX.W &esi6, &si2
+** BICX.W &esi6\+2, &si2\+2
+** BIC.W &lsi4, &lsi3
+** BIC.W &lsi4\+2, &lsi3\+2
+** BIC.W &si3, &lsi5
+** BIC.W &si3\+2, &lsi5\+2
+** BIC.W &lsi6, &si4
+** BIC.W &lsi6\+2, &si4\+2
+** BIC.W &si6, &si5
+** BIC.W &si6\+2, &si5\+2
+** ...
+*/
+/*
+** bicsi3: { target msp430_region_not_lower }
+** ...
+** BICX.W &esi2, &esi1
+** BICX.W &esi2\+2, &esi1\+2
+** BICX.W &lsi1, &esi3
+** BICX.W &lsi1\+2, &esi3\+2
+** BICX.W &si1, &esi4
+** BICX.W &si1\+2, &esi4\+2
+** BICX.W &esi5, &lsi2
+** BICX.W &esi5\+2, &lsi2\+2
+** BICX.W &esi6, &si2
+** BICX.W &esi6\+2, &si2\+2
+** BIC.W &lsi4, &lsi3
+** BIC.W &lsi4\+2, &lsi3\+2
+** BICX.W &si3, &lsi5
+** BICX.W &si3\+2, &lsi5\+2
+** BICX.W &lsi6, &si4
+** BICX.W &lsi6\+2, &si4\+2
+** BICX.W &si6, &si5
+** BICX.W &si6\+2, &si5\+2
+** ...
+*/
+void
+bicsi3 (void)
+{
+ BIC_INSN(si)
+}
+
+#define BIC_CG_INSN(MODE) \
+ E_VAR(MODE,1) &= (1 ^ E_VAR(MODE,1)); \
+ E_VAR(MODE,2) &= (2 ^ E_VAR(MODE,2)); \
+ L_VAR(MODE,1) &= (4 ^ L_VAR(MODE,1)); \
+ VAR(MODE,1) &= (8 ^ VAR(MODE,1)); \
+
+/*
+** bic_cg_qi3: { target msp430_region_lower }
+** ...
+** BICX.B #1, &eqi1
+** BICX.B #2, &eqi2
+** BIC.B #4, &lqi1
+** BIC.B #8, &qi1
+** ...
+*/
+/*
+** bic_cg_qi3: { target msp430_region_not_lower }
+** ...
+** BICX.B #1, &eqi1
+** BICX.B #2, &eqi2
+** BIC.B #4, &lqi1
+** BICX.B #8, &qi1
+** ...
+*/
+void
+bic_cg_qi3 (void)
+{
+ BIC_CG_INSN(qi)
+}
+
+/*
+** bic_cg_hi3: { target msp430_region_lower }
+** ...
+** BICX.W #1, &ehi1
+** BICX.W #2, &ehi2
+** BIC.W #4, &lhi1
+** BIC.W #8, &hi1
+** ...
+*/
+/*
+** bic_cg_hi3: { target msp430_region_not_lower }
+** ...
+** BICX.W #1, &ehi1
+** BICX.W #2, &ehi2
+** BIC.W #4, &lhi1
+** BICX.W #8, &hi1
+** ...
+*/
+void
+bic_cg_hi3 (void)
+{
+ BIC_CG_INSN(hi)
+}
+
+/*
+** bic_cg_psi3:
+** ...
+** BICX.A #1, &epsi1
+** BICX.A #2, &epsi2
+** BICX.A #4, &lpsi1
+** BICX.A #8, &psi1
+** ...
+*/
+void
+bic_cg_psi3 (void)
+{
+ BIC_CG_INSN(psi)
+}
+
+/* There is no specific bic_cg_si3 pattern defined for msp430, but we check
+ this is synthesized correctly anyway. */
+/*
+** bic_cg_si3: { target msp430_region_lower }
+** ...
+** BICX.W #1, &esi1
+** BICX.W #2, &esi2
+** BIC.W #4, &lsi1
+** BIC.W #8, &si1
+** ...
+*/
+/*
+** bic_cg_si3: { target msp430_region_not_lower }
+** ...
+** BICX.W #1, &esi1
+** BICX.W #2, &esi2
+** BIC.W #4, &lsi1
+** BICX.W #8, &si1
+** ...
+*/
+void
+bic_cg_si3 (void)
+{
+ BIC_CG_INSN(si)
+}
+
+#define AND_INSN(MODE) \
+ E_VAR(MODE,1) &= E_VAR(MODE,2); \
+ E_VAR(MODE,3) &= L_VAR(MODE,1); \
+ E_VAR(MODE,4) &= VAR(MODE,1); \
+ L_VAR(MODE,2) &= E_VAR(MODE,5); \
+ VAR(MODE,2) &= E_VAR(MODE,6); \
+ L_VAR(MODE,3) &= L_VAR(MODE,4); \
+ L_VAR(MODE,5) &= VAR(MODE,3); \
+ VAR(MODE,4) &= VAR(MODE,5); \
+ VAR(MODE,6) &= L_VAR(MODE,6);
+
+/*
+** andqi3: { target msp430_region_lower }
+** ...
+** ANDX.B &eqi2, &eqi1
+** ANDX.B &lqi1, &eqi3
+** ANDX.B &qi1, &eqi4
+** ANDX.B &eqi5, &lqi2
+** ANDX.B &eqi6, &qi2
+** AND.B &lqi4, &lqi3
+** AND.B &qi3, &lqi5
+** AND.B &qi5, &qi4
+** AND.B &lqi6, &qi6
+** ...
+*/
+/*
+** andqi3: { target msp430_region_not_lower }
+** ...
+** ANDX.B &eqi2, &eqi1
+** ANDX.B &lqi1, &eqi3
+** ANDX.B &qi1, &eqi4
+** ANDX.B &eqi5, &lqi2
+** ANDX.B &eqi6, &qi2
+** AND.B &lqi4, &lqi3
+** ANDX.B &qi3, &lqi5
+** ANDX.B &qi5, &qi4
+** ANDX.B &lqi6, &qi6
+** ...
+*/
+void
+andqi3 (void)
+{
+ AND_INSN(qi)
+}
+
+/*
+** andhi3: { target msp430_region_lower }
+** ...
+** ANDX.W &ehi2, &ehi1
+** ANDX.W &lhi1, &ehi3
+** ANDX.W &hi1, &ehi4
+** ANDX.W &ehi5, &lhi2
+** ANDX.W &ehi6, &hi2
+** AND.W &lhi4, &lhi3
+** AND.W &hi3, &lhi5
+** AND.W &hi5, &hi4
+** AND.W &lhi6, &hi6
+** ...
+*/
+/*
+** andhi3: { target msp430_region_not_lower }
+** ...
+** ANDX.W &ehi2, &ehi1
+** ANDX.W &lhi1, &ehi3
+** ANDX.W &hi1, &ehi4
+** ANDX.W &ehi5, &lhi2
+** ANDX.W &ehi6, &hi2
+** AND.W &lhi4, &lhi3
+** ANDX.W &hi3, &lhi5
+** ANDX.W &hi5, &hi4
+** ANDX.W &lhi6, &hi6
+** ...
+*/
+void
+andhi3 (void)
+{
+ AND_INSN(hi)
+}
+
+/*
+** andpsi3:
+** ...
+** ANDX.A &epsi2, &epsi1
+** ANDX.A &lpsi1, &epsi3
+** ANDX.A &psi1, &epsi4
+** ANDX.A &epsi5, &lpsi2
+** ANDX.A &epsi6, &psi2
+** ANDX.A &lpsi4, &lpsi3
+** ANDX.A &psi3, &lpsi5
+** ANDX.A &psi5, &psi4
+** ANDX.A &lpsi6, &psi6
+** ...
+*/
+void
+andpsi3 (void)
+{
+ AND_INSN(psi)
+}
+
+/* There is no specific andsi3 pattern defined for msp430, but we check
+ this is synthesized correctly anyway. */
+/*
+** andsi3: { target msp430_region_lower }
+** ...
+** ANDX.W &esi2, &esi1
+** ANDX.W &esi2\+2, &esi1\+2
+** ANDX.W &lsi1, &esi3
+** ANDX.W &lsi1\+2, &esi3\+2
+** ANDX.W &si1, &esi4
+** ANDX.W &si1\+2, &esi4\+2
+** ANDX.W &esi5, &lsi2
+** ANDX.W &esi5\+2, &lsi2\+2
+** ANDX.W &esi6, &si2
+** ANDX.W &esi6\+2, &si2\+2
+** AND.W &lsi4, &lsi3
+** AND.W &lsi4\+2, &lsi3\+2
+** AND.W &si3, &lsi5
+** AND.W &si3\+2, &lsi5\+2
+** AND.W &si5, &si4
+** AND.W &si5\+2, &si4\+2
+** AND.W &lsi6, &si6
+** AND.W &lsi6\+2, &si6\+2
+** ...
+*/
+/*
+** andsi3: { target msp430_region_not_lower }
+** ...
+** ANDX.W &esi2, &esi1
+** ANDX.W &esi2\+2, &esi1\+2
+** ANDX.W &lsi1, &esi3
+** ANDX.W &lsi1\+2, &esi3\+2
+** ANDX.W &si1, &esi4
+** ANDX.W &si1\+2, &esi4\+2
+** ANDX.W &esi5, &lsi2
+** ANDX.W &esi5\+2, &lsi2\+2
+** ANDX.W &esi6, &si2
+** ANDX.W &esi6\+2, &si2\+2
+** AND.W &lsi4, &lsi3
+** AND.W &lsi4\+2, &lsi3\+2
+** ANDX.W &si3, &lsi5
+** ANDX.W &si3\+2, &lsi5\+2
+** ANDX.W &si5, &si4
+** ANDX.W &si5\+2, &si4\+2
+** ANDX.W &lsi6, &si6
+** ANDX.W &lsi6\+2, &si6\+2
+** ...
+*/
+void
+andsi3 (void)
+{
+ AND_INSN(si)
+}
+
+#define IOR_INSN(MODE) \
+ E_VAR(MODE,1) |= E_VAR(MODE,2); \
+ E_VAR(MODE,3) |= L_VAR(MODE,1); \
+ E_VAR(MODE,4) |= VAR(MODE,1); \
+ L_VAR(MODE,2) |= E_VAR(MODE,5); \
+ VAR(MODE,2) |= E_VAR(MODE,6); \
+ L_VAR(MODE,3) |= L_VAR(MODE,4); \
+ L_VAR(MODE,5) |= VAR(MODE,3); \
+ VAR(MODE,4) |= VAR(MODE,5); \
+ VAR(MODE,6) |= L_VAR(MODE,6);
+
+/*
+** iorqi3: { target msp430_region_lower }
+** ...
+** BISX.B &eqi2, &eqi1
+** BISX.B &lqi1, &eqi3
+** BISX.B &qi1, &eqi4
+** BISX.B &eqi5, &lqi2
+** BISX.B &eqi6, &qi2
+** BIS.B &lqi4, &lqi3
+** BIS.B &qi3, &lqi5
+** BIS.B &qi5, &qi4
+** BIS.B &lqi6, &qi6
+** ...
+*/
+/*
+** iorqi3: { target msp430_region_not_lower }
+** ...
+** BISX.B &eqi2, &eqi1
+** BISX.B &lqi1, &eqi3
+** BISX.B &qi1, &eqi4
+** BISX.B &eqi5, &lqi2
+** BISX.B &eqi6, &qi2
+** BIS.B &lqi4, &lqi3
+** BISX.B &qi3, &lqi5
+** BISX.B &qi5, &qi4
+** BISX.B &lqi6, &qi6
+** ...
+*/
+void
+iorqi3 (void)
+{
+ IOR_INSN(qi)
+}
+
+/*
+** iorhi3: { target msp430_region_lower }
+** ...
+** BISX.W &ehi2, &ehi1
+** BISX.W &lhi1, &ehi3
+** BISX.W &hi1, &ehi4
+** BISX.W &ehi5, &lhi2
+** BISX.W &ehi6, &hi2
+** BIS.W &lhi4, &lhi3
+** BIS.W &hi3, &lhi5
+** BIS.W &hi5, &hi4
+** BIS.W &lhi6, &hi6
+** ...
+*/
+/*
+** iorhi3: { target msp430_region_not_lower }
+** ...
+** BISX.W &ehi2, &ehi1
+** BISX.W &lhi1, &ehi3
+** BISX.W &hi1, &ehi4
+** BISX.W &ehi5, &lhi2
+** BISX.W &ehi6, &hi2
+** BIS.W &lhi4, &lhi3
+** BISX.W &hi3, &lhi5
+** BISX.W &hi5, &hi4
+** BISX.W &lhi6, &hi6
+** ...
+*/
+void
+iorhi3 (void)
+{
+ IOR_INSN(hi)
+}
+
+/*
+** iorpsi3:
+** ...
+** BISX.A &epsi2, &epsi1
+** BISX.A &lpsi1, &epsi3
+** BISX.A &psi1, &epsi4
+** BISX.A &epsi5, &lpsi2
+** BISX.A &epsi6, &psi2
+** BISX.A &lpsi4, &lpsi3
+** BISX.A &psi3, &lpsi5
+** BISX.A &psi5, &psi4
+** BISX.A &lpsi6, &psi6
+** ...
+*/
+void
+iorpsi3 (void)
+{
+ IOR_INSN(psi)
+}
+
+/* There is no specific iorsi3 pattern defined for msp430, but we check
+ this is synthesized correctly anyway. */
+/*
+** iorsi3: { target msp430_region_lower }
+** ...
+** BISX.W &esi2, &esi1
+** BISX.W &esi2\+2, &esi1\+2
+** BISX.W &lsi1, &esi3
+** BISX.W &lsi1\+2, &esi3\+2
+** BISX.W &si1, &esi4
+** BISX.W &si1\+2, &esi4\+2
+** BISX.W &esi5, &lsi2
+** BISX.W &esi5\+2, &lsi2\+2
+** BISX.W &esi6, &si2
+** BISX.W &esi6\+2, &si2\+2
+** BIS.W &lsi4, &lsi3
+** BIS.W &lsi4\+2, &lsi3\+2
+** BIS.W &si3, &lsi5
+** BIS.W &si3\+2, &lsi5\+2
+** BIS.W &si5, &si4
+** BIS.W &si5\+2, &si4\+2
+** BIS.W &lsi6, &si6
+** BIS.W &lsi6\+2, &si6\+2
+** ...
+*/
+/*
+** iorsi3: { target msp430_region_not_lower }
+** ...
+** BISX.W &esi2, &esi1
+** BISX.W &esi2\+2, &esi1\+2
+** BISX.W &lsi1, &esi3
+** BISX.W &lsi1\+2, &esi3\+2
+** BISX.W &si1, &esi4
+** BISX.W &si1\+2, &esi4\+2
+** BISX.W &esi5, &lsi2
+** BISX.W &esi5\+2, &lsi2\+2
+** BISX.W &esi6, &si2
+** BISX.W &esi6\+2, &si2\+2
+** BIS.W &lsi4, &lsi3
+** BIS.W &lsi4\+2, &lsi3\+2
+** BISX.W &si3, &lsi5
+** BISX.W &si3\+2, &lsi5\+2
+** BISX.W &si5, &si4
+** BISX.W &si5\+2, &si4\+2
+** BISX.W &lsi6, &si6
+** BISX.W &lsi6\+2, &si6\+2
+** ...
+*/
+void
+iorsi3 (void)
+{
+ IOR_INSN(si)
+}
+
+#define XOR_INSN(MODE) \
+ E_VAR(MODE,1) ^= E_VAR(MODE,2); \
+ E_VAR(MODE,3) ^= L_VAR(MODE,1); \
+ E_VAR(MODE,4) ^= VAR(MODE,1); \
+ L_VAR(MODE,2) ^= E_VAR(MODE,5); \
+ VAR(MODE,2) ^= E_VAR(MODE,6); \
+ L_VAR(MODE,3) ^= L_VAR(MODE,4); \
+ L_VAR(MODE,5) ^= VAR(MODE,3); \
+ VAR(MODE,4) ^= VAR(MODE,5); \
+ VAR(MODE,6) ^= L_VAR(MODE,6);
+
+/*
+** xorqi3: { target msp430_region_lower }
+** ...
+** XORX.B &eqi2, &eqi1
+** XORX.B &lqi1, &eqi3
+** XORX.B &qi1, &eqi4
+** XORX.B &eqi5, &lqi2
+** XORX.B &eqi6, &qi2
+** XOR.B &lqi4, &lqi3
+** XOR.B &qi3, &lqi5
+** XOR.B &qi5, &qi4
+** XOR.B &lqi6, &qi6
+** ...
+*/
+/*
+** xorqi3: { target msp430_region_not_lower }
+** ...
+** XORX.B &eqi2, &eqi1
+** XORX.B &lqi1, &eqi3
+** XORX.B &qi1, &eqi4
+** XORX.B &eqi5, &lqi2
+** XORX.B &eqi6, &qi2
+** XOR.B &lqi4, &lqi3
+** XORX.B &qi3, &lqi5
+** XORX.B &qi5, &qi4
+** XORX.B &lqi6, &qi6
+** ...
+*/
+void
+xorqi3 (void)
+{
+ XOR_INSN(qi)
+}
+
+/*
+** xorhi3: { target msp430_region_lower }
+** ...
+** XORX.W &ehi2, &ehi1
+** XORX.W &lhi1, &ehi3
+** XORX.W &hi1, &ehi4
+** XORX.W &ehi5, &lhi2
+** XORX.W &ehi6, &hi2
+** XOR.W &lhi4, &lhi3
+** XOR.W &hi3, &lhi5
+** XOR.W &hi5, &hi4
+** XOR.W &lhi6, &hi6
+** ...
+*/
+/*
+** xorhi3: { target msp430_region_not_lower }
+** ...
+** XORX.W &ehi2, &ehi1
+** XORX.W &lhi1, &ehi3
+** XORX.W &hi1, &ehi4
+** XORX.W &ehi5, &lhi2
+** XORX.W &ehi6, &hi2
+** XOR.W &lhi4, &lhi3
+** XORX.W &hi3, &lhi5
+** XORX.W &hi5, &hi4
+** XORX.W &lhi6, &hi6
+** ...
+*/
+void
+xorhi3 (void)
+{
+ XOR_INSN(hi)
+}
+
+/*
+** xorpsi3:
+** ...
+** XORX.A &epsi2, &epsi1
+** XORX.A &lpsi1, &epsi3
+** XORX.A &psi1, &epsi4
+** XORX.A &epsi5, &lpsi2
+** XORX.A &epsi6, &psi2
+** XORX.A &lpsi4, &lpsi3
+** XORX.A &psi3, &lpsi5
+** XORX.A &psi5, &psi4
+** XORX.A &lpsi6, &psi6
+** ...
+*/
+void
+xorpsi3 (void)
+{
+ XOR_INSN(psi)
+}
+
+/* There is no specific xorsi3 pattern defined for msp430, but we check
+ this is synthesized correctly anyway. */
+/*
+** xorsi3: { target msp430_region_lower }
+** ...
+** XORX.W &esi2, &esi1
+** XORX.W &esi2\+2, &esi1\+2
+** XORX.W &lsi1, &esi3
+** XORX.W &lsi1\+2, &esi3\+2
+** XORX.W &si1, &esi4
+** XORX.W &si1\+2, &esi4\+2
+** XORX.W &esi5, &lsi2
+** XORX.W &esi5\+2, &lsi2\+2
+** XORX.W &esi6, &si2
+** XORX.W &esi6\+2, &si2\+2
+** XOR.W &lsi4, &lsi3
+** XOR.W &lsi4\+2, &lsi3\+2
+** XOR.W &si3, &lsi5
+** XOR.W &si3\+2, &lsi5\+2
+** XOR.W &si5, &si4
+** XOR.W &si5\+2, &si4\+2
+** XOR.W &lsi6, &si6
+** XOR.W &lsi6\+2, &si6\+2
+** ...
+*/
+/*
+** xorsi3: { target msp430_region_not_lower }
+** ...
+** XORX.W &esi2, &esi1
+** XORX.W &esi2\+2, &esi1\+2
+** XORX.W &lsi1, &esi3
+** XORX.W &lsi1\+2, &esi3\+2
+** XORX.W &si1, &esi4
+** XORX.W &si1\+2, &esi4\+2
+** XORX.W &esi5, &lsi2
+** XORX.W &esi5\+2, &lsi2\+2
+** XORX.W &esi6, &si2
+** XORX.W &esi6\+2, &si2\+2
+** XOR.W &lsi4, &lsi3
+** XOR.W &lsi4\+2, &lsi3\+2
+** XORX.W &si3, &lsi5
+** XORX.W &si3\+2, &lsi5\+2
+** XORX.W &si5, &si4
+** XORX.W &si5\+2, &si4\+2
+** XORX.W &lsi6, &si6
+** XORX.W &lsi6\+2, &si6\+2
+** ...
+*/
+void
+xorsi3 (void)
+{
+ XOR_INSN(si)
+}
+
+#define DO1 \
+{ \
+ qi z; \
+ z += use_qi(z); \
+ use_qi(z); \
+}
+
+#define DO2 \
+{ \
+ hi z; \
+ z += use_hi(z); \
+ use_hi(z); \
+}
+
+#define DO3 \
+{ \
+ si z; \
+ z += use_si(z); \
+ use_si(z); \
+}
+
+#define CBRANCH_INSN(MODE) \
+ if (E_VAR(MODE,1) == E_VAR(MODE,2)) \
+ DO1 \
+ else if (E_VAR(MODE,3) == L_VAR(MODE,1)) \
+ DO2 \
+ else if (E_VAR(MODE,4) == VAR(MODE,1)) \
+ DO1 \
+ else if (L_VAR(MODE,2) == E_VAR(MODE,5)) \
+ DO2 \
+ else if (VAR(MODE,2) == E_VAR(MODE,6)) \
+ DO1 \
+ else if (L_VAR(MODE,3) == L_VAR(MODE,4)) \
+ DO2 \
+ else if (L_VAR(MODE,5) == VAR(MODE,3)) \
+ DO2 \
+ else if (VAR(MODE,4) == VAR(MODE,5)) \
+ DO1 \
+ else if (VAR(MODE,6) == L_VAR(MODE,6)) \
+ DO2
+
+/*
+** cbranchqi4_real: { target msp430_region_lower }
+** ...
+** CMPX.B &eqi2, &eqi1 { JEQ .L[0-9]+
+** CMPX.B &lqi1, &eqi3 { JEQ .L[0-9]+
+** CMPX.B &qi1, &eqi4 { JEQ .L[0-9]+
+** CMPX.B &eqi5, &lqi2 { JEQ .L[0-9]+
+** CMPX.B &eqi6, &qi2 { JEQ .L[0-9]+
+** CMP.B &lqi4, &lqi3 { JEQ .L[0-9]+
+** CMP.B &qi3, &lqi5 { JEQ .L[0-9]+
+** CMP.B &qi5, &qi4 { JEQ .L[0-9]+
+** CMP.B &lqi6, &qi6 { JNE .L[0-9]+
+** ...
+*/
+/*
+** cbranchqi4_real: { target msp430_region_not_lower }
+** ...
+** CMPX.B &eqi2, &eqi1 { JEQ .L[0-9]+
+** CMPX.B &lqi1, &eqi3 { JEQ .L[0-9]+
+** CMPX.B &qi1, &eqi4 { JEQ .L[0-9]+
+** CMPX.B &eqi5, &lqi2 { JEQ .L[0-9]+
+** CMPX.B &eqi6, &qi2 { JEQ .L[0-9]+
+** CMP.B &lqi4, &lqi3 { JEQ .L[0-9]+
+** CMPX.B &qi3, &lqi5 { JEQ .L[0-9]+
+** CMPX.B &qi5, &qi4 { JEQ .L[0-9]+
+** CMPX.B &lqi6, &qi6 { JNE .L[0-9]+
+** ...
+*/
+void
+cbranchqi4_real (void)
+{
+ CBRANCH_INSN(qi)
+}
+
+/*
+** cbranchhi4_real: { target msp430_region_lower }
+** ...
+** CMPX.W &ehi2, &ehi1 { JEQ .L[0-9]+
+** CMPX.W &lhi1, &ehi3 { JEQ .L[0-9]+
+** CMPX.W &hi1, &ehi4 { JEQ .L[0-9]+
+** CMPX.W &ehi5, &lhi2 { JEQ .L[0-9]+
+** CMPX.W &ehi6, &hi2 { JEQ .L[0-9]+
+** CMP.W &lhi4, &lhi3 { JEQ .L[0-9]+
+** CMP.W &hi3, &lhi5 { JEQ .L[0-9]+
+** CMP.W &hi5, &hi4 { JEQ .L[0-9]+
+** CMP.W &lhi6, &hi6 { JNE .L[0-9]+
+** ...
+*/
+/*
+** cbranchhi4_real: { target msp430_region_not_lower }
+** ...
+** CMPX.W &ehi2, &ehi1 { JEQ .L[0-9]+
+** CMPX.W &lhi1, &ehi3 { JEQ .L[0-9]+
+** CMPX.W &hi1, &ehi4 { JEQ .L[0-9]+
+** CMPX.W &ehi5, &lhi2 { JEQ .L[0-9]+
+** CMPX.W &ehi6, &hi2 { JEQ .L[0-9]+
+** CMP.W &lhi4, &lhi3 { JEQ .L[0-9]+
+** CMPX.W &hi3, &lhi5 { JEQ .L[0-9]+
+** CMPX.W &hi5, &hi4 { JEQ .L[0-9]+
+** CMPX.W &lhi6, &hi6 { JNE .L[0-9]+
+** ...
+*/
+void
+cbranchhi4_real (void)
+{
+ CBRANCH_INSN(hi)
+}
+
+/* There is no specific cbranchsi4_real pattern defined for msp430, but we
+ check this is synthesized correctly anyway. */
+/*
+** cbranchsi4_real: { target msp430_region_lower }
+** ...
+** CMPX.W &esi2, &esi1 { JEQ .L[0-9]+
+** CMPX.W &lsi1, &esi3 { JEQ .L[0-9]+
+** CMPX.W &si1, &esi4 { JEQ .L[0-9]+
+** CMPX.W &esi5, &lsi2 { JEQ .L[0-9]+
+** CMPX.W &esi6, &si2 { JEQ .L[0-9]+
+** CMP.W &lsi4, &lsi3 { JEQ .L[0-9]+
+** CMP.W &si3, &lsi5 { JEQ .L[0-9]+
+** CMP.W &si5, &si4 { JEQ .L[0-9]+
+** CMP.W &lsi6, &si6 { JNE .L[0-9]+
+** CMP.W &lsi6\+2, &si6\+2 { JNE .L[0-9]+
+** ...
+** CMPX.W &esi2\+2, &esi1\+2 { JNE .L[0-9]+
+** ...
+** CMPX.W &lsi1\+2, &esi3\+2 { JNE .L[0-9]+
+** ...
+** CMPX.W &si1\+2, &esi4\+2 { JNE .L[0-9]+
+** ...
+** CMPX.W &esi5\+2, &lsi2\+2 { JNE .L[0-9]+
+** ...
+** CMPX.W &esi6\+2, &si2\+2 { JNE .L[0-9]+
+** ...
+** CMP.W &lsi4\+2, &lsi3\+2 { JNE .L[0-9]+
+** ...
+** CMP.W &si3\+2, &lsi5\+2 { JNE .L[0-9]+
+** ...
+** CMP.W &si5\+2, &si4\+2 { JNE .L[0-9]+
+** ...
+*/
+/*
+** cbranchsi4_real: { target msp430_region_not_lower }
+** ...
+** CMPX.W &esi2, &esi1 { JEQ .L[0-9]+
+** CMPX.W &lsi1, &esi3 { JEQ .L[0-9]+
+** CMPX.W &si1, &esi4 { JEQ .L[0-9]+
+** CMPX.W &esi5, &lsi2 { JEQ .L[0-9]+
+** CMPX.W &esi6, &si2 { JEQ .L[0-9]+
+** CMP.W &lsi4, &lsi3 { JEQ .L[0-9]+
+** CMPX.W &si3, &lsi5 { JEQ .L[0-9]+
+** CMPX.W &si5, &si4 { JEQ .L[0-9]+
+** CMPX.W &lsi6, &si6 { JNE .L[0-9]+
+** CMPX.W &lsi6\+2, &si6\+2 { JNE .L[0-9]+
+** ...
+** CMPX.W &esi2\+2, &esi1\+2 { JNE .L[0-9]+
+** ...
+** CMPX.W &lsi1\+2, &esi3\+2 { JNE .L[0-9]+
+** ...
+** CMPX.W &si1\+2, &esi4\+2 { JNE .L[0-9]+
+** ...
+** CMPX.W &esi5\+2, &lsi2\+2 { JNE .L[0-9]+
+** ...
+** CMPX.W &esi6\+2, &si2\+2 { JNE .L[0-9]+
+** ...
+** CMP.W &lsi4\+2, &lsi3\+2 { JNE .L[0-9]+
+** ...
+** CMPX.W &si3\+2, &lsi5\+2 { JNE .L[0-9]+
+** ...
+** CMPX.W &si5\+2, &si4\+2 { JNE .L[0-9]+
+** ...
+*/
+void
+cbranchsi4_real (void)
+{
+ CBRANCH_INSN(si)
+}
+
+#define CBRANCH_REVERSE_INSN(MODE) \
+ if (E_VAR(MODE,1) > E_VAR(MODE,2)) \
+ DO1 \
+ else if (E_VAR(MODE,3) > L_VAR(MODE,1)) \
+ DO2 \
+ else if (E_VAR(MODE,4) > VAR(MODE,1)) \
+ DO1 \
+ else if (L_VAR(MODE,2) > E_VAR(MODE,5)) \
+ DO2 \
+ else if (VAR(MODE,2) > E_VAR(MODE,6)) \
+ DO1 \
+ else if (L_VAR(MODE,3) > L_VAR(MODE,4)) \
+ DO2 \
+ else if (L_VAR(MODE,5) > VAR(MODE,3)) \
+ DO2 \
+ else if (VAR(MODE,4) > VAR(MODE,5)) \
+ DO1 \
+ else if (VAR(MODE,6) > L_VAR(MODE,6)) \
+ DO2
+
+/*
+** cbranchqi4_reversed: { target msp430_region_lower }
+** ...
+** CMPX.B &eqi1, &eqi2 { JLO .L[0-9]+
+** CMPX.B &eqi3, &lqi1 { JLO .L[0-9]+
+** CMPX.B &eqi4, &qi1 { JLO .L[0-9]+
+** CMPX.B &lqi2, &eqi5 { JLO .L[0-9]+
+** CMPX.B &qi2, &eqi6 { JLO .L[0-9]+
+** CMP.B &lqi3, &lqi4 { JLO .L[0-9]+
+** CMP.B &lqi5, &qi3 { JLO .L[0-9]+
+** CMP.B &qi4, &qi5 { JLO .L[0-9]+
+** CMP.B &qi6, &lqi6 { JHS .L[0-9]+
+** ...
+*/
+/*
+** cbranchqi4_reversed: { target msp430_region_not_lower }
+** ...
+** CMPX.B &eqi1, &eqi2 { JLO .L[0-9]+
+** CMPX.B &eqi3, &lqi1 { JLO .L[0-9]+
+** CMPX.B &eqi4, &qi1 { JLO .L[0-9]+
+** CMPX.B &lqi2, &eqi5 { JLO .L[0-9]+
+** CMPX.B &qi2, &eqi6 { JLO .L[0-9]+
+** CMP.B &lqi3, &lqi4 { JLO .L[0-9]+
+** CMPX.B &lqi5, &qi3 { JLO .L[0-9]+
+** CMPX.B &qi4, &qi5 { JLO .L[0-9]+
+** CMPX.B &qi6, &lqi6 { JHS .L[0-9]+
+** ...
+*/
+void
+cbranchqi4_reversed (void)
+{
+ CBRANCH_REVERSE_INSN(qi)
+}
+
+/*
+** cbranchhi4_reversed: { target msp430_region_lower }
+** ...
+** CMPX.W &ehi1, &ehi2 { JL .L[0-9]+
+** CMPX.W &ehi3, &lhi1 { JL .L[0-9]+
+** CMPX.W &ehi4, &hi1 { JL .L[0-9]+
+** CMPX.W &lhi2, &ehi5 { JL .L[0-9]+
+** CMPX.W &hi2, &ehi6 { JL .L[0-9]+
+** CMP.W &lhi3, &lhi4 { JL .L[0-9]+
+** CMP.W &lhi5, &hi3 { JL .L[0-9]+
+** CMP.W &hi4, &hi5 { JL .L[0-9]+
+** CMP.W &hi6, &lhi6 { JGE .L[0-9]+
+** ...
+*/
+/*
+** cbranchhi4_reversed: { target msp430_region_not_lower }
+** ...
+** CMPX.W &ehi1, &ehi2 { JL .L[0-9]+
+** CMPX.W &ehi3, &lhi1 { JL .L[0-9]+
+** CMPX.W &ehi4, &hi1 { JL .L[0-9]+
+** CMPX.W &lhi2, &ehi5 { JL .L[0-9]+
+** CMPX.W &hi2, &ehi6 { JL .L[0-9]+
+** CMP.W &lhi3, &lhi4 { JL .L[0-9]+
+** CMPX.W &lhi5, &hi3 { JL .L[0-9]+
+** CMPX.W &hi4, &hi5 { JL .L[0-9]+
+** CMPX.W &hi6, &lhi6 { JGE .L[0-9]+
+** ...
+*/
+void
+cbranchhi4_reversed (void)
+{
+ CBRANCH_REVERSE_INSN(hi)
+}
+
+/* There is no specific cbranchsi4_reversed pattern defined for msp430, but
+ we check this is synthesized correctly anyway.
+ This output assembly for this one is quite long and convoluted so we only
+ check part of it. */
+/*
+** cbranchsi4_reversed: { target msp430_region_lower }
+** ...
+** CMPX.W &esi1\+2, &esi2\+2 { JL .L[0-9]+
+** CMPX.W &esi2\+2, &esi1\+2 { JEQ .L[0-9]+
+** CMPX.W &esi3\+2, &lsi1\+2 { JL .L[0-9]+
+** CMPX.W &lsi1\+2, &esi3\+2 { JEQ .L[0-9]+
+** CMPX.W &esi4\+2, &si1\+2 { JL .L[0-9]+
+** CMPX.W &si1\+2, &esi4\+2 { JEQ .L[0-9]+
+** CMPX.W &lsi2\+2, &esi5\+2 { JL .L[0-9]+
+** CMPX.W &esi5\+2, &lsi2\+2 { JEQ .L[0-9]+
+** CMPX.W &si2\+2, &esi6\+2 { JL .L[0-9]+
+** CMPX.W &esi6\+2, &si2\+2 { JEQ .L[0-9]+
+** CMP.W &lsi3\+2, &lsi4\+2 { JL .L[0-9]+
+** CMP.W &lsi4\+2, &lsi3\+2 { JEQ .L[0-9]+
+** CMP.W &lsi5\+2, &si3\+2 { JL .L[0-9]+
+** CMP.W &si3\+2, &lsi5\+2 { JEQ .L[0-9]+
+** CMP.W &si4\+2, &si5\+2 { JL .L[0-9]+
+** CMP.W &si5\+2, &si4\+2 { JEQ .L[0-9]+
+** CMP.W &si6\+2, &lsi6\+2 { JL .L[0-9]+
+** CMP.W &lsi6\+2, &si6\+2 { JNE .L[0-9]+
+** ...
+*/
+/*
+** cbranchsi4_reversed: { target msp430_region_not_lower }
+** ...
+** CMPX.W &esi1\+2, &esi2\+2 { JL .L[0-9]+
+** CMPX.W &esi2\+2, &esi1\+2 { JEQ .L[0-9]+
+** CMPX.W &esi3\+2, &lsi1\+2 { JL .L[0-9]+
+** CMPX.W &lsi1\+2, &esi3\+2 { JEQ .L[0-9]+
+** CMPX.W &esi4\+2, &si1\+2 { JL .L[0-9]+
+** CMPX.W &si1\+2, &esi4\+2 { JEQ .L[0-9]+
+** CMPX.W &lsi2\+2, &esi5\+2 { JL .L[0-9]+
+** CMPX.W &esi5\+2, &lsi2\+2 { JEQ .L[0-9]+
+** CMPX.W &si2\+2, &esi6\+2 { JL .L[0-9]+
+** CMPX.W &esi6\+2, &si2\+2 { JEQ .L[0-9]+
+** CMP.W &lsi3\+2, &lsi4\+2 { JL .L[0-9]+
+** CMP.W &lsi4\+2, &lsi3\+2 { JEQ .L[0-9]+
+** CMPX.W &lsi5\+2, &si3\+2 { JL .L[0-9]+
+** CMPX.W &si3\+2, &lsi5\+2 { JEQ .L[0-9]+
+** CMPX.W &si4\+2, &si5\+2 { JL .L[0-9]+
+** CMPX.W &si5\+2, &si4\+2 { JEQ .L[0-9]+
+** CMPX.W &si6\+2, &lsi6\+2 { JL .L[0-9]+
+** CMPX.W &lsi6\+2, &si6\+2 { JNE .L[0-9]+
+** ...
+*/
+void
+cbranchsi4_reversed (void)
+{
+ CBRANCH_REVERSE_INSN(si)
+}
+
+#define BITBRANCH_NE_INSN(MODE) \
+ if (E_VAR(MODE,1) & E_VAR(MODE,2)) \
+ DO1 \
+ else if (E_VAR(MODE,3) & L_VAR(MODE,1)) \
+ DO2 \
+ else if (E_VAR(MODE,4) & VAR(MODE,1)) \
+ DO1 \
+ else if (L_VAR(MODE,2) & E_VAR(MODE,5)) \
+ DO2 \
+ else if (VAR(MODE,2) & E_VAR(MODE,6)) \
+ DO1 \
+ else if (L_VAR(MODE,3) & L_VAR(MODE,4)) \
+ DO2 \
+ else if (L_VAR(MODE,5) & VAR(MODE,3)) \
+ DO2 \
+ else if (VAR(MODE,4) & VAR(MODE,5)) \
+ DO1 \
+ else if (VAR(MODE,6) & L_VAR(MODE,6)) \
+ DO2
+/*
+** bitbranchqi4: { target msp430_region_lower }
+** ...
+** BITX.B &eqi2, &eqi1 { JNE .L[0-9]+
+** BITX.B &lqi1, &eqi3 { JNE .L[0-9]+
+** BITX.B &qi1, &eqi4 { JNE .L[0-9]+
+** BITX.B &eqi5, &lqi2 { JNE .L[0-9]+
+** BITX.B &eqi6, &qi2 { JNE .L[0-9]+
+** BIT.B &lqi4, &lqi3 { JNE .L[0-9]+
+** BIT.B &qi3, &lqi5 { JNE .L[0-9]+
+** BIT.B &qi5, &qi4 { JNE .L[0-9]+
+** BIT.B &lqi6, &qi6 { JEQ .L[0-9]+
+** ...
+*/
+/*
+** bitbranchqi4: { target msp430_region_not_lower }
+** ...
+** BITX.B &eqi2, &eqi1 { JNE .L[0-9]+
+** BITX.B &lqi1, &eqi3 { JNE .L[0-9]+
+** BITX.B &qi1, &eqi4 { JNE .L[0-9]+
+** BITX.B &eqi5, &lqi2 { JNE .L[0-9]+
+** BITX.B &eqi6, &qi2 { JNE .L[0-9]+
+** BIT.B &lqi4, &lqi3 { JNE .L[0-9]+
+** BITX.B &qi3, &lqi5 { JNE .L[0-9]+
+** BITX.B &qi5, &qi4 { JNE .L[0-9]+
+** BITX.B &lqi6, &qi6 { JEQ .L[0-9]+
+** ...
+*/
+void
+bitbranchqi4 (void)
+{
+ BITBRANCH_NE_INSN(qi)
+}
+
+/*
+** bitbranchhi4: { target msp430_region_lower }
+** ...
+** BITX.W &ehi2, &ehi1 { JNE .L[0-9]+
+** BITX.W &lhi1, &ehi3 { JNE .L[0-9]+
+** BITX.W &hi1, &ehi4 { JNE .L[0-9]+
+** BITX.W &ehi5, &lhi2 { JNE .L[0-9]+
+** BITX.W &ehi6, &hi2 { JNE .L[0-9]+
+** BIT.W &lhi4, &lhi3 { JNE .L[0-9]+
+** BIT.W &hi3, &lhi5 { JNE .L[0-9]+
+** BIT.W &hi5, &hi4 { JNE .L[0-9]+
+** BIT.W &lhi6, &hi6 { JEQ .L[0-9]+
+** ...
+*/
+/*
+** bitbranchhi4: { target msp430_region_not_lower }
+** ...
+** BITX.W &ehi2, &ehi1 { JNE .L[0-9]+
+** BITX.W &lhi1, &ehi3 { JNE .L[0-9]+
+** BITX.W &hi1, &ehi4 { JNE .L[0-9]+
+** BITX.W &ehi5, &lhi2 { JNE .L[0-9]+
+** BITX.W &ehi6, &hi2 { JNE .L[0-9]+
+** BIT.W &lhi4, &lhi3 { JNE .L[0-9]+
+** BITX.W &hi3, &lhi5 { JNE .L[0-9]+
+** BITX.W &hi5, &hi4 { JNE .L[0-9]+
+** BITX.W &lhi6, &hi6 { JEQ .L[0-9]+
+** ...
+*/
+void
+bitbranchhi4 (void)
+{
+ BITBRANCH_NE_INSN(hi)
+}
+
+/*
+** bitbranchpsi4:
+** ...
+** BITX.A &epsi2, &epsi1 { JNE .L[0-9]+
+** BITX.A &lpsi1, &epsi3 { JNE .L[0-9]+
+** BITX.A &psi1, &epsi4 { JNE .L[0-9]+
+** BITX.A &epsi5, &lpsi2 { JNE .L[0-9]+
+** BITX.A &epsi6, &psi2 { JNE .L[0-9]+
+** BITX.A &lpsi4, &lpsi3 { JNE .L[0-9]+
+** BITX.A &psi3, &lpsi5 { JNE .L[0-9]+
+** BITX.A &psi5, &psi4 { JNE .L[0-9]+
+** BITX.A &lpsi6, &psi6 { JEQ .L[0-9]+
+** ...
+*/
+void
+bitbranchpsi4 (void)
+{
+ BITBRANCH_NE_INSN(psi)
+}
+
+
+/* "bitbranch" using SImode operands is omitted since the resulting assembly
+ uses many temporary registers to perform the bitwise and comparison
+ operations. */
diff --git a/gcc/testsuite/gcc.target/msp430/data-attributes-2.c b/gcc/testsuite/gcc.target/msp430/data-attributes-2.c
index d049194425d..6113e99f052 100644
--- a/gcc/testsuite/gcc.target/msp430/data-attributes-2.c
+++ b/gcc/testsuite/gcc.target/msp430/data-attributes-2.c
@@ -27,7 +27,7 @@ int __attribute__((lower,upper)) lu = 20; /* { dg-warning "ignoring attribute 'u
int __attribute__((lower,either)) le = 20; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'lower'" } */
int __attribute__((lower,persistent)) lp = 20; /* { dg-warning "ignoring attribute 'persistent' because it conflicts with attribute 'lower'" } */
int __attribute__((lower,noinit)) ln; /* { dg-warning "ignoring attribute 'noinit' because it conflicts with attribute 'lower'" } */
-int __attribute__((lower,section(".data.foo"))) ls = 30; /* { dg-warning "ignoring attribute 'section' because it conflicts with attribute 'lower'" } */
+int __attribute__((lower,section(".data.foo"))) ls = 30;
int __attribute__((upper)) u = 20;
int __attribute__((upper,lower)) ul = 20; /* { dg-warning "ignoring attribute 'lower' because it conflicts with attribute 'upper'" } */
@@ -46,6 +46,6 @@ int __attribute__((either,section(".data.foo"))) es = 30; /* { dg-warning "ignor
int __attribute__((section(".data.foo"))) s = 20;
int __attribute__((section(".data.foo"),noinit)) sn; /* { dg-warning "ignoring attribute 'noinit' because it conflicts with attribute 'section'" } */
int __attribute__((section(".data.foo"),persistent)) sp = 20; /* { dg-warning "ignoring attribute 'persistent' because it conflicts with attribute 'section'" } */
-int __attribute__((section(".data.foo"),lower)) sl = 2; /* { dg-warning "ignoring attribute 'lower' because it conflicts with attribute 'section'" } */
+int __attribute__((section(".data.foo"),lower)) sl = 2;
int __attribute__((section(".data.foo"),upper)) su = 20; /* { dg-warning "ignoring attribute 'upper' because it conflicts with attribute 'section'" } */
int __attribute__((section(".data.foo"),either)) se = 2; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'section'" } */
diff --git a/gcc/testsuite/gcc.target/msp430/msp430.exp b/gcc/testsuite/gcc.target/msp430/msp430.exp
index b97f4dcdc16..bcc56861abc 100644
--- a/gcc/testsuite/gcc.target/msp430/msp430.exp
+++ b/gcc/testsuite/gcc.target/msp430/msp430.exp
@@ -36,6 +36,14 @@ proc check_effective_target_msp430_mlarge_selected { } {
return [check-flags [list "" { *-*-* } { "-mlarge" } { "" } ]]
}
+proc check_effective_target_msp430_region_not_lower { } {
+ return [check-flags [list "" { *-*-* } { "-mdata-region=none" "-mdata-region=upper" "-mdata-region=either" } { "" } ]]
+}
+
+proc check_effective_target_msp430_region_lower { } {
+ return [check-flags [list "" { *-*-* } { "*" } { "-mdata-region=none" "-mdata-region=upper" "-mdata-region=either" } ]]
+}
+
proc check_effective_target_msp430_hwmul_not_none { } {
return [check-flags [list "" { *-*-* } \
{ "-mhwmult=16bit" "-mhwmult=32bit" "-mhwmult=f5series" } { "" } ]]
diff --git a/gcc/testsuite/gcc.target/msp430/object-attributes-430.c b/gcc/testsuite/gcc.target/msp430/object-attributes-430.c
new file mode 100644
index 00000000000..4296be22edb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/object-attributes-430.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-mcpu=msp430x" "-mlarge" } { "" } } */
+/* { dg-options "-mcpu=msp430" } */
+/* { dg-final { scan-assembler ".mspabi_attribute 4, 1" } } */
+/* { dg-final { scan-assembler ".mspabi_attribute 6, 1" } } */
+/* { dg-final { scan-assembler ".mspabi_attribute 8, 1" } } */
+/* { dg-final { scan-assembler ".gnu_attribute 4, 1" } } */
+
+int
+main (void)
+{
+ while (1);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/msp430/object-attributes-default.c b/gcc/testsuite/gcc.target/msp430/object-attributes-default.c
new file mode 100644
index 00000000000..39c1f3eab44
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/object-attributes-default.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler ".mspabi_attribute 4, 1" { target msp430_430_selected } } } */
+/* { dg-final { scan-assembler ".mspabi_attribute 4, 2" { target msp430_430x_selected } } } */
+/* { dg-final { scan-assembler ".mspabi_attribute 6, 1" { target { ! msp430_mlarge_selected } } } } */
+/* { dg-final { scan-assembler ".mspabi_attribute 8, 1" { target { ! msp430_mlarge_selected } } } } */
+/* { dg-final { scan-assembler ".mspabi_attribute 6, 2" { target msp430_mlarge_selected } } } */
+/* { dg-final { scan-assembler ".mspabi_attribute 8, 2" { target msp430_mlarge_selected } } } */
+/* { dg-final { scan-assembler ".gnu_attribute 4, 1" { target { ! msp430_region_not_lower } } } } */
+/* { dg-final { scan-assembler ".gnu_attribute 4, 2" { target msp430_region_not_lower } } } */
+
+int
+main (void)
+{
+ while (1);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/msp430/object-attributes-mlarge-any-region.c b/gcc/testsuite/gcc.target/msp430/object-attributes-mlarge-any-region.c
new file mode 100644
index 00000000000..2aa8bfb3663
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/object-attributes-mlarge-any-region.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-mcpu=msp430" "-mdata-region=lower" } { "" } } */
+/* { dg-options "-mlarge -mdata-region=none" } */
+/* { dg-final { scan-assembler ".mspabi_attribute 4, 2" } } */
+/* { dg-final { scan-assembler ".mspabi_attribute 6, 2" } } */
+/* { dg-final { scan-assembler ".mspabi_attribute 8, 2" } } */
+/* { dg-final { scan-assembler ".gnu_attribute 4, 2" } } */
+
+int
+main (void)
+{
+ while (1);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/msp430/object-attributes-mlarge.c b/gcc/testsuite/gcc.target/msp430/object-attributes-mlarge.c
new file mode 100644
index 00000000000..06738ea795a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/object-attributes-mlarge.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-mcpu=msp430" } { "" } } */
+/* { dg-options "-mlarge" } */
+/* { dg-final { scan-assembler ".mspabi_attribute 4, 2" } } */
+/* { dg-final { scan-assembler ".mspabi_attribute 6, 2" } } */
+/* { dg-final { scan-assembler ".mspabi_attribute 8, 2" } } */
+/* { dg-final { scan-assembler ".gnu_attribute 4, 1" { target msp430_region_lower } } } */
+/* { dg-final { scan-assembler ".gnu_attribute 4, 2" { target { ! msp430_region_lower } } } } */
+
+int
+main (void)
+{
+ while (1);
+ return 0;
+}
diff --git a/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_13.c b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_13.c
new file mode 100644
index 00000000000..1ac9fc89eb1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_13.c
@@ -0,0 +1,12 @@
+/* Test the fix for PR91926. */
+
+/* Contributed by José Rui Faustino de Sousa <jrfsousa@hotmail.com> */
+
+#include <stdlib.h>
+
+int ifb_echo(void*);
+
+int ifb_echo(void *this)
+{
+ return this == NULL ? 1 : 2;
+}
diff --git a/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_13.f90 b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_13.f90
new file mode 100644
index 00000000000..132a97cd4c4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_13.f90
@@ -0,0 +1,39 @@
+! { dg-do run { target c99_runtime } }
+! { dg-additional-sources ISO_Fortran_binding_13.c }
+!
+! Test the fix for PR91926. The additional source is the main program.
+!
+! Contributed by José Rui Faustino de Sousa <jrfsousa@hotmail.com>
+!
+program ifb_p
+
+ implicit none
+
+ integer :: i = 42
+
+ interface
+ integer function ifb_echo_aux(this) bind(c, name="ifb_echo")
+ implicit none
+ type(*), dimension(..), & ! removing assumed rank solves segmentation fault
+ optional, intent(in) :: this
+ end function ifb_echo_aux
+ end interface
+
+ if (ifb_echo_aux() .ne. 1) STOP 1 ! worked
+ if (ifb_echo() .ne. 1) stop 2 ! segmentation fault
+ if (ifb_echo_aux(i) .ne. 2) stop 3 ! worked
+ if (ifb_echo(i) .ne. 2) stop 4 ! worked
+
+ stop
+
+contains
+
+ integer function ifb_echo(this)
+ type(*), dimension(..), &
+ optional, intent(in) :: this
+
+ ifb_echo = ifb_echo_aux(this)
+ return
+ end function ifb_echo
+
+end program ifb_p
diff --git a/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_14.f90 b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_14.f90
new file mode 100644
index 00000000000..388c5438252
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_14.f90
@@ -0,0 +1,41 @@
+! { dg-do run }
+!
+! Correct an error in the eveluation of the CFI descriptor attribute for
+! the case where the bind_C formal argument is not an assumed shape array
+! and not allocatable or pointer.
+!
+! Contributed by Gilles Gouaillardet <gilles@rist.or.jp>
+!
+MODULE FOO
+INTERFACE
+SUBROUTINE dummy(buf) BIND(C, name="sync")
+type(*), dimension(..) :: buf
+END SUBROUTINE
+END INTERFACE
+END MODULE
+
+PROGRAM main
+ USE FOO
+ IMPLICIT NONE
+ integer(8) :: before, after
+
+ INTEGER, parameter :: n = 1
+
+ INTEGER, ALLOCATABLE :: buf(:)
+ INTEGER :: buf2(n)
+ INTEGER :: i
+
+ ALLOCATE(buf(n))
+ before = LOC(buf(1))
+ CALL dummy (buf)
+ after = LOC(buf(1))
+
+ if (before .NE. after) stop 1
+
+ before = LOC(buf2(1))
+ CALL dummy (buf)
+ after = LOC(buf2(1))
+
+ if (before .NE. after) stop 2
+
+END PROGRAM
diff --git a/gcc/testsuite/gfortran.dg/auto_in_equiv_1.f90 b/gcc/testsuite/gfortran.dg/auto_in_equiv_1.f90
index bf6e0c68a57..2791675af1b 100644
--- a/gcc/testsuite/gfortran.dg/auto_in_equiv_1.f90
+++ b/gcc/testsuite/gfortran.dg/auto_in_equiv_1.f90
@@ -1,36 +1,35 @@
-! { dg-do compile }
+! { dg-do run }
+! { dg-options "-fdec-static -frecursive" }
! Contributed by Mark Eggleston <mark.eggleston@codethink.com>
+!
+! Check automatic variables can be used in equivalence statements.
+! Any other variables that do not explicitly have the automatic
+! attribute will be given the automatic attribute.
+!
+! Check that variables are on the stack by incorporating the
+! equivalence in a recursive function.
+!
program test
- call suba(0)
- call subb(0)
- call suba(1)
+ integer :: f
+
+ f = factorial(5)
+ if (f.ne.120) stop 2
contains
- subroutine suba(option)
- integer, intent(in) :: option
- integer, automatic :: a ! { dg-error "AUTOMATIC at \\(1\\) is a DEC extension" }
+ function factorial(n) result(f)
+ integer :: f
+ integer, intent(in) :: n
+ integer, automatic :: a
integer :: b
- integer :: c
- equivalence (a, b)
- if (option.eq.0) then
- ! initialise a and c
- a = 9
- c = 99
- if (a.ne.b) stop 1
- if (loc(a).ne.loc(b)) stop 2
+ equivalence (a,b)
+
+ if (loc(a).ne.loc(b)) stop 1
+ b = n
+ if (a.eq.1) then
+ f = 1
else
- ! a should've been overwritten
- if (a.eq.9) stop 3
+ f = a * factorial(b-1)
end if
- end subroutine suba
-
- subroutine subb(dummy)
- integer, intent(in) :: dummy
- integer, automatic :: x ! { dg-error "AUTOMATIC at \\(1\\) is a DEC extension" }
- integer :: y
- x = 77
- y = 7
- end subroutine subb
-
+ end function
end program test
diff --git a/gcc/testsuite/gfortran.dg/auto_in_equiv_2.f90 b/gcc/testsuite/gfortran.dg/auto_in_equiv_2.f90
index e40c0f15f3e..5d8a9fbb90e 100644
--- a/gcc/testsuite/gfortran.dg/auto_in_equiv_2.f90
+++ b/gcc/testsuite/gfortran.dg/auto_in_equiv_2.f90
@@ -1,38 +1,14 @@
! { dg-do run }
-! { dg-options "-fdec-static" }
+! { dg-options "-fdec-static -frecursive -fno-automatic" }
! Contributed by Mark Eggleston <mark.eggleston@codethink.com>
-
-program test
- call suba(0)
- call subb(0)
- call suba(1)
-
-contains
- subroutine suba(option)
- integer, intent(in) :: option
- integer, automatic :: a
- integer :: b
- integer :: c
- equivalence (a, b)
- if (option.eq.0) then
- ! initialise a and c
- a = 9
- c = 99
- if (a.ne.b) stop 1
- if (loc(a).ne.loc(b)) stop 2
- else
- ! a should've been overwritten
- if (a.eq.9) stop 3
- end if
- end subroutine suba
-
- subroutine subb(dummy)
- integer, intent(in) :: dummy
- integer, automatic :: x
- integer :: y
- x = 77
- y = 7
- end subroutine subb
-
-end program test
+!
+! Check that -fno-automatic does not break recursion. The recursive
+! function is not marked with the resursive key word consequently
+! local variables can be made static when -fno-automatic is used. The
+! recursive function contains an equivalence that has a variable with
+! the automatic attribute and one without.
+!
+include "auto_in_equiv_1.f90"
+
+! { dg-warning "Flag '-fno-automatic' overwrites '-frecursive'" "warning" { target *-*-* } 0 }
diff --git a/gcc/testsuite/gfortran.dg/auto_in_equiv_3.f90 b/gcc/testsuite/gfortran.dg/auto_in_equiv_3.f90
deleted file mode 100644
index 57c384d1772..00000000000
--- a/gcc/testsuite/gfortran.dg/auto_in_equiv_3.f90
+++ /dev/null
@@ -1,63 +0,0 @@
-! { dg-do run }
-! { dg-options "-fdec-static -fno-automatic" }
-
-! Contributed by Mark Eggleston <mark.eggleston@codethink.com>
-
-! Storage is NOT on the static unless explicitly specified using the
-! DEC extension "automatic". The address of the first local variable
-! is used to determine that storage for the automatic local variable
-! is different to that of a local variable with no attributes. The
-! contents of the local variable in suba should be overwritten by the
-! call to subb.
-!
-program test
- integer :: dummy
- integer, parameter :: address = kind(loc(dummy))
- integer(address) :: ad1
- integer(address) :: ad2
- integer(address) :: ad3
- logical :: ok
-
- call suba(0, ad1)
- call subb(0, ad2)
- call suba(1, ad1)
- call subc(0, ad3)
- ok = (ad1.eq.ad3).and.(ad1.ne.ad2)
- if (.not.ok) stop 4
-
-contains
- subroutine suba(option, addr)
- integer, intent(in) :: option
- integer(address), intent(out) :: addr
- integer, automatic :: a
- integer :: b
- equivalence (a, b)
- addr = loc(a)
- if (option.eq.0) then
- ! initialise a and c
- a = 9
- if (a.ne.b) stop 1
- if (loc(a).ne.loc(b)) stop 2
- else
- ! a should've been overwritten
- if (a.eq.9) stop 3
- end if
- end subroutine suba
-
- subroutine subb(dummy, addr)
- integer, intent(in) :: dummy
- integer(address), intent(out) :: addr
- integer :: x
- addr = loc(x)
- x = 77
- end subroutine subb
-
- subroutine subc(dummy, addr)
- integer, intent(in) :: dummy
- integer(address), intent(out) :: addr
- integer, automatic :: y
- addr = loc(y)
- y = 77
- end subroutine subc
-
-end program test
diff --git a/gcc/testsuite/gfortran.dg/bad_operands.f90 b/gcc/testsuite/gfortran.dg/bad_operands.f90
new file mode 100644
index 00000000000..e82a07fdbd3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bad_operands.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+!
+! Test case contributed by Mark Eggleston <mark.eggleston@codethink.com>
+
+program test
+ integer(4) :: x
+
+ x = x // "rubbish" ! { dg-error "INTEGER\\(4\\)/CHARACTER\\(7\\)" }
+ x = 4_"more rubbish" + 6 ! { dg-error "CHARACTER\\(12,4\\)/INTEGER\\(4\\)" }
+end program
diff --git a/gcc/testsuite/gfortran.dg/character_mismatch.f90 b/gcc/testsuite/gfortran.dg/character_mismatch.f90
new file mode 100644
index 00000000000..e1619467ccc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/character_mismatch.f90
@@ -0,0 +1,76 @@
+! { dg-do compile }
+!
+! Test case contributed by Mark Eggleston <mark.eggleston@codethink.com>
+
+program test
+ use iso_fortran_env
+ implicit none
+ integer, parameter :: ucs4 = selected_char_kind('ISO_10646')
+ integer :: x
+ character(len=7) :: s = "abcd123"
+ character(4, ucs4) :: s4 = char(int(z'20ac'), ucs4) // ucs4_"100"
+
+ x = s
+ x = "string"
+ x = "A longer string" // " plus a bit"
+ x = s // s
+ x = s // "a bit more"
+ x = "prefix:" // s
+ x = s4
+ x = ucs4_"string"
+ x = ucs4_"A longer string" // ucs4_" plus a bit"
+ x = s4 // s4
+ x = s4 // ucs4_"a bit more"
+ x = ucs4_"prefix:" // s4
+
+ call f(s)
+ call f("string")
+ call f("A longer string" // " plus a bit")
+ call f(s // s)
+ call f(s // "a bit more")
+ call f("a string:" // s)
+
+ call f(s4)
+ call f(ucs4_"string")
+ call f(ucs4_"A longer string" // ucs4_" plus a bit")
+ call f(s4 // s4)
+ call f(s4 // ucs4_"a bit more")
+ call f(ucs4_"a string:" // s4)
+
+ write(*,*) "" // ucs4_""
+
+contains
+ subroutine f(y)
+ integer, intent(in) :: y
+
+ write(*,*) y
+ end subroutine f
+
+end program
+
+! { dg-error "CHARACTER\\(7\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 13 }
+! { dg-error "CHARACTER\\(6\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 14 }
+! { dg-error "CHARACTER\\(26\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 15 }
+! { dg-error "CHARACTER\\(14\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 16 }
+! { dg-error "CHARACTER\\(17\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 17 }
+! { dg-error "CHARACTER\\(14\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 18 }
+! { dg-error "CHARACTER\\(4,4\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 19 }
+! { dg-error "CHARACTER\\(6,4\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 20 }
+! { dg-error "CHARACTER\\(26,4\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 21 }
+! { dg-error "CHARACTER\\(8,4\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 22 }
+! { dg-error "CHARACTER\\(14,4\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 23 }
+! { dg-error "CHARACTER\\(11,4\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 24 }
+! { dg-error "CHARACTER\\(7\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 26 }
+! { dg-error "CHARACTER\\(6\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 27 }
+! { dg-error "CHARACTER\\(26\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 28 }
+! { dg-error "CHARACTER\\(14\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 29 }
+! { dg-error "CHARACTER\\(17\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 30 }
+! { dg-error "CHARACTER\\(16\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 31 }
+! { dg-error "CHARACTER\\(4,4\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 33 }
+! { dg-error "CHARACTER\\(6,4\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 34 }
+! { dg-error "CHARACTER\\(26,4\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 35 }
+! { dg-error "CHARACTER\\(8,4\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 36 }
+! { dg-error "CHARACTER\\(14,4\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 37 }
+! { dg-error "CHARACTER\\(13,4\\) to INTEGER\\(4\\)" "type mismatch" { target \*-\*-\* } 38 }
+! { dg-error "CHARACTER\\(0\\)/CHARACTER\\(0,4\\)" "operand type mismatch" { target \*-\*-\* } 40 }
+
diff --git a/gcc/testsuite/gfortran.dg/compare_interfaces.f90 b/gcc/testsuite/gfortran.dg/compare_interfaces.f90
new file mode 100644
index 00000000000..cb2cbb759a6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/compare_interfaces.f90
@@ -0,0 +1,73 @@
+! { dg-do compile }
+!
+! Contributed by Mark Eggleston <mark.eggleston@codethink.co.uk>
+
+subroutine f(a, b)
+ integer :: a
+ real :: b
+
+ write(*,*) a, b
+end subroutine
+
+subroutine g(a, b)
+ integer :: a
+ character(*) :: b
+
+ write(*,*) a, b
+end subroutine
+
+subroutine h
+ interface
+ subroutine f(a, b) ! { dg-error "\\(CHARACTER\\(\\*\\)/REAL\\(4\\)\\)" }
+ integer :: a
+ character(*) :: b
+ end subroutine
+ subroutine g(a, b) ! { dg-error "\\(REAL\\(4\\)/CHARACTER\\(\\*\\)\\)" }
+ integer :: a
+ real :: b
+ end subroutine
+ end interface
+
+ call f(6, 6.0)
+ call g(6, "abcdef")
+end subroutine
+
+subroutine f4(a, b)
+ integer :: a
+ real :: b
+
+ write(*,*) a, b
+end subroutine
+
+subroutine g4(a, b)
+ integer :: a
+ character(*,4) :: b
+
+ write(*,*) a, b
+end subroutine
+
+subroutine h4
+ interface
+ subroutine f4(a, b) ! { dg-error "\\(CHARACTER\\(\\*,4\\)/REAL\\(4\\)\\)" }
+ integer :: a
+ character(*,4) :: b
+ end subroutine
+ subroutine g4(a, b) ! { dg-error "REAL\\(4\\)/CHARACTER\\(\\*,4\\)" }
+ integer :: a
+ real :: b
+ end subroutine
+ end interface
+
+ call f4(6, 6.0)
+ call g4(6, 4_"abcdef")
+end subroutine
+
+program test
+ call h
+ call h4
+end program
+
+! { dg-error "passed REAL\\(4\\) to CHARACTER\\(\\*\\)" "type mismatch" { target \*-\*-\* } 31 }
+! { dg-error "passed CHARACTER\\(6\\) to REAL\\(4\\)" "type mismatch" { target \*-\*-\* } 32 }
+! { dg-error "passed REAL\\(4\\) to CHARACTER\\(\\*,4\\)" "type mismatch" { target \*-\*-\* } 61 }
+! { dg-error "passed CHARACTER\\(6,4\\) to REAL\\(4\\)" "type mismatch" { target \*-\*-\* } 62 }
diff --git a/gcc/testsuite/gfortran.dg/goacc/asyncwait-1.f95 b/gcc/testsuite/gfortran.dg/goacc/asyncwait-1.f95
index d630d388ef7..c8a72fabadd 100644
--- a/gcc/testsuite/gfortran.dg/goacc/asyncwait-1.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/asyncwait-1.f95
@@ -11,13 +11,13 @@ program asyncwait
a(:) = 3.0
b(:) = 0.0
- !$acc parallel copyin (a(1:N)) copy (b(1:N)) async (1 2) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel copyin (a(1:N)) copy (b(1:N)) async (1 2) ! { dg-error "Failed to match clause" }
do i = 1, N
b(i) = a(i)
end do
!$acc end parallel ! { dg-error "Unexpected \\\!\\\$ACC END PARALLEL" }
- !$acc parallel copyin (a(1:N)) copy (b(1:N)) async (1,) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel copyin (a(1:N)) copy (b(1:N)) async (1,) ! { dg-error "Failed to match clause" }
do i = 1, N
b(i) = a(i)
end do
@@ -29,25 +29,25 @@ program asyncwait
end do
!$acc end parallel ! { dg-error "Unexpected \\\!\\\$ACC END PARALLEL" }
- !$acc parallel copyin (a(1:N)) copy (b(1:N)) async (1,2,) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel copyin (a(1:N)) copy (b(1:N)) async (1,2,) ! { dg-error "Failed to match clause" }
do i = 1, N
b(i) = a(i)
end do
!$acc end parallel ! { dg-error "Unexpected \\\!\\\$ACC END PARALLEL" }
- !$acc parallel copyin (a(1:N)) copy (b(1:N)) async (1,2 3) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel copyin (a(1:N)) copy (b(1:N)) async (1,2 3) ! { dg-error "Failed to match clause" }
do i = 1, N
b(i) = a(i)
end do
!$acc end parallel ! { dg-error "Unexpected \\\!\\\$ACC END PARALLEL" }
- !$acc parallel copyin (a(1:N)) copy (b(1:N)) async (1,2,,) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel copyin (a(1:N)) copy (b(1:N)) async (1,2,,) ! { dg-error "Failed to match clause" }
do i = 1, N
b(i) = a(i)
end do
!$acc end parallel ! { dg-error "Unexpected \\\!\\\$ACC END PARALLEL" }
- !$acc parallel copyin (a(1:N)) copy (b(1:N)) async (1 ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel copyin (a(1:N)) copy (b(1:N)) async (1 ! { dg-error "Failed to match clause" }
do i = 1, N
b(i) = a(i)
end do
diff --git a/gcc/testsuite/gfortran.dg/goacc/asyncwait-2.f95 b/gcc/testsuite/gfortran.dg/goacc/asyncwait-2.f95
index fe4e4eeed2c..3663c9b2ffc 100644
--- a/gcc/testsuite/gfortran.dg/goacc/asyncwait-2.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/asyncwait-2.f95
@@ -83,13 +83,13 @@ program asyncwait
end do
!$acc end parallel ! { dg-error "Unexpected \\\!\\\$ACC END PARALLEL" }
- !$acc parallel copyin (a(1:N)) copy (b(1:N)) waitasync ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel copyin (a(1:N)) copy (b(1:N)) waitasync ! { dg-error "Failed to match clause" }
do i = 1, N
b(i) = a(i)
end do
!$acc end parallel ! { dg-error "Unexpected \\\!\\\$ACC END PARALLEL" }
- !$acc parallel copyin (a(1:N)) copy (b(1:N)) asyncwait ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel copyin (a(1:N)) copy (b(1:N)) asyncwait ! { dg-error "Failed to match clause" }
do i = 1, N
b(i) = a(i)
end do
diff --git a/gcc/testsuite/gfortran.dg/goacc/asyncwait-3.f95 b/gcc/testsuite/gfortran.dg/goacc/asyncwait-3.f95
index 5c55c36e0ac..815928a1bb7 100644
--- a/gcc/testsuite/gfortran.dg/goacc/asyncwait-3.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/asyncwait-3.f95
@@ -33,9 +33,9 @@ program asyncwait
!$acc wait (1.0) ! { dg-error "WAIT clause at \\\(1\\\) requires a scalar INTEGER expression" }
- !$acc wait 1 ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc wait 1 ! { dg-error "Failed to match clause" }
- !$acc wait N ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc wait N ! { dg-error "Failed to match clause" }
!$acc wait (1)
end program asyncwait
diff --git a/gcc/testsuite/gfortran.dg/goacc/asyncwait-4.f95 b/gcc/testsuite/gfortran.dg/goacc/asyncwait-4.f95
index df311545c52..057d06bbe78 100644
--- a/gcc/testsuite/gfortran.dg/goacc/asyncwait-4.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/asyncwait-4.f95
@@ -11,21 +11,21 @@ program asyncwait
a(:) = 3.0
b(:) = 0.0
- !$acc wait async (1 2) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc wait async (1 2) ! { dg-error "Failed to match clause" }
- !$acc wait async (1,) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc wait async (1,) ! { dg-error "Failed to match clause" }
!$acc wait async (,1) ! { dg-error "Invalid character in name" }
- !$acc wait async (1, 2, ) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc wait async (1, 2, ) ! { dg-error "Failed to match clause" }
- !$acc wait async (1, 2, ,) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc wait async (1, 2, ,) ! { dg-error "Failed to match clause" }
- !$acc wait async (1 ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc wait async (1 ! { dg-error "Failed to match clause" }
- !$acc wait async (1, *) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc wait async (1, *) ! { dg-error "Failed to match clause" }
- !$acc wait async (1, a) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc wait async (1, a) ! { dg-error "Failed to match clause" }
!$acc wait async (a) ! { dg-error "ASYNC clause at \\\(1\\\) requires a scalar INTEGER expression" }
@@ -33,9 +33,9 @@ program asyncwait
!$acc wait async (1.0) ! { dg-error "ASYNC clause at \\\(1\\\) requires a scalar INTEGER expression" }
- !$acc wait async 1 ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc wait async 1 ! { dg-error "Failed to match clause" }
- !$acc waitasync ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc waitasync ! { dg-error "Failed to match clause" }
- !$acc wait,async ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc wait,async ! { dg-error "Failed to match clause" }
end program asyncwait
diff --git a/gcc/testsuite/gfortran.dg/goacc/default-2.f b/gcc/testsuite/gfortran.dg/goacc/default-2.f
index 8f886887f4b..ea82388eae9 100644
--- a/gcc/testsuite/gfortran.dg/goacc/default-2.f
+++ b/gcc/testsuite/gfortran.dg/goacc/default-2.f
@@ -3,58 +3,58 @@
SUBROUTINE F1
IMPLICIT NONE
-!$ACC KERNELS DEFAULT ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC KERNELS DEFAULT ! { dg-error "Failed to match clause" }
!$ACC END KERNELS ! { dg-error "Unexpected" }
-!$ACC PARALLEL DEFAULT ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC PARALLEL DEFAULT ! { dg-error "Failed to match clause" }
!$ACC END PARALLEL ! { dg-error "Unexpected" }
-!$ACC KERNELS DEFAULT ( ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC KERNELS DEFAULT ( ! { dg-error "Failed to match clause" }
!$ACC END KERNELS ! { dg-error "Unexpected" }
-!$ACC PARALLEL DEFAULT ( ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC PARALLEL DEFAULT ( ! { dg-error "Failed to match clause" }
!$ACC END PARALLEL ! { dg-error "Unexpected" }
-!$ACC KERNELS DEFAULT (, ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC KERNELS DEFAULT (, ! { dg-error "Failed to match clause" }
!$ACC END KERNELS ! { dg-error "Unexpected" }
-!$ACC PARALLEL DEFAULT (, ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC PARALLEL DEFAULT (, ! { dg-error "Failed to match clause" }
!$ACC END PARALLEL ! { dg-error "Unexpected" }
-!$ACC KERNELS DEFAULT () ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC KERNELS DEFAULT () ! { dg-error "Failed to match clause" }
!$ACC END KERNELS ! { dg-error "Unexpected" }
-!$ACC PARALLEL DEFAULT () ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC PARALLEL DEFAULT () ! { dg-error "Failed to match clause" }
!$ACC END PARALLEL ! { dg-error "Unexpected" }
-!$ACC KERNELS DEFAULT (,) ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC KERNELS DEFAULT (,) ! { dg-error "Failed to match clause" }
!$ACC END KERNELS ! { dg-error "Unexpected" }
-!$ACC PARALLEL DEFAULT (,) ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC PARALLEL DEFAULT (,) ! { dg-error "Failed to match clause" }
!$ACC END PARALLEL ! { dg-error "Unexpected" }
-!$ACC KERNELS DEFAULT (FIRSTPRIVATE) ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC KERNELS DEFAULT (FIRSTPRIVATE) ! { dg-error "Failed to match clause" }
!$ACC END KERNELS ! { dg-error "Unexpected" }
-!$ACC PARALLEL DEFAULT (FIRSTPRIVATE) ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC PARALLEL DEFAULT (FIRSTPRIVATE) ! { dg-error "Failed to match clause" }
!$ACC END PARALLEL ! { dg-error "Unexpected" }
-!$ACC KERNELS DEFAULT (PRIVATE) ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC KERNELS DEFAULT (PRIVATE) ! { dg-error "Failed to match clause" }
!$ACC END KERNELS ! { dg-error "Unexpected" }
-!$ACC PARALLEL DEFAULT (PRIVATE) ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC PARALLEL DEFAULT (PRIVATE) ! { dg-error "Failed to match clause" }
!$ACC END PARALLEL ! { dg-error "Unexpected" }
-!$ACC KERNELS DEFAULT (SHARED) ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC KERNELS DEFAULT (SHARED) ! { dg-error "Failed to match clause" }
!$ACC END KERNELS ! { dg-error "Unexpected" }
-!$ACC PARALLEL DEFAULT (SHARED) ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC PARALLEL DEFAULT (SHARED) ! { dg-error "Failed to match clause" }
!$ACC END PARALLEL ! { dg-error "Unexpected" }
-!$ACC KERNELS DEFAULT (NONE ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC KERNELS DEFAULT (NONE ! { dg-error "Failed to match clause" }
!$ACC END KERNELS ! { dg-error "Unexpected" }
-!$ACC PARALLEL DEFAULT (NONE ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC PARALLEL DEFAULT (NONE ! { dg-error "Failed to match clause" }
!$ACC END PARALLEL ! { dg-error "Unexpected" }
-!$ACC KERNELS DEFAULT (NONE NONE) ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC KERNELS DEFAULT (NONE NONE) ! { dg-error "Failed to match clause" }
!$ACC END KERNELS ! { dg-error "Unexpected" }
-!$ACC PARALLEL DEFAULT (NONE NONE) ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC PARALLEL DEFAULT (NONE NONE) ! { dg-error "Failed to match clause" }
!$ACC END PARALLEL ! { dg-error "Unexpected" }
-!$ACC KERNELS DEFAULT (NONE, NONE) ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC KERNELS DEFAULT (NONE, NONE) ! { dg-error "Failed to match clause" }
!$ACC END KERNELS ! { dg-error "Unexpected" }
-!$ACC PARALLEL DEFAULT (NONE, NONE) ! { dg-error "Unclassifiable OpenACC directive" }
+!$ACC PARALLEL DEFAULT (NONE, NONE) ! { dg-error "Failed to match clause" }
!$ACC END PARALLEL ! { dg-error "Unexpected" }
END SUBROUTINE F1
diff --git a/gcc/testsuite/gfortran.dg/goacc/enter-exit-data.f95 b/gcc/testsuite/gfortran.dg/goacc/enter-exit-data.f95
index 805459c1bb0..a414df8d439 100644
--- a/gcc/testsuite/gfortran.dg/goacc/enter-exit-data.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/enter-exit-data.f95
@@ -28,7 +28,7 @@ contains
!$acc enter data
!$acc enter data if (.false.)
!$acc enter data if (l)
- !$acc enter data if (.false.) if (l) ! { dg-error "Unclassifiable" }
+ !$acc enter data if (.false.) if (l) ! { dg-error "Failed to match clause" }
!$acc enter data if (i) ! { dg-error "LOGICAL" }
!$acc enter data if (1) ! { dg-error "LOGICAL" }
!$acc enter data if (a) ! { dg-error "LOGICAL" }
@@ -63,7 +63,7 @@ contains
!$acc exit data
!$acc exit data if (.false.)
!$acc exit data if (l)
- !$acc exit data if (.false.) if (l) ! { dg-error "Unclassifiable" }
+ !$acc exit data if (.false.) if (l) ! { dg-error "Failed to match clause" }
!$acc exit data if (i) ! { dg-error "LOGICAL" }
!$acc exit data if (1) ! { dg-error "LOGICAL" }
!$acc exit data if (a) ! { dg-error "LOGICAL" }
diff --git a/gcc/testsuite/gfortran.dg/goacc/if.f95 b/gcc/testsuite/gfortran.dg/goacc/if.f95
index a45035d8230..35e9cfee134 100644
--- a/gcc/testsuite/gfortran.dg/goacc/if.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/if.f95
@@ -6,7 +6,7 @@ program test
logical :: x
integer :: i
- !$acc parallel if ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel if ! { dg-error "Failed to match clause" }
!$acc parallel if () ! { dg-error "Invalid character" }
!$acc parallel if (i) ! { dg-error "scalar LOGICAL expression" }
!$acc end parallel
@@ -14,11 +14,11 @@ program test
!$acc end parallel
!$acc kernels if (i) ! { dg-error "scalar LOGICAL expression" }
!$acc end kernels
- !$acc kernels if ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc kernels if ! { dg-error "Failed to match clause" }
!$acc kernels if () ! { dg-error "Invalid character" }
!$acc kernels if (1) ! { dg-error "scalar LOGICAL expression" }
!$acc end kernels
- !$acc data if ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc data if ! { dg-error "Failed to match clause" }
!$acc data if () ! { dg-error "Invalid character" }
!$acc data if (i) ! { dg-error "scalar LOGICAL expression" }
!$acc end data
@@ -26,9 +26,9 @@ program test
!$acc end data
! at most one if clause may appear
- !$acc parallel if (.false.) if (.false.) { dg-error "Unclassifiable OpenACC directive" }
- !$acc kernels if (.false.) if (.false.) { dg-error "Unclassifiable OpenACC directive" }
- !$acc data if (.false.) if (.false.) { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel if (.false.) if (.false.) { dg-error "Failed to match clause" }
+ !$acc kernels if (.false.) if (.false.) { dg-error "Failed to match clause" }
+ !$acc data if (.false.) if (.false.) { dg-error "Failed to match clause" }
!$acc parallel if (x)
!$acc end parallel
@@ -49,4 +49,4 @@ program test
!$acc data if (i.gt.1)
!$acc end data
-end program test \ No newline at end of file
+end program test
diff --git a/gcc/testsuite/gfortran.dg/goacc/list.f95 b/gcc/testsuite/gfortran.dg/goacc/list.f95
index 87c84085b13..d2f4c5e88be 100644
--- a/gcc/testsuite/gfortran.dg/goacc/list.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/list.f95
@@ -24,7 +24,7 @@ program test
!$acc parallel private (i) private (j)
!$acc end parallel
- !$acc parallel private ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel private ! { dg-error "Failed to match clause" }
!$acc parallel private() ! { dg-error "Syntax error" }
@@ -56,7 +56,7 @@ program test
!$acc parallel firstprivate (i) firstprivate (j)
!$acc end parallel
- !$acc parallel firstprivate ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel firstprivate ! { dg-error "Failed to match clause" }
!$acc parallel firstprivate() ! { dg-error "Syntax error" }
@@ -91,7 +91,7 @@ program test
!$acc host_data use_device (i) use_device (j) ! { dg-error "neither a POINTER nor an array" }
!$acc end host_data
- !$acc host_data use_device ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc host_data use_device ! { dg-error "Failed to match clause" }
!$acc host_data use_device() ! { dg-error "Syntax error" }
diff --git a/gcc/testsuite/gfortran.dg/goacc/literal.f95 b/gcc/testsuite/gfortran.dg/goacc/literal.f95
index e6760d04fa1..896749a46cb 100644
--- a/gcc/testsuite/gfortran.dg/goacc/literal.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/literal.f95
@@ -10,7 +10,7 @@ contains
!$acc end data ! { dg-error "Unexpected" }
!$acc data deviceptr (10) ! { dg-error "Syntax error" }
!$acc end data ! { dg-error "Unexpected" }
- !$acc data private (10) ! { dg-error "Unclassifiable" }
+ !$acc data private (10) ! { dg-error "Failed to match clause" }
!$acc end data ! { dg-error "Unexpected" }
!$acc host_data use_device (10) ! { dg-error "Syntax error" }
!$acc end host_data ! { dg-error "Unexpected" }
diff --git a/gcc/testsuite/gfortran.dg/goacc/loop-2-kernels-tile.f95 b/gcc/testsuite/gfortran.dg/goacc/loop-2-kernels-tile.f95
index 96e0ccbd2ac..afc8a278cac 100644
--- a/gcc/testsuite/gfortran.dg/goacc/loop-2-kernels-tile.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/loop-2-kernels-tile.f95
@@ -3,7 +3,7 @@ program test
integer :: i, j
!$acc kernels
- !$acc loop tile ! { dg-error "Unclassifiable" }
+ !$acc loop tile ! { dg-error "Failed to match clause" }
DO i = 1,10
ENDDO
!$acc loop tile() ! { dg-error "Syntax error" }
@@ -65,7 +65,7 @@ program test
ENDDO
!$acc end kernels
- !$acc kernels loop tile ! { dg-error "Unclassifiable" }
+ !$acc kernels loop tile ! { dg-error "Failed to match clause" }
DO i = 1,10
ENDDO
!$acc kernels loop tile() ! { dg-error "Syntax error" }
diff --git a/gcc/testsuite/gfortran.dg/goacc/loop-2-parallel-tile.f95 b/gcc/testsuite/gfortran.dg/goacc/loop-2-parallel-tile.f95
index 3a4db5dc1af..4bfca748f75 100644
--- a/gcc/testsuite/gfortran.dg/goacc/loop-2-parallel-tile.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/loop-2-parallel-tile.f95
@@ -3,7 +3,7 @@ program test
integer :: i, j
!$acc parallel
- !$acc loop tile ! { dg-error "Unclassifiable" }
+ !$acc loop tile ! { dg-error "Failed to match clause" }
DO i = 1,10
ENDDO
!$acc loop tile() ! { dg-error "Syntax error" }
@@ -56,7 +56,7 @@ program test
ENDDO
!$acc end parallel
- !$acc parallel loop tile ! { dg-error "Unclassifiable" }
+ !$acc parallel loop tile ! { dg-error "Failed to match clause" }
DO i = 1,10
ENDDO
!$acc parallel loop tile() ! { dg-error "Syntax error" }
diff --git a/gcc/testsuite/gfortran.dg/goacc/loop-7.f95 b/gcc/testsuite/gfortran.dg/goacc/loop-7.f95
index 9ca8297d81a..37d50d3b82b 100644
--- a/gcc/testsuite/gfortran.dg/goacc/loop-7.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/loop-7.f95
@@ -30,13 +30,13 @@ program test
!$acc loop gang(num:num, static:1)
DO i = 1,10
ENDDO
- !$acc loop gang(static:*, num:5, static:5) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc loop gang(static:*, num:5, static:5) ! { dg-error "Failed to match clause" }
DO i = 1,10
ENDDO
- !$acc loop gang(1, num:2, static:3) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc loop gang(1, num:2, static:3) ! { dg-error "Failed to match clause" }
DO i = 1,10
ENDDO
- !$acc loop gang(num:num static:1) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc loop gang(num:num static:1) ! { dg-error "Failed to match clause" }
DO i = 1,10
ENDDO
!$acc loop gang(num)
@@ -45,7 +45,7 @@ program test
!$acc loop gang(num:num+1, static:1+num)
DO i = 1,10
ENDDO
- !$acc loop gang(length:num) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc loop gang(length:num) ! { dg-error "Failed to match clause" }
DO i = 1,10
ENDDO
@@ -58,19 +58,19 @@ program test
!$acc loop worker (num)
DO i = 1,10
ENDDO
- !$acc loop worker (static:num) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc loop worker (static:num) ! { dg-error "Failed to match clause" }
DO i = 1,10
ENDDO
!$acc loop worker (num:,) ! { dg-error "Invalid character" }
DO i = 1,10
ENDDO
- !$acc loop worker (num:num:num) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc loop worker (num:num:num) ! { dg-error "Failed to match clause" }
DO i = 1,10
ENDDO
!$acc loop worker (num:num*num)
DO i = 1,10
ENDDO
- !$acc loop worker (length:num*num) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc loop worker (length:num*num) ! { dg-error "Failed to match clause" }
DO i = 1,10
ENDDO
!$acc loop worker (num:*) ! { dg-error "Invalid character" }
@@ -89,13 +89,13 @@ program test
!$acc loop vector (length)
DO i = 1,10
ENDDO
- !$acc loop vrctor (static:num) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc loop vrctor (static:num) ! { dg-error "Failed to match clause" }
DO i = 1,10
ENDDO
!$acc loop vector (length:,) ! { dg-error "Invalid character" }
DO i = 1,10
ENDDO
- !$acc loop vector (length:num:num) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc loop vector (length:num:num) ! { dg-error "Failed to match clause" }
DO i = 1,10
ENDDO
!$acc loop vector (length:static*num)
@@ -107,7 +107,7 @@ program test
!$acc loop vector (length:32)
DO i = 1,10
ENDDO
- !$acc loop vector (num:num*num) ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc loop vector (num:num*num) ! { dg-error "Failed to match clause" }
DO i = 1,10
ENDDO
!$acc loop vector (length:*) ! { dg-error "Invalid character" }
diff --git a/gcc/testsuite/gfortran.dg/goacc/parallel-kernels-clauses.f95 b/gcc/testsuite/gfortran.dg/goacc/parallel-kernels-clauses.f95
index c37208c7e6f..72ba147565b 100644
--- a/gcc/testsuite/gfortran.dg/goacc/parallel-kernels-clauses.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/parallel-kernels-clauses.f95
@@ -16,8 +16,8 @@ program test
!$acc parallel async(i)
!$acc end parallel
- !$acc kernels async(0, 1) { dg-error "Unclassifiable" }
- !$acc parallel async(0, 1) { dg-error "Unclassifiable" }
+ !$acc kernels async(0, 1) { dg-error "Failed to match clause" }
+ !$acc parallel async(0, 1) { dg-error "Failed to match clause" }
!$acc kernels async
!$acc end kernels
@@ -37,11 +37,11 @@ program test
!$acc kernels async() { dg-error "Invalid character" }
!$acc parallel async() { dg-error "Invalid character" }
- !$acc kernels async("a") { dg-error "Unclassifiable" }
- !$acc parallel async("a") { dg-error "Unclassifiable" }
+ !$acc kernels async("a") { dg-error "Failed to match clause" }
+ !$acc parallel async("a") { dg-error "Failed to match clause" }
- !$acc kernels async(.true.) { dg-error "Unclassifiable" }
- !$acc parallel async(.true.) { dg-error "Unclassifiable" }
+ !$acc kernels async(.true.) { dg-error "Failed to match clause" }
+ !$acc parallel async(.true.) { dg-error "Failed to match clause" }
! default(none)
!$acc kernels default(none)
@@ -59,17 +59,17 @@ program test
!$acc parallel default ( none )
!$acc end parallel
- !$acc kernels default { dg-error "Unclassifiable" }
- !$acc parallel default { dg-error "Unclassifiable" }
+ !$acc kernels default { dg-error "Failed to match clause" }
+ !$acc parallel default { dg-error "Failed to match clause" }
- !$acc kernels default() { dg-error "Unclassifiable" }
- !$acc parallel default() { dg-error "Unclassifiable" }
+ !$acc kernels default() { dg-error "Failed to match clause" }
+ !$acc parallel default() { dg-error "Failed to match clause" }
- !$acc kernels default(i) { dg-error "Unclassifiable" }
- !$acc parallel default(i) { dg-error "Unclassifiable" }
+ !$acc kernels default(i) { dg-error "Failed to match clause" }
+ !$acc parallel default(i) { dg-error "Failed to match clause" }
- !$acc kernels default(1) { dg-error "Unclassifiable" }
- !$acc parallel default(1) { dg-error "Unclassifiable" }
+ !$acc kernels default(1) { dg-error "Failed to match clause" }
+ !$acc parallel default(1) { dg-error "Failed to match clause" }
! Wait
!$acc kernels wait (l) ! { dg-error "INTEGER" }
diff --git a/gcc/testsuite/gfortran.dg/goacc/routine-6.f90 b/gcc/testsuite/gfortran.dg/goacc/routine-6.f90
index cdf643ff44c..f1e2aa3c3c3 100644
--- a/gcc/testsuite/gfortran.dg/goacc/routine-6.f90
+++ b/gcc/testsuite/gfortran.dg/goacc/routine-6.f90
@@ -108,7 +108,7 @@ subroutine subr4 (x)
end subroutine subr4
subroutine subr10 (x)
- !$acc routine (subr10) device ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc routine (subr10) device ! { dg-error "Failed to match clause" }
integer, intent(inout) :: x
if (x < 1) then
x = 1
diff --git a/gcc/testsuite/gfortran.dg/goacc/several-directives.f95 b/gcc/testsuite/gfortran.dg/goacc/several-directives.f95
index 8fb97b53d38..e7610be69d9 100644
--- a/gcc/testsuite/gfortran.dg/goacc/several-directives.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/several-directives.f95
@@ -2,5 +2,5 @@
program test
! only one directive-name may appear in directive
- !$acc parallel kernels ! { dg-error "Unclassifiable OpenACC directive" }
-end \ No newline at end of file
+ !$acc parallel kernels ! { dg-error "Failed to match clause" }
+end
diff --git a/gcc/testsuite/gfortran.dg/goacc/sie.f95 b/gcc/testsuite/gfortran.dg/goacc/sie.f95
index abfe28bc533..194a1daae5f 100644
--- a/gcc/testsuite/gfortran.dg/goacc/sie.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/sie.f95
@@ -67,7 +67,7 @@ program test
!$acc end kernels
- !$acc parallel num_gangs ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel num_gangs ! { dg-error "Failed to match clause" }
!$acc parallel num_gangs(3)
!$acc end parallel
@@ -95,7 +95,7 @@ program test
!$acc parallel num_gangs("1") ! { dg-error "scalar INTEGER expression" }
!$acc end parallel
- !$acc kernels num_gangs ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc kernels num_gangs ! { dg-error "Failed to match clause" }
!$acc kernels num_gangs(3)
!$acc end kernels
@@ -124,7 +124,7 @@ program test
!$acc end kernels
- !$acc parallel num_workers ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel num_workers ! { dg-error "Failed to match clause" }
!$acc parallel num_workers(3)
!$acc end parallel
@@ -152,7 +152,7 @@ program test
!$acc parallel num_workers("1") ! { dg-error "scalar INTEGER expression" }
!$acc end parallel
- !$acc kernels num_workers ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc kernels num_workers ! { dg-error "Failed to match clause" }
!$acc kernels num_workers(3)
!$acc end kernels
@@ -181,7 +181,7 @@ program test
!$acc end kernels
- !$acc parallel vector_length ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel vector_length ! { dg-error "Failed to match clause" }
!$acc parallel vector_length(3)
!$acc end parallel
@@ -209,7 +209,7 @@ program test
!$acc parallel vector_length("1") ! { dg-error "scalar INTEGER expression" }
!$acc end parallel
- !$acc kernels vector_length ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc kernels vector_length ! { dg-error "Failed to match clause" }
!$acc kernels vector_length(3)
!$acc end kernels
diff --git a/gcc/testsuite/gfortran.dg/goacc/tile-1.f90 b/gcc/testsuite/gfortran.dg/goacc/tile-1.f90
index 3dbabda0342..f609b127df9 100644
--- a/gcc/testsuite/gfortran.dg/goacc/tile-1.f90
+++ b/gcc/testsuite/gfortran.dg/goacc/tile-1.f90
@@ -24,7 +24,7 @@ subroutine parloop
end do
end do
- !$acc parallel loop tile ! { dg-error "Unclassifiable" }
+ !$acc parallel loop tile ! { dg-error "Failed to match clause" }
do i = 1, n
end do
@@ -92,7 +92,7 @@ subroutine par
integer i, j, k
!$acc parallel
- !$acc loop tile ! { dg-error "Unclassifiable" }
+ !$acc loop tile ! { dg-error "Failed to match clause" }
do i = 1, n
end do
@@ -173,7 +173,7 @@ subroutine kern
integer i, j, k
!$acc kernels
- !$acc loop tile ! { dg-error "Unclassifiable" }
+ !$acc loop tile ! { dg-error "Failed to match clause" }
do i = 1, n
end do
@@ -275,7 +275,7 @@ subroutine kernsloop
end do
end do
- !$acc kernels loop tile ! { dg-error "Unclassifiable" }
+ !$acc kernels loop tile ! { dg-error "Failed to match clause" }
do i = 1, n
end do
diff --git a/gcc/testsuite/gfortran.dg/goacc/update-if_present-2.f90 b/gcc/testsuite/gfortran.dg/goacc/update-if_present-2.f90
index e73c2dc0875..bf8b319a78e 100644
--- a/gcc/testsuite/gfortran.dg/goacc/update-if_present-2.f90
+++ b/gcc/testsuite/gfortran.dg/goacc/update-if_present-2.f90
@@ -2,7 +2,7 @@
subroutine t1
implicit none
- !$acc routine gang if_present ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc routine gang if_present ! { dg-error "Failed to match clause" }
integer a, b, c(10)
real, allocatable :: x, y, z(:)
@@ -12,10 +12,10 @@ subroutine t1
allocate (x, y, z(100))
- !$acc enter data copyin(a) if_present ! { dg-error "Unclassifiable OpenACC directive" }
- !$acc exit data copyout(a) if_present ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc enter data copyin(a) if_present ! { dg-error "Failed to match clause" }
+ !$acc exit data copyout(a) if_present ! { dg-error "Failed to match clause" }
- !$acc data copy(a) if_present ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc data copy(a) if_present ! { dg-error "Failed to match clause" }
!$acc end data ! { dg-error "Unexpected ..ACC END DATA statement" }
!$acc declare link(a) if_present ! { dg-error "Unexpected junk after" }
@@ -23,7 +23,7 @@ subroutine t1
!$acc init if_present ! { dg-error "Unclassifiable OpenACC directive" }
!$acc shutdown if_present ! { dg-error "Unclassifiable OpenACC directive" }
- !$acc update self(a) device_type(nvidia) device(b) if_present ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc update self(a) device_type(nvidia) device(b) if_present ! { dg-error "Failed to match clause" }
end subroutine t1
subroutine t2
@@ -35,17 +35,17 @@ subroutine t2
c(:) = -1
!$acc parallel
- !$acc loop if_present ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc loop if_present ! { dg-error "Failed to match clause" }
do b = 1, 10
end do
!$acc end parallel
- !$acc kernels loop if_present ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc kernels loop if_present ! { dg-error "Failed to match clause" }
do b = 1, 10
end do
!$acc end kernels loop ! { dg-error "Unexpected ..ACC END KERNELS LOOP statement" }
- !$acc parallel loop if_present ! { dg-error "Unclassifiable OpenACC directive" }
+ !$acc parallel loop if_present ! { dg-error "Failed to match clause" }
do b = 1, 10
end do
!$acc end parallel loop ! { dg-error "Unexpected ..ACC END PARALLEL LOOP statement" }
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-simd-1.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-simd-1.f90
index d6ae7c9c812..40169d38da4 100644
--- a/gcc/testsuite/gfortran.dg/gomp/declare-simd-1.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-simd-1.f90
@@ -2,7 +2,7 @@
subroutine fn1 (x)
integer :: x
-!$omp declare simd (fn1) inbranch notinbranch uniform (x) ! { dg-error "Unclassifiable OpenMP directive" }
+!$omp declare simd (fn1) inbranch notinbranch uniform (x) ! { dg-error "Failed to match clause" }
end subroutine fn1
subroutine fn2 (x)
!$omp declare simd (fn100) ! { dg-error "should refer to containing procedure" }
diff --git a/gcc/testsuite/gfortran.dg/gomp/is_device_ptr-1.f90 b/gcc/testsuite/gfortran.dg/gomp/is_device_ptr-1.f90
new file mode 100644
index 00000000000..0eeca0ee23a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/is_device_ptr-1.f90
@@ -0,0 +1,27 @@
+! { dg-do compile }
+subroutine test(b,c,d)
+ implicit none
+ integer, value, target :: b
+ integer, pointer :: c
+ integer, allocatable, target :: d
+
+ integer, target :: a(5)
+
+ !$omp target is_device_ptr(a) ! { dg-error "Non-dummy object .a. in IS_DEVICE_PTR clause" }
+ !$omp end target
+
+ !$omp target is_device_ptr(b) ! { dg-error "VALUE object .b. in IS_DEVICE_PTR clause" }
+ !$omp end target
+
+ !$omp target is_device_ptr(c) ! { dg-error "POINTER object .c. in IS_DEVICE_PTR clause" }
+ !$omp end target
+
+ !$omp target is_device_ptr(d) ! { dg-error "ALLOCATABLE object .d. in IS_DEVICE_PTR clause" }
+ !$omp end target
+
+ !$omp target data map(a) use_device_addr(a) ! Should be okay
+ !$omp end target data
+
+ !$omp target data map(c) use_device_ptr(c) ! Should be okay
+ !$omp end target data
+end subroutine test
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr29759.f90 b/gcc/testsuite/gfortran.dg/gomp/pr29759.f90
index 39c59c5e0ff..1b1f379522c 100644
--- a/gcc/testsuite/gfortran.dg/gomp/pr29759.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr29759.f90
@@ -21,20 +21,20 @@ PROGRAM test_omp
!$OMP END PARALLEL
-!$OMP PARALLEL & ! { dg-error "Unclassifiable OpenMP" }
+!$OMP PARALLEL & ! { dg-error "Failed to match clause" }
!$ NUM_THREADS(2)
!$OMP END PARALLEL ! { dg-error "Unexpected" }
-!$OMP PARALLEL & ! { dg-error "Unclassifiable OpenMP" }
+!$OMP PARALLEL & ! { dg-error "Failed to match clause" }
!$ & NUM_THREADS(2) ! { dg-error "Invalid character" }
!$OMP END PARALLEL ! { dg-error "Unexpected" }
-!$OMP PARALLEL & ! { dg-error "Unclassifiable OpenMP" }
+!$OMP PARALLEL & ! { dg-error "Failed to match clause" }
!
!$ NUM_THREADS(2)
!$OMP END PARALLEL ! { dg-error "Unexpected" }
-!$OMP PARALLEL & ! { dg-error "Unclassifiable OpenMP" }
+!$OMP PARALLEL & ! { dg-error "Failed to match clause" }
!
!$ & NUM_THREADS(2) ! { dg-error "Invalid character" }
!$OMP END PARALLEL ! { dg-error "Unexpected" }
diff --git a/gcc/testsuite/gfortran.dg/hollerith_to_char_parameter_1.f90 b/gcc/testsuite/gfortran.dg/hollerith_to_char_parameter_1.f90
new file mode 100644
index 00000000000..4c50be4acbb
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/hollerith_to_char_parameter_1.f90
@@ -0,0 +1,11 @@
+! { dg-do compile }
+! { dg-options "-Wconversion -std=legacy" }
+!
+! Test case contributed by Mark Eggleston <mark.eggleston@codethink.com>
+
+program test
+ character(*), parameter :: h = 5hABCDE ! { dg-warning "HOLLERITH to CHARACTER\\(\\*\\)" }
+
+ write(*,*) h
+end program
+
diff --git a/gcc/testsuite/gfortran.dg/hollerith_to_char_parameter_2.f90 b/gcc/testsuite/gfortran.dg/hollerith_to_char_parameter_2.f90
new file mode 100644
index 00000000000..1d5bc6cd7e3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/hollerith_to_char_parameter_2.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+!
+! Test case contributed by Mark Eggleston <mark.eggleston@codethink.com>
+
+program test
+ character(*), parameter :: h = 5hABCDE ! { dg-warning "HOLLERITH to CHARACTER\\(\\*\\)" }
+
+ write(*,*) h
+end program
+
+! { dg-warning "Legacy Extension" "extension" { target \*-\*-\* } 6 }
+
diff --git a/gcc/testsuite/gfortran.dg/pr47054_1.f90 b/gcc/testsuite/gfortran.dg/pr47054_1.f90
new file mode 100644
index 00000000000..3665edbd72b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr47054_1.f90
@@ -0,0 +1,15 @@
+! { dg-do compile }
+! { dg-options "-fcray-pointer" }
+! PR fortran/47054
+subroutine host_sub
+ implicit none
+ real xg
+ pointer (paxg, xg)
+ call internal_sub
+ contains
+ subroutine internal_sub
+ implicit none
+ real xg
+ pointer (paxg, xg)
+ end subroutine internal_sub
+end subroutine host_sub
diff --git a/gcc/testsuite/gfortran.dg/pr47054_2.f90 b/gcc/testsuite/gfortran.dg/pr47054_2.f90
new file mode 100644
index 00000000000..3b7c4aaf815
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr47054_2.f90
@@ -0,0 +1,41 @@
+! { dg-do compile }
+! { dg-options "-fcray-pointer" }
+! PR fortran/47054
+! Code contributed by Deji Akingunola <deji_aking at yahoo dot ca>
+subroutine host_sub(F_su,F_nk)
+ implicit none
+
+ integer :: F_nk
+ real,dimension(F_nk) :: F_su
+ integer G_ni, G_nj
+ real*8 G_xg_8, G_yg_8
+ pointer (paxg_8, G_xg_8(G_ni))
+ pointer (payg_8, G_yg_8(G_nj))
+ common / G_p / paxg_8,payg_8
+ common / G / G_ni, G_nj
+
+ call internal_sub(F_su,F_nk)
+ return
+contains
+
+ subroutine internal_sub(F_su,F_nk)
+ implicit none
+ integer G_ni, G_nj
+ real*8 G_xg_8, G_yg_8
+ pointer (paxg_8, G_xg_8(G_ni))
+ pointer (payg_8, G_yg_8(G_nj))
+ common / G_p / paxg_8,payg_8
+ common / G / G_ni, G_nj
+
+ integer :: F_nk
+ real,dimension(F_nk) :: F_su
+ integer k,k2
+
+ k2 = 0
+ do k = 1, F_nk, 2
+ k2 = k2+1
+ F_su(k) = F_su(k) + 1.0
+ enddo
+ return
+ end subroutine internal_sub
+end subroutine host_sub
diff --git a/gcc/testsuite/gfortran.dg/pr91497.f90 b/gcc/testsuite/gfortran.dg/pr91497.f90
new file mode 100644
index 00000000000..d324b3b1aa0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr91497.f90
@@ -0,0 +1,127 @@
+! { dg-do compile { target { i?86-*-* x86_64-*-* } } }
+! { dg-options "-Wall" }
+! Code contributed by Manfred Schwarb <manfred99 at gmx dot ch>
+! PR fortran/91497
+!
+! Prior to applying the patch for this PR, the following code
+! would generate numerous conversion warnings.
+!
+program foo
+
+ real*4 a,aa
+ real*8 b,bb
+ real*10 c,cc
+ real*16 d
+ integer*2 e,ee
+ integer*4 f,ff
+ integer*8 g,gg
+ PARAMETER(a=3.1415927_4)
+ PARAMETER(b=3.1415927_8)
+ PARAMETER(c=3.1415927_10)
+ PARAMETER(d=3.1415927_16)
+ PARAMETER(e=123_2)
+ PARAMETER(f=123_4)
+ PARAMETER(g=123_8)
+
+ aa=REAL(b)
+ aa=REAL(c)
+ aa=REAL(d)
+ aa=REAL(e)
+ aa=REAL(f)
+ aa=REAL(g)
+ aa=FLOAT(f)
+ aa=FLOOR(b)
+ aa=FLOOR(c)
+ aa=FLOOR(d)
+ aa=CEILING(b)
+ aa=CEILING(c)
+ aa=CEILING(d)
+ !---unknown but documented type conversions:
+ !!aa=FLOATI(e)
+ !!aa=FLOATJ(f)
+ !!aa=FLOATK(g)
+ !---documentation is wrong for sngl:
+ aa=SNGL(c)
+ aa=SNGL(d)
+ bb=REAL(c, kind=8)
+ bb=REAL(d, kind=8)
+ bb=DBLE(c)
+ bb=DBLE(d)
+ bb=DFLOAT(g)
+ bb=FLOOR(c)
+ bb=FLOOR(d)
+ bb=CEILING(c)
+ bb=CEILING(d)
+ cc=REAL(d, kind=10)
+ cc=FLOOR(d)
+ cc=CEILING(d)
+
+ aa=AINT(b)
+ aa=ANINT(b)
+ aa=AINT(c)
+ aa=ANINT(c)
+ aa=AINT(d)
+ aa=ANINT(d)
+ bb=DINT(b)
+ bb=DNINT(b)
+
+ ee=INT(a, kind=2)
+ ee=NINT(a, kind=2)
+ ee=INT(b, kind=2)
+ ee=NINT(b, kind=2)
+ ee=INT(c, kind=2)
+ ee=NINT(c, kind=2)
+ ee=INT(d, kind=2)
+ ee=NINT(d, kind=2)
+ ee=INT(f, kind=2)
+ ee=INT(g, kind=2)
+ ee=IFIX(a)
+ ee=IDINT(b)
+ ee=IDNINT(b)
+ ee=INT2(a)
+ ee=INT2(b)
+ ee=INT2(c)
+ ee=INT2(d)
+ ee=INT2(f)
+ ee=INT2(g)
+
+ ff=INT(a, kind=4)
+ ff=NINT(a, kind=4)
+ ff=INT(b, kind=4)
+ ff=NINT(b, kind=4)
+ ff=INT(c, kind=4)
+ ff=NINT(c, kind=4)
+ ff=INT(d, kind=4)
+ ff=NINT(d, kind=4)
+ ff=INT(f, kind=4)
+ ff=INT(g, kind=4)
+ ff=IFIX(a)
+ ff=IDINT(b)
+ ff=IDNINT(b)
+ !---LONG not allowed anymore in gfortran 10 (?):
+ !!ff=LONG(a)
+ !!ff=LONG(b)
+ !!ff=LONG(c)
+ !!ff=LONG(d)
+ !!ff=LONG(g)
+
+ gg=INT(a, kind=8)
+ gg=NINT(a, kind=8)
+ gg=INT(b, kind=8)
+ gg=NINT(b, kind=8)
+ gg=INT(c, kind=8)
+ gg=NINT(c, kind=8)
+ gg=INT(d, kind=8)
+ gg=NINT(d, kind=8)
+ gg=INT(f, kind=8)
+ gg=INT(g, kind=8)
+ gg=IFIX(a)
+ gg=IDINT(b)
+ gg=IDNINT(b)
+ gg=INT8(a)
+ gg=INT8(b)
+ gg=INT8(c)
+ gg=INT8(d)
+ gg=INT8(g)
+end
+
diff --git a/gcc/testsuite/gfortran.dg/pr91587.f90 b/gcc/testsuite/gfortran.dg/pr91587.f90
index c07735df65e..c304be116c0 100644
--- a/gcc/testsuite/gfortran.dg/pr91587.f90
+++ b/gcc/testsuite/gfortran.dg/pr91587.f90
@@ -2,9 +2,9 @@
! PR fortran/91587
! Code contributed by Gerhard Steinmetz
program p
- backspace(err=!) ! { dg-error "Syntax error in" }
- flush(err=!) ! { dg-error "Syntax error in" }
- rewind(err=!) ! { dg-error "Syntax error in" }
+ backspace(err=!) ! { dg-error "Invalid value for" }
+ flush(err=!) ! { dg-error "Invalid value for" }
+ rewind(err=!) ! { dg-error "Invalid value for" }
end
subroutine bar ! An other matcher runs, and gives a different error.
diff --git a/gcc/testsuite/gfortran.dg/pr91784.f90 b/gcc/testsuite/gfortran.dg/pr91784.f90
new file mode 100644
index 00000000000..25280e07eb2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr91784.f90
@@ -0,0 +1,9 @@
+! { dg-do run }
+! PR fortran/91784
+! Code originally contributed by Gerhard Steinmetz
+program p
+ complex :: x(1)
+ x = (1.0, 2.0) * [real :: -(3.0 + 4.0)]
+ if (int(real(x(1))) /= -7) stop 1
+ if (int(aimag(x(1))) /= -14) stop 2
+end
diff --git a/gcc/testsuite/gfortran.dg/pr91785.f90 b/gcc/testsuite/gfortran.dg/pr91785.f90
new file mode 100644
index 00000000000..fb3d964fc06
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr91785.f90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+! PR fortran/91785
+! Code contributed by Gerhard Steinmetz
+program p
+ complex :: a(*) ! { dg-error "Assumed size array at" }
+ real :: b(2)
+ b = a%im ! { dg-error "upper bound in the last dimension" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pr91942.f90 b/gcc/testsuite/gfortran.dg/pr91942.f90
new file mode 100644
index 00000000000..cd237d38660
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr91942.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+! PR fortran/91942
+! Code contributed by Gerhard Steinmetz
+program p
+ integer :: i
+ backspace (iostat=i%kind) ! { dg-error "Expecting a variable at" }
+ endfile (iostat=i%kind) ! { dg-error "Expecting END PROGRAM" }
+ flush (iostat=i%kind) ! { dg-error "Expecting a variable at" }
+ rewind (iostat=i%kind) ! { dg-error "Expecting a variable at" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pr91943.f90 b/gcc/testsuite/gfortran.dg/pr91943.f90
new file mode 100644
index 00000000000..c2752c54e7b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr91943.f90
@@ -0,0 +1,7 @@
+! { dg-do compile }
+! PR fortran/91943
+! Code contributed by Gerhard Steinmetz
+program p
+ print *, f(b'1001') ! { dg-error "cannot appear as an actual argument" }
+ call sub(b'1001') ! { dg-error "cannot appear as an actual argument" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pr91959.f90 b/gcc/testsuite/gfortran.dg/pr91959.f90
new file mode 100644
index 00000000000..788b413c447
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr91959.f90
@@ -0,0 +1,9 @@
+! { dg-do compile }
+! PR fortran/91959
+! Code contributed by Gerhard Steinmetz
+program p
+ implicit none
+ integer :: %a ! { dg-error "Invalid character" }
+ a = 1 ! { dg-error "has no IMPLICIT type" }
+ print *, a
+end
diff --git a/gcc/testsuite/gfortran.dg/typebound_call_22.f03 b/gcc/testsuite/gfortran.dg/typebound_call_22.f03
index b9f0b712573..30f86937fe2 100644
--- a/gcc/testsuite/gfortran.dg/typebound_call_22.f03
+++ b/gcc/testsuite/gfortran.dg/typebound_call_22.f03
@@ -26,4 +26,4 @@ program test
call x%bar ()
end program
-! { dg-final { scan-tree-dump-times "base \\(\\);" 1 "optimized" } }
+! { dg-final { scan-tree-dump-times "base \\(\\);" 1 "optimized" { xfail *-*-* } } }
diff --git a/gcc/testsuite/gfortran.dg/use_without_only_1.f90 b/gcc/testsuite/gfortran.dg/use_without_only_1.f90
index 06af9853933..ad64b206b76 100644
--- a/gcc/testsuite/gfortran.dg/use_without_only_1.f90
+++ b/gcc/testsuite/gfortran.dg/use_without_only_1.f90
@@ -6,16 +6,16 @@ MODULE foo
END MODULE
MODULE testmod
- USE foo ! { dg-warning "6:has no ONLY qualifier" }
+ USE foo ! { dg-warning "7:has no ONLY qualifier" }
IMPLICIT NONE
CONTAINS
SUBROUTINE S1
- USE foo ! { dg-warning "9:has no ONLY qualifier" }
+ USE foo ! { dg-warning "10:has no ONLY qualifier" }
END SUBROUTINE S1
SUBROUTINE S2
USE foo, ONLY: bar
END SUBROUTINE
SUBROUTINE S3
- USE ISO_C_BINDING ! { dg-warning "9:has no ONLY qualifier" }
+ USE ISO_C_BINDING ! { dg-warning "10:has no ONLY qualifier" }
END SUBROUTINE S3
END MODULE
diff --git a/gcc/testsuite/gfortran.dg/vect/vect-8.f90 b/gcc/testsuite/gfortran.dg/vect/vect-8.f90
index e26cdf95e51..386f7de4a7e 100644
--- a/gcc/testsuite/gfortran.dg/vect/vect-8.f90
+++ b/gcc/testsuite/gfortran.dg/vect/vect-8.f90
@@ -247,7 +247,7 @@ nl1= 1
nl2= 2
fw= 2.000D0
DO ky= 2,n
-DO kx= 2,3
+DO kx= 2,4
du1ky= u1(kx,ky+1,nl1)-u1(kx,ky-1,nl1)
du2ky= u2(kx,ky+1,nl1)-u2(kx,ky-1,nl1)
du3ky= u3(kx,ky+1,nl1)-u3(kx,ky-1,nl1)
diff --git a/gcc/testsuite/gfortran.dg/widechar_intrinsics_1.f90 b/gcc/testsuite/gfortran.dg/widechar_intrinsics_1.f90
index cb9804296dd..259ed1b783e 100644
--- a/gcc/testsuite/gfortran.dg/widechar_intrinsics_1.f90
+++ b/gcc/testsuite/gfortran.dg/widechar_intrinsics_1.f90
@@ -15,18 +15,18 @@
call date_and_time(s4, t4, u4) ! { dg-error "must be of kind 1" }
call get_command(s1)
- call get_command(s4) ! { dg-error "Type of argument" }
+ call get_command(s4) ! { dg-error "'CHARACTER\\(20,4\\)' to 'CHARACTER\\(\\*\\)'" }
call get_command_argument(1, s1)
- call get_command_argument(1, s4) ! { dg-error "Type of argument" }
+ call get_command_argument(1, s4) ! { dg-error "'CHARACTER\\(20,4\\)' to 'CHARACTER\\(\\*\\)'" }
call get_environment_variable("PATH", s1)
call get_environment_variable(s1)
call get_environment_variable(s1, t1)
- call get_environment_variable(4_"PATH", s1) ! { dg-error "Type of argument" }
- call get_environment_variable(s4) ! { dg-error "Type of argument" }
- call get_environment_variable(s1, t4) ! { dg-error "Type of argument" }
- call get_environment_variable(s4, t1) ! { dg-error "Type of argument" }
+ call get_environment_variable(4_"PATH", s1) ! { dg-error "'CHARACTER\\(4,4\\)' to 'CHARACTER\\(\\*\\)'" }
+ call get_environment_variable(s4) ! { dg-error "'CHARACTER\\(20,4\\)' to 'CHARACTER\\(\\*\\)'" }
+ call get_environment_variable(s1, t4) ! { dg-error "'CHARACTER\\(20,4\\)' to 'CHARACTER\\(\\*\\)'" }
+ call get_environment_variable(s4, t1) ! { dg-error "'CHARACTER\\(20,4\\)' to 'CHARACTER\\(\\*\\)'" }
print *, lge(s1,t1)
print *, lge(s1,"foo")
diff --git a/gcc/testsuite/gfortran.dg/widechar_intrinsics_2.f90 b/gcc/testsuite/gfortran.dg/widechar_intrinsics_2.f90
index 0a1d449b605..db4fc3c1f4e 100644
--- a/gcc/testsuite/gfortran.dg/widechar_intrinsics_2.f90
+++ b/gcc/testsuite/gfortran.dg/widechar_intrinsics_2.f90
@@ -38,9 +38,9 @@ program failme
call getcwd (s4, i) ! { dg-error "must be of kind" }
call getenv (s1, t1)
- call getenv (s1, t4) ! { dg-error "Type of argument" }
- call getenv (s4, t1) ! { dg-error "Type of argument" }
- call getenv (s4, t4) ! { dg-error "Type of argument" }
+ call getenv (s1, t4) ! { dg-error "'CHARACTER\\(20,4\\)' to 'CHARACTER\\(\\*\\)'" }
+ call getenv (s4, t1) ! { dg-error "'CHARACTER\\(20,4\\)' to 'CHARACTER\\(\\*\\)'" }
+ call getenv (s4, t4) ! { dg-error "'CHARACTER\\(20,4\\)' to 'CHARACTER\\(\\*\\)'" }
call getarg (i, s1)
call getarg (i, s4) ! { dg-error "must be of kind" }
@@ -115,8 +115,8 @@ program failme
call system (s1)
call system (s1, i)
- call system (s4) ! { dg-error "Type of argument" }
- call system (s4, i) ! { dg-error "Type of argument" }
+ call system (s4) ! { dg-error "'CHARACTER\\(20,4\\)' to 'CHARACTER\\(\\*\\)'" }
+ call system (s4, i) ! { dg-error "'CHARACTER\\(20,4\\)' to 'CHARACTER\\(\\*\\)'" }
call ttynam (i, s1)
call ttynam (i, s4) ! { dg-error "must be of kind" }
diff --git a/gcc/testsuite/gfortran.dg/widechar_intrinsics_3.f90 b/gcc/testsuite/gfortran.dg/widechar_intrinsics_3.f90
index 7073b893bb3..7995c3693f9 100644
--- a/gcc/testsuite/gfortran.dg/widechar_intrinsics_3.f90
+++ b/gcc/testsuite/gfortran.dg/widechar_intrinsics_3.f90
@@ -35,7 +35,7 @@ program failme
print *, fputc (i, s4) ! { dg-error "must be of kind" }
print *, getcwd (s1)
- print *, getcwd (s4) ! { dg-error "Type of argument" }
+ print *, getcwd (s4) ! { dg-error "'CHARACTER\\(20,4\\)' to 'CHARACTER\\(\\*\\)'" }
print *, hostnm (s1)
print *, hostnm (s4) ! { dg-error "must be of kind" }
@@ -61,7 +61,7 @@ program failme
print *, symlnk (s4, t4) ! { dg-error "must be of kind" }
print *, system (s1)
- print *, system (s4) ! { dg-error "Type of argument" }
+ print *, system (s4) ! { dg-error "'CHARACTER\\(20,4\\)' to 'CHARACTER\\(\\*\\)'" }
print *, unlink (s1)
print *, unlink (s4) ! { dg-error "must be of kind" }
diff --git a/gcc/testsuite/gnat.dg/opt82.adb b/gcc/testsuite/gnat.dg/opt82.adb
new file mode 100644
index 00000000000..9e8e7bb1344
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt82.adb
@@ -0,0 +1,14 @@
+-- { dg-do compile }
+-- { dg-options "-O2 -fdump-tree-optimized" }
+
+with Opt82_Pkg; use Opt82_Pkg;
+
+procedure Opt82 (R : access Rec) is
+begin
+ R.A := 'A';
+ R.B := 'B';
+ R.C := 'C';
+ R.D := 'D';
+exception
+ when Storage_Error => R.A := 'E';
+end;
diff --git a/gcc/testsuite/gnat.dg/opt82_pkg.ads b/gcc/testsuite/gnat.dg/opt82_pkg.ads
new file mode 100644
index 00000000000..7b67890aafc
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt82_pkg.ads
@@ -0,0 +1,10 @@
+
+-- { dg-final { scan-tree-dump "= 1145258561|= 1094861636" "optimized" } }
+
+package Opt82_Pkg is
+
+ type Rec is record
+ A, B, C, D : Character;
+ end record;
+
+end Opt82_Pkg;
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 5bb07e49d28..7a028735d4e 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -2523,6 +2523,10 @@ operation_could_trap_p (enum tree_code op, bool fp_operation, bool honor_trapv,
bool honor_snans = fp_operation && flag_signaling_nans != 0;
bool handled;
+ /* This function cannot tell whether or not COND_EXPR and VEC_COND_EXPR could
+ trap, because that depends on the respective condition op. */
+ gcc_assert (op != COND_EXPR && op != VEC_COND_EXPR);
+
if (TREE_CODE_CLASS (op) != tcc_comparison
&& TREE_CODE_CLASS (op) != tcc_unary
&& TREE_CODE_CLASS (op) != tcc_binary)
@@ -2610,6 +2614,10 @@ tree_could_trap_p (tree expr)
if (!expr)
return false;
+ /* For COND_EXPR and VEC_COND_EXPR only the condition may trap. */
+ if (TREE_CODE (expr) == COND_EXPR || TREE_CODE (expr) == VEC_COND_EXPR)
+ expr = TREE_OPERAND (expr, 0);
+
code = TREE_CODE (expr);
t = TREE_TYPE (expr);
@@ -4040,15 +4048,14 @@ maybe_remove_unreachable_handlers (void)
if (cfun->eh == NULL)
return;
-
+
FOR_EACH_VEC_SAFE_ELT (cfun->eh->lp_array, i, lp)
- if (lp && lp->post_landing_pad)
+ if (lp
+ && (lp->post_landing_pad == NULL_TREE
+ || label_to_block (cfun, lp->post_landing_pad) == NULL))
{
- if (label_to_block (cfun, lp->post_landing_pad) == NULL)
- {
- remove_unreachable_handlers ();
- return;
- }
+ remove_unreachable_handlers ();
+ return;
}
}
@@ -4211,6 +4218,27 @@ unsplit_all_eh (void)
return changed;
}
+/* Wrapper around unsplit_all_eh that makes it usable everywhere. */
+
+void
+unsplit_eh_edges (void)
+{
+ bool changed;
+
+ /* unsplit_all_eh can die looking up unreachable landing pads. */
+ maybe_remove_unreachable_handlers ();
+
+ changed = unsplit_all_eh ();
+
+ /* If EH edges have been unsplit, delete unreachable forwarder blocks. */
+ if (changed)
+ {
+ free_dominance_info (CDI_DOMINATORS);
+ free_dominance_info (CDI_POST_DOMINATORS);
+ delete_unreachable_blocks ();
+ }
+}
+
/* A subroutine of cleanup_empty_eh. Redirect all EH edges incoming
to OLD_BB to NEW_BB; return true on success, false on failure.
diff --git a/gcc/tree-eh.h b/gcc/tree-eh.h
index a588c10dcd5..511bb84aefb 100644
--- a/gcc/tree-eh.h
+++ b/gcc/tree-eh.h
@@ -50,6 +50,7 @@ extern bool maybe_duplicate_eh_stmt_fn (struct function *, gimple *,
hash_map<void *, void *> *, int);
extern bool maybe_duplicate_eh_stmt (gimple *, gimple *);
extern void maybe_remove_unreachable_handlers (void);
+extern void unsplit_eh_edges (void);
extern bool verify_eh_edges (gimple *);
extern bool verify_eh_dispatch_edge (geh_dispatch *);
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 822aae5b83f..af49813b0d1 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -120,6 +120,7 @@ along with GCC; see the file COPYING3. If not see
#include "fold-const.h"
#include "tree-ssa-sccvn.h"
#include "tree-cfgcleanup.h"
+#include "tree-ssa-dse.h"
/* Only handle PHIs with no more arguments unless we are asked to by
simd pragma. */
@@ -2873,7 +2874,7 @@ ifcvt_split_critical_edges (class loop *loop, bool aggressive_if_conv)
loop vectorization. */
static void
-ifcvt_local_dce (basic_block bb)
+ifcvt_local_dce (class loop *loop)
{
gimple *stmt;
gimple *stmt1;
@@ -2890,6 +2891,10 @@ ifcvt_local_dce (basic_block bb)
replace_uses_by (name_pair->first, name_pair->second);
redundant_ssa_names.release ();
+ /* The loop has a single BB only. */
+ basic_block bb = loop->header;
+ tree latch_vdef = NULL_TREE;
+
worklist.create (64);
/* Consider all phi as live statements. */
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -2897,6 +2902,8 @@ ifcvt_local_dce (basic_block bb)
phi = gsi_stmt (gsi);
gimple_set_plf (phi, GF_PLF_2, true);
worklist.safe_push (phi);
+ if (virtual_operand_p (gimple_phi_result (phi)))
+ latch_vdef = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop));
}
/* Consider load/store statements, CALL and COND as live. */
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -2960,6 +2967,19 @@ ifcvt_local_dce (basic_block bb)
while (!gsi_end_p (gsi))
{
stmt = gsi_stmt (gsi);
+ if (gimple_store_p (stmt))
+ {
+ tree lhs = gimple_get_lhs (stmt);
+ ao_ref write;
+ ao_ref_init (&write, lhs);
+
+ if (dse_classify_store (&write, stmt, false, NULL, NULL, latch_vdef)
+ == DSE_STORE_DEAD)
+ delete_dead_or_redundant_assignment (&gsi, "dead");
+ gsi_next (&gsi);
+ continue;
+ }
+
if (gimple_plf (stmt, GF_PLF_2))
{
gsi_next (&gsi);
@@ -3070,7 +3090,7 @@ tree_if_conversion (class loop *loop, vec<gimple *> *preds)
todo |= do_rpo_vn (cfun, loop_preheader_edge (loop), exit_bbs);
/* Delete dead predicate computations. */
- ifcvt_local_dce (loop->header);
+ ifcvt_local_dce (loop);
BITMAP_FREE (exit_bbs);
todo |= TODO_cleanup_cfg;
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index f9ad7e83943..db9b5694e85 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -54,7 +54,8 @@ static const unsigned HOST_WIDE_INT unknown[4] = {
static tree compute_object_offset (const_tree, const_tree);
static bool addr_object_size (struct object_size_info *,
- const_tree, int, unsigned HOST_WIDE_INT *);
+ const_tree, int, unsigned HOST_WIDE_INT *,
+ tree * = NULL);
static unsigned HOST_WIDE_INT alloc_object_size (const gcall *, int);
static tree pass_through_call (const gcall *);
static void collect_object_sizes_for (struct object_size_info *, tree);
@@ -172,10 +173,15 @@ compute_object_offset (const_tree expr, const_tree var)
static bool
addr_object_size (struct object_size_info *osi, const_tree ptr,
- int object_size_type, unsigned HOST_WIDE_INT *psize)
+ int object_size_type, unsigned HOST_WIDE_INT *psize,
+ tree *pdecl /* = NULL */)
{
tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
+ tree dummy;
+ if (!pdecl)
+ pdecl = &dummy;
+
gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
/* Set to unknown and overwrite just before returning if the size
@@ -195,7 +201,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
|| TREE_CODE (TREE_OPERAND (pt_var, 0)) != SSA_NAME)
{
compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
- object_size_type & ~1, &sz);
+ object_size_type & ~1, &sz, pdecl);
}
else
{
@@ -232,7 +238,10 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
&& DECL_P (pt_var)
&& tree_fits_uhwi_p (DECL_SIZE_UNIT (pt_var))
&& tree_to_uhwi (DECL_SIZE_UNIT (pt_var)) < offset_limit)
- pt_var_size = DECL_SIZE_UNIT (pt_var);
+ {
+ *pdecl = pt_var;
+ pt_var_size = DECL_SIZE_UNIT (pt_var);
+ }
else if (pt_var
&& TREE_CODE (pt_var) == STRING_CST
&& TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
@@ -478,13 +487,16 @@ pass_through_call (const gcall *call)
/* Compute __builtin_object_size value for PTR and set *PSIZE to
- the resulting value. OBJECT_SIZE_TYPE is the second argument
- to __builtin_object_size. Return true on success and false
- when the object size could not be determined. */
+ the resulting value. If the declared object is known and PDECL
+ is nonnull, sets *PDECL to the object's DECL. OBJECT_SIZE_TYPE
+ is the second argument to __builtin_object_size.
+ Returns true on success and false when the object size could not
+ be determined. */
bool
compute_builtin_object_size (tree ptr, int object_size_type,
- unsigned HOST_WIDE_INT *psize)
+ unsigned HOST_WIDE_INT *psize,
+ tree *pdecl /* = NULL */)
{
gcc_assert (object_size_type >= 0 && object_size_type <= 3);
@@ -496,7 +508,7 @@ compute_builtin_object_size (tree ptr, int object_size_type,
init_offset_limit ();
if (TREE_CODE (ptr) == ADDR_EXPR)
- return addr_object_size (NULL, ptr, object_size_type, psize);
+ return addr_object_size (NULL, ptr, object_size_type, psize, pdecl);
if (TREE_CODE (ptr) != SSA_NAME
|| !POINTER_TYPE_P (TREE_TYPE (ptr)))
@@ -520,7 +532,8 @@ compute_builtin_object_size (tree ptr, int object_size_type,
ptr = gimple_assign_rhs1 (def);
if (tree_fits_shwi_p (offset)
- && compute_builtin_object_size (ptr, object_size_type, psize))
+ && compute_builtin_object_size (ptr, object_size_type,
+ psize, pdecl))
{
/* Return zero when the offset is out of bounds. */
unsigned HOST_WIDE_INT off = tree_to_shwi (offset);
diff --git a/gcc/tree-object-size.h b/gcc/tree-object-size.h
index 420af3e0633..65528b3a696 100644
--- a/gcc/tree-object-size.h
+++ b/gcc/tree-object-size.h
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
extern void init_object_sizes (void);
extern void fini_object_sizes (void);
-extern bool compute_builtin_object_size (tree, int, unsigned HOST_WIDE_INT *);
+extern bool compute_builtin_object_size (tree, int, unsigned HOST_WIDE_INT *,
+ tree * = NULL);
#endif // GCC_TREE_OBJECT_SIZE_H
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
index ba67884a825..d8f7089786a 100644
--- a/gcc/tree-ssa-dse.c
+++ b/gcc/tree-ssa-dse.c
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "alias.h"
#include "tree-ssa-loop.h"
+#include "tree-ssa-dse.h"
/* This file implements dead store elimination.
@@ -76,21 +77,13 @@ along with GCC; see the file COPYING3. If not see
fact, they are the same transformation applied to different views of
the CFG. */
-static void delete_dead_or_redundant_assignment (gimple_stmt_iterator *, const char *);
+void delete_dead_or_redundant_assignment (gimple_stmt_iterator *, const char *);
static void delete_dead_or_redundant_call (gimple_stmt_iterator *, const char *);
/* Bitmap of blocks that have had EH statements cleaned. We should
remove their dead edges eventually. */
static bitmap need_eh_cleanup;
-/* Return value from dse_classify_store */
-enum dse_store_status
-{
- DSE_STORE_LIVE,
- DSE_STORE_MAYBE_PARTIAL_DEAD,
- DSE_STORE_DEAD
-};
-
/* STMT is a statement that may write into memory. Analyze it and
initialize WRITE to describe how STMT affects memory.
@@ -662,10 +655,10 @@ dse_optimize_redundant_stores (gimple *stmt)
if only clobber statements influenced the classification result.
Returns the classification. */
-static dse_store_status
+dse_store_status
dse_classify_store (ao_ref *ref, gimple *stmt,
bool byte_tracking_enabled, sbitmap live_bytes,
- bool *by_clobber_p = NULL)
+ bool *by_clobber_p, tree stop_at_vuse)
{
gimple *temp;
int cnt = 0;
@@ -701,6 +694,11 @@ dse_classify_store (ao_ref *ref, gimple *stmt,
}
else
defvar = gimple_vdef (temp);
+
+ /* If we're instructed to stop walking at region boundary, do so. */
+ if (defvar == stop_at_vuse)
+ return DSE_STORE_LIVE;
+
auto_vec<gimple *, 10> defs;
gimple *phi_def = NULL;
FOR_EACH_IMM_USE_STMT (use_stmt, ui, defvar)
@@ -901,7 +899,7 @@ delete_dead_or_redundant_call (gimple_stmt_iterator *gsi, const char *type)
/* Delete a dead store at GSI, which is a gimple assignment. */
-static void
+void
delete_dead_or_redundant_assignment (gimple_stmt_iterator *gsi, const char *type)
{
gimple *stmt = gsi_stmt (*gsi);
diff --git a/gcc/tree-ssa-dse.h b/gcc/tree-ssa-dse.h
new file mode 100644
index 00000000000..a5eccbd746d
--- /dev/null
+++ b/gcc/tree-ssa-dse.h
@@ -0,0 +1,36 @@
+/* Support routines for dead store elimination.
+ Copyright (C) 2019 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_TREE_SSA_DSE_H
+#define GCC_TREE_SSA_DSE_H
+
+/* Return value from dse_classify_store */
+enum dse_store_status
+{
+ DSE_STORE_LIVE,
+ DSE_STORE_MAYBE_PARTIAL_DEAD,
+ DSE_STORE_DEAD
+};
+
+dse_store_status dse_classify_store (ao_ref *, gimple *, bool, sbitmap,
+ bool * = NULL, tree = NULL);
+
+void delete_dead_or_redundant_assignment (gimple_stmt_iterator *, const char *);
+
+#endif /* GCC_TREE_SSA_DSE_H */
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 221f140b356..fe55ca958b4 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -527,9 +527,10 @@ forward_propagate_into_gimple_cond (gcond *stmt)
tmp = forward_propagate_into_comparison_1 (stmt, code,
boolean_type_node,
rhs1, rhs2);
- if (tmp)
+ if (tmp
+ && is_gimple_condexpr_for_cond (tmp))
{
- if (dump_file && tmp)
+ if (dump_file)
{
fprintf (dump_file, " Replaced '");
print_gimple_expr (dump_file, stmt, 0);
@@ -607,7 +608,7 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
if (tmp
&& is_gimple_condexpr (tmp))
{
- if (dump_file && tmp)
+ if (dump_file)
{
fprintf (dump_file, " Replaced '");
print_generic_expr (dump_file, cond);
@@ -1426,8 +1427,10 @@ simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2)
if (!is_gimple_val (ptr1))
ptr1 = force_gimple_operand_gsi (gsi_p, ptr1, true, NULL_TREE,
true, GSI_SAME_STMT);
- gimple_call_set_fndecl (stmt2,
- builtin_decl_explicit (BUILT_IN_MEMCPY));
+ tree fndecl = builtin_decl_explicit (BUILT_IN_MEMCPY);
+ gimple_call_set_fndecl (stmt2, fndecl);
+ gimple_call_set_fntype (as_a <gcall *> (stmt2),
+ TREE_TYPE (fndecl));
gimple_call_set_arg (stmt2, 0, ptr1);
gimple_call_set_arg (stmt2, 1, new_str_cst);
gimple_call_set_arg (stmt2, 2,
diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c
index 5952cad7bba..d38959c3aa2 100644
--- a/gcc/tree-ssa-loop-ivcanon.c
+++ b/gcc/tree-ssa-loop-ivcanon.c
@@ -195,9 +195,8 @@ constant_after_peeling (tree op, gimple *stmt, class loop *loop)
/* Induction variables are constants when defined in loop. */
if (loop_containing_stmt (stmt) != loop)
return false;
- tree ev = analyze_scalar_evolution (loop, op);
- if (chrec_contains_undetermined (ev)
- || chrec_contains_symbols (ev))
+ tree ev = instantiate_parameters (loop, analyze_scalar_evolution (loop, op));
+ if (chrec_contains_undetermined (ev))
return false;
return true;
}
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index c82bc7c4815..d68df19aa82 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -3801,40 +3801,44 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
tree type = TREE_TYPE (exp);
if (TREE_CODE (type) == INTEGER_TYPE
&& TYPE_MODE (type) == TYPE_MODE (char_type_node)
- && TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node))
+ && TYPE_PRECISION (type) == TYPE_PRECISION (char_type_node)
+ && tree_expr_nonzero_p (exp))
{
- /* Determine if the character EXP is known to be non-zero
- (even if its exact value is not known) and if so, recurse
- once to set the range, etc. */
- if (tree_expr_nonzero_p (exp))
- return count_nonzero_bytes (build_int_cst (type, 1),
- offset, nbytes, lenrange,
- nulterm, allnul, allnonnul, snlim);
- /* Don't know whether EXP is or isn't nonzero. */
- return false;
+ /* If the character EXP is known to be non-zero (even if its
+ exact value is not known) recurse once to set the range
+ for an arbitrary constant. */
+ exp = build_int_cst (type, 1);
+ return count_nonzero_bytes (exp, offset, 1, lenrange,
+ nulterm, allnul, allnonnul, snlim);
}
gimple *stmt = SSA_NAME_DEF_STMT (exp);
- if (gimple_code (stmt) != GIMPLE_PHI)
- return false;
-
- /* Avoid processing an SSA_NAME that has already been visited
- or if an SSA_NAME limit has been reached. Indicate success
- if the former and failure if the latter. */
- if (int res = snlim.next_ssa_name (exp))
- return res > 0;
-
- /* Determine the minimum and maximum from the PHI arguments. */
- unsigned int n = gimple_phi_num_args (stmt);
- for (unsigned i = 0; i != n; i++)
+ if (gimple_assign_single_p (stmt))
{
- tree def = gimple_phi_arg_def (stmt, i);
- if (!count_nonzero_bytes (def, offset, nbytes, lenrange, nulterm,
- allnul, allnonnul, snlim))
+ exp = gimple_assign_rhs1 (stmt);
+ if (TREE_CODE (exp) != MEM_REF)
return false;
}
+ else if (gimple_code (stmt) == GIMPLE_PHI)
+ {
+ /* Avoid processing an SSA_NAME that has already been visited
+ or if an SSA_NAME limit has been reached. Indicate success
+ if the former and failure if the latter. */
+ if (int res = snlim.next_ssa_name (exp))
+ return res > 0;
+
+ /* Determine the minimum and maximum from the PHI arguments. */
+ unsigned int n = gimple_phi_num_args (stmt);
+ for (unsigned i = 0; i != n; i++)
+ {
+ tree def = gimple_phi_arg_def (stmt, i);
+ if (!count_nonzero_bytes (def, offset, nbytes, lenrange, nulterm,
+ allnul, allnonnul, snlim))
+ return false;
+ }
- return true;
+ return true;
+ }
}
if (TREE_CODE (exp) == MEM_REF)
@@ -3897,14 +3901,25 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset,
prep = reinterpret_cast <char *>(buf);
/* Try to extract the representation of the constant object
or expression starting from the offset. */
- nbytes = native_encode_expr (exp, buf, sizeof buf, offset);
- if (!nbytes)
- return false;
+ unsigned repsize = native_encode_expr (exp, buf, sizeof buf, offset);
+ if (repsize < nbytes)
+ {
+ /* This should only happen when REPSIZE is zero because EXP
+ doesn't denote an object with a known initializer, except
+ perhaps when the reference reads past its end. */
+ lenrange[0] = 0;
+ prep = NULL;
+ }
+ else
+ nbytes = repsize;
}
+ if (!nbytes)
+ return false;
+
/* Compute the number of leading nonzero bytes in the representation
and update the minimum and maximum. */
- unsigned n = strnlen (prep, nbytes);
+ unsigned n = prep ? strnlen (prep, nbytes) : nbytes;
if (n < lenrange[0])
lenrange[0] = n;
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 350cee58246..3db4a5cdf78 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -5783,9 +5783,7 @@ vectorizable_reduction (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
bool is_simple_use;
int i;
int ncopies;
- stmt_vec_info prev_phi_info;
bool single_defuse_cycle = false;
- int j;
tree ops[3];
enum vect_def_type dts[3];
bool nested_cycle = false, found_nested_cycle_def = false;
@@ -5811,207 +5809,15 @@ vectorizable_reduction (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
gcc_assert (slp_node
&& REDUC_GROUP_FIRST_ELEMENT (stmt_info) == stmt_info);
- if (gphi *phi = dyn_cast <gphi *> (stmt_info->stmt))
+ if (is_a <gphi *> (stmt_info->stmt))
{
- tree phi_result = gimple_phi_result (phi);
/* Analysis is fully done on the reduction stmt invocation. */
- if (! vec_stmt)
- {
- if (slp_node)
- slp_node_instance->reduc_phis = slp_node;
-
- STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
- return true;
- }
-
- if (STMT_VINFO_REDUC_TYPE (stmt_info) == FOLD_LEFT_REDUCTION)
- /* Leave the scalar phi in place. Note that checking
- STMT_VINFO_VEC_REDUCTION_TYPE (as below) only works
- for reductions involving a single statement. */
- return true;
-
- stmt_vec_info reduc_stmt_info = STMT_VINFO_REDUC_DEF (stmt_info);
- reduc_stmt_info = vect_stmt_to_vectorize (reduc_stmt_info);
-
- if (STMT_VINFO_VEC_REDUCTION_TYPE (reduc_stmt_info)
- == EXTRACT_LAST_REDUCTION)
- /* Leave the scalar phi in place. */
- return true;
-
- if (gassign *reduc_stmt = dyn_cast <gassign *> (reduc_stmt_info->stmt))
- for (unsigned k = 1; k < gimple_num_ops (reduc_stmt); ++k)
- {
- tree op = gimple_op (reduc_stmt, k);
- if (op == phi_result)
- continue;
- if (k == 1 && gimple_assign_rhs_code (reduc_stmt) == COND_EXPR)
- continue;
- bool is_simple_use = vect_is_simple_use (op, loop_vinfo, &dt);
- gcc_assert (is_simple_use);
- if (dt == vect_constant_def || dt == vect_external_def)
- continue;
- if (!vectype_in
- || (GET_MODE_SIZE (SCALAR_TYPE_MODE (TREE_TYPE (vectype_in)))
- < GET_MODE_SIZE (SCALAR_TYPE_MODE (TREE_TYPE (op)))))
- vectype_in = get_vectype_for_scalar_type (TREE_TYPE (op));
- break;
- }
- /* For a nested cycle we might end up with an operation like
- phi_result * phi_result. */
- if (!vectype_in)
- vectype_in = STMT_VINFO_VECTYPE (stmt_info);
- gcc_assert (vectype_in);
+ gcc_assert (! vec_stmt);
if (slp_node)
- {
- /* The size vect_schedule_slp_instance computes is off for us. */
- vec_num = vect_get_num_vectors
- (LOOP_VINFO_VECT_FACTOR (loop_vinfo)
- * SLP_TREE_SCALAR_STMTS (slp_node).length (), vectype_in);
- ncopies = 1;
- }
- else
- {
- vec_num = 1;
- ncopies = vect_get_num_copies (loop_vinfo, vectype_in);
- }
-
- /* Check whether we can use a single PHI node and accumulate
- vectors to one before the backedge. */
- stmt_vec_info use_stmt_info;
- if (ncopies > 1
- && STMT_VINFO_RELEVANT (reduc_stmt_info) <= vect_used_only_live
- && (use_stmt_info = loop_vinfo->lookup_single_use (phi_result))
- && (!STMT_VINFO_IN_PATTERN_P (use_stmt_info)
- || !STMT_VINFO_PATTERN_DEF_SEQ (use_stmt_info))
- && vect_stmt_to_vectorize (use_stmt_info) == reduc_stmt_info)
- {
- single_defuse_cycle = true;
- ncopies = 1;
- }
-
- /* Create the destination vector */
- tree vec_dest = vect_create_destination_var (phi_result, vectype_out);
-
- /* Get the loop-entry arguments. */
- tree vec_initial_def;
- auto_vec<tree> vec_initial_defs;
- if (slp_node)
- {
- vec_initial_defs.reserve (vec_num);
- gcc_assert (slp_node == slp_node_instance->reduc_phis);
- stmt_vec_info first = REDUC_GROUP_FIRST_ELEMENT (reduc_stmt_info);
- tree neutral_op
- = neutral_op_for_slp_reduction (slp_node,
- STMT_VINFO_REDUC_CODE
- (first ? first : reduc_stmt_info),
- first != NULL);
- get_initial_defs_for_reduction (slp_node_instance->reduc_phis,
- &vec_initial_defs, vec_num,
- first != NULL, neutral_op);
- }
- else
- {
- /* Get at the scalar def before the loop, that defines the initial
- value of the reduction variable. */
- tree initial_def = PHI_ARG_DEF_FROM_EDGE (phi,
- loop_preheader_edge (loop));
- /* Optimize: if initial_def is for REDUC_MAX smaller than the base
- and we can't use zero for induc_val, use initial_def. Similarly
- for REDUC_MIN and initial_def larger than the base. */
- if (STMT_VINFO_VEC_REDUCTION_TYPE (reduc_stmt_info)
- == INTEGER_INDUC_COND_REDUCTION)
- {
- tree induc_val
- = STMT_VINFO_VEC_INDUC_COND_INITIAL_VAL (reduc_stmt_info);
- if (TREE_CODE (initial_def) == INTEGER_CST
- && (STMT_VINFO_VEC_REDUCTION_TYPE (reduc_stmt_info)
- == INTEGER_INDUC_COND_REDUCTION)
- && !integer_zerop (induc_val)
- && (((STMT_VINFO_VEC_COND_REDUC_CODE (reduc_stmt_info)
- == MAX_EXPR)
- && tree_int_cst_lt (initial_def, induc_val))
- || ((STMT_VINFO_VEC_COND_REDUC_CODE (reduc_stmt_info)
- == MIN_EXPR)
- && tree_int_cst_lt (induc_val, initial_def))))
- {
- induc_val = initial_def;
- /* Communicate we used the initial_def to epilouge
- generation. */
- STMT_VINFO_VEC_INDUC_COND_INITIAL_VAL (reduc_stmt_info)
- = NULL_TREE;
- }
- vec_initial_def = build_vector_from_val (vectype_out, induc_val);
- }
- else if (nested_cycle)
- {
- /* Do not use an adjustment def as that case is not supported
- correctly if ncopies is not one. */
- vec_initial_def = vect_get_vec_def_for_operand (initial_def,
- reduc_stmt_info);
- }
- else
- {
- tree adjustment_def = NULL_TREE;
- tree *adjustment_defp = &adjustment_def;
- enum tree_code code = STMT_VINFO_REDUC_CODE (reduc_stmt_info);
- /* ??? For the outer loop PHI we have to do a bit of searching
- to find the stmt with the code. reduc_stmt_info here is the
- loop-closed PHI of the inner reduction which means we can look
- at its single-arg def. */
- if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def)
- {
- tree def = gimple_phi_arg_def
- (as_a <gphi *> (reduc_stmt_info->stmt), 0);
- code = STMT_VINFO_REDUC_CODE
- (vect_stmt_to_vectorize (loop_vinfo->lookup_def (def)));
- adjustment_defp = NULL;
- }
- vec_initial_def
- = get_initial_def_for_reduction (reduc_stmt_info, code,
- initial_def, adjustment_defp);
- STMT_VINFO_REDUC_EPILOGUE_ADJUSTMENT (reduc_stmt_info)
- = adjustment_def;
- }
- vec_initial_defs.create (1);
- vec_initial_defs.quick_push (vec_initial_def);
- }
-
- /* Generate the reduction PHIs upfront. */
- prev_phi_info = NULL;
- for (i = 0; i < vec_num; i++)
- {
- tree vec_init_def = vec_initial_defs[i];
- for (j = 0; j < ncopies; j++)
- {
- /* Create the reduction-phi that defines the reduction
- operand. */
- gphi *new_phi = create_phi_node (vec_dest, loop->header);
- stmt_vec_info new_phi_info = loop_vinfo->add_stmt (new_phi);
-
- /* Set the loop-entry arg of the reduction-phi. */
- if (j != 0 && nested_cycle)
- vec_init_def = vect_get_vec_def_for_stmt_copy (loop_vinfo,
- vec_init_def);
- add_phi_arg (new_phi, vec_init_def, loop_preheader_edge (loop),
- UNKNOWN_LOCATION);
-
- /* The loop-latch arg is set in epilogue processing. */
-
- if (slp_node)
- SLP_TREE_VEC_STMTS (slp_node).quick_push (new_phi_info);
- else
- {
- if (j == 0)
- STMT_VINFO_VEC_STMT (stmt_info)
- = *vec_stmt = new_phi_info;
- else
- STMT_VINFO_RELATED_STMT (prev_phi_info) = new_phi_info;
- prev_phi_info = new_phi_info;
- }
- }
- }
+ slp_node_instance->reduc_phis = slp_node;
+ STMT_VINFO_TYPE (stmt_info) = cycle_phi_info_type;
return true;
}
@@ -6769,43 +6575,224 @@ vectorizable_reduction (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
vec_loop_masks *masks = &LOOP_VINFO_MASKS (loop_vinfo);
bool mask_by_cond_expr = use_mask_by_cond_expr_p (code, cond_fn, vectype_in);
- if (!vec_stmt) /* transformation not required. */
+ /* transformation not required. */
+ gcc_assert (!vec_stmt);
+
+ vect_model_reduction_cost (stmt_info, reduc_fn, ncopies, cost_vec);
+ if (loop_vinfo && LOOP_VINFO_CAN_FULLY_MASK_P (loop_vinfo))
{
- vect_model_reduction_cost (stmt_info, reduc_fn, ncopies, cost_vec);
- if (loop_vinfo && LOOP_VINFO_CAN_FULLY_MASK_P (loop_vinfo))
+ if (reduction_type != FOLD_LEFT_REDUCTION
+ && !mask_by_cond_expr
+ && (cond_fn == IFN_LAST
+ || !direct_internal_fn_supported_p (cond_fn, vectype_in,
+ OPTIMIZE_FOR_SPEED)))
{
- if (reduction_type != FOLD_LEFT_REDUCTION
- && !mask_by_cond_expr
- && (cond_fn == IFN_LAST
- || !direct_internal_fn_supported_p (cond_fn, vectype_in,
- OPTIMIZE_FOR_SPEED)))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "can't use a fully-masked loop because no"
- " conditional operation is available.\n");
- LOOP_VINFO_CAN_FULLY_MASK_P (loop_vinfo) = false;
- }
- else if (reduc_index == -1)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "can't use a fully-masked loop for chained"
- " reductions.\n");
- LOOP_VINFO_CAN_FULLY_MASK_P (loop_vinfo) = false;
- }
- else
- vect_record_loop_mask (loop_vinfo, masks, ncopies * vec_num,
- vectype_in);
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "can't use a fully-masked loop because no"
+ " conditional operation is available.\n");
+ LOOP_VINFO_CAN_FULLY_MASK_P (loop_vinfo) = false;
+ }
+ else if (reduc_index == -1)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "can't use a fully-masked loop for chained"
+ " reductions.\n");
+ LOOP_VINFO_CAN_FULLY_MASK_P (loop_vinfo) = false;
+ }
+ else
+ vect_record_loop_mask (loop_vinfo, masks, ncopies * vec_num,
+ vectype_in);
+ }
+ if (dump_enabled_p ()
+ && reduction_type == FOLD_LEFT_REDUCTION)
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "using an in-order (fold-left) reduction.\n");
+ STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
+ return true;
+}
+
+/* Transform the definition stmt STMT_INFO of a reduction PHI backedge
+ value. */
+
+bool
+vect_transform_reduction (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, slp_tree slp_node)
+{
+ tree vectype_out = STMT_VINFO_VECTYPE (stmt_info);
+ tree vectype_in = NULL_TREE;
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ enum tree_code code;
+ int op_type;
+ bool is_simple_use;
+ int i;
+ int ncopies;
+ bool single_defuse_cycle = false;
+ int j;
+ tree ops[3];
+ bool nested_cycle = false;
+ int vec_num;
+
+ if (nested_in_vect_loop_p (loop, stmt_info))
+ {
+ loop = loop->inner;
+ nested_cycle = true;
+ }
+
+ gassign *stmt = as_a <gassign *> (stmt_info->stmt);
+
+ /* Flatten RHS. */
+ switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
+ {
+ case GIMPLE_BINARY_RHS:
+ code = gimple_assign_rhs_code (stmt);
+ op_type = TREE_CODE_LENGTH (code);
+ gcc_assert (op_type == binary_op);
+ ops[0] = gimple_assign_rhs1 (stmt);
+ ops[1] = gimple_assign_rhs2 (stmt);
+ break;
+
+ case GIMPLE_TERNARY_RHS:
+ code = gimple_assign_rhs_code (stmt);
+ op_type = TREE_CODE_LENGTH (code);
+ gcc_assert (op_type == ternary_op);
+ ops[0] = gimple_assign_rhs1 (stmt);
+ ops[1] = gimple_assign_rhs2 (stmt);
+ ops[2] = gimple_assign_rhs3 (stmt);
+ break;
+
+ case GIMPLE_UNARY_RHS:
+ return false;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* All uses but the last are expected to be defined in the loop.
+ The last use is the reduction variable. In case of nested cycle this
+ assumption is not true: we use reduc_index to record the index of the
+ reduction variable. */
+ stmt_vec_info reduc_def_info
+ = STMT_VINFO_REDUC_DEF (vect_orig_stmt (stmt_info));
+ gcc_assert (reduc_def_info);
+ gphi *reduc_def_phi = as_a <gphi *> (reduc_def_info->stmt);
+ tree reduc_def = PHI_RESULT (reduc_def_phi);
+ int reduc_index = -1;
+ for (i = 0; i < op_type; i++)
+ {
+ /* The condition of COND_EXPR is checked in vectorizable_condition(). */
+ if (i == 0 && code == COND_EXPR)
+ continue;
+
+ stmt_vec_info def_stmt_info;
+ enum vect_def_type dt;
+ tree tem;
+ is_simple_use = vect_is_simple_use (ops[i], loop_vinfo, &dt, &tem,
+ &def_stmt_info);
+ gcc_assert (is_simple_use);
+ if (dt == vect_reduction_def
+ && ops[i] == reduc_def)
+ {
+ reduc_index = i;
+ continue;
+ }
+ else if (tem)
+ {
+ /* To properly compute ncopies we are interested in the widest
+ input type in case we're looking at a widening accumulation. */
+ if (!vectype_in
+ || (GET_MODE_SIZE (SCALAR_TYPE_MODE (TREE_TYPE (vectype_in)))
+ < GET_MODE_SIZE (SCALAR_TYPE_MODE (TREE_TYPE (tem)))))
+ vectype_in = tem;
+ }
+
+ if (dt == vect_nested_cycle
+ && ops[i] == reduc_def)
+ {
+ reduc_index = i;
}
- if (dump_enabled_p ()
- && reduction_type == FOLD_LEFT_REDUCTION)
- dump_printf_loc (MSG_NOTE, vect_location,
- "using an in-order (fold-left) reduction.\n");
- STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
- return true;
}
+ if (!vectype_in)
+ vectype_in = vectype_out;
+
+ if (STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info) == INTEGER_INDUC_COND_REDUCTION
+ && dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "condition expression based on "
+ "integer induction.\n");
+
+ if (slp_node)
+ ncopies = 1;
+ else
+ ncopies = vect_get_num_copies (loop_vinfo, vectype_in);
+
+ vect_reduction_type reduction_type
+ = STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info);
+
+ /* In case of widenning multiplication by a constant, we update the type
+ of the constant to be the type of the other operand. We check that the
+ constant fits the type in the pattern recognition pass. */
+ if (code == DOT_PROD_EXPR
+ && !types_compatible_p (TREE_TYPE (ops[0]), TREE_TYPE (ops[1])))
+ {
+ gcc_unreachable ();
+ /* No testcase for this. PR49478. */
+ if (TREE_CODE (ops[0]) == INTEGER_CST)
+ ops[0] = fold_convert (TREE_TYPE (ops[1]), ops[0]);
+ else if (TREE_CODE (ops[1]) == INTEGER_CST)
+ ops[1] = fold_convert (TREE_TYPE (ops[0]), ops[1]);
+ }
+
+ /* In case the vectorization factor (VF) is bigger than the number
+ of elements that we can fit in a vectype (nunits), we have to generate
+ more than one vector stmt - i.e - we need to "unroll" the
+ vector stmt by a factor VF/nunits. For more details see documentation
+ in vectorizable_operation. */
+
+ /* If the reduction is used in an outer loop we need to generate
+ VF intermediate results, like so (e.g. for ncopies=2):
+ r0 = phi (init, r0)
+ r1 = phi (init, r1)
+ r0 = x0 + r0;
+ r1 = x1 + r1;
+ (i.e. we generate VF results in 2 registers).
+ In this case we have a separate def-use cycle for each copy, and therefore
+ for each copy we get the vector def for the reduction variable from the
+ respective phi node created for this copy.
+
+ Otherwise (the reduction is unused in the loop nest), we can combine
+ together intermediate results, like so (e.g. for ncopies=2):
+ r = phi (init, r)
+ r = x0 + r;
+ r = x1 + r;
+ (i.e. we generate VF/2 results in a single register).
+ In this case for each copy we get the vector def for the reduction variable
+ from the vectorized reduction operation generated in the previous iteration.
+
+ This only works when we see both the reduction PHI and its only consumer
+ in vectorizable_reduction and there are no intermediate stmts
+ participating. */
+ stmt_vec_info use_stmt_info;
+ tree reduc_phi_result = gimple_phi_result (reduc_def_phi);
+ if (ncopies > 1
+ && (STMT_VINFO_RELEVANT (stmt_info) <= vect_used_only_live)
+ && (use_stmt_info = loop_vinfo->lookup_single_use (reduc_phi_result))
+ && (!STMT_VINFO_IN_PATTERN_P (use_stmt_info)
+ || !STMT_VINFO_PATTERN_DEF_SEQ (use_stmt_info))
+ && vect_stmt_to_vectorize (use_stmt_info) == stmt_info)
+ single_defuse_cycle = true;
+
+ if (slp_node)
+ vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
+ else
+ vec_num = 1;
+
+ internal_fn cond_fn = get_conditional_internal_fn (code);
+ vec_loop_masks *masks = &LOOP_VINFO_MASKS (loop_vinfo);
+ bool mask_by_cond_expr = use_mask_by_cond_expr_p (code, cond_fn, vectype_in);
/* Transform. */
stmt_vec_info new_stmt_info = NULL;
@@ -6826,9 +6813,12 @@ vectorizable_reduction (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
bool masked_loop_p = LOOP_VINFO_FULLY_MASKED_P (loop_vinfo);
if (reduction_type == FOLD_LEFT_REDUCTION)
- return vectorize_fold_left_reduction
- (stmt_info, gsi, vec_stmt, slp_node, reduc_def_phi, code,
- reduc_fn, ops, vectype_in, reduc_index, masks);
+ {
+ internal_fn reduc_fn = STMT_VINFO_REDUC_FN (stmt_info);
+ return vectorize_fold_left_reduction
+ (stmt_info, gsi, vec_stmt, slp_node, reduc_def_phi, code,
+ reduc_fn, ops, vectype_in, reduc_index, masks);
+ }
if (reduction_type == EXTRACT_LAST_REDUCTION)
{
@@ -6838,10 +6828,10 @@ vectorizable_reduction (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
}
/* Create the destination vector */
+ tree scalar_dest = gimple_assign_lhs (stmt);
tree vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
prev_stmt_info = NULL;
- prev_phi_info = NULL;
if (!slp_node)
{
vec_oprnds0.create (1);
@@ -6998,7 +6988,221 @@ vectorizable_reduction (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
return true;
}
-/* Vectorizes LC PHIs of nested cycles (sofar). */
+/* Transform phase of a cycle PHI. */
+
+bool
+vect_transform_cycle_phi (stmt_vec_info stmt_info, stmt_vec_info *vec_stmt,
+ slp_tree slp_node, slp_instance slp_node_instance)
+{
+ tree vectype_out = STMT_VINFO_VECTYPE (stmt_info);
+ tree vectype_in = NULL_TREE;
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ enum vect_def_type dt;
+ int i;
+ int ncopies;
+ stmt_vec_info prev_phi_info;
+ int j;
+ bool nested_cycle = false;
+ int vec_num;
+
+ if (nested_in_vect_loop_p (loop, stmt_info))
+ {
+ loop = loop->inner;
+ nested_cycle = true;
+ }
+
+ gphi *phi = as_a <gphi *> (stmt_info->stmt);
+ tree phi_result = gimple_phi_result (phi);
+
+ if (STMT_VINFO_REDUC_TYPE (stmt_info) == FOLD_LEFT_REDUCTION)
+ /* Leave the scalar phi in place. Note that checking
+ STMT_VINFO_VEC_REDUCTION_TYPE (as below) only works
+ for reductions involving a single statement. */
+ return true;
+
+ stmt_vec_info reduc_stmt_info = STMT_VINFO_REDUC_DEF (stmt_info);
+ reduc_stmt_info = vect_stmt_to_vectorize (reduc_stmt_info);
+
+ if (STMT_VINFO_VEC_REDUCTION_TYPE (reduc_stmt_info)
+ == EXTRACT_LAST_REDUCTION)
+ /* Leave the scalar phi in place. */
+ return true;
+
+ if (gassign *reduc_stmt = dyn_cast <gassign *> (reduc_stmt_info->stmt))
+ for (unsigned k = 1; k < gimple_num_ops (reduc_stmt); ++k)
+ {
+ tree op = gimple_op (reduc_stmt, k);
+ if (op == phi_result)
+ continue;
+ if (k == 1 && gimple_assign_rhs_code (reduc_stmt) == COND_EXPR)
+ continue;
+ bool is_simple_use = vect_is_simple_use (op, loop_vinfo, &dt);
+ gcc_assert (is_simple_use);
+ if (dt == vect_constant_def || dt == vect_external_def)
+ continue;
+ if (!vectype_in
+ || (GET_MODE_SIZE (SCALAR_TYPE_MODE (TREE_TYPE (vectype_in)))
+ < GET_MODE_SIZE (SCALAR_TYPE_MODE (TREE_TYPE (op)))))
+ vectype_in = get_vectype_for_scalar_type (TREE_TYPE (op));
+ break;
+ }
+ /* For a nested cycle we might end up with an operation like
+ phi_result * phi_result. */
+ if (!vectype_in)
+ vectype_in = STMT_VINFO_VECTYPE (stmt_info);
+ gcc_assert (vectype_in);
+
+ if (slp_node)
+ {
+ /* The size vect_schedule_slp_instance computes is off for us. */
+ vec_num = vect_get_num_vectors
+ (LOOP_VINFO_VECT_FACTOR (loop_vinfo)
+ * SLP_TREE_SCALAR_STMTS (slp_node).length (), vectype_in);
+ ncopies = 1;
+ }
+ else
+ {
+ vec_num = 1;
+ ncopies = vect_get_num_copies (loop_vinfo, vectype_in);
+ }
+
+ /* Check whether we can use a single PHI node and accumulate
+ vectors to one before the backedge. */
+ stmt_vec_info use_stmt_info;
+ if (ncopies > 1
+ && STMT_VINFO_RELEVANT (reduc_stmt_info) <= vect_used_only_live
+ && (use_stmt_info = loop_vinfo->lookup_single_use (phi_result))
+ && (!STMT_VINFO_IN_PATTERN_P (use_stmt_info)
+ || !STMT_VINFO_PATTERN_DEF_SEQ (use_stmt_info))
+ && vect_stmt_to_vectorize (use_stmt_info) == reduc_stmt_info)
+ ncopies = 1;
+
+ /* Create the destination vector */
+ tree vec_dest = vect_create_destination_var (phi_result, vectype_out);
+
+ /* Get the loop-entry arguments. */
+ tree vec_initial_def;
+ auto_vec<tree> vec_initial_defs;
+ if (slp_node)
+ {
+ vec_initial_defs.reserve (vec_num);
+ gcc_assert (slp_node == slp_node_instance->reduc_phis);
+ stmt_vec_info first = REDUC_GROUP_FIRST_ELEMENT (reduc_stmt_info);
+ tree neutral_op
+ = neutral_op_for_slp_reduction (slp_node,
+ STMT_VINFO_REDUC_CODE
+ (first ? first : reduc_stmt_info),
+ first != NULL);
+ get_initial_defs_for_reduction (slp_node_instance->reduc_phis,
+ &vec_initial_defs, vec_num,
+ first != NULL, neutral_op);
+ }
+ else
+ {
+ /* Get at the scalar def before the loop, that defines the initial
+ value of the reduction variable. */
+ tree initial_def = PHI_ARG_DEF_FROM_EDGE (phi,
+ loop_preheader_edge (loop));
+ /* Optimize: if initial_def is for REDUC_MAX smaller than the base
+ and we can't use zero for induc_val, use initial_def. Similarly
+ for REDUC_MIN and initial_def larger than the base. */
+ if (STMT_VINFO_VEC_REDUCTION_TYPE (reduc_stmt_info)
+ == INTEGER_INDUC_COND_REDUCTION)
+ {
+ tree induc_val
+ = STMT_VINFO_VEC_INDUC_COND_INITIAL_VAL (reduc_stmt_info);
+ if (TREE_CODE (initial_def) == INTEGER_CST
+ && (STMT_VINFO_VEC_REDUCTION_TYPE (reduc_stmt_info)
+ == INTEGER_INDUC_COND_REDUCTION)
+ && !integer_zerop (induc_val)
+ && (((STMT_VINFO_VEC_COND_REDUC_CODE (reduc_stmt_info)
+ == MAX_EXPR)
+ && tree_int_cst_lt (initial_def, induc_val))
+ || ((STMT_VINFO_VEC_COND_REDUC_CODE (reduc_stmt_info)
+ == MIN_EXPR)
+ && tree_int_cst_lt (induc_val, initial_def))))
+ {
+ induc_val = initial_def;
+ /* Communicate we used the initial_def to epilouge
+ generation. */
+ STMT_VINFO_VEC_INDUC_COND_INITIAL_VAL (reduc_stmt_info)
+ = NULL_TREE;
+ }
+ vec_initial_def = build_vector_from_val (vectype_out, induc_val);
+ }
+ else if (nested_cycle)
+ {
+ /* Do not use an adjustment def as that case is not supported
+ correctly if ncopies is not one. */
+ vec_initial_def = vect_get_vec_def_for_operand (initial_def,
+ reduc_stmt_info);
+ }
+ else
+ {
+ tree adjustment_def = NULL_TREE;
+ tree *adjustment_defp = &adjustment_def;
+ enum tree_code code = STMT_VINFO_REDUC_CODE (reduc_stmt_info);
+ /* ??? For the outer loop PHI we have to do a bit of searching
+ to find the stmt with the code. reduc_stmt_info here is the
+ loop-closed PHI of the inner reduction which means we can look
+ at its single-arg def. */
+ if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def)
+ {
+ tree def = gimple_phi_arg_def
+ (as_a <gphi *> (reduc_stmt_info->stmt), 0);
+ code = STMT_VINFO_REDUC_CODE
+ (vect_stmt_to_vectorize (loop_vinfo->lookup_def (def)));
+ adjustment_defp = NULL;
+ }
+ vec_initial_def
+ = get_initial_def_for_reduction (reduc_stmt_info, code,
+ initial_def, adjustment_defp);
+ STMT_VINFO_REDUC_EPILOGUE_ADJUSTMENT (reduc_stmt_info)
+ = adjustment_def;
+ }
+ vec_initial_defs.create (1);
+ vec_initial_defs.quick_push (vec_initial_def);
+ }
+
+ /* Generate the reduction PHIs upfront. */
+ prev_phi_info = NULL;
+ for (i = 0; i < vec_num; i++)
+ {
+ tree vec_init_def = vec_initial_defs[i];
+ for (j = 0; j < ncopies; j++)
+ {
+ /* Create the reduction-phi that defines the reduction
+ operand. */
+ gphi *new_phi = create_phi_node (vec_dest, loop->header);
+ stmt_vec_info new_phi_info = loop_vinfo->add_stmt (new_phi);
+
+ /* Set the loop-entry arg of the reduction-phi. */
+ if (j != 0 && nested_cycle)
+ vec_init_def = vect_get_vec_def_for_stmt_copy (loop_vinfo,
+ vec_init_def);
+ add_phi_arg (new_phi, vec_init_def, loop_preheader_edge (loop),
+ UNKNOWN_LOCATION);
+
+ /* The loop-latch arg is set in epilogue processing. */
+
+ if (slp_node)
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_phi_info);
+ else
+ {
+ if (j == 0)
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_phi_info;
+ else
+ STMT_VINFO_RELATED_STMT (prev_phi_info) = new_phi_info;
+ prev_phi_info = new_phi_info;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Vectorizes LC PHIs. */
bool
vectorizable_lc_phi (stmt_vec_info stmt_info, stmt_vec_info *vec_stmt,
@@ -7697,7 +7901,10 @@ vectorizable_live_operation (stmt_vec_info stmt_info,
return true;
if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def)
{
- if (STMT_VINFO_REDUC_TYPE (stmt_info) == FOLD_LEFT_REDUCTION)
+ if (STMT_VINFO_REDUC_TYPE (stmt_info) == FOLD_LEFT_REDUCTION
+ || (STMT_VINFO_REDUC_TYPE (stmt_info) == COND_REDUCTION
+ && (STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
+ == EXTRACT_LAST_REDUCTION)))
return true;
if (slp_node)
{
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 4dfebbefce6..09db74bdd77 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -46,6 +46,8 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "omp-simd-clone.h"
#include "predict.h"
+#include "tree-vector-builder.h"
+#include "vec-perm-indices.h"
/* Return true if we have a useful VR_RANGE range for VAR, storing it
in *MIN_VALUE and *MAX_VALUE if so. Note the range in the dump files. */
@@ -2168,24 +2170,107 @@ vect_recog_rotate_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
enum vect_def_type dt;
optab optab1, optab2;
edge ext_def = NULL;
+ bool bswap16_p = false;
- if (!is_gimple_assign (last_stmt))
- return NULL;
+ if (is_gimple_assign (last_stmt))
+ {
+ rhs_code = gimple_assign_rhs_code (last_stmt);
+ switch (rhs_code)
+ {
+ case LROTATE_EXPR:
+ case RROTATE_EXPR:
+ break;
+ default:
+ return NULL;
+ }
- rhs_code = gimple_assign_rhs_code (last_stmt);
- switch (rhs_code)
+ lhs = gimple_assign_lhs (last_stmt);
+ oprnd0 = gimple_assign_rhs1 (last_stmt);
+ type = TREE_TYPE (oprnd0);
+ oprnd1 = gimple_assign_rhs2 (last_stmt);
+ }
+ else if (gimple_call_builtin_p (last_stmt, BUILT_IN_BSWAP16))
{
- case LROTATE_EXPR:
- case RROTATE_EXPR:
- break;
- default:
- return NULL;
+ /* __builtin_bswap16 (x) is another form of x r>> 8.
+ The vectorizer has bswap support, but only if the argument isn't
+ promoted. */
+ lhs = gimple_call_lhs (last_stmt);
+ oprnd0 = gimple_call_arg (last_stmt, 0);
+ type = TREE_TYPE (oprnd0);
+ if (TYPE_PRECISION (TREE_TYPE (lhs)) != 16
+ || TYPE_PRECISION (type) <= 16
+ || TREE_CODE (oprnd0) != SSA_NAME
+ || BITS_PER_UNIT != 8
+ || !TYPE_UNSIGNED (TREE_TYPE (lhs)))
+ return NULL;
+
+ stmt_vec_info def_stmt_info;
+ if (!vect_is_simple_use (oprnd0, vinfo, &dt, &def_stmt_info, &def_stmt))
+ return NULL;
+
+ if (dt != vect_internal_def)
+ return NULL;
+
+ if (gimple_assign_cast_p (def_stmt))
+ {
+ def = gimple_assign_rhs1 (def_stmt);
+ if (INTEGRAL_TYPE_P (TREE_TYPE (def))
+ && TYPE_PRECISION (TREE_TYPE (def)) == 16)
+ oprnd0 = def;
+ }
+
+ type = TREE_TYPE (lhs);
+ vectype = get_vectype_for_scalar_type (type);
+ if (vectype == NULL_TREE)
+ return NULL;
+
+ if (tree char_vectype = get_same_sized_vectype (char_type_node, vectype))
+ {
+ /* The encoding uses one stepped pattern for each byte in the
+ 16-bit word. */
+ vec_perm_builder elts (TYPE_VECTOR_SUBPARTS (char_vectype), 2, 3);
+ for (unsigned i = 0; i < 3; ++i)
+ for (unsigned j = 0; j < 2; ++j)
+ elts.quick_push ((i + 1) * 2 - j - 1);
+
+ vec_perm_indices indices (elts, 1,
+ TYPE_VECTOR_SUBPARTS (char_vectype));
+ if (can_vec_perm_const_p (TYPE_MODE (char_vectype), indices))
+ {
+ /* vectorizable_bswap can handle the __builtin_bswap16 if we
+ undo the argument promotion. */
+ if (!useless_type_conversion_p (type, TREE_TYPE (oprnd0)))
+ {
+ def = vect_recog_temp_ssa_var (type, NULL);
+ def_stmt = gimple_build_assign (def, NOP_EXPR, oprnd0);
+ append_pattern_def_seq (stmt_vinfo, def_stmt);
+ oprnd0 = def;
+ }
+
+ /* Pattern detected. */
+ vect_pattern_detected ("vect_recog_rotate_pattern", last_stmt);
+
+ *type_out = vectype;
+
+ /* Pattern supported. Create a stmt to be used to replace the
+ pattern, with the unpromoted argument. */
+ var = vect_recog_temp_ssa_var (type, NULL);
+ pattern_stmt = gimple_build_call (gimple_call_fndecl (last_stmt),
+ 1, oprnd0);
+ gimple_call_set_lhs (pattern_stmt, var);
+ gimple_call_set_fntype (as_a <gcall *> (pattern_stmt),
+ gimple_call_fntype (last_stmt));
+ return pattern_stmt;
+ }
+ }
+
+ oprnd1 = build_int_cst (integer_type_node, 8);
+ rhs_code = LROTATE_EXPR;
+ bswap16_p = true;
}
+ else
+ return NULL;
- lhs = gimple_assign_lhs (last_stmt);
- oprnd0 = gimple_assign_rhs1 (last_stmt);
- type = TREE_TYPE (oprnd0);
- oprnd1 = gimple_assign_rhs2 (last_stmt);
if (TREE_CODE (oprnd0) != SSA_NAME
|| TYPE_PRECISION (TREE_TYPE (lhs)) != TYPE_PRECISION (type)
|| !INTEGRAL_TYPE_P (type)
@@ -2210,14 +2295,39 @@ vect_recog_rotate_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
optab1 = optab_for_tree_code (rhs_code, vectype, optab_vector);
if (optab1
&& optab_handler (optab1, TYPE_MODE (vectype)) != CODE_FOR_nothing)
- return NULL;
+ {
+ use_rotate:
+ if (bswap16_p)
+ {
+ if (!useless_type_conversion_p (type, TREE_TYPE (oprnd0)))
+ {
+ def = vect_recog_temp_ssa_var (type, NULL);
+ def_stmt = gimple_build_assign (def, NOP_EXPR, oprnd0);
+ append_pattern_def_seq (stmt_vinfo, def_stmt);
+ oprnd0 = def;
+ }
+
+ /* Pattern detected. */
+ vect_pattern_detected ("vect_recog_rotate_pattern", last_stmt);
+
+ *type_out = vectype;
+
+ /* Pattern supported. Create a stmt to be used to replace the
+ pattern. */
+ var = vect_recog_temp_ssa_var (type, NULL);
+ pattern_stmt = gimple_build_assign (var, LROTATE_EXPR, oprnd0,
+ oprnd1);
+ return pattern_stmt;
+ }
+ return NULL;
+ }
if (is_a <bb_vec_info> (vinfo) || dt != vect_internal_def)
{
optab2 = optab_for_tree_code (rhs_code, vectype, optab_scalar);
if (optab2
&& optab_handler (optab2, TYPE_MODE (vectype)) != CODE_FOR_nothing)
- return NULL;
+ goto use_rotate;
}
/* If vector/vector or vector/scalar shifts aren't supported by the target,
@@ -2242,6 +2352,14 @@ vect_recog_rotate_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
*type_out = vectype;
+ if (bswap16_p && !useless_type_conversion_p (type, TREE_TYPE (oprnd0)))
+ {
+ def = vect_recog_temp_ssa_var (type, NULL);
+ def_stmt = gimple_build_assign (def, NOP_EXPR, oprnd0);
+ append_pattern_def_seq (stmt_vinfo, def_stmt);
+ oprnd0 = def;
+ }
+
if (dt == vect_external_def
&& TREE_CODE (oprnd1) == SSA_NAME)
ext_def = vect_get_external_def_edge (vinfo, oprnd1);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 7fcd2fa19a8..cac7410387b 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -10819,8 +10819,13 @@ vect_transform_stmt (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
break;
case reduc_vec_info_type:
- done = vectorizable_reduction (stmt_info, gsi, &vec_stmt, slp_node,
- slp_node_instance, NULL);
+ done = vect_transform_reduction (stmt_info, gsi, &vec_stmt, slp_node);
+ gcc_assert (done);
+ break;
+
+ case cycle_phi_info_type:
+ done = vect_transform_cycle_phi (stmt_info, &vec_stmt, slp_node,
+ slp_node_instance);
gcc_assert (done);
break;
@@ -10892,6 +10897,9 @@ vect_transform_stmt (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
stmt_vec_info orig_stmt_info = vect_orig_stmt (stmt_info);
if (!slp_node && STMT_VINFO_REDUC_DEF (orig_stmt_info)
&& STMT_VINFO_REDUC_TYPE (orig_stmt_info) != FOLD_LEFT_REDUCTION
+ && (STMT_VINFO_REDUC_TYPE (orig_stmt_info) != COND_REDUCTION
+ || (STMT_VINFO_VEC_REDUCTION_TYPE (orig_stmt_info)
+ != EXTRACT_LAST_REDUCTION))
&& is_a <gphi *> (STMT_VINFO_REDUC_DEF (orig_stmt_info)->stmt))
{
gphi *phi = as_a <gphi *> (STMT_VINFO_REDUC_DEF (orig_stmt_info)->stmt);
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 462a968f2ba..837fb5ab525 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -694,6 +694,7 @@ enum stmt_vec_info_type {
type_promotion_vec_info_type,
type_demotion_vec_info_type,
type_conversion_vec_info_type,
+ cycle_phi_info_type,
lc_phi_info_type,
loop_exit_ctrl_vec_info_type
};
@@ -1658,6 +1659,10 @@ extern bool vectorizable_reduction (stmt_vec_info, gimple_stmt_iterator *,
extern bool vectorizable_induction (stmt_vec_info, gimple_stmt_iterator *,
stmt_vec_info *, slp_tree,
stmt_vector_for_cost *);
+extern bool vect_transform_reduction (stmt_vec_info, gimple_stmt_iterator *,
+ stmt_vec_info *, slp_tree);
+extern bool vect_transform_cycle_phi (stmt_vec_info, stmt_vec_info *,
+ slp_tree, slp_instance);
extern bool vectorizable_lc_phi (stmt_vec_info, stmt_vec_info *, slp_tree);
extern bool vect_worthwhile_without_simd_p (vec_info *, tree_code);
extern int vect_get_known_peeling_cost (loop_vec_info, int, int *,
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index a2ab4a21925..d69cfb107cb 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -379,10 +379,7 @@ value_range_base::singleton_p (tree *result) const
}
return false;
}
-
- /* An anti-range that includes an extreme, is just a range with
- one sub-range. Use the one sub-range. */
- if (vrp_val_is_min (m_min, true) || vrp_val_is_max (m_max, true))
+ if (num_pairs () == 1)
{
value_range_base vr0, vr1;
ranges_from_anti_range (this, &vr0, &vr1, true);
@@ -913,15 +910,21 @@ vrp_bitmap_equal_p (const_bitmap b1, const_bitmap b2)
&& bitmap_equal_p (b1, b2)));
}
+static bool
+range_has_numeric_bounds_p (const value_range_base *vr)
+{
+ return (vr->min ()
+ && TREE_CODE (vr->min ()) == INTEGER_CST
+ && TREE_CODE (vr->max ()) == INTEGER_CST);
+}
+
/* Return true if max and min of VR are INTEGER_CST. It's not necessary
a singleton. */
bool
range_int_cst_p (const value_range_base *vr)
{
- return (vr->kind () == VR_RANGE
- && TREE_CODE (vr->min ()) == INTEGER_CST
- && TREE_CODE (vr->max ()) == INTEGER_CST);
+ return (vr->kind () == VR_RANGE && range_has_numeric_bounds_p (vr));
}
/* Return true if VR is a INTEGER_CST singleton. */
@@ -1763,119 +1766,102 @@ extract_range_from_plus_minus_expr (value_range_base *vr,
vr->set (kind, min, max);
}
-/* Normalize a value_range for use in range_ops and return it. */
+/* Return the range-ops handler for CODE and EXPR_TYPE. If no
+ suitable operator is found, return NULL and set VR to VARYING. */
-static value_range_base
-normalize_for_range_ops (const value_range_base &vr)
+static const range_operator *
+get_range_op_handler (value_range_base *vr,
+ enum tree_code code,
+ tree expr_type)
{
- tree type = vr.type ();
+ const range_operator *op = range_op_handler (code, expr_type);
+ if (!op)
+ vr->set_varying (expr_type);
+ return op;
+}
+
+/* If the types passed are supported, return TRUE, otherwise set VR to
+ VARYING and return FALSE. */
- /* This will return ~[0,0] for [&var, &var]. */
- if (POINTER_TYPE_P (type) && !range_includes_zero_p (&vr))
+static bool
+supported_types_p (value_range_base *vr,
+ tree type0,
+ tree type1 = NULL)
+{
+ if (!value_range_base::supports_type_p (type0)
+ || (type1 && !value_range_base::supports_type_p (type1)))
{
- value_range_base temp;
- temp.set_nonzero (type);
- return temp;
+ vr->set_varying (type0);
+ return false;
}
- if (vr.symbolic_p ())
- return normalize_for_range_ops (vr.normalize_symbolics ());
- if (TREE_CODE (vr.min ()) == INTEGER_CST
- && TREE_CODE (vr.max ()) == INTEGER_CST)
- return vr;
- /* Anything not strictly numeric at this point becomes varying. */
- return value_range_base (vr.type ());
+ return true;
}
-/* Fold a binary expression of two value_range's with range-ops. */
+/* If any of the ranges passed are defined, return TRUE, otherwise set
+ VR to UNDEFINED and return FALSE. */
-void
-range_fold_binary_expr (value_range_base *vr,
- enum tree_code code,
- tree expr_type,
- const value_range_base *vr0_,
- const value_range_base *vr1_)
+static bool
+defined_ranges_p (value_range_base *vr,
+ const value_range_base *vr0,
+ const value_range_base *vr1 = NULL)
{
- if (!value_range_base::supports_type_p (expr_type)
- || (!vr0_->undefined_p ()
- && !value_range_base::supports_type_p (vr0_->type ()))
- || (!vr1_->undefined_p ()
- && !value_range_base::supports_type_p (vr1_->type ())))
- {
- vr->set_varying (expr_type);
- return;
- }
- if (vr0_->undefined_p () && vr1_->undefined_p ())
+ if (vr0->undefined_p () && (!vr1 || vr1->undefined_p ()))
{
vr->set_undefined ();
- return;
- }
- range_operator *op = range_op_handler (code, expr_type);
- if (!op)
- {
- vr->set_varying (expr_type);
- return;
+ return false;
}
+ return true;
+}
- /* Mimic any behavior users of extract_range_from_binary_expr may
- expect. */
- value_range_base vr0 = *vr0_, vr1 = *vr1_;
- if (vr0.undefined_p ())
- vr0.set_varying (expr_type);
- else if (vr1.undefined_p ())
- vr1.set_varying (expr_type);
+static value_range_base
+drop_undefines_to_varying (const value_range_base *vr, tree expr_type)
+{
+ if (vr->undefined_p ())
+ return value_range_base (expr_type);
+ else
+ return *vr;
+}
+
+/* If any operand is symbolic, perform a binary operation on them and
+ return TRUE, otherwise return FALSE. */
- /* Handle symbolics. */
- if (vr0.symbolic_p () || vr1.symbolic_p ())
+static bool
+range_fold_binary_symbolics_p (value_range_base *vr,
+ tree_code code,
+ tree expr_type,
+ const value_range_base *vr0,
+ const value_range_base *vr1)
+{
+ if (vr0->symbolic_p () || vr1->symbolic_p ())
{
if ((code == PLUS_EXPR || code == MINUS_EXPR))
{
- extract_range_from_plus_minus_expr (vr, code, expr_type,
- &vr0, &vr1);
- return;
+ extract_range_from_plus_minus_expr (vr, code, expr_type, vr0, vr1);
+ return true;
}
if (POINTER_TYPE_P (expr_type) && code == POINTER_PLUS_EXPR)
{
- extract_range_from_pointer_plus_expr (vr, code, expr_type,
- &vr0, &vr1);
- return;
+ extract_range_from_pointer_plus_expr (vr, code, expr_type, vr0, vr1);
+ return true;
}
+ const range_operator *op = get_range_op_handler (vr, code, expr_type);
+ *vr = op->fold_range (expr_type,
+ vr0->normalize_symbolics (),
+ vr1->normalize_symbolics ());
+ return true;
}
-
- /* Do the range-ops dance. */
- value_range_base n0 = normalize_for_range_ops (vr0);
- value_range_base n1 = normalize_for_range_ops (vr1);
- *vr = op->fold_range (expr_type, n0, n1);
+ return false;
}
-/* Fold a unary expression of a value_range with range-ops. */
+/* If operand is symbolic, perform a unary operation on it and return
+ TRUE, otherwise return FALSE. */
-void
-range_fold_unary_expr (value_range_base *vr,
- enum tree_code code, tree expr_type,
- const value_range_base *vr0,
- tree vr0_type)
+static bool
+range_fold_unary_symbolics_p (value_range_base *vr,
+ tree_code code,
+ tree expr_type,
+ const value_range_base *vr0)
{
- /* Mimic any behavior users of extract_range_from_unary_expr may
- expect. */
- if (!value_range_base::supports_type_p (expr_type)
- || !value_range_base::supports_type_p (vr0_type))
- {
- vr->set_varying (expr_type);
- return;
- }
- if (vr0->undefined_p ())
- {
- vr->set_undefined ();
- return;
- }
- range_operator *op = range_op_handler (code, expr_type);
- if (!op)
- {
- vr->set_varying (expr_type);
- return;
- }
-
- /* Handle symbolics. */
if (vr0->symbolic_p ())
{
if (code == NEGATE_EXPR)
@@ -1884,7 +1870,7 @@ range_fold_unary_expr (value_range_base *vr,
value_range_base zero;
zero.set_zero (vr0->type ());
range_fold_binary_expr (vr, MINUS_EXPR, expr_type, &zero, vr0);
- return;
+ return true;
}
if (code == BIT_NOT_EXPR)
{
@@ -1892,30 +1878,64 @@ range_fold_unary_expr (value_range_base *vr,
value_range_base minusone;
minusone.set (build_int_cst (vr0->type (), -1));
range_fold_binary_expr (vr, MINUS_EXPR, expr_type, &minusone, vr0);
- return;
+ return true;
}
+ const range_operator *op = get_range_op_handler (vr, code, expr_type);
*vr = op->fold_range (expr_type,
- normalize_for_range_ops (*vr0),
+ vr0->normalize_symbolics (),
value_range_base (expr_type));
- return;
- }
- if (CONVERT_EXPR_CODE_P (code) && (POINTER_TYPE_P (expr_type)
- || POINTER_TYPE_P (vr0->type ())))
- {
- /* This handles symbolic conversions such such as [25, x_4]. */
- if (!range_includes_zero_p (vr0))
- vr->set_nonzero (expr_type);
- else if (vr0->zero_p ())
- vr->set_zero (expr_type);
- else
- vr->set_varying (expr_type);
- return;
+ return true;
}
+ return false;
+}
+
+/* Perform a binary operation on a pair of ranges. */
+
+void
+range_fold_binary_expr (value_range_base *vr,
+ enum tree_code code,
+ tree expr_type,
+ const value_range_base *vr0_,
+ const value_range_base *vr1_)
+{
+ if (!supported_types_p (vr, expr_type)
+ || !defined_ranges_p (vr, vr0_, vr1_))
+ return;
+ const range_operator *op = get_range_op_handler (vr, code, expr_type);
+ if (!op)
+ return;
+
+ value_range_base vr0 = drop_undefines_to_varying (vr0_, expr_type);
+ value_range_base vr1 = drop_undefines_to_varying (vr1_, expr_type);
+ if (range_fold_binary_symbolics_p (vr, code, expr_type, &vr0, &vr1))
+ return;
+
+ *vr = op->fold_range (expr_type,
+ vr0.normalize_addresses (),
+ vr1.normalize_addresses ());
+}
+
+/* Perform a unary operation on a range. */
+
+void
+range_fold_unary_expr (value_range_base *vr,
+ enum tree_code code, tree expr_type,
+ const value_range_base *vr0,
+ tree vr0_type)
+{
+ if (!supported_types_p (vr, expr_type, vr0_type)
+ || !defined_ranges_p (vr, vr0))
+ return;
+ const range_operator *op = get_range_op_handler (vr, code, expr_type);
+ if (!op)
+ return;
- /* Do the range-ops dance. */
- value_range_base n0 = normalize_for_range_ops (*vr0);
- value_range_base n1 (expr_type);
- *vr = op->fold_range (expr_type, n0, n1);
+ if (range_fold_unary_symbolics_p (vr, code, expr_type, vr0))
+ return;
+
+ *vr = op->fold_range (expr_type,
+ vr0->normalize_addresses (),
+ value_range_base (expr_type));
}
/* Given a COND_EXPR COND of the form 'V OP W', and an SSA name V,
@@ -6000,7 +6020,24 @@ value_range::union_ (const value_range *other)
}
}
-/* Normalize symbolics into constants. */
+/* Normalize addresses into constants. */
+
+value_range_base
+value_range_base::normalize_addresses () const
+{
+ if (!POINTER_TYPE_P (type ()) || range_has_numeric_bounds_p (this))
+ return *this;
+
+ if (!range_includes_zero_p (this))
+ {
+ gcc_checking_assert (TREE_CODE (m_min) == ADDR_EXPR
+ || TREE_CODE (m_max) == ADDR_EXPR);
+ return range_nonzero (type ());
+ }
+ return value_range_base (type ());
+}
+
+/* Normalize symbolics and addresses into constants. */
value_range_base
value_range_base::normalize_symbolics () const
@@ -6011,7 +6048,7 @@ value_range_base::normalize_symbolics () const
bool min_symbolic = !is_gimple_min_invariant (min ());
bool max_symbolic = !is_gimple_min_invariant (max ());
if (!min_symbolic && !max_symbolic)
- return *this;
+ return normalize_addresses ();
// [SYM, SYM] -> VARYING
if (min_symbolic && max_symbolic)
diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h
index d20d0043ba3..a3f9e90699d 100644
--- a/gcc/tree-vrp.h
+++ b/gcc/tree-vrp.h
@@ -86,6 +86,7 @@ public:
static bool supports_type_p (tree);
value_range_base normalize_symbolics () const;
+ value_range_base normalize_addresses () const;
static const unsigned int m_max_pairs = 2;
bool contains_p (tree) const;
diff --git a/gcc/tree.c b/gcc/tree.c
index 59ea6b93454..e845fc7a00e 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -5963,8 +5963,9 @@ find_decls_types_r (tree *tp, int *ws, void *data)
{
for (tree *tem = &BLOCK_VARS (t); *tem; )
{
- if (TREE_CODE (*tem) != VAR_DECL
- || !auto_var_in_fn_p (*tem, DECL_CONTEXT (*tem)))
+ if (TREE_CODE (*tem) != LABEL_DECL
+ && (TREE_CODE (*tem) != VAR_DECL
+ || !auto_var_in_fn_p (*tem, DECL_CONTEXT (*tem))))
{
gcc_assert (TREE_CODE (*tem) != RESULT_DECL
&& TREE_CODE (*tem) != PARM_DECL);
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 3d069e41323..5de36ae2f47 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -4902,9 +4902,10 @@ dataflow_set_clear_at_call (dataflow_set *set, rtx_insn *call_insn)
unsigned int r;
hard_reg_set_iterator hrsi;
- function_abi callee_abi = insn_callee_abi (call_insn);
+ HARD_REG_SET callee_clobbers
+ = insn_callee_abi (call_insn).full_reg_clobbers ();
- EXECUTE_IF_SET_IN_HARD_REG_SET (callee_abi.full_reg_clobbers (), 0, r, hrsi)
+ EXECUTE_IF_SET_IN_HARD_REG_SET (callee_clobbers, 0, r, hrsi)
var_regno_delete (set, r);
if (MAY_HAVE_DEBUG_BIND_INSNS)
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 682caaccd96..f3237fbd38f 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,13 @@
+2019-10-04 Nathan Sidwell <nathan@acm.org>
+
+ PR preprocessor/91991
+ * line-map.c (linemap_line_start): Clear max_column_hint if we run
+ out of locations.
+
+2019-10-02 Richard Biener <rguenther@suse.de>
+
+ * internal.h (enum include_type): Remove trailing comma.
+
2019-10-02 Joseph Myers <joseph@codesourcery.com>
* include/cpplib.h (struct cpp_options): Add member scope.
diff --git a/libcpp/internal.h b/libcpp/internal.h
index 90263bde47d..cd1a523219e 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -126,7 +126,7 @@ enum include_type
IT_MAIN, /* main */
IT_DIRECTIVE_HWM = IT_IMPORT + 1, /* Directives below this. */
- IT_HEADER_HWM = IT_DEFAULT + 1, /* Header files below this. */
+ IT_HEADER_HWM = IT_DEFAULT + 1 /* Header files below this. */
};
union utoken
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index d6924eb3e78..feeb7480876 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -717,11 +717,11 @@ linemap_line_start (line_maps *set, linenum_type to_line,
/* If the column number is ridiculous or we've allocated a huge
number of location_ts, give up on column numbers
(and on packed ranges). */
- max_column_hint = 0;
+ max_column_hint = 1;
column_bits = 0;
range_bits = 0;
if (highest >= LINE_MAP_MAX_LOCATION)
- return 0;
+ goto overflowed;
}
else
{
@@ -735,6 +735,7 @@ linemap_line_start (line_maps *set, linenum_type to_line,
max_column_hint = 1U << column_bits;
column_bits += range_bits;
}
+
/* Allocate the new line_map. However, if the current map only has a
single line we can sometimes just increase its column_bits instead. */
if (line_delta < 0
@@ -765,8 +766,11 @@ linemap_line_start (line_maps *set, linenum_type to_line,
macro tokens. */
if (r >= LINE_MAP_MAX_LOCATION)
{
+ overflowed:
/* Remember we overflowed. */
set->highest_line = set->highest_location = LINE_MAP_MAX_LOCATION - 1;
+ /* No column numbers! */
+ set->max_column_hint = 1;
return 0;
}
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index f242fba2ec3..815118dbf83 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,7 @@
+2019-10-03 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/fptr.c: Disable -Warray-bounds warning.
+
2019-09-25 Richard Henderson <richard.henderson@linaro.org>
* config.in, configure: Re-rebuild with stock autoconf 2.69,
diff --git a/libgcc/config/pa/fptr.c b/libgcc/config/pa/fptr.c
index 53440051730..6cca747ece2 100644
--- a/libgcc/config/pa/fptr.c
+++ b/libgcc/config/pa/fptr.c
@@ -62,6 +62,9 @@ _dl_read_access_allowed (unsigned int *addr)
return result;
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+
/* __canonicalize_funcptr_for_compare must be hidden so that it is not
placed in the dynamic symbol table. Like millicode functions, it
must be linked into all binaries in order access the got table of
@@ -141,3 +144,5 @@ __canonicalize_funcptr_for_compare (fptr_t fptr)
return plabel[0];
}
+
+#pragma GCC diagnostic pop
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 3f69e567ef7..7736e5da937 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,9 @@
+2019-10-05 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/91926
+ * runtime/ISO_Fortran_binding.c (cfi_desc_to_gfc_desc): Do not
+ modify the bounds and offset for CFI_other.
+
2019-10-01 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libfortran/91593
@@ -14,7 +20,7 @@
formatted_transfer_scalar_read, formatted_transfer_scalar_write,
pre_position, next_record_r, next_record_w): Add and use
FORMATTED_UNSPECIFIED to enumeration.
-
+
2019-09-27 Maciej W. Rozycki <macro@wdc.com>
* configure: Regenerate.
diff --git a/libgfortran/runtime/ISO_Fortran_binding.c b/libgfortran/runtime/ISO_Fortran_binding.c
index 695ef57ac32..8cfcc98965e 100644
--- a/libgfortran/runtime/ISO_Fortran_binding.c
+++ b/libgfortran/runtime/ISO_Fortran_binding.c
@@ -63,7 +63,8 @@ cfi_desc_to_gfc_desc (gfc_array_void *d, CFI_cdesc_t **s_ptr)
d->dtype.version = s->version;
GFC_DESCRIPTOR_RANK (d) = (signed char)s->rank;
- d->dtype.attribute = (signed short)s->attribute;
+ if (d->dtype.attribute == CFI_attribute_other)
+ return;
if (s->rank)
{
diff --git a/libgo/runtime/go-context.S b/libgo/runtime/go-context.S
index 8beeebfb85a..170bced1818 100644
--- a/libgo/runtime/go-context.S
+++ b/libgo/runtime/go-context.S
@@ -66,4 +66,8 @@ __go_makecontext:
ret
+ .section .note.GNU-stack,"",@progbits
+ .section .note.GNU-split-stack,"",@progbits
+ .section .note.GNU-no-split-stack,"",@progbits
+
#endif
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index dbb95e424de..2059e053457 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,18 @@
+2019-10-02 Julian Brown <julian@codesourcery.com>
+ Cesar Philippidis <cesar@codesourcery.com>
+
+ * libgomp.h (OFFSET_INLINED, OFFSET_POINTER, OFFSET_STRUCT): Define.
+ * target.c (FIELD_TGT_EMPTY): Define.
+ (gomp_map_val): Use OFFSET_* macros instead of magic constants. Write
+ as switch instead of list of ifs.
+ (gomp_map_vars_internal): Use OFFSET_* and FIELD_TGT_EMPTY macros.
+
+2019-10-02 Andreas Tobler <andreast@gcc.gnu.org>
+
+ * testsuite/libgomp.oacc-c-c++-common/loop-default.h: Remove alloca.h
+ include. Replace alloca () with __builtin_alloca ().
+ * testsuite/libgomp.oacc-c-c++-common/loop-dim-default.c: Likewise.
+
2019-10-01 Jakub Jelinek <jakub@redhat.com>
* configure.ac: Remove GCC_HEADER_STDINT(gstdint.h).
diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h
index abb5c2263c4..178eb600ccd 100644
--- a/libgomp/libgomp.h
+++ b/libgomp/libgomp.h
@@ -903,6 +903,11 @@ struct target_mem_desc {
artificial pointer to "omp declare target link" object. */
#define REFCOUNT_LINK (~(uintptr_t) 1)
+/* Special offset values. */
+#define OFFSET_INLINED (~(uintptr_t) 0)
+#define OFFSET_POINTER (~(uintptr_t) 1)
+#define OFFSET_STRUCT (~(uintptr_t) 2)
+
struct splay_tree_key_s {
/* Address of the host object. */
uintptr_t host_start;
diff --git a/libgomp/target.c b/libgomp/target.c
index 1c9ca68ba10..a83cb48108a 100644
--- a/libgomp/target.c
+++ b/libgomp/target.c
@@ -44,6 +44,8 @@
#include "plugin-suffix.h"
#endif
+#define FIELD_TGT_EMPTY (~(size_t) 0)
+
static void gomp_target_init (void);
/* The whole initialization code for offloading plugins is only run one. */
@@ -497,17 +499,25 @@ gomp_map_val (struct target_mem_desc *tgt, void **hostaddrs, size_t i)
return tgt->list[i].key->tgt->tgt_start
+ tgt->list[i].key->tgt_offset
+ tgt->list[i].offset;
- if (tgt->list[i].offset == ~(uintptr_t) 0)
- return (uintptr_t) hostaddrs[i];
- if (tgt->list[i].offset == ~(uintptr_t) 1)
- return 0;
- if (tgt->list[i].offset == ~(uintptr_t) 2)
- return tgt->list[i + 1].key->tgt->tgt_start
- + tgt->list[i + 1].key->tgt_offset
- + tgt->list[i + 1].offset
- + (uintptr_t) hostaddrs[i]
- - (uintptr_t) hostaddrs[i + 1];
- return tgt->tgt_start + tgt->list[i].offset;
+
+ switch (tgt->list[i].offset)
+ {
+ case OFFSET_INLINED:
+ return (uintptr_t) hostaddrs[i];
+
+ case OFFSET_POINTER:
+ return 0;
+
+ case OFFSET_STRUCT:
+ return tgt->list[i + 1].key->tgt->tgt_start
+ + tgt->list[i + 1].key->tgt_offset
+ + tgt->list[i + 1].offset
+ + (uintptr_t) hostaddrs[i]
+ - (uintptr_t) hostaddrs[i + 1];
+
+ default:
+ return tgt->tgt_start + tgt->list[i].offset;
+ }
}
static inline __attribute__((always_inline)) struct target_mem_desc *
@@ -575,7 +585,7 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
|| (kind & typemask) == GOMP_MAP_FIRSTPRIVATE_INT)
{
tgt->list[i].key = NULL;
- tgt->list[i].offset = ~(uintptr_t) 0;
+ tgt->list[i].offset = OFFSET_INLINED;
continue;
}
else if ((kind & typemask) == GOMP_MAP_USE_DEVICE_PTR)
@@ -596,7 +606,7 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
cur_node.host_end = (uintptr_t) hostaddrs[last]
+ sizes[last];
tgt->list[i].key = NULL;
- tgt->list[i].offset = ~(uintptr_t) 2;
+ tgt->list[i].offset = OFFSET_STRUCT;
splay_tree_key n = splay_tree_lookup (mem_map, &cur_node);
if (n == NULL)
{
@@ -629,7 +639,7 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
else if ((kind & typemask) == GOMP_MAP_ALWAYS_POINTER)
{
tgt->list[i].key = NULL;
- tgt->list[i].offset = ~(uintptr_t) 1;
+ tgt->list[i].offset = OFFSET_POINTER;
has_firstprivate = true;
continue;
}
@@ -659,7 +669,7 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
if (!n)
{
tgt->list[i].key = NULL;
- tgt->list[i].offset = ~(uintptr_t) 1;
+ tgt->list[i].offset = OFFSET_POINTER;
continue;
}
}
@@ -884,12 +894,12 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
size_t align = (size_t) 1 << (kind >> rshift);
tgt->list[i].key = k;
k->tgt = tgt;
- if (field_tgt_clear != ~(size_t) 0)
+ if (field_tgt_clear != FIELD_TGT_EMPTY)
{
k->tgt_offset = k->host_start - field_tgt_base
+ field_tgt_offset;
if (i == field_tgt_clear)
- field_tgt_clear = ~(size_t) 0;
+ field_tgt_clear = FIELD_TGT_EMPTY;
}
else
{
diff --git a/libgomp/testsuite/libgomp.fortran/use_device_ptr-optional-1.f90 b/libgomp/testsuite/libgomp.fortran/use_device_ptr-optional-1.f90
new file mode 100644
index 00000000000..93c61216034
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/use_device_ptr-optional-1.f90
@@ -0,0 +1,36 @@
+! Test whether use_device_ptr properly handles OPTIONAL arguments
+! (Only case of present arguments is tested)
+program test_it
+ implicit none
+ integer, target :: ixx
+ integer, pointer :: ptr_i, ptr_null
+
+ ptr_i => ixx
+ call foo(ptr_i)
+
+ ptr_null => null()
+ call bar(ptr_null)
+contains
+ subroutine foo(ii)
+ integer, pointer, optional :: ii
+
+ if (.not.present(ii)) call abort()
+ if (.not.associated(ii, ixx)) call abort()
+ !$omp target data map(to:ixx) use_device_ptr(ii)
+ if (.not.present(ii)) call abort()
+ if (.not.associated(ii)) call abort()
+ !$omp end target data
+ end subroutine foo
+
+ ! For bar, it is assumed that a NULL ptr on the host maps to NULL on the device
+ subroutine bar(jj)
+ integer, pointer, optional :: jj
+
+ if (.not.present(jj)) call abort()
+ if (associated(jj)) call abort()
+ !$omp target data map(to:ixx) use_device_ptr(jj)
+ if (.not.present(jj)) call abort()
+ if (associated(jj)) call abort()
+ !$omp end target data
+ end subroutine bar
+end program test_it
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-default.h b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-default.h
index a9e26939cf2..8c71249687c 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-default.h
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-default.h
@@ -1,5 +1,4 @@
#include <openacc.h>
-#include <alloca.h>
#include <string.h>
#include <stdio.h>
#include <gomp-constants.h>
@@ -28,9 +27,9 @@ check (const int *ary, int size, int gp, int wp, int vp)
{
int exit = 0;
int ix;
- int *gangs = (int *)alloca (gp * sizeof (int));
- int *workers = (int *)alloca (wp * sizeof (int));
- int *vectors = (int *)alloca (vp * sizeof (int));
+ int *gangs = (int *)__builtin_alloca (gp * sizeof (int));
+ int *workers = (int *)__builtin_alloca (wp * sizeof (int));
+ int *vectors = (int *)__builtin_alloca (vp * sizeof (int));
int offloaded = 0;
memset (gangs, 0, gp * sizeof (int));
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-dim-default.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-dim-default.c
index dd8107c1acc..04387d36174 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-dim-default.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-dim-default.c
@@ -1,7 +1,6 @@
/* { dg-additional-options "-fopenacc-dim=16:16" } */
#include <openacc.h>
-#include <alloca.h>
#include <string.h>
#include <stdio.h>
#include <gomp-constants.h>
@@ -28,9 +27,9 @@ int check (const int *ary, int size, int gp, int wp, int vp)
{
int exit = 0;
int ix;
- int *gangs = (int *)alloca (gp * sizeof (int));
- int *workers = (int *)alloca (wp * sizeof (int));
- int *vectors = (int *)alloca (vp * sizeof (int));
+ int *gangs = (int *)__builtin_alloca (gp * sizeof (int));
+ int *workers = (int *)__builtin_alloca (wp * sizeof (int));
+ int *vectors = (int *)__builtin_alloca (vp * sizeof (int));
int offloaded = 0;
memset (gangs, 0, gp * sizeof (int));
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 712c4fe5549..97d9767c2ea 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,11 @@
+2019-10-03 Eduard-Mihai Burtescu <eddyb@lyken.rs>
+
+ * rust-demangle.c (looks_like_rust): Remove.
+ (rust_is_mangled): Don't check escapes.
+ (is_prefixed_hash): Allow 0-9a-f permutations.
+ (rust_demangle_sym): Don't bail on unknown escapes.
+ * testsuite/rust-demangle-expected: Update 'main::$99$' test.
+
2019-09-03 Eduard-Mihai Burtescu <eddyb@lyken.rs>
* rust-demangle.c (unescape): Remove.
diff --git a/libiberty/rust-demangle.c b/libiberty/rust-demangle.c
index da591902db1..6b62e6dbd80 100644
--- a/libiberty/rust-demangle.c
+++ b/libiberty/rust-demangle.c
@@ -85,7 +85,6 @@ static const size_t hash_prefix_len = 3;
static const size_t hash_len = 16;
static int is_prefixed_hash (const char *start);
-static int looks_like_rust (const char *sym, size_t len);
static int parse_lower_hex_nibble (char nibble);
static char parse_legacy_escape (const char **in);
@@ -105,16 +104,13 @@ static char parse_legacy_escape (const char **in);
negative (the rare Rust symbol is not demangled) so this sets
the balance in favor of false negatives.
- 3. There must be no characters other than a-zA-Z0-9 and _.:$
-
- 4. There must be no unrecognized $-sign sequences.
-
- 5. There must be no sequence of three or more dots in a row ("..."). */
+ 3. There must be no characters other than a-zA-Z0-9 and _.:$ */
int
rust_is_mangled (const char *sym)
{
size_t len, len_without_hash;
+ const char *end;
if (!sym)
return 0;
@@ -128,12 +124,22 @@ rust_is_mangled (const char *sym)
if (!is_prefixed_hash (sym + len_without_hash))
return 0;
- return looks_like_rust (sym, len_without_hash);
+ end = sym + len_without_hash;
+
+ while (sym < end)
+ {
+ if (*sym == '$' || *sym == '.' || *sym == '_' || *sym == ':'
+ || ISALNUM (*sym))
+ sym++;
+ else
+ return 0;
+ }
+
+ return 1;
}
/* A hash is the prefix "::h" followed by 16 lowercase hex digits. The
- hex digits must comprise between 5 and 15 (inclusive) distinct
- digits. */
+ hex digits must contain at least 5 distinct digits. */
static int
is_prefixed_hash (const char *str)
@@ -162,28 +168,7 @@ is_prefixed_hash (const char *str)
if (seen[i])
count++;
- return count >= 5 && count <= 15;
-}
-
-static int
-looks_like_rust (const char *str, size_t len)
-{
- const char *end = str + len;
-
- while (str < end)
- {
- if (*str == '$')
- {
- if (!parse_legacy_escape (&str))
- return 0;
- }
- else if (*str == '.' || *str == '_' || *str == ':' || ISALNUM (*str))
- str++;
- else
- return 0;
- }
-
- return 1;
+ return count >= 5;
}
/*
@@ -215,8 +200,9 @@ rust_demangle_sym (char *sym)
if (unescaped)
*out++ = unescaped;
else
- /* unexpected escape sequence, not looks_like_rust. */
- goto fail;
+ /* unexpected escape sequence, skip the rest of this segment. */
+ while (in < end && *in != ':')
+ *out++ = *in++;
}
else if (*in == '_')
{
@@ -248,14 +234,14 @@ rust_demangle_sym (char *sym)
else if (*in == ':' || ISALNUM (*in))
*out++ = *in++;
else
- /* unexpected character in symbol, not looks_like_rust. */
- goto fail;
+ {
+ /* unexpected character in symbol, not rust_is_mangled. */
+ *out++ = '?'; /* This is pretty lame, but it's hard to do better. */
+ *out = '\0';
+ return;
+ }
}
- goto done;
-fail:
- *out++ = '?'; /* This is pretty lame, but it's hard to do better. */
-done:
*out = '\0';
}
diff --git a/libiberty/testsuite/rust-demangle-expected b/libiberty/testsuite/rust-demangle-expected
index c3b03f9f02d..74774794736 100644
--- a/libiberty/testsuite/rust-demangle-expected
+++ b/libiberty/testsuite/rust-demangle-expected
@@ -41,7 +41,7 @@ main::main::he714a2e23ed7db2g
# $XX$ substitutions should not contain just numbers.
--format=auto
_ZN4main4$99$17he714a2e23ed7db23E
-main::$99$::he714a2e23ed7db23
+main::$99$
# _ at start of path should be removed.
# ".." translates to "::" "$GT$" to ">" and "$LT$" to "<".
--format=rust
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 9cf1c9a52c4..e0d3fd5f3a9 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,86 @@
+2019-10-06 François Dumont <fdumont@gcc.gnu.org>
+
+ * include/bits/stl_algo.h
+ (__copy_n_a(_IIte, _Size, _OIte)): New.
+ (__copy_n_a(istreambuf_iterator<>, _Size, _CharT*)): New declaration.
+ (__copy_n(_IIte, _Size, _OIte, input_iterator_tag)): Adapt to use
+ latter.
+ * include/bits/streambuf_iterator.h (istreambuf_iterator<>): Declare
+ std::__copy_n_a friend.
+ (__copy_n_a(istreambuf_iterator<>, _Size, _CharT*)): New.
+ * testsuite/25_algorithms/copy_n/istreambuf_iterator/1.cc: New.
+ * testsuite/25_algorithms/copy_n/istreambuf_iterator/1_neg.cc: New.
+ * testsuite/25_algorithms/copy_n/istreambuf_iterator/2_neg.cc: New.
+
+ * include/bits/stl_iterator_base_types.h (__iterator_category_t): Define
+ for C++11.
+ (_RequireInputIte): Likewise and use __enable_if_t.
+ * include/std/numeric
+ (__is_random_access_iter): Use __iterator_category_t.
+
+ * include/bits/stl_algo.h (copy_n): Add __glibcxx_requires_can_increment
+ debug checks.
+ * testsuite/25_algorithms/copy_n/debug/1_neg.cc: New.
+ * testsuite/25_algorithms/copy_n/debug/2_neg.cc: New.
+
+2019-10-04 François Dumont <fdumont@gcc.gnu.org>
+
+ * include/debug/forward_list
+ (_Sequence_traits<__debug::forward_list<>>::_S_size): Returns __dp_sign
+ distance when not empty.
+ * include/debug/list (_Sequence_traits<__debug::list<>>::_S_size):
+ Likewise.
+ * include/debug/helper_functions.h (__dp_sign_max_size): New
+ _Distance_precision enum entry.
+ (__valid_range_aux(_IIte, _IIte, _Distance_traits<>::__type,
+ __false_type)): Adapt.
+ * include/debug/safe_iterator.tcc
+ (_Safe_iterator<>::_M_get_distance_to(const _Safe_iterator&)): Review
+ distance computation.
+
+2019-10-04 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/81091
+ PR libstdc++/91947
+ * configure.ac: Use AC_SYS_LARGEFILE to enable 64-bit file APIs.
+ * config.h.in: Regenerate:
+ * configure: Regenerate:
+ * include/Makefile.am (${host_builddir}/largefile-config.h): New
+ target to generate config header for filesystem library.
+ (${host_builddir}/c++config.h): Rename macros for large file support.
+ * include/Makefile.in: Regenerate.
+ * src/c++17/fs_dir.cc: Include new config header.
+ * src/c++17/fs_ops.cc: Likewise.
+ (filesystem::file_size): Use uintmax_t for size.
+ * src/filesystem/dir.cc: Include new config header.
+ * src/filesystem/ops.cc: Likewise.
+ (experimental::filesystem::file_size): Use uintmax_t for size.
+
+ * testsuite/util/testsuite_abi.h: Use std::unordered_map instead of
+ std::tr1::unordered_map.
+ * testsuite/util/testsuite_allocator.h: Likewise.
+
+ * include/tr1/hashtable.h: Add header for __gnu_cxx::__alloc_traits.
+
+ * include/tr1/hashtable.h (tr1::_Hashtable::_M_allocate_node): Use
+ __gnu_cxx::__alloc_traits for allocator construct function.
+ (tr1::_Hashtable::_M_deallocate_node): Likewise for destroy function.
+
+ * include/precompiled/stdc++.h: Include <span> for C++20.
+ * testsuite/17_intro/names.cc: Do not define 'e' for C++20.
+
+2019-10-03 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * include/parallel/multiway_merge.h (_RAIter3): Replace _C by _Cp.
+
+2019-10-02 Jonathan Wakely <jwakely@redhat.com>
+
+ * config/abi/pre/gnu.ver: Tighten up greedy wildcards.
+
+ * doc/xml/manual/parallel_mode.xml: Add caveat about support for
+ recent standards.
+ * doc/html/*: Regenerate.
+
2019-10-01 Jonathan Wakely <jwakely@redhat.com>
* include/experimental/algorithm (experimental::sample): Qualify call
diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
index 3d13402f923..32f7863a85e 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -803,6 +803,14 @@
/* Version number of package */
#undef VERSION
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
/* Define if C99 functions in <complex.h> should be used in <complex> for
C++11. Using compiler builtins for these functions requires corresponding
C99 library functions to be present. */
@@ -1047,6 +1055,9 @@
/* Define to 1 if mutex_timedlock is available. */
#undef _GTHREAD_USE_MUTEX_TIMEDLOCK
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
/* Define if all C++11 floating point overloads are available in <math.h>. */
#if __cplusplus >= 201103L
#undef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 07a00036827..e61fbe0ad66 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -80,9 +80,8 @@ GLIBCXX_3.4 {
# std::domain_error::d*;
# std::domain_error::~d*;
std::d[p-z]*;
- std::e[a-q]*;
std::error[^_]*;
- std::e[s-z]*;
+ std::exception::*;
std::gslice*;
std::h[^a]*;
std::i[a-m]*;
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index e646c412f98..cb67581206d 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -895,6 +895,7 @@ ac_user_opts='
enable_option_checking
enable_multilib
enable_silent_rules
+enable_largefile
with_target_subdir
with_cross_host
with_newlib
@@ -1579,6 +1580,7 @@ Optional Features:
--enable-multilib build many library versions (default)
--enable-silent-rules less verbose build output (undo: "make V=1")
--disable-silent-rules verbose build output (undo: "make V=0")
+ --disable-largefile omit support for large files
--enable-maintainer-mode
enable make rules and dependencies not useful (and
sometimes confusing) to the casual installer
@@ -4928,9 +4930,210 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
CXXFLAGS="$save_CXXFLAGS"
+
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+ enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
+if ${ac_cv_sys_largefile_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_sys_largefile_CC=no
+ if test "$GCC" != yes; then
+ ac_save_CC=$CC
+ while :; do
+ # IRIX 6.2 and later do not support large files by default,
+ # so use the C compiler's -n32 option if that helps.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ if ac_fn_c_try_compile "$LINENO"; then :
+ break
+fi
+rm -f core conftest.err conftest.$ac_objext
+ CC="$CC -n32"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_largefile_CC=' -n32'; break
+fi
+rm -f core conftest.err conftest.$ac_objext
+ break
+ done
+ CC=$ac_save_CC
+ rm -f conftest.$ac_ext
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+$as_echo "$ac_cv_sys_largefile_CC" >&6; }
+ if test "$ac_cv_sys_largefile_CC" != no; then
+ CC=$CC$ac_cv_sys_largefile_CC
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if ${ac_cv_sys_file_offset_bits+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_file_offset_bits=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_file_offset_bits=64; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_sys_file_offset_bits=unknown
+ break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -rf conftest*
+ if test $ac_cv_sys_file_offset_bits = unknown; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
+if ${ac_cv_sys_large_files+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_large_files=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_sys_large_files=unknown
+ break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+$as_echo "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -rf conftest*
+ fi
+
+
+fi
+
+
# Runs configure.host, and assorted other critical bits. Sets
# up critical shell variables.
-
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -11850,7 +12053,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11853 "configure"
+#line 12056 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11956,7 +12159,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11959 "configure"
+#line 12162 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -15648,7 +15851,7 @@ $as_echo "$glibcxx_cv_atomic_long_long" >&6; }
# Fake what AC_TRY_COMPILE does.
cat > conftest.$ac_ext << EOF
-#line 15651 "configure"
+#line 15854 "configure"
int main()
{
typedef bool atomic_type;
@@ -15683,7 +15886,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15686 "configure"
+#line 15889 "configure"
int main()
{
typedef short atomic_type;
@@ -15718,7 +15921,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15721 "configure"
+#line 15924 "configure"
int main()
{
// NB: _Atomic_word not necessarily int.
@@ -15754,7 +15957,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15757 "configure"
+#line 15960 "configure"
int main()
{
typedef long long atomic_type;
@@ -15907,7 +16110,7 @@ $as_echo "mutex" >&6; }
# unnecessary for this test.
cat > conftest.$ac_ext << EOF
-#line 15910 "configure"
+#line 16113 "configure"
int main()
{
_Decimal32 d1;
@@ -15949,7 +16152,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
# unnecessary for this test.
cat > conftest.$ac_ext << EOF
-#line 15952 "configure"
+#line 16155 "configure"
template<typename T1, typename T2>
struct same
{ typedef T2 type; };
@@ -15983,7 +16186,7 @@ $as_echo "$enable_int128" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15986 "configure"
+#line 16189 "configure"
template<typename T1, typename T2>
struct same
{ typedef T2 type; };
diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
index ad4ae0c3b7d..154819acefe 100644
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -83,6 +83,8 @@ AC_PROG_CC
AC_PROG_CXX
CXXFLAGS="$save_CXXFLAGS"
+AC_SYS_LARGEFILE
+
# Runs configure.host, and assorted other critical bits. Sets
# up critical shell variables.
GLIBCXX_CONFIGURE
diff --git a/libstdc++-v3/doc/html/manual/parallel_mode.html b/libstdc++-v3/doc/html/manual/parallel_mode.html
index db64389b5b1..7ffa8bb606b 100644
--- a/libstdc++-v3/doc/html/manual/parallel_mode.html
+++ b/libstdc++-v3/doc/html/manual/parallel_mode.html
@@ -3,20 +3,30 @@
Extensions
</th><td width="20%" align="right"> <a accesskey="n" href="parallel_mode_semantics.html">Next</a></td></tr></table><hr /></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a id="manual.ext.parallel_mode"></a>Chapter 18. Parallel Mode</h2></div></div></div><div class="toc"><p><strong>Table of Contents</strong></p><dl class="toc"><dt><span class="section"><a href="parallel_mode.html#manual.ext.parallel_mode.intro">Intro</a></span></dt><dt><span class="section"><a href="parallel_mode_semantics.html">Semantics</a></span></dt><dt><span class="section"><a href="parallel_mode_using.html">Using</a></span></dt><dd><dl><dt><span class="section"><a href="parallel_mode_using.html#parallel_mode.using.prereq_flags">Prerequisite Compiler Flags</a></span></dt><dt><span class="section"><a href="parallel_mode_using.html#parallel_mode.using.parallel_mode">Using Parallel Mode</a></span></dt><dt><span class="section"><a href="parallel_mode_using.html#parallel_mode.using.specific">Using Specific Parallel Components</a></span></dt></dl></dd><dt><span class="section"><a href="parallel_mode_design.html">Design</a></span></dt><dd><dl><dt><span class="section"><a href="parallel_mode_design.html#parallel_mode.design.intro">Interface Basics</a></span></dt><dt><span class="section"><a href="parallel_mode_design.html#parallel_mode.design.tuning">Configuration and Tuning</a></span></dt><dd><dl><dt><span class="section"><a href="parallel_mode_design.html#parallel_mode.design.tuning.omp">Setting up the OpenMP Environment</a></span></dt><dt><span class="section"><a href="parallel_mode_design.html#parallel_mode.design.tuning.compile">Compile Time Switches</a></span></dt><dt><span class="section"><a href="parallel_mode_design.html#parallel_mode.design.tuning.settings">Run Time Settings and Defaults</a></span></dt></dl></dd><dt><span class="section"><a href="parallel_mode_design.html#parallel_mode.design.impl">Implementation Namespaces</a></span></dt></dl></dd><dt><span class="section"><a href="parallel_mode_test.html">Testing</a></span></dt><dt><span class="bibliography"><a href="parallel_mode.html#parallel_mode.biblio">Bibliography</a></span></dt></dl></div><p> The libstdc++ parallel mode is an experimental parallel
-implementation of many algorithms the C++ Standard Library.
+implementation of many algorithms of the C++ Standard Library.
</p><p>
Several of the standard algorithms, for instance
<code class="function">std::sort</code>, are made parallel using OpenMP
-annotations. These parallel mode constructs and can be invoked by
+annotations. These parallel mode constructs can be invoked by
explicit source declaration or by compiling existing sources with a
specific compiler flag.
-</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="manual.ext.parallel_mode.intro"></a>Intro</h2></div></div></div><p>The following library components in the include
+</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
+ The parallel mode has not been kept up to date with recent C++ standards
+ and so it only conforms to the C++03 requirements.
+ That means that move-only predicates may not work with parallel mode
+ algorithms, and for C++20 most of the algorithms cannot be used in
+ <code class="code">constexpr</code> functions.
+ </p><p>
+ For C++17 and above there are new overloads of the standard algorithms
+ which take an execution policy argument. You should consider using those
+ instead of the non-standard parallel mode extensions.
+ </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="manual.ext.parallel_mode.intro"></a>Intro</h2></div></div></div><p>The following library components in the include
<code class="filename">numeric</code> are included in the parallel mode:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p><code class="function">std::accumulate</code></p></li><li class="listitem"><p><code class="function">std::adjacent_difference</code></p></li><li class="listitem"><p><code class="function">std::inner_product</code></p></li><li class="listitem"><p><code class="function">std::partial_sum</code></p></li></ul></div><p>The following library components in the include
-<code class="filename">algorithm</code> are included in the parallel mode:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p><code class="function">std::adjacent_find</code></p></li><li class="listitem"><p><code class="function">std::count</code></p></li><li class="listitem"><p><code class="function">std::count_if</code></p></li><li class="listitem"><p><code class="function">std::equal</code></p></li><li class="listitem"><p><code class="function">std::find</code></p></li><li class="listitem"><p><code class="function">std::find_if</code></p></li><li class="listitem"><p><code class="function">std::find_first_of</code></p></li><li class="listitem"><p><code class="function">std::for_each</code></p></li><li class="listitem"><p><code class="function">std::generate</code></p></li><li class="listitem"><p><code class="function">std::generate_n</code></p></li><li class="listitem"><p><code class="function">std::lexicographical_compare</code></p></li><li class="listitem"><p><code class="function">std::mismatch</code></p></li><li class="listitem"><p><code class="function">std::search</code></p></li><li class="listitem"><p><code class="function">std::search_n</code></p></li><li class="listitem"><p><code class="function">std::transform</code></p></li><li class="listitem"><p><code class="function">std::replace</code></p></li><li class="listitem"><p><code class="function">std::replace_if</code></p></li><li class="listitem"><p><code class="function">std::max_element</code></p></li><li class="listitem"><p><code class="function">std::merge</code></p></li><li class="listitem"><p><code class="function">std::min_element</code></p></li><li class="listitem"><p><code class="function">std::nth_element</code></p></li><li class="listitem"><p><code class="function">std::partial_sort</code></p></li><li class="listitem"><p><code class="function">std::partition</code></p></li><li class="listitem"><p><code class="function">std::random_shuffle</code></p></li><li class="listitem"><p><code class="function">std::set_union</code></p></li><li class="listitem"><p><code class="function">std::set_intersection</code></p></li><li class="listitem"><p><code class="function">std::set_symmetric_difference</code></p></li><li class="listitem"><p><code class="function">std::set_difference</code></p></li><li class="listitem"><p><code class="function">std::sort</code></p></li><li class="listitem"><p><code class="function">std::stable_sort</code></p></li><li class="listitem"><p><code class="function">std::unique_copy</code></p></li></ul></div></div><div class="bibliography"><div class="titlepage"><div><div><h2 class="title"><a id="parallel_mode.biblio"></a>Bibliography</h2></div></div></div><div class="biblioentry"><a id="id-1.3.5.5.9.2"></a><p><span class="citetitle"><em class="citetitle">
+<code class="filename">algorithm</code> are included in the parallel mode:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p><code class="function">std::adjacent_find</code></p></li><li class="listitem"><p><code class="function">std::count</code></p></li><li class="listitem"><p><code class="function">std::count_if</code></p></li><li class="listitem"><p><code class="function">std::equal</code></p></li><li class="listitem"><p><code class="function">std::find</code></p></li><li class="listitem"><p><code class="function">std::find_if</code></p></li><li class="listitem"><p><code class="function">std::find_first_of</code></p></li><li class="listitem"><p><code class="function">std::for_each</code></p></li><li class="listitem"><p><code class="function">std::generate</code></p></li><li class="listitem"><p><code class="function">std::generate_n</code></p></li><li class="listitem"><p><code class="function">std::lexicographical_compare</code></p></li><li class="listitem"><p><code class="function">std::mismatch</code></p></li><li class="listitem"><p><code class="function">std::search</code></p></li><li class="listitem"><p><code class="function">std::search_n</code></p></li><li class="listitem"><p><code class="function">std::transform</code></p></li><li class="listitem"><p><code class="function">std::replace</code></p></li><li class="listitem"><p><code class="function">std::replace_if</code></p></li><li class="listitem"><p><code class="function">std::max_element</code></p></li><li class="listitem"><p><code class="function">std::merge</code></p></li><li class="listitem"><p><code class="function">std::min_element</code></p></li><li class="listitem"><p><code class="function">std::nth_element</code></p></li><li class="listitem"><p><code class="function">std::partial_sort</code></p></li><li class="listitem"><p><code class="function">std::partition</code></p></li><li class="listitem"><p><code class="function">std::random_shuffle</code></p></li><li class="listitem"><p><code class="function">std::set_union</code></p></li><li class="listitem"><p><code class="function">std::set_intersection</code></p></li><li class="listitem"><p><code class="function">std::set_symmetric_difference</code></p></li><li class="listitem"><p><code class="function">std::set_difference</code></p></li><li class="listitem"><p><code class="function">std::sort</code></p></li><li class="listitem"><p><code class="function">std::stable_sort</code></p></li><li class="listitem"><p><code class="function">std::unique_copy</code></p></li></ul></div></div><div class="bibliography"><div class="titlepage"><div><div><h2 class="title"><a id="parallel_mode.biblio"></a>Bibliography</h2></div></div></div><div class="biblioentry"><a id="id-1.3.5.5.10.2"></a><p><span class="citetitle"><em class="citetitle">
Parallelization of Bulk Operations for STL Dictionaries
</em>. </span><span class="author"><span class="firstname">Johannes</span> <span class="surname">Singler</span>. </span><span class="author"><span class="firstname">Leonor</span> <span class="surname">Frias</span>. </span><span class="copyright">Copyright © 2007 . </span><span class="publisher"><span class="publishername">
Workshop on Highly Parallel Processing on a Chip (HPPC) 2007. (LNCS)
- . </span></span></p></div><div class="biblioentry"><a id="id-1.3.5.5.9.3"></a><p><span class="citetitle"><em class="citetitle">
+ . </span></span></p></div><div class="biblioentry"><a id="id-1.3.5.5.10.3"></a><p><span class="citetitle"><em class="citetitle">
The Multi-Core Standard Template Library
</em>. </span><span class="author"><span class="firstname">Johannes</span> <span class="surname">Singler</span>. </span><span class="author"><span class="firstname">Peter</span> <span class="surname">Sanders</span>. </span><span class="author"><span class="firstname">Felix</span> <span class="surname">Putze</span>. </span><span class="copyright">Copyright © 2007 . </span><span class="publisher"><span class="publishername">
Euro-Par 2007: Parallel Processing. (LNCS 4641)
diff --git a/libstdc++-v3/doc/xml/manual/parallel_mode.xml b/libstdc++-v3/doc/xml/manual/parallel_mode.xml
index 60e2088b2a1..ab7d2f2b56b 100644
--- a/libstdc++-v3/doc/xml/manual/parallel_mode.xml
+++ b/libstdc++-v3/doc/xml/manual/parallel_mode.xml
@@ -13,17 +13,31 @@
<para> The libstdc++ parallel mode is an experimental parallel
-implementation of many algorithms the C++ Standard Library.
+implementation of many algorithms of the C++ Standard Library.
</para>
<para>
Several of the standard algorithms, for instance
<function>std::sort</function>, are made parallel using OpenMP
-annotations. These parallel mode constructs and can be invoked by
+annotations. These parallel mode constructs can be invoked by
explicit source declaration or by compiling existing sources with a
specific compiler flag.
</para>
+<note>
+ <para>
+ The parallel mode has not been kept up to date with recent C++ standards
+ and so it only conforms to the C++03 requirements.
+ That means that move-only predicates may not work with parallel mode
+ algorithms, and for C++20 most of the algorithms cannot be used in
+ <code>constexpr</code> functions.
+ </para>
+ <para>
+ For C++17 and above there are new overloads of the standard algorithms
+ which take an execution policy argument. You should consider using those
+ instead of the non-standard parallel mode extensions.
+ </para>
+</note>
<section xml:id="manual.ext.parallel_mode.intro" xreflabel="Intro"><info><title>Intro</title></info>
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index b8b786d9260..3e9540ca047 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -1014,6 +1014,7 @@ allstamped = \
# catenation.
allcreated = \
${host_builddir}/c++config.h \
+ ${host_builddir}/largefile-config.h \
${thread_host_headers} \
${pch_build}
@@ -1237,10 +1238,29 @@ stamp-float128:
echo 'undef _GLIBCXX_USE_FLOAT128' > stamp-float128
endif
+# This header is not installed, it's only used to build libstdc++ itself.
+${host_builddir}/largefile-config.h: ${CONFIG_HEADER} \
+ ${glibcxx_srcdir}/include/bits/c++config
+ @echo '#if defined _GLIBCXX_CXX_CONFIG_H || defined _FEATURES_H' > $@
+ @echo '# error "This file must be included before any others"' >> $@
+ @echo '#endif' >> $@
+ @echo >> $@
+ @echo '/* Enable large inode numbers on Mac OS X 10.5. */' >> $@
+ @echo '#ifndef _DARWIN_USE_64_BIT_INODE' >> $@
+ @echo '# define _DARWIN_USE_64_BIT_INODE 1' >> $@
+ @echo '#endif' >> $@
+ @echo >> $@
+ @echo '/* Number of bits in a file offset, on hosts where this is settable. */' >> $@
+ @grep '_FILE_OFFSET_BITS' ${CONFIG_HEADER} >> $@
+ @echo >> $@
+ @echo '/* Define for large files, on AIX-style hosts. */' >> $@
+ @grep '_LARGE_FILES' ${CONFIG_HEADER} >> $@
+
# NB: The non-empty default ldbl_compat works around an AIX sed
# oddity, see libstdc++/31957 for details.
${host_builddir}/c++config.h: ${CONFIG_HEADER} \
${glibcxx_srcdir}/include/bits/c++config \
+ ${host_builddir}/largefile-config.h \
stamp-${host_alias} \
${toplevel_srcdir}/gcc/DATESTAMP \
stamp-namespace-version \
@@ -1278,6 +1298,9 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
-e 's/PACKAGE/_GLIBCXX_PACKAGE/g' \
-e 's/VERSION/_GLIBCXX_VERSION/g' \
-e 's/WORDS_/_GLIBCXX_WORDS_/g' \
+ -e 's/_DARWIN_USE_64_BIT_INODE/_GLIBCXX_DARWIN_USE_64_BIT_INODE/g' \
+ -e 's/_FILE_OFFSET_BITS/_GLIBCXX_FILE_OFFSET_BITS/g' \
+ -e 's/_LARGE_FILES/_GLIBCXX_LARGE_FILES/g' \
-e 's/ICONV_CONST/_GLIBCXX_ICONV_CONST/g' \
-e '/[ ]_GLIBCXX_LONG_DOUBLE_COMPAT[ ]/d' \
< ${CONFIG_HEADER} >> $@ ;\
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index cd1e9df5482..24e1363951c 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -1346,6 +1346,7 @@ allstamped = \
# catenation.
allcreated = \
${host_builddir}/c++config.h \
+ ${host_builddir}/largefile-config.h \
${thread_host_headers} \
${pch_build}
@@ -1717,10 +1718,29 @@ stamp-host: ${host_headers} ${bits_host_headers} ${ext_host_headers} ${host_head
@ENABLE_FLOAT128_FALSE@stamp-float128:
@ENABLE_FLOAT128_FALSE@ echo 'undef _GLIBCXX_USE_FLOAT128' > stamp-float128
+# This header is not installed, it's only used to build libstdc++ itself.
+${host_builddir}/largefile-config.h: ${CONFIG_HEADER} \
+ ${glibcxx_srcdir}/include/bits/c++config
+ @echo '#if defined _GLIBCXX_CXX_CONFIG_H || defined _FEATURES_H' > $@
+ @echo '# error "This file must be included before any others"' >> $@
+ @echo '#endif' >> $@
+ @echo >> $@
+ @echo '/* Enable large inode numbers on Mac OS X 10.5. */' >> $@
+ @echo '#ifndef _DARWIN_USE_64_BIT_INODE' >> $@
+ @echo '# define _DARWIN_USE_64_BIT_INODE 1' >> $@
+ @echo '#endif' >> $@
+ @echo >> $@
+ @echo '/* Number of bits in a file offset, on hosts where this is settable. */' >> $@
+ @grep '_FILE_OFFSET_BITS' ${CONFIG_HEADER} >> $@
+ @echo >> $@
+ @echo '/* Define for large files, on AIX-style hosts. */' >> $@
+ @grep '_LARGE_FILES' ${CONFIG_HEADER} >> $@
+
# NB: The non-empty default ldbl_compat works around an AIX sed
# oddity, see libstdc++/31957 for details.
${host_builddir}/c++config.h: ${CONFIG_HEADER} \
${glibcxx_srcdir}/include/bits/c++config \
+ ${host_builddir}/largefile-config.h \
stamp-${host_alias} \
${toplevel_srcdir}/gcc/DATESTAMP \
stamp-namespace-version \
@@ -1758,6 +1778,9 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
-e 's/PACKAGE/_GLIBCXX_PACKAGE/g' \
-e 's/VERSION/_GLIBCXX_VERSION/g' \
-e 's/WORDS_/_GLIBCXX_WORDS_/g' \
+ -e 's/_DARWIN_USE_64_BIT_INODE/_GLIBCXX_DARWIN_USE_64_BIT_INODE/g' \
+ -e 's/_FILE_OFFSET_BITS/_GLIBCXX_FILE_OFFSET_BITS/g' \
+ -e 's/_LARGE_FILES/_GLIBCXX_LARGE_FILES/g' \
-e 's/ICONV_CONST/_GLIBCXX_ICONV_CONST/g' \
-e '/[ ]_GLIBCXX_LONG_DOUBLE_COMPAT[ ]/d' \
< ${CONFIG_HEADER} >> $@ ;\
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index b326c6305d8..661db0264ea 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -778,8 +778,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _InputIterator, typename _Size, typename _OutputIterator>
_GLIBCXX20_CONSTEXPR
_OutputIterator
- __copy_n(_InputIterator __first, _Size __n,
- _OutputIterator __result, input_iterator_tag)
+ __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result)
{
if (__n > 0)
{
@@ -795,6 +794,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
return __result;
}
+
+ template<typename _CharT, typename _Size>
+ __enable_if_t<__is_char<_CharT>::__value, _CharT*>
+ __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT>>,
+ _Size, _CharT*);
+
+ template<typename _InputIterator, typename _Size, typename _OutputIterator>
+ _GLIBCXX20_CONSTEXPR
+ _OutputIterator
+ __copy_n(_InputIterator __first, _Size __n,
+ _OutputIterator __result, input_iterator_tag)
+ {
+ return std::__niter_wrap(__result,
+ __copy_n_a(__first, __n,
+ std::__niter_base(__result)));
+ }
template<typename _RandomAccessIterator, typename _Size,
typename _OutputIterator>
@@ -826,6 +841,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
typename iterator_traits<_InputIterator>::value_type>)
+ __glibcxx_requires_can_increment(__first, __n);
+ __glibcxx_requires_can_increment(__result, __n);
return std::__copy_n(__first, __n, __result,
std::__iterator_category(__first));
@@ -878,7 +895,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return pair<_OutputIterator1, _OutputIterator2>(__out_true, __out_false);
}
-#endif
+#endif // C++11
template<typename _ForwardIterator, typename _Predicate>
_GLIBCXX20_CONSTEXPR
diff --git a/libstdc++-v3/include/bits/stl_iterator_base_types.h b/libstdc++-v3/include/bits/stl_iterator_base_types.h
index af69dbb017a..951e704e468 100644
--- a/libstdc++-v3/include/bits/stl_iterator_base_types.h
+++ b/libstdc++-v3/include/bits/stl_iterator_base_types.h
@@ -208,11 +208,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
//@}
#if __cplusplus >= 201103L
+ template<typename _Iter>
+ using __iterator_category_t
+ = typename iterator_traits<_Iter>::iterator_category;
+
template<typename _InIter>
- using _RequireInputIter = typename
- enable_if<is_convertible<typename
- iterator_traits<_InIter>::iterator_category,
- input_iterator_tag>::value>::type;
+ using _RequireInputIter =
+ __enable_if_t<is_convertible<__iterator_category_t<_InIter>,
+ input_iterator_tag>::value>;
#endif
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h
index 2f4ff494a3a..e3e8736e768 100644
--- a/libstdc++-v3/include/bits/streambuf_iterator.h
+++ b/libstdc++-v3/include/bits/streambuf_iterator.h
@@ -80,6 +80,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__copy_move_a2(istreambuf_iterator<_CharT2>,
istreambuf_iterator<_CharT2>, _CharT2*);
+#if __cplusplus >= 201103L
+ template<typename _CharT2, typename _Size>
+ friend __enable_if_t<__is_char<_CharT2>::__value, _CharT2*>
+ __copy_n_a(istreambuf_iterator<_CharT2>, _Size, _CharT2*);
+#endif
+
template<typename _CharT2>
friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
istreambuf_iterator<_CharT2> >::__type
@@ -367,6 +373,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __result;
}
+#if __cplusplus >= 201103L
+ template<typename _CharT, typename _Size>
+ __enable_if_t<__is_char<_CharT>::__value, _CharT*>
+ __copy_n_a(istreambuf_iterator<_CharT> __it, _Size __n, _CharT* __result)
+ {
+ if (__n == 0)
+ return __result;
+
+ __glibcxx_requires_cond(__it._M_sbuf,
+ _M_message(__gnu_debug::__msg_inc_istreambuf)
+ ._M_iterator(__it));
+ _CharT* __beg = __result;
+ __result += __it._M_sbuf->sgetn(__beg, __n);
+ __glibcxx_requires_cond(__result - __beg == __n,
+ _M_message(__gnu_debug::__msg_inc_istreambuf)
+ ._M_iterator(__it));
+ return __result;
+ }
+#endif // C++11
+
template<typename _CharT>
typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
istreambuf_iterator<_CharT> >::__type
diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list
index e30b000009e..f1756ddec9d 100644
--- a/libstdc++-v3/include/debug/forward_list
+++ b/libstdc++-v3/include/debug/forward_list
@@ -911,7 +911,7 @@ namespace __gnu_debug
_S_size(const std::__debug::forward_list<_Tp, _Alloc>& __seq)
{
return __seq.empty()
- ? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_equality);
+ ? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_sign);
}
};
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index 475fdda1d7b..5a920bb9a6f 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -50,10 +50,11 @@ namespace __gnu_debug
*/
enum _Distance_precision
{
- __dp_none, // Not even an iterator type
- __dp_equality, //< Can compare iterator equality, only
- __dp_sign, //< Can determine equality and ordering
- __dp_exact //< Can determine distance precisely
+ __dp_none, // Not even an iterator type
+ __dp_equality, //< Can compare iterator equality, only
+ __dp_sign, //< Can determine equality and ordering
+ __dp_sign_max_size, //< __dp_sign and gives max range size
+ __dp_exact //< Can determine distance precisely
};
template<typename _Iterator,
@@ -176,6 +177,7 @@ namespace __gnu_debug
return true;
break;
case __dp_sign:
+ case __dp_sign_max_size:
case __dp_exact:
return __dist.first >= 0;
}
diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list
index 5eb9a6094e3..140546a633e 100644
--- a/libstdc++-v3/include/debug/list
+++ b/libstdc++-v3/include/debug/list
@@ -916,7 +916,7 @@ namespace __gnu_debug
_S_size(const std::__debug::list<_Tp, _Alloc>& __seq)
{
return __seq.empty()
- ? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_equality);
+ ? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_sign);
}
};
#endif
diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc b/libstdc++-v3/include/debug/safe_iterator.tcc
index 581c51c9607..1750bc473d2 100644
--- a/libstdc++-v3/include/debug/safe_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_iterator.tcc
@@ -113,18 +113,22 @@ namespace __gnu_debug
_Safe_iterator<_Iterator, _Sequence, _Category>::
_M_get_distance_to(const _Safe_iterator& __rhs) const
{
- typedef typename _Distance_traits<_Iterator>::__type _Diff;
+ typedef typename _Distance_traits<_Iterator>::__type _Dist;
typedef _Sequence_traits<_Sequence> _SeqTraits;
- if (this->base() == __rhs.base())
- return std::make_pair(0, __dp_exact);
+ _Dist __base_dist = __get_distance(this->base(), __rhs.base());
+ if (__base_dist.second == __dp_exact)
+ return __base_dist;
+ _Dist __seq_dist = _SeqTraits::_S_size(*this->_M_get_sequence());
if (this->_M_is_before_begin())
{
if (__rhs._M_is_begin())
return std::make_pair(1, __dp_exact);
- return std::make_pair(1, __dp_sign);
+ return __seq_dist.second == __dp_exact
+ ? std::make_pair(__seq_dist.first + 1, __dp_exact)
+ : __seq_dist;
}
if (this->_M_is_begin())
@@ -133,30 +137,42 @@ namespace __gnu_debug
return std::make_pair(-1, __dp_exact);
if (__rhs._M_is_end())
- return _SeqTraits::_S_size(*this->_M_get_sequence());
+ return __seq_dist;
- return std::make_pair(1, __dp_sign);
+ return std::make_pair(__seq_dist.first,
+ __seq_dist.second == __dp_exact
+ ? __dp_sign_max_size : __seq_dist.second);
}
if (this->_M_is_end())
{
if (__rhs._M_is_before_begin())
- return std::make_pair(-1, __dp_exact);
+ return __seq_dist.second == __dp_exact
+ ? std::make_pair(-__seq_dist.first - 1, __dp_exact)
+ : std::make_pair(-__seq_dist.first, __dp_sign);
if (__rhs._M_is_begin())
- {
- _Diff __diff = _SeqTraits::_S_size(*this->_M_get_sequence());
- return std::make_pair(-__diff.first, __diff.second);
- }
+ return std::make_pair(-__seq_dist.first, __seq_dist.second);
- return std::make_pair(-1, __dp_sign);
+ return std::make_pair(-__seq_dist.first,
+ __seq_dist.second == __dp_exact
+ ? __dp_sign_max_size : __seq_dist.second);
}
- if (__rhs._M_is_before_begin() || __rhs._M_is_begin())
- return std::make_pair(-1, __dp_sign);
+ if (__rhs._M_is_before_begin())
+ return __seq_dist.second == __dp_exact
+ ? std::make_pair(__seq_dist.first - 1, __dp_exact)
+ : std::make_pair(-__seq_dist.first, __dp_sign);
+
+ if (__rhs._M_is_begin())
+ return std::make_pair(-__seq_dist.first,
+ __seq_dist.second == __dp_exact
+ ? __dp_sign_max_size : __seq_dist.second);
if (__rhs._M_is_end())
- return std::make_pair(1, __dp_sign);
+ return std::make_pair(__seq_dist.first,
+ __seq_dist.second == __dp_exact
+ ? __dp_sign_max_size : __seq_dist.second);
return std::make_pair(1, __dp_equality);
}
diff --git a/libstdc++-v3/include/parallel/multiway_merge.h b/libstdc++-v3/include/parallel/multiway_merge.h
index c5f85881ace..63ad27403c6 100644
--- a/libstdc++-v3/include/parallel/multiway_merge.h
+++ b/libstdc++-v3/include/parallel/multiway_merge.h
@@ -232,7 +232,7 @@ namespace __gnu_parallel
*
* @return End iterator of output sequence.
*/
- template<template<typename _RAI, typename _C> class iterator,
+ template<template<typename _RAI, typename _Cp> class iterator,
typename _RAIterIterator,
typename _RAIter3,
typename _DifferenceTp,
@@ -351,7 +351,7 @@ namespace __gnu_parallel
*
* @return End iterator of output sequence.
*/
- template<template<typename _RAI, typename _C> class iterator,
+ template<template<typename _RAI, typename _Cp> class iterator,
typename _RAIterIterator,
typename _RAIter3,
typename _DifferenceTp,
diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h
index d62f64b9f6e..4b668fddc03 100644
--- a/libstdc++-v3/include/precompiled/stdc++.h
+++ b/libstdc++-v3/include/precompiled/stdc++.h
@@ -139,7 +139,7 @@
// #include <concepts>
#include <numbers>
// #include <ranges>
-// #include <span>
+#include <span>
// #include <syncstream>
#include <version>
#endif
diff --git a/libstdc++-v3/include/std/numeric b/libstdc++-v3/include/std/numeric
index 239276946b5..a164a9e6430 100644
--- a/libstdc++-v3/include/std/numeric
+++ b/libstdc++-v3/include/std/numeric
@@ -230,8 +230,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// @{
/// @cond undocumented
- template<typename _It, typename _Traits = iterator_traits<_It>,
- typename _Cat = typename _Traits::iterator_category>
+ template<typename _It, typename _Cat = __iterator_category_t<_It>>
using __is_random_access_iter
= is_base_of<random_access_iterator_tag, _Cat>;
/// @endcond
diff --git a/libstdc++-v3/include/tr1/hashtable.h b/libstdc++-v3/include/tr1/hashtable.h
index c1b5c9e8fda..354d7b814eb 100644
--- a/libstdc++-v3/include/tr1/hashtable.h
+++ b/libstdc++-v3/include/tr1/hashtable.h
@@ -34,6 +34,7 @@
#pragma GCC system_header
#include <tr1/hashtable_policy.h>
+#include <ext/alloc_traits.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -429,7 +430,9 @@ namespace tr1
_Node* __n = _M_node_allocator.allocate(1);
__try
{
- _M_get_Value_allocator().construct(&__n->_M_v, __v);
+ _Value_allocator_type __a = _M_get_Value_allocator();
+ typedef __gnu_cxx::__alloc_traits<_Value_allocator_type> _Traits;
+ _Traits::construct(__a, &__n->_M_v, __v);
__n->_M_next = 0;
return __n;
}
@@ -449,7 +452,9 @@ namespace tr1
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_deallocate_node(_Node* __n)
{
- _M_get_Value_allocator().destroy(&__n->_M_v);
+ _Value_allocator_type __a = _M_get_Value_allocator();
+ typedef __gnu_cxx::__alloc_traits<_Value_allocator_type> _Traits;
+ _Traits::destroy(__a, &__n->_M_v);
_M_node_allocator.deallocate(__n, 1);
}
diff --git a/libstdc++-v3/src/c++17/fs_dir.cc b/libstdc++-v3/src/c++17/fs_dir.cc
index d8c48f6d6d8..bcbcd7ba6b3 100644
--- a/libstdc++-v3/src/c++17/fs_dir.cc
+++ b/libstdc++-v3/src/c++17/fs_dir.cc
@@ -26,6 +26,7 @@
# define _GLIBCXX_USE_CXX11_ABI 1
#endif
+#include <bits/largefile-config.h>
#include <filesystem>
#include <utility>
#include <stack>
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index d8064819d36..2541530e784 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -28,6 +28,7 @@
# define NEED_DO_SPACE
#endif
+#include <bits/largefile-config.h>
#include <filesystem>
#include <functional>
#include <ostream>
@@ -950,7 +951,7 @@ fs::file_size(const path& p, error_code& ec) noexcept
S(const stat_type& st) : type(make_file_type(st)), size(st.st_size) { }
S() : type(file_type::not_found) { }
file_type type;
- size_t size;
+ uintmax_t size;
};
auto s = do_stat(p, ec, [](const auto& st) { return S{st}; }, S{});
if (s.type == file_type::regular)
diff --git a/libstdc++-v3/src/filesystem/dir.cc b/libstdc++-v3/src/filesystem/dir.cc
index 3e6e598fa64..ac3bd3aafb3 100644
--- a/libstdc++-v3/src/filesystem/dir.cc
+++ b/libstdc++-v3/src/filesystem/dir.cc
@@ -26,6 +26,7 @@
# define _GLIBCXX_USE_CXX11_ABI 1
#endif
+#include <bits/largefile-config.h>
#include <experimental/filesystem>
#ifndef _GLIBCXX_HAVE_DIRENT_H
diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc
index 36b5d2c24f6..8687fcdc297 100644
--- a/libstdc++-v3/src/filesystem/ops.cc
+++ b/libstdc++-v3/src/filesystem/ops.cc
@@ -28,6 +28,7 @@
# define NEED_DO_SPACE
#endif
+#include <bits/largefile-config.h>
#include <experimental/filesystem>
#include <functional>
#include <ostream>
@@ -806,7 +807,7 @@ fs::file_size(const path& p, error_code& ec) noexcept
S(const stat_type& st) : type(make_file_type(st)), size(st.st_size) { }
S() : type(file_type::not_found) { }
file_type type;
- size_t size;
+ uintmax_t size;
};
auto s = do_stat(p, ec, [](const auto& st) { return S{st}; }, S{});
if (s.type == file_type::regular)
diff --git a/libstdc++-v3/testsuite/17_intro/names.cc b/libstdc++-v3/testsuite/17_intro/names.cc
index cab25498043..3d6148fa0e8 100644
--- a/libstdc++-v3/testsuite/17_intro/names.cc
+++ b/libstdc++-v3/testsuite/17_intro/names.cc
@@ -53,7 +53,10 @@
#endif
// <queue> and <stack> defined data members called c
#define d (
+#if __cplusplus <= 201703L
+// <numbers> defines std::numbers::e
#define e (
+#endif
#define f (
#define g (
#if __cplusplus >= 201402L
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/1_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/1_neg.cc
new file mode 100644
index 00000000000..3e0e0299e1d
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/1_neg.cc
@@ -0,0 +1,38 @@
+// Copyright (C) 2019 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-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <algorithm>
+#include <vector>
+
+void
+test01()
+{
+ std::vector<int> v1(3, 1);
+ std::vector<int> v2(5, 0);
+
+ std::copy_n(v1.begin(), 5, v2.begin());
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/2_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/2_neg.cc
new file mode 100644
index 00000000000..ebc7cb5ea4c
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/2_neg.cc
@@ -0,0 +1,38 @@
+// Copyright (C) 2019 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-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <algorithm>
+#include <vector>
+
+void
+test01()
+{
+ std::vector<int> v1(5, 1);
+ std::vector<int> v2(3, 0);
+
+ std::copy_n(v1.begin(), 5, v2.begin());
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/1.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/1.cc
new file mode 100644
index 00000000000..87d37b6b9ca
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/1.cc
@@ -0,0 +1,73 @@
+// Copyright (C) 2019 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-do run { target c++11 } }
+
+#include <algorithm>
+#include <sstream>
+#include <iterator>
+
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ std::stringstream ss("12345");
+
+ std::string ostr(5, '0');
+ typedef std::istreambuf_iterator<char> istrb_ite;
+ auto res = std::copy_n(istrb_ite(ss), 0, ostr.begin());
+ VERIFY( res == ostr.begin() );
+ VERIFY( ostr.front() == '0' );
+
+ res = std::copy_n(istrb_ite(ss), 2, ostr.begin());
+ VERIFY( res == ostr.begin() + 2 );
+ VERIFY( ostr == "12000" );
+
+ res = std::copy_n(istrb_ite(ss), 3, ostr.begin() + 2);
+ VERIFY( res == ostr.begin() + 5 );
+ VERIFY( ostr == "12345" );
+}
+
+void test02()
+{
+ std::stringstream ss("12345");
+
+ std::string ostr(5, '0');
+ typedef std::istreambuf_iterator<char> istrb_ite;
+
+ istrb_ite ibfit(ss);
+ auto res = std::copy_n(ibfit, 3, std::copy_n(ibfit, 2, ostr.begin()));
+ VERIFY( res == ostr.begin() + 5 );
+ VERIFY( ostr == "12345" );
+}
+
+void test03()
+{
+ std::string ostr(5, '0');
+ typedef std::istreambuf_iterator<char> istrb_ite;
+
+ auto res = std::copy_n(istrb_ite(), 0, ostr.begin());
+ VERIFY( res == ostr.begin() );
+}
+
+int main()
+{
+ test01();
+ test02();
+ test03();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/1_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/1_neg.cc
new file mode 100644
index 00000000000..42bc5b64306
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/1_neg.cc
@@ -0,0 +1,40 @@
+// Copyright (C) 2019 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-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode { } }
+
+#include <algorithm>
+#include <sstream>
+#include <iterator>
+
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ std::stringstream ss("12345");
+
+ std::string ostr(10, '0');
+ typedef std::istreambuf_iterator<char> istrb_ite;
+ std::copy_n(istrb_ite(ss), 10, ostr.begin());
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2_neg.cc
new file mode 100644
index 00000000000..cede27a248d
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2_neg.cc
@@ -0,0 +1,38 @@
+// Copyright (C) 2019 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-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode { } }
+
+#include <algorithm>
+#include <sstream>
+#include <iterator>
+
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ std::string ostr(10, '0');
+ typedef std::istreambuf_iterator<char> istrb_ite;
+ std::copy_n(istrb_ite(), 10, ostr.begin());
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.h b/libstdc++-v3/testsuite/util/testsuite_abi.h
index 47fbd76bb96..8f6a89e8739 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.h
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.h
@@ -22,7 +22,7 @@
#include <stdexcept>
#include <vector>
#include <locale>
-#include <tr1/unordered_map>
+#include <unordered_map>
#include <cxxabi.h>
// Encapsulates symbol characteristics.
@@ -65,7 +65,7 @@ struct symbol
};
// Map type between symbol names and full symbol info.
-typedef std::tr1::unordered_map<std::string, symbol> symbols;
+typedef std::unordered_map<std::string, symbol> symbols;
// Check.
diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h
index 34dba16669f..67e70a29edb 100644
--- a/libstdc++-v3/testsuite/util/testsuite_allocator.h
+++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h
@@ -26,7 +26,6 @@
#ifndef _GLIBCXX_TESTSUITE_ALLOCATOR_H
#define _GLIBCXX_TESTSUITE_ALLOCATOR_H
-#include <tr1/unordered_map>
#include <bits/move.h>
#include <ext/pointer.h>
#include <ext/alloc_traits.h>
@@ -36,6 +35,14 @@
# include <new>
#endif
+#if __cplusplus >= 201103L
+# include <unordered_map>
+namespace unord = std;
+#else
+# include <tr1/unordered_map>
+namespace unord = std::tr1;
+#endif
+
namespace __gnu_test
{
class tracker_allocator_counter
@@ -269,7 +276,7 @@ namespace __gnu_test
// (see N1599).
struct uneq_allocator_base
{
- typedef std::tr1::unordered_map<void*, int> map_type;
+ typedef unord::unordered_map<void*, int> map_type;
// Avoid static initialization troubles and/or bad interactions
// with tests linking testsuite_allocator.o and playing globally