aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--c++tools/ChangeLog5
-rwxr-xr-xc++tools/configure11
-rw-r--r--c++tools/configure.ac6
-rw-r--r--gcc/ChangeLog307
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/c-family/ChangeLog17
-rw-r--r--gcc/c-family/c.opt2
-rw-r--r--gcc/c/ChangeLog63
-rw-r--r--gcc/c/c-decl.cc1
-rw-r--r--gcc/c/c-objc-common.cc5
-rw-r--r--gcc/c/c-parser.cc19
-rw-r--r--gcc/c/c-typeck.cc17
-rw-r--r--gcc/calls.cc30
-rw-r--r--gcc/cobol/ChangeLog13
-rw-r--r--gcc/cobol/genapi.cc4
-rw-r--r--gcc/cobol/gengen.cc16
-rw-r--r--gcc/cobol/genutil.cc23
-rw-r--r--gcc/cobol/genutil.h3
-rw-r--r--gcc/config/i386/i386.md321
-rw-r--r--gcc/config/or1k/or1k.opt4
-rw-r--r--gcc/config/or1k/predicates.md3
-rw-r--r--gcc/config/riscv/autovec-opt.md52
-rw-r--r--gcc/config/riscv/autovec.md54
-rw-r--r--gcc/config/riscv/riscv-c.cc18
-rw-r--r--gcc/config/riscv/riscv-ext.def26
-rw-r--r--gcc/config/riscv/riscv-ext.opt4
-rw-r--r--gcc/config/riscv/riscv-opts.h1
-rw-r--r--gcc/config/riscv/riscv-protos.h1
-rw-r--r--gcc/config/riscv/riscv-subset.h62
-rw-r--r--gcc/config/riscv/riscv-v.cc1
-rw-r--r--gcc/config/riscv/riscv-vector-costs.cc4
-rw-r--r--gcc/config/riscv/riscv.cc66
-rw-r--r--gcc/config/riscv/riscv.opt4
-rw-r--r--gcc/config/riscv/t-riscv13
-rw-r--r--gcc/config/riscv/vector-iterators.md2
-rw-r--r--gcc/config/xtensa/xtensa.cc28
-rw-r--r--gcc/config/xtensa/xtensa.md2
-rw-r--r--gcc/cp/ChangeLog116
-rw-r--r--gcc/cp/constexpr.cc6
-rw-r--r--gcc/cp/coroutines.cc58
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/error.cc21
-rw-r--r--gcc/cp/method.cc32
-rw-r--r--gcc/cp/name-lookup.h4
-rw-r--r--gcc/cp/parser.cc21
-rw-r--r--gcc/cp/pt.cc30
-rw-r--r--gcc/cp/semantics.cc4
-rw-r--r--gcc/diagnostic-format-html.cc13
-rw-r--r--gcc/diagnostic-show-locus.cc140
-rw-r--r--gcc/doc/gm2.texi3
-rw-r--r--gcc/doc/invoke.texi7
-rw-r--r--gcc/doc/riscv-ext.texi8
-rw-r--r--gcc/doc/sourcebuild.texi18
-rw-r--r--gcc/doc/standards.texi38
-rw-r--r--gcc/doc/trouble.texi8
-rw-r--r--gcc/final.cc11
-rw-r--r--gcc/fortran/ChangeLog33
-rw-r--r--gcc/fortran/data.cc8
-rw-r--r--gcc/fortran/expr.cc84
-rw-r--r--gcc/fortran/primary.cc3
-rw-r--r--gcc/fortran/trans-expr.cc16
-rw-r--r--gcc/function.h1
-rw-r--r--gcc/gimple-fold.cc5
-rw-r--r--gcc/gimple-harden-conditionals.cc6
-rw-r--r--gcc/gimple-harden-control-flow.cc3
-rw-r--r--gcc/ipa-strub.cc3
-rw-r--r--gcc/lra-eliminations.cc2
-rw-r--r--gcc/lra-spills.cc2
-rw-r--r--gcc/m2/ChangeLog102
-rw-r--r--gcc/m2/gm2-compiler/M2Check.def3
-rw-r--r--gcc/m2/gm2-compiler/M2Check.mod522
-rw-r--r--gcc/m2/gm2-compiler/M2GenGCC.mod88
-rw-r--r--gcc/m2/gm2-compiler/M2MetaError.def6
-rw-r--r--gcc/m2/gm2-compiler/M2Options.def16
-rw-r--r--gcc/m2/gm2-compiler/M2Options.mod22
-rw-r--r--gcc/m2/gm2-compiler/M2Quads.mod141
-rw-r--r--gcc/m2/gm2-compiler/M2Range.def18
-rw-r--r--gcc/m2/gm2-compiler/M2Range.mod274
-rw-r--r--gcc/m2/gm2-gcc/m2options.h2
-rw-r--r--gcc/m2/gm2-lang.cc3
-rw-r--r--gcc/m2/gm2-libs-log/InOut.mod12
-rw-r--r--gcc/m2/lang.opt4
-rw-r--r--gcc/passes.cc25
-rw-r--r--gcc/rtl.h10
-rw-r--r--gcc/rtlanal.cc15
-rw-r--r--gcc/testsuite/ChangeLog348
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-variant-2.c2
-rw-r--r--gcc/testsuite/c-c++-common/gomp/metadirective-condition-constexpr.c13
-rw-r--r--gcc/testsuite/c-c++-common/gomp/metadirective-condition.c25
-rw-r--r--gcc/testsuite/c-c++-common/gomp/metadirective-error-recovery.c9
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr118903.C40
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-lambda24.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constinit21.C28
-rw-r--r--gcc/testsuite/g++.dg/ext/has_trivial_destructor-3.C21
-rw-r--r--gcc/testsuite/g++.dg/ext/is_destructible2.C24
-rw-r--r--gcc/testsuite/g++.dg/gomp/metadirective-condition-class.C43
-rw-r--r--gcc/testsuite/g++.dg/gomp/metadirective-condition-template.C41
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-1.C3
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-3.C1
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-4.C1
-rw-r--r--gcc/testsuite/g++.dg/tls/pr102496-1.C2
-rw-r--r--gcc/testsuite/g++.dg/tls/pr77285-1.C2
-rw-r--r--gcc/testsuite/g++.target/arm/pr120424.C34
-rw-r--r--gcc/testsuite/g++.target/i386/pr103750.C39
-rw-r--r--gcc/testsuite/gcc.dg/Wjump-misses-init-3.c10
-rw-r--r--gcc/testsuite/gcc.dg/format/diagnostic-ranges-html.py99
-rw-r--r--gcc/testsuite/gcc.dg/format/diagnostic-ranges.c6
-rw-r--r--gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c26
-rw-r--r--gcc/testsuite/gcc.dg/pr116892.c11
-rw-r--r--gcc/testsuite/gcc.dg/pr120380.c24
-rw-r--r--gcc/testsuite/gcc.dg/pr120525.c22
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/cswtch-6.c43
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phiprop-2.c28
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-early-break_136-pr120357.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr49095-2.c73
-rw-r--r--gcc/testsuite/gcc.target/i386/pr79173-13.c59
-rw-r--r--gcc/testsuite/gcc.target/i386/pr79173-14.c59
-rw-r--r--gcc/testsuite/gcc.target/i386/pr79173-15.c61
-rw-r--r--gcc/testsuite/gcc.target/i386/pr79173-16.c61
-rw-r--r--gcc/testsuite/gcc.target/i386/pr79173-17.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/pr79173-18.c33
-rw-r--r--gcc/testsuite/gcc.target/or1k/call-1.c22
-rw-r--r--gcc/testsuite/gcc.target/or1k/got-1.c18
-rw-r--r--gcc/testsuite/gcc.target/or1k/return-2.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-59.c5
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-shlocofideleg.c5
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv-nofm.c8
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv.c4
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv-nofm.c8
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv.c4
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/param-autovec-mode.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f16.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f32.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f64.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f16.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f32.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f64.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f16.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f32.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f64.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f16.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f32.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f64.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop.h61
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_data.h413
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_run.h34
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c15
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f32.c15
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f64.c15
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c15
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f32.c15
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f64.c15
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h196
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i16.c15
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i32.c15
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i64.c15
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i8.c15
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_data_2.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/inquiry_type_ref_8.f90214
-rw-r--r--gcc/testsuite/gfortran.dg/pr119856.f9015
-rw-r--r--gcc/testsuite/gfortran.dg/save_8.f9013
-rw-r--r--gcc/testsuite/gm2/pim/fail/testcharint.mod8
-rw-r--r--gcc/testsuite/gm2/pim/fail/testindrx.mod8
-rw-r--r--gcc/testsuite/gm2/pim/pass/ReturnType.mod17
-rw-r--r--gcc/testsuite/gm2/pim/pass/ReturnType2.mod19
-rw-r--r--gcc/testsuite/gm2/pim/pass/testxindr.mod17
-rw-r--r--gcc/testsuite/gm2/pim/pass/testxindr2.mod17
-rw-r--r--gcc/testsuite/gm2/pim/pass/testxindr3.mod15
-rw-r--r--gcc/testsuite/gnat.dg/controlled9.adb10
-rw-r--r--gcc/testsuite/gnat.dg/controlled9_pkg.ads5
-rw-r--r--gcc/testsuite/lib/target-supports.exp10
-rw-r--r--gcc/tree-inline.cc1
-rw-r--r--gcc/tree-pass.h6
-rw-r--r--gcc/tree-ssa-forwprop.cc8
-rw-r--r--gcc/tree-switch-conversion.cc3
-rw-r--r--gcc/tree-vect-data-refs.cc2
-rw-r--r--gcc/tree-vect-loop.cc3
-rw-r--r--gcc/tree-vrp.cc4
-rw-r--r--gcc/var-tracking.cc2
-rw-r--r--include/ChangeLog12
-rw-r--r--include/cuda/cuda.h3
-rw-r--r--libgcobol/ChangeLog5
-rw-r--r--libgcobol/libgcobol.cc14
-rw-r--r--libgfortran/ChangeLog8
-rw-r--r--libgfortran/io/format.c10
-rw-r--r--libgomp/ChangeLog160
-rw-r--r--libgomp/libgomp-plugin.h1
-rw-r--r--libgomp/libgomp.h3
-rw-r--r--libgomp/libgomp.map6
-rw-r--r--libgomp/libgomp.texi118
-rw-r--r--libgomp/omp.h.in4
-rw-r--r--libgomp/omp_lib.f90.in23
-rw-r--r--libgomp/omp_lib.h.in25
-rw-r--r--libgomp/plugin/cuda-lib.def1
-rw-r--r--libgomp/plugin/plugin-gcn.c80
-rw-r--r--libgomp/plugin/plugin-nvptx.c9
-rw-r--r--libgomp/target.c83
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/omp_target_memset-2.c62
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/omp_target_memset-3.c80
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/omp_target_memset.c62
-rw-r--r--libgomp/testsuite/libgomp.fortran/omp_target_memset-2.f9067
-rw-r--r--libgomp/testsuite/libgomp.fortran/omp_target_memset.f9039
-rw-r--r--libstdc++-v3/ChangeLog412
-rw-r--r--libstdc++-v3/include/bits/atomic_timed_wait.h7
-rw-r--r--libstdc++-v3/include/bits/basic_string.h4
-rw-r--r--libstdc++-v3/include/bits/chrono_io.h3
-rw-r--r--libstdc++-v3/include/bits/cpyfunc_impl.h4
-rw-r--r--libstdc++-v3/include/bits/funcref_impl.h4
-rw-r--r--libstdc++-v3/include/bits/funcwrap.h20
-rw-r--r--libstdc++-v3/include/bits/indirect.h376
-rw-r--r--libstdc++-v3/include/bits/mofunc_impl.h4
-rw-r--r--libstdc++-v3/include/bits/ranges_algo.h7
-rw-r--r--libstdc++-v3/include/bits/stl_algo.h89
-rw-r--r--libstdc++-v3/include/bits/stl_deque.h2
-rw-r--r--libstdc++-v3/include/bits/stl_vector.h10
-rw-r--r--libstdc++-v3/include/bits/vector.tcc6
-rw-r--r--libstdc++-v3/include/bits/version.def9
-rw-r--r--libstdc++-v3/include/bits/version.h10
-rw-r--r--libstdc++-v3/include/std/bit4
-rw-r--r--libstdc++-v3/include/std/memory1
-rw-r--r--libstdc++-v3/include/std/stop_token7
-rw-r--r--libstdc++-v3/include/std/type_traits42
-rw-r--r--libstdc++-v3/src/c++20/atomic.cc24
-rw-r--r--libstdc++-v3/src/c++23/std.cc.in8
-rw-r--r--libstdc++-v3/testsuite/20_util/copyable_function/call.cc7
-rw-r--r--libstdc++-v3/testsuite/20_util/copyable_function/conv.cc35
-rw-r--r--libstdc++-v3/testsuite/20_util/copyable_function/incomplete_neg.cc18
-rw-r--r--libstdc++-v3/testsuite/20_util/function_ref/call.cc10
-rw-r--r--libstdc++-v3/testsuite/20_util/function_ref/conv.cc34
-rw-r--r--libstdc++-v3/testsuite/20_util/function_ref/incomplete_neg.cc18
-rw-r--r--libstdc++-v3/testsuite/20_util/move_only_function/call.cc7
-rw-r--r--libstdc++-v3/testsuite/20_util/move_only_function/conv.cc35
-rw-r--r--libstdc++-v3/testsuite/20_util/move_only_function/incomplete_neg.cc18
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/unique_copy/lwg2439.cc127
-rw-r--r--libstdc++-v3/testsuite/std/memory/polymorphic/copy.cc157
-rw-r--r--libstdc++-v3/testsuite/std/memory/polymorphic/copy_alloc.cc270
-rw-r--r--libstdc++-v3/testsuite/std/memory/polymorphic/ctor.cc190
-rw-r--r--libstdc++-v3/testsuite/std/memory/polymorphic/ctor_poly.cc220
-rw-r--r--libstdc++-v3/testsuite/std/memory/polymorphic/incomplete.cc13
-rw-r--r--libstdc++-v3/testsuite/std/memory/polymorphic/invalid_neg.cc28
-rw-r--r--libstdc++-v3/testsuite/std/memory/polymorphic/move.cc177
-rw-r--r--libstdc++-v3/testsuite/std/memory/polymorphic/move_alloc.cc339
-rw-r--r--libstdc++-v3/testsuite/std/time/format/empty_spec.cc271
267 files changed, 9229 insertions, 711 deletions
diff --git a/c++tools/ChangeLog b/c++tools/ChangeLog
index ff35cac..d5a345b 100644
--- a/c++tools/ChangeLog
+++ b/c++tools/ChangeLog
@@ -1,3 +1,8 @@
+2025-06-02 Kito Cheng <kito.cheng@sifive.com>
+
+ * configure.ac: Don't check `--enable-default-pie`.
+ * configure: Regen.
+
2024-05-07 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* configure.ac (ax_lib_socket_nsl.m4): Don't sinclude.
diff --git a/c++tools/configure b/c++tools/configure
index 1353479..6df4a2f 100755
--- a/c++tools/configure
+++ b/c++tools/configure
@@ -700,7 +700,6 @@ enable_option_checking
enable_c___tools
enable_maintainer_mode
enable_checking
-enable_default_pie
enable_host_pie
enable_host_bind_now
with_gcc_major_version_only
@@ -1335,7 +1334,6 @@ Optional Features:
enable expensive run-time checks. With LIST, enable
only specific categories of checks. Categories are:
yes,no,all,none,release.
- --enable-default-pie enable Position Independent Executable as default
--enable-host-pie build host code as PIE
--enable-host-bind-now link host code as BIND_NOW
@@ -2946,15 +2944,6 @@ $as_echo "#define ENABLE_ASSERT_CHECKING 1" >>confdefs.h
fi
-# Check whether --enable-default-pie was given.
-# Check whether --enable-default-pie was given.
-if test "${enable_default_pie+set}" = set; then :
- enableval=$enable_default_pie; PICFLAG=-fPIE
-else
- PICFLAG=
-fi
-
-
# Enable --enable-host-pie
# Check whether --enable-host-pie was given.
if test "${enable_host_pie+set}" = set; then :
diff --git a/c++tools/configure.ac b/c++tools/configure.ac
index db34ee6..8c4b72a 100644
--- a/c++tools/configure.ac
+++ b/c++tools/configure.ac
@@ -97,12 +97,6 @@ if test x$ac_assert_checking != x ; then
[Define if you want assertions enabled. This is a cheap check.])
fi
-# Check whether --enable-default-pie was given.
-AC_ARG_ENABLE(default-pie,
-[AS_HELP_STRING([--enable-default-pie],
- [enable Position Independent Executable as default])],
-[PICFLAG=-fPIE], [PICFLAG=])
-
# Enable --enable-host-pie
AC_ARG_ENABLE(host-pie,
[AS_HELP_STRING([--enable-host-pie],
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5f4d53c..921d621 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,310 @@
+2025-06-03 Richard Biener <rguenther@suse.de>
+
+ * gimple-fold.cc (create_tmp_reg_or_ssa_name): Always
+ create a SSA name.
+
+2025-06-03 Pan Li <pan2.li@intel.com>
+
+ * config/riscv/riscv-v.cc (expand_vx_binary_vec_vec_dup): Add new
+ case for DIV op.
+ * config/riscv/riscv.cc (get_vector_binary_rtx_cost): Add new func
+ to get the cost of vector binary.
+ (riscv_rtx_costs): Add div rtx match and leverage above wrap to
+ get cost.
+ * config/riscv/vector-iterators.md: Add new op div to no_shift_vx_op.
+
+2025-06-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/120517
+ * tree-vect-data-refs.cc (vect_analyze_data_ref_accesses):
+ Fix math in dataref group split.
+
+2025-06-03 Paul-Antoine Arras <parras@baylibre.com>
+
+ * config/riscv/riscv-vector-costs.cc (costs::adjust_stmt_cost): Replace
+ FR2VR with get_fr2vr_cost ().
+ * config/riscv/riscv.cc (riscv_register_move_cost): Likewise.
+ (riscv_builtin_vectorization_cost): Likewise.
+
+2025-06-03 Paul-Antoine Arras <parras@baylibre.com>
+
+ PR target/119100
+ * config/riscv/autovec-opt.md (*<optab>_vf_<mode>): Add new pattern to
+ combine vec_duplicate + vfm{add,sub}.vv into vfm{add,sub}.vf.
+ * config/riscv/riscv-opts.h (FPR2VR_COST_UNPROVIDED): Define.
+ * config/riscv/riscv-protos.h (get_fr2vr_cost): Declare function.
+ * config/riscv/riscv.cc (riscv_rtx_costs): Add cost model for MULT with
+ VEC_DUPLICATE.
+ (get_fr2vr_cost): New function.
+ * config/riscv/riscv.opt: Add new option --param=fpr2vr-cost.
+
+2025-06-03 Andrew Pinski <quic_apinski@quicinc.com>
+
+ PR tree-optimization/120451
+ * tree-switch-conversion.cc (switch_conversion::build_one_array): Mark
+ the newly created decl as mergable.
+
+2025-06-02 Alexandre Oliva <oliva@adacore.com>
+
+ PR rtl-optimization/120424
+ PR middle-end/118939
+ * lra-spills.cc (spill_pseudos): Update insn regno info.
+ * lra-eliminations.cc (update_reg_eliminate): Recognize
+ disabling of active elimination regardless of
+ prev_can_eliminate.
+
+2025-06-02 Dongyan Chen <chendongyan@isrc.iscas.ac.cn>
+
+ * config/riscv/riscv-ext.def: New extension defs.
+ * config/riscv/riscv-ext.opt: Ditto.
+ * doc/riscv-ext.texi: Ditto.
+
+2025-06-02 Stafford Horne <shorne@gmail.com>
+
+ * config/or1k/predicates.md (call_insn_operand): Add condition
+ to not allow symbol_ref operands with TARGET_CMODEL_LARGE.
+ * config/or1k/or1k.opt: Document new -mcmodel=large
+ implications.
+ * doc/invoke.texi: Likewise.
+
+2025-06-02 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * doc/sourcebuild.texi (tls_link): Add documentation.
+
+2025-06-02 Kito Cheng <kito.cheng@sifive.com>
+
+ * config/riscv/t-riscv: Adjust build rule for gen-riscv-ext-opt
+ and gen-riscv-ext-texi.
+
+2025-06-02 Kito Cheng <kito.cheng@sifive.com>
+
+ * config/riscv/riscv-c.cc (riscv_cpu_cpp_builtins): Use
+ range-based-for-loop.
+ * config/riscv/riscv-subset.h (riscv_subset_list::iterator):
+ New.
+ (riscv_subset_list::const_iterator): New.
+
+2025-06-01 H.J. Lu <hjl.tools@gmail.com>
+
+ PR other/120493
+ * final.cc (call_from_call_insn): Change the argument type to
+ const rtx_call_insn *.
+ (get_call_rtx_from): New.
+ * rtl.h (is_a_helper <const rtx_call_insn *>::test): New.
+ (get_call_rtx_from): Moved to the final.cc section.
+ * rtlanal.cc (get_call_rtx_from): Removed.
+
+2025-06-01 Andrew Pinski <quic_apinski@quicinc.com>
+
+ * tree-ssa-forwprop.cc (optimize_vector_load): Set the vuse manually
+ on the new load statements. Also remove forward declaration since
+ the definition is before the first use.
+ (pass_forwprop::execute): Likewise for complex loads.
+ (pass_data_forwprop): Remove TODO_update_ssa.
+
+2025-06-01 Pan Li <pan2.li@intel.com>
+
+ * config/riscv/autovec.md: Fix line too long for sorts
+ of pattern.
+
+2025-06-01 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>
+
+ * config/xtensa/xtensa.cc: Remove include of reload.h.
+
+2025-06-01 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>
+
+ * config/xtensa/xtensa.md (movsf_internal):
+ Remove destination side constraint modifier '^' in the third
+ alternative.
+
+2025-06-01 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>
+
+ * config/xtensa/xtensa.cc
+ (xtensa_ira_change_pseudo_allocno_class):
+ New prototype and function.
+ (TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS): Define macro.
+ (xtensa_register_move_cost):
+ Change between integer and FP register move cost to a value
+ based on actual behavior, i.e. 2, the default and the same as
+ the move cost between integer registers.
+
+2025-05-31 Andrew Pinski <quic_apinski@quicinc.com>
+
+ * function.h (struct function): Remove last_verified.
+ * gimple-harden-conditionals.cc (pass_data_harden_compares): Remove
+ TODO_verify_il.
+ (pass_data_harden_conditional_branches): Likewise.
+ * gimple-harden-control-flow.cc (pass_harden_control_flow_redundancy::execute):
+ Don't return TODO_verify_il.
+ * ipa-strub.cc (pass_data_ipa_strub): Remove TODO_verify_il.
+ * passes.cc (TODO_verify_il): Define.
+ (execute_function_todo): Don't use or set last_verified.
+ (clear_last_verified): Remove.
+ (execute_one_ipa_transform_pass): Update comment before execute_todo.
+ Assert that none of the todos have TODO_verify_il set on it.
+ (execute_one_pass): Don't call clear_last_verified on all functions.
+ Assert that none of the todos have TODO_verify_il set on it.
+ * tree-inline.cc (initialize_cfun): Don't copy last_verified.
+ * tree-pass.h (TODO_verify_all): Remove.
+ * tree-vrp.cc (pass_data_early_vrp): Remove TODO_verify_all.
+ (pass_data_fast_vrp): Likewise.
+
+2025-05-31 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/120357
+ * tree-vect-loop.cc (vect_create_epilog_for_reduction): Create
+ the conditional reduction induction IV increment before the
+ main IV exit.
+
+2025-05-31 Gaius Mulley <gaiusmod2@gmail.com>
+
+ PR modula2/120389
+ * doc/gm2.texi (-fm2-strict-type-reason): Document new flag.
+
+2025-05-30 David Malcolm <dmalcolm@redhat.com>
+
+ PR other/116792
+ * diagnostic-format-html.cc (HTML_STYLE): Add ".highlight-a" and
+ ".highlight-b".
+ (html_builder::make_element_for_diagnostic): Handle begin_color
+ and end_color.
+ * diagnostic-show-locus.cc (to_html::to_html): Add "richloc"
+ param and use it to initialize m_richloc.
+ (to_html::colorize_text_for_range_idx): Drop.
+ (to_html::get_location_range_by_idx): New.
+ (to_html::get_highlight_color_for_range_idx): New.
+ (to_html::m_richloc): New field.
+ (print_html_span_start): Update for new param of to_html ctor.
+ (line_printer::m_was_in_range_p): New field.
+ (line_printer::m_last_range_idx): New field.
+ (layout_printer<Sink>::print_source_line): Use set_in_range
+ and set_outside_range rather than colorization calls.
+ (layout_printer<Sink>::set_in_range): New.
+ (layout_printer<Sink>::set_outside_range): New.
+ (layout_printer<Sink>::print_annotation_line): Use set_in_range
+ and set_outside_range rather than colorization calls.
+ (layout_printer<to_text>::begin_label): Convert param from label
+ to state_idx. Add "is_label_text" param and use it to guard logic
+ for turning off colorization within paths.
+ (layout_printer<to_html>::begin_label): Likewise. Push <span>
+ for any highlight color.
+ (layout_printer<to_text>::end_label): Likewise.
+ (layout_printer<to_text>::end_label): Likewise, popping the
+ <span>.
+ (layout_printer<Sink>::print_any_labels): Convert begin/end_label
+ calls to pass in state_idx rather than label. Use begin/end_label
+ rather than colorization calls.
+ (layout_printer<Sink>::layout_printer): Likewise.
+ (layout_printer<Sink>::layout_printer): Initialize new fields.
+ (diagnostic_source_print_policy::print_as_html): Update for new
+ param of to_html ctor.
+
+2025-05-30 Andrew Pinski <quic_apinski@quicinc.com>
+
+ * passes.cc (execute_all_ipa_transforms): Fix typo in
+ commenet.
+
+2025-05-30 Joseph Myers <josmyers@redhat.com>
+
+ * doc/standards.texi (C Language): Document library facilities
+ provided in terms of headers not declaring functions with external
+ linkage, not in terms of headers required of freestanding
+ implementations.
+ * doc/sourcebuild.texi (Subdirectories, Headers): Likewise.
+ * doc/trouble.texi (Standard Libraries): Likewise.
+
+2025-05-30 Pan Li <pan2.li@intel.com>
+
+ * config/riscv/autovec.md (avg<v_double_trunc>3_ceil): Add insn
+ expand to leverage vaadd with rnu directly.
+
+2025-05-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/120341
+ * tree-ssa-loop-im.cc (can_sm_ref_p): STRING_CSTs are readonly.
+ * tree-ssa-phiopt.cc (cond_store_replacement): Likewise.
+
+2025-05-30 Thomas Schwinge <tschwinge@baylibre.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR middle-end/119835
+ * tree-nrv.cc (pass_nrv::execute): Defuse 'RESULT_DECL' check.
+
+2025-05-30 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostic-show-locus.cc (colorizer::m_current_named_color): New
+ field.
+ (colorizer::set_named_color): Use it to consolidate repeated calls
+ to the same color.
+
+2025-05-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/120457
+ * tree-vect-slp.cc (vect_lower_load_permutations): Implement
+ the same heuristics as load vectorization for single-element
+ interleaving that spans multiple vectors.
+
+2025-05-30 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR rtl-optimization/120347
+ * rtlanal.cc (rtx_properties::try_to_add_src): Don't drop the
+ IN_MEM_LOAD and IN_MEM_STORE flags for autoinc registers.
+ * rtl-ssa/changes.cc (recog_level2): Check whether an
+ RTX_AUTOINCed register also appears outside of an address.
+
+2025-05-30 Julian Brown <julian@codesourcery.com>
+ Tobias Burnus <tburnus@baylibre.com>
+
+ * gimplify.cc (gimplify_omp_ctx): Add IMPLICIT_MAPPERS field.
+ (new_omp_context): Initialise IMPLICIT_MAPPERS hash map.
+ (delete_omp_context): Delete IMPLICIT_MAPPERS hash map.
+ (instantiate_mapper_info): New structs.
+ (remap_mapper_decl_1, omp_mapper_copy_decl, omp_instantiate_mapper,
+ omp_instantiate_implicit_mappers): New functions.
+ (gimplify_scan_omp_clauses): Handle MAPPER_BINDING clauses.
+ (gimplify_adjust_omp_clauses): Instantiate implicit declared mappers.
+ (gimplify_omp_declare_mapper): New function.
+ (gimplify_expr): Call above function.
+ * langhooks-def.h (lhd_omp_mapper_lookup,
+ lhd_omp_extract_mapper_directive, lhd_omp_map_array_section): Add
+ prototypes.
+ (LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES,
+ LANG_HOOKS_OMP_MAPPER_LOOKUP, LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE,
+ LANG_HOOKS_OMP_MAP_ARRAY_SECTION): Define macros.
+ (LANG_HOOK_DECLS): Add above macros.
+ * langhooks.cc (lhd_omp_mapper_lookup,
+ lhd_omp_extract_mapper_directive, lhd_omp_map_array_section): New
+ dummy functions.
+ * langhooks.h (lang_hooks_for_decls): Add OMP_FINISH_MAPPER_CLAUSES,
+ OMP_MAPPER_LOOKUP, OMP_EXTRACT_MAPPER_DIRECTIVE, OMP_MAP_ARRAY_SECTION
+ hooks.
+ * omp-general.h (omp_name_type<T>): Add templatized struct, hash type
+ traits (for omp_name_type<tree> specialization).
+ (omp_mapper_list<T>): Add struct.
+ * tree-core.h (omp_clause_code): Add OMP_CLAUSE__MAPPER_BINDING_.
+ * tree-pretty-print.cc (dump_omp_clause): Support GOMP_MAP_UNSET,
+ GOMP_MAP_PUSH_MAPPER_NAME, GOMP_MAP_POP_MAPPER_NAME artificial mapping
+ clauses. Support OMP_CLAUSE__MAPPER_BINDING_ and OMP_DECLARE_MAPPER.
+ * tree.cc (omp_clause_num_ops, omp_clause_code_name): Add
+ OMP_CLAUSE__MAPPER_BINDING_.
+ * tree.def (OMP_DECLARE_MAPPER): New tree code.
+ * tree.h (OMP_DECLARE_MAPPER_ID, OMP_DECLARE_MAPPER_DECL,
+ OMP_DECLARE_MAPPER_CLAUSES): New defines.
+ (OMP_CLAUSE__MAPPER_BINDING__ID, OMP_CLAUSE__MAPPER_BINDING__DECL,
+ OMP_CLAUSE__MAPPER_BINDING__MAPPER): New defines.
+
+2025-05-30 Andrew Pinski <quic_apinski@quicinc.com>
+
+ * gimple-ssa-sccopy.cc (scc_copy_prop::replace_scc_by_value): Return true
+ if something was done.
+ (scc_copy_prop::propagate): Return true if something was changed.
+ (pass_sccopy::execute): Return TODO_cleanup_cfg if a prop happened.
+
+2025-05-30 Kugan Vivekanandarajah <kvivekananda@nvidia.com>
+
+ * auto-profile.cc (function_instance::merge): New.
+ (autofdo_source_profile::read): Call merge.
+
2025-05-29 Kugan Vivekanandarajah <kvivekananda@nvidia.com>
* config/aarch64/gcc-auto-profile: Make script executable.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index ac27433..932c2dd 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20250530
+20250604
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 8de6ae5..cd96e82 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,20 @@
+2025-06-03 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120078
+ * c.opt (Wjump-misses-init): Fix typo.
+
+2025-05-30 Julian Brown <julian@codesourcery.com>
+ Tobias Burnus <tburnus@baylibre.com>
+
+ * c-common.h (c_omp_region_type): Add C_ORT_DECLARE_MAPPER and
+ C_ORT_OMP_DECLARE_MAPPER codes.
+ (omp_mapper_list): Add forward declaration.
+ (c_omp_find_nested_mappers, c_omp_instantiate_mappers): Add prototypes.
+ * c-omp.cc (c_omp_find_nested_mappers): New function.
+ (remap_mapper_decl_info): New struct.
+ (remap_mapper_decl_1, omp_instantiate_mapper,
+ c_omp_instantiate_mappers): New functions.
+
2025-05-27 Alejandro Colomar <alx@kernel.org>
Martin Uecker <uecker@tugraz.at>
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 75b6531..50ba856 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -938,7 +938,7 @@ C ObjC C++ ObjC++ CPP(cpp_warn_invalid_utf8) CppReason(CPP_W_INVALID_UTF8) Var(w
Warn about invalid UTF-8 characters.
Wjump-misses-init
-C ObjC Var(warn_jump_misses_init) Warning LangEnabledby(C ObjC,Wc++-compat)
+C ObjC Var(warn_jump_misses_init) Warning LangEnabledBy(C ObjC,Wc++-compat)
Warn when a jump misses a variable initialization.
Enum
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index f24c084..7f5b0b8 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,66 @@
+2025-06-03 Martin Uecker <uecker@tugraz.at>
+
+ * c-typeck.cc (composite_type_internal,composite_type): Move
+ checking assertions.
+
+2025-06-03 Martin Uecker <uecker@tugraz.at>
+
+ PR c/116892
+ * c-decl.cc (finish_enum): Propagate TYPE_PACKED.
+
+2025-06-02 Sandra Loosemore <sloosemore@baylibre.com>
+
+ * c-parser.cc (c_parser_omp_context_selector): Call
+ convert_lvalue_to_rvalue and c_objc_common_truthvalue_conversion
+ on the expression for OMP_TRAIT_PROPERTY_BOOL_EXPR.
+
+2025-06-01 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120380
+ * c-objc-common.cc (get_aka_type): Ignore attributes for tagged types.
+
+2025-05-30 Qing Zhao <qing.zhao@oracle.com>
+
+ PR c/120354
+ * c-decl.cc (finish_struct): Or the results for TYPE_INCLUDES_FLEXARRAY.
+
+2025-05-30 Qing Zhao <qing.zhao@oracle.com>
+
+ PR c/120353
+ * c-decl.cc (finish_struct): Copy TYPE_INCLUDES_FLEXARRAY marking
+ to all the variant types of the current structure type.
+
+2025-05-30 Julian Brown <julian@codesourcery.com>
+
+ * c-decl.cc (c_omp_mapper_id, c_omp_mapper_decl, c_omp_mapper_lookup,
+ c_omp_extract_mapper_directive, c_omp_map_array_section,
+ c_omp_scan_mapper_bindings_r, c_omp_scan_mapper_bindings): New
+ functions.
+ * c-objc-common.h (LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES,
+ LANG_HOOKS_OMP_MAPPER_LOOKUP, LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE,
+ LANG_HOOKS_OMP_MAP_ARRAY_SECTION): Define langhooks for C.
+ * c-parser.cc (c_parser_omp_clause_map): Add declare_mapper_p
+ parameter; handle mapper modifier.
+ (c_parser_omp_all_clauses): Update call to c_parser_omp_clause_map.
+ (c_parser_omp_target): Instantiate explicit mappers and record bindings
+ for implicit mappers.
+ (c_parser_omp_declare_mapper): Parse "declare mapper" directives.
+ (c_parser_omp_declare): Support "declare mapper".
+ (c_parser_omp_declare_reduction): Use inform not error_at.
+ * c-tree.h (c_omp_finish_mapper_clauses, c_omp_mapper_lookup,
+ c_omp_extract_mapper_directive, c_omp_map_array_section,
+ c_omp_mapper_id, c_omp_mapper_decl, c_omp_scan_mapper_bindings,
+ c_omp_instantiate_mappers): Add prototypes.
+ * c-typeck.cc (c_finish_omp_clauses): Handle GOMP_MAP_PUSH_MAPPER_NAME
+ and GOMP_MAP_POP_MAPPER_NAME.
+ (c_omp_finish_mapper_clauses): New function (langhook).
+
+2025-05-30 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120381
+ * c-typeck.cc (composite_type_internal): Stop recursion for
+ swapped pairs.
+
2025-05-29 Sandra Loosemore <sloosemore@baylibre.com>
* c-parser.cc (c_parser_skip_to_closing_brace): New, copied from
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 1008bca..2b0bd66 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -10293,6 +10293,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
TYPE_UNSIGNED (tem) = TYPE_UNSIGNED (enumtype);
TYPE_LANG_SPECIFIC (tem) = TYPE_LANG_SPECIFIC (enumtype);
ENUM_UNDERLYING_TYPE (tem) = ENUM_UNDERLYING_TYPE (enumtype);
+ TYPE_PACKED (tem) = TYPE_PACKED (enumtype);
}
/* Finish debugging output for this type. */
diff --git a/gcc/c/c-objc-common.cc b/gcc/c/c-objc-common.cc
index 2016eae..d574bc7 100644
--- a/gcc/c/c-objc-common.cc
+++ b/gcc/c/c-objc-common.cc
@@ -216,6 +216,11 @@ get_aka_type (tree type)
return canonical ? canonical : type;
}
}
+ /* For tagged types ignore attributes because they will otherwise
+ be ignored later causing a warning inside diagnostics which leads
+ to an ICE. */
+ if (RECORD_OR_UNION_TYPE_P (type) || TREE_CODE (type) == ENUMERAL_TYPE)
+ return build_qualified_type (result, TYPE_QUALS (type));
return build_type_attribute_qual_variant (result, TYPE_ATTRIBUTES (type),
TYPE_QUALS (type));
}
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index cc0ab12..85580c5 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -26966,17 +26966,30 @@ c_parser_omp_context_selector (c_parser *parser, enum omp_tss_code set,
break;
case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
case OMP_TRAIT_PROPERTY_BOOL_EXPR:
- t = c_parser_expr_no_commas (parser, NULL).value;
+ {
+ c_expr texpr = c_parser_expr_no_commas (parser, NULL);
+ texpr = convert_lvalue_to_rvalue (token->location, texpr,
+ true, true);
+ t = texpr.value;
+ }
if (t == error_mark_node)
return error_mark_node;
mark_exp_read (t);
- t = c_fully_fold (t, false, NULL);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
+ {
+ t = c_objc_common_truthvalue_conversion (token->location,
+ t,
+ boolean_type_node);
+ if (t == error_mark_node)
+ return error_mark_node;
+ }
+ else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
error_at (token->location,
"property must be integer expression");
return error_mark_node;
}
+ t = c_fully_fold (t, false, NULL);
properties = make_trait_property (NULL_TREE, t, properties);
break;
case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 2f243ca..b59b5c8a 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -846,12 +846,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
n = finish_struct (input_location, n, fields, attributes, NULL,
&expr);
- n = qualify_type (n, t1);
-
- gcc_checking_assert (!TYPE_NAME (n) || comptypes (n, t1));
- gcc_checking_assert (!TYPE_NAME (n) || comptypes (n, t2));
-
- return n;
+ return qualify_type (n, t1);
}
/* FALLTHRU */
case ENUMERAL_TYPE:
@@ -1004,7 +999,15 @@ tree
composite_type (tree t1, tree t2)
{
struct composite_cache cache = { };
- return composite_type_internal (t1, t2, &cache);
+ tree n = composite_type_internal (t1, t2, &cache);
+ /* For function and arrays there are some cases where qualifiers do
+ not match. See PR120510. */
+ if (FUNCTION_TYPE != TREE_CODE (n) && ARRAY_TYPE != TREE_CODE (n))
+ {
+ gcc_checking_assert (comptypes (n, t1));
+ gcc_checking_assert (comptypes (n, t2));
+ }
+ return n;
}
/* Return the type of a conditional expression between pointers to
diff --git a/gcc/calls.cc b/gcc/calls.cc
index 164f3c5..e16190c 100644
--- a/gcc/calls.cc
+++ b/gcc/calls.cc
@@ -3736,19 +3736,16 @@ expand_call (tree exp, rtx target, int ignore)
next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
flags, args_so_far);
- if (flag_ipa_ra)
+ rtx_call_insn *last;
+ rtx datum = NULL_RTX;
+ if (fndecl != NULL_TREE)
{
- rtx_call_insn *last;
- rtx datum = NULL_RTX;
- if (fndecl != NULL_TREE)
- {
- datum = XEXP (DECL_RTL (fndecl), 0);
- gcc_assert (datum != NULL_RTX
- && GET_CODE (datum) == SYMBOL_REF);
- }
- last = last_call_insn ();
- add_reg_note (last, REG_CALL_DECL, datum);
+ datum = XEXP (DECL_RTL (fndecl), 0);
+ gcc_assert (datum != NULL_RTX
+ && GET_CODE (datum) == SYMBOL_REF);
}
+ last = last_call_insn ();
+ add_reg_note (last, REG_CALL_DECL, datum);
/* If the call setup or the call itself overlaps with anything
of the argument setup we probably clobbered our call address.
@@ -4804,13 +4801,10 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
struct_value_size, call_cookie, valreg,
old_inhibit_defer_pop + 1, call_fusage, flags, args_so_far);
- if (flag_ipa_ra)
- {
- rtx datum = orgfun;
- gcc_assert (GET_CODE (datum) == SYMBOL_REF);
- rtx_call_insn *last = last_call_insn ();
- add_reg_note (last, REG_CALL_DECL, datum);
- }
+ rtx datum = orgfun;
+ gcc_assert (GET_CODE (datum) == SYMBOL_REF);
+ rtx_call_insn *last = last_call_insn ();
+ add_reg_note (last, REG_CALL_DECL, datum);
/* Right-shift returned value if necessary. */
if (!pcc_struct_value
diff --git a/gcc/cobol/ChangeLog b/gcc/cobol/ChangeLog
index 44bf89f..03243e9 100644
--- a/gcc/cobol/ChangeLog
+++ b/gcc/cobol/ChangeLog
@@ -1,3 +1,16 @@
+2025-06-02 Robert Dubner <rdubner@symas.com>
+
+ PR cobol/119975
+ * genapi.cc (parser_intrinsic_call_0): Use get_time_64() function.
+ * genutil.cc (get_time_64): Definition created.
+ * genutil.h (get_time_64): Declaration created.
+
+2025-06-01 Robert Dubner <rdubner@symas.com>
+
+ PR cobol/119524
+ * gengen.cc (gg_printf): Use the new __gg__fprintf_stderr() function
+ instead of generating a call to fprintf().
+
2025-05-20 Robert Dubner <rdubner@symas.com>
James K. Lowden <jklowden@cobolworx.com>
diff --git a/gcc/cobol/genapi.cc b/gcc/cobol/genapi.cc
index 2ce9cad..5e983ab 100644
--- a/gcc/cobol/genapi.cc
+++ b/gcc/cobol/genapi.cc
@@ -10491,7 +10491,9 @@ parser_intrinsic_call_0(cbl_field_t *tgt,
{
// Pass __gg__when_compiled() the time from right now.
struct timespec tp;
- clock_gettime(CLOCK_REALTIME, &tp); // time_t tv_sec; long tv_nsec
+ uint64_t now = get_time_64();
+ tp.tv_sec = now / 1000000000;
+ tp.tv_nsec = now % 1000000000;
store_location_stuff(function_name);
gg_call(VOID,
diff --git a/gcc/cobol/gengen.cc b/gcc/cobol/gengen.cc
index 91f67d5..a5f143c 100644
--- a/gcc/cobol/gengen.cc
+++ b/gcc/cobol/gengen.cc
@@ -2152,18 +2152,6 @@ gg_printf(const char *format_string, ...)
int nargs = 0;
tree args[ARG_LIMIT];
- // Because this routine is intended for debugging, we are sending the
- // text to STDERR
-
- // Because we don't actually use stderr ourselves, we just pick it up as a
- // VOID_P and pass it along to fprintf()
- tree t_stderr = gg_declare_variable(VOID_P, "stderr",
- NULL_TREE,
- vs_external_reference);
-
- gg_push_context();
-
- args[nargs++] = t_stderr;
args[nargs++] = build_string_literal(strlen(format_string)+1, format_string);
va_list ap;
@@ -2197,7 +2185,7 @@ gg_printf(const char *format_string, ...)
static tree function = NULL_TREE;
if( !function )
{
- function = gg_get_function_address(INT, "fprintf");
+ function = gg_get_function_address(INT, "__gg__fprintf_stderr");
}
tree stmt = build_call_array_loc (location_from_lineno(),
@@ -2206,8 +2194,6 @@ gg_printf(const char *format_string, ...)
nargs,
args);
gg_append_statement(stmt);
-
- gg_pop_context();
}
tree
diff --git a/gcc/cobol/genutil.cc b/gcc/cobol/genutil.cc
index d0aaf2b3..e971043 100644
--- a/gcc/cobol/genutil.cc
+++ b/gcc/cobol/genutil.cc
@@ -2119,3 +2119,26 @@ qualified_data_location(cbl_refer_t &refer)
return gg_add(member(refer.field->var_decl_node, "data"),
refer_offset(refer));
}
+
+uint64_t
+get_time_64()
+{
+ // This code was unabashedly stolen from gcc/timevar.cc.
+ // It returns the Unix epoch with nine decimal places.
+
+ uint64_t retval = 0;
+
+#ifdef HAVE_CLOCK_GETTIME
+ struct timespec ts;
+ clock_gettime (CLOCK_REALTIME, &ts);
+ retval = ts.tv_sec * 1000000000 + ts.tv_nsec;
+ return retval;
+#endif
+#ifdef HAVE_GETTIMEOFDAY
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+ retval = tv.tv_sec * 1000000000 + tv.tv_usec * 1000;
+ return retval;
+#endif
+ return retval;
+} \ No newline at end of file
diff --git a/gcc/cobol/genutil.h b/gcc/cobol/genutil.h
index 2f4bc36..43102d7 100644
--- a/gcc/cobol/genutil.h
+++ b/gcc/cobol/genutil.h
@@ -155,4 +155,7 @@ void build_array_of_fourplets( int ngroup,
size_t N,
cbl_refer_t *refers);
void get_depending_on_value_from_odo(tree retval, cbl_field_t *odo);
+uint64_t get_time_64();
+
+
#endif
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index b7a18d5..40b43cf 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -8719,6 +8719,34 @@
(set (match_dup 1)
(minus:SWI (match_dup 1) (match_dup 0)))])])
+;; Under APX NDD, 'sub reg, mem, reg' is valid.
+;; New format for
+;; mov reg0, mem1
+;; sub reg0, mem2, reg0
+;; mov mem2, reg0
+;; to
+;; mov reg0, mem1
+;; sub mem2, reg0
+(define_peephole2
+ [(set (match_operand:SWI 0 "general_reg_operand")
+ (match_operand:SWI 1 "memory_operand"))
+ (parallel [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:SWI 2 "memory_operand")
+ (match_dup 0)))
+ (set (match_dup 0)
+ (minus:SWI (match_dup 2) (match_dup 0)))])
+ (set (match_dup 2) (match_dup 0))]
+ "TARGET_APX_NDD
+ && (TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+ && peep2_reg_dead_p (3, operands[0])
+ && !reg_overlap_mentioned_p (operands[0], operands[1])
+ && !reg_overlap_mentioned_p (operands[0], operands[2])"
+ [(set (match_dup 0) (match_dup 1))
+ (parallel [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_dup 2) (match_dup 0)))
+ (set (match_dup 2)
+ (minus:SWI (match_dup 2) (match_dup 0)))])])
+
;; decl %eax; cmpl $-1, %eax; jne .Lxx; can be optimized into
;; subl $1, %eax; jnc .Lxx;
(define_peephole2
@@ -9166,6 +9194,118 @@
(match_dup 1))
(match_dup 0)))])])
+;; Under APX NDD, 'adc reg, mem, reg' is valid.
+;;
+;; New format for
+;; mov reg0, mem1
+;; adc reg0, mem2, reg0
+;; mov mem1, reg0
+;; to
+;; mov reg0, mem2
+;; adc mem1, reg0
+(define_peephole2
+ [(set (match_operand:SWI48 0 "general_reg_operand")
+ (match_operand:SWI48 1 "memory_operand"))
+ (parallel [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extend:<DWI>
+ (plus:SWI48
+ (plus:SWI48
+ (match_operator:SWI48 5 "ix86_carry_flag_operator"
+ [(match_operand 3 "flags_reg_operand")
+ (const_int 0)])
+ (match_operand:SWI48 2 "memory_operand"))
+ (match_dup 0)))
+ (plus:<DWI>
+ (match_operator:<DWI> 4 "ix86_carry_flag_operator"
+ [(match_dup 3) (const_int 0)])
+ (zero_extend:<DWI> (match_dup 0)))))
+ (set (match_dup 0)
+ (plus:SWI48 (plus:SWI48 (match_op_dup 5
+ [(match_dup 3) (const_int 0)])
+ (match_dup 2))
+ (match_dup 0)))])
+ (set (match_dup 1) (match_dup 0))]
+ "TARGET_APX_NDD
+ && (TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+ && peep2_reg_dead_p (3, operands[0])
+ && !reg_overlap_mentioned_p (operands[0], operands[1])
+ && !reg_overlap_mentioned_p (operands[0], operands[2])"
+ [(set (match_dup 0) (match_dup 2))
+ (parallel [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extend:<DWI>
+ (plus:SWI48
+ (plus:SWI48
+ (match_op_dup 5
+ [(match_dup 3) (const_int 0)])
+ (match_dup 1))
+ (match_dup 0)))
+ (plus:<DWI>
+ (match_op_dup 4
+ [(match_dup 3) (const_int 0)])
+ (zero_extend:<DWI> (match_dup 0)))))
+ (set (match_dup 1)
+ (plus:SWI48 (plus:SWI48 (match_op_dup 5
+ [(match_dup 3) (const_int 0)])
+ (match_dup 1))
+ (match_dup 0)))])])
+
+;; New format for
+;; mov reg0, mem1
+;; adc reg0, mem2, reg0
+;; mov mem2, reg0
+;; to
+;; mov reg0, mem1
+;; adc mem2, reg0
+(define_peephole2
+ [(set (match_operand:SWI48 0 "general_reg_operand")
+ (match_operand:SWI48 1 "memory_operand"))
+ (parallel [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extend:<DWI>
+ (plus:SWI48
+ (plus:SWI48
+ (match_operator:SWI48 5 "ix86_carry_flag_operator"
+ [(match_operand 3 "flags_reg_operand")
+ (const_int 0)])
+ (match_operand:SWI48 2 "memory_operand"))
+ (match_dup 0)))
+ (plus:<DWI>
+ (match_operator:<DWI> 4 "ix86_carry_flag_operator"
+ [(match_dup 3) (const_int 0)])
+ (zero_extend:<DWI> (match_dup 0)))))
+ (set (match_dup 0)
+ (plus:SWI48 (plus:SWI48 (match_op_dup 5
+ [(match_dup 3) (const_int 0)])
+ (match_dup 2))
+ (match_dup 0)))])
+ (set (match_dup 2) (match_dup 0))]
+ "TARGET_APX_NDD
+ && (TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+ && peep2_reg_dead_p (3, operands[0])
+ && !reg_overlap_mentioned_p (operands[0], operands[1])
+ && !reg_overlap_mentioned_p (operands[0], operands[2])"
+ [(set (match_dup 0) (match_dup 1))
+ (parallel [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extend:<DWI>
+ (plus:SWI48
+ (plus:SWI48
+ (match_op_dup 5
+ [(match_dup 3) (const_int 0)])
+ (match_dup 2))
+ (match_dup 0)))
+ (plus:<DWI>
+ (match_op_dup 4
+ [(match_dup 3) (const_int 0)])
+ (zero_extend:<DWI> (match_dup 0)))))
+ (set (match_dup 2)
+ (plus:SWI48 (plus:SWI48 (match_op_dup 5
+ [(match_dup 3) (const_int 0)])
+ (match_dup 2))
+ (match_dup 0)))])])
+
(define_peephole2
[(parallel [(set (reg:CCC FLAGS_REG)
(compare:CCC
@@ -9646,6 +9786,52 @@
[(match_dup 3) (const_int 0)]))
(match_dup 0)))])])
+;; Under APX NDD, 'sbb reg, mem, reg' is valid.
+;;
+;; New format for
+;; mov reg0, mem1
+;; sbb reg0, mem2, reg0
+;; mov mem2, reg0
+;; to
+;; mov reg0, mem1
+;; sbb mem2, reg0
+(define_peephole2
+ [(set (match_operand:SWI48 0 "general_reg_operand")
+ (match_operand:SWI48 1 "memory_operand"))
+ (parallel [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extend:<DWI> (match_operand:SWI48 2 "memory_operand"))
+ (plus:<DWI>
+ (match_operator:<DWI> 4 "ix86_carry_flag_operator"
+ [(match_operand 3 "flags_reg_operand") (const_int 0)])
+ (zero_extend:<DWI>
+ (match_dup 0)))))
+ (set (match_dup 0)
+ (minus:SWI48
+ (minus:SWI48
+ (match_dup 2)
+ (match_operator:SWI48 5 "ix86_carry_flag_operator"
+ [(match_dup 3) (const_int 0)]))
+ (match_dup 0)))])
+ (set (match_dup 2) (match_dup 0))]
+ "TARGET_APX_NDD
+ && (TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+ && peep2_reg_dead_p (3, operands[0])
+ && !reg_overlap_mentioned_p (operands[0], operands[1])
+ && !reg_overlap_mentioned_p (operands[0], operands[2])"
+ [(set (match_dup 0) (match_dup 1))
+ (parallel [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extend:<DWI> (match_dup 2))
+ (plus:<DWI> (match_op_dup 4
+ [(match_dup 3) (const_int 0)])
+ (zero_extend:<DWI> (match_dup 0)))))
+ (set (match_dup 2)
+ (minus:SWI48 (minus:SWI48 (match_dup 2)
+ (match_op_dup 5
+ [(match_dup 3) (const_int 0)]))
+ (match_dup 0)))])])
+
(define_peephole2
[(set (match_operand:SWI48 6 "general_reg_operand")
(match_operand:SWI48 7 "memory_operand"))
@@ -28212,6 +28398,41 @@
const0_rtx);
})
+;; For APX NDD PLUS/MINUS/LOGIC
+;; Like cmpelim optimized pattern.
+;; Reduce an extra mov instruction like
+;; decl (%rdi), %eax
+;; mov %eax, (%rdi)
+;; to
+;; decl (%rdi)
+(define_peephole2
+ [(parallel [(set (reg FLAGS_REG)
+ (compare (match_operator:SWI 2 "plusminuslogic_operator"
+ [(match_operand:SWI 0 "memory_operand")
+ (match_operand:SWI 1 "<nonmemory_operand>")])
+ (const_int 0)))
+ (set (match_operand:SWI 3 "register_operand") (match_dup 2))])
+ (set (match_dup 0) (match_dup 3))]
+ "TARGET_APX_NDD
+ && (TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+ && peep2_reg_dead_p (2, operands[3])
+ && !reg_overlap_mentioned_p (operands[3], operands[0])
+ && ix86_match_ccmode (peep2_next_insn (0),
+ (GET_CODE (operands[2]) == PLUS
+ || GET_CODE (operands[2]) == MINUS)
+ ? CCGOCmode : CCNOmode)"
+ [(parallel [(set (match_dup 4) (match_dup 6))
+ (set (match_dup 0) (match_dup 5))])]
+{
+ operands[4] = SET_DEST (XVECEXP (PATTERN (peep2_next_insn (0)), 0, 0));
+ operands[5]
+ = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]),
+ copy_rtx (operands[0]), operands[1]);
+ operands[6]
+ = gen_rtx_COMPARE (GET_MODE (operands[4]), copy_rtx (operands[5]),
+ const0_rtx);
+})
+
;; Likewise for instances where we have a lea pattern.
(define_peephole2
[(set (match_operand:SWI 0 "register_operand")
@@ -28305,6 +28526,54 @@
const0_rtx);
})
+;; For APX NDD XOR
+;; Reduce 2 mov and 1 cmp instruction.
+;; from
+;; movq (%rdi), %rax
+;; xorq %rsi, %rax, %rdx
+;; movb %rdx, (%rdi)
+;; cmpb %rsi, %rax
+;; jne
+;; to
+;; xorb %rsi, (%rdi)
+;; jne
+(define_peephole2
+ [(set (match_operand:SWI 0 "register_operand")
+ (match_operand:SWI 1 "memory_operand"))
+ (parallel [(set (match_operand:SWI 4 "register_operand")
+ (xor:SWI (match_operand:SWI 3 "register_operand")
+ (match_operand:SWI 2 "<nonmemory_operand>")))
+ (clobber (reg:CC FLAGS_REG))])
+ (set (match_dup 1) (match_dup 4))
+ (set (reg:CCZ FLAGS_REG)
+ (compare:CCZ (match_operand:SWI 5 "register_operand")
+ (match_operand:SWI 6 "<nonmemory_operand>")))]
+ "TARGET_APX_NDD
+ && (TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+ && REGNO (operands[3]) == REGNO (operands[0])
+ && (rtx_equal_p (operands[0], operands[5])
+ ? rtx_equal_p (operands[2], operands[6])
+ : rtx_equal_p (operands[2], operands[5])
+ && rtx_equal_p (operands[0], operands[6]))
+ && peep2_reg_dead_p (3, operands[4])
+ && peep2_reg_dead_p (4, operands[0])
+ && !reg_overlap_mentioned_p (operands[0], operands[1])
+ && !reg_overlap_mentioned_p (operands[0], operands[2])
+ && (<MODE>mode != QImode
+ || immediate_operand (operands[2], QImode)
+ || any_QIreg_operand (operands[2], QImode))"
+ [(parallel [(set (match_dup 7) (match_dup 9))
+ (set (match_dup 1) (match_dup 8))])]
+{
+ operands[7] = SET_DEST (PATTERN (peep2_next_insn (3)));
+ operands[8] = gen_rtx_XOR (<MODE>mode, copy_rtx (operands[1]),
+ operands[2]);
+ operands[9]
+ = gen_rtx_COMPARE (GET_MODE (operands[7]),
+ copy_rtx (operands[8]),
+ const0_rtx);
+})
+
(define_peephole2
[(set (match_operand:SWI12 0 "register_operand")
(match_operand:SWI12 1 "memory_operand"))
@@ -28548,6 +28817,58 @@
const0_rtx);
})
+;; For APX NDD XOR
+;; Reduce 2 mov and 1 cmp instruction.
+;; from
+;; movb (%rdi), %al
+;; xorl %esi, %eax, %edx
+;; movb %dl, (%rdi)
+;; cmpb %sil, %al
+;; jne
+;; to
+;; xorl %sil, (%rdi)
+;; jne
+(define_peephole2
+ [(set (match_operand:SWI12 0 "register_operand")
+ (match_operand:SWI12 1 "memory_operand"))
+ (parallel [(set (match_operand:SI 4 "register_operand")
+ (xor:SI (match_operand:SI 3 "register_operand")
+ (match_operand:SI 2 "<nonmemory_operand>")))
+ (clobber (reg:CC FLAGS_REG))])
+ (set (match_dup 1) (match_operand:SWI12 5 "register_operand"))
+ (set (reg:CCZ FLAGS_REG)
+ (compare:CCZ (match_operand:SWI12 6 "register_operand")
+ (match_operand:SWI12 7 "<nonmemory_operand>")))]
+ "TARGET_APX_NDD
+ && (TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
+ && REGNO (operands[3]) == REGNO (operands[0])
+ && REGNO (operands[5]) == REGNO (operands[4])
+ && (rtx_equal_p (operands[0], operands[6])
+ ? (REG_P (operands[2])
+ ? REG_P (operands[7]) && REGNO (operands[2]) == REGNO (operands[7])
+ : rtx_equal_p (operands[2], operands[7]))
+ : (rtx_equal_p (operands[0], operands[7])
+ && REG_P (operands[2])
+ && REGNO (operands[2]) == REGNO (operands[6])))
+ && peep2_reg_dead_p (3, operands[5])
+ && peep2_reg_dead_p (4, operands[0])
+ && !reg_overlap_mentioned_p (operands[0], operands[1])
+ && !reg_overlap_mentioned_p (operands[0], operands[2])
+ && (<MODE>mode != QImode
+ || immediate_operand (operands[2], SImode)
+ || any_QIreg_operand (operands[2], SImode))"
+ [(parallel [(set (match_dup 8) (match_dup 10))
+ (set (match_dup 1) (match_dup 9))])]
+{
+ operands[8] = SET_DEST (PATTERN (peep2_next_insn (3)));
+ operands[9] = gen_rtx_XOR (<MODE>mode, copy_rtx (operands[1]),
+ gen_lowpart (<MODE>mode, operands[2]));
+ operands[10]
+ = gen_rtx_COMPARE (GET_MODE (operands[8]),
+ copy_rtx (operands[9]),
+ const0_rtx);
+})
+
;; Attempt to optimize away memory stores of values the memory already
;; has. See PR79593.
(define_peephole2
diff --git a/gcc/config/or1k/or1k.opt b/gcc/config/or1k/or1k.opt
index 00c5560..d252de0 100644
--- a/gcc/config/or1k/or1k.opt
+++ b/gcc/config/or1k/or1k.opt
@@ -69,8 +69,8 @@ are used to perform unordered floating point compare and set flag operations.
mcmodel=
Target RejectNegative Joined Enum(or1k_cmodel_type) Var(or1k_code_model) Init(CMODEL_SMALL)
Specify the code model used for accessing memory addresses. Specifying large
-enables generating binaries with large global offset tables. By default the
-value is small.
+enables generating binaries with large global offset tables and calling
+functions anywhere in an executable. By default the value is small.
Enum
Name(or1k_cmodel_type) Type(enum or1k_cmodel_type)
diff --git a/gcc/config/or1k/predicates.md b/gcc/config/or1k/predicates.md
index 11bb518..144f4d7 100644
--- a/gcc/config/or1k/predicates.md
+++ b/gcc/config/or1k/predicates.md
@@ -61,7 +61,8 @@
(match_test "TARGET_ROR"))))
(define_predicate "call_insn_operand"
- (ior (match_code "symbol_ref")
+ (ior (and (match_code "symbol_ref")
+ (match_test "!TARGET_CMODEL_LARGE"))
(match_operand 0 "register_operand")))
(define_predicate "high_operand"
diff --git a/gcc/config/riscv/autovec-opt.md b/gcc/config/riscv/autovec-opt.md
index a972eda..19eb16c 100644
--- a/gcc/config/riscv/autovec-opt.md
+++ b/gcc/config/riscv/autovec-opt.md
@@ -1713,3 +1713,55 @@
<MODE>mode);
}
[(set_attr "type" "vialu")])
+
+;; =============================================================================
+;; Combine vec_duplicate + op.vv to op.vf
+;; Include
+;; - vfmadd.vf
+;; - vfmsub.vf
+;; =============================================================================
+
+
+(define_insn_and_split "*<optab>_vf_<mode>"
+ [(set (match_operand:V_VLSF 0 "register_operand" "=vd")
+ (plus_minus:V_VLSF
+ (mult:V_VLSF
+ (vec_duplicate:V_VLSF
+ (match_operand:<VEL> 1 "register_operand" " f"))
+ (match_operand:V_VLSF 2 "register_operand" " 0"))
+ (match_operand:V_VLSF 3 "register_operand" " vr")))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+ {
+ rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
+ operands[2]};
+ riscv_vector::emit_vlmax_insn (code_for_pred_mul_scalar (<CODE>, <MODE>mode),
+ riscv_vector::TERNARY_OP_FRM_DYN, ops);
+ DONE;
+ }
+ [(set_attr "type" "vfmuladd")]
+)
+
+(define_insn_and_split "*<optab>_vf_<mode>"
+ [(set (match_operand:V_VLSF 0 "register_operand" "=vd")
+ (plus_minus:V_VLSF
+ (match_operand:V_VLSF 3 "register_operand" " vr")
+ (mult:V_VLSF
+ (vec_duplicate:V_VLSF
+ (match_operand:<VEL> 1 "register_operand" " f"))
+ (match_operand:V_VLSF 2 "register_operand" " 0"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+ {
+ rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
+ operands[2]};
+ riscv_vector::emit_vlmax_insn (code_for_pred_mul_scalar (<CODE>, <MODE>mode),
+ riscv_vector::TERNARY_OP_FRM_DYN, ops);
+ DONE;
+ }
+ [(set_attr "type" "vfmuladd")]
+)
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index 60c881b..c678eef 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -2493,7 +2493,8 @@
"TARGET_VECTOR"
{
insn_code icode = code_for_pred (UNSPEC_VAADD, <V_DOUBLE_TRUNC>mode);
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RDN, operands);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RDN,
+ operands);
DONE;
}
)
@@ -2527,7 +2528,8 @@
"TARGET_VECTOR"
{
insn_code icode = code_for_pred (UNSPEC_VAADDU, <MODE>mode);
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RDN, operands);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RDN,
+ operands);
DONE;
})
@@ -2540,7 +2542,8 @@
"TARGET_VECTOR"
{
insn_code icode = code_for_pred (UNSPEC_VAADDU, <MODE>mode);
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RNU, operands);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RNU,
+ operands);
DONE;
})
@@ -2565,7 +2568,8 @@
(match_operand:V_VLSF 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_ceil (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
+ riscv_vector::expand_vec_ceil (operands[0], operands[1], <MODE>mode,
+ <VCONVERT>mode);
DONE;
}
)
@@ -2575,7 +2579,8 @@
(match_operand:V_VLSF 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_floor (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
+ riscv_vector::expand_vec_floor (operands[0], operands[1], <MODE>mode,
+ <VCONVERT>mode);
DONE;
}
)
@@ -2585,7 +2590,8 @@
(match_operand:V_VLSF 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_nearbyint (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
+ riscv_vector::expand_vec_nearbyint (operands[0], operands[1], <MODE>mode,
+ <VCONVERT>mode);
DONE;
}
)
@@ -2595,7 +2601,8 @@
(match_operand:V_VLSF 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_rint (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
+ riscv_vector::expand_vec_rint (operands[0], operands[1], <MODE>mode,
+ <VCONVERT>mode);
DONE;
}
)
@@ -2605,7 +2612,8 @@
(match_operand:V_VLSF 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_round (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
+ riscv_vector::expand_vec_round (operands[0], operands[1], <MODE>mode,
+ <VCONVERT>mode);
DONE;
}
)
@@ -2615,7 +2623,8 @@
(match_operand:V_VLSF 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_trunc (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
+ riscv_vector::expand_vec_trunc (operands[0], operands[1], <MODE>mode,
+ <VCONVERT>mode);
DONE;
}
)
@@ -2625,7 +2634,8 @@
(match_operand:V_VLSF 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_roundeven (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
+ riscv_vector::expand_vec_roundeven (operands[0], operands[1], <MODE>mode,
+ <VCONVERT>mode);
DONE;
}
)
@@ -2682,7 +2692,8 @@
(match_operand:V_VLS_F_CONVERT_SI 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_lceil (operands[0], operands[1], <MODE>mode, <V_F2SI_CONVERT>mode);
+ riscv_vector::expand_vec_lceil (operands[0], operands[1], <MODE>mode,
+ <V_F2SI_CONVERT>mode);
DONE;
}
)
@@ -2692,7 +2703,8 @@
(match_operand:V_VLS_F_CONVERT_DI 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_lceil (operands[0], operands[1], <MODE>mode, <V_F2DI_CONVERT>mode);
+ riscv_vector::expand_vec_lceil (operands[0], operands[1], <MODE>mode,
+ <V_F2DI_CONVERT>mode);
DONE;
}
)
@@ -2702,7 +2714,8 @@
(match_operand:V_VLS_F_CONVERT_SI 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_lfloor (operands[0], operands[1], <MODE>mode, <V_F2SI_CONVERT>mode);
+ riscv_vector::expand_vec_lfloor (operands[0], operands[1], <MODE>mode,
+ <V_F2SI_CONVERT>mode);
DONE;
}
)
@@ -2712,7 +2725,8 @@
(match_operand:V_VLS_F_CONVERT_DI 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_lfloor (operands[0], operands[1], <MODE>mode, <V_F2DI_CONVERT>mode);
+ riscv_vector::expand_vec_lfloor (operands[0], operands[1], <MODE>mode,
+ <V_F2DI_CONVERT>mode);
DONE;
}
)
@@ -2744,7 +2758,8 @@
(match_operand:V_VLSI 2 "register_operand")]
"TARGET_VECTOR"
{
- riscv_vector::expand_vec_usadd (operands[0], operands[1], operands[2], <MODE>mode);
+ riscv_vector::expand_vec_usadd (operands[0], operands[1], operands[2],
+ <MODE>mode);
DONE;
}
)
@@ -2755,7 +2770,8 @@
(match_operand:V_VLSI 2 "register_operand")]
"TARGET_VECTOR"
{
- riscv_vector::expand_vec_ssadd (operands[0], operands[1], operands[2], <MODE>mode);
+ riscv_vector::expand_vec_ssadd (operands[0], operands[1], operands[2],
+ <MODE>mode);
DONE;
}
)
@@ -2766,7 +2782,8 @@
(match_operand:V_VLSI 2 "register_operand")]
"TARGET_VECTOR"
{
- riscv_vector::expand_vec_ussub (operands[0], operands[1], operands[2], <MODE>mode);
+ riscv_vector::expand_vec_ussub (operands[0], operands[1], operands[2],
+ <MODE>mode);
DONE;
}
)
@@ -2777,7 +2794,8 @@
(match_operand:V_VLSI 2 "register_operand")]
"TARGET_VECTOR"
{
- riscv_vector::expand_vec_sssub (operands[0], operands[1], operands[2], <MODE>mode);
+ riscv_vector::expand_vec_sssub (operands[0], operands[1], operands[2],
+ <MODE>mode);
DONE;
}
)
diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc
index 1ff1968..d2c0af3 100644
--- a/gcc/config/riscv/riscv-c.cc
+++ b/gcc/config/riscv/riscv-c.cc
@@ -239,26 +239,22 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile)
size_t max_ext_len = 0;
/* Figure out the max length of extension name for reserving buffer. */
- for (const riscv_subset_t *subset = subset_list->begin ();
- subset != subset_list->end ();
- subset = subset->next)
- max_ext_len = MAX (max_ext_len, subset->name.length ());
+ for (auto &subset : *subset_list)
+ max_ext_len = MAX (max_ext_len, subset.name.length ());
char *buf = (char *)alloca (max_ext_len + 10 /* For __riscv_ and '\0'. */);
- for (const riscv_subset_t *subset = subset_list->begin ();
- subset != subset_list->end ();
- subset = subset->next)
+ for (auto &subset : *subset_list)
{
- int version_value = riscv_ext_version_value (subset->major_version,
- subset->minor_version);
+ int version_value = riscv_ext_version_value (subset.major_version,
+ subset.minor_version);
/* Special rule for zicsr and zifencei, it's used for ISA spec 2.2 or
earlier. */
- if ((subset->name == "zicsr" || subset->name == "zifencei")
+ if ((subset.name == "zicsr" || subset.name == "zifencei")
&& version_value == 0)
version_value = riscv_ext_version_value (2, 0);
- sprintf (buf, "__riscv_%s", subset->name.c_str ());
+ sprintf (buf, "__riscv_%s", subset.name.c_str ());
builtin_define_with_int_value (buf, version_value);
}
}
diff --git a/gcc/config/riscv/riscv-ext.def b/gcc/config/riscv/riscv-ext.def
index dbda8de..2d052c1 100644
--- a/gcc/config/riscv/riscv-ext.def
+++ b/gcc/config/riscv/riscv-ext.def
@@ -1611,6 +1611,19 @@ DEFINE_RISCV_EXT(
/* EXTRA_EXTENSION_FLAGS */ 0)
DEFINE_RISCV_EXT(
+ /* NAME */ shlcofideleg,
+ /* UPPERCASE_NAME */ SHLCOFIDELEG,
+ /* FULL_NAME */ "Delegating LCOFI interrupts to VS-mode",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"h"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sh,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
/* NAME */ shtvala,
/* UPPERCAE_NAME */ SHTVALA,
/* FULL_NAME */ "The htval register provides all needed values",
@@ -1676,6 +1689,19 @@ DEFINE_RISCV_EXT(
/* EXTRA_EXTENSION_FLAGS */ 0)
DEFINE_RISCV_EXT(
+ /* NAME */ smcntrpmf,
+ /* UPPERCAE_NAME */ SMCNTRPMF,
+ /* FULL_NAME */ "Cycle and instret privilege mode filtering",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sm,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
/* NAME */ smepmp,
/* UPPERCAE_NAME */ SMEPMP,
/* FULL_NAME */ "PMP Enhancements for memory access and execution prevention on Machine mode",
diff --git a/gcc/config/riscv/riscv-ext.opt b/gcc/config/riscv/riscv-ext.opt
index 5e9c5f5..e0314430f 100644
--- a/gcc/config/riscv/riscv-ext.opt
+++ b/gcc/config/riscv/riscv-ext.opt
@@ -325,6 +325,8 @@ Mask(SHCOUNTERENW) Var(riscv_sh_subext)
Mask(SHGATPA) Var(riscv_sh_subext)
+Mask(SHLCOFIDELEG) Var(riscv_sh_subext)
+
Mask(SHTVALA) Var(riscv_sh_subext)
Mask(SHVSTVALA) Var(riscv_sh_subext)
@@ -335,6 +337,8 @@ Mask(SHVSATPA) Var(riscv_sh_subext)
Mask(SMAIA) Var(riscv_sm_subext)
+Mask(SMCNTRPMF) Var(riscv_sm_subext)
+
Mask(SMEPMP) Var(riscv_sm_subext)
Mask(SMMPM) Var(riscv_sm_subext)
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index c02c599..e1a820b 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -164,6 +164,7 @@ enum riscv_tls_type {
(TARGET_VECTOR && riscv_mautovec_segment)
#define GPR2VR_COST_UNPROVIDED -1
+#define FPR2VR_COST_UNPROVIDED -1
/* Extra extension flags, used for carry extra info for a RISC-V extension. */
enum
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index d8c8f6b..a033120 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -841,6 +841,7 @@ const struct riscv_tune_info *
riscv_parse_tune (const char *, bool);
const cpu_vector_cost *get_vector_costs ();
int get_gr2vr_cost ();
+int get_fr2vr_cost ();
enum
{
diff --git a/gcc/config/riscv/riscv-subset.h b/gcc/config/riscv/riscv-subset.h
index c5d9fab..a35537d 100644
--- a/gcc/config/riscv/riscv-subset.h
+++ b/gcc/config/riscv/riscv-subset.h
@@ -109,9 +109,6 @@ public:
static riscv_subset_list *parse (const char *, location_t);
const char *parse_single_ext (const char *, bool exact_single_p = true);
- const riscv_subset_t *begin () const {return m_head;};
- const riscv_subset_t *end () const {return NULL;};
-
int match_score (riscv_subset_list *) const;
void set_loc (location_t);
@@ -119,6 +116,65 @@ public:
void set_allow_adding_dup (bool v) { m_allow_adding_dup = v; }
void finalize ();
+
+ class iterator
+ {
+ public:
+ explicit iterator(riscv_subset_t *node) : m_node(node) {}
+
+ riscv_subset_t &operator*() const { return *m_node; }
+ riscv_subset_t *operator->() const { return m_node; }
+
+ iterator &operator++()
+ {
+ if (m_node)
+ m_node = m_node->next;
+ return *this;
+ }
+
+ bool operator!=(const iterator &other) const
+ {
+ return m_node != other.m_node;
+ }
+
+ bool operator==(const iterator &other) const
+ {
+ return m_node == other.m_node;
+ }
+
+ private:
+ riscv_subset_t *m_node;
+ };
+
+ iterator begin() { return iterator(m_head); }
+ iterator end() { return iterator(nullptr); }
+
+ class const_iterator
+ {
+ public:
+ explicit const_iterator(const riscv_subset_t *node) : m_node(node) {}
+
+ const riscv_subset_t &operator*() const { return *m_node; }
+ const riscv_subset_t *operator->() const { return m_node; }
+
+ const_iterator &operator++()
+ {
+ if (m_node)
+ m_node = m_node->next;
+ return *this;
+ }
+
+ bool operator!=(const const_iterator &other) const
+ {
+ return m_node != other.m_node;
+ }
+
+ private:
+ const riscv_subset_t *m_node;
+ };
+
+ const_iterator begin() const { return const_iterator(m_head); }
+ const_iterator end() const { return const_iterator(nullptr); }
};
extern const riscv_subset_list *riscv_cmdline_subset_list (void);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 6162797..a41317f 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -5567,6 +5567,7 @@ expand_vx_binary_vec_vec_dup (rtx op_0, rtx op_1, rtx op_2,
case IOR:
case XOR:
case MULT:
+ case DIV:
icode = code_for_pred_scalar (code, mode);
break;
default:
diff --git a/gcc/config/riscv/riscv-vector-costs.cc b/gcc/config/riscv/riscv-vector-costs.cc
index a39b611..4d8170d 100644
--- a/gcc/config/riscv/riscv-vector-costs.cc
+++ b/gcc/config/riscv/riscv-vector-costs.cc
@@ -1099,8 +1099,8 @@ costs::adjust_stmt_cost (enum vect_cost_for_stmt kind, loop_vec_info loop,
switch (kind)
{
case scalar_to_vec:
- stmt_cost += (FLOAT_TYPE_P (vectype) ? costs->regmove->FR2VR
- : get_gr2vr_cost ());
+ stmt_cost
+ += (FLOAT_TYPE_P (vectype) ? get_fr2vr_cost () : get_gr2vr_cost ());
break;
case vec_to_scalar:
stmt_cost += (FLOAT_TYPE_P (vectype) ? costs->regmove->VR2FR
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index d3cee96..3254ec9 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3891,6 +3891,25 @@ riscv_extend_cost (rtx op, bool unsigned_p)
return COSTS_N_INSNS (2);
}
+/* Return the cost of the vector binary rtx like add, minus, mult.
+ The cost of scalar2vr_cost will be appended if there one of the
+ op comes from the VEC_DUPLICATE. */
+
+static int
+get_vector_binary_rtx_cost (rtx x, int scalar2vr_cost)
+{
+ gcc_assert (riscv_v_ext_mode_p (GET_MODE (x)));
+
+ rtx op_0 = XEXP (x, 0);
+ rtx op_1 = XEXP (x, 1);
+
+ if (GET_CODE (op_0) == VEC_DUPLICATE
+ || GET_CODE (op_1) == VEC_DUPLICATE)
+ return (scalar2vr_cost + 1) * COSTS_N_INSNS (1);
+ else
+ return COSTS_N_INSNS (1);
+}
+
/* Implement TARGET_RTX_COSTS. */
#define SINGLE_SHIFT_COST 1
@@ -3904,6 +3923,9 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
if (riscv_v_ext_mode_p (mode))
{
int gr2vr_cost = get_gr2vr_cost ();
+ int fr2vr_cost = get_fr2vr_cost ();
+ int scalar2vr_cost = FLOAT_MODE_P (GET_MODE_INNER (mode))
+ ? fr2vr_cost : gr2vr_cost;
switch (outer_code)
{
@@ -3914,6 +3936,21 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
case VEC_DUPLICATE:
*total = gr2vr_cost * COSTS_N_INSNS (1);
break;
+ case IF_THEN_ELSE:
+ {
+ rtx op = XEXP (x, 1);
+
+ switch (GET_CODE (op))
+ {
+ case DIV:
+ *total = get_vector_binary_rtx_cost (op, scalar2vr_cost);
+ break;
+ default:
+ *total = COSTS_N_INSNS (1);
+ break;
+ }
+ }
+ break;
case PLUS:
case MINUS:
case AND:
@@ -3921,14 +3958,15 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
case XOR:
case MULT:
{
+ rtx op;
rtx op_0 = XEXP (x, 0);
rtx op_1 = XEXP (x, 1);
- if (GET_CODE (op_0) == VEC_DUPLICATE
- || GET_CODE (op_1) == VEC_DUPLICATE)
- *total = (gr2vr_cost + 1) * COSTS_N_INSNS (1);
+ if (GET_CODE (op = op_0) == MULT
+ || GET_CODE (op = op_1) == MULT)
+ *total = get_vector_binary_rtx_cost (op, scalar2vr_cost);
else
- *total = COSTS_N_INSNS (1);
+ *total = get_vector_binary_rtx_cost (x, scalar2vr_cost);
}
break;
default:
@@ -9781,7 +9819,7 @@ riscv_register_move_cost (machine_mode mode,
if (from_is_gpr)
return get_gr2vr_cost ();
else if (from_is_fpr)
- return get_vector_costs ()->regmove->FR2VR;
+ return get_fr2vr_cost ();
}
return riscv_secondary_memory_needed (mode, from, to) ? 8 : 2;
@@ -12647,6 +12685,21 @@ get_gr2vr_cost ()
return cost;
}
+/* Return the cost of moving data from floating-point to vector register.
+ It will take the value of --param=fpr2vr-cost if it is provided.
+ Otherwise the default regmove->FR2VR will be returned. */
+
+int
+get_fr2vr_cost ()
+{
+ int cost = get_vector_costs ()->regmove->FR2VR;
+
+ if (fpr2vr_cost != FPR2VR_COST_UNPROVIDED)
+ cost = fpr2vr_cost;
+
+ return cost;
+}
+
/* Implement targetm.vectorize.builtin_vectorization_cost. */
static int
@@ -12712,8 +12765,7 @@ riscv_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
case vec_construct:
{
/* TODO: This is too pessimistic in case we can splat. */
- int regmove_cost = fp ? costs->regmove->FR2VR
- : get_gr2vr_cost ();
+ int regmove_cost = fp ? get_fr2vr_cost () : get_gr2vr_cost ();
return (regmove_cost + common_costs->scalar_to_vec_cost)
* estimated_poly_value (TYPE_VECTOR_SUBPARTS (vectype));
}
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index b2b9d33..6543fd1 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -286,6 +286,10 @@ Max number of bytes to compare as part of inlined strcmp/strncmp routines (defau
Target RejectNegative Joined UInteger Var(gpr2vr_cost) Init(GPR2VR_COST_UNPROVIDED)
Set the cost value of the rvv instruction when operate from GPR to VR.
+-param=fpr2vr-cost=
+Target RejectNegative Joined UInteger Var(fpr2vr_cost) Init(FPR2VR_COST_UNPROVIDED)
+Set the cost value of the rvv instruction when operate from FPR to VR.
+
-param=riscv-autovec-mode=
Target Undocumented RejectNegative Joined Var(riscv_autovec_mode) Save
Set the only autovec mode to try.
diff --git a/gcc/config/riscv/t-riscv b/gcc/config/riscv/t-riscv
index 854daa9..32092d8 100644
--- a/gcc/config/riscv/t-riscv
+++ b/gcc/config/riscv/t-riscv
@@ -198,19 +198,24 @@ RISCV_EXT_DEFS = \
$(srcdir)/config/riscv/riscv-ext.opt: $(RISCV_EXT_DEFS)
-build/gen-riscv-ext-opt$(build_exeext): $(srcdir)/config/riscv/gen-riscv-ext-opt.cc \
+build/gen-riscv-ext-opt.o: $(srcdir)/config/riscv/gen-riscv-ext-opt.cc \
$(RISCV_EXT_DEFS)
- $(CXX_FOR_BUILD) $(CXXFLAGS_FOR_BUILD) $< -o $@
+ $(CXX_FOR_BUILD) $(CXXFLAGS_FOR_BUILD) -c $< -o $@
+
+build/gen-riscv-ext-opt$(build_exeext): build/gen-riscv-ext-opt.o
+ $(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) -o $@ $<
s-riscv-ext.opt: build/gen-riscv-ext-opt$(build_exeext)
$(RUN_GEN) build/gen-riscv-ext-opt$(build_exeext) > tmp-riscv-ext.opt
$(SHELL) $(srcdir)/../move-if-change tmp-riscv-ext.opt $(srcdir)/config/riscv/riscv-ext.opt
$(STAMP) s-riscv-ext.opt
-build/gen-riscv-ext-texi$(build_exeext): $(srcdir)/config/riscv/gen-riscv-ext-texi.cc \
+build/gen-riscv-ext-texi.o: $(srcdir)/config/riscv/gen-riscv-ext-texi.cc \
$(RISCV_EXT_DEFS)
- $(CXX_FOR_BUILD) $(CXXFLAGS_FOR_BUILD) $< -o $@
+ $(CXX_FOR_BUILD) $(CXXFLAGS_FOR_BUILD) -c $< -o $@
+build/gen-riscv-ext-texi$(build_exeext): build/gen-riscv-ext-texi.o
+ $(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) -o $@ $<
$(srcdir)/doc/riscv-ext.texi: $(RISCV_EXT_DEFS)
$(srcdir)/doc/riscv-ext.texi: s-riscv-ext.texi ; @true
diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md
index 2bd99ee..62fd1c0 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -4042,7 +4042,7 @@
])
(define_code_iterator any_int_binop_no_shift_vx [
- plus minus and ior xor mult
+ plus minus and ior xor mult div
])
(define_code_iterator any_int_unop [neg not])
diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index e03dee3..a9d67a5 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -48,7 +48,6 @@ along with GCC; see the file COPYING3. If not see
#include "alias.h"
#include "explow.h"
#include "expr.h"
-#include "reload.h"
#include "langhooks.h"
#include "gimplify.h"
#include "builtins.h"
@@ -197,6 +196,8 @@ static void xtensa_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
tree function);
static rtx xtensa_delegitimize_address (rtx);
+static reg_class_t xtensa_ira_change_pseudo_allocno_class (int, reg_class_t,
+ reg_class_t);
@@ -366,6 +367,9 @@ static rtx xtensa_delegitimize_address (rtx);
#undef TARGET_DIFFERENT_ADDR_DISPLACEMENT_P
#define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
+#undef TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS
+#define TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS xtensa_ira_change_pseudo_allocno_class
+
struct gcc_target targetm = TARGET_INITIALIZER;
@@ -4432,12 +4436,10 @@ xtensa_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
&& reg_class_subset_p (to, AR_REGS)))
return 2;
- /* The cost between AR_REGS and FR_REGS must be <= 8 (2x the default
- MEMORY_MOVE_COST) to avoid unwanted spills, and > 4 (2x the above
- case) to avoid excessive register-to-register moves. */
+ /* The cost between AR_REGS and FR_REGS is 2 (the default value). */
if ((reg_class_subset_p (from, AR_REGS) && to == FP_REGS)
|| (from == FP_REGS && reg_class_subset_p (to, AR_REGS)))
- return 5;
+ return 2;
if ((reg_class_subset_p (from, AR_REGS) && to == ACC_REG)
|| (from == ACC_REG && reg_class_subset_p (to, AR_REGS)))
@@ -5433,4 +5435,20 @@ xtensa_delegitimize_address (rtx op)
return op;
}
+/* Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS, in order to tell
+ the register allocator to avoid using ALL_REGS rclass. */
+
+static reg_class_t
+xtensa_ira_change_pseudo_allocno_class (int regno, reg_class_t allocno_class,
+ reg_class_t best_class)
+{
+ if (allocno_class != ALL_REGS)
+ return allocno_class;
+
+ if (best_class != ALL_REGS)
+ return best_class;
+
+ return FLOAT_MODE_P (PSEUDO_REGNO_MODE (regno)) ? FP_REGS : AR_REGS;
+}
+
#include "gt-xtensa.h"
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 88f011c..c7ac456 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -1453,7 +1453,7 @@
})
(define_insn "movsf_internal"
- [(set (match_operand:SF 0 "nonimmed_operand" "=f,f,^U,D,a,D,R,a,f,a,a,W,a,U")
+ [(set (match_operand:SF 0 "nonimmed_operand" "=f,f,U,D,a,D,R,a,f,a,a,W,a,U")
(match_operand:SF 1 "move_operand" "f,^U,f,d,T,R,d,r,r,f,Y,iF,U,r"))]
"((register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode))
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9e425ab..524aa55 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,119 @@
+2025-06-03 Jason Merrill <jason@redhat.com>
+
+ * name-lookup.h (operator|, operator|=): Define for WMB_Flags.
+
+2025-06-02 Jason Merrill <jason@redhat.com>
+
+ PR c++/107600
+ * method.cc (destructible_expr): Fix refs and arrays of unknown
+ bound.
+
+2025-06-02 Jason Merrill <jason@redhat.com>
+
+ PR c++/120506
+ * constexpr.cc (cxx_eval_outermost_constant_expr): Always check
+ CONSTRUCTOR_NO_CLEARING.
+
+2025-06-02 Iain Sandoe <iain@sandoe.co.uk>
+
+ * coroutines.cc (build_actor_fn): Remove an unused
+ label, guard the frame deallocation correctly, use
+ simpler APIs to build if and return statements.
+
+2025-06-02 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/118903
+ * constexpr.cc (potential_constant_expression_1): Emit
+ an error when co_await et. al. are used in constexpr
+ contexts.
+
+2025-06-02 Iain Sandoe <iain@sandoe.co.uk>
+
+ * error.cc (dump_expr): Add co_await, co_yield and co_return.
+
+2025-06-02 Jason Merrill <jason@redhat.com>
+
+ PR c++/107600
+ * method.cc (destructible_expr): Handle non-classes.
+ (constructible_expr): Check for abstract class here...
+ (is_xible_helper): ...not here.
+
+2025-06-02 Jason Merrill <jason@redhat.com>
+
+ PR c++/107600
+ * semantics.cc (trait_expr_value) [CPTK_HAS_TRIVIAL_DESTRUCTOR]:
+ Add cp_unevaluated.
+
+2025-06-02 Sandra Loosemore <sloosemore@baylibre.com>
+
+ * cp-tree.h (maybe_convert_cond): Declare.
+ * parser.cc (cp_parser_omp_context_selector): Call
+ maybe_convert_cond and fold_build_cleanup_point_expr on the
+ expression for OMP_TRAIT_PROPERTY_BOOL_EXPR.
+ * pt.cc (tsubst_omp_context_selector): Likewise.
+ * semantics.cc (maybe_convert_cond): Remove static declaration.
+
+2025-05-30 Jason Merrill <jason@redhat.com>
+
+ PR c++/113563
+ * lambda.cc (lambda_capture_field_type): Handle 'this' normally.
+ (build_capture_proxy): Special-case 'this' by-ref capture more.
+ (nonlambda_method_basetype): Look through xobj lambdas.
+
+2025-05-30 Julian Brown <julian@codesourcery.com>
+ Tobias Burnus <tburnus@baylibre.com>
+
+ * constexpr.cc (reduced_constant_expression_p): Add OMP_DECLARE_MAPPER
+ case.
+ (cxx_eval_constant_expression, potential_constant_expression_1):
+ Likewise.
+ * cp-gimplify.cc (cxx_omp_finish_mapper_clauses): New function.
+ * cp-objcp-common.h (LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES,
+ LANG_HOOKS_OMP_MAPPER_LOOKUP, LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE,
+ LANG_HOOKS_OMP_MAP_ARRAY_SECTION): Define langhooks.
+ * cp-tree.h (lang_decl_base): Add omp_declare_mapper_p field. Recount
+ spare bits comment.
+ (DECL_OMP_DECLARE_MAPPER_P): New macro.
+ (omp_mapper_id): Add prototype.
+ (cp_check_omp_declare_mapper): Add prototype.
+ (omp_instantiate_mappers): Add prototype.
+ (cxx_omp_finish_mapper_clauses): Add prototype.
+ (cxx_omp_mapper_lookup): Add prototype.
+ (cxx_omp_extract_mapper_directive): Add prototype.
+ (cxx_omp_map_array_section): Add prototype.
+ * decl.cc (check_initializer): Add OpenMP declare mapper support.
+ (cp_finish_decl): Set DECL_INITIAL for OpenMP declare mapper var decls
+ as appropriate.
+ * decl2.cc (mark_used): Instantiate OpenMP "declare mapper" magic var
+ decls.
+ * error.cc (dump_omp_declare_mapper): New function.
+ (dump_simple_decl): Use above.
+ * parser.cc (cp_parser_omp_clause_map): Add KIND parameter. Support
+ "mapper" modifier.
+ (cp_parser_omp_all_clauses): Add KIND argument to
+ cp_parser_omp_clause_map call.
+ (cp_parser_omp_target): Call omp_instantiate_mappers before
+ finish_omp_clauses.
+ (cp_parser_omp_declare_mapper): New function.
+ (cp_parser_omp_declare): Add "declare mapper" support.
+ * pt.cc (tsubst_decl): Adjust name of "declare mapper" magic var decls
+ once we know their type.
+ (tsubst_omp_clauses): Call omp_instantiate_mappers before
+ finish_omp_clauses, for target regions.
+ (tsubst_expr): Support OMP_DECLARE_MAPPER nodes.
+ (instantiate_decl): Instantiate initialiser (i.e definition) for OpenMP
+ declare mappers.
+ * semantics.cc (gimplify.h): Include.
+ (omp_mapper_id, omp_mapper_lookup, omp_extract_mapper_directive,
+ cxx_omp_map_array_section, cp_check_omp_declare_mapper): New functions.
+ (finish_omp_clauses): Delete GOMP_MAP_PUSH_MAPPER_NAME and
+ GOMP_MAP_POP_MAPPER_NAME artificial clauses.
+ (omp_target_walk_data): Add MAPPERS field.
+ (finish_omp_target_clauses_r): Scan for uses of struct/union/class type
+ variables.
+ (finish_omp_target_clauses): Create artificial mapper binding clauses
+ for used structs/unions/classes in offload region.
+
2025-05-29 David Malcolm <dmalcolm@redhat.com>
* error.cc (cxx_format_postprocessor::clone): Update to use
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 61481c6..b9fdc94 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -9278,8 +9278,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
/* After verify_constant because reduced_constant_expression_p can unset
CONSTRUCTOR_NO_CLEARING. */
- if (!non_constant_p
- && 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 "
@@ -11024,6 +11023,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case CO_AWAIT_EXPR:
case CO_YIELD_EXPR:
case CO_RETURN_EXPR:
+ if (flags & tf_error)
+ constexpr_error (cp_expr_loc_or_loc (t, input_location), fundef_p,
+ "%qE is not a constant expression", t);
return false;
/* Assume a TU-local entity is not constant, we'll error later when
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 5815a8c..7f5d30c 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -2543,8 +2543,8 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
/* Finish the resume dispatcher. */
finish_switch_stmt (dispatcher);
- finish_else_clause (lsb_if);
+ finish_else_clause (lsb_if);
finish_if_stmt (lsb_if);
/* If we reach here then we've hit UB. */
@@ -2583,69 +2583,53 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
/* Add in our function body with the co_returns rewritten to final form. */
add_stmt (fnbody);
- /* now do the tail of the function. */
+ /* Now do the tail of the function; first cleanups. */
r = build_stmt (loc, LABEL_EXPR, del_promise_label);
add_stmt (r);
- /* Destructors for the things we built explicitly. */
+ /* Destructors for the things we built explicitly.
+ promise... */
if (tree c = cxx_maybe_build_cleanup (promise_proxy, tf_warning_or_error))
- add_stmt (c);
-
- tree del_frame_label
- = create_named_label_with_ctx (loc, "coro.delete.frame", actor);
- r = build_stmt (loc, LABEL_EXPR, del_frame_label);
- add_stmt (r);
-
- /* Here deallocate the frame (if we allocated it), which we will have at
- present. */
- tree fnf2_x
- = coro_build_frame_access_expr (actor_frame, coro_frame_needs_free_id,
- false, tf_warning_or_error);
+ finish_expr_stmt (c);
- tree need_free_if = begin_if_stmt ();
- fnf2_x = build1 (CONVERT_EXPR, integer_type_node, fnf2_x);
- tree cmp = build2 (NE_EXPR, integer_type_node, fnf2_x, integer_zero_node);
- finish_if_stmt_cond (cmp, need_free_if);
+ /* Argument copies ... */
while (!param_dtor_list->is_empty ())
{
tree parm_id = param_dtor_list->pop ();
tree a = coro_build_frame_access_expr (actor_frame, parm_id, false,
tf_warning_or_error);
if (tree dtor = cxx_maybe_build_cleanup (a, tf_warning_or_error))
- add_stmt (dtor);
+ finish_expr_stmt (dtor);
}
+ /* Here deallocate the frame (if we allocated it), which we will have at
+ present. */
+ tree fnf2_x
+ = coro_build_frame_access_expr (actor_frame, coro_frame_needs_free_id,
+ false, tf_warning_or_error);
+ tree need_free_if = begin_if_stmt ();
+ finish_if_stmt_cond (fnf2_x, need_free_if);
+
/* Build the frame DTOR. */
tree del_coro_fr
= build_coroutine_frame_delete_expr (actor_fp, frame_size,
promise_type, loc);
finish_expr_stmt (del_coro_fr);
finish_then_clause (need_free_if);
- tree scope = IF_SCOPE (need_free_if);
- IF_SCOPE (need_free_if) = NULL;
- r = do_poplevel (scope);
- add_stmt (r);
+ finish_if_stmt (need_free_if);
- /* done. */
- r = build_stmt (loc, RETURN_EXPR, NULL);
- suppress_warning (r); /* We don't want a warning about this. */
- r = maybe_cleanup_point_expr_void (r);
- add_stmt (r);
+ /* Done. */
+ finish_return_stmt (NULL_TREE);
/* This is the suspend return point. */
- r = build_stmt (loc, LABEL_EXPR, ret_label);
- add_stmt (r);
+ add_stmt (build_stmt (loc, LABEL_EXPR, ret_label));
- r = build_stmt (loc, RETURN_EXPR, NULL);
- suppress_warning (r); /* We don't want a warning about this. */
- r = maybe_cleanup_point_expr_void (r);
- add_stmt (r);
+ finish_return_stmt (NULL_TREE);
/* This is the 'continuation' return point. For such a case we have a coro
handle (from the await_suspend() call) and we want handle.resume() to
execute as a tailcall allowing arbitrary chaining of coroutines. */
- r = build_stmt (loc, LABEL_EXPR, continue_label);
- add_stmt (r);
+ add_stmt (build_stmt (loc, LABEL_EXPR, continue_label));
/* Should have been set earlier by the coro_initialized code. */
gcc_assert (void_coro_handle_address);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e5e20e1..3cf4a76 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7956,6 +7956,7 @@ extern bool perform_deferred_access_checks (tsubst_flags_t);
extern bool perform_or_defer_access_check (tree, tree, tree,
tsubst_flags_t,
access_failure_info *afi = NULL);
+extern tree maybe_convert_cond (tree);
/* RAII sentinel to ensures that deferred access checks are popped before
a function returns. */
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 6364345..69da381 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -3269,6 +3269,27 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
break;
}
+ case CO_AWAIT_EXPR:
+ pp_cxx_ws_string (pp, "co_await");
+ pp_cxx_whitespace (pp);
+ dump_expr (pp, TREE_OPERAND (t, 0), flags);
+ break;
+
+ case CO_YIELD_EXPR:
+ pp_cxx_ws_string (pp, "co_yield");
+ pp_cxx_whitespace (pp);
+ dump_expr (pp, TREE_OPERAND (t, 0), flags);
+ break;
+
+ case CO_RETURN_EXPR:
+ pp_cxx_ws_string (pp, "co_return");
+ if (TREE_OPERAND (t, 0))
+ {
+ pp_cxx_whitespace (pp);
+ dump_expr (pp, TREE_OPERAND (t, 0), flags);
+ }
+ break;
+
/* This list is incomplete, but should suffice for now.
It is very important that `sorry' does not call
`report_error_function'. That could cause an infinite loop. */
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 3a675d9..67a80a3 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -2251,6 +2251,8 @@ constructible_expr (tree to, tree from)
const int len = TREE_VEC_LENGTH (from);
if (CLASS_TYPE_P (to))
{
+ if (ABSTRACT_CLASS_TYPE_P (to))
+ return error_mark_node;
tree ctype = to;
vec<tree, va_gc> *args = NULL;
if (!TYPE_REF_P (to))
@@ -2330,17 +2332,35 @@ constructible_expr (tree to, tree from)
return expr;
}
-/* Return declval<T>().~T() treated as an unevaluated operand. */
+/* Valid if "Either T is a reference type, or T is a complete object type for
+ which the expression declval<U&>().~U() is well-formed when treated as an
+ unevaluated operand ([expr.context]), where U is remove_all_extents_t<T>."
+
+ For a class U, return the destructor call; otherwise return void_node if
+ valid or error_mark_node if not. */
static tree
destructible_expr (tree to)
{
cp_unevaluated cp_uneval_guard;
int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
- to = build_trait_object (to);
- tree r = build_delete (input_location, TREE_TYPE (to), to,
- sfk_complete_destructor, flags, 0, tf_none);
- return r;
+ if (TYPE_REF_P (to))
+ return void_node;
+ if (!COMPLETE_TYPE_P (complete_type (to)))
+ return error_mark_node;
+ to = strip_array_types (to);
+ if (CLASS_TYPE_P (to))
+ {
+ to = build_trait_object (to);
+ return build_delete (input_location, TREE_TYPE (to), to,
+ sfk_complete_destructor, flags, 0, tf_none);
+ }
+ /* [expr.prim.id.dtor] If the id-expression names a pseudo-destructor, T
+ shall be a scalar type.... */
+ else if (scalarish_type_p (to))
+ return void_node;
+ else
+ return error_mark_node;
}
/* Returns a tree iff TO is assignable (if CODE is MODIFY_EXPR) or
@@ -2352,7 +2372,7 @@ is_xible_helper (enum tree_code code, tree to, tree from, bool trivial)
{
to = complete_type (to);
deferring_access_check_sentinel acs (dk_no_deferred);
- if (VOID_TYPE_P (to) || ABSTRACT_CLASS_TYPE_P (to)
+ if (VOID_TYPE_P (to)
|| (from && FUNC_OR_METHOD_TYPE_P (from)
&& (TYPE_READONLY (from) || FUNCTION_REF_QUALIFIED (from))))
return error_mark_node;
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index 4216a51..2fa736b 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -501,6 +501,10 @@ enum WMB_Flags
WMB_Hidden = 1 << 3,
WMB_Purview = 1 << 4,
};
+inline WMB_Flags operator|(WMB_Flags x, WMB_Flags y)
+{ return WMB_Flags(+x|y); }
+inline WMB_Flags& operator|=(WMB_Flags& x, WMB_Flags y)
+{ return x = x|y; }
extern unsigned walk_module_binding (tree binding, bitmap partitions,
bool (*)(tree decl, WMB_Flags, void *data),
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 3d30339..8633763 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -49986,12 +49986,25 @@ cp_parser_omp_context_selector (cp_parser *parser, enum omp_tss_code set,
&& !value_dependent_expression_p (t))
{
t = fold_non_dependent_expr (t);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
{
- error_at (token->location,
- "property must be integer expression");
- return error_mark_node;
+ t = maybe_convert_cond (t);
+ if (t == error_mark_node)
+ return error_mark_node;
+ }
+ else
+ {
+ t = convert_from_reference (t);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error_at (token->location,
+ "property must be integer expression");
+ return error_mark_node;
+ }
}
+ if (!processing_template_decl
+ && TREE_CODE (t) != CLEANUP_POINT_EXPR)
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
}
properties = make_trait_property (NULL_TREE, t, properties);
break;
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ccb623d..c5a3abe 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -18380,7 +18380,9 @@ tsubst_omp_context_selector (tree ctx, tree args, tsubst_flags_t complain,
}
}
- switch (omp_ts_map[OMP_TS_CODE (sel)].tp_type)
+ enum omp_tp_type property_kind
+ = omp_ts_map[OMP_TS_CODE (sel)].tp_type;
+ switch (property_kind)
{
case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
case OMP_TRAIT_PROPERTY_BOOL_EXPR:
@@ -18388,12 +18390,26 @@ tsubst_omp_context_selector (tree ctx, tree args, tsubst_flags_t complain,
args, complain, in_decl);
t = fold_non_dependent_expr (t);
if (!value_dependent_expression_p (t)
- && !type_dependent_expression_p (t)
- && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
- error_at (cp_expr_loc_or_input_loc (t),
- "property must be integer expression");
- else
- properties = make_trait_property (NULL_TREE, t, NULL_TREE);
+ && !type_dependent_expression_p (t))
+ {
+ if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
+ t = maybe_convert_cond (t);
+ else
+ {
+ t = convert_from_reference (t);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error_at (cp_expr_loc_or_input_loc (t),
+ "property must be integer expression");
+ t = error_mark_node;
+ }
+ }
+ }
+ if (t != error_mark_node
+ && !processing_template_decl
+ && TREE_CODE (t) != CLEANUP_POINT_EXPR)
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ properties = make_trait_property (NULL_TREE, t, NULL_TREE);
break;
case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
if (OMP_TS_CODE (sel) == OMP_TRAIT_CONSTRUCT_SIMD)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index cafc9d0..7bc346b 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -52,7 +52,6 @@ along with GCC; see the file COPYING3. If not see
during template instantiation, which may be regarded as a
degenerate form of parsing. */
-static tree maybe_convert_cond (tree);
static tree finalize_nrv_r (tree *, int *, void *);
/* Used for OpenMP non-static data member privatization. */
@@ -1117,7 +1116,7 @@ annotate_saver::restore (tree new_inner)
statement. Convert it to a boolean value, if appropriate.
In addition, verify sequence points if -Wsequence-point is enabled. */
-static tree
+tree
maybe_convert_cond (tree cond)
{
/* Empty conditions remain empty. */
@@ -13420,6 +13419,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
if (CLASS_TYPE_P (type1) && type_build_dtor_call (type1))
{
deferring_access_check_sentinel dacs (dk_no_check);
+ cp_unevaluated un;
tree fn = get_dtor (type1, tf_none);
if (!fn && !seen_error ())
warning (0, "checking %qs for type %qT with a destructor that "
diff --git a/gcc/diagnostic-format-html.cc b/gcc/diagnostic-format-html.cc
index c430bda..05d4273 100644
--- a/gcc/diagnostic-format-html.cc
+++ b/gcc/diagnostic-format-html.cc
@@ -511,6 +511,10 @@ static const char * const HTML_STYLE
" box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.5); }\n"
" .frame-funcname { text-align: right;\n"
" font-style: italic; } \n"
+ " .highlight-a { color: #703fec;\n" // pf-purple-400
+ " font-weight: bold; }\n"
+ " .highlight-b { color: #3f9c35;\n" // pf-green-400
+ " font-weight: bold; }\n"
" </style>\n");
/* A little JavaScript for ease of navigation.
@@ -725,8 +729,15 @@ html_builder::make_element_for_diagnostic (const diagnostic_info &diagnostic,
break;
case pp_token::kind::begin_color:
+ {
+ pp_token_begin_color *sub = as_a <pp_token_begin_color *> (iter);
+ gcc_assert (sub->m_value.get ());
+ m_xp.push_tag_with_class ("span", sub->m_value.get ());
+ }
+ break;
+
case pp_token::kind::end_color:
- /* These are no-ops. */
+ m_xp.pop_tag ();
break;
case pp_token::kind::begin_quote:
diff --git a/gcc/diagnostic-show-locus.cc b/gcc/diagnostic-show-locus.cc
index c6a0cd8..3654102 100644
--- a/gcc/diagnostic-show-locus.cc
+++ b/gcc/diagnostic-show-locus.cc
@@ -539,8 +539,10 @@ struct to_html
friend class layout_printer<to_html>;
to_html (xml::printer &xp,
+ const rich_location *richloc,
html_label_writer *html_label_writer)
: m_xp (xp),
+ m_richloc (richloc),
m_html_label_writer (html_label_writer)
{}
@@ -620,11 +622,6 @@ struct to_html
// no-op for HTML
}
- void colorize_text_for_range_idx (int)
- {
- // no-op for HTML
- }
-
void colorize_text_for_cfg_edge ()
{
// no-op for HTML
@@ -648,7 +645,26 @@ struct to_html
source_policy.get_html_start_span_fn () (loc_policy, *this, exploc);
}
+ const location_range *
+ get_location_range_by_idx (int range_idx)
+ {
+ if (!m_richloc)
+ return nullptr;
+ return m_richloc->get_range (range_idx);
+ }
+
+ const char *
+ get_highlight_color_for_range_idx (int range_idx)
+ {
+ const location_range *const loc_range
+ = get_location_range_by_idx (range_idx);
+ if (!loc_range)
+ return nullptr;
+ return loc_range->m_highlight_color;
+ }
+
xml::printer &m_xp;
+ const rich_location *m_richloc;
private:
html_label_writer *m_html_label_writer;
pretty_printer m_scratch_pp;
@@ -671,7 +687,7 @@ print_html_span_start (const diagnostic_context &dc,
xml::printer &xp,
const expanded_location &exploc)
{
- to_html sink (xp, nullptr);
+ to_html sink (xp, nullptr, nullptr);
diagnostic_source_print_policy source_policy (dc);
source_policy.get_html_start_span_fn () (*this, sink, exploc);
}
@@ -835,8 +851,8 @@ private:
void end_line ();
void print_annotation_line (linenum_type row, const line_bounds lbounds);
void print_any_labels (linenum_type row);
- void begin_label (const line_label &label);
- void end_label ();
+ void begin_label (int state_idx, bool is_label_text);
+ void end_label (int state_idx, bool is_label_text);
void print_trailing_fixits (linenum_type row);
void
@@ -844,11 +860,17 @@ private:
void print_any_right_to_left_edge_lines ();
+ void set_in_range (int range_idx);
+ void set_outside_range ();
+
private:
Sink &m_sink;
const layout &m_layout;
bool m_is_diagnostic_path;
+ bool m_was_in_range_p;
+ int m_last_range_idx;
+
/* Fields for handling links between labels (e.g. for showing CFG edges
in execution paths).
Note that the logic for printing such links makes various simplifying
@@ -2302,9 +2324,9 @@ layout_printer<Sink>::print_source_line (linenum_type row,
CU_BYTES,
&state);
if (in_range_p)
- m_sink.colorize_text_for_range_idx (state.range_idx);
+ set_in_range (state.range_idx);
else
- m_sink.colorize_text_ensure_normal ();
+ set_outside_range ();
}
/* Get the display width of the next character to be output, expanding
@@ -2335,6 +2357,7 @@ layout_printer<Sink>::print_source_line (linenum_type row,
m_sink.print_decoded_char (m_layout.m_char_policy, cp);
c = dw.next_byte ();
}
+ set_outside_range ();
end_line ();
return lbounds;
}
@@ -2477,6 +2500,41 @@ layout_printer<to_html>::end_line ()
m_sink.pop_html_tag ("tr");
}
+/* Handle the various transitions between being-in-range and
+ not-being-in-a-range, and between ranges. */
+
+template<typename Sink>
+void
+layout_printer<Sink>::set_in_range (int range_idx)
+{
+ if (m_was_in_range_p)
+ {
+ if (m_last_range_idx != range_idx)
+ {
+ /* transition between ranges. */
+ end_label (m_last_range_idx, false);
+ begin_label (range_idx, false);
+ }
+ }
+ else
+ {
+ /* transition from "not in a range" to "in a range". */
+ begin_label (range_idx, false);
+ m_was_in_range_p = true;
+ }
+ m_last_range_idx = range_idx;
+}
+
+template<typename Sink>
+void
+layout_printer<Sink>::set_outside_range ()
+{
+ if (m_was_in_range_p)
+ /* transition from "in a range" to "not in a range". */
+ end_label (m_last_range_idx, false);
+ m_was_in_range_p = false;
+}
+
/* Print a line consisting of the caret/underlines for the given
source line. */
@@ -2501,9 +2559,13 @@ layout_printer<Sink>::print_annotation_line (linenum_type row,
CU_DISPLAY_COLS,
&state);
if (in_range_p)
+ set_in_range (state.range_idx);
+ else
+ set_outside_range ();
+
+ if (in_range_p)
{
/* Within a range. Draw either the caret or an underline. */
- m_sink.colorize_text_for_range_idx (state.range_idx);
if (state.draw_caret_p)
{
/* Draw the caret. */
@@ -2520,11 +2582,12 @@ layout_printer<Sink>::print_annotation_line (linenum_type row,
else
{
/* Not in a range. */
- m_sink.colorize_text_ensure_normal ();
m_sink.add_character (' ');
}
}
+ set_outside_range ();
+
end_line ();
}
@@ -2606,36 +2669,59 @@ public:
bool m_has_out_edge;
};
+/* Implementations of layout_printer::{begin,end}_label for
+ to_text and to_html.
+
+ RANGE_IDX is the index of the range within the rich_location.
+
+ IS_LABEL_TEXT is true for the text of the label,
+ false when quoting the source code, underlining the source
+ code, and for the vertical bars connecting the underlines
+ to the text of the label. */
+
template<>
void
-layout_printer<to_text>::begin_label (const line_label &label)
+layout_printer<to_text>::begin_label (int range_idx,
+ bool is_label_text)
{
- /* Colorize the text, unless it's for events in a
+ /* Colorize the text, unless it's for labels for events in a
diagnostic_path. */
- if (!m_is_diagnostic_path)
- m_sink.colorize_text_for_range_idx (label.m_state_idx);
+ if (is_label_text && m_is_diagnostic_path)
+ return;
+
+ gcc_assert (m_sink.m_colorizer);
+ m_sink.m_colorizer->set_range (range_idx);
}
template<>
void
-layout_printer<to_html>::begin_label (const line_label &)
+layout_printer<to_html>::begin_label (int range_idx,
+ bool is_label_text)
{
- if (m_sink.m_html_label_writer)
+ if (is_label_text && m_sink.m_html_label_writer)
m_sink.m_html_label_writer->begin_label ();
+
+ if (const char *highlight_color
+ = m_sink.get_highlight_color_for_range_idx (range_idx))
+ m_sink.m_xp.push_tag_with_class ("span", highlight_color);
}
template<>
void
-layout_printer<to_text>::end_label ()
+layout_printer<to_text>::end_label (int, bool)
{
m_sink.colorize_text_ensure_normal ();
}
template<>
void
-layout_printer<to_html>::end_label ()
+layout_printer<to_html>::end_label (int range_idx,
+ bool is_label_text)
{
- if (m_sink.m_html_label_writer)
+ if (m_sink.get_highlight_color_for_range_idx (range_idx))
+ m_sink.m_xp.pop_tag ();
+
+ if (is_label_text && m_sink.m_html_label_writer)
m_sink.m_html_label_writer->end_label ();
}
@@ -2804,9 +2890,9 @@ layout_printer<Sink>::print_any_labels (linenum_type row)
move_to_column (&column, label->m_column, true);
gcc_assert (column == label->m_column);
- begin_label (*label);
+ begin_label (label->m_state_idx, true);
m_sink.add_text (label->m_text.m_buffer);
- end_label ();
+ end_label (label->m_state_idx, true);
column += label->m_display_width;
if (get_options ().show_event_links_p && label->m_has_out_edge)
@@ -2837,9 +2923,9 @@ layout_printer<Sink>::print_any_labels (linenum_type row)
{
gcc_assert (column <= label->m_column);
move_to_column (&column, label->m_column, true);
- m_sink.colorize_text_for_range_idx (label->m_state_idx);
+ begin_label (label->m_state_idx, false);
m_sink.add_character ('|');
- m_sink.colorize_text_ensure_normal ();
+ end_label (label->m_state_idx, false);
column++;
}
}
@@ -3676,6 +3762,8 @@ layout_printer<Sink>::layout_printer (Sink &sink,
: m_sink (sink),
m_layout (layout),
m_is_diagnostic_path (is_diagnostic_path),
+ m_was_in_range_p (false),
+ m_last_range_idx (0),
m_link_lhs_state (link_lhs_state::none),
m_link_rhs_column (-1)
{
@@ -3857,7 +3945,7 @@ diagnostic_source_print_policy::print_as_html (xml::printer &xp,
const
{
layout layout (*this, richloc, effects);
- to_html sink (xp, label_writer);
+ to_html sink (xp, &richloc, label_writer);
layout_printer<to_html> lp (sink, layout,
diagnostic_kind == DK_DIAGNOSTIC_PATH);
lp.print (*this);
diff --git a/gcc/doc/gm2.texi b/gcc/doc/gm2.texi
index 8293da4..9bd0f0d 100644
--- a/gcc/doc/gm2.texi
+++ b/gcc/doc/gm2.texi
@@ -540,6 +540,9 @@ lines compiled.
@item -fm2-strict-type
experimental flag to turn on the new strict type checker.
+@item -fm2-strict-type-reason
+provides more detail why the types are incompatible.
+
@item -fm2-whole-program
compile all implementation modules and program module at once. Notice
that you need to take care if you are compiling different dialect
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 0150ad0..8de0085 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -30911,12 +30911,13 @@ to store the immediate to a register first.
@opindex mcmodel=
@opindex mcmodel=small
@item -mcmodel=small
-Generate OpenRISC code for the small model: The GOT is limited to 64k. This is
-the default model.
+Generate OpenRISC code for the small model: The GOT is limited to 64k and
+function call jumps are limited to 64M offsets. This is the default model.
@opindex mcmodel=large
@item -mcmodel=large
-Generate OpenRISC code for the large model: The GOT may grow up to 4G in size.
+Generate OpenRISC code for the large model: The GOT may grow up to 4G in size
+and function call jumps can target the full 4G address space.
@end table
diff --git a/gcc/doc/riscv-ext.texi b/gcc/doc/riscv-ext.texi
index 7a22d84..e7e1f75 100644
--- a/gcc/doc/riscv-ext.texi
+++ b/gcc/doc/riscv-ext.texi
@@ -474,6 +474,10 @@
@tab 1.0
@tab SvNNx4 mode supported for all modes supported by satp
+@item shlcofideleg
+@tab 1.0
+@tab Delegating LCOFI interrupts to VS-mode
+
@item shtvala
@tab 1.0
@tab The htval register provides all needed values
@@ -494,6 +498,10 @@
@tab 1.0
@tab Advanced interrupt architecture extension
+@item smcntrpmf
+@tab 1.0
+@tab Cycle and instret privilege mode filtering
+
@item smepmp
@tab 1.0
@tab PMP Enhancements for memory access and execution prevention on Machine mode
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 91fadc6..6c5586e 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -215,10 +215,10 @@ man pages and support for converting the installation manual to
HTML@. @xref{Documentation}.
@item ginclude
-System headers installed by GCC, mainly those required by the C
-standard of freestanding implementations. @xref{Headers, , Headers
-Installed by GCC}, for details of when these and other headers are
-installed.
+System headers installed by GCC, mainly those defined by the C
+standard that do not declare functions with external linkage.
+@xref{Headers, , Headers Installed by GCC}, for details of when these
+and other headers are installed.
@item po
Message catalogs with translations of messages produced by GCC into
@@ -326,7 +326,8 @@ Headers Installed by GCC}, for more information about the
In general, GCC expects the system C library to provide most of the
headers to be used with it. However, GCC will fix those headers if
necessary to make them work with GCC, and will install some headers
-required of freestanding implementations. These headers are installed
+of its own, mainly headers that do not declare functions with external
+linkage. These headers are installed
in @file{@var{libsubdir}/include}. Headers for non-C runtime
libraries are also installed by GCC; these are not documented here.
(FIXME: document them somewhere.)
@@ -351,8 +352,8 @@ representation of floating point numbers.
GCC also installs its own version of @code{<limits.h>}; this is generated
from @file{glimits.h}, together with @file{limitx.h} and
@file{limity.h} if the system also has its own version of
-@code{<limits.h>}. (GCC provides its own header because it is
-required of ISO C freestanding implementations, but needs to include
+@code{<limits.h>}. (GCC provides its own header because it does not
+declare functions with external linkage, but needs to include
the system header from its own header as well because other standards
such as POSIX specify additional values to be defined in
@code{<limits.h>}.) The system's @code{<limits.h>} header is used via
@@ -1975,6 +1976,9 @@ at plain @option{-O2}.
@item tls
Target supports thread-local storage.
+@item tls_link
+Target supports linking TLS executables.
+
@item tls_native
Target supports native (rather than emulated) thread-local storage.
diff --git a/gcc/doc/standards.texi b/gcc/doc/standards.texi
index bbae350..011f7e2 100644
--- a/gcc/doc/standards.texi
+++ b/gcc/doc/standards.texi
@@ -152,7 +152,9 @@ library facilities: those in @code{<float.h>}, @code{<limits.h>},
@code{<iso646.h>}; since C99, also those in @code{<stdbool.h>} and
@code{<stdint.h>}; and since C11, also those in @code{<stdalign.h>}
and @code{<stdnoreturn.h>}. In addition, complex types, added in C99, are not
-required for freestanding implementations.
+required for freestanding implementations. Since C23, freestanding
+implementations are required to support a larger range of library
+facilities, including some functions from other headers.
The standard also defines two environments for programs, a
@dfn{freestanding environment}, required of all implementations and
@@ -167,13 +169,13 @@ a program using the facilities of an
operating system is an example of a program running in a hosted environment.
@opindex ffreestanding
-GCC aims towards being usable as a conforming freestanding
-implementation, or as the compiler for a conforming hosted
-implementation. By default, it acts as the compiler for a hosted
+GCC aims towards being usable as the compiler for a conforming
+freestanding or hosted implementation.
+By default, it acts as the compiler for a hosted
implementation, defining @code{__STDC_HOSTED__} as @code{1} and
presuming that when the names of ISO C functions are used, they have
-the semantics defined in the standard. To make it act as a conforming
-freestanding implementation for a freestanding environment, use the
+the semantics defined in the standard. To make it act as the compiler
+for a freestanding environment, use the
option @option{-ffreestanding}; it then defines
@code{__STDC_HOSTED__} to @code{0} and does not make assumptions about the
meanings of function names from the standard library, with exceptions
@@ -181,12 +183,24 @@ noted below. To build an OS kernel, you may well still need to make
your own arrangements for linking and startup.
@xref{C Dialect Options,,Options Controlling C Dialect}.
-GCC does not provide the library facilities required only of hosted
-implementations, nor yet all the facilities required by C99 of
-freestanding implementations on all platforms.
-To use the facilities of a hosted
-environment, you need to find them elsewhere (for example, in the
-GNU C library). @xref{Standard Libraries,,Standard Libraries}.
+GCC generally provides library facilities in headers that do not
+declare functions with external linkage (which includes the headers
+required by C11 and before to be provided by freestanding
+implementations), but not those included in other headers.
+Additionally, GCC provides @code{<stdatomic.h>}, even though it
+declares some functions with external linkage (which are provided in
+@code{libatomic}). On a few platforms, some of the headers not
+declaring functions with external linkage are instead obtained from
+the OS's C library, which may mean that they lack support for features
+from more recent versions of the C standard that are supported in
+GCC's own versions of those headers. On some platforms, GCC provides
+@code{<tgmath.h>} (but this implementation does not support interfaces
+added in C23).
+
+To use the facilities of a hosted environment, and some of the
+facilities required in a freestanding environment by C23, you need to
+find them elsewhere (for example, in the GNU C library).
+@xref{Standard Libraries,,Standard Libraries}.
Most of the compiler support routines used by GCC are present in
@file{libgcc}, but there are a few exceptions. GCC requires the
diff --git a/gcc/doc/trouble.texi b/gcc/doc/trouble.texi
index 15ced5f..a2e6de4 100644
--- a/gcc/doc/trouble.texi
+++ b/gcc/doc/trouble.texi
@@ -494,10 +494,12 @@ as to use the proper set, but you'll have to do this by hand.
@section Standard Libraries
@opindex Wall
-GCC by itself attempts to be a conforming freestanding implementation.
+GCC by itself attempts to provide the compiler part of a conforming
+implementation, but only a limited subset of the library part of such
+an implementation.
@xref{Standards,,Language Standards Supported by GCC}, for details of
-what this means. Beyond the library facilities required of such an
-implementation, the rest of the C library is supplied by the vendor of
+what this means. Beyond the limited library facilities described
+there, the rest of the C library is supplied by the vendor of
the operating system. If that C library doesn't conform to the C
standards, then your programs might get warnings (especially when using
@option{-Wall}) that you don't expect.
diff --git a/gcc/final.cc b/gcc/final.cc
index 12c6eb0..a4dbab7 100644
--- a/gcc/final.cc
+++ b/gcc/final.cc
@@ -2072,7 +2072,7 @@ output_alternate_entry_point (FILE *file, rtx_insn *insn)
/* Given a CALL_INSN, find and return the nested CALL. */
static rtx
-call_from_call_insn (rtx_call_insn *insn)
+call_from_call_insn (const rtx_call_insn *insn)
{
rtx x;
gcc_assert (CALL_P (insn));
@@ -2098,6 +2098,15 @@ call_from_call_insn (rtx_call_insn *insn)
return x;
}
+/* Return the CALL in X if there is one. */
+
+rtx
+get_call_rtx_from (const rtx_insn *insn)
+{
+ const rtx_call_insn *call_insn = as_a<const rtx_call_insn *> (insn);
+ return call_from_call_insn (call_insn);
+}
+
/* Print a comment into the asm showing FILENAME, LINENUM, and the
corresponding source line, if available. */
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 1218bb8..395cd0a 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,36 @@
+2025-06-03 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/99838
+ * data.cc (gfc_assign_data_value): For a new initializer use the
+ location from the constructor as fallback.
+
+2025-05-30 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102599
+ PR fortran/114022
+ * expr.cc (simplify_complex_array_inquiry_ref): Helper function for
+ simplification of inquiry references (%re/%im) of constant complex
+ arrays.
+ (find_inquiry_ref): Use it for handling %re/%im inquiry references
+ of complex arrays.
+ (scalarize_intrinsic_call): Fix frontend memleak.
+ * primary.cc (gfc_match_varspec): When the reference is NULL, the
+ previous simplification has succeeded in evaluating inquiry
+ references also of arrays.
+
+2025-05-30 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/120355
+ * interface.cc (compare_parameter): If the global function has a
+ result clause, take typespec from there for the comparison against
+ the dummy argument.
+
+2025-05-30 Julian Brown <julian@codesourcery.com>
+ Tobias Burnus <tburnus@baylibre.com>
+
+ * parse.cc (tree.h, fold-const.h, tree-hash-traits.h): Add includes
+ (for additions to omp-general.h).
+
2025-05-29 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/120049
diff --git a/gcc/fortran/data.cc b/gcc/fortran/data.cc
index 5c83f69..a438c26 100644
--- a/gcc/fortran/data.cc
+++ b/gcc/fortran/data.cc
@@ -593,7 +593,13 @@ gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index,
{
/* Point the container at the new expression. */
if (last_con == NULL)
- symbol->value = expr;
+ {
+ symbol->value = expr;
+ /* For a new initializer use the location from the
+ constructor as fallback. */
+ if (!GFC_LOCUS_IS_SET(expr->where) && con != NULL)
+ symbol->value->where = con->where;
+ }
else
last_con->expr = expr;
}
diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc
index bf858ea..b0495b7 100644
--- a/gcc/fortran/expr.cc
+++ b/gcc/fortran/expr.cc
@@ -1838,6 +1838,55 @@ find_substring_ref (gfc_expr *p, gfc_expr **newp)
}
+/* Simplify inquiry references (%re/%im) of constant complex arrays.
+ Used by find_inquiry_ref. */
+
+static gfc_expr *
+simplify_complex_array_inquiry_ref (gfc_expr *p, inquiry_type inquiry)
+{
+ gfc_expr *e, *r, *result;
+ gfc_constructor_base base;
+ gfc_constructor *c;
+
+ if ((inquiry != INQUIRY_RE && inquiry != INQUIRY_IM)
+ || p->expr_type != EXPR_ARRAY
+ || p->ts.type != BT_COMPLEX
+ || p->rank <= 0
+ || p->value.constructor == NULL
+ || !gfc_is_constant_array_expr (p))
+ return NULL;
+
+ /* Simplify array sections. */
+ gfc_simplify_expr (p, 0);
+
+ result = gfc_get_array_expr (BT_REAL, p->ts.kind, &p->where);
+ result->rank = p->rank;
+ result->shape = gfc_copy_shape (p->shape, p->rank);
+
+ base = p->value.constructor;
+ for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
+ {
+ e = c->expr;
+ if (e->expr_type != EXPR_CONSTANT)
+ goto fail;
+
+ r = gfc_get_constant_expr (BT_REAL, e->ts.kind, &e->where);
+ if (inquiry == INQUIRY_RE)
+ mpfr_set (r->value.real, mpc_realref (e->value.complex), GFC_RND_MODE);
+ else
+ mpfr_set (r->value.real, mpc_imagref (e->value.complex), GFC_RND_MODE);
+
+ gfc_constructor_append_expr (&result->value.constructor, r, &e->where);
+ }
+
+ return result;
+
+fail:
+ gfc_free_expr (result);
+ return NULL;
+}
+
+
/* Pull an inquiry result out of an expression. */
static bool
@@ -1848,6 +1897,7 @@ find_inquiry_ref (gfc_expr *p, gfc_expr **newp)
gfc_ref *inquiry_head;
gfc_ref *ref_ss = NULL;
gfc_expr *tmp;
+ bool nofail = false;
tmp = gfc_copy_expr (p);
@@ -1947,24 +1997,50 @@ find_inquiry_ref (gfc_expr *p, gfc_expr **newp)
break;
case INQUIRY_RE:
- if (tmp->ts.type != BT_COMPLEX || tmp->expr_type != EXPR_CONSTANT)
+ if (tmp->ts.type != BT_COMPLEX)
goto cleanup;
if (!gfc_notify_std (GFC_STD_F2008, "RE part_ref at %C"))
goto cleanup;
+ if (tmp->expr_type == EXPR_ARRAY)
+ {
+ *newp = simplify_complex_array_inquiry_ref (tmp, INQUIRY_RE);
+ if (*newp != NULL)
+ {
+ nofail = true;
+ break;
+ }
+ }
+
+ if (tmp->expr_type != EXPR_CONSTANT)
+ goto cleanup;
+
*newp = gfc_get_constant_expr (BT_REAL, tmp->ts.kind, &tmp->where);
mpfr_set ((*newp)->value.real,
mpc_realref (tmp->value.complex), GFC_RND_MODE);
break;
case INQUIRY_IM:
- if (tmp->ts.type != BT_COMPLEX || tmp->expr_type != EXPR_CONSTANT)
+ if (tmp->ts.type != BT_COMPLEX)
goto cleanup;
if (!gfc_notify_std (GFC_STD_F2008, "IM part_ref at %C"))
goto cleanup;
+ if (tmp->expr_type == EXPR_ARRAY)
+ {
+ *newp = simplify_complex_array_inquiry_ref (tmp, INQUIRY_IM);
+ if (*newp != NULL)
+ {
+ nofail = true;
+ break;
+ }
+ }
+
+ if (tmp->expr_type != EXPR_CONSTANT)
+ goto cleanup;
+
*newp = gfc_get_constant_expr (BT_REAL, tmp->ts.kind, &tmp->where);
mpfr_set ((*newp)->value.real,
mpc_imagref (tmp->value.complex), GFC_RND_MODE);
@@ -1977,7 +2053,7 @@ find_inquiry_ref (gfc_expr *p, gfc_expr **newp)
if (!(*newp))
goto cleanup;
- else if ((*newp)->expr_type != EXPR_CONSTANT)
+ else if ((*newp)->expr_type != EXPR_CONSTANT && !nofail)
{
gfc_free_expr (*newp);
goto cleanup;
@@ -2549,7 +2625,7 @@ scalarize_intrinsic_call (gfc_expr *e, bool init_flag)
rank[n] = a->expr->rank;
else
rank[n] = 1;
- ctor = gfc_constructor_copy (a->expr->value.constructor);
+ ctor = a->expr->value.constructor;
args[n] = gfc_constructor_first (ctor);
}
else
diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc
index db5fc5d..f0e1fef 100644
--- a/gcc/fortran/primary.cc
+++ b/gcc/fortran/primary.cc
@@ -2716,6 +2716,9 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag,
if (primary->expr_type == EXPR_CONSTANT)
goto check_done;
+ if (primary->ref == NULL)
+ goto check_done;
+
switch (tmp->u.i)
{
case INQUIRY_RE:
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 8d9448e..74d4265 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -2782,9 +2782,11 @@ gfc_conv_substring (gfc_se * se, gfc_ref * ref, int kind,
start.expr = gfc_evaluate_now (start.expr, &se->pre);
/* Change the start of the string. */
- if ((TREE_CODE (TREE_TYPE (se->expr)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (se->expr)) == INTEGER_TYPE)
- && TYPE_STRING_FLAG (TREE_TYPE (se->expr)))
+ if (((TREE_CODE (TREE_TYPE (se->expr)) == ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (se->expr)) == INTEGER_TYPE)
+ && TYPE_STRING_FLAG (TREE_TYPE (se->expr)))
+ || (POINTER_TYPE_P (TREE_TYPE (se->expr))
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (se->expr))) != ARRAY_TYPE))
tmp = se->expr;
else
tmp = build_fold_indirect_ref_loc (input_location,
@@ -2795,6 +2797,14 @@ gfc_conv_substring (gfc_se * se, gfc_ref * ref, int kind,
tmp = gfc_build_array_ref (tmp, start.expr, NULL_TREE, true);
se->expr = gfc_build_addr_expr (type, tmp);
}
+ else if (POINTER_TYPE_P (TREE_TYPE (tmp)))
+ {
+ tree diff;
+ diff = fold_build2 (MINUS_EXPR, size_type_node, start.expr,
+ build_one_cst (size_type_node));
+ se->expr
+ = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (tmp), tmp, diff);
+ }
}
/* Length = end + 1 - start. */
diff --git a/gcc/function.h b/gcc/function.h
index 2260d67..370629f 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -333,7 +333,6 @@ struct GTY(()) function {
/* Properties used by the pass manager. */
unsigned int curr_properties;
- unsigned int last_verified;
/* Different from normal TODO_flags which are handled right at the
beginning or the end of one pass execution, the pending_TODOs
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index 0f43761..185f9db 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -198,10 +198,7 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl)
tree
create_tmp_reg_or_ssa_name (tree type, gimple *stmt)
{
- if (gimple_in_ssa_p (cfun))
- return make_ssa_name (type, stmt);
- else
- return create_tmp_reg (type);
+ return make_ssa_name (type, stmt);
}
/* CVAL is value taken from DECL_INITIAL of variable. Try to transform it into
diff --git a/gcc/gimple-harden-conditionals.cc b/gcc/gimple-harden-conditionals.cc
index 3ad3bb9..d4a418d 100644
--- a/gcc/gimple-harden-conditionals.cc
+++ b/gcc/gimple-harden-conditionals.cc
@@ -61,8 +61,7 @@ const pass_data pass_data_harden_compares = {
0, // properties_destroyed
0, // properties_start
TODO_update_ssa
- | TODO_cleanup_cfg
- | TODO_verify_il, // properties_finish
+ | TODO_cleanup_cfg, // properties_finish
};
class pass_harden_compares : public gimple_opt_pass
@@ -96,8 +95,7 @@ const pass_data pass_data_harden_conditional_branches = {
0, // properties_destroyed
0, // properties_start
TODO_update_ssa
- | TODO_cleanup_cfg
- | TODO_verify_il, // properties_finish
+ | TODO_cleanup_cfg, // properties_finish
};
class pass_harden_conditional_branches : public gimple_opt_pass
diff --git a/gcc/gimple-harden-control-flow.cc b/gcc/gimple-harden-control-flow.cc
index e46acaf..f129ff1 100644
--- a/gcc/gimple-harden-control-flow.cc
+++ b/gcc/gimple-harden-control-flow.cc
@@ -1549,8 +1549,7 @@ pass_harden_control_flow_redundancy::execute (function *fun)
return
TODO_update_ssa
- | TODO_cleanup_cfg
- | TODO_verify_il;
+ | TODO_cleanup_cfg;
}
/* Instantiate a hardcfr pass. */
diff --git a/gcc/ipa-strub.cc b/gcc/ipa-strub.cc
index 99cc9d9..d7c0a92 100644
--- a/gcc/ipa-strub.cc
+++ b/gcc/ipa-strub.cc
@@ -1770,8 +1770,7 @@ const pass_data pass_data_ipa_strub = {
0, // properties_start
TODO_update_ssa
| TODO_cleanup_cfg
- | TODO_rebuild_cgraph_edges
- | TODO_verify_il, // properties_finish
+ | TODO_rebuild_cgraph_edges, // properties_finish
};
class pass_ipa_strub : public simple_ipa_opt_pass
diff --git a/gcc/lra-eliminations.cc b/gcc/lra-eliminations.cc
index d84a7d1..bb708b0 100644
--- a/gcc/lra-eliminations.cc
+++ b/gcc/lra-eliminations.cc
@@ -1185,7 +1185,7 @@ update_reg_eliminate (bitmap insns_with_changed_offsets)
setup_can_eliminate (ep, false);
continue;
}
- if (ep->can_eliminate != prev && elimination_map[ep->from] == ep)
+ if (!ep->can_eliminate && elimination_map[ep->from] == ep)
{
/* We cannot use this elimination anymore -- find another
one. */
diff --git a/gcc/lra-spills.cc b/gcc/lra-spills.cc
index fc912c4..4febc69 100644
--- a/gcc/lra-spills.cc
+++ b/gcc/lra-spills.cc
@@ -556,7 +556,7 @@ spill_pseudos (void)
fprintf (lra_dump_file,
"Changing spilled pseudos to memory in insn #%u\n",
INSN_UID (insn));
- lra_push_insn (insn);
+ lra_push_insn_and_update_insn_regno_info (insn);
if (lra_reg_spill_p || targetm.different_addr_displacement_p ())
lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
}
diff --git a/gcc/m2/ChangeLog b/gcc/m2/ChangeLog
index 0009211..6b19a4d 100644
--- a/gcc/m2/ChangeLog
+++ b/gcc/m2/ChangeLog
@@ -1,3 +1,105 @@
+2025-06-01 Gaius Mulley <gaiusmod2@gmail.com>
+
+ PR modula2/120474
+ * gm2-libs-log/InOut.mod (LocalWrite): Call FIO.FlushBuffer.
+
+2025-06-01 Gaius Mulley <gaiusmod2@gmail.com>
+
+ PR modula2/120497
+ * gm2-compiler/M2Range.mod (IsAssignmentCompatible): Remove from
+ import list.
+ (FoldTypeReturnFunc): Rewrite to skip the Lvalue of a var
+ variable.
+ (CodeTypeReturnFunc): Ditto.
+ (CodeTypeIndrX): Call AssignmentTypeCompatible rather than
+ IsAssignmentCompatible.
+ (FoldTypeIndrX): Ditto.
+
+2025-05-31 Gaius Mulley <gaiusmod2@gmail.com>
+
+ PR modula2/120389
+ * gm2-compiler/M2Check.def (AssignmentTypeCompatible): Add new
+ parameter enableReason.
+ * gm2-compiler/M2Check.mod (EquivalenceProcedure): New type.
+ (falseReason2): New procedure function.
+ (falseReason1): Ditto.
+ (falseReason0): Ditto.
+ (checkTypeEquivalence): Rewrite.
+ (checkUnboundedArray): Ditto.
+ (checkUnbounded): Ditto.
+ (checkArrayTypeEquivalence): Ditto.
+ (checkCharStringTypeEquivalence): Ditto.
+ (buildError4): Add false reason.
+ (buildError2): Ditto.
+ (IsTyped): Use GetDType.
+ (IsTypeEquivalence): New procedure function.
+ (checkVarTypeEquivalence): Ditto.
+ (checkVarEquivalence ): Rewrite.
+ (checkConstMeta): Ditto.
+ (checkEnumField): New procedure function.
+ (checkEnumFieldEquivalence): Ditto.
+ (checkSubrangeTypeEquivalence): Rewrite.
+ (checkSystemEquivalence): Ditto.
+ (checkTypeKindViolation): Ditto.
+ (doCheckPair): Ditto.
+ (InitEquivalenceArray): New procedure.
+ (addEquivalence): Ditto.
+ (checkProcType): Rewrite.
+ (deconstruct): Deallocate reason string.
+ (AssignmentTypeCompatible): Initialize reason and reasonEnable
+ fields.
+ (ParameterTypeCompatible): Ditto.
+ (doExpressionTypeCompatible): Ditto.
+ * gm2-compiler/M2GenGCC.mod (CodeIndrX) Rewrite.
+ (CheckBinaryExpressionTypes): Rewrite and simplify now that the
+ type checker is more robust.
+ (CheckElementSetTypes): Ditto.
+ (CodeXIndr): Add new range assignment type check.
+ * gm2-compiler/M2MetaError.def: Correct comments.
+ * gm2-compiler/M2Options.def (SetStrictTypeAssignment): New procedure.
+ (SetStrictTypeReason): Ditto.
+ * gm2-compiler/M2Options.mod: (SetStrictTypeAssignment): New procedure.
+ (SetStrictTypeReason): Ditto.
+ (StrictTypeReason): Initialize.
+ (StrictTypeAssignment): Ditto.
+ * gm2-compiler/M2Quads.mod (CheckBreak): Delete.
+ (BreakQuad): New global variable.
+ (BreakAtQuad): Delete.
+ (gdbhook): New procedure.
+ (BreakWhenQuadCreated): Ditto.
+ (CheckBreak): Ditto.
+ (Init): Call BreakWhenQuadCreated and gdbhook.
+ (doBuildAssignment): Add type assignment range check.
+ (CheckProcTypeAndProcedure): Only check if the procedure
+ types differ.
+ (doIndrX): Add type IndrX range check.
+ (CheckReturnType): Add range return type check.
+ * gm2-compiler/M2Range.def (InitTypesIndrXCheck): New procedure
+ function.
+ (InitTypesReturnTypeCheck): Ditto.
+ * gm2-compiler/M2Range.mod (InitTypesIndrXCheck): New procedure
+ function.
+ (InitTypesReturnTypeCheck): Ditto.
+ (HandlerExists): Add new clauses.
+ (FoldAssignment): Pass extra FALSE parameter to
+ AssignmentTypeCompatible.
+ (FoldTypeReturnFunc): New procedure.
+ (FoldTypeAssign): Ditto.
+ (FoldTypeIndrX): Ditto.
+ (CodeTypeAssign): Rewrite.
+ (CodeTypeIndrX): New procedure.
+ (CodeTypeReturnFunc): Ditto.
+ (FoldTypeCheck): Add new case clauses.
+ (CodeTypeCheck): Ditto.
+ (FoldRangeCheckLower): Ditto.
+ (IssueWarning): Ditto.
+ * gm2-gcc/m2options.h (M2Options_SetStrictTypeAssignment): New
+ function prototype.
+ (M2Options_SetStrictTypeReason): Ditto.
+ * gm2-lang.cc (gm2_langhook_handle_option): New case clause
+ OPT_fm2_strict_type_reason.
+ * lang.opt (-fm2-strict-type-reason): New option.
+
2025-05-22 Gaius Mulley <gaiusmod2@gmail.com>
PR modula2/120389
diff --git a/gcc/m2/gm2-compiler/M2Check.def b/gcc/m2/gm2-compiler/M2Check.def
index 0ceb173..9d9f760 100644
--- a/gcc/m2/gm2-compiler/M2Check.def
+++ b/gcc/m2/gm2-compiler/M2Check.def
@@ -50,7 +50,8 @@ PROCEDURE ParameterTypeCompatible (token: CARDINAL; format: ARRAY OF CHAR;
*)
PROCEDURE AssignmentTypeCompatible (token: CARDINAL; format: ARRAY OF CHAR;
- des, expr: CARDINAL) : BOOLEAN ;
+ des, expr: CARDINAL;
+ enableReason: BOOLEAN) : BOOLEAN ;
(*
diff --git a/gcc/m2/gm2-compiler/M2Check.mod b/gcc/m2/gm2-compiler/M2Check.mod
index d86ef8e..614526c 100644
--- a/gcc/m2/gm2-compiler/M2Check.mod
+++ b/gcc/m2/gm2-compiler/M2Check.mod
@@ -36,26 +36,33 @@ FROM M2System IMPORT IsSystemType, IsGenericSystemType, IsSameSize, IsComplexN ;
FROM M2Base IMPORT IsParameterCompatible, IsAssignmentCompatible, IsExpressionCompatible, IsComparisonCompatible, IsBaseType, IsMathType, ZType, CType, RType, IsComplexType, Char ;
FROM Indexing IMPORT Index, InitIndex, GetIndice, PutIndice, KillIndex, HighIndice, LowIndice, IncludeIndiceIntoIndex, ForeachIndiceInIndexDo ;
FROM M2Error IMPORT Error, InternalError, NewError, ErrorString, ChainError ;
-FROM M2MetaError IMPORT MetaErrorStringT2, MetaErrorStringT3, MetaErrorStringT4, MetaString2, MetaString3, MetaString4, MetaError1 ;
+
+FROM M2MetaError IMPORT MetaErrorStringT0, MetaErrorStringT2, MetaErrorStringT3,
+ MetaErrorStringT4,
+ MetaString0, MetaString1, MetaString2, MetaString3,
+ MetaString4,
+ MetaError0, MetaError1 ;
+
FROM StrLib IMPORT StrEqual ;
FROM M2Debug IMPORT Assert ;
-FROM SymbolTable IMPORT NulSym, IsRecord, IsSet, GetDType, GetSType, IsType,
+FROM SymbolTable IMPORT NulSym, IsRecord, IsSet, GetDType, GetType, IsType,
SkipType, IsProcedure, NoOfParamAny, IsVarParamAny, GetNth,
GetNthParamAny, IsProcType, IsVar, IsEnumeration, IsArray,
IsSubrange, GetArraySubscript, IsConst,
IsReallyPointer, IsPointer, IsParameter, ModeOfAddr,
- GetMode, GetType, IsUnbounded, IsComposite, IsConstructor,
+ GetMode, IsUnbounded, IsComposite, IsConstructor,
IsParameter, IsConstString, IsConstLitInternal, IsConstLit,
GetStringLength, GetProcedureProcType, IsHiddenType,
- IsHiddenReallyPointer, GetDimension ;
+ IsHiddenReallyPointer, GetDimension, IsFieldEnumeration ;
FROM M2GCCDeclare IMPORT GetTypeMin, GetTypeMax ;
FROM M2System IMPORT Address ;
FROM M2ALU IMPORT Equ, PushIntegerTree ;
+FROM M2Options IMPORT StrictTypeReason ;
FROM m2expr IMPORT AreConstantsEqual ;
-FROM SymbolConversion IMPORT Mod2Gcc ;
-FROM DynamicStrings IMPORT String, InitString, KillString ;
+FROM SymbolConversion IMPORT Mod2Gcc, GccKnowsAbout ;
+FROM DynamicStrings IMPORT String, InitString, KillString, ConCat, Mark ;
FROM M2LexBuf IMPORT GetTokenNo ;
FROM Storage IMPORT ALLOCATE ;
FROM SYSTEM IMPORT ADR ;
@@ -63,7 +70,8 @@ FROM libc IMPORT printf ;
CONST
- debugging = FALSE ;
+ debugging = FALSE ;
+ MaxEquvalence = 20 ;
TYPE
errorSig = POINTER TO RECORD
@@ -83,6 +91,8 @@ TYPE
checkType = (parameter, assignment, expression) ;
tInfo = POINTER TO RECORD
+ reasonEnable: BOOLEAN ;
+ reason,
format : String ;
kind : checkType ;
token,
@@ -105,11 +115,14 @@ TYPE
status = (true, false, unknown, visited, unused) ;
+ EquivalenceProcedure = PROCEDURE (status, tInfo, CARDINAL, CARDINAL) : status ;
VAR
- pairFreeList : pair ;
- tinfoFreeList: tInfo ;
- errors : Index ;
+ pairFreeList : pair ;
+ tinfoFreeList : tInfo ;
+ errors : Index ;
+ HighEquivalence: CARDINAL ;
+ Equivalence : ARRAY [1..MaxEquvalence] OF EquivalenceProcedure ;
(*
@@ -159,6 +172,53 @@ END dumptInfo ;
(*
+ falseReason2 - return false. It also stores the message as the
+ reason for the false value.
+*)
+
+PROCEDURE falseReason2 (message: ARRAY OF CHAR; tinfo: tInfo;
+ left, right: CARDINAL) : status ;
+BEGIN
+ IF tinfo^.reasonEnable AND (tinfo^.reason = NIL)
+ THEN
+ tinfo^.reason := MetaString2 (InitString (message), left, right)
+ END ;
+ RETURN false
+END falseReason2 ;
+
+
+(*
+ falseReason1 - return false. It also stores the message as the
+ reason for the false value.
+*)
+
+PROCEDURE falseReason1 (message: ARRAY OF CHAR; tinfo: tInfo;
+ operand: CARDINAL) : status ;
+BEGIN
+ IF tinfo^.reasonEnable AND (tinfo^.reason = NIL)
+ THEN
+ tinfo^.reason := MetaString1 (InitString (message), operand)
+ END ;
+ RETURN false
+END falseReason1 ;
+
+
+(*
+ falseReason0 - return false. It also stores the message as the
+ reason for the false value.
+*)
+
+PROCEDURE falseReason0 (message: ARRAY OF CHAR; tinfo: tInfo) : status ;
+BEGIN
+ IF tinfo^.reasonEnable AND (tinfo^.reason = NIL)
+ THEN
+ tinfo^.reason := MetaString0 (InitString (message))
+ END ;
+ RETURN false
+END falseReason0 ;
+
+
+(*
isKnown - returns BOOLEAN:TRUE if result is status:true or status:false.
*)
@@ -192,31 +252,29 @@ END isFalse ;
checkTypeEquivalence - returns TRUE if left and right can be skipped and found to be equal.
*)
-PROCEDURE checkTypeEquivalence (result: status; left, right: CARDINAL) : status ;
-VAR
- leftT, rightT: CARDINAL ;
+PROCEDURE checkTypeEquivalence (result: status;
+ tinfo: tInfo;
+ left, right: CARDINAL) : status ;
BEGIN
- (* firstly check to see if we already have resolved this as false. *)
- IF isFalse (result)
+ IF left = right
THEN
- RETURN result
- ELSE
- (* check to see if we dont care about left or right. *)
- IF (left = NulSym) OR (right = NulSym)
+ RETURN true
+ ELSIF IsType (left) AND IsType (right)
+ THEN
+ IF IsHiddenType (left) AND IsHiddenType (right)
+ THEN
+ RETURN falseReason2 ('opaque types {%1a} {%2a} differ', tinfo, left, right)
+ ELSIF (IsHiddenType (left) AND (right = Address)) OR
+ (IsHiddenType (right) AND (left = Address))
THEN
RETURN true
- ELSE
- leftT := SkipType (left) ;
- rightT := SkipType (right) ;
- IF leftT = rightT
- THEN
- RETURN true
- ELSIF IsType (leftT) AND IsType (rightT)
- THEN
- (* the fundamental types are definitely different. *)
- RETURN false
- END
END
+ ELSIF IsTypeEquivalence (left)
+ THEN
+ RETURN checkPair (result, tinfo, GetDType (left), right)
+ ELSIF IsTypeEquivalence (right)
+ THEN
+ RETURN checkPair (result, tinfo, left, GetDType (right))
END ;
RETURN result
END checkTypeEquivalence ;
@@ -246,13 +304,15 @@ BEGIN
PushIntegerTree (Mod2Gcc (rLow)) ;
IF NOT Equ (tinfo^.token)
THEN
- RETURN false
+ RETURN falseReason2 ('low values of the subrange types {%1a} {%2a} differ',
+ tinfo, left, right)
END ;
PushIntegerTree (Mod2Gcc (lHigh)) ;
PushIntegerTree (Mod2Gcc (rHigh)) ;
IF NOT Equ (tinfo^.token)
THEN
- RETURN false
+ RETURN falseReason2 ('high values of the subrange types {%1a} {%2a} differ',
+ tinfo, left, right)
END
END ;
RETURN true
@@ -266,6 +326,7 @@ END checkSubrange ;
*)
PROCEDURE checkUnboundedArray (result: status;
+ tinfo: tInfo;
unbounded, array: CARDINAL) : status ;
VAR
dim : CARDINAL ;
@@ -280,13 +341,13 @@ BEGIN
Assert (IsUnbounded (unbounded)) ;
Assert (IsArray (array)) ;
dim := GetDimension (unbounded) ;
- ubtype := GetType (unbounded) ;
+ ubtype := GetDType (unbounded) ;
type := array ;
REPEAT
- type := GetType (type) ;
+ type := GetDType (type) ;
DEC (dim) ;
(* Check type equivalences. *)
- IF checkTypeEquivalence (result, type, ubtype) = true
+ IF checkTypeEquivalence (result, tinfo, type, ubtype) = true
THEN
RETURN true
END ;
@@ -294,11 +355,13 @@ BEGIN
(* If we have run out of dimensions we conclude false. *)
IF dim = 0
THEN
- RETURN false
+ RETURN falseReason0 ('unbounded array has less dimensions than the array',
+ tinfo)
END ;
UNTIL NOT IsArray (type)
END ;
- RETURN false
+ RETURN falseReason0 ('array has less dimensions than the unbounded array',
+ tinfo)
END checkUnboundedArray ;
@@ -327,14 +390,18 @@ BEGIN
referenced. We use GetDimension for 'bar' which is 2. *)
IF GetDimension (formal) # GetDimension (tinfo^.actual)
THEN
- RETURN false
+ RETURN falseReason2 ('the formal parameter unbounded array {%1a} has a different number' +
+ ' of dimensions to the actual parameter unbounded array {%2a}',
+ tinfo, formal, actual)
END ;
- IF checkTypeEquivalence (result, GetType (formal), GetType (actual)) = true
+ IF checkTypeEquivalence (result, tinfo, GetType (formal), GetType (actual)) = true
THEN
RETURN true
END
END ;
- RETURN false
+ RETURN falseReason2 ('the formal unbounded array type {%1a}' +
+ ' and the actual unbounded array type {%2a} differ',
+ tinfo, formal, actual)
END checkUnboundedUnbounded ;
@@ -373,10 +440,14 @@ BEGIN
END
ELSIF IsArray (right)
THEN
- RETURN checkUnboundedArray (result, unbounded, right)
+ RETURN checkUnboundedArray (result, tinfo, unbounded, right)
ELSIF IsUnbounded (right)
THEN
RETURN checkUnboundedUnbounded (result, tinfo, unbounded, right)
+ ELSE
+ RETURN falseReason2 ('the formal unbounded array type {%1a}' +
+ ' and the actual unbounded array type {%2a} differ',
+ tinfo, unbounded, right)
END
END
END ;
@@ -400,7 +471,7 @@ BEGIN
THEN
lSub := GetArraySubscript (left) ;
rSub := GetArraySubscript (right) ;
- result := checkPair (result, tinfo, GetSType (left), GetSType (right)) ;
+ result := checkPair (result, tinfo, GetDType (left), GetDType (right)) ;
IF (lSub # NulSym) AND (rSub # NulSym)
THEN
result := checkSubrange (result, tinfo, getSType (lSub), getSType (rSub))
@@ -423,31 +494,58 @@ BEGIN
END
ELSIF IsArray (left) AND IsConst (right)
THEN
- result := checkPair (result, tinfo, GetType (left), GetType (right))
+ result := checkPair (result, tinfo, GetDType (left), GetDType (right))
ELSIF IsArray (right) AND IsConst (left)
THEN
- result := checkPair (result, tinfo, GetType (left), GetType (right))
+ result := checkPair (result, tinfo, GetDType (left), GetDType (right))
END ;
RETURN result
END checkArrayTypeEquivalence ;
(*
- checkGenericTypeEquivalence - check left and right for generic equivalence.
+ checkCharStringTypeEquivalence - check char and string constants for type equivalence.
*)
-PROCEDURE checkGenericTypeEquivalence (result: status; left, right: CARDINAL) : status ;
+PROCEDURE checkCharStringTypeEquivalence (result: status; tinfo: tInfo;
+ left, right: CARDINAL) : status ;
BEGIN
IF isFalse (result)
THEN
RETURN result
- ELSIF left = right
+ ELSIF left = Char
THEN
- RETURN true
- ELSE
- RETURN result
- END
-END checkGenericTypeEquivalence ;
+ IF IsConst (right)
+ THEN
+ (* We might not know the length of the string yet, in which case we return true. *)
+ IF IsConstString (right) AND
+ ((NOT GccKnowsAbout (right)) OR (GetStringLength (tinfo^.token, right) <= 1))
+ THEN
+ RETURN true
+ ELSE
+ RETURN falseReason2 ('the string {%2a} does not fit into a {%1a}',
+ tinfo, left, right)
+ END
+ ELSIF IsParameter (right)
+ THEN
+ right := GetDType (right) ;
+ IF (right = Char) OR (IsUnbounded (right) AND (SkipType (GetDType (right)) = Char))
+ THEN
+ RETURN true
+ END
+ ELSIF IsArray (right)
+ THEN
+ IF Char = SkipType (GetDType (right))
+ THEN
+ RETURN true
+ END
+ END
+ ELSIF right = Char
+ THEN
+ RETURN checkCharStringTypeEquivalence (result, tinfo, right, left)
+ END ;
+ RETURN result
+END checkCharStringTypeEquivalence ;
(*
@@ -491,7 +589,7 @@ BEGIN
THEN
IF tinfo^.error = NIL
THEN
- (* need to create top level error message first. *)
+ (* We need to create top level error message first. *)
tinfo^.error := NewError (tinfo^.token) ;
(* The parameters to MetaString4 in buildError4 must match the order
of paramters passed to ParameterTypeCompatible. *)
@@ -499,9 +597,17 @@ BEGIN
tinfo^.procedure,
tinfo^.formal, tinfo^.actual,
tinfo^.nth) ;
+ (* Append the overall reason for the failure. *)
+ IF tinfo^.reason # NIL
+ THEN
+ (* The string tinfo^.reason is given to the error handler. *)
+ s := ConCat (s, Mark (InitString (" because "))) ;
+ s := ConCat (s, tinfo^.reason) ;
+ tinfo^.reason := NIL (* Hand over deconstructing to M2MetaError. *)
+ END ;
ErrorString (tinfo^.error, s)
END ;
- (* and also generate a sub error containing detail. *)
+ (* And now also generate a sub error containing detail. *)
IF (left # tinfo^.left) OR (right # tinfo^.right)
THEN
MetaError1 ('formal parameter {%1EDad}', right) ;
@@ -512,7 +618,7 @@ END buildError4 ;
(*
- buildError2 - generate a MetaString2 error. This is called by all three kinds of errors.
+ buildError2 - generate a MetaString2 error.
*)
PROCEDURE buildError2 (tinfo: tInfo; left, right: CARDINAL) ;
@@ -543,6 +649,14 @@ BEGIN
left, right)
END ;
+ (* Lastly the overall reason for the failure. *)
+ IF tinfo^.reason # NIL
+ THEN
+ (* The string tinfo^.reason is given to the error handler. *)
+ s := ConCat (s, Mark (InitString (" because "))) ;
+ s := ConCat (s, tinfo^.reason) ;
+ tinfo^.reason := NIL (* Hand over deconstructing to M2MetaError. *)
+ END ;
ErrorString (tinfo^.error, s)
END
END
@@ -559,7 +673,7 @@ BEGIN
THEN
RETURN true
ELSE
- (* check whether errors are required. *)
+ (* Check whether errors are required. *)
IF tinfo^.format # NIL
THEN
CASE tinfo^.kind OF
@@ -700,11 +814,21 @@ PROCEDURE IsTyped (sym: CARDINAL) : BOOLEAN ;
BEGIN
RETURN IsVar (sym) OR IsParameter (sym) OR IsConstructor (sym) OR
(IsConst (sym) AND IsConstructor (sym)) OR IsParameter (sym) OR
- (IsConst (sym) AND (GetType (sym) # NulSym))
+ (IsConst (sym) AND (GetDType (sym) # NulSym))
END IsTyped ;
(*
+ IsTypeEquivalence - returns TRUE if sym is a type equivalence symbol.
+*)
+
+PROCEDURE IsTypeEquivalence (sym: CARDINAL) : BOOLEAN ;
+BEGIN
+ RETURN IsType (sym) AND (GetDType (sym) # NulSym) AND (GetDType (sym) # sym)
+END IsTypeEquivalence ;
+
+
+(*
isLValue -
*)
@@ -715,6 +839,38 @@ END isLValue ;
(*
+ checkVarTypeEquivalence -
+*)
+
+PROCEDURE checkVarTypeEquivalence (result: status; tinfo: tInfo;
+ left, right: CARDINAL) : status ;
+BEGIN
+ IF isFalse (result)
+ THEN
+ RETURN result
+ ELSIF (left = NulSym) OR (right = NulSym)
+ THEN
+ RETURN true
+ ELSE
+ IF IsVar (left) OR IsVar (right)
+ THEN
+ (* Either left or right will change, so we can call doCheckPair. *)
+ IF IsVar (left)
+ THEN
+ left := getType (left)
+ END ;
+ IF IsVar (right)
+ THEN
+ right := getType (right)
+ END ;
+ RETURN doCheckPair (result, tinfo, left, right)
+ END
+ END ;
+ RETURN result
+END checkVarTypeEquivalence ;
+
+
+(*
checkVarEquivalence - this test must be done early as it checks the symbol mode.
An LValue is treated as a pointer during assignment and the
LValue is attached to a variable. This function skips the variable
@@ -722,40 +878,44 @@ END isLValue ;
*)
PROCEDURE checkVarEquivalence (result: status; tinfo: tInfo;
- left, right: CARDINAL) : status ;
+ des, expr: CARDINAL) : status ;
BEGIN
IF isFalse (result)
THEN
RETURN result
- ELSIF IsTyped (left) OR IsTyped (right)
+ ELSIF IsTyped (des) OR IsTyped (expr)
THEN
IF tinfo^.kind = assignment
THEN
+ IF GetDType (des) = GetDType (expr)
+ THEN
+ RETURN true
(* LValues are only relevant during assignment. *)
- IF isLValue (left) AND (NOT isLValue (right))
+ ELSIF isLValue (des) AND (NOT isLValue (expr))
THEN
- IF SkipType (getType (right)) = Address
+ IF SkipType (getType (expr)) = Address
THEN
RETURN true
- ELSIF IsPointer (SkipType (getType (right)))
+ ELSIF IsPointer (SkipType (getType (expr)))
THEN
- right := GetDType (SkipType (getType (right)))
+ expr := GetDType (SkipType (getType (expr))) ;
+ RETURN doCheckPair (result, tinfo, getType (des), expr)
END
- ELSIF isLValue (right) AND (NOT isLValue (left))
+ ELSIF isLValue (expr) AND (NOT isLValue (des))
THEN
- IF SkipType (getType (left)) = Address
+ IF SkipType (getType (des)) = Address
THEN
RETURN true
- ELSIF IsPointer (SkipType (getType (left)))
+ ELSIF IsPointer (SkipType (getType (des)))
THEN
- left := GetDType (SkipType (getType (left)))
+ des := GetDType (SkipType (getType (des))) ;
+ RETURN doCheckPair (result, tinfo, des, getType (expr))
END
END
END ;
- RETURN doCheckPair (result, tinfo, getType (left), getType (right))
- ELSE
- RETURN result
- END
+ RETURN doCheckPair (result, tinfo, getType (des), getType (expr))
+ END ;
+ RETURN result
END checkVarEquivalence ;
@@ -790,10 +950,15 @@ BEGIN
IsProcedure (typeRight) OR IsRecord (typeRight) OR
IsReallyPointer (typeRight)
THEN
- RETURN false
+ RETURN falseReason1 ('constant string is incompatible with {%1ad}',
+ tinfo, typeRight)
ELSIF IsArray (typeRight)
THEN
- RETURN doCheckPair (result, tinfo, Char, GetType (typeRight))
+ RETURN doCheckPair (result, tinfo, Char, GetDType (typeRight))
+ ELSIF NOT GccKnowsAbout (left)
+ THEN
+ (* We do not know the length of this string, so assume true. *)
+ RETURN true
ELSIF GetStringLength (tinfo^.token, left) = 1
THEN
RETURN doCheckPair (result, tinfo, Char, typeRight)
@@ -805,7 +970,9 @@ BEGIN
typeLeft := GetDType (left) ;
IF IsZRCType (typeLeft) AND IsUnbounded (typeRight)
THEN
- RETURN false
+ RETURN falseReason2 ('the constant {%1a} is incompatible' +
+ ' with an unbounded array of {%2a}',
+ tinfo, typeLeft, typeRight)
ELSE
RETURN doCheckPair (result, tinfo, typeLeft, typeRight)
END
@@ -815,6 +982,58 @@ END checkConstMeta ;
(*
+ checkEnumField -
+*)
+
+PROCEDURE checkEnumField (result: status; tinfo: tInfo;
+ left, right: CARDINAL) : status ;
+VAR
+ typeRight: CARDINAL ;
+BEGIN
+ Assert (IsFieldEnumeration (left)) ;
+ IF isFalse (result)
+ THEN
+ RETURN result
+ ELSIF IsTyped (right)
+ THEN
+ typeRight := GetDType (right) ;
+ IF typeRight = NulSym
+ THEN
+ RETURN result
+ ELSE
+ RETURN doCheckPair (result, tinfo, GetDType (left), typeRight)
+ END
+ END ;
+ RETURN result
+END checkEnumField ;
+
+
+(*
+ checkEnumFieldEquivalence -
+*)
+
+PROCEDURE checkEnumFieldEquivalence (result: status; tinfo: tInfo;
+ left, right: CARDINAL) : status ;
+BEGIN
+ IF isFalse (result)
+ THEN
+ RETURN result
+ ELSIF (left = NulSym) OR (right = NulSym)
+ THEN
+ (* No option but to return true. *)
+ RETURN true
+ ELSIF IsFieldEnumeration (left)
+ THEN
+ RETURN checkEnumField (result, tinfo, left, right)
+ ELSIF IsFieldEnumeration (right)
+ THEN
+ RETURN checkEnumField (result, tinfo, right, left)
+ END ;
+ RETURN result
+END checkEnumFieldEquivalence ;
+
+
+(*
checkConstEquivalence - this check can be done first as it checks symbols which
may have no type. Ie constant strings. These constants
will likely have their type set during quadruple folding.
@@ -861,14 +1080,9 @@ BEGIN
IF IsSubrange (right)
THEN
RETURN doCheckPair (result, tinfo, left, GetDType (right))
- END ;
- IF left = right
- THEN
- RETURN true
- ELSE
- RETURN result
END
- END
+ END ;
+ RETURN result
END checkSubrangeTypeEquivalence ;
@@ -892,7 +1106,7 @@ PROCEDURE isZRC (zrc, sym: CARDINAL) : BOOLEAN ;
BEGIN
IF IsConst (sym)
THEN
- sym := SkipType (GetType (sym))
+ sym := SkipType (GetDType (sym))
END ;
IF (zrc = CType) AND (IsComplexN (sym) OR IsComplexType (sym))
THEN
@@ -911,11 +1125,11 @@ PROCEDURE isSameSizeConst (a, b: CARDINAL) : BOOLEAN ;
BEGIN
IF IsConst (a)
THEN
- a := SkipType (GetType (a)) ;
+ a := SkipType (GetDType (a)) ;
RETURN isZRC (a, b) OR (a = b) OR ((a # NulSym) AND isSameSize (a, b))
ELSIF IsConst (b)
THEN
- b := SkipType (GetType (b)) ;
+ b := SkipType (GetDType (b)) ;
RETURN isZRC (b, a) OR (a = b) OR ((b # NulSym) AND isSameSize (a, b))
END ;
RETURN FALSE
@@ -936,13 +1150,15 @@ END isSameSize ;
checkSystemEquivalence - check whether left and right are system types and whether they have the same size.
*)
-PROCEDURE checkSystemEquivalence (result: status; left, right: CARDINAL) : status ;
+PROCEDURE checkSystemEquivalence (result: status; tinfo: tInfo <* unused *>;
+ left, right: CARDINAL) : status ;
BEGIN
IF isFalse (result) OR (result = visited)
THEN
RETURN result
ELSE
IF (IsGenericSystemType (left) OR IsGenericSystemType (right)) AND
+ GccKnowsAbout (left) AND GccKnowsAbout (right) AND
isSameSize (left, right)
THEN
RETURN true
@@ -957,7 +1173,7 @@ END checkSystemEquivalence ;
a set, record or array.
*)
-PROCEDURE checkTypeKindViolation (result: status;
+PROCEDURE checkTypeKindViolation (result: status; tinfo: tInfo;
left, right: CARDINAL) : status ;
BEGIN
IF isFalse (result) OR (result = visited)
@@ -969,7 +1185,8 @@ BEGIN
(IsRecord (left) OR IsRecord (right)) OR
(IsArray (left) OR IsArray (right))
THEN
- RETURN false
+ RETURN falseReason2 ('a {%1ad} is incompatible with a {%2ad}',
+ tinfo, left, right)
END
END ;
RETURN result
@@ -977,7 +1194,7 @@ END checkTypeKindViolation ;
(*
- doCheckPair - invoke a series of ordered type checks checking compatibility
+ doCheckPair - invoke a series of type checks checking compatibility
between left and right modula2 symbols.
Pre-condition: left and right are modula-2 symbols.
tinfo is configured.
@@ -989,50 +1206,28 @@ END checkTypeKindViolation ;
PROCEDURE doCheckPair (result: status; tinfo: tInfo;
left, right: CARDINAL) : status ;
+VAR
+ i: CARDINAL ;
BEGIN
- IF isFalse (result) OR (result = visited)
+ IF (left = NulSym) OR (right = NulSym)
+ THEN
+ (* We cannot check NulSym. *)
+ RETURN true
+ ELSIF isKnown (result)
THEN
RETURN return (result, tinfo, left, right)
ELSIF left = right
THEN
RETURN return (true, tinfo, left, right)
ELSE
- result := checkConstEquivalence (unknown, tinfo, left, right) ;
- IF NOT isKnown (result)
- THEN
- result := checkVarEquivalence (unknown, tinfo, left, right) ;
- IF NOT isKnown (result)
+ i := 1 ;
+ WHILE i <= HighEquivalence DO
+ result := Equivalence[i] (result, tinfo, left, right) ;
+ IF isKnown (result)
THEN
- result := checkSystemEquivalence (unknown, left, right) ;
- IF NOT isKnown (result)
- THEN
- result := checkSubrangeTypeEquivalence (unknown, tinfo, left, right) ;
- IF NOT isKnown (result)
- THEN
- result := checkBaseTypeEquivalence (unknown, tinfo, left, right) ;
- IF NOT isKnown (result)
- THEN
- result := checkTypeEquivalence (unknown, left, right) ;
- IF NOT isKnown (result)
- THEN
- result := checkArrayTypeEquivalence (result, tinfo, left, right) ;
- IF NOT isKnown (result)
- THEN
- result := checkGenericTypeEquivalence (result, left, right) ;
- IF NOT isKnown (result)
- THEN
- result := checkTypeKindEquivalence (result, tinfo, left, right) ;
- IF NOT isKnown (result)
- THEN
- result := checkTypeKindViolation (result, left, right)
- END
- END
- END
- END
- END
- END
- END
- END
+ RETURN return (result, tinfo, left, right)
+ END ;
+ INC (i)
END
END ;
RETURN return (result, tinfo, left, right)
@@ -1040,6 +1235,45 @@ END doCheckPair ;
(*
+ InitEquivalenceArray - populate the Equivalence array with the
+ checking procedures.
+*)
+
+PROCEDURE InitEquivalenceArray ;
+BEGIN
+ HighEquivalence := 0 ;
+ addEquivalence (checkVarEquivalence) ;
+ addEquivalence (checkVarTypeEquivalence) ;
+ addEquivalence (checkCharStringTypeEquivalence) ;
+ addEquivalence (checkConstEquivalence);
+ addEquivalence (checkEnumFieldEquivalence) ;
+ addEquivalence (checkSystemEquivalence) ;
+ addEquivalence (checkSubrangeTypeEquivalence) ;
+ addEquivalence (checkBaseTypeEquivalence) ;
+ addEquivalence (checkTypeEquivalence) ;
+ addEquivalence (checkArrayTypeEquivalence) ;
+ addEquivalence (checkTypeKindEquivalence) ;
+ addEquivalence (checkTypeKindViolation)
+END InitEquivalenceArray ;
+
+
+(*
+ addEquivalence - places proc into Equivalence array.
+*)
+
+PROCEDURE addEquivalence (proc: EquivalenceProcedure) ;
+BEGIN
+ INC (HighEquivalence) ;
+ IF HighEquivalence <= MaxEquvalence
+ THEN
+ Equivalence[HighEquivalence] := proc
+ ELSE
+ InternalError ('increase MaxEquivalence constant in M2Check.mod')
+ END
+END addEquivalence ;
+
+
+(*
checkProcType -
*)
@@ -1090,6 +1324,12 @@ BEGIN
i := 1 ;
n := NoOfParamAny (left) ;
WHILE i <= n DO
+ IF isFalse (result) OR (result = visited)
+ THEN
+ (* Seen a mismatch therefore return. *)
+ RETURN return (result, tinfo, left, right)
+ END ;
+ result := unknown ; (* Each parameter must match. *)
IF IsVarParamAny (left, i) # IsVarParamAny (right, i)
THEN
IF IsVarParamAny (left, i)
@@ -1281,7 +1521,6 @@ BEGIN
END checkProcTypeEquivalence ;
-
(*
checkTypeKindEquivalence -
*)
@@ -1551,7 +1790,7 @@ BEGIN
THEN
RETURN Address
ELSE
- RETURN GetSType (sym)
+ RETURN GetDType (sym)
END
END getSType ;
@@ -1627,11 +1866,19 @@ BEGIN
printf ("doCheck (%d, %d)\n", left, right) ;
dumptInfo (tinfo)
END ;
- IF isInternal (left) OR isInternal (right)
+ IF (left = NulSym) OR (right = NulSym)
+ THEN
+ (* Cannot test if a type is NulSym, we assume true.
+ It maybe that later on a symbols type is set and later
+ on checking will be called and more accurately resolved.
+ For example constant strings can be concatenated during
+ the quadruple folding phase. *)
+ RETURN TRUE
+ ELSIF isInternal (left) OR isInternal (right)
THEN
(* Do not check constants which have been generated internally.
- Currently these are generated by the default BY constant value
- in a FOR loop. *)
+ Currently these are generated by the default BY constant
+ value in a FOR loop. *)
RETURN TRUE
END ;
(*
@@ -1650,9 +1897,9 @@ BEGIN
result := tinfo^.checkFunc (unknown, tinfo, left, right) ;
IF isKnown (result)
THEN
- (* remove this pair from the unresolved list. *)
+ (* Remove this pair from the unresolved list. *)
exclude (tinfo^.unresolved, left, right) ;
- (* add it to the resolved list. *)
+ (* Add it to the resolved list. *)
include (tinfo^.resolved, left, right, result) ;
IF result = false
THEN
@@ -1757,6 +2004,7 @@ END deconstructIndex ;
PROCEDURE deconstruct (tinfo: tInfo) ;
BEGIN
tinfo^.format := KillString (tinfo^.format) ;
+ tinfo^.reason := KillString (tinfo^.reason) ;
tinfo^.visited := deconstructIndex (tinfo^.visited) ;
tinfo^.resolved := deconstructIndex (tinfo^.resolved) ;
tinfo^.unresolved := deconstructIndex (tinfo^.unresolved)
@@ -1803,11 +2051,14 @@ END collapseString ;
*)
PROCEDURE AssignmentTypeCompatible (token: CARDINAL; format: ARRAY OF CHAR;
- des, expr: CARDINAL) : BOOLEAN ;
+ des, expr: CARDINAL;
+ enableReason: BOOLEAN) : BOOLEAN ;
VAR
tinfo: tInfo ;
BEGIN
tinfo := newtInfo () ;
+ tinfo^.reason := NIL ;
+ tinfo^.reasonEnable := enableReason AND StrictTypeReason ;
tinfo^.format := collapseString (format) ;
tinfo^.token := token ;
tinfo^.kind := assignment ;
@@ -1852,6 +2103,8 @@ BEGIN
tinfo := newtInfo () ;
formalT := getSType (formal) ;
actualT := getSType (actual) ;
+ tinfo^.reasonEnable := StrictTypeReason ;
+ tinfo^.reason := NIL ;
tinfo^.format := collapseString (format) ;
tinfo^.token := token ;
tinfo^.kind := parameter ;
@@ -1896,6 +2149,8 @@ VAR
tinfo: tInfo ;
BEGIN
tinfo := newtInfo () ;
+ tinfo^.reasonEnable := StrictTypeReason ;
+ tinfo^.reason := NIL ;
tinfo^.format := collapseString (format) ;
tinfo^.token := token ;
tinfo^.kind := expression ;
@@ -1960,7 +2215,8 @@ PROCEDURE init ;
BEGIN
pairFreeList := NIL ;
tinfoFreeList := NIL ;
- errors := InitIndex (1)
+ errors := InitIndex (1) ;
+ InitEquivalenceArray
END init ;
diff --git a/gcc/m2/gm2-compiler/M2GenGCC.mod b/gcc/m2/gm2-compiler/M2GenGCC.mod
index 2dfa566..4a9ced3 100644
--- a/gcc/m2/gm2-compiler/M2GenGCC.mod
+++ b/gcc/m2/gm2-compiler/M2GenGCC.mod
@@ -681,7 +681,7 @@ BEGIN
IfGreOp : CodeIfGre (q) |
IfInOp : CodeIfIn (q) |
IfNotInOp : CodeIfNotIn (q) |
- IndrXOp : CodeIndrX (q, op1, op2, op3) |
+ IndrXOp : CodeIndrX (q) |
XIndrOp : CodeXIndr (q) |
CallOp : CodeCall (CurrentQuadToken, op3) |
ParamOp : CodeParam (q) |
@@ -3004,7 +3004,7 @@ BEGIN
despos, op2pos, exprpos) ;
Assert (op2pos = UnknownTokenNo) ;
IF StrictTypeChecking AND
- (NOT AssignmentTypeCompatible (despos, "", des, expr))
+ (NOT AssignmentTypeCompatible (despos, "", des, expr, TRUE))
THEN
MetaErrorT2 (MakeVirtualTok (becomespos, despos, exprpos),
'assignment check caught mismatch between {%1Ead} and {%2ad}',
@@ -3233,7 +3233,7 @@ BEGIN
IF SkipType(GetTypeMode(op1))#SkipType(GetTypeMode(op3))
THEN
DescribeTypeError (tokenno, op1, op3) ;
- (* Assigning an errant op3 might ICE, therefore it is safer to return op1. *)
+ (* Assigning an errant op3 might ICE, therefore it is safer to return op1. *)
RETURN( Mod2Gcc (op1) )
END
END ;
@@ -3550,7 +3550,7 @@ BEGIN
location := TokenToLocation (virtpos) ;
IF StrictTypeChecking AND
- (NOT AssignmentTypeCompatible (virtpos, "", des, expr))
+ (NOT AssignmentTypeCompatible (virtpos, "", des, expr, TRUE))
THEN
ErrorMessageDecl (virtpos,
'assignment check caught mismatch between {%1Ead} and {%2ad}',
@@ -3918,8 +3918,6 @@ END NoWalkProcedure ;
PROCEDURE CheckBinaryExpressionTypes (quad: CARDINAL; p: WalkAction) : BOOLEAN ;
VAR
- lefttype,
- righttype,
des, left, right: CARDINAL ;
typeChecking,
constExpr,
@@ -3937,10 +3935,8 @@ BEGIN
IF typeChecking AND (op # LogicalRotateOp) AND (op # LogicalShiftOp)
THEN
subexprpos := MakeVirtualTok (operatorpos, leftpos, rightpos) ;
- lefttype := GetType (left) ;
- righttype := GetType (right) ;
IF StrictTypeChecking AND
- (NOT ExpressionTypeCompatible (subexprpos, "", lefttype, righttype,
+ (NOT ExpressionTypeCompatible (subexprpos, "", left, right,
StrictTypeChecking, FALSE))
THEN
MetaErrorT2 (subexprpos,
@@ -3950,19 +3946,6 @@ BEGIN
SubQuad (quad) ;
p (des) ;
RETURN FALSE
- END ;
- (* --fixme-- the ExpressionTypeCompatible above should be enough
- and the code below can be removed once ExpressionTypeCompatible
- is bug free. *)
- IF NOT IsExpressionCompatible (lefttype, righttype)
- THEN
- ErrorMessageDecl (subexprpos,
- 'expression mismatch between {%1Etad} and {%2tad}',
- left, right, TRUE) ;
- NoChange := FALSE ;
- SubQuad (quad) ;
- p (des) ;
- RETURN FALSE
END
END ;
RETURN TRUE
@@ -3978,7 +3961,6 @@ END CheckBinaryExpressionTypes ;
PROCEDURE CheckElementSetTypes (quad: CARDINAL) : BOOLEAN ;
VAR
- lefttype,
righttype,
ignore, left, right: CARDINAL ;
constExpr,
@@ -3995,13 +3977,9 @@ BEGIN
overflowChecking, constExpr,
leftpos, rightpos, ignorepos) ;
subexprpos := MakeVirtualTok (operatorpos, leftpos, rightpos) ;
- lefttype := GetType (left) ;
righttype := GetType (right) ;
- (* --fixme-- the ExpressionTypeCompatible below does not always catch
- type errors, it needs to be fixed and then some of the subsequent tests
- can be removed (and/or this procedure function rewritten). *)
IF StrictTypeChecking AND
- (NOT ExpressionTypeCompatible (subexprpos, "", lefttype, righttype,
+ (NOT ExpressionTypeCompatible (subexprpos, "", left, right,
StrictTypeChecking, TRUE))
THEN
MetaErrorT2 (subexprpos,
@@ -4020,17 +3998,6 @@ BEGIN
SubQuad (quad) ;
RETURN FALSE
END ;
- righttype := GetType (SkipType (righttype)) ;
- (* Now fall though and compare the set element left against the type of set righttype. *)
- IF NOT IsExpressionCompatible (lefttype, righttype)
- THEN
- ErrorMessageDecl (subexprpos,
- 'the types used in expression {%1Etad} {%kIN} {%2tad} are incompatible',
- left, right, TRUE) ;
- NoChange := FALSE ;
- SubQuad (quad) ;
- RETURN FALSE
- END ;
RETURN TRUE
END CheckElementSetTypes ;
@@ -8174,25 +8141,52 @@ END CodeIfNotIn ;
(op2 is the type of the data being indirectly copied)
*)
-PROCEDURE CodeIndrX (quad: CARDINAL; op1, op2, op3: CARDINAL) ;
+PROCEDURE CodeIndrX (quad: CARDINAL) ;
VAR
- location: location_t ;
+ constExpr,
+ overflowChecking: BOOLEAN ;
+ op : QuadOperator ;
+ tokenno,
+ left,
+ type,
+ right,
+ leftpos,
+ rightpos,
+ typepos,
+ indrxpos : CARDINAL ;
+ length,
+ newstr : tree ;
+ location : location_t ;
BEGIN
- location := TokenToLocation (CurrentQuadToken) ;
+ GetQuadOtok (quad, indrxpos, op, left, type, right,
+ overflowChecking, constExpr,
+ leftpos, typepos, rightpos) ;
+ tokenno := MakeVirtualTok (indrxpos, leftpos, rightpos) ;
+ location := TokenToLocation (tokenno) ;
(*
Follow the Quadruple rules:
*)
- DeclareConstant (CurrentQuadToken, op3) ; (* checks to see whether it is a constant and declares it *)
- DeclareConstructor (CurrentQuadToken, quad, op3) ;
- IF IsConstString (op3)
+ DeclareConstant (rightpos, right) ; (* Checks to see whether it is a constant
+ and if necessary declare it. *)
+ DeclareConstructor (rightpos, quad, right) ;
+ IF IsConstString (right)
THEN
InternalError ('not expecting to index through a constant string')
+ ELSIF StrictTypeChecking AND
+ (NOT AssignmentTypeCompatible (indrxpos, "", left, GetType (right), TRUE))
+ THEN
+ MetaErrorT2 (tokenno,
+ 'assignment check caught mismatch between {%1Ead} and {%2ad}',
+ left, right) ;
+ SubQuad (quad)
ELSE
+
(*
Mem[op1] := Mem[Mem[op3]]
*)
- BuildAssignmentStatement (location, Mod2Gcc (op1), BuildIndirect (location, Mod2Gcc (op3), Mod2Gcc (op2)))
+ BuildAssignmentStatement (location, Mod2Gcc (left),
+ BuildIndirect (location, Mod2Gcc (right), Mod2Gcc (type)))
END
END CodeIndrX ;
@@ -8230,7 +8224,7 @@ BEGIN
DeclareConstant (rightpos, right) ;
DeclareConstructor (rightpos, quad, right) ;
IF StrictTypeChecking AND
- (NOT AssignmentTypeCompatible (xindrpos, "", GetType (left), right))
+ (NOT AssignmentTypeCompatible (xindrpos, "", GetType (left), right, TRUE))
THEN
MetaErrorT2 (tokenno,
'assignment check caught mismatch between {%1Ead} and {%2ad}',
diff --git a/gcc/m2/gm2-compiler/M2MetaError.def b/gcc/m2/gm2-compiler/M2MetaError.def
index cfe9195..3dfe9fa 100644
--- a/gcc/m2/gm2-compiler/M2MetaError.def
+++ b/gcc/m2/gm2-compiler/M2MetaError.def
@@ -93,9 +93,9 @@ FROM NameKey IMPORT Name ;
%} }
the error messages may also embed optional strings such as:
- {%1a:this string is emitted if the symbol name is non null}
- {!%1a:this string is emitted if the symbol name is null}
- {!%1a:{%1d}}
+ {%1a:this string is emitted if the symbol name is null}
+ {!%1a:this string is emitted if the symbol name is non null}
+ {%1a:{%1d}}
if the symbol name does not exist then print a description
of the symbol.
{%1atd} was incompatible with the return type of the procedure
diff --git a/gcc/m2/gm2-compiler/M2Options.def b/gcc/m2/gm2-compiler/M2Options.def
index 2b78add..4cb7f8f 100644
--- a/gcc/m2/gm2-compiler/M2Options.def
+++ b/gcc/m2/gm2-compiler/M2Options.def
@@ -87,6 +87,8 @@ VAR
LineDirectives, (* Should compiler understand preprocessor *)
(* # linenumber "filename" markers? *)
StrictTypeChecking, (* -fm2-strict-type experimental checker. *)
+ StrictTypeAssignment, (* -fm2-strict-assignment. *)
+ StrictTypeReason, (* -fm2-strict-reason. *)
CPreProcessor, (* Must we run the cpp on the source? *)
Xcode, (* Should errors follow Xcode format? *)
ExtendedOpaque, (* Do we allow non pointer opaque types? *)
@@ -756,6 +758,20 @@ PROCEDURE SetStrictTypeChecking (value: BOOLEAN) ;
(*
+ SetStrictTypeAssignment - assigns the StrictTypeAssignment flag to value.
+*)
+
+PROCEDURE SetStrictTypeAssignment (value: BOOLEAN) ;
+
+
+(*
+ SetStrictTypeReason - assigns the StrictTypeReason flag to value.
+*)
+
+PROCEDURE SetStrictTypeReason (value: BOOLEAN) ;
+
+
+(*
setdefextension - set the source file definition module extension to arg.
This should include the . and by default it is set to .def.
*)
diff --git a/gcc/m2/gm2-compiler/M2Options.mod b/gcc/m2/gm2-compiler/M2Options.mod
index 39f0b2a..542b87b 100644
--- a/gcc/m2/gm2-compiler/M2Options.mod
+++ b/gcc/m2/gm2-compiler/M2Options.mod
@@ -657,6 +657,26 @@ END SetStrictTypeChecking ;
(*
+ SetStrictTypeAssignment - assigns the StrictTypeAssignment flag to value.
+*)
+
+PROCEDURE SetStrictTypeAssignment (value: BOOLEAN) ;
+BEGIN
+ StrictTypeAssignment := value
+END SetStrictTypeAssignment ;
+
+
+(*
+ SetStrictTypeReason - assigns the StrictTypeReason flag to value.
+*)
+
+PROCEDURE SetStrictTypeReason (value: BOOLEAN) ;
+BEGIN
+ StrictTypeReason := value
+END SetStrictTypeReason ;
+
+
+(*
SetVerboseUnbounded - sets the VerboseUnbounded flag to, value.
*)
@@ -2111,6 +2131,8 @@ BEGIN
UnusedVariableChecking := FALSE ;
UnusedParameterChecking := FALSE ;
StrictTypeChecking := TRUE ;
+ StrictTypeAssignment := TRUE ;
+ StrictTypeReason := TRUE ;
AutoInit := FALSE ;
SaveTemps := FALSE ;
ScaffoldDynamic := TRUE ;
diff --git a/gcc/m2/gm2-compiler/M2Quads.mod b/gcc/m2/gm2-compiler/M2Quads.mod
index 4022657..3c29fdd 100644
--- a/gcc/m2/gm2-compiler/M2Quads.mod
+++ b/gcc/m2/gm2-compiler/M2Quads.mod
@@ -226,6 +226,7 @@ FROM M2Options IMPORT NilChecking,
GenerateLineDebug, Exceptions,
Profiling, Coding, Optimizing,
UninitVariableChecking,
+ StrictTypeAssignment,
ScaffoldDynamic, ScaffoldStatic, cflag,
ScaffoldMain, SharedFlag, WholeProgram,
GetDumpDir, GetM2DumpFilter,
@@ -258,8 +259,10 @@ FROM M2Range IMPORT InitAssignmentRangeCheck,
InitRotateCheck,
InitShiftCheck,
InitTypesAssignmentCheck,
+ InitTypesIndrXCheck,
InitTypesExpressionCheck,
InitTypesParameterCheck,
+ InitTypesReturnTypeCheck,
InitForLoopBeginRangeCheck,
InitForLoopToRangeCheck,
InitForLoopEndRangeCheck,
@@ -284,7 +287,6 @@ IMPORT M2Error, FIO, SFIO, DynamicStrings, StdIO ;
CONST
DebugStackOn = TRUE ;
DebugVarients = FALSE ;
- BreakAtQuad = 758 ;
DebugTokPos = FALSE ;
TYPE
@@ -397,6 +399,7 @@ VAR
(* in order. *)
NoOfQuads : CARDINAL ; (* Number of used quadruples. *)
Head : CARDINAL ; (* Head of the list of quadruples. *)
+ BreakQuad : CARDINAL ; (* Stop when BreakQuad is created. *)
(*
@@ -1487,22 +1490,6 @@ BEGIN
END AddQuadInformation ;
-PROCEDURE stop ; BEGIN END stop ;
-
-
-(*
- CheckBreak - check whether QuadNo = BreakAtQuad and if so call stop.
-*)
-
-PROCEDURE CheckBreak (QuadNo: CARDINAL) ;
-BEGIN
- IF QuadNo = BreakAtQuad
- THEN
- stop
- END
-END CheckBreak ;
-
-
(*
PutQuadO - alters a quadruple QuadNo with Op, Oper1, Oper2, Oper3, and
sets a boolean to determinine whether overflow should be checked.
@@ -3888,6 +3875,10 @@ BEGIN
THEN
MetaErrorT1 (combinedtok, 'combined {%1Oad}', Des)
END ;
+ IF StrictTypeAssignment
+ THEN
+ BuildRange (InitTypesAssignmentCheck (combinedtok, Des, Exp))
+ END ;
IF (GetSType (Des) # NulSym) AND (NOT IsSet (GetDType (Des)))
THEN
(* Tell code generator to test runtime values of assignment so ensure we
@@ -5628,7 +5619,7 @@ VAR
proctok,
paramtok : CARDINAL ;
n1, n2 : Name ;
- ParamCheckId,
+ ParamCheckId,
Dim,
Actual,
FormalI,
@@ -5770,42 +5761,46 @@ VAR
CheckedProcedure: CARDINAL ;
e : Error ;
BEGIN
- n := NoOfParamAny (ProcType) ;
IF IsVar(call) OR IsTemporary(call) OR IsParameter(call)
THEN
CheckedProcedure := GetDType(call)
ELSE
CheckedProcedure := call
END ;
- IF n # NoOfParamAny (CheckedProcedure)
+ IF ProcType # CheckedProcedure
THEN
- e := NewError(GetDeclaredMod(ProcType)) ;
- n1 := GetSymName(call) ;
- n2 := GetSymName(ProcType) ;
- ErrorFormat2(e, 'procedure (%a) is a parameter being passed as variable (%a) but they are declared with different number of parameters',
- n1, n2) ;
- e := ChainError(GetDeclaredMod(call), e) ;
- t := NoOfParamAny (CheckedProcedure) ;
- IF n<2
+ n := NoOfParamAny (ProcType) ;
+ (* We need to check the formal parameters between the procedure and proc type. *)
+ IF n # NoOfParamAny (CheckedProcedure)
THEN
- ErrorFormat3(e, 'procedure (%a) is being called incorrectly with (%d) parameter, declared with (%d)',
- n1, n, t)
- ELSE
- ErrorFormat3(e, 'procedure (%a) is being called incorrectly with (%d) parameters, declared with (%d)',
- n1, n, t)
- END
- ELSE
- i := 1 ;
- WHILE i<=n DO
- IF IsVarParamAny (ProcType, i) # IsVarParamAny (CheckedProcedure, i)
+ e := NewError(GetDeclaredMod(ProcType)) ;
+ n1 := GetSymName(call) ;
+ n2 := GetSymName(ProcType) ;
+ ErrorFormat2(e, 'procedure (%a) is a parameter being passed as variable (%a) but they are declared with different number of parameters',
+ n1, n2) ;
+ e := ChainError(GetDeclaredMod(call), e) ;
+ t := NoOfParamAny (CheckedProcedure) ;
+ IF n<2
THEN
- MetaError3 ('parameter {%3n} in {%1dD} causes a mismatch it was declared as a {%2d}', ProcType, GetNth (ProcType, i), i) ;
- MetaError3 ('parameter {%3n} in {%1dD} causes a mismatch it was declared as a {%2d}', call, GetNth (call, i), i)
- END ;
- BuildRange (InitTypesParameterCheck (tokno, CheckedProcedure, i,
- GetNthParamAnyClosest (CheckedProcedure, i, GetCurrentModule ()),
- GetParam (ProcType, i), ParamCheckId)) ;
- INC(i)
+ ErrorFormat3(e, 'procedure (%a) is being called incorrectly with (%d) parameter, declared with (%d)',
+ n1, n, t)
+ ELSE
+ ErrorFormat3(e, 'procedure (%a) is being called incorrectly with (%d) parameters, declared with (%d)',
+ n1, n, t)
+ END
+ ELSE
+ i := 1 ;
+ WHILE i<=n DO
+ IF IsVarParamAny (ProcType, i) # IsVarParamAny (CheckedProcedure, i)
+ THEN
+ MetaError3 ('parameter {%3n} in {%1dD} causes a mismatch it was declared as a {%2d}', ProcType, GetNth (ProcType, i), i) ;
+ MetaError3 ('parameter {%3n} in {%1dD} causes a mismatch it was declared as a {%2d}', call, GetNth (call, i), i)
+ END ;
+ BuildRange (InitTypesParameterCheck (tokno, CheckedProcedure, i,
+ GetNthParamAnyClosest (CheckedProcedure, i, GetCurrentModule ()),
+ GetParam (ProcType, i), ParamCheckId)) ;
+ INC(i)
+ END
END
END
END CheckProcTypeAndProcedure ;
@@ -6272,21 +6267,24 @@ END ExpectVariable ;
doIndrX - perform des = *exp with a conversion if necessary.
*)
-PROCEDURE doIndrX (tok: CARDINAL;
- des, exp: CARDINAL) ;
+PROCEDURE doIndrX (tok: CARDINAL; des, exp: CARDINAL) ;
VAR
t: CARDINAL ;
BEGIN
- IF GetDType(des)=GetDType(exp)
+ IF GetDType (des) = GetDType (exp)
THEN
GenQuadOtok (tok, IndrXOp, des, GetSType (des), exp, TRUE,
tok, tok, tok)
ELSE
+ IF StrictTypeAssignment
+ THEN
+ BuildRange (InitTypesIndrXCheck (tok, des, exp))
+ END ;
t := MakeTemporary (tok, RightValue) ;
PutVar (t, GetSType (exp)) ;
GenQuadOtok (tok, IndrXOp, t, GetSType (exp), exp, TRUE,
tok, tok, tok) ;
- GenQuadOtok (tok, BecomesOp, des, NulSym, doVal (GetSType(des), t), TRUE,
+ GenQuadOtok (tok, BecomesOp, des, NulSym, doVal (GetSType (des), t), TRUE,
tok, UnknownTokenNo, tok)
END
END doIndrX ;
@@ -11295,7 +11293,7 @@ BEGIN
n1, n2)
ELSE
(* this checks the types are compatible, not the data contents. *)
- BuildRange (InitTypesAssignmentCheck (tokno, currentProc, actualVal))
+ BuildRange (InitTypesReturnTypeCheck (tokno, currentProc, actualVal))
END
END CheckReturnType ;
@@ -16061,12 +16059,55 @@ END StressStack ;
(*
+ gdbhook - a debugger convenience hook.
+*)
+
+PROCEDURE gdbhook ;
+END gdbhook ;
+
+
+(*
+ BreakWhenQuadCreated - to be called interactively by gdb.
+*)
+
+PROCEDURE BreakWhenQuadCreated (quad: CARDINAL) ;
+BEGIN
+ BreakQuad := quad
+END BreakWhenQuadCreated ;
+
+
+(*
+ CheckBreak - if quad = BreakQuad then call gdbhook.
+*)
+
+PROCEDURE CheckBreak (quad: CARDINAL) ;
+BEGIN
+ IF quad = BreakQuad
+ THEN
+ gdbhook
+ END
+END CheckBreak ;
+
+
+(*
Init - initialize the M2Quads module, all the stacks, all the lists
and the quads list.
*)
PROCEDURE Init ;
BEGIN
+ BreakWhenQuadCreated (0) ; (* Disable the intereactive quad watch. *)
+ (* To examine the quad table when a quad is created run cc1gm2 from gdb
+ and set a break point on gdbhook.
+ (gdb) break gdbhook
+ (gdb) run
+ Now below interactively call BreakWhenQuadCreated with the quad
+ under investigation. *)
+ gdbhook ;
+ (* Now is the time to interactively call gdb, for example:
+ (gdb) print BreakWhenQuadCreated (1234)
+ (gdb) cont
+ and you will arrive at gdbhook when this quad is created. *)
LogicalOrTok := MakeKey('_LOR') ;
LogicalAndTok := MakeKey('_LAND') ;
LogicalXorTok := MakeKey('_LXOR') ;
diff --git a/gcc/m2/gm2-compiler/M2Range.def b/gcc/m2/gm2-compiler/M2Range.def
index 42aa142..e825d94 100644
--- a/gcc/m2/gm2-compiler/M2Range.def
+++ b/gcc/m2/gm2-compiler/M2Range.def
@@ -291,6 +291,24 @@ PROCEDURE InitTypesExpressionCheck (tokno: CARDINAL; d, e: CARDINAL;
(*
+ InitTypesIndrXCheck - checks to see that the types of d and e
+ are assignment compatible. The type checking
+ will dereference *e during the type check.
+ d = *e.
+*)
+
+PROCEDURE InitTypesIndrXCheck (tokno: CARDINAL; d, e: CARDINAL) : CARDINAL ;
+
+
+(*
+ InitTypesReturnTypeCheck - checks to see that the type of val can
+ be returned from func.
+*)
+
+PROCEDURE InitTypesReturnTypeCheck (tokno: CARDINAL; func, val: CARDINAL) : CARDINAL ;
+
+
+(*
InitCaseBounds - creates a case bound range check.
*)
diff --git a/gcc/m2/gm2-compiler/M2Range.mod b/gcc/m2/gm2-compiler/M2Range.mod
index 8e3943a..dcac2ba 100644
--- a/gcc/m2/gm2-compiler/M2Range.mod
+++ b/gcc/m2/gm2-compiler/M2Range.mod
@@ -58,7 +58,7 @@ FROM M2Debug IMPORT Assert ;
FROM Indexing IMPORT Index, InitIndex, InBounds, PutIndice, GetIndice ;
FROM Storage IMPORT ALLOCATE ;
FROM M2ALU IMPORT PushIntegerTree, PushInt, ConvertToInt, Equ, Gre, Less, GreEqu ;
-FROM M2Options IMPORT VariantValueChecking, CaseEnumChecking, GetPIM ;
+FROM M2Options IMPORT VariantValueChecking, CaseEnumChecking, GetPIM, StrictTypeAssignment ;
FROM M2Error IMPORT Error, InternalError, ErrorFormat0, ErrorFormat1, ErrorFormat2, FlushErrors,
GetAnnounceScope ;
@@ -91,7 +91,6 @@ FROM M2Check IMPORT ParameterTypeCompatible, ExpressionTypeCompatible, Assignmen
FROM M2Base IMPORT Nil, IsRealType, GetBaseTypeMinMax,
Cardinal, Integer, ZType, IsComplexType,
- IsAssignmentCompatible,
IsExpressionCompatible,
IsParameterCompatible,
ExceptionAssign,
@@ -115,7 +114,9 @@ FROM M2CaseList IMPORT CaseBoundsResolved, OverlappingCaseBounds,
TYPE
TypeOfRange = (assignment, returnassignment, subrangeassignment,
inc, dec, incl, excl, shift, rotate,
- typeexpr, typeassign, typeparam, paramassign,
+ typeindrx, typeexpr, typeassign, typeparam,
+ typereturn,
+ paramassign,
staticarraysubscript,
dynamicarraysubscript,
forloopbegin, forloopto, forloopend,
@@ -289,9 +290,10 @@ BEGIN
excl : RETURN( ExceptionExcl ) |
shift : RETURN( ExceptionShift ) |
rotate : RETURN( ExceptionRotate ) |
- typeassign : InternalError ('not expecting this case value') |
- typeparam : InternalError ('not expecting this case value') |
- typeexpr : InternalError ('not expecting this case value') |
+ typeassign,
+ typeparam,
+ typeexpr,
+ typeindrx : InternalError ('not expecting this case value') |
paramassign : RETURN( ExceptionParameterBounds ) |
staticarraysubscript : RETURN( ExceptionStaticArray ) |
dynamicarraysubscript: RETURN( ExceptionDynamicArray ) |
@@ -822,7 +824,7 @@ END InitRotateCheck ;
(*
- InitTypesAssignmentCheck - checks to see that the types of, d, and, e,
+ InitTypesAssignmentCheck - checks to see that the types of d and e
are assignment compatible.
*)
@@ -837,6 +839,38 @@ END InitTypesAssignmentCheck ;
(*
+ InitTypesIndrXCheck - checks to see that the types of d and e
+ are assignment compatible. The type checking
+ will dereference *e during the type check.
+ d = *e.
+*)
+
+PROCEDURE InitTypesIndrXCheck (tokno: CARDINAL; d, e: CARDINAL) : CARDINAL ;
+VAR
+ r: CARDINAL ;
+BEGIN
+ r := InitRange () ;
+ Assert (PutRangeNoLow (tokno, GetIndice (RangeIndex, r), typeindrx, d, e) # NIL) ;
+ RETURN r
+END InitTypesIndrXCheck ;
+
+
+(*
+ InitTypesReturnTypeCheck - checks to see that the types of des and func
+ are assignment compatible.
+*)
+
+PROCEDURE InitTypesReturnTypeCheck (tokno: CARDINAL; func, val: CARDINAL) : CARDINAL ;
+VAR
+ r: CARDINAL ;
+BEGIN
+ r := InitRange () ;
+ Assert (PutRangeNoLow (tokno, GetIndice (RangeIndex, r), typereturn, func, val) # NIL) ;
+ RETURN r
+END InitTypesReturnTypeCheck ;
+
+
+(*
InitTypesParameterCheck - checks to see that the types of, d,
and, e, are parameter compatible.
*)
@@ -1219,9 +1253,11 @@ BEGIN
excl : RETURN( ExceptionExcl#NulSym ) |
shift : RETURN( ExceptionShift#NulSym ) |
rotate : RETURN( ExceptionRotate#NulSym ) |
- typeassign : RETURN( FALSE ) |
- typeparam : RETURN( FALSE ) |
- typeexpr : RETURN( FALSE ) |
+ typereturn,
+ typeassign,
+ typeparam,
+ typeexpr,
+ typeindrx : RETURN( FALSE ) |
paramassign : RETURN( ExceptionParameterBounds#NulSym ) |
staticarraysubscript : RETURN( ExceptionStaticArray#NulSym ) |
dynamicarraysubscript: RETURN( ExceptionDynamicArray#NulSym ) |
@@ -1246,7 +1282,9 @@ END HandlerExists ;
(*
- FoldAssignment -
+ FoldAssignment - attempts to fold the range violation checks.
+ It does not issue errors on type violations as that
+ is performed by FoldTypeAssign.
*)
PROCEDURE FoldAssignment (tokenno: CARDINAL; q: CARDINAL; r: CARDINAL) ;
@@ -1259,7 +1297,7 @@ BEGIN
TryDeclareConstant (exprtok, expr) ;
IF desLowestType # NulSym
THEN
- IF AssignmentTypeCompatible (tokenno, "", des, expr)
+ IF AssignmentTypeCompatible (tokenno, "", des, expr, FALSE)
THEN
IF GccKnowsAbout (expr) AND IsConst (expr) AND
GetMinMax (tokenno, desLowestType, min, max)
@@ -1275,6 +1313,8 @@ BEGIN
END
END
ELSE
+ (* We do not issue an error if these types are incompatible here
+ as this is done by FoldTypeAssign. *)
SubQuad (q)
END
END
@@ -1757,21 +1797,94 @@ END FoldRotate ;
(*
+ FoldTypeReturnFunc - checks to see that val can be returned from func.
+*)
+
+PROCEDURE FoldTypeReturnFunc (q: CARDINAL; tokenNo: CARDINAL; func, val: CARDINAL; r: CARDINAL) ;
+VAR
+ valType,
+ returnType: CARDINAL ;
+BEGIN
+ returnType := GetType (func) ;
+ IF returnType = NulSym
+ THEN
+ IF NOT reportedError (r)
+ THEN
+ MetaErrorsT2 (tokenNo,
+ 'procedure {%1Da} is not a procedure function',
+ '{%2ad} cannot be returned from {%1Da}',
+ func, val) ;
+ SubQuad(q)
+ END
+ ELSE
+ valType := val ;
+ IF IsVar (val) AND (GetMode (val) = LeftValue)
+ THEN
+ valType := GetType (val)
+ END ;
+ IF AssignmentTypeCompatible (tokenNo, "", returnType, valType, FALSE)
+ THEN
+ SubQuad (q)
+ ELSE
+ IF NOT reportedError (r)
+ THEN
+ MetaErrorsT2 (tokenNo,
+ 'the return type {%1Etad} used in procedure {%1Da}',
+ 'is incompatible with the returned expression {%1ad}}',
+ func, val) ;
+ setReported (r) ;
+ FlushErrors
+ END
+ END
+ END
+END FoldTypeReturnFunc ;
+
+
+(*
FoldTypeAssign -
*)
PROCEDURE FoldTypeAssign (q: CARDINAL; tokenNo: CARDINAL; des, expr: CARDINAL; r: CARDINAL) ;
+BEGIN
+ IF NOT reportedError (r)
+ THEN
+ IF AssignmentTypeCompatible (tokenNo,
+ 'assignment designator {%1Ea} {%1ta:of type {%1ta}}' +
+ ' cannot be assigned with' +
+ ' {%2ad: a {%2td} {%2ad}}{!%2ad: {%2ad} of type {%2tad}}',
+ des, expr, TRUE)
+ THEN
+ SubQuad (q)
+ ELSE
+ setReported (r) ;
+ FlushErrors
+ END
+ END
+END FoldTypeAssign ;
+
+
+(*
+ FoldTypeIndrX - check to see that des = *expr is type compatible.
+*)
+
+PROCEDURE FoldTypeIndrX (q: CARDINAL; tokenNo: CARDINAL; des, expr: CARDINAL; r: CARDINAL) ;
VAR
+ desType,
exprType: CARDINAL ;
BEGIN
- IF IsProcedure(expr)
+ (* Need to skip over a variable or temporary in des and expr so
+ long as expr is not a procedure. In the case of des = *expr,
+ both expr and des will be variables due to the property of
+ indirection. *)
+ desType := GetType (des) ;
+ IF IsProcedure (expr)
THEN
+ (* Must not GetType for a procedure as it gives the return type. *)
exprType := expr
ELSE
- exprType := GetType(expr)
+ exprType := GetType (expr)
END ;
-
- IF IsAssignmentCompatible (GetType(des), exprType)
+ IF AssignmentTypeCompatible (tokenNo, "", GetType (des), GetType (expr), FALSE)
THEN
SubQuad(q)
ELSE
@@ -1785,14 +1898,16 @@ BEGIN
des, expr) ;
ELSE
MetaErrorT3 (tokenNo,
- 'assignment designator {%1Ea} {%1ta:of type {%1ta}} {%1d:is a {%1d}} and expression {%2a} {%3ad:of type {%3ad}} are incompatible',
+ 'assignment designator {%1Ea} {%1ta:of type {%1ta}}' +
+ ' {%1d:is a {%1d}} and expression {%2a} {%3ad:of type' +
+ ' {%3ad}} are incompatible',
des, expr, exprType)
END ;
setReported (r) ;
FlushErrors
END
END
-END FoldTypeAssign ;
+END FoldTypeIndrX ;
(*
@@ -1859,35 +1974,90 @@ END FoldTypeExpr ;
*)
PROCEDURE CodeTypeAssign (tokenNo: CARDINAL; des, expr: CARDINAL; r: CARDINAL) ;
+BEGIN
+ IF NOT AssignmentTypeCompatible (tokenNo, "", des, expr, FALSE)
+ THEN
+ IF NOT reportedError (r)
+ THEN
+ MetaErrorT2 (tokenNo,
+ 'assignment designator {%1Ea} {%1ta:of type {%1ta}} {%1d:is a {%1d}} and expression {%2a} {%2tad:of type {%2tad}} are incompatible',
+ des, expr)
+ END ;
+ setReported (r)
+ END
+END CodeTypeAssign ;
+
+
+(*
+ CodeTypeReturnFunc -
+*)
+
+PROCEDURE CodeTypeReturnFunc (tokenNo: CARDINAL; func, val: CARDINAL; r: CARDINAL) ;
VAR
- exprType: CARDINAL ;
+ valType,
+ returnType: CARDINAL ;
BEGIN
- IF IsProcedure(expr)
+ returnType := GetType (func) ;
+ IF returnType = NulSym
THEN
- exprType := expr
+ IF NOT reportedError (r)
+ THEN
+ MetaErrorsT2 (tokenNo,
+ 'procedure {%1Da} is not a procedure function',
+ '{%2ad} cannot be returned from {%1Da}',
+ func, val) ;
+ END
ELSE
- exprType := GetType(expr)
- END ;
- IF NOT IsAssignmentCompatible(GetType(des), exprType)
+ valType := val ;
+ IF IsVar (val) AND (GetMode (val) = LeftValue)
+ THEN
+ valType := GetType (val)
+ END ;
+ IF NOT AssignmentTypeCompatible (tokenNo, "", returnType, valType, FALSE)
+ THEN
+ IF NOT reportedError (r)
+ THEN
+ MetaErrorsT2 (tokenNo,
+ 'the return type {%1Etad} used in procedure function {%1Da}',
+ 'is incompatible with the returned expression {%2EUa} {%2tad:of type {%2tad}}',
+ func, val)
+ END
+ END
+ END
+END CodeTypeReturnFunc ;
+
+
+(*
+ CodeTypeIndrX - checks that des = *expr is type compatible and generates an error if they
+ are not compatible. It skips over the LValue type so that to allow
+ the error messages to pick up the source variable name rather than
+ a temporary name or vague name 'expression'.
+*)
+
+PROCEDURE CodeTypeIndrX (tokenNo: CARDINAL; des, expr: CARDINAL; r: CARDINAL) ;
+BEGIN
+ IF NOT AssignmentTypeCompatible (tokenNo, "", GetType (des), GetType (expr), FALSE)
THEN
IF NOT reportedError (r)
THEN
- IF IsProcedure(des)
+ IF IsProcedure (des)
THEN
- MetaErrorsT2(tokenNo,
- 'the return type {%1Etad} declared in procedure {%1Da}',
- 'is incompatible with the returned expression {%2EUa} {%2tad:of type {%2tad}}',
- des, expr) ;
+ MetaErrorsT2 (tokenNo,
+ 'the return type {%1Etad} declared in procedure {%1Da}',
+ 'is incompatible with the returned expression {%2EUa} {%2tad:of type {%2tad}}',
+ des, expr) ;
ELSE
- MetaErrorT2(tokenNo,
- 'assignment designator {%1Ea} {%1ta:of type {%1ta}} {%1d:is a {%1d}} and expression {%2a} {%2tad:of type {%2tad}} are incompatible',
- des, expr)
+ MetaErrorT2 (tokenNo,
+ 'assignment designator {%1Ea} {%1ta:of type {%1ta}}' +
+ ' {%1d:is a {%1d}} and expression {%2a}' +
+ ' {%2tad:of type {%2tad}} are incompatible',
+ des, expr)
END ;
setReported (r)
END
(* FlushErrors *)
END
-END CodeTypeAssign ;
+END CodeTypeIndrX ;
(*
@@ -1941,9 +2111,11 @@ BEGIN
THEN
CASE type OF
- typeassign: FoldTypeAssign(q, tokenNo, des, expr, r) |
- typeparam: FoldTypeParam(q, tokenNo, des, expr, procedure, paramNo, r) |
- typeexpr: FoldTypeExpr(q, tokenNo, des, expr, strict, isin, r)
+ typeassign: FoldTypeAssign (q, tokenNo, des, expr, r) |
+ typeparam : FoldTypeParam (q, tokenNo, des, expr, procedure, paramNo, r) |
+ typeexpr : FoldTypeExpr (q, tokenNo, des, expr, strict, isin, r) |
+ typeindrx : FoldTypeIndrX (q, tokenNo, des, expr, r) |
+ typereturn: FoldTypeReturnFunc (q, tokenNo, des, expr, r)
ELSE
InternalError ('not expecting to reach this point')
@@ -1974,9 +2146,11 @@ BEGIN
THEN
CASE type OF
- typeassign: CodeTypeAssign(tokenNo, des, expr, r) |
- typeparam: CodeTypeParam(tokenNo, des, expr, procedure, paramNo) |
- typeexpr: CodeTypeExpr(tokenNo, des, expr, strict, isin, r)
+ typeassign: CodeTypeAssign (tokenNo, des, expr, r) |
+ typeparam : CodeTypeParam (tokenNo, des, expr, procedure, paramNo) |
+ typeexpr : CodeTypeExpr (tokenNo, des, expr, strict, isin, r) |
+ typeindrx : CodeTypeIndrX (tokenNo, des, expr, r) |
+ typereturn: CodeTypeReturnFunc (tokenNo, des, expr, r)
ELSE
InternalError ('not expecting to reach this point')
@@ -2005,7 +2179,7 @@ BEGIN
success := TRUE ;
WITH p^ DO
combinedtok := MakeVirtual2Tok (destok, exprtok) ;
- IF NOT AssignmentTypeCompatible (combinedtok, "", des, expr)
+ IF NOT AssignmentTypeCompatible (combinedtok, "", des, expr, TRUE)
THEN
MetaErrorT2 (combinedtok,
'type incompatibility between {%1Et} and {%2t} detected during the assignment of the designator {%1a} to the first expression {%2a} in the {%kFOR} loop',
@@ -2419,9 +2593,11 @@ BEGIN
excl : FoldExcl(tokenno, quad, range) |
shift : FoldShift(tokenno, quad, range) |
rotate : FoldRotate(tokenno, quad, range) |
- typeassign : FoldTypeCheck(tokenno, quad, range) |
- typeparam : FoldTypeCheck(tokenno, quad, range) |
- typeexpr : FoldTypeCheck(tokenno, quad, range) |
+ typereturn,
+ typeassign,
+ typeparam,
+ typeexpr,
+ typeindrx : FoldTypeCheck (tokenno, quad, range) |
paramassign : FoldParameterAssign(tokenno, quad, range) |
staticarraysubscript : FoldStaticArraySubscript(tokenno, quad, range) |
dynamicarraysubscript: FoldDynamicArraySubscript(tokenno, quad, range) |
@@ -3557,6 +3733,8 @@ BEGIN
typeassign : s := NIL |
typeparam : s := NIL |
typeexpr : s := NIL |
+ typeindrx : s := InitString ('assignment between designator {%1ad} and {%2ad} is incompatible') |
+ typereturn : s := InitString ('the value {%2ad} returned from procedure function {%1a} is type incompatible, expecting {%1tad} rather than a {%2tad}') |
paramassign : s := InitString('if this call is executed then the actual parameter {%2Wa} will be out of range of the {%3N} formal parameter {%1a}') |
staticarraysubscript : s := InitString('if this access to the static array {%1Wa:{%2a:{%1a}[{%2a}]}} is ever made then the index will be out of bounds in the {%3N} array subscript') |
dynamicarraysubscript: s := InitString('if this access to the dynamic array {%1Wa:{%2a:{%1a}[{%2a}]}} is ever made then the index will be out of bounds in the {%3N} array subscript') |
@@ -3605,9 +3783,11 @@ BEGIN
excl : CodeInclExcl (tokenNo, r, function, message) |
shift,
rotate : CodeShiftRotate (tokenNo, r, function, message) |
- typeassign : CodeTypeCheck (tokenNo, r) |
- typeparam : CodeTypeCheck (tokenNo, r) |
- typeexpr : CodeTypeCheck (tokenNo, r) |
+ typeassign,
+ typeparam,
+ typeexpr,
+ typeindrx,
+ typereturn : CodeTypeCheck (tokenNo, r) |
staticarraysubscript : CodeStaticArraySubscript (tokenNo, r, function, message) |
dynamicarraysubscript: CodeDynamicArraySubscript (tokenNo, r, function, message) |
forloopbegin : CodeForLoopBegin (tokenNo, r, function, message) |
@@ -3743,6 +3923,8 @@ BEGIN
rotate : WriteString('rotate(') ; WriteOperand(des) ; WriteString(', ') ; WriteOperand(expr) |
typeexpr : WriteString('expr compatible (') ; WriteOperand(des) ; WriteString(', ') ; WriteOperand(expr) |
typeassign : WriteString('assignment compatible (') ; WriteOperand(des) ; WriteString(', ') ; WriteOperand(expr) |
+ typeindrx : WriteString('indrx compatible (') ; WriteOperand(des) ; WriteString(', ') ; WriteOperand(expr) |
+ typereturn : WriteString('return compatible (') ; WriteOperand(des) ; WriteString(', ') ; WriteOperand(expr) |
typeparam : WriteString('parameter compatible (') ; WriteOperand(des) ; WriteString(', ') ; WriteOperand(expr) |
paramassign : WriteString('parameter range (') ; WriteOperand(des) ; WriteString(', ') ; WriteOperand(expr) |
staticarraysubscript : WriteString('staticarraysubscript(') ; WriteOperand(des) ; WriteString(', ') ; WriteOperand(expr) |
diff --git a/gcc/m2/gm2-gcc/m2options.h b/gcc/m2/gm2-gcc/m2options.h
index d60b510..041de26 100644
--- a/gcc/m2/gm2-gcc/m2options.h
+++ b/gcc/m2/gm2-gcc/m2options.h
@@ -168,6 +168,8 @@ EXTERN char *M2Options_GetM2DumpFilter (void);
EXTERN void M2Options_SetM2DebugTraceFilter (bool value, const char *arg);
EXTERN bool M2Options_SetM2Dump (bool value, const char *arg);
EXTERN bool M2Options_GetDumpGimple (void);
+EXTERN void M2Options_SetStrictTypeAssignment (bool value);
+EXTERN void M2Options_SetStrictTypeReason (bool value);
#undef EXTERN
#endif /* m2options_h. */
diff --git a/gcc/m2/gm2-lang.cc b/gcc/m2/gm2-lang.cc
index e8820da..31a2e46 100644
--- a/gcc/m2/gm2-lang.cc
+++ b/gcc/m2/gm2-lang.cc
@@ -525,6 +525,9 @@ gm2_langhook_handle_option (
case OPT_fm2_strict_type:
M2Options_SetStrictTypeChecking (value);
return 1;
+ case OPT_fm2_strict_type_reason:
+ M2Options_SetStrictTypeReason (value);
+ return 1;
case OPT_fm2_debug_trace_:
M2Options_SetM2DebugTraceFilter (value, arg);
return 1;
diff --git a/gcc/m2/gm2-libs-log/InOut.mod b/gcc/m2/gm2-libs-log/InOut.mod
index 79c706a..6b03034 100644
--- a/gcc/m2/gm2-libs-log/InOut.mod
+++ b/gcc/m2/gm2-libs-log/InOut.mod
@@ -257,16 +257,8 @@ END WriteString ;
PROCEDURE LocalWrite (ch: CHAR) ;
BEGIN
FIO.WriteChar(outFile, ch) ;
- Done := FIO.IsNoError(outFile)
-(*
- IF outUsed
- THEN
- FIO.WriteChar(outFile, ch) ;
- Done := FIO.IsNoError(outFile)
- ELSE
- Done := (write(stdout, ADR(ch), 1) = 1)
- END
-*)
+ Done := FIO.IsNoError(outFile) ;
+ FIO.FlushBuffer (outFile)
END LocalWrite ;
diff --git a/gcc/m2/lang.opt b/gcc/m2/lang.opt
index 1ea55f2..48c2380 100644
--- a/gcc/m2/lang.opt
+++ b/gcc/m2/lang.opt
@@ -190,6 +190,10 @@ fm2-strict-type
Modula-2
experimental flag to turn on the new strict type checker
+fm2-strict-type-reason
+Modula-2
+provides more detail why the types are incompatible
+
fm2-whole-program
Modula-2
compile all implementation modules and program module at once
diff --git a/gcc/passes.cc b/gcc/passes.cc
index 0482de0..6c67ffe 100644
--- a/gcc/passes.cc
+++ b/gcc/passes.cc
@@ -64,6 +64,9 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h"
#include "attribs.h"
+/* Reserved TODOs */
+#define TODO_verify_il (1u << 31)
+
using namespace gcc;
/* This is used for debugging. It allows the current pass to printed
@@ -2059,7 +2062,6 @@ execute_function_todo (function *fn, void *data)
{
bool from_ipa_pass = (cfun == NULL);
unsigned int flags = (size_t)data;
- flags &= ~fn->last_verified;
if (!flags)
return;
@@ -2127,8 +2129,6 @@ execute_function_todo (function *fn, void *data)
gcc_assert (dom_info_state (fn, CDI_POST_DOMINATORS) == pre_verify_pstate);
}
- fn->last_verified = flags & TODO_verify_all;
-
pop_cfun ();
/* For IPA passes make sure to release dominator info, it can be
@@ -2193,14 +2193,6 @@ verify_interpass_invariants (void)
gcc_checking_assert (!fold_deferring_overflow_warnings_p ());
}
-/* Clear the last verified flag. */
-
-static void
-clear_last_verified (function *fn, void *data ATTRIBUTE_UNUSED)
-{
- fn->last_verified = 0;
-}
-
/* Helper function. Verify that the properties has been turn into the
properties expected by the pass. */
@@ -2339,13 +2331,15 @@ execute_one_ipa_transform_pass (struct cgraph_node *node,
if (pass->tv_id != TV_NONE)
timevar_push (pass->tv_id);
+ gcc_checking_assert (!(ipa_pass->function_transform_todo_flags_start & TODO_verify_il));
/* Run pre-pass verification. */
execute_todo (ipa_pass->function_transform_todo_flags_start);
/* Do it! */
todo_after = ipa_pass->function_transform (node);
- /* Run post-pass cleanup and verification. */
+ /* Run post-pass cleanup. */
+ gcc_checking_assert (!(todo_after & TODO_verify_il));
execute_todo (todo_after);
verify_interpass_invariants ();
@@ -2391,7 +2385,7 @@ execute_all_ipa_transforms (bool do_not_collect)
for (auto p : node->ipa_transforms_to_apply)
{
- /* To get consistent statistics, we need to account each functio
+ /* To get consistent statistics, we need to account each function
to each IPA pass. */
if (report)
{
@@ -2649,6 +2643,7 @@ execute_one_pass (opt_pass *pass)
/* Run pre-pass verification. */
+ gcc_checking_assert (!(pass->todo_flags_start & TODO_verify_il));
execute_todo (pass->todo_flags_start);
if (flag_checking)
@@ -2697,11 +2692,11 @@ execute_one_pass (opt_pass *pass)
return true;
}
- do_per_function (clear_last_verified, NULL);
-
do_per_function (update_properties_after_pass, pass);
/* Run post-pass cleanup and verification. */
+ gcc_checking_assert (!(todo_after & TODO_verify_il));
+ gcc_checking_assert (!(pass->todo_flags_finish & TODO_verify_il));
execute_todo (todo_after | pass->todo_flags_finish | TODO_verify_il);
if (profile_report)
{
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 7049ed7..8a74021 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -960,6 +960,14 @@ is_a_helper <rtx_call_insn *>::test (rtx_insn *insn)
template <>
template <>
inline bool
+is_a_helper <const rtx_call_insn *>::test (const rtx_insn *insn)
+{
+ return CALL_P (insn);
+}
+
+template <>
+template <>
+inline bool
is_a_helper <rtx_jump_table_data *>::test (rtx rt)
{
return JUMP_TABLE_DATA_P (rt);
@@ -3682,7 +3690,6 @@ extern bool nonzero_address_p (const_rtx);
extern bool rtx_unstable_p (const_rtx);
extern bool rtx_varies_p (const_rtx, bool);
extern bool rtx_addr_varies_p (const_rtx, bool);
-extern rtx get_call_rtx_from (const rtx_insn *);
extern tree get_call_fndecl (const rtx_insn *);
extern HOST_WIDE_INT get_integer_term (const_rtx);
extern rtx get_related_value (const_rtx);
@@ -4572,6 +4579,7 @@ extern void simplify_using_condition (rtx, rtx *, bitmap);
extern void compute_alignments (void);
extern void update_alignments (vec<rtx> &);
extern int asm_str_count (const char *templ);
+extern rtx get_call_rtx_from (const rtx_insn *);
struct rtl_hooks
{
diff --git a/gcc/rtlanal.cc b/gcc/rtlanal.cc
index 900f53e..239d669 100644
--- a/gcc/rtlanal.cc
+++ b/gcc/rtlanal.cc
@@ -813,21 +813,6 @@ rtx_addr_varies_p (const_rtx x, bool for_alias)
return false;
}
-/* Return the CALL in X if there is one. */
-
-rtx
-get_call_rtx_from (const rtx_insn *insn)
-{
- rtx x = PATTERN (insn);
- if (GET_CODE (x) == PARALLEL)
- x = XVECEXP (x, 0, 0);
- if (GET_CODE (x) == SET)
- x = SET_SRC (x);
- if (GET_CODE (x) == CALL && MEM_P (XEXP (x, 0)))
- return x;
- return NULL_RTX;
-}
-
/* Get the declaration of the function called by INSN. */
tree
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 27ddc57..185857d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,351 @@
+2025-06-03 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/99838
+ * gfortran.dg/coarray_data_2.f90: New test.
+
+2025-06-03 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120078
+ * gcc.dg/Wjump-misses-init-3.c: New test.
+
+2025-06-03 Martin Uecker <uecker@tugraz.at>
+
+ * gcc.dg/gnu23-tag-composite-6.c: Update.
+
+2025-06-03 Martin Uecker <uecker@tugraz.at>
+
+ PR c/116892
+ * gcc.dg/pr116892.c: New test.
+
+2025-06-03 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/modules/cpp-1.C
+ * g++.dg/modules/cpp-3.C
+ * g++.dg/modules/cpp-4.C: Specify -fno-modules.
+
+2025-06-03 Pan Li <pan2.li@intel.com>
+
+ * gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv-nofm.c: Adjust
+ the asm check for vdiv.
+ * gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv-nofm.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv.c: Ditto.
+
+2025-06-03 Pan Li <pan2.li@intel.com>
+
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c: Add asm check
+ check for vdiv.vx combine.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c: Ditto.
+
+2025-06-03 Pan Li <pan2.li@intel.com>
+
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c: Add asm check
+ for vdiv.vx combine.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h: Add test
+ data for vdiv run test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i16.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i32.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i64.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i8.c: New test.
+
+2025-06-03 Paul-Antoine Arras <parras@baylibre.com>
+
+ PR target/119100
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f16.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f32.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f64.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f16.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f32.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f64.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f16.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f32.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f64.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f16.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f32.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f64.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop.h: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_data.h: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_run.h: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f32.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f64.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f32.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f64.c: New test.
+
+2025-06-03 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/103750
+ * g++.target/i386/pr103750.C: New test.
+
+2025-06-03 Andrew Pinski <quic_apinski@quicinc.com>
+
+ PR tree-optimization/116824
+ * gcc.dg/tree-ssa/phiprop-2.c: New test.
+
+2025-06-03 Andrew Pinski <quic_apinski@quicinc.com>
+
+ PR tree-optimization/120451
+ * gcc.dg/tree-ssa/cswtch-6.c: New test.
+
+2025-06-02 Alexandre Oliva <oliva@adacore.com>
+
+ PR rtl-optimization/120424
+ PR middle-end/118939
+ * g++.target/arm/pr120424.C: New.
+ * gnat.dg/controlled9.adb: New.
+ * gnat.dg/controlled9_pkg.ads: New.
+
+2025-06-02 Jason Merrill <jason@redhat.com>
+
+ PR c++/107600
+ * g++.dg/ext/is_destructible2.C: Add more cases.
+
+2025-06-02 Dongyan Chen <chendongyan@isrc.iscas.ac.cn>
+
+ * gcc.target/riscv/arch-59.c: New test.
+
+2025-06-02 Jason Merrill <jason@redhat.com>
+
+ PR c++/120506
+ * g++.dg/cpp2a/constinit21.C: New test.
+
+2025-06-02 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/118903
+ * g++.dg/coroutines/pr118903.C: New test.
+
+2025-06-02 Jason Merrill <jason@redhat.com>
+
+ PR c++/107600
+ * g++.dg/ext/is_destructible2.C: New test.
+
+2025-06-02 Jason Merrill <jason@redhat.com>
+
+ PR c++/107600
+ * g++.dg/ext/has_trivial_destructor-3.C: New test.
+
+2025-06-02 Stafford Horne <shorne@gmail.com>
+
+ * gcc.target/or1k/return-2.c: Fix test.
+
+2025-06-02 Stafford Horne <shorne@gmail.com>
+
+ * gcc.target/or1k/call-1.c: New test.
+ * gcc.target/or1k/got-1.c: New test.
+
+2025-06-02 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * lib/target-supports.exp (check_effective_target_tls_link): New.
+ * g++.dg/tls/pr102496-1.C: Require tls_link.
+ * g++.dg/tls/pr77285-1.C: Likewise.
+
+2025-06-02 Sandra Loosemore <sloosemore@baylibre.com>
+
+ * c-c++-common/gomp/declare-variant-2.c: Update expected output.
+ * c-c++-common/gomp/metadirective-condition-constexpr.c: New.
+ * c-c++-common/gomp/metadirective-condition.c: New.
+ * c-c++-common/gomp/metadirective-error-recovery.c: Update expected
+ output.
+ * g++.dg/gomp/metadirective-condition-class.C: New.
+ * g++.dg/gomp/metadirective-condition-template.C: New.
+
+2025-06-02 Liao Shihua <shihua@iscas.ac.cn>
+
+ * gcc.target/riscv/rvv/autovec/param-autovec-mode.c: Change
+ `autovec-mode` to `riscv-autovec-mode` in dg-options.
+
+2025-06-01 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR libfortran/119856
+ * gfortran.dg/pr119856.f90: New test.
+
+2025-06-01 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120380
+ * gcc.dg/pr120380.c: New test.
+
+2025-06-01 Jason Merrill <jason@redhat.com>
+
+ PR c++/120123
+ * g++.dg/cpp23/explicit-obj-lambda18.C: Move to...
+ * g++.dg/cpp2a/concepts-lambda24.C: ...here.
+
+2025-06-01 Gaius Mulley <gaiusmod2@gmail.com>
+
+ PR modula2/120497
+ * gm2/pim/pass/ReturnType.mod: New test.
+ * gm2/pim/pass/ReturnType2.mod: New test.
+
+2025-05-31 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/120357
+ * gcc.dg/vect/vect-early-break_136-pr120357.c: New testcase.
+
+2025-05-31 Gaius Mulley <gaiusmod2@gmail.com>
+
+ PR modula2/120389
+ * gm2/pim/fail/testcharint.mod: New test.
+ * gm2/pim/fail/testindrx.mod: New test.
+ * gm2/pim/pass/testxindr.mod: New test.
+ * gm2/pim/pass/testxindr2.mod: New test.
+ * gm2/pim/pass/testxindr3.mod: New test.
+
+2025-05-30 David Malcolm <dmalcolm@redhat.com>
+
+ PR other/116792
+ * gcc.dg/format/diagnostic-ranges-html.py: New test script.
+ * gcc.dg/format/diagnostic-ranges.c: Add HTML generation to
+ options, and invoke the new script to check the HTML output.
+
+2025-05-30 Jason Merrill <jason@redhat.com>
+
+ PR c++/120123
+ * g++.dg/cpp23/explicit-obj-lambda18.C: New test.
+
+2025-05-30 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/102599
+ PR fortran/114022
+ * gfortran.dg/inquiry_type_ref_8.f90: New test.
+
+2025-05-30 Jason Merrill <jason@redhat.com>
+
+ PR c++/113563
+ * g++.dg/cpp23/explicit-obj-lambda17.C: New test.
+
+2025-05-30 Qing Zhao <qing.zhao@oracle.com>
+
+ PR c/120354
+ * gcc.dg/pr120354.c: New test.
+
+2025-05-30 Qing Zhao <qing.zhao@oracle.com>
+
+ PR c/120353
+ * gcc.dg/pr120353.c: New test.
+
+2025-05-30 Pan Li <pan2.li@intel.com>
+
+ * gcc.target/riscv/rvv/autovec/avg.h: Add test helper macros.
+ * gcc.target/riscv/rvv/autovec/avg_data.h: Add test data for
+ avg_ceil.
+ * gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i32.c: New test.
+ * gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i64.c: New test.
+ * gcc.target/riscv/rvv/autovec/avg_ceil-1-i32-from-i64.c: New test.
+ * gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i16.c: New test.
+ * gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i32.c: New test.
+ * gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i64.c: New test.
+ * gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i16-from-i32.c: New test.
+ * gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i16-from-i64.c: New test.
+ * gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i32-from-i64.c: New test.
+ * gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i16.c: New test.
+ * gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i32.c: New test.
+ * gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i64.c: New test.
+
+2025-05-30 Pan Li <pan2.li@intel.com>
+
+ * gcc.target/riscv/rvv/autovec/vls/avg-4.c: Update asm check
+ to vaadd.
+ * gcc.target/riscv/rvv/autovec/vls/avg-5.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vls/avg-6.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/widen/vec-avg-rv32gcv.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/widen/vec-avg-rv64gcv.c: Ditto.
+
+2025-05-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/120341
+ * gcc.dg/torture/pr120341-1.c: New testcase.
+ * gcc.dg/torture/pr120341-2.c: Likewise.
+
+2025-05-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/120480
+ * gcc.dg/pr120480.c: New test.
+
+2025-05-30 Julian Brown <julian@codesourcery.com>
+
+ * c-c++-common/gomp/declare-mapper-3.c: Enable for C.
+ * c-c++-common/gomp/declare-mapper-4.c: Likewise.
+ * c-c++-common/gomp/declare-mapper-5.c: Likewise.
+ * c-c++-common/gomp/declare-mapper-6.c: Likewise.
+ * c-c++-common/gomp/declare-mapper-7.c: Likewise.
+ * c-c++-common/gomp/declare-mapper-8.c: Likewise.
+ * c-c++-common/gomp/declare-mapper-9.c: Likewise.
+ * c-c++-common/gomp/declare-mapper-10.c: Likewise.
+ * c-c++-common/gomp/declare-mapper-12.c: Likewise.
+ * c-c++-common/gomp/map-6.c: Update dg-error.
+ * gcc.dg/gomp/udr-3.c: Update for change to dg-note.
+ * c-c++-common/gomp/declare-mapper-11.c: New.
+ * gcc.dg/gomp/declare-mapper-10.c: New test.
+ * gcc.dg/gomp/declare-mapper-11.c: New test.
+ * gcc.dg/gomp/declare-mapper-13.c: New test.
+
+2025-05-30 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/120355
+ * gfortran.dg/interface_62.f90: New test.
+
+2025-05-30 David Malcolm <dmalcolm@redhat.com>
+
+ * g++.dg/diagnostic/bad-binary-ops-highlight-colors.C: Update
+ expected multiline output for quoted source and underlines to
+ reflect emitting color codes when changes happen, rather than
+ per character.
+ * g++.dg/diagnostic/long-short-colorization.C: Likewise.
+ * g++.dg/plugin/show-template-tree-color-labels.C: Likewise.
+ * gcc.dg/bad-binary-ops-highlight-colors.c: Likewise.
+ * gcc.dg/format/colors.c: Likewise.
+
+2025-05-30 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR rtl-optimization/120347
+ * gcc.dg/torture/pr120347.c: New test.
+
+2025-05-30 Julian Brown <julian@codesourcery.com>
+ Tobias Burnus <tburnus@baylibre.com>
+
+ * c-c++-common/gomp/map-6.c: Update error scan output.
+ * c-c++-common/gomp/declare-mapper-3.c: New test (only enabled for C++
+ for now).
+ * c-c++-common/gomp/declare-mapper-4.c: Likewise.
+ * c-c++-common/gomp/declare-mapper-5.c: Likewise.
+ * c-c++-common/gomp/declare-mapper-6.c: Likewise.
+ * c-c++-common/gomp/declare-mapper-7.c: Likewise.
+ * c-c++-common/gomp/declare-mapper-8.c: Likewise.
+ * c-c++-common/gomp/declare-mapper-9.c: Likewise.
+ * c-c++-common/gomp/declare-mapper-10.c: Likewise.
+ * c-c++-common/gomp/declare-mapper-12.c: Likewise.
+ * g++.dg/gomp/declare-mapper-1.C: New test.
+ * g++.dg/gomp/declare-mapper-2.C: New test.
+ * g++.dg/gomp/declare-mapper-3.C: New test.
+
+2025-05-30 Martin Uecker <uecker@tugraz.at>
+
+ PR c/120381
+ * gcc.dg/pr120381.c: New test.
+ * gcc.dg/gnu23-tag-composite-6.c: New test.
+
2025-05-29 Kugan Vivekanandarajah <kvivekananda@nvidia.com>
* lib/target-supports.exp: Enable autofdo tests for aarch64.
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c
index f8f5143..83e1bb1 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c
@@ -38,7 +38,7 @@ void f18 (void);
void f19 (void);
#pragma omp declare variant (f1) match(user={condition()}) /* { dg-error "expected \[^\n\r]*expression before '\\)' token" } */
void f20 (void);
-#pragma omp declare variant (f1) match(user={condition(f1)}) /* { dg-error "property must be integer expression" } */
+#pragma omp declare variant (f1) match(user={condition(f1)})
void f21 (void);
#pragma omp declare variant (f1) match(user={condition(1, 2, 3)}) /* { dg-error "expected '\\)' before ',' token" } */
void f22 (void);
diff --git a/gcc/testsuite/c-c++-common/gomp/metadirective-condition-constexpr.c b/gcc/testsuite/c-c++-common/gomp/metadirective-condition-constexpr.c
new file mode 100644
index 0000000..3484478
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/metadirective-condition-constexpr.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { c || c++11 } } } */
+/* { dg-additional-options "-std=c23" { target c } } */
+/* { dg-additional-options "-fdump-tree-original" } */
+
+constexpr int flag = 1;
+
+void f() {
+#pragma omp metadirective when(user={condition(flag)} : nothing) \
+ otherwise(error at(execution))
+}
+
+/* { dg-final { scan-tree-dump-not "__builtin_GOMP_error" "original" } } */
+
diff --git a/gcc/testsuite/c-c++-common/gomp/metadirective-condition.c b/gcc/testsuite/c-c++-common/gomp/metadirective-condition.c
new file mode 100644
index 0000000..099ad9d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/metadirective-condition.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-original" } */
+
+static int arr[10];
+static int g (int a) { return -a; }
+
+void f (int *ptr, float x) {
+
+ /* Implicit conversion float -> bool */
+ #pragma omp metadirective when(user={condition(x)} : nothing) otherwise(nothing)
+
+ /* Implicit conversion pointer -> bool */
+ #pragma omp metadirective when(user={condition(ptr)} : nothing) otherwise(nothing)
+
+ /* Array expression undergoes array->pointer conversion, OK but test is
+ always optimized away. */
+ #pragma omp metadirective when(user={condition(arr)} : nothing) otherwise(nothing)
+
+ /* Function reference has pointer-to-function type, OK but test is
+ always optimized away. */
+ #pragma omp metadirective when(user={condition(g)} : nothing) otherwise(nothing)
+}
+
+/* { dg-final { scan-tree-dump "x != 0.0" "original" } } */
+/* { dg-final { scan-tree-dump "ptr != 0B" "original" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/metadirective-error-recovery.c b/gcc/testsuite/c-c++-common/gomp/metadirective-error-recovery.c
index 3242281..92995a2 100644
--- a/gcc/testsuite/c-c++-common/gomp/metadirective-error-recovery.c
+++ b/gcc/testsuite/c-c++-common/gomp/metadirective-error-recovery.c
@@ -15,6 +15,11 @@ void f (int aa, int bb)
s2.b = bb + 1;
/* A struct is not a valid argument for the condition selector. */
- #pragma omp metadirective when(user={condition(s1)} : nothing) otherwise(nothing) /* { dg-error "property must be integer expression" } */
- #pragma omp metadirective when(user={condition(s2)} : nothing) otherwise(nothing) /* { dg-error "property must be integer expression" } */
+ #pragma omp metadirective when(user={condition(s1)} : nothing) otherwise(nothing)
+ /* { dg-error "used struct type value where scalar is required" "" { target c } .-1 } */
+ /* { dg-error "could not convert .s1. from .s. to .bool." "" { target c++ } .-2 } */
+ #pragma omp metadirective when(user={condition(s2)} : nothing) otherwise(nothing)
+ /* { dg-error "used struct type value where scalar is required" "" { target c } .-1 } */
+ /* { dg-error "could not convert .s2. from .s. to .bool." "" { target c++ } .-2 } */
+
}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr118903.C b/gcc/testsuite/g++.dg/coroutines/pr118903.C
new file mode 100644
index 0000000..a577a9a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr118903.C
@@ -0,0 +1,40 @@
+// { dg-additional-options "-fsyntax-only" }
+
+#include <coroutine>
+
+struct awaitable {
+ constexpr bool await_ready() {
+ return true;
+ }
+ void await_suspend(std::coroutine_handle<void>) {
+
+ }
+ constexpr int await_resume() {
+ return 42;
+ }
+};
+
+struct super_simple_coroutine {
+ struct promise_type {
+ constexpr auto initial_suspend() {
+ return std::suspend_never();
+ }
+ constexpr auto final_suspend() const noexcept {
+ return std::suspend_never();
+ }
+ constexpr void unhandled_exception() {
+ // do nothing
+ }
+ constexpr auto get_return_object() {
+ return super_simple_coroutine{};
+ }
+ constexpr void return_void() {
+ }
+ };
+};
+
+auto fib (float f) -> super_simple_coroutine {
+ // if `co_await` is part of BodyStatement of a function
+ // it makes it coroutine
+ constexpr int x = co_await awaitable{}; // { dg-error {'co_await awaitable..' is not a constant expression} }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda24.C b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda24.C
new file mode 100644
index 0000000..28f56ca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda24.C
@@ -0,0 +1,13 @@
+// PR c++/120123
+// { dg-do compile { target c++20 } }
+
+struct H {
+ void member(int) {}
+ void call() {
+ [this]() {
+ [this](const auto& v)
+ requires requires { /*this->*/member(v); }
+ { return member(v); }(0);
+ };
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/constinit21.C b/gcc/testsuite/g++.dg/cpp2a/constinit21.C
new file mode 100644
index 0000000..18bca90
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constinit21.C
@@ -0,0 +1,28 @@
+// PR c++/120506
+// { dg-do compile { target c++20 } }
+// Test that we give more information about why the init is non-constant
+
+struct A
+{
+ constexpr A(int c) : counter(c) { }
+
+ int counter;
+};
+
+
+struct B : A
+{
+ constexpr B(int c) : A(c) { }
+
+ int i; // OOPS, not initialized
+};
+
+struct C
+{
+ B sem;
+
+ constexpr C(int c) : sem(c) { }
+};
+
+constinit C s(0); // { dg-error "incompletely initialized" }
+// { dg-prune-output "constant" }
diff --git a/gcc/testsuite/g++.dg/ext/has_trivial_destructor-3.C b/gcc/testsuite/g++.dg/ext/has_trivial_destructor-3.C
new file mode 100644
index 0000000..a179be5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/has_trivial_destructor-3.C
@@ -0,0 +1,21 @@
+// { dg-do compile { target c++11 } }
+
+struct X;
+
+template<class T>
+struct default_delete
+{
+ void operator()(T*) { static_assert(sizeof(T), "type is not incomplete"); }
+};
+
+template<class T, class D = default_delete<T>>
+struct unique_ptr
+{
+ ~unique_ptr() { del(ptr); }
+
+ T* ptr;
+ D del;
+};
+
+
+constexpr bool b = __has_trivial_destructor(unique_ptr<X>);
diff --git a/gcc/testsuite/g++.dg/ext/is_destructible2.C b/gcc/testsuite/g++.dg/ext/is_destructible2.C
new file mode 100644
index 0000000..2edf440
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_destructible2.C
@@ -0,0 +1,24 @@
+// PR c++/107600
+// { dg-additional-options -Wno-c++17-extensions }
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ A& operator= (const A&);
+ virtual ~A() = 0;
+};
+
+static_assert( __is_destructible(A) );
+static_assert( __is_assignable(A, A) );
+static_assert( not __is_destructible(int()) );
+static_assert( not __is_nothrow_destructible(int()) );
+static_assert( not __is_trivially_destructible(int()) );
+static_assert( __is_destructible(int&) );
+static_assert( __is_destructible(int&&) );
+static_assert( __is_destructible(int(&)[1]) );
+static_assert( __is_destructible(const int(&)[1]) );
+static_assert( __is_destructible(void(&)()) );
+static_assert( not __is_destructible(int[]) );
+static_assert( not __is_destructible(const int[]) );
+static_assert( not __is_destructible(int[][1]) );
+static_assert( not __is_destructible(const int[][1]) );
diff --git a/gcc/testsuite/g++.dg/gomp/metadirective-condition-class.C b/gcc/testsuite/g++.dg/gomp/metadirective-condition-class.C
new file mode 100644
index 0000000..6403611
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/metadirective-condition-class.C
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-original" } */
+
+class c
+{
+ public:
+ int x;
+ c (int xx) { x = xx; }
+ operator bool() { return x != 0; }
+};
+
+void f (c &objref)
+{
+ #pragma omp metadirective when(user={condition(objref)} : nothing) otherwise(nothing)
+}
+
+
+template <typename T> class d
+{
+ public:
+ T x;
+ d (T xx) { x = xx; }
+ operator bool() { return x != 0; }
+};
+
+template <typename T>
+void g (d<T> &objref)
+{
+ #pragma omp metadirective when(user={condition(objref)} : nothing) otherwise(nothing)
+}
+
+int main (void)
+{
+ c obj1 (42);
+ d<int> obj2 (69);
+
+ f (obj1);
+ g (obj2);
+}
+
+/* { dg-final { scan-tree-dump "c::operator bool \\(\\(struct c .\\) objref\\)" "original" } } */
+
+/* { dg-final { scan-tree-dump "d<int>::operator bool \\(\\(struct d .\\) objref\\)" "original" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/metadirective-condition-template.C b/gcc/testsuite/g++.dg/gomp/metadirective-condition-template.C
new file mode 100644
index 0000000..30783d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/metadirective-condition-template.C
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-original" } */
+
+template<typename T, typename T2>
+void f (T x, T2 y)
+{
+ #pragma omp metadirective when(user={condition(x)}, \
+ target_device={device_num(y)} : flush)
+}
+
+class c
+{
+ public:
+ int x;
+ c (int xx) { x = xx; }
+ operator bool() { return x != 0; }
+};
+
+template <typename T> class d
+{
+ public:
+ T x;
+ d (T xx) { x = xx; }
+ operator bool() { return x != 0; }
+};
+
+int main (void)
+{
+ c obj1 (42);
+ d<int> obj2 (69);
+
+ f (42, 0);
+ f (&obj1, 0);
+ f (obj1, 0);
+ f (obj2, 0);
+}
+
+/* { dg-final { scan-tree-dump-times "if \\(x != 0 &&" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "if \\(x != 0B &&" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "if \\(<<cleanup_point c::operator bool \\(&x\\)>> &&" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "if \\(<<cleanup_point d<int>::operator bool \\(&x\\)>> &&" 1 "original" } } */
diff --git a/gcc/testsuite/g++.dg/modules/cpp-1.C b/gcc/testsuite/g++.dg/modules/cpp-1.C
index 2ad9637..56ef05fe 100644
--- a/gcc/testsuite/g++.dg/modules/cpp-1.C
+++ b/gcc/testsuite/g++.dg/modules/cpp-1.C
@@ -1,4 +1,5 @@
// { dg-do preprocess }
+// { dg-additional-options -fno-modules }
module bob;
#if 1
@@ -11,4 +12,4 @@ import gru;
EXPORT import mabel;
int i;
-// { dg-final { scan-file cpp-1.i "cpp-1.C\"\n\n\nmodule bob;\n\nexport import stuart;\n\n\n\nimport gru;\n\n import mabel;\n" } }
+// { dg-final { scan-file cpp-1.i "cpp-1.C\"\n\n\n\nmodule bob;\n\nexport import stuart;\n\n\n\nimport gru;\n\n import mabel;\n" } }
diff --git a/gcc/testsuite/g++.dg/modules/cpp-3.C b/gcc/testsuite/g++.dg/modules/cpp-3.C
index 3aa0c6e..cd776ae 100644
--- a/gcc/testsuite/g++.dg/modules/cpp-3.C
+++ b/gcc/testsuite/g++.dg/modules/cpp-3.C
@@ -1,4 +1,5 @@
// { dg-do preprocess }
+// { dg-additional-options -fno-modules }
#define NAME(X) X;
diff --git a/gcc/testsuite/g++.dg/modules/cpp-4.C b/gcc/testsuite/g++.dg/modules/cpp-4.C
index 6c19431..c423de2 100644
--- a/gcc/testsuite/g++.dg/modules/cpp-4.C
+++ b/gcc/testsuite/g++.dg/modules/cpp-4.C
@@ -1,3 +1,4 @@
+// { dg-additional-options -fno-modules }
// { dg-do preprocess }
#if 1
diff --git a/gcc/testsuite/g++.dg/tls/pr102496-1.C b/gcc/testsuite/g++.dg/tls/pr102496-1.C
index 8220e1e..e015ae9 100644
--- a/gcc/testsuite/g++.dg/tls/pr102496-1.C
+++ b/gcc/testsuite/g++.dg/tls/pr102496-1.C
@@ -1,6 +1,6 @@
// PR c++/102496
// { dg-do link { target c++11 } }
-// { dg-require-effective-target tls }
+// { dg-require-effective-target tls_link }
// { dg-add-options tls }
// { dg-additional-sources pr102496-2.C }
diff --git a/gcc/testsuite/g++.dg/tls/pr77285-1.C b/gcc/testsuite/g++.dg/tls/pr77285-1.C
index 7a93414..340c88b 100644
--- a/gcc/testsuite/g++.dg/tls/pr77285-1.C
+++ b/gcc/testsuite/g++.dg/tls/pr77285-1.C
@@ -1,5 +1,5 @@
// { dg-do link { target c++11 } }
-// { dg-require-effective-target tls }
+// { dg-require-effective-target tls_link }
// { dg-add-options tls }
// { dg-additional-sources pr77285-2.C }
diff --git a/gcc/testsuite/g++.target/arm/pr120424.C b/gcc/testsuite/g++.target/arm/pr120424.C
new file mode 100644
index 0000000..4d0e490
--- /dev/null
+++ b/gcc/testsuite/g++.target/arm/pr120424.C
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv7 -O2 -fstack-clash-protection -fnon-call-exceptions" } */
+/* { dg-final { scan-assembler-not {#-8} } } */
+/* LRA register elimination gets confused when register spilling
+ causes arm_frame_pointer_required to switch from false to true, and
+ ends up using a stack slot below sp. */
+
+void f() {
+ int i = 0, j = 0;
+ asm ("" : : "m" (i), "m" (j));
+}
+
+void g(void (*fn[])(), int i)
+{
+ auto fn0 = fn[i+0];
+ auto fn1 = fn[i+1];
+ auto fn2 = fn[i+2];
+ auto fn3 = fn[i+3];
+ fn0();
+ fn1();
+ if (!fn2)
+ throw i+2;
+ fn2();
+ fn3();
+ fn0();
+ fn1();
+}
+
+int
+main()
+{
+ void (*fn[4])() = { f, f, f, f };
+ g (fn, 0);
+}
diff --git a/gcc/testsuite/g++.target/i386/pr103750.C b/gcc/testsuite/g++.target/i386/pr103750.C
new file mode 100644
index 0000000..c82c10a
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr103750.C
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=x86-64-v4 -std=c++17" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */
+
+#include <x86intrin.h>
+
+/*
+**_Z8qustrchrPDsS_Ds:
+**...
+**.L[0-9]+:
+** vpcmpeqw \(%[a-x]+\), %ymm0, %k1
+** vpcmpeqw 32\(%[a-x]+\), %ymm0, %k0
+** kortestw %k0, %k1
+** je .L[0-9]+
+**...
+*/
+
+const char16_t *
+qustrchr(char16_t *n, char16_t *e, char16_t c) noexcept
+{
+ __m256i mch256 = _mm256_set1_epi16(c);
+ for ( ; n < e; n += 32) {
+ __m256i data1 = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(n));
+ __m256i data2 = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(n) + 1);
+ __mmask16 mask1 = _mm256_cmpeq_epu16_mask(data1, mch256);
+ __mmask16 mask2 = _mm256_cmpeq_epu16_mask(data2, mch256);
+ if (_kortestz_mask16_u8(mask1, mask2))
+ continue;
+
+ unsigned idx = _tzcnt_u32(mask1);
+ if (mask1 == 0) {
+ idx = __tzcnt_u16(mask2);
+ n += 16;
+ }
+ return n + idx;
+ }
+ return e;
+}
diff --git a/gcc/testsuite/gcc.dg/Wjump-misses-init-3.c b/gcc/testsuite/gcc.dg/Wjump-misses-init-3.c
new file mode 100644
index 0000000..c3110c4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wjump-misses-init-3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-Wc++-compat" } */
+
+void f()
+{
+ goto skip; /* { dg-warning "jump skips variable initialization" } */
+ int i = 1;
+skip: ;
+}
+
diff --git a/gcc/testsuite/gcc.dg/format/diagnostic-ranges-html.py b/gcc/testsuite/gcc.dg/format/diagnostic-ranges-html.py
new file mode 100644
index 0000000..91383d6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/diagnostic-ranges-html.py
@@ -0,0 +1,99 @@
+from htmltest import *
+
+import pytest
+
+@pytest.fixture(scope='function', autouse=True)
+def html_tree():
+ return html_tree_from_env()
+
+def assert_highlighted_text(element, expected_highlight, expected_text):
+ assert_tag(element, 'span')
+ assert_class(element, expected_highlight)
+ assert element.text == expected_text
+
+def test_message(html_tree):
+ """
+ Verify that the quoted text in the message has the correct
+ highlight colors.
+ """
+ diag = get_diag_by_index(html_tree, 0)
+ msg = get_message_within_diag(diag)
+
+ assert_tag(msg[0], 'span')
+ assert_class(msg[0], 'gcc-quoted-text')
+ assert_highlighted_text(msg[0][0], 'highlight-a', '%i')
+
+ assert_tag(msg[1], 'span')
+ assert_class(msg[1], 'gcc-quoted-text')
+ assert_highlighted_text(msg[1][0], 'highlight-a', 'int')
+
+ assert_tag(msg[2], 'span')
+ assert_class(msg[2], 'gcc-quoted-text')
+ assert_highlighted_text(msg[2][0], 'highlight-b', 'const char *')
+
+def test_annotations(html_tree):
+ """
+ Verify that the labels in the annotations have the correct
+ highlight colors.
+ """
+ diag = get_diag_by_index(html_tree, 0)
+ locus = get_locus_within_diag(diag)
+ tbody = locus.find('xhtml:tbody', ns)
+ assert tbody.attrib['class'] == 'line-span'
+
+ rows = tbody.findall('xhtml:tr', ns)
+
+ # Source row
+ row = rows[0]
+ tds = row.findall('xhtml:td', ns)
+ assert len(tds) == 2
+ assert_class(tds[1], 'source')
+ assert_highlighted_text(tds[1][0], 'highlight-a', '%i')
+ assert_highlighted_text(tds[1][1], 'highlight-b', 'msg')
+
+ # Underline row:
+ row = rows[1]
+ tds = row.findall('xhtml:td', ns)
+ assert len(tds) == 2
+ assert_class(tds[1], 'annotation')
+ assert_highlighted_text(tds[1][0], 'highlight-a', '~^')
+ assert_highlighted_text(tds[1][1], 'highlight-b', '~~~')
+
+ # vline row:
+ row = rows[2]
+ tds = row.findall('xhtml:td', ns)
+ assert len(tds) == 2
+ assert_class(tds[1], 'annotation')
+ assert_highlighted_text(tds[1][0], 'highlight-a', '|')
+ assert_highlighted_text(tds[1][1], 'highlight-b', '|')
+
+ # Label row:
+ row = rows[3]
+ tds = row.findall('xhtml:td', ns)
+ assert len(tds) == 2
+ assert_class(tds[1], 'annotation')
+ assert_highlighted_text(tds[1][0], 'highlight-a', 'int')
+ assert_highlighted_text(tds[1][1], 'highlight-b', 'const char *')
+
+# For reference, here's the generated HTML:
+"""
+ <span class="gcc-message" id="gcc-diag-0-message">format &apos;<span class="gcc-quoted-text"><span class="high
+light-a">%i</span></span>&apos; expects argument of type &apos;<span class="gcc-quoted-text"><span class="highlight-a"
+>int</span></span>&apos;, but argument 2 has type &apos;<span class="gcc-quoted-text"><span class="highlight-b">const
+char *</span></span>&apos;</span>
+
+ <span class="gcc-option">[<a href="https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wformat">-Wfo
+rmat=</a>]</span>
+ <table class="locus">
+ <tbody class="line-span">
+ <tr><td class="left-margin"> </td><td class="source"> printf(&quot;hello <span class="highlight-a">%i</span>&quot;, <span class="highlight-b">msg</span>); /* { dg-warning &quot;format &apos;%i&apos; expects argument of type &apos;int&apos;, but argument 2 has type &apos;const char \\*&apos; &quot; } */</td></tr>
+ <tr><td class="left-margin"> </td><td class="annotation"> <span class="highlight-a">~^</spa
+n> <span class="highlight-b">~~~</span></td></tr>
+ <tr><td class="left-margin"> </td><td class="annotation"> <span class="highlight-a">|</spa
+n> <span class="highlight-b">|</span></td></tr>
+ <tr><td class="left-margin"> </td><td class="annotation"> <span class="highlight-a">int</s
+pan> <span class="highlight-b">const char *</span></td></tr>
+ <tr><td class="left-margin"> </td><td class="annotation"> %s</td></tr>
+ </tbody>
+ </table>
+"""
diff --git a/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c b/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
index 2c33ce2..d3e334d 100644
--- a/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
+++ b/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
@@ -1,4 +1,4 @@
-/* { dg-options "-Wformat -fdiagnostics-show-caret" } */
+/* { dg-options "-Wformat -fdiagnostics-show-caret -fdiagnostics-add-output=experimental-html:javascript=no" } */
/* See PR 52952. */
@@ -390,3 +390,7 @@ void test_const_arrays (void)
double
{ dg-end-multiline-output "" } */
}
+
+/* Use a Python script to verify various properties about the generated
+ HTML file:
+ { dg-final { run-html-pytest diagnostic-ranges.c "diagnostic-ranges-html.py" } } */
diff --git a/gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c b/gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c
index 2411b04..076c066 100644
--- a/gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c
+++ b/gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c
@@ -1,11 +1,31 @@
/* { dg-do compile } */
/* { dg-options "-std=gnu23" } */
+#define NEST(...) typeof(({ (__VA_ARGS__){ }; }))
+
int f()
{
typedef struct foo bar;
- struct foo { typeof(({ (struct foo { bar * x; }){ }; })) * x; } *q;
- typeof(q->x) p;
- 1 ? p : q;
+ struct foo { NEST(struct foo { bar *x; }) *x; } *q;
+ typeof(q->x) p0;
+ typeof(q->x) p1;
+ 1 ? p0 : q;
+ 1 ? p1 : q;
+ 1 ? p0 : p1;
+}
+
+int g()
+{
+ typedef struct fo2 bar;
+ struct fo2 { NEST(struct fo2 { NEST(struct fo2 { bar *x; }) * x; }) *x; } *q;
+ typeof(q->x) p0;
+ typeof(q->x->x) p1;
+ typeof(q->x->x->x) p2;
+ 1 ? p0 : q;
+ 1 ? p1 : q;
+ 1 ? p2 : q;
+ 1 ? p0 : p1;
+ 1 ? p2 : p1;
+ 1 ? p0 : p2;
}
diff --git a/gcc/testsuite/gcc.dg/pr116892.c b/gcc/testsuite/gcc.dg/pr116892.c
new file mode 100644
index 0000000..7eb431b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr116892.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-g -std=gnu23" } */
+
+enum fmt_type;
+
+void foo(const enum fmt_type a);
+
+enum [[gnu::packed]] fmt_type {
+ A
+} const a;
+
diff --git a/gcc/testsuite/gcc.dg/pr120380.c b/gcc/testsuite/gcc.dg/pr120380.c
new file mode 100644
index 0000000..10577a1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120380.c
@@ -0,0 +1,24 @@
+/* PR c/120380 */
+/* { dg-do compile } */
+
+struct pair_t {
+ char c;
+ int i;
+};
+typedef struct foo_ { /* { dg-error "no member" } */
+ struct foo_ { /* { dg-error "nested redefinition" } */
+ /* { dg-error "no member" "" { target *-*-* } .-1 } */
+ struct foo_ { /* { dg-error "nested redefinition" } */
+ int value;
+ }
+ } /* { dg-error "does not declare anything" } */
+ /* { dg-error "no semicolon" "" { target *-*-* } .-1 } */
+} __attribute__((packed)) foo; /* { dg-error "does not declare anything" } */
+ /* { dg-error "no semicolon" "" { target *-*-* } .-1 } */
+struct pair_t p = {0, 1};
+foo *addr = (foo *)&p.i;
+int main() {
+ addr->value = 0; /* { dg-error "has no member" } */
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/pr120525.c b/gcc/testsuite/gcc.dg/pr120525.c
new file mode 100644
index 0000000..5ab7a22
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120525.c
@@ -0,0 +1,22 @@
+/* { dg-do compile { target fpic } } */
+/* { dg-options "-O2 -fpic -g" } */
+/* { dg-additional-options "-m31" { target s390x-*-* } } */
+
+typedef __SIZE_TYPE__ uintptr_t;
+static __thread uintptr_t start_sp;
+static inline uintptr_t
+__thread_stack_pointer (void)
+{
+ return (uintptr_t) __builtin_frame_address (0);
+}
+
+void
+update_data (void)
+{
+ if (__builtin_expect ((!start_sp), 0))
+ start_sp = __thread_stack_pointer ();
+
+ uintptr_t sp = __thread_stack_pointer ();
+ if (__builtin_expect ((sp > start_sp), 0))
+ start_sp = sp;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cswtch-6.c b/gcc/testsuite/gcc.dg/tree-ssa/cswtch-6.c
new file mode 100644
index 0000000..d765a03
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/cswtch-6.c
@@ -0,0 +1,43 @@
+/* PR tree-optimization/120451 */
+/* { dg-do compile { target elf } } */
+/* { dg-options "-O2" } */
+
+void foo (int, int);
+
+__attribute__((noinline, noclone)) void
+f1 (int v, int w)
+{
+ int i, j;
+ if (w)
+ {
+ i = 129;
+ j = i - 1;
+ goto lab;
+ }
+ switch (v)
+ {
+ case 170:
+ j = 7;
+ i = 27;
+ break;
+ case 171:
+ i = 8;
+ j = 122;
+ break;
+ case 172:
+ i = 21;
+ j = -19;
+ break;
+ case 173:
+ i = 18;
+ j = 17;
+ break;
+ default:
+ __builtin_abort ();
+ }
+
+ lab:
+ foo (i, j);
+}
+
+/* { dg-final { scan-assembler ".rodata.cst16" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phiprop-2.c b/gcc/testsuite/gcc.dg/tree-ssa/phiprop-2.c
new file mode 100644
index 0000000..7181787
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phiprop-2.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-phiopt2 -fdump-tree-phiprop1-details" } */
+
+/* PR tree-optimization/116824 */
+
+int g(int i, int *tt)
+{
+ const int t = 10;
+ const int *a;
+ {
+ if (t < i)
+ {
+ *tt = 1;
+ a = &t;
+ }
+ else
+ {
+ *tt = 1;
+ a = &i;
+ }
+ }
+ return *a;
+}
+
+/* Check that phiprop1 can do the insert of the loads. */
+/* { dg-final { scan-tree-dump-times "Inserting PHI for result of load" 1 "phiprop1"} } */
+/* Should be able to get MIN_EXPR in phiopt2 after cselim and phiprop. */
+/* { dg-final { scan-tree-dump-times "MIN_EXPR " 1 "phiopt2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_136-pr120357.c b/gcc/testsuite/gcc.dg/vect/vect-early-break_136-pr120357.c
new file mode 100644
index 0000000..8a51cfc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_136-pr120357.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-add-options vect_early_break } */
+/* { dg-additional-options "-O3" } */
+
+char a;
+unsigned long long t[2][22];
+int u[22];
+void f(void)
+{
+ for (int v = 0; v < 22; v++)
+ for (_Bool w = 0; w < (u[v] < 0) + 1; w = 1)
+ a *= 0 != t[w][v];
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr49095-2.c b/gcc/testsuite/gcc.target/i386/pr49095-2.c
new file mode 100644
index 0000000..25bc6b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr49095-2.c
@@ -0,0 +1,73 @@
+/* PR rtl-optimization/49095 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-Os -fno-shrink-wrap -masm=att -mapxf" } */
+
+void foo (void *);
+
+int *
+f1 (int *x)
+{
+ if (!--*x)
+ foo (x);
+ return x;
+}
+
+int
+g1 (int x)
+{
+ if (!--x)
+ foo ((void *) 0);
+ return x;
+}
+
+#define F(T, OP, OPN) \
+T * \
+f##T##OPN (T *x, T y) \
+{ \
+ *x OP y; \
+ if (!*x) \
+ foo (x); \
+ return x; \
+} \
+ \
+T \
+g##T##OPN (T x, T y) \
+{ \
+ x OP y; \
+ if (!x) \
+ foo ((void *) 0); \
+ return x; \
+} \
+ \
+T * \
+h##T##OPN (T *x) \
+{ \
+ *x OP 24; \
+ if (!*x) \
+ foo (x); \
+ return x; \
+} \
+ \
+T \
+i##T##OPN (T x, T y) \
+{ \
+ x OP 24; \
+ if (!x) \
+ foo ((void *) 0); \
+ return x; \
+}
+
+#define G(T) \
+F (T, +=, plus) \
+F (T, -=, minus) \
+F (T, &=, and) \
+F (T, |=, or) \
+F (T, ^=, xor)
+
+G (char)
+G (short)
+G (int)
+G (long)
+
+/* { dg-final { scan-assembler-not "test\[lq\]" } } */
+/* { dg-final { scan-assembler-not "\\(%\[re\]di\\), %" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr79173-13.c b/gcc/testsuite/gcc.target/i386/pr79173-13.c
new file mode 100644
index 0000000..7d5818b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr79173-13.c
@@ -0,0 +1,59 @@
+/* PR middle-end/79173 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -fno-stack-protector -masm=att -mapxf" } */
+/* { dg-final { scan-assembler-times "addq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "subq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "addl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "subl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+
+static unsigned long
+uaddc (unsigned long x, unsigned long y, unsigned long carry_in, unsigned long *carry_out)
+{
+ unsigned long r;
+ unsigned long c1 = __builtin_add_overflow (x, y, &r);
+ unsigned long c2 = __builtin_add_overflow (r, carry_in, &r);
+ *carry_out = c1 + c2;
+ return r;
+}
+
+static unsigned long
+usubc (unsigned long x, unsigned long y, unsigned long carry_in, unsigned long *carry_out)
+{
+ unsigned long r;
+ unsigned long c1 = __builtin_sub_overflow (x, y, &r);
+ unsigned long c2 = __builtin_sub_overflow (r, carry_in, &r);
+ *carry_out = c1 + c2;
+ return r;
+}
+
+void
+foo (unsigned long *p, unsigned long *q)
+{
+ unsigned long c;
+ p[0] = uaddc (p[0], q[0], 0, &c);
+ p[1] = uaddc (p[1], q[1], c, &c);
+ p[2] = uaddc (p[2], q[2], c, &c);
+ p[3] = uaddc (p[3], q[3], c, &c);
+}
+
+void
+bar (unsigned long *p, unsigned long *q)
+{
+ unsigned long c;
+ p[0] = usubc (p[0], q[0], 0, &c);
+ p[1] = usubc (p[1], q[1], c, &c);
+ p[2] = usubc (p[2], q[2], c, &c);
+ p[3] = usubc (p[3], q[3], c, &c);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr79173-14.c b/gcc/testsuite/gcc.target/i386/pr79173-14.c
new file mode 100644
index 0000000..de85051
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr79173-14.c
@@ -0,0 +1,59 @@
+/* PR middle-end/79173 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -fno-stack-protector -masm=att -mapxf" } */
+/* { dg-final { scan-assembler-times "addq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "subq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "addl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "subl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+
+static unsigned long
+uaddc (unsigned long x, unsigned long y, _Bool carry_in, _Bool *carry_out)
+{
+ unsigned long r;
+ _Bool c1 = __builtin_add_overflow (x, y, &r);
+ _Bool c2 = __builtin_add_overflow (r, carry_in, &r);
+ *carry_out = c1 | c2;
+ return r;
+}
+
+static unsigned long
+usubc (unsigned long x, unsigned long y, _Bool carry_in, _Bool *carry_out)
+{
+ unsigned long r;
+ _Bool c1 = __builtin_sub_overflow (x, y, &r);
+ _Bool c2 = __builtin_sub_overflow (r, carry_in, &r);
+ *carry_out = c1 | c2;
+ return r;
+}
+
+void
+foo (unsigned long *p, unsigned long *q)
+{
+ _Bool c;
+ p[0] = uaddc (p[0], q[0], 0, &c);
+ p[1] = uaddc (p[1], q[1], c, &c);
+ p[2] = uaddc (p[2], q[2], c, &c);
+ p[3] = uaddc (p[3], q[3], c, &c);
+}
+
+void
+bar (unsigned long *p, unsigned long *q)
+{
+ _Bool c;
+ p[0] = usubc (p[0], q[0], 0, &c);
+ p[1] = usubc (p[1], q[1], c, &c);
+ p[2] = usubc (p[2], q[2], c, &c);
+ p[3] = usubc (p[3], q[3], c, &c);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr79173-15.c b/gcc/testsuite/gcc.target/i386/pr79173-15.c
new file mode 100644
index 0000000..c3017f7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr79173-15.c
@@ -0,0 +1,61 @@
+/* PR middle-end/79173 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -fno-stack-protector -masm=att -mapxf" } */
+/* { dg-final { scan-assembler-times "addq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "subq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "addl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "subl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+
+static unsigned long
+uaddc (unsigned long x, unsigned long y, unsigned long carry_in, unsigned long *carry_out)
+{
+ unsigned long r;
+ unsigned long c1 = __builtin_add_overflow (x, y, &r);
+ unsigned long c2 = __builtin_add_overflow (r, carry_in, &r);
+ *carry_out = c1 + c2;
+ return r;
+}
+
+static unsigned long
+usubc (unsigned long x, unsigned long y, unsigned long carry_in, unsigned long *carry_out)
+{
+ unsigned long r;
+ unsigned long c1 = __builtin_sub_overflow (x, y, &r);
+ unsigned long c2 = __builtin_sub_overflow (r, carry_in, &r);
+ *carry_out = c1 + c2;
+ return r;
+}
+
+unsigned long
+foo (unsigned long *p, unsigned long *q)
+{
+ unsigned long c;
+ p[0] = uaddc (p[0], q[0], 0, &c);
+ p[1] = uaddc (p[1], q[1], c, &c);
+ p[2] = uaddc (p[2], q[2], c, &c);
+ p[3] = uaddc (p[3], q[3], c, &c);
+ return c;
+}
+
+unsigned long
+bar (unsigned long *p, unsigned long *q)
+{
+ unsigned long c;
+ p[0] = usubc (p[0], q[0], 0, &c);
+ p[1] = usubc (p[1], q[1], c, &c);
+ p[2] = usubc (p[2], q[2], c, &c);
+ p[3] = usubc (p[3], q[3], c, &c);
+ return c;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr79173-16.c b/gcc/testsuite/gcc.target/i386/pr79173-16.c
new file mode 100644
index 0000000..91062fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr79173-16.c
@@ -0,0 +1,61 @@
+/* PR middle-end/79173 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -fno-stack-protector -masm=att -mapxf" } */
+/* { dg-final { scan-assembler-times "addq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "subq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "sbbq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "addl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "subl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "sbbl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+
+static unsigned long
+uaddc (unsigned long x, unsigned long y, _Bool carry_in, _Bool *carry_out)
+{
+ unsigned long r;
+ _Bool c1 = __builtin_add_overflow (x, y, &r);
+ _Bool c2 = __builtin_add_overflow (r, carry_in, &r);
+ *carry_out = c1 ^ c2;
+ return r;
+}
+
+static unsigned long
+usubc (unsigned long x, unsigned long y, _Bool carry_in, _Bool *carry_out)
+{
+ unsigned long r;
+ _Bool c1 = __builtin_sub_overflow (x, y, &r);
+ _Bool c2 = __builtin_sub_overflow (r, carry_in, &r);
+ *carry_out = c1 ^ c2;
+ return r;
+}
+
+_Bool
+foo (unsigned long *p, unsigned long *q)
+{
+ _Bool c;
+ p[0] = uaddc (p[0], q[0], 0, &c);
+ p[1] = uaddc (p[1], q[1], c, &c);
+ p[2] = uaddc (p[2], q[2], c, &c);
+ p[3] = uaddc (p[3], q[3], c, &c);
+ return c;
+}
+
+_Bool
+bar (unsigned long *p, unsigned long *q)
+{
+ _Bool c;
+ p[0] = usubc (p[0], q[0], 0, &c);
+ p[1] = usubc (p[1], q[1], c, &c);
+ p[2] = usubc (p[2], q[2], c, &c);
+ p[3] = usubc (p[3], q[3], c, &c);
+ return c;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr79173-17.c b/gcc/testsuite/gcc.target/i386/pr79173-17.c
new file mode 100644
index 0000000..e27f4b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr79173-17.c
@@ -0,0 +1,32 @@
+/* PR middle-end/79173 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -fno-stack-protector -masm=att -mapxf" } */
+/* { dg-final { scan-assembler-times "addq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "addl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+
+static unsigned long
+uaddc (unsigned long x, unsigned long y, unsigned long carry_in, unsigned long *carry_out)
+{
+ unsigned long r = x + y;
+ unsigned long c1 = r < x;
+ r += carry_in;
+ unsigned long c2 = r < carry_in;
+ *carry_out = c1 + c2;
+ return r;
+}
+
+void
+foo (unsigned long *p, unsigned long *q)
+{
+ unsigned long c;
+ p[0] = uaddc (p[0], q[0], 0, &c);
+ p[1] = uaddc (p[1], q[1], c, &c);
+ p[2] = uaddc (p[2], q[2], c, &c);
+ p[3] = uaddc (p[3], q[3], c, &c);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr79173-18.c b/gcc/testsuite/gcc.target/i386/pr79173-18.c
new file mode 100644
index 0000000..2728ae7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr79173-18.c
@@ -0,0 +1,33 @@
+/* PR middle-end/79173 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -fno-stack-protector -masm=att -mapxf" } */
+/* { dg-final { scan-assembler-times "addq\t%r\[^\n\r]*, \\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 8\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 16\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "adcq\t%r\[^\n\r]*, 24\\\(%rdi\\\)" 1 { target lp64 } } } */
+/* { dg-final { scan-assembler-times "addl\t%e\[^\n\r]*, \\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 4\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 8\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "adcl\t%e\[^\n\r]*, 12\\\(%e\[^\n\r]*\\\)" 1 { target ia32 } } } */
+
+static unsigned long
+uaddc (unsigned long x, unsigned long y, unsigned long carry_in, unsigned long *carry_out)
+{
+ unsigned long r = x + y;
+ unsigned long c1 = r < x;
+ r += carry_in;
+ unsigned long c2 = r < carry_in;
+ *carry_out = c1 + c2;
+ return r;
+}
+
+unsigned long
+foo (unsigned long *p, unsigned long *q)
+{
+ unsigned long c;
+ p[0] = uaddc (p[0], q[0], 0, &c);
+ p[1] = uaddc (p[1], q[1], c, &c);
+ p[2] = uaddc (p[2], q[2], c, &c);
+ p[3] = uaddc (p[3], q[3], c, &c);
+ return c;
+}
diff --git a/gcc/testsuite/gcc.target/or1k/call-1.c b/gcc/testsuite/gcc.target/or1k/call-1.c
new file mode 100644
index 0000000..593e402
--- /dev/null
+++ b/gcc/testsuite/gcc.target/or1k/call-1.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcmodel=large" } */
+
+/* Generate local and global function calls. */
+
+extern int geti (void);
+
+__attribute__ ((noinline)) int
+calc (int a, int b)
+{
+ return a * b + 255;
+}
+
+int
+main (void)
+{
+ return geti () + calc (3, 4);
+}
+
+/* Ensure the 2 calls use register not immediate jumps. */
+/* { dg-final { scan-assembler-times "l.movhi\\s+" 2 } } */
+/* { dg-final { scan-assembler-times "l.jalr\\s+" 2 } } */
diff --git a/gcc/testsuite/gcc.target/or1k/got-1.c b/gcc/testsuite/gcc.target/or1k/got-1.c
new file mode 100644
index 0000000..5357096
--- /dev/null
+++ b/gcc/testsuite/gcc.target/or1k/got-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mcmodel=large" } */
+
+/* Generate references to the GOT. */
+
+extern int geti (void);
+extern int j;
+
+int
+calc (int a)
+{
+ return a * j + geti ();
+}
+
+/* Ensure the 2 references use gotha relocations and that the function call does
+ not use an immediate jump instruction. */
+/* { dg-final { scan-assembler-times "gotha" 2 } } */
+/* { dg-final { scan-assembler "l.jalr\\s+" } } */
diff --git a/gcc/testsuite/gcc.target/or1k/return-2.c b/gcc/testsuite/gcc.target/or1k/return-2.c
index add3720..c072ae2 100644
--- a/gcc/testsuite/gcc.target/or1k/return-2.c
+++ b/gcc/testsuite/gcc.target/or1k/return-2.c
@@ -16,4 +16,4 @@ struct a getstruct (long aa) {
/* Ensure our return value is returned on stack. */
/* { dg-final { scan-assembler-not "r12," } } */
/* { dg-final { scan-assembler "l.or\\s+r11, r3, r3" } } */
-/* { dg-final { scan-assembler-times "l.sw\\s+\\d+.r11.," 3 } } */
+/* { dg-final { scan-assembler-times "l.sw\\s+\\d+.r3.," 3 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/arch-59.c b/gcc/testsuite/gcc.target/riscv/arch-59.c
new file mode 100644
index 0000000..511cf22
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-59.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i_smcntrpmf -mabi=lp64" } */
+int foo()
+{
+}
diff --git a/gcc/testsuite/gcc.target/riscv/arch-shlocofideleg.c b/gcc/testsuite/gcc.target/riscv/arch-shlocofideleg.c
new file mode 100644
index 0000000..de9f9fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-shlocofideleg.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i_shlcofideleg -mabi=lp64" } */
+int foo()
+{
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv-nofm.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv-nofm.c
index 0750d8e..4685ed2 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv-nofm.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv-nofm.c
@@ -3,13 +3,13 @@
#include "vdiv-template.h"
-/* { dg-final { scan-assembler-times {\tvdiv\.vv} 5 } } */
-/* { dg-final { scan-assembler-times {\tvdiv\.vx} 3 } } */
+/* { dg-final { scan-assembler-times {\tvdiv\.vv} 8 } } */
+/* { dg-final { scan-assembler-not {\tvdiv\.vx} } } */
/* { dg-final { scan-assembler-times {\tvdivu\.vv} 5 } } */
/* { dg-final { scan-assembler-times {\tvdivu\.vx} 3 } } */
-/* { dg-final { scan-assembler-times {\tvfdiv\.vv} 3 } } */
-/* { dg-final { scan-assembler-times {\tvfdiv\.vf} 3 } } */
+/* { dg-final { scan-assembler-times {\tvfdiv\.vv} 6 } } */
+/* { dg-final { scan-assembler-not {\tvfdiv\.vf} } } */
/* { dg-final { scan-tree-dump-times "\.COND_LEN_DIV" 16 "optimized" } } */
/* { dg-final { scan-tree-dump-times "\.COND_LEN_RDIV" 6 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv.c
index 31b2284..59c48d2 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv32gcv.c
@@ -3,8 +3,8 @@
#include "vdiv-template.h"
-/* { dg-final { scan-assembler-times {\tvdiv\.vv} 5 } } */
-/* { dg-final { scan-assembler-times {\tvdiv\.vx} 3 } } */
+/* { dg-final { scan-assembler-times {\tvdiv\.vv} 8 } } */
+/* { dg-final { scan-assembler-not {\tvdiv\.vx} } } */
/* { dg-final { scan-assembler-times {\tvdivu\.vv} 5 } } */
/* { dg-final { scan-assembler-times {\tvdivu\.vx} 3 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv-nofm.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv-nofm.c
index 6015af9..b574dc4 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv-nofm.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv-nofm.c
@@ -3,13 +3,13 @@
#include "vdiv-template.h"
-/* { dg-final { scan-assembler-times {\tvdiv\.vv} 4 } } */
-/* { dg-final { scan-assembler-times {\tvdiv\.vx} 4 } } */
+/* { dg-final { scan-assembler-times {\tvdiv\.vv} 8 } } */
+/* { dg-final { scan-assembler-not {\tvdiv\.vx} } } */
/* { dg-final { scan-assembler-times {\tvdivu\.vv} 4 } } */
/* { dg-final { scan-assembler-times {\tvdivu\.vx} 4 } } */
-/* { dg-final { scan-assembler-times {\tvfdiv\.vv} 3 } } */
-/* { dg-final { scan-assembler-times {\tvfdiv\.vf} 3 } } */
+/* { dg-final { scan-assembler-times {\tvfdiv\.vv} 6 } } */
+/* { dg-final { scan-assembler-not {\tvfdiv\.vf} } } */
/* { dg-final { scan-tree-dump-times "\.COND_LEN_DIV" 16 "optimized" } } */
/* { dg-final { scan-tree-dump-times "\.COND_LEN_RDIV" 6 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv.c
index ccaa2f8..9b46c6b 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/binop/vdiv-rv64gcv.c
@@ -3,8 +3,8 @@
#include "vdiv-template.h"
-/* { dg-final { scan-assembler-times {\tvdiv\.vv} 4 } } */
-/* { dg-final { scan-assembler-times {\tvdiv\.vx} 4 } } */
+/* { dg-final { scan-assembler-times {\tvdiv\.vv} 8 } } */
+/* { dg-final { scan-assembler-not {\tvdiv\.vx} } } */
/* { dg-final { scan-assembler-times {\tvdivu\.vv} 4 } } */
/* { dg-final { scan-assembler-times {\tvdivu\.vx} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/param-autovec-mode.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/param-autovec-mode.c
index b2ec8f9..1ee7eb3 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/param-autovec-mode.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/param-autovec-mode.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d --param=autovec-mode=V4QI -fdump-tree-vect-details" } */
+/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d --param=riscv-autovec-mode=V4QI -fdump-tree-vect-details" } */
/* By default we will use RVVM1SI mode for vectorization because N is not
known. Check that we use V4QI and create an epilogue when the autovec-mode
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f16.c
new file mode 100644
index 0000000..821e5c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f16.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh -mabi=lp64d --param=fpr2vr-cost=0" } */
+
+#include "vf_mulop.h"
+
+DEF_VF_MULOP_CASE_0(_Float16, +, add)
+DEF_VF_MULOP_CASE_0(_Float16, -, sub)
+
+/* { dg-final { scan-assembler-times {vfmadd.vf} 1 } } */
+/* { dg-final { scan-assembler-times {vfmsub.vf} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f32.c
new file mode 100644
index 0000000..49b4287
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f32.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d --param=fpr2vr-cost=0" } */
+
+#include "vf_mulop.h"
+
+DEF_VF_MULOP_CASE_0(float, +, add)
+DEF_VF_MULOP_CASE_0(float, -, sub)
+
+/* { dg-final { scan-assembler-times {vfmadd.vf} 1 } } */
+/* { dg-final { scan-assembler-times {vfmsub.vf} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f64.c
new file mode 100644
index 0000000..2bb5d89
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-1-f64.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d --param=fpr2vr-cost=0" } */
+
+#include "vf_mulop.h"
+
+DEF_VF_MULOP_CASE_0(double, +, add)
+DEF_VF_MULOP_CASE_0(double, -, sub)
+
+/* { dg-final { scan-assembler-times {vfmadd.vf} 1 } } */
+/* { dg-final { scan-assembler-times {vfmsub.vf} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f16.c
new file mode 100644
index 0000000..cbb43ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f16.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh -mabi=lp64d --param=fpr2vr-cost=1" } */
+
+#include "vf_mulop.h"
+
+DEF_VF_MULOP_CASE_0(_Float16, +, add)
+DEF_VF_MULOP_CASE_0(_Float16, -, sub)
+
+/* { dg-final { scan-assembler-not {vfmadd.vf} } } */
+/* { dg-final { scan-assembler-not {vfmsub.vf} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f32.c
new file mode 100644
index 0000000..66ff9b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f32.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d --param=fpr2vr-cost=1" } */
+
+#include "vf_mulop.h"
+
+DEF_VF_MULOP_CASE_0(float, +, add)
+DEF_VF_MULOP_CASE_0(float, -, sub)
+
+/* { dg-final { scan-assembler-not {vfmadd.vf} } } */
+/* { dg-final { scan-assembler-not {vfmsub.vf} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f64.c
new file mode 100644
index 0000000..66ff9b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-2-f64.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d --param=fpr2vr-cost=1" } */
+
+#include "vf_mulop.h"
+
+DEF_VF_MULOP_CASE_0(float, +, add)
+DEF_VF_MULOP_CASE_0(float, -, sub)
+
+/* { dg-final { scan-assembler-not {vfmadd.vf} } } */
+/* { dg-final { scan-assembler-not {vfmsub.vf} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f16.c
new file mode 100644
index 0000000..45980f4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f16.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh -mabi=lp64d --param=fpr2vr-cost=0" } */
+
+#include "vf_mulop.h"
+
+DEF_VF_MULOP_CASE_1(_Float16, +, add, VF_MULOP_BODY_X16)
+DEF_VF_MULOP_CASE_1(_Float16, -, sub, VF_MULOP_BODY_X16)
+
+/* { dg-final { scan-assembler {vfmadd.vf} } } */
+/* { dg-final { scan-assembler {vfmsub.vf} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f32.c
new file mode 100644
index 0000000..c853620
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f32.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d --param=fpr2vr-cost=0" } */
+
+#include "vf_mulop.h"
+
+DEF_VF_MULOP_CASE_1(float, +, add, VF_MULOP_BODY_X16)
+DEF_VF_MULOP_CASE_1(float, -, sub, VF_MULOP_BODY_X16)
+
+/* { dg-final { scan-assembler {vfmadd.vf} } } */
+/* { dg-final { scan-assembler {vfmsub.vf} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f64.c
new file mode 100644
index 0000000..d38ae8b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-3-f64.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d --param=fpr2vr-cost=0" } */
+
+#include "vf_mulop.h"
+
+DEF_VF_MULOP_CASE_1(double, +, add, VF_MULOP_BODY_X16)
+DEF_VF_MULOP_CASE_1(double, -, sub, VF_MULOP_BODY_X16)
+
+/* { dg-final { scan-assembler {vfmadd.vf} } } */
+/* { dg-final { scan-assembler {vfmsub.vf} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f16.c
new file mode 100644
index 0000000..f1ca34e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f16.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh -mabi=lp64d --param=fpr2vr-cost=4" } */
+
+#include "vf_mulop.h"
+
+DEF_VF_MULOP_CASE_1(_Float16, +, add, VF_MULOP_BODY_X16)
+DEF_VF_MULOP_CASE_1(_Float16, -, sub, VF_MULOP_BODY_X16)
+
+/* { dg-final { scan-assembler-not {vfmadd.vf} } } */
+/* { dg-final { scan-assembler-not {vfmsub.vf} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f32.c
new file mode 100644
index 0000000..6730d4b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f32.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d --param=fpr2vr-cost=4" } */
+
+#include "vf_mulop.h"
+
+DEF_VF_MULOP_CASE_1(float, +, add, VF_MULOP_BODY_X16)
+DEF_VF_MULOP_CASE_1(float, -, sub, VF_MULOP_BODY_X16)
+
+/* { dg-final { scan-assembler-not {vfmadd.vf} } } */
+/* { dg-final { scan-assembler-not {vfmsub.vf} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f64.c
new file mode 100644
index 0000000..bcb6a6e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf-4-f64.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d --param=fpr2vr-cost=4" } */
+
+#include "vf_mulop.h"
+
+DEF_VF_MULOP_CASE_1(double, +, add, VF_MULOP_BODY_X16)
+DEF_VF_MULOP_CASE_1(double, -, sub, VF_MULOP_BODY_X16)
+
+/* { dg-final { scan-assembler-not {vfmadd.vf} } } */
+/* { dg-final { scan-assembler-not {vfmsub.vf} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop.h
new file mode 100644
index 0000000..5253978
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop.h
@@ -0,0 +1,61 @@
+#ifndef HAVE_DEFINED_VF_MULOP_H
+#define HAVE_DEFINED_VF_MULOP_H
+
+#include <stdint.h>
+
+#define DEF_VF_MULOP_CASE_0(T, OP, NAME) \
+ void test_vf_mulop_##NAME##_##T##_case_0(T *restrict out, T *restrict in, \
+ T x, unsigned n) { \
+ for (unsigned i = 0; i < n; i++) \
+ out[i] = in[i] OP out[i] * x; \
+ }
+#define DEF_VF_MULOP_CASE_0_WRAP(T, OP, NAME) DEF_VF_MULOP_CASE_0(T, OP, NAME)
+#define RUN_VF_MULOP_CASE_0(T, NAME, out, in, x, n) \
+ test_vf_mulop_##NAME##_##T##_case_0(out, in, x, n)
+#define RUN_VF_MULOP_CASE_0_WRAP(T, NAME, out, in, x, n) \
+ RUN_VF_MULOP_CASE_0(T, NAME, out, in, x, n)
+
+#define VF_MULOP_BODY(op) \
+ out[k + 0] = in[k + 0] op tmp * out[k + 0]; \
+ out[k + 1] = in[k + 1] op tmp * out[k + 1]; \
+ k += 2;
+
+#define VF_MULOP_BODY_X4(op) \
+ VF_MULOP_BODY(op) \
+ VF_MULOP_BODY(op)
+
+#define VF_MULOP_BODY_X8(op) \
+ VF_MULOP_BODY_X4(op) \
+ VF_MULOP_BODY_X4(op)
+
+#define VF_MULOP_BODY_X16(op) \
+ VF_MULOP_BODY_X8(op) \
+ VF_MULOP_BODY_X8(op)
+
+#define VF_MULOP_BODY_X32(op) \
+ VF_MULOP_BODY_X16(op) \
+ VF_MULOP_BODY_X16(op)
+
+#define VF_MULOP_BODY_X64(op) \
+ VF_MULOP_BODY_X32(op) \
+ VF_MULOP_BODY_X32(op)
+
+#define VF_MULOP_BODY_X128(op) \
+ VF_MULOP_BODY_X64(op) \
+ VF_MULOP_BODY_X64(op)
+
+#define DEF_VF_MULOP_CASE_1(T, OP, NAME, BODY) \
+ void test_vf_mulop_##NAME##_##T##_case_1(T *restrict out, T *restrict in, \
+ T x, unsigned n) { \
+ unsigned k = 0; \
+ T tmp = x + 3; \
+ \
+ while (k < n) { \
+ tmp = tmp * 0x3f; \
+ BODY(OP) \
+ } \
+ }
+#define DEF_VF_MULOP_CASE_1_WRAP(T, OP, NAME, BODY) \
+ DEF_VF_MULOP_CASE_1(T, OP, NAME, BODY)
+
+#endif
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_data.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_data.h
new file mode 100644
index 0000000..c16c1a9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_data.h
@@ -0,0 +1,413 @@
+#ifndef HAVE_DEFINED_VF_MULOP_DATA_H
+#define HAVE_DEFINED_VF_MULOP_DATA_H
+
+#define N 16
+
+#define TEST_MULOP_DATA(T, NAME) test_##T##_##NAME##_data
+#define TEST_MULOP_DATA_WRAP(T, NAME) TEST_MULOP_DATA(T, NAME)
+
+
+_Float16 TEST_MULOP_DATA(_Float16, add)[][4][N] =
+{
+ {
+ { 0.30f16 },
+ {
+ 1.48f16, 1.48f16, 1.48f16, 1.48f16,
+ 0.80f16, 0.80f16, 0.80f16, 0.80f16,
+ 0.62f16, 0.62f16, 0.62f16, 0.62f16,
+ 1.18f16, 1.18f16, 1.18f16, 1.18f16,
+ },
+ {
+ 1.25f16, 1.25f16, 1.25f16, 1.25f16,
+ 1.89f16, 1.89f16, 1.89f16, 1.89f16,
+ 1.57f16, 1.57f16, 1.57f16, 1.57f16,
+ 1.21f16, 1.21f16, 1.21f16, 1.21f16,
+ },
+ {
+ 1.85f16, 1.85f16, 1.85f16, 1.85f16,
+ 1.37f16, 1.37f16, 1.37f16, 1.37f16,
+ 1.09f16, 1.09f16, 1.09f16, 1.09f16,
+ 1.54f16, 1.54f16, 1.54f16, 1.54f16,
+ }
+ },
+ {
+ { -0.505f16 },
+ {
+ -2.38f16, -2.38f16, -2.38f16, -2.38f16,
+ -2.06f16, -2.06f16, -2.06f16, -2.06f16,
+ -1.69f16, -1.69f16, -1.69f16, -1.69f16,
+ -1.1f16, -1.1f16, -1.1f16, -1.1f16,
+ },
+ {
+ -1.77f16, -1.77f16, -1.77f16, -1.77f16,
+ -1.6f16, -1.6f16, -1.6f16, -1.6f16,
+ -1.f16, -1.f16, -1.f16, -1.f16,
+ -1.23f16, -1.23f16, -1.23f16, -1.23f16,
+ },
+ {
+ -1.49f16, -1.49f16, -1.49f16, -1.49f16,
+ -1.25f16, -1.25f16, -1.25f16, -1.25f16,
+ -1.18f16, -1.18f16, -1.18f16, -1.18f16,
+ -0.479f16, -0.479f16, -0.479f16, -0.479f16,
+ }
+ },
+ {
+ { 4.95e-04f16 },
+ {
+ 1.4266e-05f16, 1.4266e-05f16, 1.4266e-05f16, 1.4266e-05f16,
+ 1.8129e-05f16, 1.8129e-05f16, 1.8129e-05f16, 1.8129e-05f16,
+ -8.4710e-06f16, -8.4710e-06f16, -8.4710e-06f16, -8.4710e-06f16,
+ 3.7876e-05f16, 3.7876e-05f16, 3.7876e-05f16, 3.7876e-05f16,
+ },
+ {
+ 2.2808e-02f16, 2.2808e-02f16, 2.2808e-02f16, 2.2808e-02f16,
+ 3.9633e-02f16, 3.9633e-02f16, 3.9633e-02f16, 3.9633e-02f16,
+ 9.9657e-02f16, 9.9657e-02f16, 9.9657e-02f16, 9.9657e-02f16,
+ 7.7189e-02f16, 7.7189e-02f16, 7.7189e-02f16, 7.7189e-02f16,
+ },
+ {
+ 2.5547e-05f16, 2.5547e-05f16, 2.5547e-05f16, 2.5547e-05f16,
+ 3.7732e-05f16, 3.7732e-05f16, 3.7732e-05f16, 3.7732e-05f16,
+ 4.0820e-05f16, 4.0820e-05f16, 4.0820e-05f16, 4.0820e-05f16,
+ 7.6054e-05f16, 7.6054e-05f16, 7.6054e-05f16, 7.6054e-05f16,
+ }
+ },
+};
+
+float TEST_MULOP_DATA(float, add)[][4][N] =
+{
+ {
+ { 43.71f },
+ {
+ -410.28f, -410.28f, -410.28f, -410.28f,
+ -276.91f, -276.91f, -276.91f, -276.91f,
+ -103.38f, -103.38f, -103.38f, -103.38f,
+ -378.24f, -378.24f, -378.24f, -378.24f,
+ },
+ {
+ 9.56f, 9.56f, 9.56f, 9.56f,
+ 6.39f, 6.39f, 6.39f, 6.39f,
+ 2.40f, 2.40f, 2.40f, 2.40f,
+ 8.80f, 8.80f, 8.80f, 8.80f,
+ },
+ {
+ 7.59f, 7.59f, 7.59f, 7.59f,
+ 2.40f, 2.40f, 2.40f, 2.40f,
+ 1.52f, 1.52f, 1.52f, 1.52f,
+ 6.41f, 6.41f, 6.41f, 6.41f,
+ }
+ },
+ {
+ { 2.04f },
+ {
+ -110.22f, -110.22f, -110.22f, -110.22f,
+ -25.13f, -25.13f, -25.13f, -25.13f,
+ -108.18f, -108.18f, -108.18f, -108.18f,
+ -107.14f, -107.14f, -107.14f, -107.14f,
+ },
+ {
+ 64.82f, 64.82f, 64.82f, 64.82f,
+ 31.65f, 31.65f, 31.65f, 31.65f,
+ 87.32f, 87.32f, 87.32f, 87.32f,
+ 58.70f, 58.70f, 58.70f, 58.70f,
+ },
+ {
+ 22.01f, 22.01f, 22.01f, 22.01f,
+ 39.44f, 39.44f, 39.44f, 39.44f,
+ 69.95f, 69.95f, 69.95f, 69.95f,
+ 12.61f, 12.61f, 12.61f, 12.61f,
+ }
+ },
+ {
+ { 20.35f },
+ {
+ 881.43f, 881.43f, 881.43f, 881.43f,
+ 3300.17f, 3300.17f, 3300.17f, 3300.17f,
+ 5217.85f, 5217.85f, 5217.85f, 5217.85f,
+ 66.57f, 66.57f, 66.57f, 66.57f,
+ },
+ {
+ 64.82f, 64.82f, 64.82f, 64.82f,
+ 31.65f, 31.65f, 31.65f, 31.65f,
+ 87.32f, 87.32f, 87.32f, 87.32f,
+ 58.70f, 58.70f, 58.70f, 58.70f,
+ },
+ {
+ 2200.52f, 2200.52f, 2200.52f, 2200.52f,
+ 3944.25f, 3944.25f, 3944.25f, 3944.25f,
+ 6994.81f, 6994.81f, 6994.81f, 6994.81f,
+ 1261.12f, 1261.12f, 1261.12f, 1261.12f,
+ }
+ },
+};
+
+double TEST_MULOP_DATA(double, add)[][4][N] =
+{
+ {
+ { 1.16e+12 },
+ {
+ 1.8757e+45, 1.8757e+45, 1.8757e+45, 1.8757e+45,
+ 7.5140e+45, 7.5140e+45, 7.5140e+45, 7.5140e+45,
+ 8.2069e+45, 8.2069e+45, 8.2069e+45, 8.2069e+45,
+ 4.9456e+45, 4.9456e+45, 4.9456e+45, 4.9456e+45,
+ },
+ {
+ 9.0242e+32, 9.0242e+32, 9.0242e+32, 9.0242e+32,
+ 3.6908e+32, 3.6908e+32, 3.6908e+32, 3.6908e+32,
+ 3.9202e+32, 3.9202e+32, 3.9202e+32, 3.9202e+32,
+ 5.0276e+32, 5.0276e+32, 5.0276e+32, 5.0276e+32,
+ },
+ {
+ 2.9201e+45, 2.9201e+45, 2.9201e+45, 2.9201e+45,
+ 7.9411e+45, 7.9411e+45, 7.9411e+45, 7.9411e+45,
+ 8.6606e+45, 8.6606e+45, 8.6606e+45, 8.6606e+45,
+ 5.5275e+45, 5.5275e+45, 5.5275e+45, 5.5275e+45,
+ }
+ },
+ {
+ { -7.29e+23 },
+ {
+ -6.4993e+65, -6.4993e+65, -6.4993e+65, -6.4993e+65,
+ -4.6760e+65, -4.6760e+65, -4.6760e+65, -4.6760e+65,
+ -8.1564e+65, -8.1564e+65, -8.1564e+65, -8.1564e+65,
+ -8.2899e+65, -8.2899e+65, -8.2899e+65, -8.2899e+65,
+ },
+ {
+ -7.7764e+41, -7.7764e+41, -7.7764e+41, -7.7764e+41,
+ -1.9756e+41, -1.9756e+41, -1.9756e+41, -1.9756e+41,
+ -4.8980e+41, -4.8980e+41, -4.8980e+41, -4.8980e+41,
+ -8.1062e+41, -8.1062e+41, -8.1062e+41, -8.1062e+41,
+ },
+ {
+ -8.2928e+64, -8.2928e+64, -8.2928e+64, -8.2928e+64,
+ -3.2356e+65, -3.2356e+65, -3.2356e+65, -3.2356e+65,
+ -4.5850e+65, -4.5850e+65, -4.5850e+65, -4.5850e+65,
+ -2.3794e+65, -2.3794e+65, -2.3794e+65, -2.3794e+65,
+ }
+ },
+ {
+ { 2.02e-03 },
+ {
+ -1.2191e-35, -1.2191e-35, -1.2191e-35, -1.2191e-35,
+ -1.0471e-36, -1.0471e-36, -1.0471e-36, -1.0471e-36,
+ -9.7582e-36, -9.7582e-36, -9.7582e-36, -9.7582e-36,
+ -2.2097e-36, -2.2097e-36, -2.2097e-36, -2.2097e-36,
+ },
+ {
+ 9.7703e-33, 9.7703e-33, 9.7703e-33, 9.7703e-33,
+ 4.1632e-33, 4.1632e-33, 4.1632e-33, 4.1632e-33,
+ 8.1964e-33, 8.1964e-33, 8.1964e-33, 8.1964e-33,
+ 4.7314e-33, 4.7314e-33, 4.7314e-33, 4.7314e-33,
+ },
+ {
+ 7.5586e-36, 7.5586e-36, 7.5586e-36, 7.5586e-36,
+ 7.3684e-36, 7.3684e-36, 7.3684e-36, 7.3684e-36,
+ 6.8101e-36, 6.8101e-36, 6.8101e-36, 6.8101e-36,
+ 7.3543e-36, 7.3543e-36, 7.3543e-36, 7.3543e-36,
+ }
+ },
+};
+
+_Float16 TEST_MULOP_DATA(_Float16, sub)[][4][N] =
+{
+ {
+ { 0.676f16 },
+ {
+ 1.39f16, 1.39f16, 1.39f16, 1.39f16,
+ 1.68f16, 1.68f16, 1.68f16, 1.68f16,
+ 1.63f16, 1.63f16, 1.63f16, 1.63f16,
+ 2.12f16, 2.12f16, 2.12f16, 2.12f16,
+ },
+ {
+ 1.04f16, 1.04f16, 1.04f16, 1.04f16,
+ 1.64f16, 1.64f16, 1.64f16, 1.64f16,
+ 1.95f16, 1.95f16, 1.95f16, 1.95f16,
+ 1.39f16, 1.39f16, 1.39f16, 1.39f16,
+ },
+ {
+ 0.687f16, 0.687f16, 0.687f16, 0.687f16,
+ 0.568f16, 0.568f16, 0.568f16, 0.568f16,
+ 0.315f16, 0.315f16, 0.315f16, 0.315f16,
+ 1.18f16, 1.18f16, 1.18f16, 1.18f16,
+ }
+},
+ {
+ { -0.324f16 },
+ {
+ -0.679f16, -0.679f16, -0.679f16, -0.679f16,
+ -0.992f16, -0.992f16, -0.992f16, -0.992f16,
+ -1.34f16, -1.34f16, -1.34f16, -1.34f16,
+ -0.297f16, -0.297f16, -0.297f16, -0.297f16,
+ },
+ {
+ -1.96f16, -1.96f16, -1.96f16, -1.96f16,
+ -1.36f16, -1.36f16, -1.36f16, -1.36f16,
+ -1.05f16, -1.05f16, -1.05f16, -1.05f16,
+ -1.61f16, -1.61f16, -1.61f16, -1.61f16,
+ },
+ {
+ -1.31f16, -1.31f16, -1.31f16, -1.31f16,
+ -1.43f16, -1.43f16, -1.43f16, -1.43f16,
+ -1.68f16, -1.68f16, -1.68f16, -1.68f16,
+ -0.82f16, -0.82f16, -0.82f16, -0.82f16,
+ }
+ },
+ {
+ { 7.08e+01f16 },
+ {
+ 4.49e+03f16, 4.49e+03f16, 4.49e+03f16, 4.49e+03f16,
+ 7.73e+03f16, 7.73e+03f16, 7.73e+03f16, 7.73e+03f16,
+ 8.42e+03f16, 8.42e+03f16, 8.42e+03f16, 8.42e+03f16,
+ 9.12e+03f16, 9.12e+03f16, 9.12e+03f16, 9.12e+03f16,
+ },
+ {
+ 1.40e+01f16, 1.40e+01f16, 1.40e+01f16, 1.40e+01f16,
+ 6.80e+01f16, 6.80e+01f16, 6.80e+01f16, 6.80e+01f16,
+ 9.54e+01f16, 9.54e+01f16, 9.54e+01f16, 9.54e+01f16,
+ 4.49e+01f16, 4.49e+01f16, 4.49e+01f16, 4.49e+01f16,
+ },
+ {
+ 3.50e+03f16, 3.50e+03f16, 3.50e+03f16, 3.50e+03f16,
+ 2.91e+03f16, 2.91e+03f16, 2.91e+03f16, 2.91e+03f16,
+ 1.66e+03f16, 1.66e+03f16, 1.66e+03f16, 1.66e+03f16,
+ 5.94e+03f16, 5.94e+03f16, 5.94e+03f16, 5.94e+03f16,
+ }
+ },
+};
+
+float TEST_MULOP_DATA(float, sub)[][4][N] =
+{
+ {
+ {8.51f },
+ {
+ 24.21f, 24.21f, 24.21f, 24.21f,
+ 40.31f, 40.31f, 40.31f, 40.31f,
+ 59.68f, 59.68f, 59.68f, 59.68f,
+ 45.42f, 45.42f, 45.42f, 45.42f,
+ },
+ {
+ 1.94f, 1.94f, 1.94f, 1.94f,
+ 4.24f, 4.24f, 4.24f, 4.24f,
+ 6.48f, 6.48f, 6.48f, 6.48f,
+ 4.68f, 4.68f, 4.68f, 4.68f,
+ },
+ {
+ 7.70f, 7.70f, 7.70f, 7.70f,
+ 4.23f, 4.23f, 4.23f, 4.23f,
+ 4.54f, 4.54f, 4.54f, 4.54f,
+ 5.59f, 5.59f, 5.59f, 5.59f,
+ },
+},
+ {
+ { 85.14f },
+ {
+ 1731.29f, 1731.29f, 1731.29f, 1731.29f,
+ 3656.53f, 3656.53f, 3656.53f, 3656.53f,
+ 5565.07f, 5565.07f, 5565.07f, 5565.07f,
+ 4042.14f, 4042.14f, 4042.14f, 4042.14f,
+ },
+ {
+ 19.43f, 19.43f, 19.43f, 19.43f,
+ 42.45f, 42.45f, 42.45f, 42.45f,
+ 64.83f, 64.83f, 64.83f, 64.83f,
+ 46.82f, 46.82f, 46.82f, 46.82f,
+ },
+ {
+ 77.02f, 77.02f, 77.02f, 77.02f,
+ 42.34f, 42.34f, 42.34f, 42.34f,
+ 45.44f, 45.44f, 45.44f, 45.44f,
+ 55.89f, 55.89f, 55.89f, 55.89f,
+ }
+ },
+ {
+ { 99.01f },
+ {
+ 6240.43f, 6240.43f, 6240.43f, 6240.43f,
+ 2179.23f, 2179.23f, 2179.23f, 2179.23f,
+ 5346.65f, 5346.65f, 5346.65f, 5346.65f,
+ 2649.91f, 2649.91f, 2649.91f, 2649.91f,
+ },
+ {
+ 59.46f, 59.46f, 59.46f, 59.46f,
+ 16.96f, 16.96f, 16.96f, 16.96f,
+ 52.55f, 52.55f, 52.55f, 52.55f,
+ 24.70f, 24.70f, 24.70f, 24.70f,
+ },
+ {
+ 353.30f, 353.30f, 353.30f, 353.30f,
+ 500.02f, 500.02f, 500.02f, 500.02f,
+ 143.67f, 143.67f, 143.67f, 143.67f,
+ 204.36f, 204.36f, 204.36f, 204.36f,
+ }
+ },
+};
+
+double TEST_MULOP_DATA(double, sub)[][4][N] =
+{
+ {
+ { 80.54 },
+ {
+ 5731.60, 5731.60, 5731.60, 5731.60,
+ 6682.41, 6682.41, 6682.41, 6682.41,
+ 7737.53, 7737.53, 7737.53, 7737.53,
+ 4922.68, 4922.68, 4922.68, 4922.68,
+ },
+ {
+ 67.14, 67.14, 67.14, 67.14,
+ 78.23, 78.23, 78.23, 78.23,
+ 94.35, 94.35, 94.35, 94.35,
+ 49.68, 49.68, 49.68, 49.68,
+ },
+ {
+ 324.14, 324.14, 324.14, 324.14,
+ 381.77, 381.77, 381.77, 381.77,
+ 138.58, 138.58, 138.58, 138.58,
+ 921.45, 921.45, 921.45, 921.45,
+ }
+ },
+ {
+ { 8.05e+01 },
+ {
+ 8.65e+27, 8.65e+27, 8.65e+27, 8.65e+27,
+ 1.01e+28, 1.01e+28, 1.01e+28, 1.01e+28,
+ 8.99e+27, 8.99e+27, 8.99e+27, 8.99e+27,
+ 1.32e+28, 1.32e+28, 1.32e+28, 1.32e+28,
+ },
+ {
+ 6.71e+25, 6.71e+25, 6.71e+25, 6.71e+25,
+ 7.82e+25, 7.82e+25, 7.82e+25, 7.82e+25,
+ 9.44e+25, 9.44e+25, 9.44e+25, 9.44e+25,
+ 4.97e+25, 4.97e+25, 4.97e+25, 4.97e+25,
+ },
+ {
+ 3.24e+27, 3.24e+27, 3.24e+27, 3.24e+27,
+ 3.82e+27, 3.82e+27, 3.82e+27, 3.82e+27,
+ 1.39e+27, 1.39e+27, 1.39e+27, 1.39e+27,
+ 9.21e+27, 9.21e+27, 9.21e+27, 9.21e+27,
+ }
+ },
+ {
+ { 2.02e-03 },
+ {
+ 2.7308e-35, 2.7308e-35, 2.7308e-35, 2.7308e-35,
+ 1.5784e-35, 1.5784e-35, 1.5784e-35, 1.5784e-35,
+ 2.3378e-35, 2.3378e-35, 2.3378e-35, 2.3378e-35,
+ 1.6918e-35, 1.6918e-35, 1.6918e-35, 1.6918e-35,
+ },
+ {
+ 9.7703e-33, 9.7703e-33, 9.7703e-33, 9.7703e-33,
+ 4.1632e-33, 4.1632e-33, 4.1632e-33, 4.1632e-33,
+ 8.1964e-33, 8.1964e-33, 8.1964e-33, 8.1964e-33,
+ 4.7314e-33, 4.7314e-33, 4.7314e-33, 4.7314e-33,
+ },
+ {
+ 7.5586e-36, 7.5586e-36, 7.5586e-36, 7.5586e-36,
+ 7.3684e-36, 7.3684e-36, 7.3684e-36, 7.3684e-36,
+ 6.8101e-36, 6.8101e-36, 6.8101e-36, 6.8101e-36,
+ 7.3543e-36, 7.3543e-36, 7.3543e-36, 7.3543e-36,
+ }
+ },
+};
+
+
+#endif
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_run.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_run.h
new file mode 100644
index 0000000..bc6f483d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_run.h
@@ -0,0 +1,34 @@
+#ifndef HAVE_DEFINED_VF_MULOP_RUN_H
+#define HAVE_DEFINED_VF_MULOP_RUN_H
+
+#include <math.h>
+
+#define TYPE_FABS(x, T) \
+ (__builtin_types_compatible_p (T, double) ? fabs (x) : fabsf (x))
+
+int
+main ()
+{
+ unsigned i, k;
+
+ for (i = 0; i < sizeof (TEST_DATA) / sizeof (TEST_DATA[0]); i++)
+ {
+ T x = TEST_DATA[i][0][0];
+ T *in = TEST_DATA[i][1];
+ T *out = TEST_DATA[i][2];
+ T *expect = TEST_DATA[i][3];
+
+ TEST_RUN (T, NAME, out, in, x, N);
+
+ for (k = 0; k < N; k++)
+ {
+ T diff = expect[k] - out[k];
+ if (TYPE_FABS (diff, T) > .01 * TYPE_FABS (expect[k], T))
+ __builtin_abort ();
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c
new file mode 100644
index 0000000..1bcf9e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "--param=fpr2vr-cost=0" } */
+
+#include "vf_mulop.h"
+#include "vf_mulop_data.h"
+
+#define T _Float16
+#define NAME add
+
+DEF_VF_MULOP_CASE_0_WRAP(T, +, NAME)
+
+#define TEST_DATA TEST_MULOP_DATA_WRAP(T, NAME)
+#define TEST_RUN(T, NAME, out, in, x, n) RUN_VF_MULOP_CASE_0_WRAP(T, NAME, out, in, x, n)
+
+#include "vf_mulop_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f32.c
new file mode 100644
index 0000000..199b9ad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f32.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "--param=fpr2vr-cost=0" } */
+
+#include "vf_mulop.h"
+#include "vf_mulop_data.h"
+
+#define T float
+#define NAME add
+
+DEF_VF_MULOP_CASE_0_WRAP(T, +, NAME)
+
+#define TEST_DATA TEST_MULOP_DATA_WRAP(T, NAME)
+#define TEST_RUN(T, NAME, out, in, x, n) RUN_VF_MULOP_CASE_0_WRAP(T, NAME, out, in, x, n)
+
+#include "vf_mulop_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f64.c
new file mode 100644
index 0000000..3857f58
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f64.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "--param=fpr2vr-cost=0" } */
+
+#include "vf_mulop.h"
+#include "vf_mulop_data.h"
+
+#define T double
+#define NAME add
+
+DEF_VF_MULOP_CASE_0_WRAP(T, +, NAME)
+
+#define TEST_DATA TEST_MULOP_DATA_WRAP(T, NAME)
+#define TEST_RUN(T, NAME, out, in, x, n) RUN_VF_MULOP_CASE_0_WRAP(T, NAME, out, in, x, n)
+
+#include "vf_mulop_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c
new file mode 100644
index 0000000..671c7d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "--param=fpr2vr-cost=0" } */
+
+#include "vf_mulop.h"
+#include "vf_mulop_data.h"
+
+#define T _Float16
+#define NAME sub
+
+DEF_VF_MULOP_CASE_0_WRAP(T, -, NAME)
+
+#define TEST_DATA TEST_MULOP_DATA_WRAP(T, NAME)
+#define TEST_RUN(T, NAME, out, in, x, n) RUN_VF_MULOP_CASE_0_WRAP(T, NAME, out, in, x, n)
+
+#include "vf_mulop_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f32.c
new file mode 100644
index 0000000..f896963
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f32.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "--param=fpr2vr-cost=0" } */
+
+#include "vf_mulop.h"
+#include "vf_mulop_data.h"
+
+#define T float
+#define NAME sub
+
+DEF_VF_MULOP_CASE_0_WRAP(T, -, NAME)
+
+#define TEST_DATA TEST_MULOP_DATA_WRAP(T, NAME)
+#define TEST_RUN(T, NAME, out, in, x, n) RUN_VF_MULOP_CASE_0_WRAP(T, NAME, out, in, x, n)
+
+#include "vf_mulop_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f64.c
new file mode 100644
index 0000000..b42ab1e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f64.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "--param=fpr2vr-cost=0" } */
+
+#include "vf_mulop.h"
+#include "vf_mulop_data.h"
+
+#define T double
+#define NAME sub
+
+DEF_VF_MULOP_CASE_0_WRAP(T, -, NAME)
+
+#define TEST_DATA TEST_MULOP_DATA_WRAP(T, NAME)
+#define TEST_RUN(T, NAME, out, in, x, n) RUN_VF_MULOP_CASE_0_WRAP(T, NAME, out, in, x, n)
+
+#include "vf_mulop_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c
index 144d1ba..d88e76b 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_0_WRAP(T, &, and)
DEF_VX_BINARY_CASE_0_WRAP(T, |, or)
DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)
DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
+DEF_VX_BINARY_CASE_0_WRAP(T, /, div)
/* { dg-final { scan-assembler-times {vadd.vx} 1 } } */
/* { dg-final { scan-assembler-times {vsub.vx} 1 } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
/* { dg-final { scan-assembler-times {vor.vx} 1 } } */
/* { dg-final { scan-assembler-times {vxor.vx} 1 } } */
/* { dg-final { scan-assembler-times {vmul.vx} 1 } } */
+/* { dg-final { scan-assembler-times {vdiv.vx} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c
index 74d35d1..53189c2 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_0_WRAP(T, &, and)
DEF_VX_BINARY_CASE_0_WRAP(T, |, or)
DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)
DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
+DEF_VX_BINARY_CASE_0_WRAP(T, /, div)
/* { dg-final { scan-assembler-times {vadd.vx} 1 } } */
/* { dg-final { scan-assembler-times {vsub.vx} 1 } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
/* { dg-final { scan-assembler-times {vor.vx} 1 } } */
/* { dg-final { scan-assembler-times {vxor.vx} 1 } } */
/* { dg-final { scan-assembler-times {vmul.vx} 1 } } */
+/* { dg-final { scan-assembler-times {vdiv.vx} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c
index ac512ff..5059beb 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_0_WRAP(T, &, and)
DEF_VX_BINARY_CASE_0_WRAP(T, |, or)
DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)
DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
+DEF_VX_BINARY_CASE_0_WRAP(T, /, div)
/* { dg-final { scan-assembler-times {vadd.vx} 1 } } */
/* { dg-final { scan-assembler-times {vsub.vx} 1 } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
/* { dg-final { scan-assembler-times {vor.vx} 1 } } */
/* { dg-final { scan-assembler-times {vxor.vx} 1 } } */
/* { dg-final { scan-assembler-times {vmul.vx} 1 } } */
+/* { dg-final { scan-assembler-times {vdiv.vx} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c
index 4f7b675..4bbe5a4 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_0_WRAP(T, &, and)
DEF_VX_BINARY_CASE_0_WRAP(T, |, or)
DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)
DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
+DEF_VX_BINARY_CASE_0_WRAP(T, /, div)
/* { dg-final { scan-assembler-times {vadd.vx} 1 } } */
/* { dg-final { scan-assembler-times {vsub.vx} 1 } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
/* { dg-final { scan-assembler-times {vor.vx} 1 } } */
/* { dg-final { scan-assembler-times {vxor.vx} 1 } } */
/* { dg-final { scan-assembler-times {vmul.vx} 1 } } */
+/* { dg-final { scan-assembler-times {vdiv.vx} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c
index 075c8be..0437db4 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_0_WRAP(T, &, and)
DEF_VX_BINARY_CASE_0_WRAP(T, |, or)
DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)
DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
+DEF_VX_BINARY_CASE_0_WRAP(T, /, div)
/* { dg-final { scan-assembler-not {vadd.vx} } } */
/* { dg-final { scan-assembler-not {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
/* { dg-final { scan-assembler-not {vor.vx} } } */
/* { dg-final { scan-assembler-not {vxor.vx} } } */
/* { dg-final { scan-assembler-not {vmul.vx} } } */
+/* { dg-final { scan-assembler-not {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c
index 595479c..95ed403 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_0_WRAP(T, &, and)
DEF_VX_BINARY_CASE_0_WRAP(T, |, or)
DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)
DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
+DEF_VX_BINARY_CASE_0_WRAP(T, /, div)
/* { dg-final { scan-assembler-not {vadd.vx} } } */
/* { dg-final { scan-assembler-not {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
/* { dg-final { scan-assembler-not {vor.vx} } } */
/* { dg-final { scan-assembler-not {vxor.vx} } } */
/* { dg-final { scan-assembler-not {vmul.vx} } } */
+/* { dg-final { scan-assembler-not {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c
index 7b6fcbf..f8912a0 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_0_WRAP(T, &, and)
DEF_VX_BINARY_CASE_0_WRAP(T, |, or)
DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)
DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
+DEF_VX_BINARY_CASE_0_WRAP(T, /, div)
/* { dg-final { scan-assembler-not {vadd.vx} } } */
/* { dg-final { scan-assembler-not {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
/* { dg-final { scan-assembler-not {vor.vx} } } */
/* { dg-final { scan-assembler-not {vxor.vx} } } */
/* { dg-final { scan-assembler-not {vmul.vx} } } */
+/* { dg-final { scan-assembler-not {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c
index 55fc717..3c8f915 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_0_WRAP(T, &, and)
DEF_VX_BINARY_CASE_0_WRAP(T, |, or)
DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)
DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
+DEF_VX_BINARY_CASE_0_WRAP(T, /, div)
/* { dg-final { scan-assembler-not {vadd.vx} } } */
/* { dg-final { scan-assembler-not {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
/* { dg-final { scan-assembler-not {vor.vx} } } */
/* { dg-final { scan-assembler-not {vxor.vx} } } */
/* { dg-final { scan-assembler-not {vmul.vx} } } */
+/* { dg-final { scan-assembler-not {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c
index bec6b3a..f49dae4 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_0_WRAP(T, &, and)
DEF_VX_BINARY_CASE_0_WRAP(T, |, or)
DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)
DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
+DEF_VX_BINARY_CASE_0_WRAP(T, /, div)
/* { dg-final { scan-assembler-not {vadd.vx} } } */
/* { dg-final { scan-assembler-not {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
/* { dg-final { scan-assembler-not {vor.vx} } } */
/* { dg-final { scan-assembler-not {vxor.vx} } } */
/* { dg-final { scan-assembler-not {vmul.vx} } } */
+/* { dg-final { scan-assembler-not {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c
index 98fce52..8f502a3 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_0_WRAP(T, &, and)
DEF_VX_BINARY_CASE_0_WRAP(T, |, or)
DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)
DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
+DEF_VX_BINARY_CASE_0_WRAP(T, /, div)
/* { dg-final { scan-assembler-not {vadd.vx} } } */
/* { dg-final { scan-assembler-not {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
/* { dg-final { scan-assembler-not {vor.vx} } } */
/* { dg-final { scan-assembler-not {vxor.vx} } } */
/* { dg-final { scan-assembler-not {vmul.vx} } } */
+/* { dg-final { scan-assembler-not {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c
index 48dd57a..3277bf2 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_0_WRAP(T, &, and)
DEF_VX_BINARY_CASE_0_WRAP(T, |, or)
DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)
DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
+DEF_VX_BINARY_CASE_0_WRAP(T, /, div)
/* { dg-final { scan-assembler-not {vadd.vx} } } */
/* { dg-final { scan-assembler-not {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
/* { dg-final { scan-assembler-not {vor.vx} } } */
/* { dg-final { scan-assembler-not {vxor.vx} } } */
/* { dg-final { scan-assembler-not {vmul.vx} } } */
+/* { dg-final { scan-assembler-not {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c
index 9bdce82..25ed2ad 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_0_WRAP(T, &, and)
DEF_VX_BINARY_CASE_0_WRAP(T, |, or)
DEF_VX_BINARY_CASE_0_WRAP(T, ^, xor)
DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
+DEF_VX_BINARY_CASE_0_WRAP(T, /, div)
/* { dg-final { scan-assembler-not {vadd.vx} } } */
/* { dg-final { scan-assembler-not {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_0_WRAP(T, *, mul)
/* { dg-final { scan-assembler-not {vor.vx} } } */
/* { dg-final { scan-assembler-not {vxor.vx} } } */
/* { dg-final { scan-assembler-not {vmul.vx} } } */
+/* { dg-final { scan-assembler-not {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c
index a1b24f7..1e409de 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_1_WRAP(T, &, and, VX_BINARY_BODY_X16)
DEF_VX_BINARY_CASE_1_WRAP(T, |, or, VX_BINARY_BODY_X16)
DEF_VX_BINARY_CASE_1_WRAP(T, ^, xor, VX_BINARY_BODY_X16)
DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X16)
+DEF_VX_BINARY_CASE_1_WRAP(T, /, div, VX_BINARY_BODY_X16)
/* { dg-final { scan-assembler {vadd.vx} } } */
/* { dg-final { scan-assembler {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X16)
/* { dg-final { scan-assembler {vor.vx} } } */
/* { dg-final { scan-assembler {vxor.vx} } } */
/* { dg-final { scan-assembler {vmul.vx} } } */
+/* { dg-final { scan-assembler {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c
index 53bd744..2f242c7 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_1_WRAP(T, &, and, VX_BINARY_BODY_X4)
DEF_VX_BINARY_CASE_1_WRAP(T, |, or, VX_BINARY_BODY_X4)
DEF_VX_BINARY_CASE_1_WRAP(T, ^, xor, VX_BINARY_BODY_X4)
DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X4)
+DEF_VX_BINARY_CASE_1_WRAP(T, /, div, VX_BINARY_BODY_X4)
/* { dg-final { scan-assembler {vadd.vx} } } */
/* { dg-final { scan-assembler {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X4)
/* { dg-final { scan-assembler {vor.vx} } } */
/* { dg-final { scan-assembler {vxor.vx} } } */
/* { dg-final { scan-assembler {vmul.vx} } } */
+/* { dg-final { scan-assembler {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c
index 73cb89d..f027bd8 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_1_WRAP(T, &, and, VX_BINARY_BODY)
DEF_VX_BINARY_CASE_1_WRAP(T, |, or, VX_BINARY_BODY)
DEF_VX_BINARY_CASE_1_WRAP(T, ^, xor, VX_BINARY_BODY)
DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY)
+DEF_VX_BINARY_CASE_1_WRAP(T, /, div, VX_BINARY_BODY)
/* { dg-final { scan-assembler {vadd.vx} } } */
/* { dg-final { scan-assembler {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY)
/* { dg-final { scan-assembler {vor.vx} } } */
/* { dg-final { scan-assembler {vxor.vx} } } */
/* { dg-final { scan-assembler {vmul.vx} } } */
+/* { dg-final { scan-assembler {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c
index ec20474..c4f55b0 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_1_WRAP(T, &, and, VX_BINARY_BODY_X16)
DEF_VX_BINARY_CASE_1_WRAP(T, |, or, VX_BINARY_BODY_X16)
DEF_VX_BINARY_CASE_1_WRAP(T, ^, xor, VX_BINARY_BODY_X16)
DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X16)
+DEF_VX_BINARY_CASE_1_WRAP(T, /, div, VX_BINARY_BODY_X8)
/* { dg-final { scan-assembler {vadd.vx} } } */
/* { dg-final { scan-assembler {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X16)
/* { dg-final { scan-assembler {vor.vx} } } */
/* { dg-final { scan-assembler {vxor.vx} } } */
/* { dg-final { scan-assembler {vmul.vx} } } */
+/* { dg-final { scan-assembler {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c
index 902ba1e..d6b05bc 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_1_WRAP(T, &, and, VX_BINARY_BODY_X8)
DEF_VX_BINARY_CASE_1_WRAP(T, |, or, VX_BINARY_BODY_X8)
DEF_VX_BINARY_CASE_1_WRAP(T, ^, xor, VX_BINARY_BODY_X8)
DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X8)
+DEF_VX_BINARY_CASE_1_WRAP(T, /, div, VX_BINARY_BODY_X8)
/* { dg-final { scan-assembler-not {vadd.vx} } } */
/* { dg-final { scan-assembler {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X8)
/* { dg-final { scan-assembler {vor.vx} } } */
/* { dg-final { scan-assembler {vxor.vx} } } */
/* { dg-final { scan-assembler-not {vmul.vx} } } */
+/* { dg-final { scan-assembler {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c
index e57cee6..e1c043f 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_1_WRAP(T, &, and, VX_BINARY_BODY_X4)
DEF_VX_BINARY_CASE_1_WRAP(T, |, or, VX_BINARY_BODY_X4)
DEF_VX_BINARY_CASE_1_WRAP(T, ^, xor, VX_BINARY_BODY_X4)
DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X4)
+DEF_VX_BINARY_CASE_1_WRAP(T, /, div, VX_BINARY_BODY_X4)
/* { dg-final { scan-assembler {vadd.vx} } } */
/* { dg-final { scan-assembler {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X4)
/* { dg-final { scan-assembler {vor.vx} } } */
/* { dg-final { scan-assembler {vxor.vx} } } */
/* { dg-final { scan-assembler {vmul.vx} } } */
+/* { dg-final { scan-assembler {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c
index 3b4138d..1beb914 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_1_WRAP(T, &, and, VX_BINARY_BODY)
DEF_VX_BINARY_CASE_1_WRAP(T, |, or, VX_BINARY_BODY)
DEF_VX_BINARY_CASE_1_WRAP(T, ^, xor, VX_BINARY_BODY)
DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY)
+DEF_VX_BINARY_CASE_1_WRAP(T, /, div, VX_BINARY_BODY)
/* { dg-final { scan-assembler {vadd.vx} } } */
/* { dg-final { scan-assembler {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY)
/* { dg-final { scan-assembler {vor.vx} } } */
/* { dg-final { scan-assembler {vxor.vx} } } */
/* { dg-final { scan-assembler {vmul.vx} } } */
+/* { dg-final { scan-assembler {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c
index 0ad52b2..0291517 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_1_WRAP(T, &, and, VX_BINARY_BODY_X16)
DEF_VX_BINARY_CASE_1_WRAP(T, |, or, VX_BINARY_BODY_X16)
DEF_VX_BINARY_CASE_1_WRAP(T, ^, xor, VX_BINARY_BODY_X16)
DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X16)
+DEF_VX_BINARY_CASE_1_WRAP(T, /, div, VX_BINARY_BODY_X8)
/* { dg-final { scan-assembler-not {vadd.vx} } } */
/* { dg-final { scan-assembler {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X16)
/* { dg-final { scan-assembler {vor.vx} } } */
/* { dg-final { scan-assembler {vxor.vx} } } */
/* { dg-final { scan-assembler-not {vmul.vx} } } */
+/* { dg-final { scan-assembler {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c
index 5e04050..c22c82d 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_1_WRAP(T, &, and, VX_BINARY_BODY_X8)
DEF_VX_BINARY_CASE_1_WRAP(T, |, or, VX_BINARY_BODY_X8)
DEF_VX_BINARY_CASE_1_WRAP(T, ^, xor, VX_BINARY_BODY_X8)
DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X8)
+DEF_VX_BINARY_CASE_1_WRAP(T, /, div, VX_BINARY_BODY_X8)
/* { dg-final { scan-assembler-not {vadd.vx} } } */
/* { dg-final { scan-assembler {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X8)
/* { dg-final { scan-assembler {vor.vx} } } */
/* { dg-final { scan-assembler {vxor.vx} } } */
/* { dg-final { scan-assembler-not {vmul.vx} } } */
+/* { dg-final { scan-assembler {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c
index 13a9fe2..dc35600 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_1_WRAP(T, &, and, VX_BINARY_BODY_X4)
DEF_VX_BINARY_CASE_1_WRAP(T, |, or, VX_BINARY_BODY_X4)
DEF_VX_BINARY_CASE_1_WRAP(T, ^, xor, VX_BINARY_BODY_X4)
DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X4)
+DEF_VX_BINARY_CASE_1_WRAP(T, /, div, VX_BINARY_BODY_X4)
/* { dg-final { scan-assembler {vadd.vx} } } */
/* { dg-final { scan-assembler {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X4)
/* { dg-final { scan-assembler {vor.vx} } } */
/* { dg-final { scan-assembler {vxor.vx} } } */
/* { dg-final { scan-assembler {vmul.vx} } } */
+/* { dg-final { scan-assembler {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c
index ca515b4..cee1e3a 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_1_WRAP(T, &, and, VX_BINARY_BODY)
DEF_VX_BINARY_CASE_1_WRAP(T, |, or, VX_BINARY_BODY)
DEF_VX_BINARY_CASE_1_WRAP(T, ^, xor, VX_BINARY_BODY)
DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY)
+DEF_VX_BINARY_CASE_1_WRAP(T, /, div, VX_BINARY_BODY)
/* { dg-final { scan-assembler-not {vadd.vx} } } */
/* { dg-final { scan-assembler-not {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY)
/* { dg-final { scan-assembler-not {vor.vx} } } */
/* { dg-final { scan-assembler-not {vxor.vx} } } */
/* { dg-final { scan-assembler-not {vmul.vx} } } */
+/* { dg-final { scan-assembler-not {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c
index 70e1abc..74fd2fb 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c
@@ -12,6 +12,7 @@ DEF_VX_BINARY_CASE_1_WRAP(T, &, and, VX_BINARY_BODY_X16)
DEF_VX_BINARY_CASE_1_WRAP(T, |, or, VX_BINARY_BODY_X16)
DEF_VX_BINARY_CASE_1_WRAP(T, ^, xor, VX_BINARY_BODY_X16)
DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X16)
+DEF_VX_BINARY_CASE_1_WRAP(T, /, div, VX_BINARY_BODY_X8)
/* { dg-final { scan-assembler-not {vadd.vx} } } */
/* { dg-final { scan-assembler {vsub.vx} } } */
@@ -20,3 +21,4 @@ DEF_VX_BINARY_CASE_1_WRAP(T, *, mul, VX_BINARY_BODY_X16)
/* { dg-final { scan-assembler {vor.vx} } } */
/* { dg-final { scan-assembler {vxor.vx} } } */
/* { dg-final { scan-assembler-not {vmul.vx} } } */
+/* { dg-final { scan-assembler {vdiv.vx} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h
index c7289ac..ed8c562 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h
@@ -2554,4 +2554,200 @@ int64_t TEST_BINARY_DATA(int64_t, mul)[][3][N] =
},
};
+int8_t TEST_BINARY_DATA(int8_t, div)[][3][N] =
+{
+ {
+ { 1 },
+ {
+ 2, 2, 2, 2,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ -2, -2, -2, -2,
+ },
+ {
+ 2, 2, 2, 2,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ -2, -2, -2, -2,
+ },
+ },
+ {
+ { 127 },
+ {
+ 127, 127, 127, 127,
+ -1, -1, -1, -1,
+ -128, -128, -128, -128,
+ -2, -2, -2, -2,
+ },
+ {
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ -1, -1, -1, -1,
+ 0, 0, 0, 0,
+ },
+ },
+ {
+ { -128 },
+ {
+ -128, -128, -128, -128,
+ 1, 1, 1, 1,
+ 127, 127, 127, 127,
+ 2, 2, 2, 2,
+ },
+ {
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ },
+};
+
+int16_t TEST_BINARY_DATA(int16_t, div)[][3][N] =
+{
+ {
+ { 1 },
+ {
+ 2, 2, 2, 2,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ -2, -2, -2, -2,
+ },
+ {
+ 2, 2, 2, 2,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ -2, -2, -2, -2,
+ },
+ },
+ {
+ { 32767 },
+ {
+ 32767, 32767, 32767, 32767,
+ -1, -1, -1, -1,
+ -32768, -32768, -32768, -32768,
+ -2, -2, -2, -2,
+ },
+ {
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ -1, -1, -1, -1,
+ 0, 0, 0, 0,
+ },
+ },
+ {
+ { -32768 },
+ {
+ -32768, -32768, -32768, -32768,
+ 1, 1, 1, 1,
+ 32767, 32767, 32767, 32767,
+ 2, 2, 2, 2,
+ },
+ {
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ },
+};
+
+int32_t TEST_BINARY_DATA(int32_t, div)[][3][N] =
+{
+ {
+ { 1 },
+ {
+ 2, 2, 2, 2,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ -2, -2, -2, -2,
+ },
+ {
+ 2, 2, 2, 2,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ -2, -2, -2, -2,
+ },
+ },
+ {
+ { 2147483647 },
+ {
+ 2147483647, 2147483647, 2147483647, 2147483647,
+ -1, -1, -1, -1,
+ -2147483648, -2147483648, -2147483648, -2147483648,
+ -2, -2, -2, -2,
+ },
+ {
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ -1, -1, -1, -1,
+ 0, 0, 0, 0,
+ },
+ },
+ {
+ { -2147483648 },
+ {
+ -2147483648, -2147483648, -2147483648, -2147483648,
+ 1, 1, 1, 1,
+ 2147483647, 2147483647, 2147483647, 2147483647,
+ 2, 2, 2, 2,
+ },
+ {
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ },
+};
+
+int64_t TEST_BINARY_DATA(int64_t, div)[][3][N] =
+{
+ {
+ { 1 },
+ {
+ 2, 2, 2, 2,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ -2, -2, -2, -2,
+ },
+ {
+ 2, 2, 2, 2,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ -2, -2, -2, -2,
+ },
+ },
+ {
+ { 9223372036854775807ll },
+ {
+ 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll,
+ -1, -1, -1, -1,
+ -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+ -2, -2, -2, -2,
+ },
+ {
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ -1, -1, -1, -1,
+ 0, 0, 0, 0,
+ },
+ },
+ {
+ { -9223372036854775808ull },
+ {
+ -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+ 1, 1, 1, 1,
+ 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll,
+ 2, 2, 2, 2,
+ },
+ {
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ },
+};
+
#endif
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i16.c
new file mode 100644
index 0000000..64cf31c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i16.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+
+#include "vx_binary.h"
+#include "vx_binary_data.h"
+
+#define T int16_t
+#define NAME div
+
+DEF_VX_BINARY_CASE_0_WRAP(T, /, NAME)
+
+#define TEST_DATA TEST_BINARY_DATA_WRAP(T, NAME)
+#define TEST_RUN(T, NAME, out, in, x, n) RUN_VX_BINARY_CASE_0_WRAP(T, NAME, out, in, x, n)
+
+#include "vx_binary_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i32.c
new file mode 100644
index 0000000..2fe6623
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i32.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+
+#include "vx_binary.h"
+#include "vx_binary_data.h"
+
+#define T int32_t
+#define NAME div
+
+DEF_VX_BINARY_CASE_0_WRAP(T, /, NAME)
+
+#define TEST_DATA TEST_BINARY_DATA_WRAP(T, NAME)
+#define TEST_RUN(T, NAME, out, in, x, n) RUN_VX_BINARY_CASE_0_WRAP(T, NAME, out, in, x, n)
+
+#include "vx_binary_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i64.c
new file mode 100644
index 0000000..03dbe03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i64.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+
+#include "vx_binary.h"
+#include "vx_binary_data.h"
+
+#define T int64_t
+#define NAME div
+
+DEF_VX_BINARY_CASE_0_WRAP(T, /, NAME)
+
+#define TEST_DATA TEST_BINARY_DATA_WRAP(T, NAME)
+#define TEST_RUN(T, NAME, out, in, x, n) RUN_VX_BINARY_CASE_0_WRAP(T, NAME, out, in, x, n)
+
+#include "vx_binary_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i8.c
new file mode 100644
index 0000000..e54e5bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vdiv-run-1-i8.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */
+
+#include "vx_binary.h"
+#include "vx_binary_data.h"
+
+#define T int8_t
+#define NAME div
+
+DEF_VX_BINARY_CASE_0_WRAP(T, /, NAME)
+
+#define TEST_DATA TEST_BINARY_DATA_WRAP(T, NAME)
+#define TEST_RUN(T, NAME, out, in, x, n) RUN_VX_BINARY_CASE_0_WRAP(T, NAME, out, in, x, n)
+
+#include "vx_binary_run.h"
diff --git a/gcc/testsuite/gfortran.dg/coarray_data_2.f90 b/gcc/testsuite/gfortran.dg/coarray_data_2.f90
new file mode 100644
index 0000000..bda57f3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_data_2.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+! { dg-additional-options "-fcoarray=lib -Warray-temporaries" }
+!
+! PR fortran/99838 - ICE due to missing locus with data statement for coarray
+!
+! Contributed by Gerhard Steinmetz
+
+program p
+ type t
+ integer :: a
+ end type
+ type(t) :: x(3)[*]
+ data x%a /1, 2, 3/ ! { dg-warning "Creating array temporary" }
+end
diff --git a/gcc/testsuite/gfortran.dg/inquiry_type_ref_8.f90 b/gcc/testsuite/gfortran.dg/inquiry_type_ref_8.f90
new file mode 100644
index 0000000..70ef621
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/inquiry_type_ref_8.f90
@@ -0,0 +1,214 @@
+! { dg-do compile }
+! { dg-additional-options "-O0 -fdump-tree-original -std=f2018" }
+!
+! PR fortran/102599 - type parameter inquiries and constant complex arrays
+! PR fortran/114022 - likewise
+!
+! Everything below shall be simplified at compile time.
+
+module mod
+ implicit none
+ public :: wp, c0, z0, y, test1
+ private
+
+ integer :: j
+ integer, parameter :: n = 5
+ integer, parameter :: wp = 8
+ type :: cx
+ real(wp) :: re
+ real(wp) :: im
+ end type cx
+ type(cx), parameter :: c0(*) = [(cx (j,-j), j=1,n)]
+ complex(wp), parameter :: z0(*) = [(cmplx(j,-j,wp),j=1,n)]
+
+ type :: my_type
+ complex(wp) :: z(n) = z0
+ type(cx) :: c(n) = c0
+ end type my_type
+ type(my_type), parameter :: y = my_type()
+
+contains
+
+ ! Check simplification for inquiries of host-associated variables
+ subroutine test1 ()
+ ! Inquiries and full arrays
+ real(wp), parameter :: r0(*) = real (z0)
+ real(wp), parameter :: i0(*) = aimag (z0)
+ real(wp), parameter :: r1(*) = c0 % re
+ real(wp), parameter :: i1(*) = c0 % im
+ real(wp), parameter :: r2(*) = z0 % re
+ real(wp), parameter :: i2(*) = z0 % im
+ real(wp), parameter :: r3(*) = y % c % re
+ real(wp), parameter :: i3(*) = y % c % im
+ real(wp), parameter :: r4(*) = y % z % re
+ real(wp), parameter :: i4(*) = y % z % im
+
+ logical, parameter :: l1 = all (r1 == r0)
+ logical, parameter :: l2 = all (i1 == i0)
+ logical, parameter :: l3 = all (r1 == r2)
+ logical, parameter :: l4 = all (i1 == i2)
+ logical, parameter :: l5 = all (r3 == r4)
+ logical, parameter :: l6 = all (i3 == i4)
+ logical, parameter :: l7 = all (r1 == r3)
+ logical, parameter :: l8 = all (i1 == i3)
+
+ ! Inquiries and array sections
+ real(wp), parameter :: p0(*) = real (z0(::2))
+ real(wp), parameter :: q0(*) = aimag (z0(::2))
+ real(wp), parameter :: p1(*) = c0(::2) % re
+ real(wp), parameter :: q1(*) = c0(::2) % im
+ real(wp), parameter :: p2(*) = z0(::2) % re
+ real(wp), parameter :: q2(*) = z0(::2) % im
+ real(wp), parameter :: p3(*) = y % c(::2) % re
+ real(wp), parameter :: q3(*) = y % c(::2) % im
+ real(wp), parameter :: p4(*) = y % z(::2) % re
+ real(wp), parameter :: q4(*) = y % z(::2) % im
+
+ logical, parameter :: m1 = all (p1 == p0)
+ logical, parameter :: m2 = all (q1 == q0)
+ logical, parameter :: m3 = all (p1 == p2)
+ logical, parameter :: m4 = all (q1 == q2)
+ logical, parameter :: m5 = all (p3 == p4)
+ logical, parameter :: m6 = all (q3 == q4)
+ logical, parameter :: m7 = all (p1 == p3)
+ logical, parameter :: m8 = all (q1 == q3)
+
+ ! Inquiries and vector subscripts
+ real(wp), parameter :: v0(*) = real (z0([3,2]))
+ real(wp), parameter :: w0(*) = aimag (z0([3,2]))
+ real(wp), parameter :: v1(*) = c0([3,2]) % re
+ real(wp), parameter :: w1(*) = c0([3,2]) % im
+ real(wp), parameter :: v2(*) = z0([3,2]) % re
+ real(wp), parameter :: w2(*) = z0([3,2]) % im
+ real(wp), parameter :: v3(*) = y % c([3,2]) % re
+ real(wp), parameter :: w3(*) = y % c([3,2]) % im
+ real(wp), parameter :: v4(*) = y % z([3,2]) % re
+ real(wp), parameter :: w4(*) = y % z([3,2]) % im
+
+ logical, parameter :: o1 = all (v1 == v0)
+ logical, parameter :: o2 = all (w1 == w0)
+ logical, parameter :: o3 = all (v1 == v2)
+ logical, parameter :: o4 = all (w1 == w2)
+ logical, parameter :: o5 = all (v3 == v4)
+ logical, parameter :: o6 = all (w3 == w4)
+ logical, parameter :: o7 = all (v1 == v3)
+ logical, parameter :: o8 = all (w1 == w3)
+
+ ! Miscellaneous
+ complex(wp), parameter :: x(-1:*) = cmplx (r1,i1,kind=wp)
+ real(x%re%kind), parameter :: r(*) = x % re
+ real(x%im%kind), parameter :: i(*) = x % im
+ real(x%re%kind), parameter :: s(*) = [ x(:) % re ]
+ real(x%im%kind), parameter :: t(*) = [ x(:) % im ]
+
+ integer, parameter :: kr = x % re % kind
+ integer, parameter :: ki = x % im % kind
+ integer, parameter :: kx = x % kind
+
+ if (kr /= wp .or. ki /= wp .or. kx /= wp) stop 1
+ if (any (r /= r1)) stop 2
+ if (any (i /= i1)) stop 3
+ if (any (s /= r1)) stop 4
+ if (any (t /= i1)) stop 5
+
+ if (.not. all ([l1,l2,l3,l4,l5,l6,l7,l8])) stop 6
+ if (.not. all ([m1,m2,m3,m4,m5,m6,m7,m8])) stop 7
+ if (.not. all ([o1,o2,o3,o4,o5,o6,o7,o8])) stop 8
+ end subroutine test1
+end
+
+program p
+ use mod, only: wp, c0, z0, y, test1
+ implicit none
+ call test1 ()
+ call test2 ()
+contains
+ ! Check simplification for inquiries of use-associated variables
+ subroutine test2 ()
+ ! Inquiries and full arrays
+ real(wp), parameter :: r0(*) = real (z0)
+ real(wp), parameter :: i0(*) = aimag (z0)
+ real(wp), parameter :: r1(*) = c0 % re
+ real(wp), parameter :: i1(*) = c0 % im
+ real(wp), parameter :: r2(*) = z0 % re
+ real(wp), parameter :: i2(*) = z0 % im
+ real(wp), parameter :: r3(*) = y % c % re
+ real(wp), parameter :: i3(*) = y % c % im
+ real(wp), parameter :: r4(*) = y % z % re
+ real(wp), parameter :: i4(*) = y % z % im
+
+ logical, parameter :: l1 = all (r1 == r0)
+ logical, parameter :: l2 = all (i1 == i0)
+ logical, parameter :: l3 = all (r1 == r2)
+ logical, parameter :: l4 = all (i1 == i2)
+ logical, parameter :: l5 = all (r3 == r4)
+ logical, parameter :: l6 = all (i3 == i4)
+ logical, parameter :: l7 = all (r1 == r3)
+ logical, parameter :: l8 = all (i1 == i3)
+
+ ! Inquiries and array sections
+ real(wp), parameter :: p0(*) = real (z0(::2))
+ real(wp), parameter :: q0(*) = aimag (z0(::2))
+ real(wp), parameter :: p1(*) = c0(::2) % re
+ real(wp), parameter :: q1(*) = c0(::2) % im
+ real(wp), parameter :: p2(*) = z0(::2) % re
+ real(wp), parameter :: q2(*) = z0(::2) % im
+ real(wp), parameter :: p3(*) = y % c(::2) % re
+ real(wp), parameter :: q3(*) = y % c(::2) % im
+ real(wp), parameter :: p4(*) = y % z(::2) % re
+ real(wp), parameter :: q4(*) = y % z(::2) % im
+
+ logical, parameter :: m1 = all (p1 == p0)
+ logical, parameter :: m2 = all (q1 == q0)
+ logical, parameter :: m3 = all (p1 == p2)
+ logical, parameter :: m4 = all (q1 == q2)
+ logical, parameter :: m5 = all (p3 == p4)
+ logical, parameter :: m6 = all (q3 == q4)
+ logical, parameter :: m7 = all (p1 == p3)
+ logical, parameter :: m8 = all (q1 == q3)
+
+ ! Inquiries and vector subscripts
+ real(wp), parameter :: v0(*) = real (z0([3,2]))
+ real(wp), parameter :: w0(*) = aimag (z0([3,2]))
+ real(wp), parameter :: v1(*) = c0([3,2]) % re
+ real(wp), parameter :: w1(*) = c0([3,2]) % im
+ real(wp), parameter :: v2(*) = z0([3,2]) % re
+ real(wp), parameter :: w2(*) = z0([3,2]) % im
+ real(wp), parameter :: v3(*) = y % c([3,2]) % re
+ real(wp), parameter :: w3(*) = y % c([3,2]) % im
+ real(wp), parameter :: v4(*) = y % z([3,2]) % re
+ real(wp), parameter :: w4(*) = y % z([3,2]) % im
+
+ logical, parameter :: o1 = all (v1 == v0)
+ logical, parameter :: o2 = all (w1 == w0)
+ logical, parameter :: o3 = all (v1 == v2)
+ logical, parameter :: o4 = all (w1 == w2)
+ logical, parameter :: o5 = all (v3 == v4)
+ logical, parameter :: o6 = all (w3 == w4)
+ logical, parameter :: o7 = all (v1 == v3)
+ logical, parameter :: o8 = all (w1 == w3)
+
+ ! Miscellaneous
+ complex(wp), parameter :: x(-1:*) = cmplx (r1,i1,kind=wp)
+ real(x%re%kind), parameter :: r(*) = x % re
+ real(x%im%kind), parameter :: i(*) = x % im
+ real(x%re%kind), parameter :: s(*) = [ x(:) % re ]
+ real(x%im%kind), parameter :: t(*) = [ x(:) % im ]
+
+ integer, parameter :: kr = x % re % kind
+ integer, parameter :: ki = x % im % kind
+ integer, parameter :: kx = x % kind
+
+ if (kr /= wp .or. ki /= wp .or. kx /= wp) stop 11
+ if (any (r /= r1)) stop 12
+ if (any (i /= i1)) stop 13
+ if (any (s /= r1)) stop 14
+ if (any (t /= i1)) stop 15
+
+ if (.not. all ([l1,l2,l3,l4,l5,l6,l7,l8])) stop 16
+ if (.not. all ([m1,m2,m3,m4,m5,m6,m7,m8])) stop 17
+ if (.not. all ([o1,o2,o3,o4,o5,o6,o7,o8])) stop 18
+ end subroutine test2
+end
+
+! { dg-final { scan-tree-dump-not "_gfortran_stop_numeric" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/pr119856.f90 b/gcc/testsuite/gfortran.dg/pr119856.f90
new file mode 100644
index 0000000..60ada0a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr119856.f90
@@ -0,0 +1,15 @@
+! { dg-do run }
+! PR119856, the error should occur in both write statements.
+program badfmt
+ implicit none
+
+ character(10):: fmt = "(AI5)" ! Not a PARAMETER so not examined
+ ! at compile time
+ integer :: ioerr
+ ioerr = 0
+ write (*, fmt, iostat=ioerr) 'value =', 42
+ if (ioerr /= 5006) stop 10
+!
+ write (*, fmt, iostat=ioerr) 'value =', 43
+ if (ioerr /= 5006) stop 13
+end program badfmt
diff --git a/gcc/testsuite/gfortran.dg/save_8.f90 b/gcc/testsuite/gfortran.dg/save_8.f90
new file mode 100644
index 0000000..8e9198c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/save_8.f90
@@ -0,0 +1,13 @@
+!{ dg-do run }
+
+! Check PR120483 is fixed.
+! Contributed by Thomas Koenig <tkoenig@gcc.gnu.org>
+! and Peter Güntert <peter@guentert.com>
+
+program save_8
+ implicit none
+ character(len=:), allocatable, save :: s1
+ s1 = 'ABC'
+ if (s1(3:3) /= 'C') stop 1
+end program save_8
+
diff --git a/gcc/testsuite/gm2/pim/fail/testcharint.mod b/gcc/testsuite/gm2/pim/fail/testcharint.mod
new file mode 100644
index 0000000..d403651
--- /dev/null
+++ b/gcc/testsuite/gm2/pim/fail/testcharint.mod
@@ -0,0 +1,8 @@
+MODULE testcharint ; (*!m2iso+gm2*)
+
+VAR
+ ch: CHAR ;
+ i : INTEGER ;
+BEGIN
+ ch := i
+END testcharint.
diff --git a/gcc/testsuite/gm2/pim/fail/testindrx.mod b/gcc/testsuite/gm2/pim/fail/testindrx.mod
new file mode 100644
index 0000000..2630ebd
--- /dev/null
+++ b/gcc/testsuite/gm2/pim/fail/testindrx.mod
@@ -0,0 +1,8 @@
+MODULE testindrx ; (*!m2iso+gm2*)
+
+VAR
+ x: ARRAY [1..5] OF INTEGER ;
+ ch: CHAR ;
+BEGIN
+ ch := x[1]
+END testindrx.
diff --git a/gcc/testsuite/gm2/pim/pass/ReturnType.mod b/gcc/testsuite/gm2/pim/pass/ReturnType.mod
new file mode 100644
index 0000000..149bc85
--- /dev/null
+++ b/gcc/testsuite/gm2/pim/pass/ReturnType.mod
@@ -0,0 +1,17 @@
+MODULE ReturnType ;
+
+TYPE
+ bar = POINTER TO CARDINAL ;
+
+
+PROCEDURE foo (VAR value: bar) : bar ;
+BEGIN
+ RETURN value
+END foo ;
+
+VAR
+ b: bar ;
+BEGIN
+ b := NIL ;
+ b := foo (b)
+END ReturnType.
diff --git a/gcc/testsuite/gm2/pim/pass/ReturnType2.mod b/gcc/testsuite/gm2/pim/pass/ReturnType2.mod
new file mode 100644
index 0000000..bab7f5b
--- /dev/null
+++ b/gcc/testsuite/gm2/pim/pass/ReturnType2.mod
@@ -0,0 +1,19 @@
+MODULE ReturnType2 ;
+
+TYPE
+ bar = POINTER TO RECORD
+ field: CARDINAL ;
+ END ;
+
+
+PROCEDURE foo (VAR value: bar) : bar ;
+BEGIN
+ RETURN value
+END foo ;
+
+VAR
+ b: bar ;
+BEGIN
+ b := NIL ;
+ b := foo (b)
+END ReturnType2.
diff --git a/gcc/testsuite/gm2/pim/pass/testxindr.mod b/gcc/testsuite/gm2/pim/pass/testxindr.mod
new file mode 100644
index 0000000..271f430
--- /dev/null
+++ b/gcc/testsuite/gm2/pim/pass/testxindr.mod
@@ -0,0 +1,17 @@
+MODULE testxindr ; (*!m2iso+gm2*)
+
+CONST
+ NulName = 0 ;
+
+TYPE
+ Name = CARDINAL ;
+
+ ptr = POINTER TO RECORD
+ n: Name ;
+ END ;
+
+VAR
+ p: ptr ;
+BEGIN
+ p^.n := NulName
+END testxindr.
diff --git a/gcc/testsuite/gm2/pim/pass/testxindr2.mod b/gcc/testsuite/gm2/pim/pass/testxindr2.mod
new file mode 100644
index 0000000..b0776dc
--- /dev/null
+++ b/gcc/testsuite/gm2/pim/pass/testxindr2.mod
@@ -0,0 +1,17 @@
+MODULE testxindr2 ; (*!m2iso+gm2*)
+
+CONST
+ NulName = 0 ;
+TYPE
+ Name = CARDINAL ;
+
+PROCEDURE set (VAR n: Name) ;
+BEGIN
+ n := NulName
+END set ;
+
+VAR
+ n: Name ;
+BEGIN
+ set (n)
+END testxindr2.
diff --git a/gcc/testsuite/gm2/pim/pass/testxindr3.mod b/gcc/testsuite/gm2/pim/pass/testxindr3.mod
new file mode 100644
index 0000000..5625c3e
--- /dev/null
+++ b/gcc/testsuite/gm2/pim/pass/testxindr3.mod
@@ -0,0 +1,15 @@
+MODULE testxindr3 ; (*!m2iso+gm2*)
+
+CONST
+ NulName = 0 ;
+
+PROCEDURE set (VAR n: CARDINAL) ;
+BEGIN
+ n := NulName
+END set ;
+
+VAR
+ n: CARDINAL ;
+BEGIN
+ set (n)
+END testxindr3.
diff --git a/gcc/testsuite/gnat.dg/controlled9.adb b/gcc/testsuite/gnat.dg/controlled9.adb
new file mode 100644
index 0000000..fb7acce
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/controlled9.adb
@@ -0,0 +1,10 @@
+-- { dg-do run }
+-- { dg-options "-O1 -fstack-check" }
+-- from PR middle-end/118939
+
+with Controlled9_Pkg;
+procedure Controlled9 is
+ S : constant Controlled9_Pkg.T_Access := new Controlled9_Pkg.T;
+begin
+ null;
+end Controlled9;
diff --git a/gcc/testsuite/gnat.dg/controlled9_pkg.ads b/gcc/testsuite/gnat.dg/controlled9_pkg.ads
new file mode 100644
index 0000000..d0e7c28
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/controlled9_pkg.ads
@@ -0,0 +1,5 @@
+with Ada.Finalization;
+package Controlled9_Pkg is
+ type T is new Ada.Finalization.Controlled with null record;
+ type T_Access is access all T;
+end Controlled9_Pkg;
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 75d723c..dfffe3a 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -1098,6 +1098,16 @@ proc check_effective_target_tls {} {
}]
}
+# Return 1 if we can link using TLS, 0 otherwise.
+
+proc check_effective_target_tls_link {} {
+ return [check_no_compiler_messages tls_link executable {
+ __thread int i;
+ int main (void) { return i; }
+ void g (int j) { i = j; }
+ }]
+}
+
# Return 1 if *native* thread local storage (TLS) is supported, 0 otherwise.
proc check_effective_target_tls_native {} {
diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc
index 3289b4f..1a72e31 100644
--- a/gcc/tree-inline.cc
+++ b/gcc/tree-inline.cc
@@ -2866,7 +2866,6 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, profile_count count)
cfun->nonlocal_goto_save_area = src_cfun->nonlocal_goto_save_area;
cfun->function_end_locus = src_cfun->function_end_locus;
cfun->curr_properties = src_cfun->curr_properties;
- cfun->last_verified = src_cfun->last_verified;
cfun->va_list_gpr_size = src_cfun->va_list_gpr_size;
cfun->va_list_fpr_size = src_cfun->va_list_fpr_size;
cfun->has_nonlocal_label = src_cfun->has_nonlocal_label;
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 7cb5a12..4139f6d 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -236,9 +236,9 @@ protected:
(PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_lomp)
/* To-do flags. */
+/* Note (1ul << 31) is reserved for TODO_verify_il. */
#define TODO_do_not_ggc_collect (1 << 1)
#define TODO_cleanup_cfg (1 << 5)
-#define TODO_verify_il (1 << 6)
#define TODO_dump_symtab (1 << 7)
#define TODO_remove_functions (1 << 8)
@@ -308,6 +308,8 @@ protected:
and stop pass manager. */
#define TODO_discard_function (1 << 23)
+/* (1ul << 31) is reserved for TODO_verify_il. */
+
/* Internally used in execute_function_todo(). */
#define TODO_update_ssa_any \
(TODO_update_ssa \
@@ -315,8 +317,6 @@ protected:
| TODO_update_ssa_full_phi \
| TODO_update_ssa_only_virtuals)
-#define TODO_verify_all TODO_verify_il
-
/* To-do flags for pending_TODOs. */
/* Tell the next scalar cleanup pass that there is
diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
index 81ea7d4..75901ec 100644
--- a/gcc/tree-ssa-forwprop.cc
+++ b/gcc/tree-ssa-forwprop.cc
@@ -205,7 +205,6 @@ struct _vec_perm_simplify_seq
typedef struct _vec_perm_simplify_seq *vec_perm_simplify_seq;
static bool forward_propagate_addr_expr (tree, tree, bool);
-static void optimize_vector_load (gimple_stmt_iterator *);
/* Set to true if we delete dead edges during the optimization. */
static bool cfg_changed;
@@ -3387,6 +3386,7 @@ optimize_vector_load (gimple_stmt_iterator *gsi)
gimple *stmt = gsi_stmt (*gsi);
tree lhs = gimple_assign_lhs (stmt);
tree rhs = gimple_assign_rhs1 (stmt);
+ tree vuse = gimple_vuse (stmt);
/* Gather BIT_FIELD_REFs to rewrite, looking through
VEC_UNPACK_{LO,HI}_EXPR. */
@@ -3495,6 +3495,7 @@ optimize_vector_load (gimple_stmt_iterator *gsi)
gimple *new_stmt = gimple_build_assign (tem, new_rhs);
location_t loc = gimple_location (use_stmt);
gimple_set_location (new_stmt, loc);
+ gimple_set_vuse (new_stmt, vuse);
gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
/* Perform scalar promotion. */
new_stmt = gimple_build_assign (gimple_assign_lhs (use_stmt),
@@ -3514,6 +3515,7 @@ optimize_vector_load (gimple_stmt_iterator *gsi)
new_rhs);
location_t loc = gimple_location (use_stmt);
gimple_set_location (new_stmt, loc);
+ gimple_set_vuse (new_stmt, vuse);
gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
}
gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt);
@@ -4167,7 +4169,7 @@ const pass_data pass_data_forwprop =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_update_ssa, /* todo_flags_finish */
+ 0, /* todo_flags_finish */
};
class pass_forwprop : public gimple_opt_pass
@@ -4404,6 +4406,7 @@ pass_forwprop::execute (function *fun)
component-wise loads. */
use_operand_p use_p;
imm_use_iterator iter;
+ tree vuse = gimple_vuse (stmt);
bool rewrite = true;
FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
{
@@ -4443,6 +4446,7 @@ pass_forwprop::execute (function *fun)
location_t loc = gimple_location (use_stmt);
gimple_set_location (new_stmt, loc);
+ gimple_set_vuse (new_stmt, vuse);
gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt);
unlink_stmt_vdef (use_stmt);
gsi_remove (&gsi2, true);
diff --git a/gcc/tree-switch-conversion.cc b/gcc/tree-switch-conversion.cc
index bd4de96..d088287 100644
--- a/gcc/tree-switch-conversion.cc
+++ b/gcc/tree-switch-conversion.cc
@@ -1030,6 +1030,9 @@ switch_conversion::build_one_array (int num, tree arr_index_type,
TREE_CONSTANT (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_IGNORED_P (decl) = 1;
+ /* The decl is mergable since we don't take the address ever and
+ just reading from it. */
+ DECL_MERGEABLE (decl) = 1;
if (offloading_function_p (cfun->decl))
DECL_ATTRIBUTES (decl)
= tree_cons (get_identifier ("omp declare target"), NULL_TREE,
diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
index f2deb75..1792ee4 100644
--- a/gcc/tree-vect-data-refs.cc
+++ b/gcc/tree-vect-data-refs.cc
@@ -3685,7 +3685,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
/* For datarefs with big gap, it's better to split them into different
groups.
.i.e a[0], a[1], a[2], .. a[7], a[100], a[101],..., a[107] */
- if ((unsigned HOST_WIDE_INT)(init_b - init_prev) * tree_to_uhwi (szb)
+ if ((unsigned HOST_WIDE_INT)(init_b - init_prev)
> MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT)
break;
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 2d1a688..8c5761d 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -6016,7 +6016,8 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo,
/* Create an induction variable. */
gimple_stmt_iterator incr_gsi;
bool insert_after;
- vect_iv_increment_position (loop_exit, &incr_gsi, &insert_after);
+ vect_iv_increment_position (LOOP_VINFO_IV_EXIT (loop_vinfo),
+ &incr_gsi, &insert_after);
create_iv (series_vect, PLUS_EXPR, vec_step, NULL_TREE, loop, &incr_gsi,
insert_after, &indx_before_incr, &indx_after_incr);
diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
index 5aeb1e0..cad1a24 100644
--- a/gcc/tree-vrp.cc
+++ b/gcc/tree-vrp.cc
@@ -1297,7 +1297,7 @@ const pass_data pass_data_early_vrp =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all ),
+ ( TODO_cleanup_cfg | TODO_update_ssa ),
};
const pass_data pass_data_fast_vrp =
@@ -1310,7 +1310,7 @@ const pass_data pass_data_fast_vrp =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all ),
+ ( TODO_cleanup_cfg | TODO_update_ssa ),
};
diff --git a/gcc/var-tracking.cc b/gcc/var-tracking.cc
index d70ed02..8732c3b 100644
--- a/gcc/var-tracking.cc
+++ b/gcc/var-tracking.cc
@@ -6273,7 +6273,7 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn)
if (SYMBOL_REF_DECL (symbol))
fndecl = SYMBOL_REF_DECL (symbol);
}
- if (fndecl == NULL_TREE)
+ if (fndecl == NULL_TREE && MEM_P (XEXP (call, 0)))
fndecl = MEM_EXPR (XEXP (call, 0));
if (fndecl
&& TREE_CODE (TREE_TYPE (fndecl)) != FUNCTION_TYPE
diff --git a/include/ChangeLog b/include/ChangeLog
index 310a5d5..886dab6 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,15 @@
+2025-06-02 Tobias Burnus <tburnus@baylibre.com>
+
+ PR libgomp/120444
+ * cuda/cuda.h (cuMemsetD8, cuMemsetD8Async): Declare.
+
+2025-05-30 Julian Brown <julian@codesourcery.com>
+ Tobias Burnus <tburnus@baylibre.com>
+
+ * gomp-constants.h (gomp_map_kind): Add GOMP_MAP_UNSET,
+ GOMP_MAP_PUSH_MAPPER_NAME, GOMP_MAP_POP_MAPPER_NAME artificial mapping
+ clause types.
+
2025-05-14 Andreas Schwab <schwab@suse.de>
* libiberty.h (mkstemps): Remove duplicate.
diff --git a/include/cuda/cuda.h b/include/cuda/cuda.h
index 5e4b7f1..6be1ac0 100644
--- a/include/cuda/cuda.h
+++ b/include/cuda/cuda.h
@@ -279,6 +279,9 @@ CUresult cuMemcpy3D (const CUDA_MEMCPY3D *);
CUresult cuMemcpy3DAsync (const CUDA_MEMCPY3D *, CUstream);
CUresult cuMemcpy3DPeer (const CUDA_MEMCPY3D_PEER *);
CUresult cuMemcpy3DPeerAsync (const CUDA_MEMCPY3D_PEER *, CUstream);
+#define cuMemsetD8 cuMemsetD8_v2
+CUresult cuMemsetD8 (CUdeviceptr, unsigned char, size_t);
+CUresult cuMemsetD8Async (CUdeviceptr, unsigned char, size_t, CUstream);
#define cuMemFree cuMemFree_v2
CUresult cuMemFree (CUdeviceptr);
CUresult cuMemFreeHost (void *);
diff --git a/libgcobol/ChangeLog b/libgcobol/ChangeLog
index 83a826e..4293598 100644
--- a/libgcobol/ChangeLog
+++ b/libgcobol/ChangeLog
@@ -1,3 +1,8 @@
+2025-06-01 Robert Dubner <rdubner@symas.com>
+
+ PR cobol/119524
+ * libgcobol.cc (__gg__fprintf_stderr): New function.
+
2025-05-20 Robert Dubner <rdubner@symas.com>
James K. Lowden <jklowden@cobolworx.com>
diff --git a/libgcobol/libgcobol.cc b/libgcobol/libgcobol.cc
index 66405ba..3ab7463 100644
--- a/libgcobol/libgcobol.cc
+++ b/libgcobol/libgcobol.cc
@@ -49,6 +49,7 @@
#include <signal.h>
#include <syslog.h>
#include <unistd.h>
+#include <stdarg.h>
#if __has_include(<errno.h>)
# include <errno.h> // for program_invocation_short_name
#endif
@@ -13151,3 +13152,16 @@ __gg__set_env_value(cblc_field_t *value,
// And now, anticlimactically, set the variable:
setenv(trimmed_env, trimmed_val, 1);
}
+
+extern "C"
+void
+__gg__fprintf_stderr(const char *format_string, ...)
+ {
+ /* This routine allows the compiler to send stuff to stderr in a way
+ that is straightforward to use.. */
+ va_list ap;
+ va_start(ap, format_string);
+ vfprintf(stderr, format_string, ap);
+ va_end(ap);
+ }
+
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 638c03e..1f658d5 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,11 @@
+2025-06-01 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR libfortran/119856
+ * io/format.c (parse_format_list): Set the fmt->error
+ message for missing comma.
+ (parse_format): Do not cache the parsed format string
+ if a previous error ocurred.
+
2025-05-13 Jakub Jelinek <jakub@redhat.com>
PR libfortran/120196
diff --git a/libgfortran/io/format.c b/libgfortran/io/format.c
index eef1d34..87e21a9 100644
--- a/libgfortran/io/format.c
+++ b/libgfortran/io/format.c
@@ -1235,9 +1235,9 @@ parse_format_list (st_parameter_dt *dtp, bool *seen_dd)
default:
/* Assume a missing comma with -std=legacy, GNU extension. */
- if (compile_options.warn_std == 0)
- goto format_item_1;
- format_error (dtp, tail, comma_missing);
+ if (compile_options.warn_std != 0)
+ fmt->error = comma_missing;
+ goto format_item_1;
}
/* Optional comma is a weird between state where we've just finished
@@ -1252,7 +1252,7 @@ parse_format_list (st_parameter_dt *dtp, bool *seen_dd)
case FMT_RPAREN:
goto finished;
- default: /* Assume that we have another format item */
+ default: /* Assume that we have another format item */
fmt->saved_token = t;
break;
}
@@ -1419,7 +1419,7 @@ parse_format (st_parameter_dt *dtp)
else
fmt->error = "Missing initial left parenthesis in format";
- if (format_cache_ok)
+ if (format_cache_ok && !fmt->error)
save_parsed_format (dtp);
else
dtp->u.p.format_not_saved = 1;
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index fd9d59e..974c44b 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,163 @@
+2025-06-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR libgomp/120444
+ * testsuite/libgomp.c-c++-common/omp_target_memset-3.c (test_it):
+ Change ptr argument type from void * to int8_t *.
+ (main): Change ptr variable type from void * to int8_t * and cast
+ omp_target_alloc result to the latter type.
+
+2025-06-02 Tobias Burnus <tburnus@baylibre.com>
+
+ PR libgomp/120444
+ * libgomp-plugin.h (GOMP_OFFLOAD_memset): Declare.
+ * libgomp.h (struct gomp_device_descr): Add memset_func.
+ * libgomp.map (GOMP_6.0.1): Add omp_target_memset{,_async}.
+ * libgomp.texi (Device Memory Routines): Document them.
+ * omp.h.in (omp_target_memset, omp_target_memset_async): Declare.
+ * omp_lib.f90.in (omp_target_memset, omp_target_memset_async):
+ Add interfaces.
+ * omp_lib.h.in (omp_target_memset, omp_target_memset_async): Likewise.
+ * plugin/cuda-lib.def: Add cuMemsetD8.
+ * plugin/plugin-gcn.c (struct hsa_runtime_fn_info): Add
+ hsa_amd_memory_fill_fn.
+ (init_hsa_runtime_functions): DLSYM_OPT_FN load it.
+ (GOMP_OFFLOAD_memset): New.
+ * plugin/plugin-nvptx.c (GOMP_OFFLOAD_memset): New.
+ * target.c (omp_target_memset_int, omp_target_memset,
+ omp_target_memset_async_helper, omp_target_memset_async): New.
+ (gomp_load_plugin_for_device): Add DLSYM (memset).
+ * testsuite/libgomp.c-c++-common/omp_target_memset.c: New test.
+ * testsuite/libgomp.c-c++-common/omp_target_memset-2.c: New test.
+ * testsuite/libgomp.c-c++-common/omp_target_memset-3.c: New test.
+ * testsuite/libgomp.fortran/omp_target_memset.f90: New test.
+ * testsuite/libgomp.fortran/omp_target_memset-2.f90: New test.
+
+2025-05-30 Thomas Schwinge <tschwinge@baylibre.com>
+
+ * testsuite/libgomp.c++/target-std__valarray-1.C: New.
+ * testsuite/libgomp.c++/target-std__valarray-1.output: Likewise.
+
+2025-05-30 Thomas Schwinge <tschwinge@baylibre.com>
+
+ * testsuite/libgomp.c++/target-std__array-concurrent-usm.C: New.
+ * testsuite/libgomp.c++/target-std__array-concurrent.C: Adjust.
+ * testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C: New.
+ * testsuite/libgomp.c++/target-std__bitset-concurrent.C: Adjust.
+ * testsuite/libgomp.c++/target-std__deque-concurrent-usm.C: New.
+ * testsuite/libgomp.c++/target-std__deque-concurrent.C: Adjust.
+ * testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C: New.
+ * testsuite/libgomp.c++/target-std__forward_list-concurrent.C: Adjust.
+ * testsuite/libgomp.c++/target-std__list-concurrent-usm.C: New.
+ * testsuite/libgomp.c++/target-std__list-concurrent.C: Adjust.
+ * testsuite/libgomp.c++/target-std__map-concurrent-usm.C: New.
+ * testsuite/libgomp.c++/target-std__map-concurrent.C: Adjust.
+ * testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C: New.
+ * testsuite/libgomp.c++/target-std__multimap-concurrent.C: Adjust.
+ * testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C: New.
+ * testsuite/libgomp.c++/target-std__multiset-concurrent.C: Adjust.
+ * testsuite/libgomp.c++/target-std__set-concurrent-usm.C: New.
+ * testsuite/libgomp.c++/target-std__set-concurrent.C: Adjust.
+ * testsuite/libgomp.c++/target-std__span-concurrent-usm.C: New.
+ * testsuite/libgomp.c++/target-std__span-concurrent.C: Adjust.
+ * testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C: New.
+ * testsuite/libgomp.c++/target-std__valarray-concurrent.C: Adjust.
+ * testsuite/libgomp.c++/target-std__vector-concurrent-usm.C: New.
+ * testsuite/libgomp.c++/target-std__vector-concurrent.C: Adjust.
+
+2025-05-30 Kwok Cheung Yeung <kcyeung@baylibre.com>
+ Thomas Schwinge <tschwinge@baylibre.com>
+
+ * testsuite/libgomp.c++/target-std__array-concurrent.C: New.
+ * testsuite/libgomp.c++/target-std__bitset-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__deque-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__flat_map-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__flat_multimap-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__flat_multiset-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__flat_set-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__forward_list-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__list-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__map-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__multimap-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__multiset-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__set-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__span-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__unordered_map-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__unordered_multimap-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__unordered_multiset-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__unordered_set-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__valarray-concurrent.C: Likewise.
+ * testsuite/libgomp.c++/target-std__vector-concurrent.C: Likewise.
+
+2025-05-30 Kwok Cheung Yeung <kcyeung@baylibre.com>
+
+ * testsuite/libgomp.c++/target-std__cmath.C: New.
+ * testsuite/libgomp.c++/target-std__complex.C: Likewise.
+ * testsuite/libgomp.c++/target-std__numbers.C: Likewise.
+
+2025-05-30 Waffl3x <waffl3x@baylibre.com>
+ Thomas Schwinge <tschwinge@baylibre.com>
+
+ * testsuite/libgomp.c++/target-flex-10.C: New test.
+ * testsuite/libgomp.c++/target-flex-100.C: New test.
+ * testsuite/libgomp.c++/target-flex-101.C: New test.
+ * testsuite/libgomp.c++/target-flex-11.C: New test.
+ * testsuite/libgomp.c++/target-flex-12.C: New test.
+ * testsuite/libgomp.c++/target-flex-2000.C: New test.
+ * testsuite/libgomp.c++/target-flex-2001.C: New test.
+ * testsuite/libgomp.c++/target-flex-2002.C: New test.
+ * testsuite/libgomp.c++/target-flex-2003.C: New test.
+ * testsuite/libgomp.c++/target-flex-30.C: New test.
+ * testsuite/libgomp.c++/target-flex-300.C: New test.
+ * testsuite/libgomp.c++/target-flex-31.C: New test.
+ * testsuite/libgomp.c++/target-flex-32.C: New test.
+ * testsuite/libgomp.c++/target-flex-33.C: New test.
+ * testsuite/libgomp.c++/target-flex-41.C: New test.
+ * testsuite/libgomp.c++/target-flex-60.C: New test.
+ * testsuite/libgomp.c++/target-flex-61.C: New test.
+ * testsuite/libgomp.c++/target-flex-62.C: New test.
+ * testsuite/libgomp.c++/target-flex-70.C: New test.
+ * testsuite/libgomp.c++/target-flex-80.C: New test.
+ * testsuite/libgomp.c++/target-flex-81.C: New test.
+ * testsuite/libgomp.c++/target-flex-90.C: New test.
+ * testsuite/libgomp.c++/target-flex-common.h: New test.
+
+2025-05-30 Thomas Schwinge <tschwinge@baylibre.com>
+ Richard Biener <rguenther@suse.de>
+
+ PR middle-end/119835
+ * testsuite/libgomp.oacc-c-c++-common/abi-struct-1.c:
+ '#pragma GCC optimize "-fno-inline"'.
+ * testsuite/libgomp.c-c++-common/target-abi-struct-1.c: New.
+ * testsuite/libgomp.c-c++-common/target-abi-struct-1-O0.c: Adjust.
+
+2025-05-30 Julian Brown <julian@codesourcery.com>
+
+ * testsuite/libgomp.c-c++-common/declare-mapper-9.c: Enable for C.
+ * testsuite/libgomp.c-c++-common/declare-mapper-10.c: Likewise.
+ * testsuite/libgomp.c-c++-common/declare-mapper-11.c: Likewise.
+ * testsuite/libgomp.c-c++-common/declare-mapper-12.c: Likewise.
+ * testsuite/libgomp.c-c++-common/declare-mapper-13.c: Likewise.
+ * testsuite/libgomp.c-c++-common/declare-mapper-14.c: Likewise.
+
+2025-05-30 Julian Brown <julian@codesourcery.com>
+ Tobias Burnus <tburnus@baylibre.com>
+
+ * testsuite/libgomp.c++/declare-mapper-1.C: New test.
+ * testsuite/libgomp.c++/declare-mapper-2.C: New test.
+ * testsuite/libgomp.c++/declare-mapper-3.C: New test.
+ * testsuite/libgomp.c++/declare-mapper-4.C: New test.
+ * testsuite/libgomp.c++/declare-mapper-5.C: New test.
+ * testsuite/libgomp.c++/declare-mapper-6.C: New test.
+ * testsuite/libgomp.c++/declare-mapper-7.C: New test.
+ * testsuite/libgomp.c++/declare-mapper-8.C: New test.
+ * testsuite/libgomp.c-c++-common/declare-mapper-9.c: New test (only
+ enabled for C++ for now).
+ * testsuite/libgomp.c-c++-common/declare-mapper-10.c: Likewise.
+ * testsuite/libgomp.c-c++-common/declare-mapper-11.c: Likewise.
+ * testsuite/libgomp.c-c++-common/declare-mapper-12.c: Likewise.
+ * testsuite/libgomp.c-c++-common/declare-mapper-13.c: Likewise.
+ * testsuite/libgomp.c-c++-common/declare-mapper-14.c: Likewise.
+
2025-05-29 Tobias Burnus <tburnus@baylibre.com>
PR libgomp/93226
diff --git a/libgomp/libgomp-plugin.h b/libgomp/libgomp-plugin.h
index 50c89fe..191106b 100644
--- a/libgomp/libgomp-plugin.h
+++ b/libgomp/libgomp-plugin.h
@@ -177,6 +177,7 @@ extern int GOMP_OFFLOAD_memcpy3d (int, int, size_t, size_t, size_t, void *,
size_t, size_t, size_t, size_t, size_t,
const void *, size_t, size_t, size_t, size_t,
size_t);
+extern bool GOMP_OFFLOAD_memset (int, void *, int, size_t);
extern bool GOMP_OFFLOAD_can_run (void *);
extern void GOMP_OFFLOAD_run (int, void *, void *, void **);
extern void GOMP_OFFLOAD_async_run (int, void *, void *, void **, void *);
diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h
index ed4e23a..a433983 100644
--- a/libgomp/libgomp.h
+++ b/libgomp/libgomp.h
@@ -1421,9 +1421,10 @@ struct gomp_device_descr
__typeof (GOMP_OFFLOAD_free) *free_func;
__typeof (GOMP_OFFLOAD_dev2host) *dev2host_func;
__typeof (GOMP_OFFLOAD_host2dev) *host2dev_func;
+ __typeof (GOMP_OFFLOAD_dev2dev) *dev2dev_func;
__typeof (GOMP_OFFLOAD_memcpy2d) *memcpy2d_func;
__typeof (GOMP_OFFLOAD_memcpy3d) *memcpy3d_func;
- __typeof (GOMP_OFFLOAD_dev2dev) *dev2dev_func;
+ __typeof (GOMP_OFFLOAD_memset) *memset_func;
__typeof (GOMP_OFFLOAD_can_run) *can_run_func;
__typeof (GOMP_OFFLOAD_run) *run_func;
__typeof (GOMP_OFFLOAD_async_run) *async_run_func;
diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map
index ad9787c..f6aee7c 100644
--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map
@@ -453,6 +453,12 @@ GOMP_6.0 {
omp_get_uid_from_device_8_;
} GOMP_5.1.3;
+GOMP_6.0.1 {
+ global:
+ omp_target_memset;
+ omp_target_memset_async;
+} GOMP_6.0;
+
OACC_2.0 {
global:
acc_get_num_devices;
diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index e6ebe22..7116fcd 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -603,7 +603,7 @@ to address of matching mapped list item per 5.1, Sect. 2.21.7.2 @tab N @tab
@code{omp_get_device_teams_thread_limit}, and
@code{omp_set_device_teams_thread_limit} routines @tab N @tab
@item @code{omp_target_memset} and @code{omp_target_memset_async} routines
- @tab N @tab
+ @tab Y @tab
@item Fortran version of the interop runtime routines @tab Y @tab
@item Routines for obtaining memory spaces/allocators for shared/device memory
@tab N @tab
@@ -1984,8 +1984,8 @@ pointers on devices. They have C linkage and do not throw exceptions.
* omp_target_memcpy_async:: Copy data between devices asynchronously
* omp_target_memcpy_rect:: Copy a subvolume of data between devices
* omp_target_memcpy_rect_async:: Copy a subvolume of data between devices asynchronously
-@c * omp_target_memset:: <fixme>/TR12
-@c * omp_target_memset_async:: <fixme>/TR12
+* omp_target_memset:: Set bytes in device memory
+* omp_target_memset_async:: Set bytes in device memory asynchronously
* omp_target_associate_ptr:: Associate a device pointer with a host pointer
* omp_target_disassociate_ptr:: Remove device--host pointer association
* omp_get_mapped_ptr:: Return device pointer to a host pointer
@@ -2398,6 +2398,98 @@ the initial device.
@end table
+@node omp_target_memset
+@subsection @code{omp_target_memset} -- Set bytes in device memory
+@table @asis
+@item @emph{Description}:
+This routine fills memory on the device identified by device number
+@var{device_num}. Starting from the device address @var{ptr}, the first
+@var{count} bytes are set to the value @var{val}, converted to
+@code{unsigned char}. If @var{count} is zero, the routine has no effect;
+if @var{ptr} is @code{NULL}, the behavior is unspecified. The function
+returns @var{ptr}.
+
+The @var{device_num} must be a conforming device number and @var{ptr} must be
+a valid device pointer for that device. Running this routine in a
+@code{target} region except on the initial device is not supported.
+
+@item @emph{C/C++}
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{void *omp_target_memcpy(void *ptr,}
+@item @tab @code{ int val,}
+@item @tab @code{ size_t count,}
+@item @tab @code{ int device_num)}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{type(c_ptr) function omp_target_memset( &}
+@item @tab @code{ ptr, val, count, device_num) bind(C)}
+@item @tab @code{use, intrinsic :: iso_c_binding, only: c_ptr, c_size_t, c_int}
+@item @tab @code{type(c_ptr), value :: ptr}
+@item @tab @code{integer(c_size_t), value :: count}
+@item @tab @code{integer(c_int), value :: val, device_num}
+@end multitable
+
+@item @emph{See also}:
+@ref{omp_target_memset_async}
+
+@item @emph{Reference}:
+@uref{https://www.openmp.org, OpenMP specification v6.0}, Section 25.8.1
+@end table
+
+
+
+@node omp_target_memset_async
+@subsection @code{omp_target_memset} -- Set bytes in device memory asynchronously
+@table @asis
+@item @emph{Description}:
+This routine fills memory on the device identified by device number
+@var{device_num}. Starting from the device address @var{ptr}, the first
+@var{count} bytes are set to the value @var{val}, converted to
+@code{unsigned char}. If @var{count} is zero, the routine has no effect;
+if @var{ptr} is @code{NULL}, the behavior is unspecified. Task dependence
+is expressed by passing an array of depend objects to @var{depobj_list}, where
+the number of array elements is passed as @var{depobj_count}; if the count is
+zero, the @var{depobj_list} argument is ignored. In C++ and Fortran, the
+@var{depobj_list} argument can also be omitted in that case. The function
+returns @var{ptr}.
+
+The @var{device_num} must be a conforming device number and @var{ptr} must be
+a valid device pointer for that device. Running this routine in a
+@code{target} region except on the initial device is not supported.
+
+@item @emph{C/C++}
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{void *omp_target_memcpy_async(void *ptr,}
+@item @tab @code{ int val,}
+@item @tab @code{ size_t count,}
+@item @tab @code{ int device_num,}
+@item @tab @code{ int depobj_count,}
+@item @tab @code{ omp_depend_t *depobj_list)}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{type(c_ptr) function omp_target_memset_async( &}
+@item @tab @code{ ptr, val, count, device_num, &}
+@item @tab @code{ depobj_count, depobj_list) bind(C)}
+@item @tab @code{use, intrinsic :: iso_c_binding, only: c_ptr, c_size_t, c_int}
+@item @tab @code{type(c_ptr), value :: ptr}
+@item @tab @code{integer(c_size_t), value :: count}
+@item @tab @code{integer(c_int), value :: val, device_num, depobj_count}
+@item @tab @code{integer(omp_depend_kind), optional :: depobj_list(*)}
+@end multitable
+
+
+@item @emph{See also}:
+@ref{omp_target_memset}
+
+@item @emph{Reference}:
+@uref{https://www.openmp.org, OpenMP specification v6.0}, Section 25.8.2
+@end table
+
+
@node omp_target_associate_ptr
@subsection @code{omp_target_associate_ptr} -- Associate a device pointer with a host pointer
@@ -3038,6 +3130,11 @@ and Fortran or used with @code{NULL} as argument in C and C++. If successful,
In GCC, the effect of running this routine in a @code{target} region that is not
the initial device is unspecified.
+GCC implements the OpenMP 6.0 version of this function for C and C++, which is not
+compatible with its type signature in previous versions of the OpenMP specification.
+In older versions, the type @code{int*} was used for the @var{ret_code} argument
+in place of a pointer to the enumerated type @code{omp_interop_rc_t}.
+
@c Implementation remark: In GCC, the Fortran interface differs from the one shown
@c below: the function has C binding and @var{interop} and @var{property_id} are
@c passed by value, which permits use of the same ABI as the C function. This does
@@ -3084,6 +3181,11 @@ and Fortran or used with @code{NULL} as argument in C and C++. If successful,
In GCC, the effect of running this routine in a @code{target} region that is not
the initial device is unspecified.
+GCC implements the OpenMP 6.0 version of this function for C and C++, which is not
+compatible with its type signature in previous versions of the OpenMP specification.
+In older versions, the type @code{int*} was used for the @var{ret_code} argument
+in place of a pointer to the enumerated type @code{omp_interop_rc_t}.
+
@c Implementation remark: In GCC, the Fortran interface differs from the one shown
@c below: the function has C binding and @var{interop} and @var{property_id} are
@c passed by value, which permits use of the same ABI as the C function. This does
@@ -3130,6 +3232,11 @@ and Fortran or used with @code{NULL} as argument in C and C++. If successful,
In GCC, the effect of running this routine in a @code{target} region that is not
the initial device is unspecified.
+GCC implements the OpenMP 6.0 version of this function for C and C++, which is not
+compatible with its type signature in previous versions of the OpenMP specification.
+In older versions, the type @code{int*} was used for the @var{ret_code} argument
+in place of a pointer to the enumerated type @code{omp_interop_rc_t}.
+
@c Implementation remark: In GCC, the Fortran interface differs from the one shown
@c below: @var{interop} and @var{property_id} are passed by value. This does not
@c affect the usage of the function when GCC's @code{omp_lib} module or
@@ -3256,6 +3363,11 @@ the @var{ret_code} in human-readable form.
The behavior is unspecified if value of @var{ret_code} was not set by an
interoperability routine invoked for @var{interop}.
+GCC implements the OpenMP 6.0 version of this function for C and C++, which is not
+compatible with its type signature in previous versions of the OpenMP specification.
+In older versions, the type @code{int} was used for the @var{ret_code} argument
+in place of the enumerated type @code{omp_interop_rc_t}.
+
@item @emph{C/C++}:
@multitable @columnfractions .20 .80
@item @emph{Prototype}: @tab @code{const char *omp_get_interop_rc_desc(const omp_interop_t interop,
diff --git a/libgomp/omp.h.in b/libgomp/omp.h.in
index 8d17db1..4f2bc46 100644
--- a/libgomp/omp.h.in
+++ b/libgomp/omp.h.in
@@ -347,6 +347,10 @@ extern int omp_target_memcpy_rect_async (void *, const void *, __SIZE_TYPE__,
const __SIZE_TYPE__ *, int, int, int,
omp_depend_t * __GOMP_DEFAULT_NULL)
__GOMP_NOTHROW;
+extern void *omp_target_memset (void *, int, __SIZE_TYPE__, int) __GOMP_NOTHROW;
+extern void *omp_target_memset_async (void *, int, __SIZE_TYPE__, int,
+ int, omp_depend_t * __GOMP_DEFAULT_NULL)
+ __GOMP_NOTHROW;
extern int omp_target_associate_ptr (const void *, const void *, __SIZE_TYPE__,
__SIZE_TYPE__, int) __GOMP_NOTHROW;
extern int omp_target_disassociate_ptr (const void *, int) __GOMP_NOTHROW;
diff --git a/libgomp/omp_lib.f90.in b/libgomp/omp_lib.f90.in
index cb6b95f..ce866c0 100644
--- a/libgomp/omp_lib.f90.in
+++ b/libgomp/omp_lib.f90.in
@@ -904,6 +904,29 @@
end interface
interface
+ function omp_target_memset (ptr, val, count, device_num) bind(c)
+ use, intrinsic :: iso_c_binding, only : c_ptr, c_int, c_size_t
+ type(c_ptr) :: omp_target_memset
+ type(c_ptr), value :: ptr
+ integer(c_size_t), value :: count
+ integer(c_int), value :: val, device_num
+ end function omp_target_memset
+ end interface
+
+ interface
+ function omp_target_memset_async (ptr, val, count, device_num, &
+ depobj_count, depobj_list) bind(c)
+ use, intrinsic :: iso_c_binding, only : c_ptr, c_int, c_size_t
+ import :: omp_depend_kind
+ type(c_ptr) :: omp_target_memset_async
+ type(c_ptr), value :: ptr
+ integer(c_size_t), value :: count
+ integer(c_int), value :: val, device_num, depobj_count
+ integer(omp_depend_kind), optional :: depobj_list(*)
+ end function omp_target_memset_async
+ end interface
+
+ interface
function omp_target_associate_ptr (host_ptr, device_ptr, size, &
device_offset, device_num) bind(c)
use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t, c_int
diff --git a/libgomp/omp_lib.h.in b/libgomp/omp_lib.h.in
index f7af5ff..9047095 100644
--- a/libgomp/omp_lib.h.in
+++ b/libgomp/omp_lib.h.in
@@ -505,6 +505,31 @@
end interface
interface
+ function omp_target_memset (ptr, val, count, device_num) bind(c)
+ use, intrinsic :: iso_c_binding, only : c_ptr, c_int, c_size_t
+ type(c_ptr) omp_target_memset
+ type(c_ptr), value :: ptr
+ integer(c_size_t), value :: count
+ integer(c_int), value :: val, device_num
+ end function omp_target_memset
+ end interface
+
+ interface
+ function omp_target_memset_async (ptr, val, count, device_num, &
+ & depobj_count, depobj_list) &
+ & bind(c)
+ use, intrinsic :: iso_c_binding, only : c_ptr, c_int, c_size_t
+ import :: omp_depend_kind
+ type(c_ptr) :: omp_target_memset_async
+ type(c_ptr), value :: ptr
+ integer(c_size_t), value :: count
+ integer(c_int), value :: val, device_num, depobj_count
+ integer(omp_depend_kind), optional :: depobj_list(*)
+ end function omp_target_memset_async
+ end interface
+
+
+ interface
function omp_target_associate_ptr (host_ptr, device_ptr, size, &
& device_offset, device_num) &
& bind(c)
diff --git a/libgomp/plugin/cuda-lib.def b/libgomp/plugin/cuda-lib.def
index eb562ac..7f4ddcc 100644
--- a/libgomp/plugin/cuda-lib.def
+++ b/libgomp/plugin/cuda-lib.def
@@ -42,6 +42,7 @@ CUDA_ONE_CALL (cuMemcpyHtoDAsync)
CUDA_ONE_CALL (cuMemcpy2D)
CUDA_ONE_CALL (cuMemcpy2DUnaligned)
CUDA_ONE_CALL (cuMemcpy3D)
+CUDA_ONE_CALL (cuMemsetD8)
CUDA_ONE_CALL (cuMemFree)
CUDA_ONE_CALL (cuMemFreeHost)
CUDA_ONE_CALL (cuMemGetAddressRange)
diff --git a/libgomp/plugin/plugin-gcn.c b/libgomp/plugin/plugin-gcn.c
index 46203838..498b549 100644
--- a/libgomp/plugin/plugin-gcn.c
+++ b/libgomp/plugin/plugin-gcn.c
@@ -208,6 +208,8 @@ struct hsa_runtime_fn_info
hsa_status_t (*hsa_code_object_deserialize_fn)
(void *serialized_code_object, size_t serialized_code_object_size,
const char *options, hsa_code_object_t *code_object);
+ hsa_status_t (*hsa_amd_memory_fill_fn)(void *ptr, uint32_t value,
+ size_t count);
hsa_status_t (*hsa_amd_memory_lock_fn)
(void *host_ptr, size_t size, hsa_agent_t *agents, int num_agent,
void **agent_ptr);
@@ -1456,6 +1458,7 @@ init_hsa_runtime_functions (void)
DLSYM_FN (hsa_signal_load_acquire)
DLSYM_FN (hsa_queue_destroy)
DLSYM_FN (hsa_code_object_deserialize)
+ DLSYM_OPT_FN (hsa_amd_memory_fill)
DLSYM_OPT_FN (hsa_amd_memory_lock)
DLSYM_OPT_FN (hsa_amd_memory_unlock)
DLSYM_OPT_FN (hsa_amd_memory_async_copy_rect)
@@ -4435,6 +4438,83 @@ init_hip_runtime_functions (void)
return true;
}
+bool
+GOMP_OFFLOAD_memset (int ord, void *ptr, int val, size_t count)
+{
+ hsa_status_t status = HSA_STATUS_SUCCESS;
+
+ /* A memset feature is only provided via hsa_amd_memory_fill; while it
+ is fast, it is an HSA extension and it has two requirements: The memory
+ must be aligned to multiples of 4 bytes - and, by construction, only
+ multiples of 4 bytes can be filled (uint32_t value argument).
+
+ This means: Either not using that function or up to three function calls:
+ - copy 1 to 3 bytes to get alignment (hsa_memory_copy), if unaligned
+ - call hsa_amd_memory_fill
+ - copy remaining 1 to 3 bytes (hsa_memory_copy), if after alignment
+ count is not a multiple of 4 bytes.
+
+ Having more than one function call is only profitable if there is
+ enough data to process; see below for the used heuristic values. */
+
+ uint8_t v8 = (uint8_t) val;
+ size_t before = (4 - (uintptr_t) ptr % 4) % 4; /* 0 to 3 bytes. */
+ size_t tail = (count - before) % 4; /* 0 to 3 bytes. */
+
+ /* Heuristic */
+ enum {
+ /* Prefer alloca to malloc up to ... */
+ alloca_size = 256, /* bytes */
+ /* Call hsa_amd_memory_fill also when two copy calls are required. */
+ always_use_fill = 256*1024, /* bytes */
+ /* Call hsa_amd_memory_fill also when on copy call is required. */
+ use_fill_one_copy = (128+64)*1024 /* bytes */
+ };
+
+ /* Do not call hsa_amd_memory_fill when any of the following conditions
+ is true. Note that it is always preferred if available and
+ before == tail == 0. */
+ if (__builtin_expect (!hsa_fns.hsa_amd_memory_fill_fn, 0)
+ || (before && tail && count < always_use_fill)
+ || ((before || tail) && count < use_fill_one_copy))
+ before = count;
+
+ /* Copy call for alignment - or all data, if condition above is true. */
+ if (before)
+ {
+ void *data;
+ if (before > alloca_size)
+ data = malloc (before * sizeof (uint8_t));
+ else
+ data = alloca (before * sizeof (uint8_t));
+ memset (data, val, before);
+ status = hsa_fns.hsa_memory_copy_fn (ptr, data, before);
+ if (before > alloca_size)
+ free (data);
+ if (data == 0 || status != HSA_STATUS_SUCCESS)
+ goto fail;
+ count -= before;
+ }
+
+ if (count == 0)
+ return true;
+
+ ptr += before;
+
+ uint32_t values = v8 | (v8 << 8) | (v8 << 16) | (v8 << 24);
+ status = hsa_fns.hsa_amd_memory_fill_fn (ptr, values, count / 4);
+ if (tail && status == HSA_STATUS_SUCCESS)
+ {
+ ptr += count - tail;
+ status = hsa_fns.hsa_memory_copy_fn (ptr, &values, tail);
+ }
+ if (status == HSA_STATUS_SUCCESS)
+ return true;
+
+fail:
+ GOMP_PLUGIN_error ("memory set failed");
+ return false;
+}
void
GOMP_OFFLOAD_interop (struct interop_obj_t *obj, int ord,
diff --git a/libgomp/plugin/plugin-nvptx.c b/libgomp/plugin/plugin-nvptx.c
index a52d1ad..0ba445e 100644
--- a/libgomp/plugin/plugin-nvptx.c
+++ b/libgomp/plugin/plugin-nvptx.c
@@ -2298,6 +2298,15 @@ GOMP_OFFLOAD_memcpy3d (int dst_ord, int src_ord, size_t dim2_size,
}
bool
+GOMP_OFFLOAD_memset (int ord, void *ptr, int val, size_t count)
+{
+ if (!nvptx_attach_host_thread_to_device (ord))
+ return false;
+ CUDA_CALL (cuMemsetD8, (CUdeviceptr) ptr, (unsigned char) val, count);
+ return true;
+}
+
+bool
GOMP_OFFLOAD_openacc_async_host2dev (int ord, void *dst, const void *src,
size_t n, struct goacc_asyncqueue *aq)
{
diff --git a/libgomp/target.c b/libgomp/target.c
index fe94978..a2a4a72 100644
--- a/libgomp/target.c
+++ b/libgomp/target.c
@@ -5003,6 +5003,88 @@ omp_target_memcpy_rect_async (void *dst, const void *src, size_t element_size,
return 0;
}
+static void
+omp_target_memset_int (void *ptr, int val, size_t count,
+ struct gomp_device_descr *devicep)
+{
+ if (__builtin_expect (count == 0, 0))
+ return;
+ if (devicep == NULL)
+ {
+ memset (ptr, val, count);
+ return;
+ }
+
+ gomp_mutex_lock (&devicep->lock);
+ int ret = devicep->memset_func (devicep->target_id, ptr, val, count);
+ gomp_mutex_unlock (&devicep->lock);
+ if (!ret)
+ gomp_fatal ("omp_target_memset failed");
+}
+
+void*
+omp_target_memset (void *ptr, int val, size_t count, int device_num)
+{
+ struct gomp_device_descr *devicep;
+ if (device_num == omp_initial_device
+ || device_num == gomp_get_num_devices ()
+ || (devicep = resolve_device (device_num, false)) == NULL
+ || !(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
+ || devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
+ devicep = NULL;
+
+ omp_target_memset_int (ptr, val, count, devicep);
+ return ptr;
+}
+
+typedef struct
+{
+ void *ptr;
+ size_t count;
+ struct gomp_device_descr *devicep;
+ int val;
+} omp_target_memset_data;
+
+static void
+omp_target_memset_async_helper (void *args)
+{
+ omp_target_memset_data *a = args;
+ omp_target_memset_int (a->ptr, a->val, a->count, a->devicep);
+}
+
+void*
+omp_target_memset_async (void *ptr, int val, size_t count, int device_num,
+ int depobj_count, omp_depend_t *depobj_list)
+{
+ void *depend[depobj_count + 5];
+ struct gomp_device_descr *devicep;
+ unsigned flags = 0;
+ int i;
+
+ if (device_num == omp_initial_device
+ || device_num == gomp_get_num_devices ()
+ || (devicep = resolve_device (device_num, false)) == NULL
+ || !(devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400)
+ || devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)
+ devicep = NULL;
+
+ omp_target_memset_data s = {.ptr = ptr, .val = val, .count = count,
+ .devicep = devicep};
+ if (depobj_count > 0 && depobj_list != NULL)
+ {
+ flags |= GOMP_TASK_FLAG_DEPEND;
+ depend[0] = 0;
+ depend[1] = (void *) (uintptr_t) depobj_count;
+ depend[2] = depend[3] = depend[4] = 0;
+ for (i = 0; i < depobj_count; ++i)
+ depend[i + 5] = &depobj_list[i];
+ }
+
+ GOMP_task (omp_target_memset_async_helper, &s, NULL, sizeof (s),
+ __alignof__ (s), true, flags, depend, 0, NULL);
+ return ptr;
+}
+
int
omp_target_associate_ptr (const void *host_ptr, const void *device_ptr,
size_t size, size_t device_offset, int device_num)
@@ -5568,6 +5650,7 @@ gomp_load_plugin_for_device (struct gomp_device_descr *device,
DLSYM_OPT (async_run, async_run);
DLSYM_OPT (can_run, can_run);
DLSYM (dev2dev);
+ DLSYM (memset);
}
if (device->capabilities & GOMP_OFFLOAD_CAP_OPENACC_200)
{
diff --git a/libgomp/testsuite/libgomp.c-c++-common/omp_target_memset-2.c b/libgomp/testsuite/libgomp.c-c++-common/omp_target_memset-2.c
new file mode 100644
index 0000000..b36d2f5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/omp_target_memset-2.c
@@ -0,0 +1,62 @@
+// PR libgomp/120444
+// Async version
+
+#include <omp.h>
+
+int main()
+{
+ #pragma omp parallel for
+ for (int dev = omp_initial_device; dev <= omp_get_num_devices (); dev++)
+ {
+ char *ptr = (char *) omp_target_alloc (sizeof(int) * 1024, dev);
+
+ omp_depend_t dep;
+ #pragma omp depobj(dep) depend(inout: ptr)
+
+ /* Play also around with the alignment - as hsa_amd_memory_fill operates
+ on multiples of 4 bytes (uint32_t). */
+
+ for (int start = 0; start < 32; start++)
+ for (int tail = 0; tail < 32; tail++)
+ {
+ unsigned char val = '0' + start + tail;
+#if __cplusplus
+ void *ptr2 = omp_target_memset_async (ptr + start, val,
+ 1024 - start - tail, dev, 0);
+#else
+ void *ptr2 = omp_target_memset_async (ptr + start, val,
+ 1024 - start - tail, dev, 0, nullptr);
+#endif
+ if (ptr + start != ptr2)
+ __builtin_abort ();
+
+ #pragma omp taskwait
+
+ #pragma omp target device(dev) is_device_ptr(ptr) depend(depobj: dep) nowait
+ for (int i = start; i < 1024 - start - tail; i++)
+ {
+ if (ptr[i] != val)
+ __builtin_abort ();
+ ptr[i] += 2;
+ }
+
+ omp_target_memset_async (ptr + start, val + 3,
+ 1024 - start - tail, dev, 1, &dep);
+
+ #pragma omp target device(dev) is_device_ptr(ptr) depend(depobj: dep) nowait
+ for (int i = start; i < 1024 - start - tail; i++)
+ {
+ if (ptr[i] != val + 3)
+ __builtin_abort ();
+ ptr[i] += 1;
+ }
+
+ omp_target_memset_async (ptr + start, val - 3,
+ 1024 - start - tail, dev, 1, &dep);
+
+ #pragma omp taskwait depend (depobj: dep)
+ }
+ #pragma omp depobj(dep) destroy
+ omp_target_free (ptr, dev);
+ }
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/omp_target_memset-3.c b/libgomp/testsuite/libgomp.c-c++-common/omp_target_memset-3.c
new file mode 100644
index 0000000..c0e4fa9
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/omp_target_memset-3.c
@@ -0,0 +1,80 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <omp.h>
+
+#define MIN(x,y) ((x) < (y) ? x : y)
+
+enum { N = 524288 + 8 };
+
+static void
+init_val (int8_t *ptr, int val, size_t count)
+{
+ #pragma omp target is_device_ptr(ptr) firstprivate(val, count)
+ __builtin_memset (ptr, val, count);
+}
+
+static void
+check_val (int8_t *ptr, int val, size_t count)
+{
+ if (count == 0)
+ return;
+ #pragma omp target is_device_ptr(ptr) firstprivate(val, count)
+ for (size_t i = 0; i < count; i++)
+ if (ptr[i] != val) __builtin_abort ();
+}
+
+static void
+test_it (int8_t *ptr, int lshift, size_t count)
+{
+ if (N < count + lshift) __builtin_abort ();
+ if (lshift >= 4) __builtin_abort ();
+ ptr += lshift;
+
+ init_val (ptr, 'z', MIN (count + 32, N - lshift));
+
+ omp_target_memset (ptr, '1', count, omp_get_default_device());
+
+ check_val (ptr, '1', count);
+ check_val (ptr + count, 'z', MIN (32, N - lshift - count));
+}
+
+
+int main()
+{
+ size_t size;
+ int8_t *ptr = (int8_t *) omp_target_alloc (N + 3, omp_get_default_device());
+ ptr += (4 - (uintptr_t) ptr % 4) % 4;
+ if ((uintptr_t) ptr % 4 != 0) __builtin_abort ();
+
+ test_it (ptr, 0, 1);
+ test_it (ptr, 3, 1);
+ test_it (ptr, 0, 4);
+ test_it (ptr, 3, 4);
+ test_it (ptr, 0, 5);
+ test_it (ptr, 3, 5);
+ test_it (ptr, 0, 6);
+ test_it (ptr, 3, 6);
+
+ for (int i = 1; i <= 9; i++)
+ {
+ switch (i)
+ {
+ case 1: size = 16; break; // = 2^4 bytes
+ case 2: size = 32; break; // = 2^5 bytes
+ case 3: size = 64; break; // = 2^7 bytes
+ case 4: size = 128; break; // = 2^7 bytes
+ case 5: size = 256; break; // = 2^8 bytes
+ case 6: size = 512; break; // = 2^9 bytes
+ case 7: size = 65536; break; // = 2^16 bytes
+ case 8: size = 262144; break; // = 2^18 bytes
+ case 9: size = 524288; break; // = 2^20 bytes
+ default: __builtin_abort ();
+ }
+ test_it (ptr, 0, size);
+ test_it (ptr, 3, size);
+ test_it (ptr, 0, size + 1);
+ test_it (ptr, 3, size + 1);
+ test_it (ptr, 3, size + 2);
+ }
+ omp_target_free (ptr, omp_get_default_device());
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/omp_target_memset.c b/libgomp/testsuite/libgomp.c-c++-common/omp_target_memset.c
new file mode 100644
index 0000000..01909f8
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/omp_target_memset.c
@@ -0,0 +1,62 @@
+// PR libgomp/120444
+
+#include <omp.h>
+
+int main()
+{
+ for (int dev = omp_initial_device; dev < omp_get_num_devices (); dev++)
+ {
+ char *ptr = (char *) omp_target_alloc (sizeof(int) * 1024, dev);
+
+ /* Play also around with the alignment - as hsa_amd_memory_fill operates
+ on multiples of 4 bytes (uint32_t). */
+
+ for (int start = 0; start < 32; start++)
+ for (int tail = 0; tail < 32; tail++)
+ {
+ unsigned char val = '0' + start + tail;
+ void *ptr2 = omp_target_memset (ptr + start, val,
+ 1024 - start - tail, dev);
+ if (ptr + start != ptr2)
+ __builtin_abort ();
+
+ #pragma omp target device(dev) is_device_ptr(ptr)
+ for (int i = start; i < 1024 - start - tail; i++)
+ if (ptr[i] != val)
+ __builtin_abort ();
+
+ }
+
+ /* Check 'small' values for correctness. */
+
+ for (int start = 0; start < 32; start++)
+ for (int size = 0; size <= 64 + 32; size++)
+ {
+ omp_target_memset (ptr, 'a' - 2, 1024, dev);
+
+ unsigned char val = '0' + start + size % 32;
+ void *ptr2 = omp_target_memset (ptr + start, val, size, dev);
+
+ if (ptr + start != ptr2)
+ __builtin_abort ();
+
+ if (size == 0)
+ continue;
+
+ #pragma omp target device(dev) is_device_ptr(ptr)
+ {
+ for (int i = 0; i < start; i++)
+ if (ptr[i] != 'a' - 2)
+ __builtin_abort ();
+ for (int i = start; i < start + size; i++)
+ if (ptr[i] != val)
+ __builtin_abort ();
+ for (int i = start + size + 1; i < 1024; i++)
+ if (ptr[i] != 'a' - 2)
+ __builtin_abort ();
+ }
+ }
+
+ omp_target_free (ptr, dev);
+ }
+}
diff --git a/libgomp/testsuite/libgomp.fortran/omp_target_memset-2.f90 b/libgomp/testsuite/libgomp.fortran/omp_target_memset-2.f90
new file mode 100644
index 0000000..2641086
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/omp_target_memset-2.f90
@@ -0,0 +1,67 @@
+! PR libgomp/120444
+! Async version
+
+use omp_lib
+use iso_c_binding
+implicit none (type, external)
+integer(c_int) :: dev
+
+!$omp parallel do
+do dev = omp_initial_device, omp_get_num_devices ()
+block
+ integer(c_int) :: i, val, start, tail
+ type(c_ptr) :: ptr, ptr2, tmpptr
+ integer(c_int8_t), pointer, contiguous :: fptr(:)
+ integer(c_intptr_t) :: intptr
+ integer(c_size_t), parameter :: count = 1024
+ integer(omp_depend_kind) :: dep(1)
+
+ ptr = omp_target_alloc (count, dev)
+
+ !$omp depobj(dep(1)) depend(inout: ptr)
+
+ ! Play also around with the alignment - as hsa_amd_memory_fill operates
+ ! on multiples of 4 bytes (c_int32_t)
+
+ do start = 0, 31
+ do tail = 0, 31
+ val = iachar('0') + start + tail
+
+ tmpptr = transfer (transfer (ptr, intptr) + start, tmpptr)
+ ptr2 = omp_target_memset_async (tmpptr, val, count - start - tail, dev, 0)
+
+ if (.not. c_associated (tmpptr, ptr2)) stop 1
+
+ !$omp taskwait
+
+ !$omp target device(dev) is_device_ptr(ptr) depend(depobj: dep(1)) nowait
+ do i = 1 + start, int(count, c_int) - start - tail
+ call c_f_pointer (ptr, fptr, [count])
+ if (fptr(i) /= int (val, c_int8_t)) stop 2
+ fptr(i) = fptr(i) + 2_c_int8_t
+ end do
+ !$omp end target
+
+ ptr2 = omp_target_memset_async (tmpptr, val + 3, &
+ count - start - tail, dev, 1, dep)
+
+ !$omp target device(dev) is_device_ptr(ptr) depend(depobj: dep(1)) nowait
+ do i = 1 + start, int(count, c_int) - start - tail
+ call c_f_pointer (ptr, fptr, [count])
+ if (fptr(i) /= int (val + 3, c_int8_t)) stop 3
+ fptr(i) = fptr(i) - 1_c_int8_t
+ end do
+ !$omp end target
+
+ ptr2 = omp_target_memset_async (tmpptr, val - 3, &
+ count - start - tail, dev, 1, dep)
+
+ !$omp taskwait depend (depobj: dep(1))
+ end do
+ end do
+
+ !$omp depobj(dep(1)) destroy
+ call omp_target_free (ptr, dev);
+end block
+end do
+end
diff --git a/libgomp/testsuite/libgomp.fortran/omp_target_memset.f90 b/libgomp/testsuite/libgomp.fortran/omp_target_memset.f90
new file mode 100644
index 0000000..1ee184a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/omp_target_memset.f90
@@ -0,0 +1,39 @@
+! PR libgomp/120444
+
+use omp_lib
+use iso_c_binding
+implicit none (type, external)
+
+integer(c_int) :: dev, i, val, start, tail
+type(c_ptr) :: ptr, ptr2, tmpptr
+integer(c_int8_t), pointer, contiguous :: fptr(:)
+integer(c_intptr_t) :: intptr
+integer(c_size_t), parameter :: count = 1024
+
+do dev = omp_initial_device, omp_get_num_devices ()
+ ptr = omp_target_alloc (count, dev)
+
+ ! Play also around with the alignment - as hsa_amd_memory_fill operates
+ ! on multiples of 4 bytes (c_int32_t)
+
+ do start = 0, 31
+ do tail = 0, 31
+ val = iachar('0') + start + tail
+
+ tmpptr = transfer (transfer (ptr, intptr) + start, tmpptr)
+ ptr2 = omp_target_memset (tmpptr, val, count - start - tail, dev)
+
+ if (.not. c_associated (tmpptr, ptr2)) stop 1
+
+ !$omp target device(dev) is_device_ptr(ptr)
+ do i = 1 + start, int(count, c_int) - start - tail
+ call c_f_pointer (ptr, fptr, [count])
+ if (fptr(i) /= int (val, c_int8_t)) stop 2
+ end do
+ !$omp end target
+ end do
+ end do
+
+ call omp_target_free (ptr, dev);
+end do
+end
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index e3da41b..9cbb8a0 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,415 @@
+2025-06-03 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/stop_token: Check __glibcxx_jthread instead of
+ __cplusplus.
+
+2025-06-03 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/type_traits (is_destructible, is_destructible_v):
+ Define using new built-in.
+ (is_nothrow_destructible, is_nothrow_destructible_v): Likewise.
+ (is_trivially_destructible, is_trivially_destructible_v):
+ Likewise.
+
+2025-06-03 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/atomic_timed_wait.h (__detail::__wait_until):
+ Remove incorrect comment.
+ (__atomic_wait_address_until_v): Do not take address of __args in
+ call to __detail::__wait_until. Fix return statement to refer to
+ member of __wait_result_type.
+ (__atomic_wait_address_for_v): Change parameter type from
+ time_point to duration.
+ * src/c++20/atomic.cc (__spin_until_impl): Fix incorrect
+ return value. Reuse result of first call to clock.
+
+2025-06-03 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/stl_vector.h (~_Vector_base): Add unreachable
+ hint for negative capacity and cast to size_t explicitly.
+ * include/bits/vector.tcc (vector::_M_realloc_append): Use
+ size() instead of end() - begin().
+
+2025-06-03 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/bit (__rotl, __rotr): Use static_cast for
+ conversion from int to unsigned.
+
+2025-06-03 Jonathan Wakely <jwakely@redhat.com>
+
+ * src/c++23/std.cc.in: Remove redundant checks for feature test
+ macros that are always true.
+
+2025-06-02 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/basic_string.h (basic_string::size): Remove space
+ before parameter list.
+ (basic_string::capacity): Likewise.
+ * include/bits/stl_deque.h (deque::size): Likewise.
+ * include/bits/stl_vector.h (vector::size, vector::capacity):
+ Likewise.
+ * include/bits/vector.tcc (vector::_M_realloc_insert): Likewise.
+ (vector::_M_realloc_append): Likewise.
+
+2025-06-02 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/120386
+ * include/bits/ranges_algo.h (__unique_copy_fn): Reorder
+ arguments for third case to match the first two cases.
+ * include/bits/stl_algo.h (__unique_copy): Replace three
+ overloads with two, depending only on the iterator category of
+ the input range. Dispatch to __unique_copy_1 for the
+ non-forward case.
+ (__unique_copy_1): New overloads for the case where the input
+ range uses non-forward iterators.
+ (unique_copy): Only pass the input range category to
+ __unique_copy.
+ * testsuite/25_algorithms/unique_copy/lwg2439.cc: New test.
+
+2025-06-02 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ * include/bits/funcwrap.h (__polyfunc::__pass_by_rref): Define.
+ (__polyfunc::__param_t): Update to use __pass_by_rref.
+ * include/bits/cpyfunc_impl.h:: Assert that are parameters type
+ are complete.
+ * include/bits/funcref_impl.h: Likewise.
+ * include/bits/mofunc_impl.h: Likewise.
+ * testsuite/20_util/copyable_function/call.cc: New test.
+ * testsuite/20_util/function_ref/call.cc: New test.
+ * testsuite/20_util/move_only_function/call.cc: New test.
+ * testsuite/20_util/copyable_function/conv.cc: New test.
+ * testsuite/20_util/function_ref/conv.cc: New test.
+ * testsuite/20_util/move_only_function/conv.cc: New test.
+ * testsuite/20_util/copyable_function/incomplete_neg.cc: New test.
+ * testsuite/20_util/function_ref/incomplete_neg.cc: New test.
+ * testsuite/20_util/move_only_function/incomplete_neg.cc: New test.
+
+2025-06-02 Jonathan Wakely <jwakely@redhat.com>
+ Tomasz Kamiński <tkaminsk@redhat.com>
+
+ PR libstdc++/119152
+ * include/bits/indirect.h (std::polymorphic, pmr::polymorphic)
+ [__glibcxx_polymorphic]: Define.
+ * include/bits/version.def (polymorphic): Define.
+ * include/bits/version.h: Regenerate.
+ * include/std/memory: Define __cpp_lib_polymorphic.
+ * testsuite/std/memory/polymorphic/copy.cc: New test.
+ * testsuite/std/memory/polymorphic/copy_alloc.cc: New test.
+ * testsuite/std/memory/polymorphic/ctor.cc: New test.
+ * testsuite/std/memory/polymorphic/ctor_poly.cc: New test.
+ * testsuite/std/memory/polymorphic/incomplete.cc: New test.
+ * testsuite/std/memory/polymorphic/invalid_neg.cc: New test.
+ * testsuite/std/memory/polymorphic/move.cc: New test.
+ * testsuite/std/memory/polymorphic/move_alloc.cc: New test.
+
+2025-05-30 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ * testsuite/std/time/format/empty_spec.cc: New test.
+
+2025-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/atomic_timed_wait.h: Use __wait_result_type.
+ * include/bits/atomic_wait.h (__wait_result_type): New struct.
+ (__wait_args::_M_prep_for_wait_on): Rename to _M_setup_wait, use
+ __wait_result_type.
+ (__atomic_wait_address): Adjust to call _M_setup_wait.
+ * src/c++20/atomic.cc (__spin_impl): Use __wait_result_type.
+ (__wait_impl): Likewise.
+ (__spin_until_impl): Likewise.
+ (__wait_until_impl): Likewise.
+
+2025-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/118494
+ PR libstdc++/110854
+ PR libstdc++/98749
+ * acinclude.m4 (GLIBCXX_CHECK_GTHREADS): Remove checks for
+ sem_timedwait. Do not define _GLIBCXX_HAVE_POSIX_SEMAPHORE.
+ * config.h.in: Regenerate.
+ * configure: Regenerate.
+ * include/bits/semaphore_base.h (__platform_semaphore): Remove.
+ (__atomic_semaphore): Replace with __semaphore_base<bool> and
+ make type of _M_count depend on template parameter. Fix _S_max
+ constant to use correct type.
+ (__semaphore_base::_M_try_acquire): Qualify to avoid ADL.
+ (__semaphore_base::_M_release): Return old value. Remove FIXME
+ comment.
+ (__semaphore_impl): Replace typedef with alias template.
+ * include/bits/version.def (semaphore): Do not depend on
+ _GLIBCXX_HAVE_POSIX_SEMAPHORE.
+ * include/bits/version.h: Regenerate.
+ * include/std/semaphore (semaphore): Adjust type of _M_sem
+ member. Add constexpr to constructor. Add assertions to
+ (semaphore::semaphore(ptrdiff_t)): Add constexpr. Add assertion
+ for precondition.
+ (semaphore::release): Add assertion using value returned from
+ _M_release.
+ * testsuite/30_threads/semaphore/100806.cc: Increase template
+ argument for std::counting_semaphore, so constructor
+ precondition is met.
+ * testsuite/30_threads/semaphore/cons.cc: New test.
+ * testsuite/30_threads/semaphore/try_acquire_posix.cc: Remove.
+ * testsuite/30_threads/semaphore/platform_try_acquire_for.cc:
+ Removed.
+
+2025-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/barrier (__tree_barrier_base): New class.
+ (__tree_barrier): Move non-dependent code into
+ __tree_barrier_base and derive from it.
+
+2025-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/118395
+ PR libstdc++/108974
+ PR libstdc++/98749
+ * include/std/barrier (__tree_barrier): Use default
+ member-initializers. Change _M_state member from
+ unique_ptr<__state_t[]> to atomic<__state_t*>. Add
+ no_unique_address attribute to _M_completion.
+ (__tree_barrier::_M_arrive): Load value from _M_state.
+ (__tree_barrier::_M_invoke_completion): New member function to
+ ensure a throwing completion function will terminate, as
+ proposed in LWG 3898.
+ (__tree_barrier::max): Reduce by one to avoid overflow.
+ (__tree_barrier::__tree_barrier): Add constexpr. Qualify call to
+ std::move. Remove mem-initializers made unnecessary by default
+ member-initializers. Add precondition check. Only allocate state
+ array if not constant evaluated.
+ (__tree_barrier::arrive): Add precondition check. Do deferred
+ initialization of _M_state if needed.
+ (barrier): Add static_assert, as proposed in LWG 3898.
+ (barrier::barrier): Add constexpr.
+ * testsuite/30_threads/barrier/cons.cc: New test.
+ * testsuite/30_threads/barrier/lwg3898.cc: New test.
+
+2025-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/latch (latch::arrive_and_wait): Optimise.
+
+2025-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * config/abi/pre/gnu.ver: Add new symbol version and exports.
+ * include/bits/atomic_timed_wait.h (__platform_wait_until): Move
+ to atomic.cc.
+ (__cond_wait_until, __spin_until_impl): Likewise.
+ (__wait_until_impl): Likewise. Change __wait_args_base parameter
+ to non-const reference and change third parameter to
+ __wait_clock_t::duration.
+ (__wait_until): Change __wait_args_base parameter to non-const
+ reference. Change Call time_since_epoch() to get duration from
+ time_point.
+ (__wait_for): Change __wait_args_base parameter to non-const
+ reference.
+ (__atomic_wait_address_until): Call _M_prep_for_wait_on on args.
+ (__atomic_wait_address_for): Likewise.
+ (__atomic_wait_address_until_v): Qualify call to avoid ADL. Do
+ not forward __vfn.
+ * include/bits/atomic_wait.h (__platform_wait_uses_type): Use
+ alignof(T) not alignof(T*).
+ (__futex_wait_flags, __platform_wait, __platform_notify)
+ (__waitable_state, __spin_impl, __notify_impl): Move to
+ atomic.cc.
+ (__wait_impl): Likewise. Change __wait_args_base parameter to
+ non-const reference.
+ (__wait_args_base::_M_wait_state): New data member.
+ (__wait_args_base::_M_prep_for_wait_on): New member function.
+ (__wait_args_base::_M_load_proxy_wait_val): New member
+ function.
+ (__wait_args_base::_S_memory_order_for): Remove member function.
+ (__atomic_wait_address): Call _M_prep_for_wait_on on args.
+ (__atomic_wait_address_v): Qualify call to avoid ADL.
+ * src/c++20/Makefile.am: Add new file.
+ * src/c++20/Makefile.in: Regenerate.
+ * src/c++20/atomic.cc: New file.
+ * testsuite/17_intro/headers/c++1998/49745.cc: Remove XFAIL for
+ C++20 and later.
+ * testsuite/29_atomics/atomic/wait_notify/100334.cc: Remove use
+ of internal implementation details.
+ * testsuite/util/testsuite_abi.cc: Add GLIBCXX_3.4.35 version.
+
+2025-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/atomic_timed_wait.h (__wait_until_impl): Adjust
+ to use new naming.
+ * include/bits/atomic_wait.h (__waiter_pool_impl): Rename to
+ __waitable_state.
+ (__waiter_pool_impl::_S_wait): Rename to _M_waiters.
+ (__waiter_pool_impl::_S_impl_for): Rename to _S_state_for.
+ (__waiter_pool_impl::_S_track): Adjust to use new naming.
+ (__wait_impl, __notify_impl): Likewise.
+ * testsuite/29_atomics/atomic/wait_notify/100334.cc: Adjust to
+ use new naming.
+
+2025-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/atomic_timed_wait.h
+ (__atomic_wait_address_until_v): Replace __atomic_compare with
+ __atomic_eq.
+ (__atomic_wait_address_for_v): Likewise.
+ * include/bits/atomic_wait.h (__atomic_compare): Rename to
+ __atomic_eq.
+ (__atomic_wait_address_v): Replace __atomic_compare with
+ __atomic_eq.
+
+2025-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/atomic_timed_wait.h (__wait_until_impl): Change
+ first parameter to const void* and then static_cast to const
+ __platform_wait_t* when not using proxied wait.
+ (__wait_until): Change first parameter to const void*.
+ (__wait_for): Likewise.
+ (__atomic_wait_address_until): Remove reinterpret_cast and allow
+ address to implicitly convert to const void* instead.
+ (__atomic_wait_address_for): Likewise.
+ * include/bits/atomic_wait.h: (__wait_impl, __notify_impl):
+ Change first parameter to const void* and then static_cast to
+ const __platform_wait_t* when not using proxied wait.
+ (__atomic_wait_address, __atomic_notify_address) Remove
+ reinterpret_cast and allow address to implicitly convert to
+ const void* instead.
+
+2025-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/atomic_wait.h (__platform_wait): Change function
+ template to a normal function. The parameter is always
+ __platform_wait_t* which is just int* for this implementation of
+ the function.
+ (__platform_notify): Likewise.
+
+2025-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/atomic_timed_wait.h (__to_wait_clock): Do not use
+ chrono::ceil if clock and duration are already correct type.
+ (__wait_until): Always call __to_wait_clock.
+
+2025-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/atomic_wait.h (__notify_impl): Increment the
+ proxy value before returning early for the uncontended case.
+
+2025-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/atomic_timed_wait.h (__cond_wait_impl): Add
+ missing inline keyword.
+ (__spin_until_impl): Change parameter from pointer to reference.
+ Replace make_pair with list-initialization. Initialize variable
+ for return value.
+ (__wait_until_impl): Likewise. Remove some preprocessor
+ conditional logic. Use _S_track for contention tracking.
+ Avoid unnecessary const_cast.
+ (__wait_until): Change parameter from pointer to reference.
+ Replace make_pair with list-initialization.
+ (__wait_for): Change parameter from pointer to reference. Add
+ __do_spin flag to args.
+ * include/bits/atomic_wait.h (__waiter_pool_impl::_S_track): New
+ function returning an RAII object for contention tracking.
+ (__wait_flags): Do not set the __do_spin flag in the __spin_only
+ enumerator. Comment out the unused __abi_version_mask
+ enumerator. Define operator| and operator|= overloads.
+ (__wait_args_base::operator&): Define.
+ (__wait_args::operator&, __wait_args::_S_default_flags): Remove.
+ (__wait_args::operator|, __wait_args::operator|=): Remove.
+ (__spin_impl): Change parameter from pointer to reference.
+ Replace make_pair call with list-initialization.
+ (__wait_impl): Likewise. Remove some preprocessor conditional
+ logic. Always store old value in __args._M_old. Avoid
+ unnecessary const_cast. Use _S_track.
+ (__notify_impl): Change parameter to reference. Remove some
+ preprocessor conditional logic.
+ (__atomic_wait_address): Add comment. Update __args._M_old on
+ each iteration.
+ (__atomic_wait_address_v): Add comment.
+ * include/std/latch (latch::wait): Adjust predicates for new
+ logic.
+ * testsuite/29_atomics/atomic_integral/wait_notify.cc: Improve
+ test.
+
+2025-05-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/atomic_timed_wait.h: Whitespace fixes.
+ * include/bits/atomic_wait.h: Likewise.
+
+2025-05-30 Thomas Rodgers <trodgers@redhat.com>
+
+ * include/bits/atomic_timed_wait.h (__spin_until_impl): Accept
+ __wait_args as const __wait_args_base*.
+ (__wait_until_impl): Likewise.
+ (__wait_until): Likewise.
+ (__wait_for): Likewise.
+ (__atomic_wait_address_until): Pass __wait_args by address.
+ (__atomic_wait_address_for): Likewise.
+ * include/bits/atomic_wait.h (__wait_args_base): New struct.
+ (__wait_args): Derive from __wait_args_base.
+ (__wait_args::__wait_args()): Adjust ctors to call call base ctor.
+ (__wait_args::__wait_args(const __wait_args_base&)): New ctor.
+ (__wait_args::operator|=): New method.
+ (__wait_args::_S_flags_for): Change return type to
+ __wait_flags.
+ (__spin_impl): Accept __wait_args as const __wait_args_base*.
+ (__wait_impl): Likewise.
+ (__notify_impl): Likewise.
+ (__atomic_wait_address): Pass __wait_args by address.
+ (__atomic_wait_address_v): Likewise.
+ (__atomic_notify_address): Likewise.
+
+2025-05-30 Thomas Rodgers <trodgers@redhat.com>
+
+ * include/bits/atomic_timed_wait.h:
+ (__detail::__platform_wait_until_impl): Rename to
+ __platform_wait_until.
+ (__detail::__platform_wait_until): Remove previous
+ definition.
+ (__detail::__cond_wait_until_impl): Rename to
+ __cond_wait_until.
+ (__detail::__cond_wait_until): Remove previous
+ definition.
+ (__detail::__spin_until_impl): New function.
+ (__detail::__wait_until_impl): New function.
+ (__detail::__wait_until): New function.
+ (__detail::__wait_for): New function.
+ (__detail::__timed_waiter_pool): Remove type.
+ (__detail::__timed_backoff_spin_policy): Remove type.
+ (__detail::__timed_waiter): Remove type.
+ (__detail::__enters_timed_wait): Remove type alias.
+ (__detail::__bare_timed_wait): Remove type alias.
+ (__atomic_wait_address_until): Adjust to new implementation
+ detail.
+ (__atomic_wait_address_until_v): Likewise.
+ (__atomic_wait_address_bare): Remove.
+ (__atomic_wait_address_for): Adjust to new implementation
+ detail.
+ (__atomic_wait_address_for_v): Likewise.
+ (__atomic_wait_address_for_bare): Remove.
+ * include/bits/atomic_wait.h: Include bits/stl_pair.h.
+ (__detail::__default_spin_policy): Remove type.
+ (__detail::__atomic_spin): Remove function.
+ (__detail::__waiter_pool_base): Rename to __waiter_pool_impl.
+ Remove _M_notify. Rename _S_for to _S_impl_for.
+ (__detail::__waiter_base): Remove type.
+ (__detail::__waiter_pool): Remove type.
+ (__detail::__waiter): Remove type.
+ (__detail::__enters_wait): Remove type alias.
+ (__detail::__bare_wait): Remove type alias.
+ (__detail::__wait_flags): New enum.
+ (__detail::__wait_args): New struct.
+ (__detail::__wait_result_type): New type alias.
+ (__detail::__spin_impl): New function.
+ (__detail::__wait_impl): New function.
+ (__atomic_wait_address): Adjust to new implementation detail.
+ (__atomic_wait_address_v): Likewise.
+ (__atomic_notify_address): Likewise.
+ (__atomic_wait_address_bare): Delete.
+ (__atomic_notify_address_bare): Likewise.
+ * include/bits/semaphore_base.h: Adjust implementation to
+ use new __atomic_wait_address_v contract.
+ * include/std/barrier: Adjust implementation to use new
+ __atomic_wait contract.
+ * include/std/latch: Adjust implementation to use new
+ __atomic_wait contract.
+ * testsuite/29_atomics/atomic/wait_notify/100334.cc (main):
+ Adjust to for __detail::__waiter_pool_base renaming.
+
2025-05-29 Patrick Palka <ppalka@redhat.com>
* include/std/flat_map (_Flat_map_impl::operator==): Compare
diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h b/libstdc++-v3/include/bits/atomic_timed_wait.h
index 230afbc..bd2e6bf 100644
--- a/libstdc++-v3/include/bits/atomic_timed_wait.h
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -87,7 +87,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__wait_until_impl(const void* __addr, __wait_args_base& __args,
const __wait_clock_t::duration& __atime);
- // Returns {true, val} if wait ended before a timeout.
template<typename _Clock, typename _Dur>
__wait_result_type
__wait_until(const void* __addr, __wait_args_base& __args,
@@ -158,8 +157,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool __bare_wait = false) noexcept
{
__detail::__wait_args __args{ __addr, __old, __order, __bare_wait };
- auto __res = __detail::__wait_until(__addr, &__args, __atime);
- return __res.first; // C++26 will also return last observed __val
+ auto __res = __detail::__wait_until(__addr, __args, __atime);
+ return !__res._M_timeout; // C++26 will also return last observed __val
}
template<typename _Tp, typename _ValFn,
@@ -203,7 +202,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__atomic_wait_address_for_v(const __detail::__platform_wait_t* __addr,
__detail::__platform_wait_t __old,
int __order,
- const chrono::time_point<_Rep, _Period>& __rtime,
+ const chrono::duration<_Rep, _Period>& __rtime,
bool __bare_wait = false) noexcept
{
__detail::__wait_args __args{ __addr, __old, __order, __bare_wait };
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index a087e63..7081049 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -1164,7 +1164,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{
size_type __sz = _M_string_length;
if (__sz > max_size ())
- __builtin_unreachable ();
+ __builtin_unreachable();
return __sz;
}
@@ -1279,7 +1279,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
size_t __sz = _M_is_local() ? size_type(_S_local_capacity)
: _M_allocated_capacity;
if (__sz < _S_local_capacity || __sz > max_size ())
- __builtin_unreachable ();
+ __builtin_unreachable();
return __sz;
}
diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index 346eb8b..239f9c7 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -1296,7 +1296,8 @@ namespace __format
else
{
auto __str = std::format(_S_empty_spec, __ss.count());
- __out = std::format_to(_GLIBCXX_WIDEN("{:0>{}s}"),
+ __out = std::format_to(std::move(__out),
+ _GLIBCXX_WIDEN("{:0>{}s}"),
__str,
__hms.fractional_width);
}
diff --git a/libstdc++-v3/include/bits/cpyfunc_impl.h b/libstdc++-v3/include/bits/cpyfunc_impl.h
index bc44cd3e..f1918dd 100644
--- a/libstdc++-v3/include/bits/cpyfunc_impl.h
+++ b/libstdc++-v3/include/bits/cpyfunc_impl.h
@@ -64,6 +64,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_MOF_REF noexcept(_Noex)>
: __polyfunc::_Cpy_base
{
+ static_assert(
+ (std::__is_complete_or_unbounded(__type_identity<_ArgTypes>()) && ...),
+ "each parameter type must be a complete class");
+
using _Base = __polyfunc::_Cpy_base;
using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>;
using _Signature = _Invoker::_Signature;
diff --git a/libstdc++-v3/include/bits/funcref_impl.h b/libstdc++-v3/include/bits/funcref_impl.h
index 1e19866..44c9922 100644
--- a/libstdc++-v3/include/bits/funcref_impl.h
+++ b/libstdc++-v3/include/bits/funcref_impl.h
@@ -68,6 +68,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class function_ref<_Res(_ArgTypes...) _GLIBCXX_MOF_CV
noexcept(_Noex)>
{
+ static_assert(
+ (std::__is_complete_or_unbounded(__type_identity<_ArgTypes>()) && ...),
+ "each parameter type must be a complete class");
+
using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>;
using _Signature = _Invoker::_Signature;
diff --git a/libstdc++-v3/include/bits/funcwrap.h b/libstdc++-v3/include/bits/funcwrap.h
index cf261bc..9db4ab7 100644
--- a/libstdc++-v3/include/bits/funcwrap.h
+++ b/libstdc++-v3/include/bits/funcwrap.h
@@ -199,7 +199,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
template<typename _Tp>
- using __param_t = __conditional_t<is_scalar_v<_Tp>, _Tp, _Tp&&>;
+ consteval bool
+ __pass_by_value()
+ {
+ // n.b. sizeof(Incomplete&) is ill-formed for incomplete types,
+ // so we check is_reference_v first.
+ if constexpr (is_reference_v<_Tp> || is_scalar_v<_Tp>)
+ return true;
+ else
+ // n.b. we already asserted that types are complete in wrappers,
+ // avoid triggering additional errors from this function.
+ if constexpr (std::__is_complete_or_unbounded(__type_identity<_Tp>()))
+ if constexpr (sizeof(_Tp) <= 2 * sizeof(void*))
+ return is_trivially_move_constructible_v<_Tp>
+ && is_trivially_destructible_v<_Tp>;
+ return false;
+ }
+
+ template<typename _Tp>
+ using __param_t = __conditional_t<__pass_by_value<_Tp>(), _Tp, _Tp&&>;
template<bool _Noex, typename _Ret, typename... _Args>
using _Invoker = _Base_invoker<_Noex, remove_cv_t<_Ret>, __param_t<_Args>...>;
diff --git a/libstdc++-v3/include/bits/indirect.h b/libstdc++-v3/include/bits/indirect.h
index 85908e2..e8000d7 100644
--- a/libstdc++-v3/include/bits/indirect.h
+++ b/libstdc++-v3/include/bits/indirect.h
@@ -452,7 +452,381 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ };
#endif // __glibcxx_indirect
- _GLIBCXX_END_NAMESPACE_VERSION
+#if __glibcxx_polymorphic // C++26 && HOSTED
+ template<typename _Tp, typename _Alloc = allocator<_Tp>>
+ class polymorphic;
+
+ namespace pmr
+ {
+ template<typename _Tp>
+ using polymorphic = polymorphic<_Tp, polymorphic_allocator<_Tp>>;
+ }
+
+ // [polymorphic], class template polymorphic
+ template<typename _Tp, typename _Alloc>
+ class polymorphic
+ {
+ static_assert(is_object_v<_Tp>);
+ static_assert(!is_array_v<_Tp>);
+ static_assert(!is_same_v<_Tp, in_place_t>);
+ static_assert(!__is_in_place_type_v<_Tp>);
+ static_assert(!is_const_v<_Tp> && !is_volatile_v<_Tp>);
+
+ using _ATraits = allocator_traits<_Alloc>;
+ static_assert(is_same_v<_Tp, typename _ATraits::value_type>);
+
+ // The owned object is embedded within a control block which knows the
+ // dynamic type and manages cloning and destroying the owned object.
+ struct _Obj
+ {
+ typename _ATraits::pointer _M_objp{}; // pointer to the owned object.
+
+ // A pointer to this type, e.g. _Obj*
+ using pointer
+ = typename _ATraits::template rebind_traits<_Obj>::pointer;
+
+ enum class _Op { _Dispose = 1, _Copy = 2, _Move = 3 };
+
+ constexpr virtual pointer
+ _M_manage(const _Alloc&, _Op, void* = nullptr) = 0;
+ };
+
+ template<typename _Up>
+ struct _Obj_impl : _Obj
+ {
+ using _MyTraits
+ = typename _ATraits::template rebind_traits<_Obj_impl>;
+
+ using _Op = _Obj::_Op;
+
+ union _Uninitialized {
+ constexpr _Uninitialized() { }
+ constexpr ~_Uninitialized() { }
+ _Up _M_objp;
+ };
+ _Uninitialized _M_u;
+
+ template<typename... _Args>
+ constexpr
+ _Obj_impl(typename _MyTraits::allocator_type& __a,
+ _Args&&... __args)
+ {
+ using _PtrTr = pointer_traits<typename _ATraits::pointer>;
+ _MyTraits::construct(__a, __builtin_addressof(_M_u._M_objp),
+ std::forward<_Args>(__args)...);
+ this->_M_objp = _PtrTr::pointer_to(_M_u._M_objp);
+ }
+
+ constexpr virtual typename _Obj::pointer
+ _M_manage(const _Alloc& __a, _Op __op, void*) override
+ {
+
+ switch (__op)
+ {
+ case _Op::_Move:
+ return _S_make_obj<_Up>(__a, std::move(_M_u._M_objp));
+ case _Op::_Copy:
+ return _S_make_obj<_Up>(__a,
+ const_cast<const _Up&>(_M_u._M_objp));
+ case _Op::_Dispose:
+ {
+ using _PtrTr = pointer_traits<typename _MyTraits::pointer>;
+ typename _MyTraits::allocator_type __a2(__a);
+ _MyTraits::destroy(__a2, std::__addressof(_M_u._M_objp));
+ _MyTraits::deallocate(__a2, _PtrTr::pointer_to(*this), 1);
+ return nullptr;
+ }
+ }
+ __builtin_unreachable();
+ }
+ };
+
+ // TODO: the standard permits a small-object optimization where the
+ // owned object is nested within the std::polymorphic not on the heap.
+
+ public:
+
+ using value_type = _Tp;
+ using allocator_type = _Alloc;
+ using pointer = typename allocator_traits<_Alloc>::pointer;
+ using const_pointer = typename allocator_traits<_Alloc>::const_pointer;
+
+ constexpr explicit
+ polymorphic() requires is_default_constructible_v<_Alloc>
+ : polymorphic(in_place_type<_Tp>)
+ { }
+
+ constexpr explicit
+ polymorphic(allocator_arg_t, const _Alloc& __a)
+ : polymorphic(allocator_arg, __a, in_place_type<_Tp>)
+ { }
+
+ constexpr
+ polymorphic(const polymorphic& __other)
+ : polymorphic(allocator_arg,
+ _ATraits::select_on_container_copy_construction(
+ __other._M_alloc),
+ __other)
+ { }
+
+ constexpr
+ polymorphic(allocator_arg_t, const _Alloc& __a,
+ const polymorphic& __other)
+ : _M_alloc(__a)
+ {
+ if (__other._M_objp)
+ _M_objp = __other._M_objp->_M_manage(__a, _Obj::_Op::_Copy);
+ else
+ _M_objp = nullptr;
+ }
+
+ constexpr
+ polymorphic(polymorphic&& __other) noexcept
+ : _M_alloc(std::move(__other._M_alloc)),
+ _M_objp(std::__exchange(__other._M_objp, nullptr))
+ { }
+
+ constexpr
+ polymorphic(allocator_arg_t, const _Alloc& __a, polymorphic&& __other)
+ noexcept(_ATraits::is_always_equal::value)
+ : _M_alloc(__a),
+ _M_objp(std::__exchange(__other._M_objp, nullptr))
+ {
+ if constexpr (!_ATraits::is_always_equal::value)
+ if (_M_objp && _M_alloc != __other._M_alloc)
+ {
+ // _M_alloc cannot free _M_objp, give it back to __other.
+ __other._M_objp = std::__exchange(_M_objp, nullptr);
+ // And create a new object that can be freed by _M_alloc.
+ _M_objp = __other._M_objp->_M_manage(__a, _Obj::_Op::_Move);
+ }
+ }
+
+ template<typename _Up = _Tp, typename _UUp = remove_cvref_t<_Up>>
+ requires (!is_same_v<_UUp, polymorphic>)
+ && (!__is_in_place_type_v<_UUp>)
+ && derived_from<_UUp, _Tp>
+ && is_constructible_v<_UUp, _Up>
+ && is_copy_constructible_v<_UUp>
+ && is_default_constructible_v<_Alloc>
+ constexpr explicit
+ polymorphic(_Up&& __u)
+ : _M_objp(_M_make_obj<_UUp>(std::forward<_Up>(__u)))
+ { }
+
+ template<typename _Up = _Tp, typename _UUp = remove_cvref_t<_Up>>
+ requires (!is_same_v<_UUp, polymorphic>)
+ && (!__is_in_place_type_v<_UUp>)
+ && derived_from<_UUp, _Tp>
+ && is_constructible_v<_UUp, _Up>
+ && is_copy_constructible_v<_UUp>
+ constexpr explicit
+ polymorphic(allocator_arg_t, const _Alloc& __a, _Up&& __u)
+ : _M_alloc(__a), _M_objp(_M_make_obj<_UUp>(std::forward<_Up>(__u)))
+ { }
+
+ template<typename _Up, typename... _Ts>
+ requires is_same_v<remove_cvref_t<_Up>, _Up>
+ && derived_from<_Up, _Tp>
+ && is_constructible_v<_Up, _Ts...>
+ && is_copy_constructible_v<_Up>
+ && is_default_constructible_v<_Alloc>
+ constexpr explicit
+ polymorphic(in_place_type_t<_Up> __t, _Ts&&... __ts)
+ : _M_objp(_M_make_obj<_Up>(std::forward<_Ts>(__ts)...))
+ { }
+
+ template<typename _Up, typename... _Ts>
+ requires is_same_v<remove_cvref_t<_Up>, _Up>
+ && derived_from<_Up, _Tp>
+ && is_constructible_v<_Up, _Ts...>
+ && is_copy_constructible_v<_Up>
+ constexpr explicit
+ polymorphic(allocator_arg_t, const _Alloc& __a,
+ in_place_type_t<_Up>, _Ts&&... __ts)
+ : _M_alloc(__a),
+ _M_objp(_M_make_obj<_Up>(std::forward<_Ts>(__ts)...))
+ { }
+
+ template<typename _Up, typename _Ip, typename... _Us>
+ requires is_same_v<remove_cvref_t<_Up>, _Up>
+ && derived_from<_Up, _Tp>
+ && is_constructible_v<_Up, initializer_list<_Ip>&, _Us...>
+ && is_copy_constructible_v<_Up>
+ && is_default_constructible_v<_Alloc>
+ constexpr explicit
+ polymorphic(in_place_type_t<_Up>, initializer_list<_Ip> __il,
+ _Us&&... __us)
+ : _M_objp(_M_make_obj<_Up>(__il, std::forward<_Us>(__us)...))
+ { }
+
+ template<typename _Up, typename _Ip, typename... _Us>
+ requires is_same_v<remove_cvref_t<_Up>, _Up>
+ && derived_from<_Up, _Tp>
+ && is_constructible_v<_Up, initializer_list<_Ip>&, _Us...>
+ && is_copy_constructible_v<_Up>
+ constexpr explicit
+ polymorphic(allocator_arg_t, const _Alloc& __a,
+ in_place_type_t<_Up>, initializer_list<_Ip> __il,
+ _Us&&... __us)
+ : _M_alloc(__a),
+ _M_objp(_M_make_obj<_Up>(__il, std::forward<_Us>(__us)...))
+ { }
+
+ constexpr ~polymorphic()
+ {
+ static_assert(sizeof(_Tp) != 0, "must be a complete type");
+ _M_reset(nullptr);
+ }
+
+ constexpr polymorphic&
+ operator=(const polymorphic& __other)
+ {
+ static_assert(sizeof(_Tp) != 0, "must be a complete type");
+
+ if (__builtin_addressof(__other) == this) [[unlikely]]
+ return *this;
+
+ constexpr bool __pocca
+ = _ATraits::propagate_on_container_copy_assignment::value;
+
+ typename _Obj::pointer __ptr = nullptr;
+ if (__other._M_objp)
+ {
+ auto& __a = __pocca ? __other._M_alloc : _M_alloc;
+ __ptr = __other._M_objp->_M_manage(__a, _Obj::_Op::_Copy);
+ }
+
+ _M_reset(__ptr);
+
+ if constexpr (__pocca)
+ _M_alloc = __other._M_alloc;
+
+ return *this;
+ }
+
+ constexpr polymorphic&
+ operator=(polymorphic&& __other)
+ noexcept(_ATraits::propagate_on_container_move_assignment::value
+ || _ATraits::is_always_equal::value)
+ {
+ if (__builtin_addressof(__other) == this) [[unlikely]]
+ return *this;
+
+ constexpr bool __pocma
+ = _ATraits::propagate_on_container_move_assignment::value;
+
+ typename _Obj::pointer __ptr = nullptr;
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4251. Move assignment for indirect unnecessarily requires copy construction
+ if constexpr (_ATraits::is_always_equal::value || __pocma)
+ __ptr = std::__exchange(__other._M_objp, nullptr);
+ else if (_M_alloc == __other._M_alloc)
+ __ptr = std::__exchange(__other._M_objp, nullptr);
+ else if (__other._M_objp)
+ {
+ static_assert(sizeof(_Tp) != 0, "must be a complete type");
+ __ptr = __other._M_objp->_M_manage(_M_alloc, _Obj::_Op::_Move);
+ }
+
+ _M_reset(__ptr);
+
+ if constexpr (__pocma)
+ _M_alloc = __other._M_alloc;
+
+ return *this;
+ }
+
+ constexpr const _Tp&
+ operator*() const noexcept
+ {
+ __glibcxx_assert(_M_objp != nullptr);
+ return *_M_objp->_M_objp;
+ }
+
+ constexpr _Tp&
+ operator*() noexcept
+ {
+ __glibcxx_assert(_M_objp != nullptr);
+ return *_M_objp->_M_objp;
+ }
+
+ constexpr const_pointer
+ operator->() const noexcept
+ {
+ __glibcxx_assert(_M_objp != nullptr);
+ return _M_objp ? _M_objp->_M_objp : const_pointer{};
+ }
+
+ constexpr pointer
+ operator->() noexcept
+ {
+ __glibcxx_assert(_M_objp != nullptr);
+ return _M_objp ? _M_objp->_M_objp : pointer{};
+ }
+
+ constexpr bool
+ valueless_after_move() const noexcept { return _M_objp == nullptr; }
+
+ constexpr allocator_type
+ get_allocator() const noexcept { return _M_alloc; }
+
+ constexpr void
+ swap(polymorphic& __other)
+ noexcept(_ATraits::propagate_on_container_swap::value
+ || _ATraits::is_always_equal::value)
+ {
+ using std::swap;
+ swap(_M_objp, __other._M_objp);
+ if constexpr (_ATraits::propagate_on_container_swap::value)
+ swap(_M_alloc, __other._M_alloc);
+ else if constexpr (!_ATraits::is_always_equal::value)
+ __glibcxx_assert(_M_alloc == __other._M_alloc);
+ }
+
+ friend constexpr void
+ swap(polymorphic& __lhs, polymorphic& __rhs)
+ noexcept(_ATraits::propagate_on_container_swap::value
+ || _ATraits::is_always_equal::value)
+ { __lhs.swap(__rhs); }
+
+ private:
+ template<typename _Up, typename... _Args>
+ static constexpr typename _Obj::pointer
+ _S_make_obj(const _Alloc& __a, _Args&&... __args)
+ {
+ __alloc_rebind<_Alloc, _Obj_impl<_Up>> __objalloc(__a);
+ _Scoped_allocation __sa(__objalloc, in_place, __objalloc,
+ std::forward<_Args>(__args)...);
+ auto __obj = __sa.release();
+ // FIXME: We need to downcast from _Obj_impl<U>* to _Obj* but the
+ // the pointer_traits usage breaks in constexpr. PR c++/110714
+ if constexpr (is_pointer_v<typename _Obj::pointer>)
+ return __obj;
+ else
+ return pointer_traits<typename _Obj::pointer>::pointer_to(*__obj);
+ }
+
+ template<typename _Up, typename... _Args>
+ constexpr typename _Obj::pointer
+ _M_make_obj(_Args&&... __args) const
+ { return _S_make_obj<_Up>(_M_alloc, std::forward<_Args>(__args)...); }
+
+ constexpr void
+ _M_reset(typename _Obj::pointer __ptr) noexcept
+ {
+ if (_M_objp)
+ _M_objp->_M_manage(_M_alloc, _Obj::_Op::_Dispose);
+ _M_objp = __ptr;
+ }
+
+ [[no_unique_address]] _Alloc _M_alloc = _Alloc();
+ typename _Obj::pointer _M_objp;
+ };
+#endif // __glibcxx_polymorphic
+
+_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
#endif // C++26 __glibcxx_indirect || __glibcxx_polymorphic
diff --git a/libstdc++-v3/include/bits/mofunc_impl.h b/libstdc++-v3/include/bits/mofunc_impl.h
index 1ceb910..468e685 100644
--- a/libstdc++-v3/include/bits/mofunc_impl.h
+++ b/libstdc++-v3/include/bits/mofunc_impl.h
@@ -64,6 +64,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_MOF_REF noexcept(_Noex)>
: __polyfunc::_Mo_base
{
+ static_assert(
+ (std::__is_complete_or_unbounded(__type_identity<_ArgTypes>()) && ...),
+ "each parameter type must be a complete class");
+
using _Base = __polyfunc::_Mo_base;
using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>;
using _Signature = _Invoker::_Signature;
diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index f36e7dd..7b14084 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -1218,6 +1218,9 @@ namespace ranges
if (__first == __last)
return {std::move(__first), std::move(__result)};
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4269. unique_copy passes arguments to its predicate backwards
+
// TODO: perform a closer comparison with reference implementations
if constexpr (forward_iterator<_Iter>)
{
@@ -1250,8 +1253,8 @@ namespace ranges
while (++__first != __last)
{
if (!(bool)std::__invoke(__comp,
- std::__invoke(__proj, *__first),
- std::__invoke(__proj, __value)))
+ std::__invoke(__proj, __value),
+ std::__invoke(__proj, *__first)))
{
__value = *__first;
*++__result = __value;
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index f5361ae..98c2249 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -918,52 +918,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
}
- /**
- * This is an uglified
- * unique_copy(_InputIterator, _InputIterator, _OutputIterator,
- * _BinaryPredicate)
- * overloaded for forward iterators and output iterator as result.
- */
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4269. unique_copy passes arguments to its predicate backwards
+
+ // Implementation of std::unique_copy for forward iterators.
+ // This case is easy, just compare *i with *(i-1).
template<typename _ForwardIterator, typename _OutputIterator,
typename _BinaryPredicate>
_GLIBCXX20_CONSTEXPR
_OutputIterator
__unique_copy(_ForwardIterator __first, _ForwardIterator __last,
_OutputIterator __result, _BinaryPredicate __binary_pred,
- forward_iterator_tag, output_iterator_tag)
+ forward_iterator_tag)
{
- _ForwardIterator __next = __first;
+ _ForwardIterator __prev = __first;
*__result = *__first;
- while (++__next != __last)
- if (!__binary_pred(__first, __next))
+ while (++__first != __last)
+ if (!__binary_pred(__prev, __first))
{
- __first = __next;
*++__result = *__first;
+ __prev = __first;
}
return ++__result;
}
- /**
- * This is an uglified
- * unique_copy(_InputIterator, _InputIterator, _OutputIterator,
- * _BinaryPredicate)
- * overloaded for input iterators and output iterator as result.
- */
+ // Implementation of std::unique_copy for non-forward iterators,
+ // where we cannot compare with elements written to the output.
template<typename _InputIterator, typename _OutputIterator,
typename _BinaryPredicate>
_GLIBCXX20_CONSTEXPR
_OutputIterator
- __unique_copy(_InputIterator __first, _InputIterator __last,
- _OutputIterator __result, _BinaryPredicate __binary_pred,
- input_iterator_tag, output_iterator_tag)
+ __unique_copy_1(_InputIterator __first, _InputIterator __last,
+ _OutputIterator __result, _BinaryPredicate __binary_pred,
+ __false_type)
{
- typename iterator_traits<_InputIterator>::value_type __value = *__first;
- __decltype(__gnu_cxx::__ops::__iter_comp_val(__binary_pred))
- __rebound_pred
- = __gnu_cxx::__ops::__iter_comp_val(__binary_pred);
+ typedef typename iterator_traits<_InputIterator>::value_type _Val;
+ _Val __value = *__first;
*__result = __value;
while (++__first != __last)
- if (!__rebound_pred(__first, __value))
+ if (!__binary_pred(std::__addressof(__value), __first))
{
__value = *__first;
*++__result = __value;
@@ -971,19 +964,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return ++__result;
}
- /**
- * This is an uglified
- * unique_copy(_InputIterator, _InputIterator, _OutputIterator,
- * _BinaryPredicate)
- * overloaded for input iterators and forward iterator as result.
- */
+ // Implementation of std::unique_copy for non-forward iterators,
+ // where we can compare with the last element written to the output.
template<typename _InputIterator, typename _ForwardIterator,
typename _BinaryPredicate>
- _GLIBCXX20_CONSTEXPR
_ForwardIterator
- __unique_copy(_InputIterator __first, _InputIterator __last,
- _ForwardIterator __result, _BinaryPredicate __binary_pred,
- input_iterator_tag, forward_iterator_tag)
+ __unique_copy_1(_InputIterator __first, _InputIterator __last,
+ _ForwardIterator __result, _BinaryPredicate __binary_pred,
+ __true_type)
{
*__result = *__first;
while (++__first != __last)
@@ -992,6 +980,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return ++__result;
}
+ // Implementation of std::unique_copy for non-forward iterators.
+ // We cannot compare *i to *(i-1) so we need to either make a copy
+ // or compare with the last element written to the output range.
+ template<typename _InputIterator, typename _OutputIterator,
+ typename _BinaryPredicate>
+ _GLIBCXX20_CONSTEXPR
+ _OutputIterator
+ __unique_copy(_InputIterator __first, _InputIterator __last,
+ _OutputIterator __result, _BinaryPredicate __binary_pred,
+ input_iterator_tag)
+ {
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2439. unique_copy() sometimes can't fall back to reading its output
+ typedef iterator_traits<_InputIterator> _InItTraits;
+ typedef iterator_traits<_OutputIterator> _OutItTraits;
+ typedef typename _OutItTraits::iterator_category _Cat;
+ const bool __output_is_fwd = __is_base_of(forward_iterator_tag, _Cat);
+ const bool __same_type = __is_same(typename _OutItTraits::value_type,
+ typename _InItTraits::value_type);
+ typedef __truth_type<__output_is_fwd && __same_type> __cmp_with_output;
+ return std::__unique_copy_1(__first, __last, __result, __binary_pred,
+ typename __cmp_with_output::__type());
+ }
+
+
/**
* This is an uglified reverse(_BidirectionalIterator,
* _BidirectionalIterator)
@@ -4456,8 +4469,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
return __result;
return std::__unique_copy(__first, __last, __result,
__gnu_cxx::__ops::__iter_equal_to_iter(),
- std::__iterator_category(__first),
- std::__iterator_category(__result));
+ std::__iterator_category(__first));
}
/**
@@ -4499,8 +4511,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
return __result;
return std::__unique_copy(__first, __last, __result,
__gnu_cxx::__ops::__iter_comp_iter(__binary_pred),
- std::__iterator_category(__first),
- std::__iterator_category(__result));
+ std::__iterator_category(__first));
}
#if __cplusplus <= 201103L || _GLIBCXX_USE_DEPRECATED
diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h
index 8d8ee57..7055641 100644
--- a/libstdc++-v3/include/bits/stl_deque.h
+++ b/libstdc++-v3/include/bits/stl_deque.h
@@ -1331,7 +1331,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
size_type __sz = this->_M_impl._M_finish - this->_M_impl._M_start;
if (__sz > max_size ())
- __builtin_unreachable ();
+ __builtin_unreachable();
return __sz;
}
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index 625c1c9..f2c1bce 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -372,8 +372,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX20_CONSTEXPR
~_Vector_base() _GLIBCXX_NOEXCEPT
{
- _M_deallocate(_M_impl._M_start,
- _M_impl._M_end_of_storage - _M_impl._M_start);
+ ptrdiff_t __n = _M_impl._M_end_of_storage - _M_impl._M_start;
+ if (__n < 0)
+ __builtin_unreachable();
+ _M_deallocate(_M_impl._M_start, size_t(__n));
}
public:
@@ -1106,7 +1108,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
ptrdiff_t __dif = this->_M_impl._M_finish - this->_M_impl._M_start;
if (__dif < 0)
- __builtin_unreachable ();
+ __builtin_unreachable();
return size_type(__dif);
}
@@ -1198,7 +1200,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
ptrdiff_t __dif = this->_M_impl._M_end_of_storage
- this->_M_impl._M_start;
if (__dif < 0)
- __builtin_unreachable ();
+ __builtin_unreachable();
return size_type(__dif);
}
diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc
index e18f01a..70ead1d 100644
--- a/libstdc++-v3/include/bits/vector.tcc
+++ b/libstdc++-v3/include/bits/vector.tcc
@@ -466,7 +466,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
const size_type __len = _M_check_len(1u, "vector::_M_realloc_insert");
if (__len <= 0)
- __builtin_unreachable ();
+ __builtin_unreachable();
pointer __old_start = this->_M_impl._M_start;
pointer __old_finish = this->_M_impl._M_finish;
const size_type __elems_before = __position - begin();
@@ -573,10 +573,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
const size_type __len = _M_check_len(1u, "vector::_M_realloc_append");
if (__len <= 0)
- __builtin_unreachable ();
+ __builtin_unreachable();
pointer __old_start = this->_M_impl._M_start;
pointer __old_finish = this->_M_impl._M_finish;
- const size_type __elems = end() - begin();
+ const size_type __elems = size();
pointer __new_start(this->_M_allocate(__len));
pointer __new_finish(__new_start);
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 9ab14a0..5efe4d1 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1978,6 +1978,15 @@ ftms = {
};
};
+ftms = {
+ name = polymorphic;
+ values = {
+ v = 202502;
+ cxxmin = 26;
+ hosted = yes;
+ };
+};
+
// Standard test specifications.
stds[97] = ">= 199711L";
stds[03] = ">= 199711L";
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 3358e84..5e905da 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -2213,4 +2213,14 @@
#endif /* !defined(__cpp_lib_indirect) && defined(__glibcxx_want_indirect) */
#undef __glibcxx_want_indirect
+#if !defined(__cpp_lib_polymorphic)
+# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED
+# define __glibcxx_polymorphic 202502L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_polymorphic)
+# define __cpp_lib_polymorphic 202502L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_polymorphic) && defined(__glibcxx_want_polymorphic) */
+#undef __glibcxx_want_polymorphic
+
#undef __glibcxx_want_all
diff --git a/libstdc++-v3/include/std/bit b/libstdc++-v3/include/std/bit
index 5187c96..fd75edf 100644
--- a/libstdc++-v3/include/std/bit
+++ b/libstdc++-v3/include/std/bit
@@ -166,7 +166,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Variant for power of two _Nd which the compiler can
// easily pattern match.
constexpr unsigned __uNd = _Nd;
- const unsigned __r = __s;
+ const auto __r = static_cast<unsigned>(__s);
return (__x << (__r % __uNd)) | (__x >> ((-__r) % __uNd));
}
const int __r = __s % _Nd;
@@ -188,7 +188,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Variant for power of two _Nd which the compiler can
// easily pattern match.
constexpr unsigned __uNd = _Nd;
- const unsigned __r = __s;
+ const auto __r = static_cast<unsigned>(__s);
return (__x >> (__r % __uNd)) | (__x << ((-__r) % __uNd));
}
const int __r = __s % _Nd;
diff --git a/libstdc++-v3/include/std/memory b/libstdc++-v3/include/std/memory
index d64e65c..1da03b3 100644
--- a/libstdc++-v3/include/std/memory
+++ b/libstdc++-v3/include/std/memory
@@ -113,6 +113,7 @@
#define __glibcxx_want_make_unique
#define __glibcxx_want_out_ptr
#define __glibcxx_want_parallel_algorithm
+#define __glibcxx_want_polymorphic
#define __glibcxx_want_ranges
#define __glibcxx_want_raw_memory_algorithms
#define __glibcxx_want_shared_ptr_arrays
diff --git a/libstdc++-v3/include/std/stop_token b/libstdc++-v3/include/std/stop_token
index 1225b3a..775ec6a 100644
--- a/libstdc++-v3/include/std/stop_token
+++ b/libstdc++-v3/include/std/stop_token
@@ -34,8 +34,7 @@
#define __glibcxx_want_jthread
#include <bits/version.h>
-#if __cplusplus > 201703L
-
+#ifdef __glibcxx_jthread // C++ >= 20
#include <atomic>
#include <bits/std_thread.h>
@@ -650,6 +649,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
stop_callback(stop_token, _Callback) -> stop_callback<_Callback>;
_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
-#endif // __cplusplus > 201703L
+} // namespace std
+#endif // __glibcxx_jthread
#endif // _GLIBCXX_STOP_TOKEN
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 6bf355d..c8907fe 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -1039,6 +1039,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Destructible and constructible type properties.
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_destructible)
+ /// is_destructible
+ template<typename _Tp>
+ struct is_destructible
+ : public __bool_constant<__is_destructible(_Tp)>
+ { };
+#else
// In N3290 is_destructible does not say anything about function
// types and abstract types, see LWG 2049. This implementation
// describes function types as non-destructible and all complete
@@ -1090,7 +1097,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
+#endif
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_destructible)
+ /// is_nothrow_destructible
+ template<typename _Tp>
+ struct is_nothrow_destructible
+ : public __bool_constant<__is_nothrow_destructible(_Tp)>
+ { };
+#else
/// @cond undocumented
// is_nothrow_destructible requires that is_destructible is
@@ -1144,6 +1159,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
+#endif
/// @cond undocumented
template<typename _Tp, typename... _Args>
@@ -1451,6 +1467,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
"template argument must be a complete class or an unbounded array");
};
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_trivially_destructible)
+ /// is_trivially_destructible
+ template<typename _Tp>
+ struct is_trivially_destructible
+ : public __bool_constant<__is_trivially_destructible(_Tp)>
+ { };
+#else
/// is_trivially_destructible
template<typename _Tp>
struct is_trivially_destructible
@@ -1460,7 +1483,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
-
+#endif
/// has_virtual_destructor
template<typename _Tp>
@@ -3581,8 +3604,13 @@ template <typename _Tp>
inline constexpr bool is_move_assignable_v
= __is_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>);
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_destructible)
+template <typename _Tp>
+ inline constexpr bool is_destructible_v = __is_destructible(_Tp);
+#else
template <typename _Tp>
inline constexpr bool is_destructible_v = is_destructible<_Tp>::value;
+#endif
template <typename _Tp, typename... _Args>
inline constexpr bool is_trivially_constructible_v
@@ -3609,7 +3637,11 @@ template <typename _Tp>
= __is_trivially_assignable(__add_lval_ref_t<_Tp>,
__add_rval_ref_t<_Tp>);
-#if __cpp_concepts
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_trivially_destructible)
+template <typename _Tp>
+ inline constexpr bool is_trivially_destructible_v
+ = __is_trivially_destructible(_Tp);
+#elif __cpp_concepts
template <typename _Tp>
inline constexpr bool is_trivially_destructible_v = false;
@@ -3654,9 +3686,15 @@ template <typename _Tp>
inline constexpr bool is_nothrow_move_assignable_v
= __is_nothrow_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>);
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_destructible)
+template <typename _Tp>
+ inline constexpr bool is_nothrow_destructible_v
+ = __is_nothrow_destructible(_Tp);
+#else
template <typename _Tp>
inline constexpr bool is_nothrow_destructible_v =
is_nothrow_destructible<_Tp>::value;
+#endif
template <typename _Tp>
inline constexpr bool has_virtual_destructor_v
diff --git a/libstdc++-v3/src/c++20/atomic.cc b/libstdc++-v3/src/c++20/atomic.cc
index a3ec92a..4120e1a 100644
--- a/libstdc++-v3/src/c++20/atomic.cc
+++ b/libstdc++-v3/src/c++20/atomic.cc
@@ -397,17 +397,18 @@ __cond_wait_until(__condvar& __cv, mutex& __mx,
}
#endif // ! HAVE_PLATFORM_TIMED_WAIT
-// Like __spin_impl, always returns _M_has_val == true.
+// Unlike __spin_impl, does not always return _M_has_val == true.
+// If the deadline has already passed then no fresh value is loaded.
__wait_result_type
__spin_until_impl(const __platform_wait_t* __addr,
const __wait_args_base& __args,
const __wait_clock_t::time_point& __deadline)
{
- auto __t0 = __wait_clock_t::now();
using namespace literals::chrono_literals;
- __platform_wait_t __val{};
- auto __now = __wait_clock_t::now();
+ __wait_result_type __res{};
+ auto __t0 = __wait_clock_t::now();
+ auto __now = __t0;
for (; __now < __deadline; __now = __wait_clock_t::now())
{
auto __elapsed = __now - __t0;
@@ -422,16 +423,21 @@ __spin_until_impl(const __platform_wait_t* __addr,
__thread_yield();
else
{
- auto __res = __detail::__spin_impl(__addr, __args);
+ __res = __detail::__spin_impl(__addr, __args);
if (!__res._M_timeout)
return __res;
}
- __atomic_load(__addr, &__val, __args._M_order);
- if (__val != __args._M_old)
- return { ._M_val = __val, ._M_has_val = true, ._M_timeout = false };
+ __atomic_load(__addr, &__res._M_val, __args._M_order);
+ __res._M_has_val = true;
+ if (__res._M_val != __args._M_old)
+ {
+ __res._M_timeout = false;
+ return __res;
+ }
}
- return { ._M_val = __val, ._M_has_val = true, ._M_timeout = true };
+ __res._M_timeout = true;
+ return __res;
}
} // namespace
diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in
index ba46853..eddd3c8 100644
--- a/libstdc++-v3/src/c++23/std.cc.in
+++ b/libstdc++-v3/src/c++23/std.cc.in
@@ -511,7 +511,6 @@ export namespace std
}
// 22.7.2 <any>
-#if __cpp_lib_any
export namespace std
{
using std::any;
@@ -520,7 +519,6 @@ export namespace std
using std::make_any;
using std::swap;
}
-#endif
// 24.3.2 <array>
export namespace std
@@ -698,7 +696,6 @@ export namespace std
}
// 29.2 <chrono>
-#if __cpp_lib_chrono
export namespace std
{
namespace chrono
@@ -852,7 +849,6 @@ export namespace std::inline literals::inline chrono_literals
export namespace std::chrono {
using namespace literals::chrono_literals;
}
-#endif // __cpp_lib_chrono
// <codecvt>: deprecated C++17, removed C++26
export namespace std
@@ -864,7 +860,6 @@ export namespace std
}
// 17.11.1 <compare>
-#if __cpp_lib_three_way_comparison
export namespace std
{
using std::common_comparison_category;
@@ -890,7 +885,6 @@ export namespace std
using std::strong_order;
using std::weak_order;
}
-#endif // __cpp_lib_three_way_comparison
// 28.4 <complex>
export namespace std
@@ -944,7 +938,6 @@ export namespace std::inline literals::inline complex_literals
}
// 18 <concepts>
-#if __cpp_lib_concepts
export namespace std
{
using std::assignable_from;
@@ -983,7 +976,6 @@ export namespace std
using std::totally_ordered;
using std::totally_ordered_with;
}
-#endif
// 33.7 <condition_variable>
export namespace std
diff --git a/libstdc++-v3/testsuite/20_util/copyable_function/call.cc b/libstdc++-v3/testsuite/20_util/copyable_function/call.cc
index cf99757..0ac5348 100644
--- a/libstdc++-v3/testsuite/20_util/copyable_function/call.cc
+++ b/libstdc++-v3/testsuite/20_util/copyable_function/call.cc
@@ -204,13 +204,14 @@ test05()
}
struct Incomplete;
+enum CompleteEnum : int;
void
test_params()
{
- std::copyable_function<void(Incomplete)> f1;
- std::copyable_function<void(Incomplete&)> f2;
- std::copyable_function<void(Incomplete&&)> f3;
+ std::copyable_function<void(Incomplete&)> f1;
+ std::copyable_function<void(Incomplete&&)> f2;
+ std::copyable_function<void(CompleteEnum)> f4;
}
int main()
diff --git a/libstdc++-v3/testsuite/20_util/copyable_function/conv.cc b/libstdc++-v3/testsuite/20_util/copyable_function/conv.cc
index e678e16..11c839b 100644
--- a/libstdc++-v3/testsuite/20_util/copyable_function/conv.cc
+++ b/libstdc++-v3/testsuite/20_util/copyable_function/conv.cc
@@ -2,6 +2,7 @@
// { dg-require-effective-target hosted }
#include <functional>
+#include <string_view>
#include <testsuite_hooks.h>
using std::copyable_function;
@@ -15,6 +16,21 @@ static_assert( !std::is_constructible_v<std::copyable_function<void()&>,
static_assert( !std::is_constructible_v<std::copyable_function<void() const>,
std::copyable_function<void()>> );
+using FuncType = int(int);
+
+// Top level const qualifiers are ignored and decay is performed in parameters
+// of function_types.
+static_assert( std::is_same_v<std::copyable_function<void(int const)>,
+ std::copyable_function<void(int)>> );
+static_assert( std::is_same_v<std::copyable_function<void(int[2])>,
+ std::copyable_function<void(int*)>>);
+static_assert( std::is_same_v<std::copyable_function<void(int[])>,
+ std::copyable_function<void(int*)>>);
+static_assert( std::is_same_v<std::copyable_function<void(int const[5])>,
+ std::copyable_function<void(int const*)>>);
+static_assert( std::is_same_v<std::copyable_function<void(FuncType)>,
+ std::copyable_function<void(FuncType*)>>);
+
// Non-trivial args, guarantess that type is not passed by copy
struct CountedArg
{
@@ -240,6 +256,24 @@ test06()
VERIFY( f2(c) == 2 );
}
+void
+test07()
+{
+ // Scalar types and small trivially move constructible types are passed
+ // by value to invoker. So int&& signature is not compatible for such types.
+ auto fi = [](CountedArg const& arg, int) noexcept { return arg.counter; };
+ std::copyable_function<int(CountedArg, int) const noexcept> ci1(fi);
+ VERIFY( ci1(c, 0) == 1 );
+ std::copyable_function<int(CountedArg, int&&) const noexcept> ci2(ci1);
+ VERIFY( ci2(c, 0) == 2 );
+
+ auto fs = [](CountedArg const& arg, std::string_view) noexcept { return arg.counter; };
+ std::copyable_function<int(CountedArg, std::string_view) const noexcept> cs1(fs);
+ VERIFY( cs1(c, "") == 1 );
+ std::copyable_function<int(CountedArg, std::string_view&&) const noexcept> cs2(cs1);
+ VERIFY( cs2(c, "") == 2 );
+}
+
int main()
{
test01();
@@ -248,4 +282,5 @@ int main()
test04();
test05();
test06();
+ test07();
}
diff --git a/libstdc++-v3/testsuite/20_util/copyable_function/incomplete_neg.cc b/libstdc++-v3/testsuite/20_util/copyable_function/incomplete_neg.cc
new file mode 100644
index 0000000..21ddde0
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/copyable_function/incomplete_neg.cc
@@ -0,0 +1,18 @@
+// { dg-do compile { target c++26 } }
+
+#include <functional>
+
+struct IncompleteClass;
+
+using T1 = std::copyable_function<int(IncompleteClass)>::result_type; // { dg-error "here" }
+using T2 = std::copyable_function<int(int, IncompleteClass)>::result_type; // { dg-error "here" }
+
+enum Enum {
+ x = [] {
+ // Enum enumeration is incomplete here
+ using T3 = std::copyable_function<int(Enum)>::result_type; // { dg-error "here" }
+ return T3(1);
+ }()
+};
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/20_util/function_ref/call.cc b/libstdc++-v3/testsuite/20_util/function_ref/call.cc
index a91c6b4..23253c3 100644
--- a/libstdc++-v3/testsuite/20_util/function_ref/call.cc
+++ b/libstdc++-v3/testsuite/20_util/function_ref/call.cc
@@ -164,16 +164,16 @@ test05()
}
struct Incomplete;
+enum CompleteEnum : int;
void
test_params()
{
auto f = [](auto&&) {};
- // There is discussion if this is supported.
- // std::function_ref<void(Incomplete)> f1(f);
- std::function_ref<void(Incomplete&)> f2(f);
- // See PR120259, this should be supported.
- // std::function_ref<void(Incomplete&&)> f3(f);
+ std::function_ref<void(Incomplete&)> f1(f);
+ // See PR libstdc++/120259, this should be supported.
+ // std::function_ref<void(Incomplete&&)> f2(f);
+ std::function_ref<void(CompleteEnum)> f3(f);
}
int main()
diff --git a/libstdc++-v3/testsuite/20_util/function_ref/conv.cc b/libstdc++-v3/testsuite/20_util/function_ref/conv.cc
index 7dc7b8c..7606d26 100644
--- a/libstdc++-v3/testsuite/20_util/function_ref/conv.cc
+++ b/libstdc++-v3/testsuite/20_util/function_ref/conv.cc
@@ -2,6 +2,7 @@
// { dg-require-effective-target hosted }
#include <functional>
+#include <string_view>
#include <testsuite_hooks.h>
using std::function_ref;
@@ -20,6 +21,21 @@ struct CountedArg
};
CountedArg const c;
+using FuncType = int(int);
+
+// Top level const qualifiers are ignored in function types, and decay
+// is performed.
+static_assert( std::is_same_v<std::function_ref<void(int const)>,
+ std::function_ref<void(int)>> );
+static_assert( std::is_same_v<std::function_ref<void(int[2])>,
+ std::function_ref<void(int*)>>);
+static_assert( std::is_same_v<std::function_ref<void(int[])>,
+ std::function_ref<void(int*)>>);
+static_assert( std::is_same_v<std::function_ref<void(int const[5])>,
+ std::function_ref<void(int const*)>>);
+static_assert( std::is_same_v<std::function_ref<void(FuncType)>,
+ std::function_ref<void(FuncType*)>>);
+
// The C++26 [func.wrap.general] p2 does not currently cover funciton_ref,
// so we make extra copies of arguments.
@@ -244,6 +260,23 @@ test08()
return true;
};
+void
+test09()
+{
+ // Scalar types and small trivially move constructible types are passed
+ // by value to invoker. So int&& signature is not compatible for such types.
+ auto fi = [](CountedArg const& arg, int) noexcept { return arg.counter; };
+ std::function_ref<int(CountedArg, int) const noexcept> ri1(fi);
+ VERIFY( ri1(c, 0) == 1 );
+ std::function_ref<int(CountedArg, int&&) const noexcept> ri2(ri1);
+ VERIFY( ri2(c, 0) == 2 );
+
+ auto fs = [](CountedArg const& arg, std::string_view) noexcept { return arg.counter; };
+ std::function_ref<int(CountedArg, std::string_view) const noexcept> rs1(fs);
+ VERIFY( rs1(c, "") == 1 );
+ std::function_ref<int(CountedArg, std::string_view&&) const noexcept> rs2(rs1);
+ VERIFY( rs2(c, "") == 2 );
+}
int main()
{
@@ -254,6 +287,7 @@ int main()
test05();
test06();
test07();
+ test09();
static_assert( test08() );
}
diff --git a/libstdc++-v3/testsuite/20_util/function_ref/incomplete_neg.cc b/libstdc++-v3/testsuite/20_util/function_ref/incomplete_neg.cc
new file mode 100644
index 0000000..c8db1ee
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/function_ref/incomplete_neg.cc
@@ -0,0 +1,18 @@
+// { dg-do compile { target c++26 } }
+
+#include <functional>
+
+struct IncompleteClass;
+
+int a1 = alignof(std::function_ref<int(IncompleteClass)>); // { dg-error "here" }
+int a2 = alignof(std::function_ref<int(int, IncompleteClass)>); // { dg-error "here" }
+
+enum Enum {
+ x = [] {
+ // Enum enumeration is incomplete here
+ int a3 = alignof(std::function_ref<int(Enum)>); // { dg-error "here" }
+ return 1;
+ }()
+};
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/20_util/move_only_function/call.cc b/libstdc++-v3/testsuite/20_util/move_only_function/call.cc
index 217de37..72c8118 100644
--- a/libstdc++-v3/testsuite/20_util/move_only_function/call.cc
+++ b/libstdc++-v3/testsuite/20_util/move_only_function/call.cc
@@ -204,13 +204,14 @@ test05()
}
struct Incomplete;
+enum CompleteEnum : int;
void
test_params()
{
- std::move_only_function<void(Incomplete)> f1;
- std::move_only_function<void(Incomplete&)> f2;
- std::move_only_function<void(Incomplete&&)> f3;
+ std::move_only_function<void(Incomplete&)> f1;
+ std::move_only_function<void(Incomplete&&)> f2;
+ std::move_only_function<void(CompleteEnum)> f4;
}
int main()
diff --git a/libstdc++-v3/testsuite/20_util/move_only_function/conv.cc b/libstdc++-v3/testsuite/20_util/move_only_function/conv.cc
index 3da5e9e..ef8bb37b 100644
--- a/libstdc++-v3/testsuite/20_util/move_only_function/conv.cc
+++ b/libstdc++-v3/testsuite/20_util/move_only_function/conv.cc
@@ -2,6 +2,7 @@
// { dg-require-effective-target hosted }
#include <functional>
+#include <string_view>
#include <testsuite_hooks.h>
using std::move_only_function;
@@ -15,6 +16,21 @@ static_assert( !std::is_constructible_v<std::move_only_function<void()&>,
static_assert( !std::is_constructible_v<std::move_only_function<void() const>,
std::move_only_function<void()>> );
+using FuncType = int(int);
+
+// Top level const qualifiers are ignored in function types, and decay
+// is performed.
+static_assert( std::is_same_v<std::move_only_function<void(int const)>,
+ std::move_only_function<void(int)>> );
+static_assert( std::is_same_v<std::move_only_function<void(int[2])>,
+ std::move_only_function<void(int*)>>);
+static_assert( std::is_same_v<std::move_only_function<void(int[])>,
+ std::move_only_function<void(int*)>>);
+static_assert( std::is_same_v<std::move_only_function<void(int const[5])>,
+ std::move_only_function<void(int const*)>>);
+static_assert( std::is_same_v<std::move_only_function<void(FuncType)>,
+ std::move_only_function<void(FuncType*)>>);
+
// Non-trivial args, guarantess that type is not passed by copy
struct CountedArg
{
@@ -177,6 +193,24 @@ test06()
VERIFY( m1(c) == 2 );
}
+void
+test07()
+{
+ // Scalar types and small trivially move constructible types are passed
+ // by value to invoker. So int&& signature is not compatible for such types.
+ auto fi = [](CountedArg const& arg, int) noexcept { return arg.counter; };
+ std::move_only_function<int(CountedArg, int) const noexcept> mi1(fi);
+ VERIFY( mi1(c, 0) == 1 );
+ std::move_only_function<int(CountedArg, int&&) const noexcept> mi2(std::move(mi1));
+ VERIFY( mi2(c, 0) == 2 );
+
+ auto fs = [](CountedArg const& arg, std::string_view) noexcept { return arg.counter; };
+ std::move_only_function<int(CountedArg, std::string_view) const noexcept> ms1(fs);
+ VERIFY( ms1(c, "") == 1 );
+ std::move_only_function<int(CountedArg, std::string_view&&) const noexcept> ms2(std::move(ms1));
+ VERIFY( ms2(c, "") == 2 );
+}
+
int main()
{
test01();
@@ -185,4 +219,5 @@ int main()
test04();
test05();
test06();
+ test07();
}
diff --git a/libstdc++-v3/testsuite/20_util/move_only_function/incomplete_neg.cc b/libstdc++-v3/testsuite/20_util/move_only_function/incomplete_neg.cc
new file mode 100644
index 0000000..d025c47
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/move_only_function/incomplete_neg.cc
@@ -0,0 +1,18 @@
+// { dg-do compile { target c++23 } }
+
+#include <functional>
+
+struct IncompleteClass;
+
+using T1 = std::move_only_function<int(IncompleteClass)>::result_type; // { dg-error "here" }
+using T2 = std::move_only_function<int(int, IncompleteClass)>::result_type; // { dg-error "here" }
+
+enum Enum {
+ x = [] {
+ // Enum enumeration is incomplete here
+ using T3 = std::move_only_function<int(Enum)>::result_type; // { dg-error "here" }
+ return T3(1);
+ }()
+};
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/25_algorithms/unique_copy/lwg2439.cc b/libstdc++-v3/testsuite/25_algorithms/unique_copy/lwg2439.cc
new file mode 100644
index 0000000..f2ec3e3
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/unique_copy/lwg2439.cc
@@ -0,0 +1,127 @@
+// { dg-do run }
+
+#include <algorithm>
+#include <testsuite_iterators.h>
+
+using namespace __gnu_test;
+
+int out[4];
+short out_shrt[4];
+short in[7] = { 1, 2, 2, 2, 3, 4, 4 };
+
+template<typename T>
+void
+check_and_reset(T* p)
+{
+ VERIFY( p[0] == 1 );
+ VERIFY( p[1] == 2 );
+ VERIFY( p[2] == 3 );
+ VERIFY( p[3] == 4 );
+ std::fill_n(p, 4, 0);
+}
+
+struct Eq
+{
+ bool operator()(short i, short j) const { return i == j; }
+ bool operator()(short, int) const { VERIFY(false); }
+ bool operator()(int, short) const { VERIFY(false); }
+};
+
+struct Eq2
+{
+ bool operator()(const short& i, const short& j) const
+ {
+ // Both arguments should be elements of the 'in' array.
+ VERIFY( in+0 <= &i && &i < in+7 );
+ VERIFY( in+0 <= &j && &j < in+7 );
+ VERIFY( &i < &j );
+ return i == j;
+ }
+ bool operator()(short, int) const { VERIFY(false); }
+ bool operator()(int, short) const { VERIFY(false); }
+};
+
+struct Eq3
+{
+ bool operator()(const short& i, const short& j) const
+ {
+ // First argument should be element of the 'out' array.
+ // Second argument should be element of the 'in' array.
+ VERIFY( out_shrt+0 <= &i && &i < out_shrt+4 );
+ VERIFY( in+0 <= &j && &j < in+7 );
+ return i == j;
+ }
+ bool operator()(short, int) const { VERIFY(false); }
+ bool operator()(int, short) const { VERIFY(false); }
+};
+
+void
+test_forward_source()
+{
+ // The input range uses forward iterators
+ test_container<short, forward_iterator_wrapper> inc(in);
+ test_container<int, output_iterator_wrapper> outc(out);
+ std::unique_copy(inc.begin(), inc.end(), outc.begin());
+ check_and_reset(out);
+
+ test_container<short, forward_iterator_wrapper> inc2(in);
+ test_container<int, output_iterator_wrapper> outc2(out);
+ std::unique_copy(inc2.begin(), inc2.end(), outc2.begin(), Eq2());
+ check_and_reset(out);
+}
+
+void
+test_output_dest()
+{
+ // The input range uses input iterators.
+ // The output range uses output iterators.
+ test_container<short, input_iterator_wrapper> inc(in);
+ test_container<int, output_iterator_wrapper> outc(out);
+ std::unique_copy(inc.begin(), inc.end(), outc.begin());
+ check_and_reset(out);
+
+ test_container<short, input_iterator_wrapper> inc2(in);
+ test_container<int, output_iterator_wrapper> outc2(out);
+ std::unique_copy(inc2.begin(), inc2.end(), outc2.begin(), Eq());
+ check_and_reset(out);
+}
+
+void
+test_forward_dest_diff_type()
+{
+ // The input range uses input iterators.
+ // The output range uses forward iterators, but with different value type.
+ test_container<short, input_iterator_wrapper> inc(in);
+ test_container<int, forward_iterator_wrapper> outc(out);
+ std::unique_copy(inc.begin(), inc.end(), outc.begin());
+ check_and_reset(out);
+
+ test_container<short, input_iterator_wrapper> inc2(in);
+ test_container<int, forward_iterator_wrapper> outc2(out);
+ std::unique_copy(inc2.begin(), inc2.end(), outc2.begin(), Eq());
+ check_and_reset(out);
+}
+
+void
+test_forward_dest_same_type()
+{
+ // The input range uses input iterators.
+ // The output range uses forward iterators, with same value type.
+ test_container<short, input_iterator_wrapper> inc(in);
+ test_container<short, forward_iterator_wrapper> outc(out_shrt);
+ std::unique_copy(inc.begin(), inc.end(), outc.begin());
+ check_and_reset(out_shrt);
+
+ test_container<short, input_iterator_wrapper> inc2(in);
+ test_container<short, forward_iterator_wrapper> outc2(out_shrt);
+ std::unique_copy(inc2.begin(), inc2.end(), outc2.begin(), Eq3());
+ check_and_reset(out_shrt);
+}
+
+int main()
+{
+ test_forward_source();
+ test_output_dest();
+ test_forward_dest_diff_type();
+ test_forward_dest_same_type();
+}
diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/copy.cc b/libstdc++-v3/testsuite/std/memory/polymorphic/copy.cc
new file mode 100644
index 0000000..bea05ac
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/memory/polymorphic/copy.cc
@@ -0,0 +1,157 @@
+// { dg-do run { target c++26 } }
+
+#include <memory>
+#include <scoped_allocator>
+#include <utility>
+#include <vector>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct Base {
+ friend constexpr
+ bool operator==(const Base& lhs, const Base& rhs)
+ { return lhs.eq(rhs); }
+
+private:
+ constexpr virtual bool
+ eq(const Base& other) const = 0;
+};
+
+struct Derived : Base
+{
+ constexpr Derived()
+ : x(0), y(0), z(0)
+ { }
+
+ constexpr Derived(int a, int b, int c)
+ : x(a), y(b), z(c)
+ { }
+
+private:
+ constexpr bool
+ eq(const Base& other) const override
+ {
+ if (auto op = dynamic_cast<const Derived*>(&other))
+ return this->x == op->x && this->y == op->y && this->z == op->z;
+ return false;
+ }
+
+ int x;
+ int y;
+ int z;
+};
+
+using __gnu_test::tracker_allocator;
+using Counter = __gnu_test::tracker_allocator_counter;
+using Polymorhic = std::polymorphic<Base, tracker_allocator<Base>>;
+const Polymorhic src(std::in_place_type<Derived>, 1, 2, 3);
+
+constexpr void
+test_ctor()
+{
+ Counter::reset();
+ Polymorhic i1(src);
+ VERIFY( *i1 == *src );
+ VERIFY( &*i1 != &*src );
+ VERIFY( Counter::get_allocation_count() >= sizeof(Derived) );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 2 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+
+ Counter::reset();
+ Polymorhic i2(std::allocator_arg, {}, src);
+ VERIFY( *i2 == *src );
+ VERIFY( &*i2 != &*src );
+ VERIFY( Counter::get_allocation_count() >= sizeof(Derived) );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 2 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+}
+
+constexpr void
+test_assign()
+{
+ Counter::reset();
+ Polymorhic i1(std::in_place_type<Derived>);
+ const size_t holderSize = Counter::get_allocation_count();
+ VERIFY( holderSize >= sizeof(Derived) );
+ Counter::reset();
+
+ i1 = src;
+ VERIFY( *i1 == *src );
+ VERIFY( &*i1 != &*src );
+ VERIFY( Counter::get_allocation_count() == holderSize );
+ VERIFY( Counter::get_deallocation_count() == holderSize );
+ VERIFY( Counter::get_construct_count() == 2 );
+ VERIFY( Counter::get_destruct_count() == 1 );
+
+ auto(std::move(i1));
+ Counter::reset();
+
+ i1 = src;
+ VERIFY( *i1 == *src );
+ VERIFY( &*i1 != &*src );
+ VERIFY( Counter::get_allocation_count() == holderSize );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 2 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+}
+
+constexpr void
+test_valueless()
+{
+ Polymorhic e(std::in_place_type<Derived>);
+ auto(std::move(e));
+ VERIFY( e.valueless_after_move() );
+
+ Counter::reset();
+ Polymorhic i1(e);
+ VERIFY( i1.valueless_after_move() );
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+
+ Polymorhic i2(std::allocator_arg, {}, e);
+ VERIFY( i2.valueless_after_move() );
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+
+ Polymorhic i3(src);
+ Counter::reset();
+ i3 = e;
+ VERIFY( i3.valueless_after_move() );
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_deallocation_count() >= sizeof(Derived) );
+ VERIFY( Counter::get_construct_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 1 );
+
+ Counter::reset();
+ i3 = e;
+ VERIFY( i3.valueless_after_move() );
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+}
+
+constexpr void
+test_all()
+{
+ test_ctor();
+ test_assign();
+ test_valueless();
+}
+
+int main()
+{
+ test_all();
+
+ static_assert([] {
+ test_all();
+ return true;
+ });
+}
diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/copy_alloc.cc b/libstdc++-v3/testsuite/std/memory/polymorphic/copy_alloc.cc
new file mode 100644
index 0000000..f41c32e
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/memory/polymorphic/copy_alloc.cc
@@ -0,0 +1,270 @@
+// { dg-do run { target c++26 } }
+
+#include <memory>
+#include <scoped_allocator>
+#include <utility>
+#include <vector>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct Base {
+ friend constexpr
+ bool operator==(const Base& lhs, const Base& rhs)
+ { return lhs.eq(rhs); }
+
+ virtual constexpr int
+ get_alloc_personality() const
+ { return -1; }
+
+private:
+ constexpr virtual bool
+ eq(const Base& other) const = 0;
+};
+
+template<typename T, typename Allocator>
+struct VecDerived : Base, std::vector<T, Allocator>
+{
+ using VecBase = std::vector<T, Allocator>;
+
+ using VecBase::VecBase;
+
+ constexpr int
+ get_alloc_personality() const override
+ { return this->get_allocator().get_personality(); }
+
+private:
+
+ constexpr bool
+ eq(const Base& other) const override
+ {
+ if (auto op = dynamic_cast<const VecDerived*>(&other))
+ return *static_cast<const VecBase*>(this)
+ == *static_cast<const VecBase*>(op);
+ return false;
+ }
+};
+
+using __gnu_test::propagating_allocator;
+using __gnu_test::tracker_allocator;
+using Counter = __gnu_test::tracker_allocator_counter;
+
+template<bool Propagate>
+constexpr void
+test_ctor()
+{
+ using PropAlloc = propagating_allocator<int, Propagate>;
+ using Vector = VecDerived<int, PropAlloc>;
+ using ScopedAlloc = std::scoped_allocator_adaptor<
+ propagating_allocator<Vector, Propagate, tracker_allocator<Vector>>,
+ PropAlloc>;
+ using Polymorphic = std::polymorphic<Vector, ScopedAlloc>;
+
+ const Polymorphic src(std::allocator_arg, ScopedAlloc{11, 22},
+ std::in_place_type<Vector>, {1, 2, 3});
+
+ Counter::reset();
+ Polymorphic i1(src);
+ VERIFY( *i1 == *src );
+ VERIFY( &*i1 != &*src );
+ if (Propagate)
+ {
+ VERIFY( i1->get_alloc_personality() == 22 );
+ VERIFY( i1.get_allocator().get_personality() == 11 );
+ }
+ else
+ {
+ VERIFY( i1->get_alloc_personality() == 0 );
+ VERIFY( i1.get_allocator().get_personality() == 0 );
+ }
+ VERIFY( Counter::get_allocation_count() >= sizeof(Vector) );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 2 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+
+
+ Counter::reset();
+ Polymorphic i2(std::allocator_arg, ScopedAlloc{33, 44}, src);
+ VERIFY( *i2 == *src );
+ VERIFY( &*i2 != &*src );
+ VERIFY( i2->get_alloc_personality() == 44 );
+ VERIFY( i2.get_allocator().get_personality() == 33 );
+ VERIFY( Counter::get_allocation_count() >= sizeof(Vector) );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 2 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+}
+
+template<bool Propagate>
+constexpr void
+test_assign()
+{
+ using PropAlloc = propagating_allocator<int, Propagate>;
+ using Vector = VecDerived<int, PropAlloc>;
+ using ScopedAlloc = std::scoped_allocator_adaptor<
+ propagating_allocator<Vector, Propagate, tracker_allocator<Vector>>,
+ PropAlloc>;
+ using Polymorphic = std::polymorphic<Vector, ScopedAlloc>;
+
+ const Polymorphic src(std::allocator_arg, ScopedAlloc{11, 22},
+ std::in_place_type<Vector>, {1, 2, 3});
+
+ Counter::reset();
+ Polymorphic i1(std::allocator_arg, ScopedAlloc{11, 22},
+ std::in_place_type<Vector>);
+ const size_t holderSize = Counter::get_allocation_count();
+ VERIFY( holderSize >= sizeof(Vector) );
+ Counter::reset();
+
+ i1 = src;
+ VERIFY( *i1 == *src );
+ VERIFY( &*i1 != &*src );
+ VERIFY( i1->get_alloc_personality() == 22 );
+ VERIFY( i1.get_allocator().get_personality() == 11 );
+ VERIFY( Counter::get_allocation_count() == holderSize );
+ VERIFY( Counter::get_deallocation_count() == holderSize );
+ VERIFY( Counter::get_construct_count() == 2 );
+ VERIFY( Counter::get_destruct_count() == 1 );
+
+ Polymorphic i2(std::allocator_arg, ScopedAlloc{33, 44});
+ Counter::reset();
+
+ i2 = src;
+ VERIFY( *i2 == *src );
+ VERIFY( &*i2 != &*src );
+ if (Propagate)
+ {
+ VERIFY( i2->get_alloc_personality() == 22 );
+ VERIFY( i2.get_allocator().get_personality() == 11 );
+ }
+ else
+ {
+ VERIFY( i2->get_alloc_personality() == 44 );
+ VERIFY( i2.get_allocator().get_personality() == 33 );
+ }
+ VERIFY( Counter::get_allocation_count() == holderSize );
+ VERIFY( Counter::get_deallocation_count() == holderSize );
+ VERIFY( Counter::get_construct_count() == 2 );
+ VERIFY( Counter::get_destruct_count() == 1 );
+
+ Polymorphic i3(std::allocator_arg, ScopedAlloc{11, 22});
+ auto(std::move(i3));
+ Counter::reset();
+
+ i3 = src;
+ VERIFY( *i3 == *src );
+ VERIFY( &*i3 != &*src );
+ VERIFY( i3->get_alloc_personality() == 22 );
+ VERIFY( i3.get_allocator().get_personality() == 11 );
+ VERIFY( Counter::get_allocation_count() == holderSize );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 2 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+
+ Polymorphic i4(std::allocator_arg, ScopedAlloc{33, 44});
+ auto(std::move(i4));
+ Counter::reset();
+
+ i4 = src;
+ VERIFY( *i4 == *src );
+ VERIFY( &*i4 != &*src );
+ if (Propagate)
+ {
+ VERIFY( i4->get_alloc_personality() == 22 );
+ VERIFY( i4.get_allocator().get_personality() == 11 );
+ }
+ else
+ {
+ VERIFY( i4->get_alloc_personality() == 44 );
+ VERIFY( i4.get_allocator().get_personality() == 33 );
+ }
+ VERIFY( Counter::get_allocation_count() == holderSize );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 2 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+}
+
+template<bool Propagate>
+constexpr void
+test_valueless()
+{
+ using PropAlloc = propagating_allocator<int, Propagate>;
+ using Vector = VecDerived<int, PropAlloc>;
+ using ScopedAlloc = std::scoped_allocator_adaptor<
+ propagating_allocator<Vector, Propagate, tracker_allocator<Vector>>,
+ PropAlloc>;
+ using Polymorphic = std::polymorphic<Vector, ScopedAlloc>;
+
+ Polymorphic e(std::allocator_arg, ScopedAlloc{11, 22},
+ std::in_place_type<Vector>);
+ auto(std::move(e));
+ VERIFY( e.valueless_after_move() );
+
+ Counter::reset();
+ Polymorphic i1(e);
+ VERIFY( i1.valueless_after_move() );
+ if (Propagate)
+ VERIFY( i1.get_allocator().get_personality() == 11 );
+ else
+ VERIFY( i1.get_allocator().get_personality() == 0 );
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+
+ Counter::reset();
+ Polymorphic i2(std::allocator_arg, ScopedAlloc{33, 44}, e);
+ VERIFY( i2.valueless_after_move() );
+ VERIFY( i2.get_allocator().get_personality() == 33 );
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+
+ Polymorphic i3(std::allocator_arg, ScopedAlloc{33, 44});
+ Counter::reset();
+
+ i3 = e;
+ VERIFY( i3.valueless_after_move() );
+ if (Propagate)
+ VERIFY( i3.get_allocator().get_personality() == 11 );
+ else
+ VERIFY( i3.get_allocator().get_personality() == 33 );
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_deallocation_count() >= sizeof(Vector) );
+ VERIFY( Counter::get_construct_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 1 );
+
+ Counter::reset();
+ i2 = e;
+ VERIFY( i2.valueless_after_move() );
+ if (Propagate)
+ VERIFY( i2.get_allocator().get_personality() == 11 );
+ else
+ VERIFY( i2.get_allocator().get_personality() == 33 );
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+}
+
+template<bool Propagate>
+constexpr void
+test_all()
+{
+ test_ctor<Propagate>();
+ test_assign<Propagate>();
+ test_valueless<Propagate>();
+}
+
+int main()
+{
+ test_all<true>();
+ test_all<false>();
+
+ static_assert([] {
+ test_all<true>();
+ test_all<false>();
+ return true;
+ });
+}
diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/ctor.cc b/libstdc++-v3/testsuite/std/memory/polymorphic/ctor.cc
new file mode 100644
index 0000000..bb4c947
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/memory/polymorphic/ctor.cc
@@ -0,0 +1,190 @@
+// { dg-do run { target c++26 } }
+
+#include <memory>
+#include <scoped_allocator>
+#include <utility>
+#include <vector>
+
+#ifndef __cpp_lib_polymorphic
+# error __cpp_lib_polymorphic feature test macro missing in <memory>
+#elif __cpp_lib_polymorphic != 202502
+# error __cpp_lib_polymorphic feature test macro has wrong value in <memory>
+#endif
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+using UneqAlloc = uneq_allocator<int>;
+using ScopedAlloc = std::scoped_allocator_adaptor<
+ uneq_allocator<std::vector<int, UneqAlloc>>,
+ UneqAlloc>;
+
+struct Obj
+{
+ int i;
+ char c[2];
+};
+
+constexpr void
+test_default_ctor()
+{
+ using __gnu_test::default_init_allocator;
+
+ std::polymorphic<Obj, default_init_allocator<Obj>> i1;
+ default_init_allocator<int> a{};
+
+ // The contained object and the allocator should be value-initialized.
+ VERIFY( i1->i == 0 );
+ VERIFY( i1->c[0] == 0 );
+ VERIFY( i1->c[1] == 0 );
+ VERIFY( i1.get_allocator() == a );
+
+ a.state = 5;
+ // Allocator-extended default constructor:
+ std::polymorphic<Obj, default_init_allocator<Obj>> i2(std::allocator_arg, a);
+ VERIFY( i2.get_allocator() == a );
+
+ // Object is constructed using allocator-aware constructor.
+ std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc>
+ i3(std::allocator_arg, ScopedAlloc(11, 22));
+ VERIFY( i3->empty() );
+ VERIFY( i3->get_allocator().get_personality() == 22 );
+ VERIFY( i3.get_allocator().get_personality() == 11 );
+}
+
+constexpr void
+test_forwarding_ctor()
+{
+ Obj obj{1, {'2', '3'}};
+ auto verify = [](std::polymorphic<Obj> const& i)
+ {
+ VERIFY( i->i == 1 );
+ VERIFY( i->c[0] == '2' );
+ VERIFY( i->c[1] == '3' );
+ };
+
+ std::polymorphic<Obj> i1(std::as_const(obj));
+ verify(i1);
+ std::polymorphic<Obj> i2(std::move(std::as_const(obj)));
+ verify(i2);
+ std::polymorphic<Obj> i3(obj);
+ verify(i3);
+ std::polymorphic<Obj> i4(std::move(obj));
+ verify(i4);
+
+ std::polymorphic<Obj> i5({1, {'2', '3'}});
+ verify(i5);
+
+ std::vector<int, UneqAlloc> v{1, 2, 3, 4, 5};
+ // Object is constructed using allocator-aware constructor.
+ std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc>
+ i7(std::allocator_arg, ScopedAlloc(11, 22), v);
+ VERIFY( i7->size() == 5 );
+ VERIFY( v.size() == 5 );
+ VERIFY( i7->get_allocator().get_personality() == 22 );
+ VERIFY( i7.get_allocator().get_personality() == 11 );
+
+ std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc>
+ i8(std::allocator_arg, ScopedAlloc(11, 22), std::move(v));
+ VERIFY( i8->size() == 5 );
+ VERIFY( v.size() == 0 );
+ VERIFY( i8->get_allocator().get_personality() == 22 );
+ VERIFY( i8.get_allocator().get_personality() == 11 );
+}
+
+constexpr void
+test_inplace_ctor()
+{
+ std::polymorphic<Obj> i1(std::in_place_type<Obj>);
+ VERIFY( i1->i == 0 );
+ VERIFY( i1->c[0] == 0 );
+ VERIFY( i1->c[1] == 0 );
+
+ std::polymorphic<Obj> i2(std::in_place_type<Obj>, 10);
+ VERIFY( i2->i == 10 );
+ VERIFY( i2->c[0] == 0 );
+ VERIFY( i2->c[1] == 0 );
+
+ std::polymorphic<Obj, uneq_allocator<Obj>>
+ i3(std::allocator_arg, 42, std::in_place_type<Obj>);
+ VERIFY( i3->i == 0 );
+ VERIFY( i3->c[0] == 0 );
+ VERIFY( i3->c[1] == 0 );
+ VERIFY( i3.get_allocator().get_personality() == 42 );
+
+ std::polymorphic<Obj, uneq_allocator<Obj>>
+ i4(std::allocator_arg, 42, std::in_place_type<Obj>, 10);
+ VERIFY( i4->i == 10 );
+ VERIFY( i4->c[0] == 0 );
+ VERIFY( i4->c[1] == 0 );
+ VERIFY( i4.get_allocator().get_personality() == 42 );
+
+ std::polymorphic<std::vector<int>>
+ i5(std::in_place_type<std::vector<int>>);
+ VERIFY( i5->size() == 0 );
+
+ std::polymorphic<std::vector<int>>
+ i6(std::in_place_type<std::vector<int>>, 5, 13);
+ VERIFY( i6->size() == 5 );
+ VERIFY( i6->at(0) == 13 );
+
+ std::polymorphic<std::vector<int>>
+ i7(std::in_place_type<std::vector<int>>, {1, 2, 3, 4});
+ VERIFY( i7->size() == 4 );
+ VERIFY( i7->at(2) == 3 );
+
+ std::polymorphic<std::vector<int, UneqAlloc>>
+ i8(std::in_place_type<std::vector<int, UneqAlloc>>, UneqAlloc{42});
+ VERIFY( i8->size() == 0 );
+ VERIFY( i8->get_allocator().get_personality() == 42 );
+
+ std::polymorphic<std::vector<int, UneqAlloc>>
+ i9(std::in_place_type<std::vector<int, UneqAlloc>>, 5, 13, UneqAlloc{42});
+ VERIFY( i9->size() == 5 );
+ VERIFY( i9->at(0) == 13 );
+ VERIFY( i9->get_allocator().get_personality() == 42 );
+
+ std::polymorphic<std::vector<int, UneqAlloc>>
+ i10(std::in_place_type<std::vector<int, UneqAlloc>>, {1, 2, 3, 4}, UneqAlloc{42});
+ VERIFY( i10->size() == 4 );
+ VERIFY( i10->at(2) == 3 );
+ VERIFY( i10->get_allocator().get_personality() == 42 );
+
+ std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc>
+ i14(std::allocator_arg, ScopedAlloc(11, 22),
+ std::in_place_type<std::vector<int, UneqAlloc>>);
+ VERIFY( i14->size() == 0 );
+ VERIFY( i14->get_allocator().get_personality() == 22 );
+ VERIFY( i14.get_allocator().get_personality() == 11 );
+
+ std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc>
+ i15(std::allocator_arg, ScopedAlloc(11, 22),
+ std::in_place_type<std::vector<int, UneqAlloc>>, 5, 13);
+ VERIFY( i15->size() == 5 );
+ VERIFY( i15->at(0) == 13 );
+ VERIFY( i15->get_allocator().get_personality() == 22 );
+ VERIFY( i15.get_allocator().get_personality() == 11 );
+
+ std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc>
+ i16(std::allocator_arg, ScopedAlloc(11, 22),
+ std::in_place_type<std::vector<int, UneqAlloc>>, {1, 2, 3, 4});
+ VERIFY( i16->size() == 4 );
+ VERIFY( i16->at(2) == 3 );
+ VERIFY( i16->get_allocator().get_personality() == 22 );
+ VERIFY( i16.get_allocator().get_personality() == 11 );
+}
+
+int main()
+{
+ test_default_ctor();
+ test_forwarding_ctor();
+ test_inplace_ctor();
+
+ static_assert([] {
+ test_default_ctor();
+ test_forwarding_ctor();
+ test_inplace_ctor();
+ return true;
+ });
+}
diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/ctor_poly.cc b/libstdc++-v3/testsuite/std/memory/polymorphic/ctor_poly.cc
new file mode 100644
index 0000000..03519a1
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/memory/polymorphic/ctor_poly.cc
@@ -0,0 +1,220 @@
+// { dg-do run { target c++26 } }
+
+#include <memory>
+#include <scoped_allocator>
+#include <utility>
+#include <vector>
+
+#ifndef __cpp_lib_polymorphic
+# error __cpp_lib_polymorphic feature test macro missing in <memory>
+#elif __cpp_lib_polymorphic != 202502
+# error __cpp_lib_polymorphic feature test macro has wrong value in <memory>
+#endif
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct Base {
+ friend constexpr
+ bool operator==(const Base& lhs, const Base& rhs)
+ { return lhs.eq(rhs); }
+
+ virtual constexpr int
+ get_personality() const
+ { return -1; }
+
+private:
+ constexpr virtual bool
+ eq(const Base& other) const
+ { return true; }
+};
+
+struct ObjDerived : Base
+{
+ constexpr ObjDerived()
+ : x(0), y(0), z(0)
+ { }
+
+ constexpr ObjDerived(int a, int b, int c)
+ : x(a), y(b), z(c)
+ { }
+
+ virtual constexpr int
+ get_personality() const
+ { return -2; }
+
+private:
+ constexpr bool
+ eq(const Base& other) const override
+ {
+ if (auto op = dynamic_cast<const ObjDerived*>(&other))
+ return this->x == op->x && this->y == op->y && this->z == op->z;
+ return false;
+ }
+
+ int x;
+ int y;
+ int z;
+};
+
+template<typename T, typename Allocator>
+struct VecDerived : Base, std::vector<T, Allocator>
+{
+ using VecBase = std::vector<T, Allocator>;
+
+ using VecBase::VecBase;
+
+ constexpr int
+ get_personality() const override
+ { return this->get_allocator().get_personality(); }
+
+private:
+
+ constexpr bool
+ eq(const Base& other) const override
+ {
+ if (auto op = dynamic_cast<const VecDerived*>(&other))
+ return *static_cast<const VecBase*>(this)
+ == *static_cast<const VecBase*>(op);
+ return false;
+ }
+};
+
+using __gnu_test::uneq_allocator;
+using UneqAlloc = uneq_allocator<int>;
+using ScopedAlloc = std::scoped_allocator_adaptor<
+ uneq_allocator<Base>,
+ UneqAlloc>;
+
+constexpr void
+test_default_ctor()
+{
+ using __gnu_test::default_init_allocator;
+
+ std::polymorphic<Base, default_init_allocator<Base>> i1;
+ default_init_allocator<int> a{};
+
+ // The contained object and the allocator should be value-initialized.
+ VERIFY( *i1 == Base() );
+ VERIFY( i1->get_personality() == -1 );
+ VERIFY( i1.get_allocator() == a );
+
+ a.state = 5;
+ // Allocator-extended default constructor:
+ std::polymorphic<Base, default_init_allocator<Base>> i2(std::allocator_arg, a);
+ VERIFY( *i1 == Base() );
+ VERIFY( i1->get_personality() == -1 );
+}
+
+constexpr void
+test_forwarding_ctor()
+{
+ const ObjDerived src(1, 2, 3);
+
+ std::polymorphic<Base> i1(src);
+ VERIFY( *i1 == src );
+ VERIFY( i1->get_personality() == -2 );
+ std::polymorphic<Base> i2(std::move(src));
+ VERIFY( *i2 == src );
+ VERIFY( i2->get_personality() == -2 );
+
+ ObjDerived obj = src;
+ std::polymorphic<Base> i3(obj);
+ VERIFY( *i3 == src );
+ VERIFY( i3->get_personality() == -2 );
+ std::polymorphic<Base> i4(std::move(obj));
+ VERIFY( *i4 == src );
+ VERIFY( i4->get_personality() == -2 );
+
+ const VecDerived<int, UneqAlloc> v{1, 2, 3, 4, 5};
+ // Object is constructed using allocator-aware constructor.
+ std::polymorphic<Base, ScopedAlloc>
+ i5(std::allocator_arg, ScopedAlloc(11, 22), v);
+ VERIFY( *i5 == v );
+ VERIFY( i5->get_personality() == 22 );
+ VERIFY( i5.get_allocator().get_personality() == 11 );
+
+ std::polymorphic<Base, ScopedAlloc>
+ i6(std::allocator_arg, ScopedAlloc(11, 22), auto(v));
+ VERIFY( *i6 == v );
+ VERIFY( i6->get_personality() == 22 );
+ VERIFY( i6.get_allocator().get_personality() == 11 );
+}
+
+constexpr void
+test_inplace_ctor()
+{
+ std::polymorphic<Base> i1(std::in_place_type<ObjDerived>);
+ VERIFY( *i1 == ObjDerived() );
+ VERIFY( i1->get_personality() == -2 );
+
+ std::polymorphic<Base> i2(std::in_place_type<ObjDerived>, 10, 20, 30);
+ VERIFY( *i2 == ObjDerived(10, 20, 30) );
+ VERIFY( i2->get_personality() == -2 );
+
+ std::polymorphic<Base, uneq_allocator<Base>>
+ i3(std::allocator_arg, 42, std::in_place_type<ObjDerived>);
+ VERIFY( *i3 == ObjDerived() );
+ VERIFY( i3->get_personality() == -2 );
+ VERIFY( i3.get_allocator().get_personality() == 42 );
+
+ std::polymorphic<Base, uneq_allocator<Base>>
+ i4(std::allocator_arg, 42, std::in_place_type<ObjDerived>, 10, 20, 30);
+ VERIFY( *i4 == ObjDerived(10, 20, 30) );
+ VERIFY( i4->get_personality() == -2 );
+ VERIFY( i4.get_allocator().get_personality() == 42 );
+
+ const VecDerived<int, UneqAlloc> ze;
+ const VecDerived<int, UneqAlloc> fe(5, 13);
+ const VecDerived<int, UneqAlloc> il{1, 2, 3 ,4};
+
+ std::polymorphic<Base>
+ i5(std::in_place_type<VecDerived<int, UneqAlloc>>, UneqAlloc{42});
+ VERIFY( *i5 == ze );
+ VERIFY( i5->get_personality() == 42 );
+
+ std::polymorphic<Base>
+ i6(std::in_place_type<VecDerived<int, UneqAlloc>>, 5, 13, UneqAlloc{42});
+ VERIFY( *i6 == fe );
+ VERIFY( i6->get_personality() == 42 );
+
+ std::polymorphic<Base>
+ i7(std::in_place_type<VecDerived<int, UneqAlloc>>, {1, 2, 3, 4}, UneqAlloc{42});
+ VERIFY( *i7 == il );
+ VERIFY( i7->get_personality() == 42 );
+
+ std::polymorphic<Base, ScopedAlloc>
+ i8(std::allocator_arg, ScopedAlloc(11, 22),
+ std::in_place_type<VecDerived<int, UneqAlloc>>);
+ VERIFY( *i8 == ze );
+ VERIFY( i8->get_personality() == 22 );
+ VERIFY( i8.get_allocator().get_personality() == 11 );
+
+ std::polymorphic<Base, ScopedAlloc>
+ i9(std::allocator_arg, ScopedAlloc(11, 22),
+ std::in_place_type<VecDerived<int, UneqAlloc>>, 5, 13);
+ VERIFY( *i9 == fe );
+ VERIFY( i9->get_personality() == 22 );
+ VERIFY( i9.get_allocator().get_personality() == 11 );
+
+ std::polymorphic<Base, ScopedAlloc>
+ i10(std::allocator_arg, ScopedAlloc(11, 22),
+ std::in_place_type<VecDerived<int, UneqAlloc>>, {1, 2, 3, 4});
+ VERIFY( *i10 == il );
+ VERIFY( i10->get_personality() == 22 );
+ VERIFY( i10.get_allocator().get_personality() == 11 );
+}
+
+int main()
+{
+ test_default_ctor();
+ test_forwarding_ctor();
+ test_inplace_ctor();
+
+ static_assert([] {
+ test_default_ctor();
+ test_forwarding_ctor();
+ test_inplace_ctor();
+ return true;
+ });
+}
diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/incomplete.cc b/libstdc++-v3/testsuite/std/memory/polymorphic/incomplete.cc
new file mode 100644
index 0000000..e5dd78f
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/memory/polymorphic/incomplete.cc
@@ -0,0 +1,13 @@
+// { dg-do compile { target c++26 } }
+
+#include <memory>
+
+struct Incomplete;
+
+std::polymorphic<Incomplete>*
+test_move(std::polymorphic<Incomplete>& i1, std::polymorphic<Incomplete>& i2)
+{
+ i1 = std::move(i2);
+ swap(i1, i2);
+ return new std::polymorphic<Incomplete>(std::move(i1));
+}
diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/invalid_neg.cc b/libstdc++-v3/testsuite/std/memory/polymorphic/invalid_neg.cc
new file mode 100644
index 0000000..a01af3f
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/memory/polymorphic/invalid_neg.cc
@@ -0,0 +1,28 @@
+// { dg-do compile { target c++26 } }
+
+#include <memory>
+
+// In every specialization polymorphic<T, Allocator>, if the type
+// allocator_traits<Allocator>::value_type is not the same type as T,
+// the program is ill-formed.
+using T1 = std::polymorphic<int, std::allocator<long>>::value_type; // { dg-error "here" }
+
+// A program that instantiates the definition of the template
+// polymorphic<T, Allocator> with a type for the T parameter that is
+// a non-object type, an array type, in_place_t,
+// a specialization of in_place_type_t, or a cv-qualified type is ill-formed.
+
+using T2 = std::polymorphic<int&>::value_type; // { dg-error "here" }
+
+using T3 = std::polymorphic<int[1]>::value_type; // { dg-error "here" }
+
+using T4 = std::polymorphic<std::in_place_t>::value_type; // { dg-error "here" }
+
+using T5 = std::polymorphic<std::in_place_type_t<int>>::value_type; // { dg-error "here" }
+
+using T6 = std::polymorphic<const int>::value_type; // { dg-error "here" }
+
+using T7 = std::polymorphic<volatile int>::value_type; // { dg-error "here" }
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
+// { dg-prune-output "forming pointer to reference" }
diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/move.cc b/libstdc++-v3/testsuite/std/memory/polymorphic/move.cc
new file mode 100644
index 0000000..c802159
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/memory/polymorphic/move.cc
@@ -0,0 +1,177 @@
+// { dg-do run { target c++26 } }
+
+#include <memory>
+#include <scoped_allocator>
+#include <utility>
+#include <vector>
+#include <optional>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct Base {
+ friend constexpr
+ bool operator==(const Base& lhs, const Base& rhs)
+ { return lhs.eq(rhs); }
+
+private:
+ constexpr virtual bool
+ eq(const Base& other) const = 0;
+};
+
+struct Derived : Base
+{
+ constexpr Derived()
+ : x(0), y(0), z(0)
+ { }
+
+ constexpr Derived(int a, int b, int c)
+ : x(a), y(b), z(c)
+ { }
+
+private:
+ constexpr bool
+ eq(const Base& other) const override
+ {
+ if (auto op = dynamic_cast<const Derived*>(&other))
+ return this->x == op->x && this->y == op->y && this->z == op->z;
+ return false;
+ }
+
+ int x;
+ int y;
+ int z;
+};
+
+using __gnu_test::tracker_allocator;
+using Counter = __gnu_test::tracker_allocator_counter;
+using Polymorphic = std::polymorphic<Base, tracker_allocator<Base>>;
+const Polymorphic val(std::in_place_type<Derived>, 1, 2, 3);
+
+constexpr void
+verifyNoAllocations()
+{
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+}
+
+constexpr void
+test_ctor()
+{
+ std::optional<Polymorphic> src;
+ auto make = [&src] -> Polymorphic&& {
+ src.emplace(val);
+ Counter::reset();
+ return std::move(*src);
+ };
+
+ Polymorphic i1(make());
+ VERIFY( src->valueless_after_move() );
+ VERIFY( *i1 == *val );
+ verifyNoAllocations();
+
+ Polymorphic i2(std::allocator_arg, {}, make());
+ VERIFY( src->valueless_after_move() );
+ VERIFY( *i2 == *val );
+ verifyNoAllocations();
+}
+
+constexpr void
+test_assign()
+{
+ std::optional<Polymorphic> src;
+ auto make = [&src] -> Polymorphic&& {
+ src.emplace(val);
+ Counter::reset();
+ return std::move(*src);
+ };
+
+ Polymorphic i1(std::in_place_type<Derived>);
+
+ i1 = make();
+ VERIFY( src->valueless_after_move() );
+ VERIFY( *i1 == *val );
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_deallocation_count() >= sizeof(Derived) );
+ VERIFY( Counter::get_construct_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 1 );
+
+ auto(std::move(i1));
+ i1 = make();
+ VERIFY( *i1 == *val );
+ VERIFY( src->valueless_after_move() );
+ verifyNoAllocations();
+}
+
+constexpr void
+test_swap()
+{
+ const Polymorphic val1(std::in_place_type<Derived>, 1, 2, 3);
+ const Polymorphic val2(std::in_place_type<Derived>, 2, 4, 6);
+
+ Polymorphic i1(val1);
+ Polymorphic i2(val2);
+ Counter::reset();
+ i1.swap(i2);
+ VERIFY( *i2 == *val1 );
+ VERIFY( *i1 == *val2 );
+ verifyNoAllocations();
+
+ auto(std::move(i1));
+
+ Counter::reset();
+ i1.swap(i2);
+ VERIFY( *i1 == *val1 );
+ VERIFY( i2.valueless_after_move() );
+ verifyNoAllocations();
+}
+
+constexpr void
+test_valueless()
+{
+ auto e = [] {
+ Polymorphic res(std::in_place_type<Derived>);
+ auto(std::move(res));
+ Counter::reset();
+ return res;
+ };
+
+ Polymorphic i1(e());
+ VERIFY( i1.valueless_after_move() );
+ verifyNoAllocations();
+
+ Polymorphic i2(std::allocator_arg, {}, e());
+ VERIFY( i2.valueless_after_move() );
+ verifyNoAllocations();
+
+ Polymorphic i3(val);
+ i3 = e();
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_deallocation_count() >= sizeof(Derived) );
+ VERIFY( Counter::get_construct_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 1 );
+
+ i3 = e();
+ verifyNoAllocations();
+}
+
+constexpr void
+test_all()
+{
+ test_ctor();
+ test_assign();
+ test_swap();
+ test_valueless();
+}
+
+int main()
+{
+ test_all();
+
+ static_assert([] {
+ test_all();
+ return true;
+ });
+}
diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/move_alloc.cc b/libstdc++-v3/testsuite/std/memory/polymorphic/move_alloc.cc
new file mode 100644
index 0000000..09afedb
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/memory/polymorphic/move_alloc.cc
@@ -0,0 +1,339 @@
+// { dg-do run { target c++26 } }
+
+#include <memory>
+#include <scoped_allocator>
+#include <utility>
+#include <vector>
+#include <optional>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct Base {
+ friend constexpr
+ bool operator==(const Base& lhs, const Base& rhs)
+ { return lhs.eq(rhs); }
+
+ virtual constexpr int
+ get_alloc_personality() const
+ { return -1; }
+
+private:
+ constexpr virtual bool
+ eq(const Base& other) const = 0;
+};
+
+template<typename T, typename Allocator>
+struct VecDerived : Base, std::vector<T, Allocator>
+{
+ using VecBase = std::vector<T, Allocator>;
+
+ using VecBase::VecBase;
+
+ constexpr int
+ get_alloc_personality() const override
+ { return this->get_allocator().get_personality(); }
+
+private:
+
+ constexpr bool
+ eq(const Base& other) const override
+ {
+ if (auto op = dynamic_cast<const VecDerived*>(&other))
+ return *static_cast<const VecBase*>(this)
+ == *static_cast<const VecBase*>(op);
+ return false;
+ }
+};
+
+using __gnu_test::propagating_allocator;
+using __gnu_test::tracker_allocator;
+using Counter = __gnu_test::tracker_allocator_counter;
+
+constexpr void
+verifyNoAllocations()
+{
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+}
+
+template<bool Propagate>
+constexpr void
+test_ctor()
+{
+ using PropAlloc = propagating_allocator<int, Propagate>;
+ using Vector = VecDerived<int, PropAlloc>;
+ using ScopedAlloc = std::scoped_allocator_adaptor<
+ propagating_allocator<Vector, Propagate, tracker_allocator<Vector>>,
+ PropAlloc>;
+ using Polymorphic = std::polymorphic<Vector, ScopedAlloc>;
+
+ const Polymorphic val(std::in_place_type<Vector>, {1, 2, 3});
+ std::optional<Polymorphic> src;
+ auto make = [&val, &src] -> Polymorphic&& {
+ src.emplace(std::allocator_arg, ScopedAlloc{11, 22}, val);
+ Counter::reset();
+ return std::move(*src);
+ };
+
+ Polymorphic i1(make());
+ VERIFY( src->valueless_after_move() );
+ VERIFY( *i1 == *val );
+ VERIFY( i1->get_alloc_personality() == 22 );
+ VERIFY( i1.get_allocator().get_personality() == 11 );
+ verifyNoAllocations();
+
+ Polymorphic i2(std::allocator_arg, ScopedAlloc{11, 22}, make());
+ VERIFY( src->valueless_after_move() );
+ VERIFY( *i2 == *val );
+ VERIFY( i2->get_alloc_personality() == 22 );
+ VERIFY( i2.get_allocator().get_personality() == 11 );
+ verifyNoAllocations();
+
+ Polymorphic i3(std::allocator_arg, ScopedAlloc{33, 44}, make());
+ // We move-from contained object
+ VERIFY( !src->valueless_after_move() );
+ VERIFY( *i3 == *val );
+ VERIFY( i3->get_alloc_personality() == 44 );
+ VERIFY( i3.get_allocator().get_personality() == 33 );
+ VERIFY( Counter::get_allocation_count() >= sizeof(Vector) );
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 2 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+}
+
+template<bool Propagate>
+constexpr void
+test_assign()
+{
+ using PropAlloc = propagating_allocator<int, Propagate>;
+ using Vector = VecDerived<int, PropAlloc>;
+ using ScopedAlloc = std::scoped_allocator_adaptor<
+ propagating_allocator<Vector, Propagate, tracker_allocator<Vector>>,
+ PropAlloc>;
+ using Polymorphic = std::polymorphic<Vector, ScopedAlloc>;
+
+ const Polymorphic val(std::in_place_type<Vector>, {1, 2, 3});
+ std::optional<Polymorphic> src;
+ auto make = [&val, &src] -> Polymorphic&& {
+ src.emplace(std::allocator_arg, ScopedAlloc{11, 22}, val);
+ Counter::reset();
+ return std::move(*src);
+ };
+
+ Counter::reset();
+ Polymorphic i1(std::allocator_arg, ScopedAlloc{11, 22});
+ const std::size_t holderSize = Counter::get_allocation_count();
+ VERIFY( holderSize >= sizeof(Vector) );
+
+ i1 = make();
+ VERIFY( src->valueless_after_move() );
+ VERIFY( *i1 == *val );
+ VERIFY( i1->get_alloc_personality() == 22 );
+ VERIFY( i1.get_allocator().get_personality() == 11 );
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_deallocation_count() == holderSize );
+ VERIFY( Counter::get_construct_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 1 );
+
+ Polymorphic i2(std::allocator_arg, ScopedAlloc{33, 44});
+
+ i2 = make();
+ VERIFY( *i2 == *val );
+ if (Propagate)
+ {
+ VERIFY( src->valueless_after_move() );
+ VERIFY( i2->get_alloc_personality() == 22 );
+ VERIFY( i2.get_allocator().get_personality() == 11 );
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 0 );
+ }
+ else
+ {
+ // We allocate new holder and move-from contained object
+ VERIFY( !src->valueless_after_move() );
+ VERIFY( i2->get_alloc_personality() == 44 );
+ VERIFY( i2.get_allocator().get_personality() == 33 );
+ VERIFY( Counter::get_allocation_count() == holderSize );
+ VERIFY( Counter::get_construct_count() == 2 );
+ }
+ VERIFY( Counter::get_deallocation_count() == holderSize );
+ VERIFY( Counter::get_destruct_count() == 1 );
+
+ Polymorphic i3(std::allocator_arg, ScopedAlloc{11, 22},
+ std::in_place_type<Vector>);
+ auto(std::move(i3));
+
+ i3 = make();
+ VERIFY( *i3 == *val );
+ VERIFY( src->valueless_after_move() );
+ VERIFY( i3->get_alloc_personality() == 22 );
+ VERIFY( i3.get_allocator().get_personality() == 11 );
+ verifyNoAllocations();
+
+ Polymorphic i4(std::allocator_arg, ScopedAlloc{33, 44},
+ std::in_place_type<Vector>);
+ auto(std::move(i4));
+
+ i4 = make();
+ VERIFY( *i4 == *val );
+ if (Propagate)
+ {
+ VERIFY( src->valueless_after_move() );
+ VERIFY( i4->get_alloc_personality() == 22 );
+ VERIFY( i4.get_allocator().get_personality() == 11 );
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_construct_count() == 0 );
+ }
+ else
+ {
+ // We allocate new holder and move-from contained object
+ VERIFY( !src->valueless_after_move() );
+ VERIFY( i4->get_alloc_personality() == 44 );
+ VERIFY( i4.get_allocator().get_personality() == 33 );
+ VERIFY( Counter::get_allocation_count() == holderSize );
+ VERIFY( Counter::get_construct_count() == 2 );
+ }
+ VERIFY( Counter::get_deallocation_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 0 );
+}
+
+template<bool Propagate>
+constexpr void
+test_swap()
+{
+ using PropAlloc = propagating_allocator<int, Propagate>;
+ using Vector = VecDerived<int, PropAlloc>;
+ using ScopedAlloc = std::scoped_allocator_adaptor<
+ propagating_allocator<Vector, Propagate, tracker_allocator<Vector>>,
+ PropAlloc>;
+ using Polymorphic = std::polymorphic<Vector, ScopedAlloc>;
+
+ const Polymorphic val1(std::in_place_type<Vector>, {1, 2, 3});
+ const Polymorphic val2(std::in_place_type<Vector>, {2, 4, 6});
+
+ Polymorphic i1(std::allocator_arg, ScopedAlloc{11, 22}, val1);
+ Polymorphic i2(std::allocator_arg, ScopedAlloc{11, 22}, val2);
+ Counter::reset();
+ i1.swap(i2);
+ VERIFY( *i2 == *val1 );
+ VERIFY( *i1 == *val2 );
+ verifyNoAllocations();
+
+ auto(std::move(i1));
+
+ Counter::reset();
+ i1.swap(i2);
+ VERIFY( *i1 == *val1 );
+ VERIFY( i2.valueless_after_move() );
+ verifyNoAllocations();
+
+ if (!Propagate)
+ return;
+
+ Polymorphic i3(std::allocator_arg, ScopedAlloc{33, 44}, val2);
+ Counter::reset();
+ i1.swap(i3);
+ VERIFY( *i1 == *val2 );
+ VERIFY( i1->get_alloc_personality() == 44 );
+ VERIFY( i1.get_allocator().get_personality() == 33 );
+ VERIFY( *i3 == *val1 );
+ VERIFY( i3->get_alloc_personality() == 22 );
+ VERIFY( i3.get_allocator().get_personality() == 11 );
+ verifyNoAllocations();
+
+ i1.swap(i2);
+ VERIFY( i1.valueless_after_move() );
+ VERIFY( i1.get_allocator().get_personality() == 11 );
+ VERIFY( *i2 == *val2 );
+ VERIFY( i2->get_alloc_personality() == 44 );
+ VERIFY( i2.get_allocator().get_personality() == 33 );
+ verifyNoAllocations();
+}
+
+template<bool Propagate>
+constexpr void
+test_valueless()
+{
+ using PropAlloc = propagating_allocator<int, Propagate>;
+ using Vector = VecDerived<int, PropAlloc>;
+ using ScopedAlloc = std::scoped_allocator_adaptor<
+ propagating_allocator<Vector, Propagate, tracker_allocator<Vector>>,
+ PropAlloc>;
+ using Polymorphic = std::polymorphic<Vector, ScopedAlloc>;
+
+ auto e = [] {
+ Polymorphic res(std::allocator_arg, ScopedAlloc{11, 22},
+ std::in_place_type<Vector>);
+ auto(std::move(res));
+ Counter::reset();
+ return res;
+ };
+
+ Polymorphic i1(e());
+ VERIFY( i1.valueless_after_move() );
+ VERIFY( i1.get_allocator().get_personality() == 11 );
+ verifyNoAllocations();
+
+ Polymorphic i2(std::allocator_arg, ScopedAlloc{33, 44}, e());
+ VERIFY( i2.valueless_after_move() );
+ VERIFY( i2.get_allocator().get_personality() == 33 );
+ verifyNoAllocations();
+
+ Polymorphic i3(std::allocator_arg, ScopedAlloc{33, 44});
+
+ i3 = e();
+ VERIFY( i3.valueless_after_move() );
+ if (Propagate)
+ VERIFY( i3.get_allocator().get_personality() == 11 );
+ else
+ VERIFY( i3.get_allocator().get_personality() == 33 );
+ VERIFY( Counter::get_allocation_count() == 0 );
+ VERIFY( Counter::get_deallocation_count() >= sizeof(Vector) );
+ VERIFY( Counter::get_construct_count() == 0 );
+ VERIFY( Counter::get_destruct_count() == 1 );
+
+ i2 = e();
+ VERIFY( i2.valueless_after_move() );
+ if (Propagate)
+ VERIFY( i2.get_allocator().get_personality() == 11 );
+ else
+ VERIFY( i2.get_allocator().get_personality() == 33 );
+ verifyNoAllocations();
+
+ i3.swap(i2);
+ VERIFY( i2.valueless_after_move() );
+ VERIFY( i1.valueless_after_move() );
+ verifyNoAllocations();
+
+ if (!Propagate)
+ return;
+
+ Polymorphic i4(std::allocator_arg, ScopedAlloc{33, 44}, e());
+ i4.swap(i1);
+ verifyNoAllocations();
+}
+
+template<bool Propagate>
+constexpr void
+test_all()
+{
+ test_ctor<Propagate>();
+ test_assign<Propagate>();
+ test_swap<Propagate>();
+ test_valueless<Propagate>();
+}
+
+int main()
+{
+ test_all<true>();
+ test_all<false>();
+
+ static_assert([] {
+ test_all<true>();
+ test_all<false>();
+ return true;
+ });
+}
diff --git a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
index 322faa1..46942dc 100644
--- a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
+++ b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
@@ -1,7 +1,9 @@
// { dg-do run { target c++20 } }
+// { dg-require-effective-target hosted }
// { dg-timeout-factor 2 }
#include <chrono>
+#include <ranges>
#include <sstream>
#include <testsuite_hooks.h>
@@ -49,6 +51,274 @@ void verify(const T& t, const _CharT* str)
VERIFY( res == str );
}
+template<typename Ret = void>
+struct Rep
+{
+ using Return
+ = std::conditional_t<std::is_void_v<Ret>, Rep, Ret>;
+
+ Rep(long v = 0) : val(v) {}
+
+ operator long() const
+ { return val; }
+
+ Return
+ operator+() const
+ { return val; }
+
+ Rep
+ operator-() const
+ { return -val; }
+
+ friend Rep
+ operator+(Rep lhs, Rep rhs)
+ { return lhs.val + rhs.val; }
+
+ friend Rep
+ operator-(Rep lhs, Rep rhs)
+ { return lhs.val - rhs.val; }
+
+ friend Rep
+ operator*(Rep lhs, Rep rhs)
+ { return lhs.val * rhs.val; }
+
+ friend Rep
+ operator/(Rep lhs, Rep rhs)
+ { return lhs.val / rhs.val; }
+
+ friend auto operator<=>(Rep, Rep) = default;
+
+ template<typename _CharT>
+ friend std::basic_ostream<_CharT>&
+ operator<<(std::basic_ostream<_CharT>& os, const Rep& t)
+ { return os << t.val << WIDEN("[via <<]"); }
+
+ long val;
+};
+
+template<typename Ret, typename Other>
+ requires std::is_integral_v<Other>
+struct std::common_type<Rep<Ret>, Other>
+{
+ using type = Rep<Ret>;
+};
+
+template<typename Ret, typename Other>
+ requires std::is_integral_v<Other>
+struct std::common_type<Other, Rep<Ret>>
+ : std::common_type<Rep<Ret>, Other>
+{ };
+
+template<typename Ret>
+struct std::numeric_limits<Rep<Ret>>
+ : std::numeric_limits<long>
+{ };
+
+template<typename Ret, typename _CharT>
+struct std::formatter<Rep<Ret>, _CharT>
+ : std::formatter<long, _CharT>
+{
+ template<typename Out>
+ typename std::basic_format_context<Out, _CharT>::iterator
+ format(const Rep<Ret>& t, std::basic_format_context<Out, _CharT>& ctx) const
+ {
+ constexpr std::basic_string_view<_CharT> suffix = WIDEN("[via format]");
+ auto out = std::formatter<long, _CharT>::format(t.val, ctx);
+ return std::ranges::copy(suffix, out).out;
+ }
+};
+
+using deciseconds = duration<seconds::rep, std::deci>;
+
+template<typename _CharT>
+void
+test_duration()
+{
+ std::basic_string<_CharT> res;
+
+ const milliseconds di(40);
+ verify( di, WIDEN("40ms") );
+ res = std::format(WIDEN("{:>6}"), di);
+ VERIFY( res == WIDEN(" 40ms") );
+
+ verify( -di, WIDEN("-40ms") );
+ res = std::format(WIDEN("{:>6}"), -di);
+ VERIFY( res == WIDEN(" -40ms") );
+
+ const duration<double> df(11.22);
+ verify( df, WIDEN("11.22s") );
+ res = std::format(WIDEN("{:=^12}"), df);
+ VERIFY( res == WIDEN("===11.22s===") );
+
+ verify( -df, WIDEN("-11.22s") );
+ res = std::format(WIDEN("{:=^12}"), -df);
+ VERIFY( res == WIDEN("==-11.22s===") );
+}
+
+template<typename _CharT>
+void
+test_duration_cust()
+{
+ std::basic_string<_CharT> res;
+ const duration<char, std::ratio<1, 10>> charRep(123);
+ verify( charRep, WIDEN("123ds") );
+
+ // +asLong returns long, so formatted as long
+ const duration<Rep<long>> asLong(20);
+ verify( asLong, WIDEN("20s") );
+ res = std::format(WIDEN("{:>6}"), asLong);
+ VERIFY( res == WIDEN(" 20s") );
+
+ verify( -asLong, WIDEN("-20s") );
+ res = std::format(WIDEN("{:>6}"), -asLong);
+ VERIFY( res == WIDEN(" -20s") );
+
+ res = std::format(WIDEN("{:%Q}"), asLong);
+ VERIFY( res == WIDEN("20") );
+ res = std::format(WIDEN("{:+<7%Q}"), asLong);
+ VERIFY( res == WIDEN("20+++++") );
+
+ // +asRep returns Rep<>, so formatted as Rep<>
+ const duration<Rep<>> asRep(10);
+ verify( asRep, WIDEN("10[via <<]s") );
+ res = std::format(WIDEN("{:=^15}"), asRep);
+ VERIFY( res == WIDEN("==10[via <<]s==") );
+
+ verify( -asRep, WIDEN("-10[via <<]s") );
+ res = std::format(WIDEN("{:=^15}"), -asRep);
+ VERIFY( res == WIDEN("=-10[via <<]s==") );
+
+ res = std::format(WIDEN("{:%Q}"), asRep);
+ VERIFY( res == WIDEN("10[via format]") );
+ res = std::format(WIDEN("{:=^18%Q}"), asRep);
+ VERIFY( res == WIDEN("==10[via format]==") );
+
+ const duration<Rep<>, std::milli> milliRep(10);
+ verify( milliRep, WIDEN("10[via <<]ms") );
+ res = std::format(WIDEN("{:=^15}"), milliRep);
+ VERIFY( res == WIDEN("=10[via <<]ms==") );
+
+ verify( -milliRep, WIDEN("-10[via <<]ms") );
+ res = std::format(WIDEN("{:=^15}"), -milliRep);
+ VERIFY( res == WIDEN("=-10[via <<]ms=") );
+
+ res = std::format(WIDEN("{:%Q}"), milliRep);
+ VERIFY( res == WIDEN("10[via format]") );
+ res = std::format(WIDEN("{:=^18%Q}"), milliRep);
+ VERIFY( res == WIDEN("==10[via format]==") );
+}
+
+template<typename Ratio, typename Rep, typename Period>
+constexpr auto
+hms(const duration<Rep, Period>& d)
+{
+ using Dur = duration<Rep, typename Ratio::period>;
+ return hh_mm_ss<Dur>(duration_cast<Dur>(d));
+}
+
+template<typename _CharT>
+void
+test_hh_mm_ss()
+{
+ auto dt = 22h + 24min + 54s + 111222333ns;
+ verify( hms<nanoseconds>(dt),
+ WIDEN("22:24:54.111222333") );
+ verify( hms<microseconds>(dt),
+ WIDEN("22:24:54.111222") );
+ verify( hms<milliseconds>(dt),
+ WIDEN("22:24:54.111") );
+ verify( hms<deciseconds>(dt),
+ WIDEN("22:24:54.1") );
+ verify( hms<seconds>(dt),
+ WIDEN("22:24:54") );
+ verify( hms<minutes>(dt),
+ WIDEN("22:24:00") );
+ verify( hms<hours>(dt),
+ WIDEN("22:00:00") );
+ verify( hms<nanoseconds>(-dt),
+ WIDEN("-22:24:54.111222333") );
+ verify( hms<microseconds>(-dt),
+ WIDEN("-22:24:54.111222") );
+ verify( hms<milliseconds>(-dt),
+ WIDEN("-22:24:54.111") );
+ verify( hms<deciseconds>(-dt),
+ WIDEN("-22:24:54.1") );
+ verify( hms<seconds>(-dt),
+ WIDEN("-22:24:54") );
+ verify( hms<minutes>(-dt),
+ WIDEN("-22:24:00") );
+ verify( hms<hours>(-dt),
+ WIDEN("-22:00:00") );
+
+ verify( hms<nanoseconds>(-dt),
+ WIDEN("-22:24:54.111222333") );
+
+ dt += 300h;
+ verify( hms<nanoseconds>(dt),
+ WIDEN("322:24:54.111222333") );
+ verify( hms<nanoseconds>(-dt),
+ WIDEN("-322:24:54.111222333") );
+
+ dt += 14000h;
+ verify( hms<nanoseconds>(dt),
+ WIDEN("14322:24:54.111222333") );
+ verify( hms<nanoseconds>(-dt),
+ WIDEN("-14322:24:54.111222333") );
+}
+
+template<typename _CharT>
+void
+test_hh_mm_ss_cust()
+{
+ const duration<char, deciseconds::period> charRep(123);
+ verify( hms<deciseconds>(charRep),
+ WIDEN("00:00:12.3") );
+ verify( hms<seconds>(charRep),
+ WIDEN("00:00:12") );
+
+ auto dt = 22h + 24min + 54s + 123ms;
+ // +plus returns long, so formatted as long
+ const duration<Rep<long>, std::milli> asLong(dt.count());
+ verify( hms<milliseconds>(asLong),
+ WIDEN("22:24:54.123[via format]") );
+ verify( hms<deciseconds>(asLong),
+ WIDEN("22:24:54.1[via format]") );
+ verify( hms<seconds>(asLong),
+ WIDEN("22:24:54") );
+ verify( hms<milliseconds>(-asLong),
+ WIDEN("-22:24:54.123[via format]") );
+ verify( hms<deciseconds>(-asLong),
+ WIDEN("-22:24:54.1[via format]") );
+ verify( hms<seconds>(-asLong),
+ WIDEN("-22:24:54") );
+
+ // +asRep returns Rep<>, so formatted as Rep<>
+ const duration<Rep<>, std::milli> asRep(dt.count());
+ verify( hms<milliseconds>(asRep),
+ WIDEN("22:24:54.123[via format]") );
+ verify( hms<deciseconds>(asRep),
+ WIDEN("22:24:54.1[via format]") );
+ verify( hms<seconds>(asLong),
+ WIDEN("22:24:54") );
+ verify( hms<milliseconds>(-asLong),
+ WIDEN("-22:24:54.123[via format]") );
+ verify( hms<deciseconds>(-asLong),
+ WIDEN("-22:24:54.1[via format]") );
+ verify( hms<seconds>(-asLong),
+ WIDEN("-22:24:54") );
+}
+
+template<typename CharT>
+void
+test_durations()
+{
+ test_duration<CharT>();
+ test_duration_cust<CharT>();
+
+ test_hh_mm_ss<CharT>();
+ test_hh_mm_ss_cust<CharT>();
+}
+
template<typename _CharT>
void
test_day()
@@ -288,6 +558,7 @@ void
test_all()
{
test_padding<CharT>();
+ test_durations<CharT>();
test_calendar<CharT>();
}