aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog353
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/auto-profile.cc34
-rw-r--r--gcc/c-family/ChangeLog12
-rw-r--r--gcc/c-family/c-common.h5
-rw-r--r--gcc/c-family/c-omp.cc300
-rw-r--r--gcc/c/ChangeLog73
-rw-r--r--gcc/c/c-decl.cc178
-rw-r--r--gcc/c/c-objc-common.cc5
-rw-r--r--gcc/c/c-objc-common.h12
-rw-r--r--gcc/c/c-parser.cc394
-rw-r--r--gcc/c/c-tree.h8
-rw-r--r--gcc/c/c-typeck.cc17
-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
-rwxr-xr-x[-rw-r--r--]gcc/config/aarch64/gcc-auto-profile0
-rw-r--r--gcc/config/i386/i386-expand.cc27
-rw-r--r--gcc/config/i386/i386.h4
-rw-r--r--gcc/config/i386/x86-tune.def5
-rw-r--r--gcc/config/or1k/or1k.opt4
-rw-r--r--gcc/config/or1k/predicates.md3
-rw-r--r--gcc/config/riscv/autovec.md80
-rw-r--r--gcc/config/riscv/riscv-c.cc18
-rw-r--r--gcc/config/riscv/riscv-ext.def39
-rw-r--r--gcc/config/riscv/riscv-ext.opt6
-rw-r--r--gcc/config/riscv/riscv-subset.h62
-rw-r--r--gcc/config/riscv/t-riscv13
-rw-r--r--gcc/config/xtensa/xtensa.cc28
-rw-r--r--gcc/config/xtensa/xtensa.md2
-rw-r--r--gcc/cp/ChangeLog184
-rw-r--r--gcc/cp/constexpr.cc18
-rw-r--r--gcc/cp/coroutines.cc78
-rw-r--r--gcc/cp/coroutines.h1
-rw-r--r--gcc/cp/cp-gimplify.cc6
-rw-r--r--gcc/cp/cp-objcp-common.h9
-rw-r--r--gcc/cp/cp-tree.h22
-rw-r--r--gcc/cp/decl.cc55
-rw-r--r--gcc/cp/decl2.cc9
-rw-r--r--gcc/cp/error.cc56
-rw-r--r--gcc/cp/lambda.cc38
-rw-r--r--gcc/cp/method.cc32
-rw-r--r--gcc/cp/parser.cc343
-rw-r--r--gcc/cp/pt.cc83
-rw-r--r--gcc/cp/semantics.cc212
-rw-r--r--gcc/cp/typeck.cc2
-rw-r--r--gcc/diagnostic-format-html.cc71
-rw-r--r--gcc/diagnostic-show-locus.cc145
-rw-r--r--gcc/doc/gm2.texi3
-rw-r--r--gcc/doc/invoke.texi7
-rw-r--r--gcc/doc/riscv-ext.texi12
-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/ChangeLog35
-rw-r--r--gcc/fortran/check.cc4
-rw-r--r--gcc/fortran/expr.cc84
-rw-r--r--gcc/fortran/interface.cc9
-rw-r--r--gcc/fortran/parse.cc3
-rw-r--r--gcc/fortran/primary.cc3
-rw-r--r--gcc/function.h1
-rw-r--r--gcc/ggc-page.cc50
-rw-r--r--gcc/gimple-harden-conditionals.cc6
-rw-r--r--gcc/gimple-harden-control-flow.cc3
-rw-r--r--gcc/gimple-ssa-sccopy.cc20
-rw-r--r--gcc/gimplify.cc263
-rw-r--r--gcc/ipa-prop.cc29
-rw-r--r--gcc/ipa-strub.cc3
-rw-r--r--gcc/langhooks-def.h12
-rw-r--r--gcc/langhooks.cc26
-rw-r--r--gcc/langhooks.h16
-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/omp-general.h86
-rw-r--r--gcc/passes.cc25
-rw-r--r--gcc/pretty-print.cc6
-rw-r--r--gcc/pretty-print.h17
-rw-r--r--gcc/rtl-ssa/changes.cc18
-rw-r--r--gcc/rtl.h10
-rw-r--r--gcc/rtlanal.cc17
-rw-r--r--gcc/testsuite/ChangeLog355
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-mapper-10.c30
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-mapper-11.c70
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-mapper-12.c22
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-mapper-3.c30
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-mapper-4.c78
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-mapper-5.c26
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-mapper-6.c23
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-mapper-7.c29
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-mapper-8.c43
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-mapper-9.c34
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-variant-2.c15
-rw-r--r--gcc/testsuite/c-c++-common/gomp/map-6.c20
-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.c25
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr120180.c22
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr109283.C23
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr118903.C40
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr120453.C95
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/constexpr-lambda29.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda16.C39
-rw-r--r--gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda17.C144
-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/diagnostic/bad-binary-ops-highlight-colors.C4
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/long-short-colorization.C8
-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/declare-mapper-1.C58
-rw-r--r--gcc/testsuite/g++.dg/gomp/declare-mapper-2.C30
-rw-r--r--gcc/testsuite/g++.dg/gomp/declare-mapper-3.C39
-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/plugin/show-template-tree-color-labels.C4
-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/mv-symbols1.C68
-rw-r--r--gcc/testsuite/g++.target/i386/mv-symbols2.C56
-rw-r--r--gcc/testsuite/g++.target/i386/mv-symbols3.C44
-rw-r--r--gcc/testsuite/g++.target/i386/mv-symbols4.C50
-rw-r--r--gcc/testsuite/g++.target/i386/mv-symbols5.C56
-rw-r--r--gcc/testsuite/g++.target/i386/mvc-symbols1.C44
-rw-r--r--gcc/testsuite/g++.target/i386/mvc-symbols2.C29
-rw-r--r--gcc/testsuite/g++.target/i386/mvc-symbols3.C35
-rw-r--r--gcc/testsuite/g++.target/i386/mvc-symbols4.C23
-rw-r--r--gcc/testsuite/g++.target/i386/pr103750.C39
-rw-r--r--gcc/testsuite/g++.target/powerpc/mvc-symbols1.C47
-rw-r--r--gcc/testsuite/g++.target/powerpc/mvc-symbols2.C35
-rw-r--r--gcc/testsuite/g++.target/powerpc/mvc-symbols3.C41
-rw-r--r--gcc/testsuite/g++.target/powerpc/mvc-symbols4.C29
-rw-r--r--gcc/testsuite/gcc.dg/bad-binary-ops-highlight-colors.c4
-rw-r--r--gcc/testsuite/gcc.dg/format/colors.c4
-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.c11
-rw-r--r--gcc/testsuite/gcc.dg/gomp/declare-mapper-10.c61
-rw-r--r--gcc/testsuite/gcc.dg/gomp/declare-mapper-11.c33
-rw-r--r--gcc/testsuite/gcc.dg/gomp/declare-mapper-13.c13
-rw-r--r--gcc/testsuite/gcc.dg/gomp/udr-3.c8
-rw-r--r--gcc/testsuite/gcc.dg/ipa/pr120295.c66
-rw-r--r--gcc/testsuite/gcc.dg/pr120353.c11
-rw-r--r--gcc/testsuite/gcc.dg/pr120354.c33
-rw-r--r--gcc/testsuite/gcc.dg/pr120380.c24
-rw-r--r--gcc/testsuite/gcc.dg/pr120381.c10
-rw-r--r--gcc/testsuite/gcc.dg/pr120480.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr120341-1.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr120341-2.c13
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr120347.c13
-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/reduc-pshuf.c16
-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-57.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-58.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-59.c5
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/avg.h17
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i32.c12
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i64.c12
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i32-from-i64.c12
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i16.c12
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i32.c12
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i64.c12
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i16-from-i32.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i16-from-i64.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i32-from-i64.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i16.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i32.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i64.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_data.h176
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/param-autovec-mode.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-4.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-5.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-6.c6
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv32gcv.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv64gcv.c2
-rw-r--r--gcc/testsuite/gfortran.dg/c_f_pointer_tests_6.f902
-rw-r--r--gcc/testsuite/gfortran.dg/inquiry_type_ref_8.f90214
-rw-r--r--gcc/testsuite/gfortran.dg/interface_62.f9039
-rw-r--r--gcc/testsuite/gfortran.dg/pr119856.f9015
-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.exp45
-rw-r--r--gcc/tree-core.h4
-rw-r--r--gcc/tree-inline.cc1
-rw-r--r--gcc/tree-nrv.cc19
-rw-r--r--gcc/tree-pass.h6
-rw-r--r--gcc/tree-pretty-print.cc41
-rw-r--r--gcc/tree-ssa-forwprop.cc13
-rw-r--r--gcc/tree-ssa-loop-im.cc3
-rw-r--r--gcc/tree-ssa-phiopt.cc5
-rw-r--r--gcc/tree-switch-conversion.cc3
-rw-r--r--gcc/tree-vect-loop.cc3
-rw-r--r--gcc/tree-vect-slp.cc9
-rw-r--r--gcc/tree-vrp.cc4
-rw-r--r--gcc/tree.cc2
-rw-r--r--gcc/tree.def7
-rw-r--r--gcc/tree.h19
226 files changed, 8040 insertions, 839 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ca53504..74490c4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,356 @@
+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.
+
+2025-05-29 Andrew Pinski <quic_apinski@quicinc.com>
+
+ * tree-ssa-forwprop.cc (optimize_memcpy_to_memset): Adds
+ statistics when the statement changed.
+
+2025-05-29 Andrew Pinski <quic_apinski@quicinc.com>
+
+ * tree-ssa-forwprop.cc (optimize_memcpy_to_memset): Change check
+ from NULL/non-ssa name to default name.
+
+2025-05-29 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostic-format-html.cc (HTML_STYLE): Fix PatternFly URL in
+ comment.
+
+2025-05-29 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostic-format-html.cc
+ (html_builder::make_element_for_diagnostic::html_token_printer):
+ Reimplement in terms of xml::printer.
+ (html_builder::make_element_for_diagnostic): Create an
+ xml::printer and use it with the html_token_printer.
+
+2025-05-29 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostic-format-html.cc (html_builder::make_metadata_element):
+ Gracefully handle the case where "url" is null.
+
+2025-05-29 David Malcolm <dmalcolm@redhat.com>
+
+ * pretty-print.cc (pretty_printer::pretty_printer): Use "nullptr"
+ rather than "NULL". Remove explicit delete of
+ m_format_postprocessor.
+ * pretty-print.h (format_postprocessor::clone): Use unique_ptr.
+ (pretty_printer::set_format_postprocessor): New.
+ (pretty_printer::m_format_postprocessor): Use unique_ptr.
+ (pp_format_postprocessor): Update for use of unique_ptr, removing
+ reference from return type.
+
+2025-05-29 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/120295
+ * ipa-prop.cc (update_jump_functions_after_inlining): Do not
+ combine pass-through jump functions with type-casts changing
+ signedness.
+
+2025-05-29 Martin Jambor <mjambor@suse.cz>
+
+ * ipa-prop.cc (ipa_dump_jump_function): Fix whitespace when
+ dumping IPA VRs.
+
+2025-05-29 Pranav Gorantla <Pranav.Gorantla@amd.com>
+
+ * config/i386/i386-expand.cc (emit_reduc_half): Use shuffles to
+ generate reduc half for V4SI, similar modes.
+ * config/i386/i386.h (TARGET_SSE_REDUCTION_PREFER_PSHUF): New Macro.
+ * config/i386/x86-tune.def (X86_TUNE_SSE_REDUCTION_PREFER_PSHUF):
+ New tuning.
+
+2025-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR bootstrap/120464
+ * ggc-page.cc (struct ggc_globals): Fix up comment formatting.
+ (find_free_list): Likewise.
+ (alloc_page): For defined(USING_MALLOC_PAGE_GROUPS) use
+ free_list->free_pages instead of G.free_pages.
+ (do_release_pages): Add n1 and n2 arguments, make them used.
+ Move defined(USING_MALLOC_PAGE_GROUPS) page group freeing to
+ release_pages and dumping of statistics as well. Formatting fixes.
+ (release_pages): Adjust do_release_pages caller, move here
+ defined(USING_MALLOC_PAGE_GROUPS) page group freeing and dumping
+ of statistics.
+ (ggc_handle_finalizers): Fix up comment formatting and typo.
+
+2025-05-29 Jerry Zhang Jian <jerry.zhangjian@sifive.com>
+
+ * config/riscv/riscv-ext.def: New extensions
+ * config/riscv/riscv-ext.opt: Auto re-generated
+ * doc/riscv-ext.texi: Auto re-generated
+
+2025-05-29 Pan Li <pan2.li@intel.com>
+
+ * config/riscv/riscv-v.cc (expand_vx_binary_vec_dup_vec): Add
+ new case for MULT op.
+ (expand_vx_binary_vec_vec_dup): Ditto.
+ * config/riscv/riscv.cc (riscv_rtx_costs): Ditto.
+ * config/riscv/vector-iterators.md: Add new op mult to no_shift_vx_ops.
+
2025-05-28 Jan Hubicka <hubicka@ucw.cz>
PR target/119298
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 9398513..42c5479 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20250529
+20250603
diff --git a/gcc/auto-profile.cc b/gcc/auto-profile.cc
index 3eefb97..91cc8db 100644
--- a/gcc/auto-profile.cc
+++ b/gcc/auto-profile.cc
@@ -233,6 +233,10 @@ public:
function_instance *get_function_instance_by_decl (unsigned lineno,
tree decl) const;
+ /* Merge profile of clones. Note that cloning hasnt been performed when
+ we annotate the CFG (at this stage). */
+ void merge (function_instance *other);
+
/* Store the profile info for LOC in INFO. Return TRUE if profile info
is found. */
bool get_count_info (location_t loc, count_info *info) const;
@@ -558,6 +562,27 @@ function_instance::get_function_instance_by_decl (unsigned lineno,
return NULL;
}
+/* Merge profile of clones. Note that cloning hasnt been performed when
+ we annotate the CFG (at this stage). */
+
+void function_instance::merge (function_instance *other)
+{
+ total_count_ += other->total_count_;
+ head_count_ += other->head_count_;
+
+ for (callsite_map::const_iterator iter = other->callsites.begin ();
+ iter != other->callsites.end (); ++iter)
+ if (callsites.count (iter->first) == 0)
+ callsites[iter->first] = iter->second;
+
+ for (position_count_map::const_iterator iter = pos_counts.begin ();
+ iter != pos_counts.end (); ++iter)
+ if (pos_counts.count (iter->first) == 0)
+ pos_counts[iter->first] = iter->second;
+ else
+ pos_counts[iter->first].count += iter->second.count;
+}
+
/* Store the profile info for LOC in INFO. Return TRUE if profile info
is found. */
@@ -838,7 +863,14 @@ autofdo_source_profile::read ()
function_instance::function_instance_stack stack;
function_instance *s = function_instance::read_function_instance (
&stack, gcov_read_counter ());
- map_[s->name ()] = s;
+ int fun_id = afdo_string_table->get_index
+ (afdo_string_table->get_name (s->name ()));
+ /* If function_instace with get_original_name (without the clone
+ suffix) exixts, merge the function instances. */
+ if (map_.count (fun_id) == 0)
+ map_[fun_id] = s;
+ else
+ map_[fun_id]->merge (s);
}
return true;
}
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 8de6ae5..f543372 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,15 @@
+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-common.h b/gcc/c-family/c-common.h
index 91fd120..675708d 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1303,10 +1303,12 @@ enum c_omp_region_type
C_ORT_TARGET = 1 << 3,
C_ORT_EXIT_DATA = 1 << 4,
C_ORT_INTEROP = 1 << 5,
+ C_ORT_DECLARE_MAPPER = 1 << 6,
C_ORT_OMP_DECLARE_SIMD = C_ORT_OMP | C_ORT_DECLARE_SIMD,
C_ORT_OMP_TARGET = C_ORT_OMP | C_ORT_TARGET,
C_ORT_OMP_EXIT_DATA = C_ORT_OMP | C_ORT_EXIT_DATA,
C_ORT_OMP_INTEROP = C_ORT_OMP | C_ORT_INTEROP,
+ C_ORT_OMP_DECLARE_MAPPER = C_ORT_OMP | C_ORT_DECLARE_MAPPER,
C_ORT_ACC_TARGET = C_ORT_ACC | C_ORT_TARGET
};
@@ -1345,6 +1347,9 @@ extern enum omp_clause_defaultmap_kind c_omp_predetermined_mapping (tree);
extern tree c_omp_check_context_selector (location_t, tree);
extern void c_omp_mark_declare_variant (location_t, tree, tree);
extern void c_omp_adjust_map_clauses (tree, bool);
+template<typename T> struct omp_mapper_list;
+extern void c_omp_find_nested_mappers (struct omp_mapper_list<tree> *, tree);
+extern tree c_omp_instantiate_mappers (tree);
namespace omp_addr_tokenizer { struct omp_addr_token; }
typedef omp_addr_tokenizer::omp_addr_token omp_addr_token;
diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc
index a92c6e3..13de2fe 100644
--- a/gcc/c-family/c-omp.cc
+++ b/gcc/c-family/c-omp.cc
@@ -4282,6 +4282,306 @@ c_omp_address_inspector::expand_map_clause (tree c, tree expr,
return error_mark_node;
}
+/* Given a mapper function MAPPER_FN, recursively scan through the map clauses
+ for that mapper, and if any of those should use a (named or unnamed) mapper
+ themselves, add it to MLIST. */
+
+void
+c_omp_find_nested_mappers (omp_mapper_list<tree> *mlist, tree mapper_fn)
+{
+ tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
+ tree mapper_name = NULL_TREE;
+
+ if (mapper == error_mark_node)
+ return;
+
+ gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER);
+
+ for (tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper);
+ clause;
+ clause = OMP_CLAUSE_CHAIN (clause))
+ {
+ tree expr = OMP_CLAUSE_DECL (clause);
+ enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (clause);
+ tree elem_type;
+
+ if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
+ {
+ mapper_name = expr;
+ continue;
+ }
+ else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
+ {
+ mapper_name = NULL_TREE;
+ continue;
+ }
+
+ gcc_assert (TREE_CODE (expr) != TREE_LIST);
+ if (TREE_CODE (expr) == OMP_ARRAY_SECTION)
+ {
+ while (TREE_CODE (expr) == OMP_ARRAY_SECTION)
+ expr = TREE_OPERAND (expr, 0);
+
+ elem_type = TREE_TYPE (expr);
+ }
+ else
+ elem_type = TREE_TYPE (expr);
+
+ /* This might be too much... or not enough? */
+ while (TREE_CODE (elem_type) == ARRAY_TYPE
+ || TREE_CODE (elem_type) == POINTER_TYPE
+ || TREE_CODE (elem_type) == REFERENCE_TYPE)
+ elem_type = TREE_TYPE (elem_type);
+
+ elem_type = TYPE_MAIN_VARIANT (elem_type);
+
+ if (RECORD_OR_UNION_TYPE_P (elem_type)
+ && !mlist->contains (mapper_name, elem_type))
+ {
+ tree nested_mapper_fn
+ = lang_hooks.decls.omp_mapper_lookup (mapper_name, elem_type);
+
+ if (nested_mapper_fn)
+ {
+ mlist->add_mapper (mapper_name, elem_type, nested_mapper_fn);
+ c_omp_find_nested_mappers (mlist, nested_mapper_fn);
+ }
+ else if (mapper_name)
+ {
+ error ("mapper %qE not found for type %qT", mapper_name,
+ elem_type);
+ continue;
+ }
+ }
+ }
+}
+
+struct remap_mapper_decl_info
+{
+ tree dummy_var;
+ tree expr;
+};
+
+/* Helper for rewriting DUMMY_VAR into EXPR in a map clause decl. */
+
+static tree
+remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data)
+{
+ remap_mapper_decl_info *map_info = (remap_mapper_decl_info *) data;
+
+ if (operand_equal_p (*tp, map_info->dummy_var))
+ {
+ *tp = map_info->expr;
+ *walk_subtrees = 0;
+ }
+
+ return NULL_TREE;
+}
+
+/* Instantiate a mapper MAPPER for expression EXPR, adding new clauses to
+ OUTLIST. OUTER_KIND is the mapping kind to use if not already specified in
+ the mapper declaration. */
+
+static tree *
+omp_instantiate_mapper (tree *outlist, tree mapper, tree expr,
+ enum gomp_map_kind outer_kind)
+{
+ tree clauses = OMP_DECLARE_MAPPER_CLAUSES (mapper);
+ tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper);
+ tree mapper_name = NULL_TREE;
+
+ remap_mapper_decl_info map_info;
+ map_info.dummy_var = dummy_var;
+ map_info.expr = expr;
+
+ for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ {
+ tree unshared = unshare_expr (c);
+ enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (c);
+ tree t = OMP_CLAUSE_DECL (unshared);
+ tree type = NULL_TREE;
+ bool nonunit_array_with_mapper = false;
+
+ if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
+ {
+ mapper_name = t;
+ continue;
+ }
+ else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
+ {
+ mapper_name = NULL_TREE;
+ continue;
+ }
+
+ if (TREE_CODE (t) == OMP_ARRAY_SECTION)
+ {
+ location_t loc = OMP_CLAUSE_LOCATION (c);
+ tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
+
+ if (t2 == t)
+ {
+ nonunit_array_with_mapper = true;
+ /* We'd want use the mapper for the element type if this worked:
+ look that one up. */
+ type = TREE_TYPE (TREE_TYPE (t));
+ }
+ else
+ {
+ t = t2;
+ type = TREE_TYPE (t);
+ }
+ }
+ else
+ type = TREE_TYPE (t);
+
+ gcc_assert (type);
+
+ if (type == error_mark_node)
+ continue;
+
+ walk_tree (&unshared, remap_mapper_decl_1, &map_info, NULL);
+
+ if (OMP_CLAUSE_MAP_KIND (unshared) == GOMP_MAP_UNSET)
+ OMP_CLAUSE_SET_MAP_KIND (unshared, outer_kind);
+
+ type = TYPE_MAIN_VARIANT (type);
+
+ tree mapper_fn = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
+
+ if (mapper_fn && nonunit_array_with_mapper)
+ {
+ sorry ("user-defined mapper with non-unit length array section");
+ continue;
+ }
+ else if (mapper_fn)
+ {
+ tree nested_mapper
+ = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
+ if (nested_mapper != mapper)
+ {
+ if (clause_kind == GOMP_MAP_UNSET)
+ clause_kind = outer_kind;
+
+ outlist = omp_instantiate_mapper (outlist, nested_mapper,
+ t, clause_kind);
+ continue;
+ }
+ }
+ else if (mapper_name)
+ {
+ error ("mapper %qE not found for type %qT", mapper_name, type);
+ continue;
+ }
+
+ *outlist = unshared;
+ outlist = &OMP_CLAUSE_CHAIN (unshared);
+ }
+
+ return outlist;
+}
+
+/* Given a list of CLAUSES, scan each clause and invoke a user-defined mapper
+ appropriate to the type of the data in that clause, if such a mapper is
+ visible in the current parsing context. */
+
+tree
+c_omp_instantiate_mappers (tree clauses)
+{
+ tree c, *pc, mapper_name = NULL_TREE;
+
+ for (pc = &clauses, c = clauses; c; c = *pc)
+ {
+ bool using_mapper = false;
+
+ switch (OMP_CLAUSE_CODE (c))
+ {
+ case OMP_CLAUSE_MAP:
+ {
+ tree t = OMP_CLAUSE_DECL (c);
+ tree type = NULL_TREE;
+ bool nonunit_array_with_mapper = false;
+
+ if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POP_MAPPER_NAME)
+ {
+ if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME)
+ mapper_name = OMP_CLAUSE_DECL (c);
+ else
+ mapper_name = NULL_TREE;
+ pc = &OMP_CLAUSE_CHAIN (c);
+ continue;
+ }
+
+ if (TREE_CODE (t) == OMP_ARRAY_SECTION)
+ {
+ location_t loc = OMP_CLAUSE_LOCATION (c);
+ tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
+
+ if (t2 == t)
+ {
+ /* !!! Array sections of size >1 with mappers for elements
+ are hard to support. Do something here. */
+ nonunit_array_with_mapper = true;
+ type = TREE_TYPE (TREE_TYPE (t));
+ }
+ else
+ {
+ t = t2;
+ type = TREE_TYPE (t);
+ }
+ }
+ else
+ type = TREE_TYPE (t);
+
+ if (type == NULL_TREE || type == error_mark_node)
+ {
+ pc = &OMP_CLAUSE_CHAIN (c);
+ continue;
+ }
+
+ enum gomp_map_kind kind = OMP_CLAUSE_MAP_KIND (c);
+ if (kind == GOMP_MAP_UNSET)
+ kind = GOMP_MAP_TOFROM;
+
+ type = TYPE_MAIN_VARIANT (type);
+
+ tree mapper_fn
+ = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
+
+ if (mapper_fn && nonunit_array_with_mapper)
+ {
+ sorry ("user-defined mapper with non-unit length "
+ "array section");
+ using_mapper = true;
+ }
+ else if (mapper_fn)
+ {
+ tree mapper
+ = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
+ pc = omp_instantiate_mapper (pc, mapper, t, kind);
+ using_mapper = true;
+ }
+ else if (mapper_name)
+ {
+ error ("mapper %qE not found for type %qT", mapper_name, type);
+ using_mapper = true;
+ }
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ if (using_mapper)
+ *pc = OMP_CLAUSE_CHAIN (c);
+ else
+ pc = &OMP_CLAUSE_CHAIN (c);
+ }
+
+ return clauses;
+}
+
const struct c_omp_directive c_omp_directives[] = {
/* Keep this alphabetically sorted by the first word. Non-null second/third
if any should precede null ones. */
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index c8587b4..53ad780 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,76 @@
+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
+ the equivalent function in the C++ front end.
+ (c_parser_skip_to_end_of_block_or_statement): Pass false to
+ the error flag.
+ (c_parser_omp_context_selector): Immediately return error_mark_node
+ after giving an error that the integer trait property is invalid,
+ similarly to C++ front end.
+ (c_parser_omp_context_selector_specification): Likewise handle
+ error return from c_parser_omp_context_selector similarly to C++.
+ (c_parser_omp_metadirective): Do not call
+ c_parser_skip_to_end_of_block_or_statement after an error.
+
+2025-05-29 Sandra Loosemore <sloosemore@baylibre.com>
+
+ PR c/120180
+ * c-parser.cc (c_parser_omp_metadirective): Only consume the
+ token if it is the expected close paren.
+
2025-05-27 Jakub Jelinek <jakub@redhat.com>
PR c/117025
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 33d0ec1..1008bca 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9649,15 +9649,18 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
DECL_NOT_FLEXARRAY (x) = !is_flexible_array_member_p (is_last_field, x);
/* Set TYPE_INCLUDES_FLEXARRAY for the context of x, t.
- when x is an array and is the last field. */
+ when x is an array and is the last field.
+ There is only one last_field for a structure type, but there might
+ be multiple last_fields for a union type, therefore we should ORed
+ the result for multiple last_fields. */
if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
TYPE_INCLUDES_FLEXARRAY (t)
- = is_last_field && c_flexible_array_member_type_p (TREE_TYPE (x));
+ |= is_last_field && c_flexible_array_member_type_p (TREE_TYPE (x));
/* Recursively set TYPE_INCLUDES_FLEXARRAY for the context of x, t
when x is an union or record and is the last field. */
else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
TYPE_INCLUDES_FLEXARRAY (t)
- = is_last_field && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (x));
+ |= is_last_field && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (x));
if (warn_flex_array_member_not_at_end
&& !is_last_field
@@ -9893,6 +9896,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t);
C_TYPE_VARIABLY_MODIFIED (x) = C_TYPE_VARIABLY_MODIFIED (t);
C_TYPE_INCOMPLETE_VARS (x) = NULL_TREE;
+ TYPE_INCLUDES_FLEXARRAY (x) = TYPE_INCLUDES_FLEXARRAY (t);
}
/* Update type location to the one of the definition, instead of e.g.
@@ -13823,6 +13827,174 @@ c_check_omp_declare_reduction_r (tree *tp, int *, void *data)
return NULL_TREE;
}
+/* Return identifier to look up for omp declare mapper. */
+
+tree
+c_omp_mapper_id (tree mapper_id)
+{
+ const char *p = NULL;
+
+ const char prefix[] = "omp declare mapper ";
+
+ if (mapper_id == NULL_TREE)
+ p = "<default>";
+ else if (TREE_CODE (mapper_id) == IDENTIFIER_NODE)
+ p = IDENTIFIER_POINTER (mapper_id);
+ else
+ return error_mark_node;
+
+ size_t lenp = sizeof (prefix);
+ size_t len = strlen (p);
+ char *name = XALLOCAVEC (char, lenp + len);
+ memcpy (name, prefix, lenp - 1);
+ memcpy (name + lenp - 1, p, len + 1);
+ return get_identifier (name);
+}
+
+/* Lookup MAPPER_ID in the current scope, or create an artificial
+ VAR_DECL, bind it into the current scope and return it. */
+
+tree
+c_omp_mapper_decl (tree mapper_id)
+{
+ struct c_binding *b = I_SYMBOL_BINDING (mapper_id);
+ if (b != NULL && B_IN_CURRENT_SCOPE (b))
+ return b->decl;
+
+ tree decl = build_decl (BUILTINS_LOCATION, VAR_DECL,
+ mapper_id, integer_type_node);
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_EXTERNAL (decl) = 1;
+ TREE_STATIC (decl) = 1;
+ TREE_PUBLIC (decl) = 0;
+ bind (mapper_id, decl, current_scope, true, false, BUILTINS_LOCATION);
+ return decl;
+}
+
+/* Lookup MAPPER_ID in the first scope where it has entry for TYPE. */
+
+tree
+c_omp_mapper_lookup (tree mapper_id, tree type)
+{
+ if (!RECORD_OR_UNION_TYPE_P (type))
+ return NULL_TREE;
+
+ mapper_id = c_omp_mapper_id (mapper_id);
+
+ struct c_binding *b = I_SYMBOL_BINDING (mapper_id);
+ while (b)
+ {
+ tree t;
+ for (t = DECL_INITIAL (b->decl); t; t = TREE_CHAIN (t))
+ if (comptypes (TREE_PURPOSE (t), type))
+ return TREE_VALUE (t);
+ b = b->shadowed;
+ }
+ return NULL_TREE;
+}
+
+/* For C, we record a pointer to the mapper itself without wrapping it in an
+ artificial function or similar. So, just return it. */
+
+tree
+c_omp_extract_mapper_directive (tree mapper)
+{
+ return mapper;
+}
+
+/* For now we can handle singleton OMP_ARRAY_SECTIONs with custom mappers, but
+ nothing more complicated. */
+
+tree
+c_omp_map_array_section (location_t loc, tree t)
+{
+ tree low = TREE_OPERAND (t, 1);
+ tree len = TREE_OPERAND (t, 2);
+
+ if (len && integer_onep (len))
+ {
+ t = TREE_OPERAND (t, 0);
+
+ if (!low)
+ low = integer_zero_node;
+
+ t = build_array_ref (loc, t, low);
+ }
+
+ return t;
+}
+
+/* Helper function for below function. */
+
+static tree
+c_omp_scan_mapper_bindings_r (tree *tp, int *walk_subtrees, void *ptr)
+{
+ tree t = *tp;
+ omp_mapper_list<tree> *mlist = (omp_mapper_list<tree> *) ptr;
+ tree aggr_type = NULL_TREE;
+
+ if (TREE_CODE (t) == SIZEOF_EXPR
+ || TREE_CODE (t) == ALIGNOF_EXPR)
+ {
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+
+ if (TREE_CODE (t) == OMP_CLAUSE)
+ return NULL_TREE;
+
+ if (TREE_CODE (t) == COMPONENT_REF
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0))))
+ aggr_type = TREE_TYPE (TREE_OPERAND (t, 0));
+ else if ((TREE_CODE (t) == VAR_DECL
+ || TREE_CODE (t) == PARM_DECL
+ || TREE_CODE (t) == RESULT_DECL)
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
+ aggr_type = TREE_TYPE (t);
+
+ if (aggr_type)
+ {
+ tree mapper_fn = c_omp_mapper_lookup (NULL_TREE, aggr_type);
+ if (mapper_fn)
+ mlist->add_mapper (NULL_TREE, aggr_type, mapper_fn);
+ }
+
+ return NULL_TREE;
+}
+
+/* Scan an offload region's body, and record uses of struct- or union-typed
+ variables. Add _mapper_binding_ fake clauses to *CLAUSES_PTR. */
+
+void
+c_omp_scan_mapper_bindings (location_t loc, tree *clauses_ptr, tree body)
+{
+ hash_set<omp_name_type<tree>> seen_types;
+ auto_vec<tree> mappers;
+ omp_mapper_list<tree> mlist (&seen_types, &mappers);
+
+ walk_tree_without_duplicates (&body, c_omp_scan_mapper_bindings_r, &mlist);
+
+ unsigned int i;
+ tree mapper;
+ FOR_EACH_VEC_ELT (mappers, i, mapper)
+ c_omp_find_nested_mappers (&mlist, mapper);
+
+ FOR_EACH_VEC_ELT (mappers, i, mapper)
+ {
+ if (mapper == error_mark_node)
+ continue;
+ tree mapper_name = OMP_DECLARE_MAPPER_ID (mapper);
+ tree decl = OMP_DECLARE_MAPPER_DECL (mapper);
+
+ tree c = build_omp_clause (loc, OMP_CLAUSE__MAPPER_BINDING_);
+ OMP_CLAUSE__MAPPER_BINDING__ID (c) = mapper_name;
+ OMP_CLAUSE__MAPPER_BINDING__DECL (c) = decl;
+ OMP_CLAUSE__MAPPER_BINDING__MAPPER (c) = mapper;
+
+ OMP_CLAUSE_CHAIN (c) = *clauses_ptr;
+ *clauses_ptr = c;
+ }
+}
bool
c_check_in_current_scope (tree decl)
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-objc-common.h b/gcc/c/c-objc-common.h
index 84bd357..84f6fd3 100644
--- a/gcc/c/c-objc-common.h
+++ b/gcc/c/c-objc-common.h
@@ -137,6 +137,18 @@ static const scoped_attribute_specs *const c_objc_attribute_table[] =
#undef LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP
#define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP c_omp_clause_copy_ctor
+#undef LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES
+#define LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES c_omp_finish_mapper_clauses
+
+#undef LANG_HOOKS_OMP_MAPPER_LOOKUP
+#define LANG_HOOKS_OMP_MAPPER_LOOKUP c_omp_mapper_lookup
+
+#undef LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE
+#define LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE c_omp_extract_mapper_directive
+
+#undef LANG_HOOKS_OMP_MAP_ARRAY_SECTION
+#define LANG_HOOKS_OMP_MAP_ARRAY_SECTION c_omp_map_array_section
+
#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_var_mod_p
#endif /* GCC_C_OBJC_COMMON */
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 0d79f58..85580c5 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -1420,6 +1420,51 @@ c_parser_skip_to_end_of_parameter (c_parser *parser)
parser->error = false;
}
+/* Skip tokens until a non-nested closing curly brace is the next
+ token, or there are no more tokens. Return true in the first case,
+ false otherwise. */
+
+static bool
+c_parser_skip_to_closing_brace (c_parser *parser)
+{
+ unsigned nesting_depth = 0;
+
+ while (true)
+ {
+ c_token *token = c_parser_peek_token (parser);
+
+ switch (token->type)
+ {
+ case CPP_PRAGMA_EOL:
+ if (!parser->in_pragma)
+ break;
+ /* FALLTHRU */
+ case CPP_EOF:
+ /* If we've run out of tokens, stop. */
+ return false;
+
+ case CPP_CLOSE_BRACE:
+ /* If the next token is a non-nested `}', then we have reached
+ the end of the current block. */
+ if (nesting_depth-- == 0)
+ return true;
+ break;
+
+ case CPP_OPEN_BRACE:
+ /* If it the next token is a `{', then we are entering a new
+ block. Consume the entire block. */
+ ++nesting_depth;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Consume the token. */
+ c_parser_consume_token (parser);
+ }
+}
+
/* Expect to be at the end of the pragma directive and consume an
end of line marker. */
@@ -1535,7 +1580,7 @@ c_parser_skip_to_end_of_block_or_statement (c_parser *parser,
here for secondary error recovery, after parser->error has
been cleared. */
c_parser_consume_pragma (parser);
- c_parser_skip_to_pragma_eol (parser);
+ c_parser_skip_to_pragma_eol (parser, false);
parser->error = save_error;
continue;
@@ -19988,11 +20033,11 @@ c_parser_omp_clause_doacross (c_parser *parser, tree list)
always | close */
static tree
-c_parser_omp_clause_map (c_parser *parser, tree list)
+c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
{
location_t clause_loc = c_parser_peek_token (parser)->location;
- enum gomp_map_kind kind = GOMP_MAP_TOFROM;
tree nl, c;
+ enum gomp_map_kind kind = declare_mapper_p ? GOMP_MAP_UNSET : GOMP_MAP_TOFROM;
matching_parens parens;
if (!parens.require_open (parser))
@@ -20010,12 +20055,26 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
pos++;
+ else if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
+ == CPP_OPEN_PAREN)
+ {
+ unsigned int npos = pos + 2;
+ if (c_parser_check_balanced_raw_token_sequence (parser, &npos)
+ && (c_parser_peek_nth_token_raw (parser, npos)->type
+ == CPP_CLOSE_PAREN)
+ && (c_parser_peek_nth_token_raw (parser, npos + 1)->type
+ == CPP_COMMA))
+ pos = npos + 1;
+ }
+
pos++;
}
int always_modifier = 0;
int close_modifier = 0;
int present_modifier = 0;
+ int mapper_modifier = 0;
+ tree mapper_name = NULL_TREE;
for (int pos = 1; pos < map_kind_pos; ++pos)
{
c_token *tok = c_parser_peek_token (parser);
@@ -20036,6 +20095,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
return list;
}
always_modifier++;
+ c_parser_consume_token (parser);
}
else if (strcmp ("close", p) == 0)
{
@@ -20046,6 +20106,66 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
return list;
}
close_modifier++;
+ c_parser_consume_token (parser);
+ }
+ else if (strcmp ("mapper", p) == 0)
+ {
+ c_parser_consume_token (parser);
+
+ matching_parens mparens;
+ if (mparens.require_open (parser))
+ {
+ if (mapper_modifier)
+ {
+ c_parser_error (parser, "too many %<mapper%> modifiers");
+ /* Assume it's a well-formed mapper modifier, even if it
+ seems to be in the wrong place. */
+ c_parser_consume_token (parser);
+ mparens.require_close (parser);
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+
+ tok = c_parser_peek_token (parser);
+
+ switch (tok->type)
+ {
+ case CPP_NAME:
+ {
+ mapper_name = tok->value;
+ c_parser_consume_token (parser);
+ if (declare_mapper_p)
+ {
+ error_at (tok->location,
+ "in %<declare mapper%> directives, parameter "
+ "to %<mapper%> modifier must be %<default%>");
+ }
+ }
+ break;
+
+ case CPP_KEYWORD:
+ if (tok->keyword == RID_DEFAULT)
+ {
+ c_parser_consume_token (parser);
+ break;
+ }
+ /* Fallthrough. */
+
+ default:
+ error_at (tok->location,
+ "expected identifier or %<default%>");
+ return list;
+ }
+
+ if (!mparens.require_close (parser))
+ {
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+
+ mapper_modifier++;
+ pos += 3;
+ }
}
else if (strcmp ("present", p) == 0)
{
@@ -20056,16 +20176,16 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
return list;
}
present_modifier++;
+ c_parser_consume_token (parser);
}
else
{
c_parser_error (parser, "%<map%> clause with map-type modifier other "
- "than %<always%>, %<close%> or %<present%>");
+ "than %<always%>, %<close%>, %<mapper%> or "
+ "%<present%>");
parens.skip_until_found_close (parser);
return list;
}
-
- c_parser_consume_token (parser);
}
if (c_parser_next_token_is (parser, CPP_NAME)
@@ -20109,8 +20229,30 @@ c_parser_omp_clause_map (c_parser *parser, tree list)
nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list,
true);
+ tree last_new = NULL_TREE;
+
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_SET_MAP_KIND (c, kind);
+ {
+ OMP_CLAUSE_SET_MAP_KIND (c, kind);
+ last_new = c;
+ }
+
+ if (mapper_name)
+ {
+ tree name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_PUSH_MAPPER_NAME);
+ OMP_CLAUSE_DECL (name) = mapper_name;
+ OMP_CLAUSE_CHAIN (name) = nl;
+ nl = name;
+
+ gcc_assert (last_new);
+
+ name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_POP_MAPPER_NAME);
+ OMP_CLAUSE_DECL (name) = null_pointer_node;
+ OMP_CLAUSE_CHAIN (name) = OMP_CLAUSE_CHAIN (last_new);
+ OMP_CLAUSE_CHAIN (last_new) = name;
+ }
parens.skip_until_found_close (parser);
return nl;
@@ -21479,7 +21621,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
c_name = "interop";
break;
case PRAGMA_OMP_CLAUSE_MAP:
- clauses = c_parser_omp_clause_map (parser, clauses);
+ clauses = c_parser_omp_clause_map (parser, clauses, false);
c_name = "map";
break;
case PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR:
@@ -26298,7 +26440,7 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
{
location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_pragma (parser);
- tree *pc = NULL, stmt, block;
+ tree *pc = NULL, stmt, block, body, clauses;
if (context != pragma_stmt && context != pragma_compound)
{
@@ -26453,10 +26595,9 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
stmt = make_node (OMP_TARGET);
TREE_TYPE (stmt) = void_type_node;
- OMP_TARGET_CLAUSES (stmt)
- = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
- "#pragma omp target", false);
- for (tree c = OMP_TARGET_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
+ clauses = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
+ "#pragma omp target", false);
+ for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
{
tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
@@ -26465,14 +26606,19 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
OMP_CLAUSE_CHAIN (c) = nc;
}
- OMP_TARGET_CLAUSES (stmt)
- = c_finish_omp_clauses (OMP_TARGET_CLAUSES (stmt), C_ORT_OMP_TARGET);
- c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
+ clauses = c_omp_instantiate_mappers (clauses);
+ clauses = c_finish_omp_clauses (clauses, C_ORT_OMP_TARGET);
+ c_omp_adjust_map_clauses (clauses, true);
- pc = &OMP_TARGET_CLAUSES (stmt);
keep_next_level ();
block = c_begin_compound_stmt (true);
- add_stmt (c_parser_omp_structured_block (parser, if_p));
+ body = c_parser_omp_structured_block (parser, if_p);
+
+ c_omp_scan_mapper_bindings (loc, &clauses, body);
+
+ add_stmt (body);
+ OMP_TARGET_CLAUSES (stmt) = clauses;
+ pc = &OMP_TARGET_CLAUSES (stmt);
OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
SET_EXPR_LOCATION (stmt, loc);
@@ -26820,20 +26966,31 @@ 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;
- if (t != error_mark_node)
+ {
+ 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);
+ if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
{
- mark_exp_read (t);
- t = c_fully_fold (t, false, NULL);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
- error_at (token->location,
- "property must be integer expression");
- else
- properties = make_trait_property (NULL_TREE, t,
- properties);
+ t = c_objc_common_truthvalue_conversion (token->location,
+ t,
+ boolean_type_node);
+ if (t == error_mark_node)
+ return error_mark_node;
}
- else
- 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:
if (sel == OMP_TRAIT_CONSTRUCT_SIMD)
@@ -26935,11 +27092,14 @@ c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
tree selectors = c_parser_omp_context_selector (parser, set, parms);
if (selectors == error_mark_node)
- ret = error_mark_node;
+ {
+ c_parser_skip_to_closing_brace (parser);
+ ret = error_mark_node;
+ }
else if (ret != error_mark_node)
ret = make_trait_set_selector (set, selectors, ret);
- braces.skip_until_found_close (parser);
+ braces.require_close (parser);
if (c_parser_next_token_is (parser, CPP_COMMA))
c_parser_consume_token (parser);
@@ -27844,6 +28004,151 @@ c_parser_omp_end (c_parser *parser)
}
}
+/* OpenMP 5.0
+ #pragma omp declare mapper ([mapper-identifier :] type var) \
+ [clause [ [,] clause ] ... ] new-line */
+
+static void
+c_parser_omp_declare_mapper (c_parser *parser, enum pragma_context context)
+{
+ tree type, mapper_name = NULL_TREE, var = NULL_TREE, stmt, stmtlist;
+ tree maplist = NULL_TREE, mapper_id, mapper_decl, t;
+ c_token *token;
+
+ if (context == pragma_struct || context == pragma_param)
+ {
+ error ("%<#pragma omp declare mapper%> not at file or block scope");
+ goto fail;
+ }
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ goto fail;
+
+ token = c_parser_peek_token (parser);
+
+ if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ {
+ switch (token->type)
+ {
+ case CPP_NAME:
+ mapper_name = token->value;
+ c_parser_consume_token (parser);
+ break;
+ case CPP_KEYWORD:
+ if (token->keyword == RID_DEFAULT)
+ {
+ mapper_name = NULL_TREE;
+ c_parser_consume_token (parser);
+ break;
+ }
+ /* Fallthrough. */
+ default:
+ error_at (token->location, "expected identifier or %<default%>");
+ c_parser_skip_to_pragma_eol (parser, false);
+ return;
+ }
+
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ goto fail;
+ }
+
+ mapper_id = c_omp_mapper_id (mapper_name);
+ mapper_decl = c_omp_mapper_decl (mapper_id);
+
+ {
+ location_t loc = c_parser_peek_token (parser)->location;
+ struct c_type_name *ctype = c_parser_type_name (parser);
+ type = groktypename (ctype, NULL, NULL);
+ if (type == error_mark_node)
+ goto fail;
+ if (!RECORD_OR_UNION_TYPE_P (type))
+ {
+ error_at (loc, "%qT is not a struct or union type in "
+ "%<#pragma omp declare mapper%>", type);
+ c_parser_skip_to_pragma_eol (parser, false);
+ return;
+ }
+ for (tree t = DECL_INITIAL (mapper_decl); t; t = TREE_CHAIN (t))
+ if (comptypes (TREE_PURPOSE (t), type))
+ {
+ error_at (loc, "redeclaration of %qs %<#pragma omp declare "
+ "mapper%> for type %qT", IDENTIFIER_POINTER (mapper_id)
+ + sizeof ("omp declare mapper ") - 1,
+ type);
+ tree prevmapper = TREE_VALUE (t);
+ /* Hmm, this location might not be very accurate. */
+ location_t ploc
+ = DECL_SOURCE_LOCATION (OMP_DECLARE_MAPPER_DECL (prevmapper));
+ inform (ploc, "%<#pragma omp declare mapper%> "
+ "previously declared here");
+ c_parser_skip_to_pragma_eol (parser, false);
+ return;
+ }
+ }
+
+ token = c_parser_peek_token (parser);
+ if (token->type == CPP_NAME)
+ {
+ var = build_decl (token->location, VAR_DECL, token->value, type);
+ c_parser_consume_token (parser);
+ DECL_ARTIFICIAL (var) = 1;
+ }
+ else
+ {
+ error_at (token->location, "expected identifier");
+ goto fail;
+ }
+
+ if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ goto fail;
+
+ push_scope ();
+ stmtlist = push_stmt_list ();
+ pushdecl (var);
+ DECL_CONTEXT (var) = current_function_decl;
+
+ while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+ {
+ location_t here;
+ pragma_omp_clause c_kind;
+ here = c_parser_peek_token (parser)->location;
+ c_kind = c_parser_omp_clause_name (parser);
+ if (c_kind != PRAGMA_OMP_CLAUSE_MAP)
+ {
+ error_at (here, "unexpected clause");
+ goto fail;
+ }
+ maplist = c_parser_omp_clause_map (parser, maplist, true);
+ }
+
+ if (maplist == NULL_TREE)
+ {
+ error_at (input_location, "missing %<map%> clause");
+ goto fail;
+ }
+
+ stmt = make_node (OMP_DECLARE_MAPPER);
+ TREE_TYPE (stmt) = type;
+ OMP_DECLARE_MAPPER_ID (stmt) = mapper_name;
+ OMP_DECLARE_MAPPER_DECL (stmt) = var;
+ OMP_DECLARE_MAPPER_CLAUSES (stmt) = maplist;
+
+ add_stmt (stmt);
+
+ pop_stmt_list (stmtlist);
+ pop_scope ();
+
+ c_parser_skip_to_pragma_eol (parser);
+
+ t = tree_cons (type, stmt, DECL_INITIAL (mapper_decl));
+ DECL_INITIAL (mapper_decl) = t;
+
+ return;
+
+ fail:
+ c_parser_skip_to_pragma_eol (parser);
+}
+
/* OpenMP 4.0
#pragma omp declare reduction (reduction-id : typename-list : expression) \
initializer-clause[opt] new-line
@@ -27970,8 +28275,8 @@ c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
location_t ploc
= DECL_SOURCE_LOCATION (TREE_VEC_ELT (TREE_VALUE (t),
0));
- error_at (ploc, "previous %<#pragma omp declare "
- "reduction%>");
+ inform (ploc, "%<#pragma omp declare reduction%> "
+ "previously declared here");
break;
}
if (t == NULL_TREE)
@@ -28235,6 +28540,12 @@ c_parser_omp_declare (c_parser *parser, enum pragma_context context)
c_parser_omp_declare_reduction (parser, context);
return false;
}
+ if (strcmp (p, "mapper") == 0)
+ {
+ c_parser_consume_token (parser);
+ c_parser_omp_declare_mapper (parser, context);
+ return false;
+ }
if (!flag_openmp) /* flag_openmp_simd */
{
c_parser_skip_to_pragma_eol (parser, false);
@@ -29144,7 +29455,6 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
{
error_at (match_loc, "too many %<otherwise%> or %<default%> "
"clauses in %<metadirective%>");
- c_parser_skip_to_end_of_block_or_statement (parser, true);
goto error;
}
default_seen = true;
@@ -29153,14 +29463,12 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
{
error_at (match_loc, "%<otherwise%> or %<default%> clause "
"must appear last in %<metadirective%>");
- c_parser_skip_to_end_of_block_or_statement (parser, true);
goto error;
}
if (!default_p && strcmp (p, "when") != 0)
{
error_at (match_loc, "%qs is not valid for %qs",
p, "metadirective");
- c_parser_skip_to_end_of_block_or_statement (parser, true);
goto error;
}
@@ -29228,7 +29536,6 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
if (i == 0)
{
error_at (loc, "expected directive name");
- c_parser_skip_to_end_of_block_or_statement (parser, true);
goto error;
}
@@ -29296,7 +29603,10 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
goto add;
case CPP_CLOSE_PAREN:
if (nesting_depth-- == 0)
- break;
+ {
+ c_parser_consume_token (parser);
+ break;
+ }
goto add;
default:
add:
@@ -29308,8 +29618,6 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
break;
}
- c_parser_consume_token (parser);
-
if (!skip)
{
c_token eol_token;
@@ -29436,9 +29744,9 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p)
return;
error:
+ /* Skip the metadirective pragma. Do not skip the metadirective body. */
if (parser->in_pragma)
- c_parser_skip_to_pragma_eol (parser);
- c_parser_skip_to_end_of_block_or_statement (parser, true);
+ c_parser_skip_to_pragma_eol (parser, false);
}
/* Main entry point to parsing most OpenMP pragmas. */
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 723a28b..364f51d 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -888,6 +888,10 @@ extern tree c_finish_omp_task (location_t, tree, tree);
extern void c_finish_omp_cancel (location_t, tree);
extern void c_finish_omp_cancellation_point (location_t, tree);
extern tree c_finish_omp_clauses (tree, enum c_omp_region_type);
+extern tree c_omp_finish_mapper_clauses (tree);
+extern tree c_omp_mapper_lookup (tree, tree);
+extern tree c_omp_extract_mapper_directive (tree);
+extern tree c_omp_map_array_section (location_t, tree);
extern tree c_build_va_arg (location_t, tree, location_t, tree);
extern tree c_finish_transaction (location_t, tree, int);
extern bool c_tree_equal (tree, tree);
@@ -946,6 +950,10 @@ extern tree c_omp_reduction_id (enum tree_code, tree);
extern tree c_omp_reduction_decl (tree);
extern tree c_omp_reduction_lookup (tree, tree);
extern tree c_check_omp_declare_reduction_r (tree *, int *, void *);
+extern tree c_omp_mapper_id (tree);
+extern tree c_omp_mapper_decl (tree);
+extern void c_omp_scan_mapper_bindings (location_t, tree *, tree);
+extern tree c_omp_instantiate_mappers (tree);
extern bool c_check_in_current_scope (tree);
extern void c_pushtag (location_t, tree, tree);
extern void c_bind (location_t, tree, bool);
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 360216b..2f243ca 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -776,7 +776,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
construction, return it. */
for (struct composite_cache *c = cache; c != NULL; c = c->next)
- if (c->t1 == t1 && c->t2 == t2)
+ if ((c->t1 == t1 && c->t2 == t2) || (c->t1 == t2 && c->t2 == t1))
return c->composite;
/* Otherwise, create a new type node and link it into the cache. */
@@ -16947,6 +16947,12 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case OMP_CLAUSE_MAP:
if (OMP_CLAUSE_MAP_IMPLICIT (c) && !implicit_moved)
goto move_implicit;
+ if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POP_MAPPER_NAME)
+ {
+ remove = true;
+ break;
+ }
/* FALLTHRU */
case OMP_CLAUSE_TO:
case OMP_CLAUSE_FROM:
@@ -17887,6 +17893,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
return clauses;
}
+/* Do processing necessary to make CLAUSES well-formed, where CLAUSES result
+ from implicit instantiation of user-defined mappers (in gimplify.cc). */
+
+tree
+c_omp_finish_mapper_clauses (tree clauses)
+{
+ return c_finish_omp_clauses (clauses, C_ORT_OMP);
+}
+
/* Return code to initialize DST with a copy constructor from SRC.
C doesn't have copy constructors nor assignment operators, only for
_Atomic vars we need to perform __atomic_load from src into a temporary
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/aarch64/gcc-auto-profile b/gcc/config/aarch64/gcc-auto-profile
index 4d5c2e3..4d5c2e3 100644..100755
--- a/gcc/config/aarch64/gcc-auto-profile
+++ b/gcc/config/aarch64/gcc-auto-profile
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 7fd03c8..181e64a 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -18724,6 +18724,33 @@ emit_reduc_half (rtx dest, rtx src, int i)
case E_V8HFmode:
case E_V4SImode:
case E_V2DImode:
+ if (TARGET_SSE_REDUCTION_PREFER_PSHUF)
+ {
+ if (i == 128)
+ {
+ d = gen_reg_rtx (V4SImode);
+ tem = gen_sse2_pshufd_1 (
+ d, force_reg (V4SImode, gen_lowpart (V4SImode, src)),
+ GEN_INT (2), GEN_INT (3), GEN_INT (2), GEN_INT (3));
+ break;
+ }
+ else if (i == 64)
+ {
+ d = gen_reg_rtx (V4SImode);
+ tem = gen_sse2_pshufd_1 (
+ d, force_reg (V4SImode, gen_lowpart (V4SImode, src)),
+ GEN_INT (1), GEN_INT (1), GEN_INT (1), GEN_INT (1));
+ break;
+ }
+ else if (i == 32)
+ {
+ d = gen_reg_rtx (V8HImode);
+ tem = gen_sse2_pshuflw_1 (
+ d, force_reg (V8HImode, gen_lowpart (V8HImode, src)),
+ GEN_INT (1), GEN_INT (1), GEN_INT (1), GEN_INT (1));
+ break;
+ }
+ }
d = gen_reg_rtx (V1TImode);
tem = gen_sse2_lshrv1ti3 (d, gen_lowpart (V1TImode, src),
GEN_INT (i / 2));
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index ccc62fc..d32d9ad 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -490,7 +490,9 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST];
#define TARGET_SSE_MOVCC_USE_BLENDV \
ix86_tune_features[X86_TUNE_SSE_MOVCC_USE_BLENDV]
#define TARGET_ALIGN_TIGHT_LOOPS \
- ix86_tune_features[X86_TUNE_ALIGN_TIGHT_LOOPS]
+ ix86_tune_features[X86_TUNE_ALIGN_TIGHT_LOOPS]
+#define TARGET_SSE_REDUCTION_PREFER_PSHUF \
+ ix86_tune_features[X86_TUNE_SSE_REDUCTION_PREFER_PSHUF]
/* Feature tests against the various architecture variations. */
diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def
index e6044c6..91cdca7 100644
--- a/gcc/config/i386/x86-tune.def
+++ b/gcc/config/i386/x86-tune.def
@@ -572,6 +572,11 @@ DEF_TUNE (X86_TUNE_V2DF_REDUCTION_PREFER_HADDPD,
DEF_TUNE (X86_TUNE_SSE_MOVCC_USE_BLENDV,
"sse_movcc_use_blendv", ~m_CORE_ATOM)
+/* X86_TUNE_V4SI_REDUCTION_PREFER_SHUFD: Prefer pshuf to reduce V16QI,
+ V8HI, V8HI, V4SI, V4FI, V2DI modes when lshr are costlier. */
+DEF_TUNE (X86_TUNE_SSE_REDUCTION_PREFER_PSHUF,
+ "sse_reduction_prefer_pshuf", m_ZNVER4 | m_ZNVER5)
+
/*****************************************************************************/
/* AVX instruction selection tuning (some of SSE flags affects AVX, too) */
/*****************************************************************************/
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.md b/gcc/config/riscv/autovec.md
index a54f552..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;
}
)
@@ -2510,25 +2511,13 @@
(match_operand:<V_DOUBLE_TRUNC> 2 "register_operand")))
(const_int 1)))))]
"TARGET_VECTOR"
-{
- /* First emit a widening addition. */
- rtx tmp1 = gen_reg_rtx (<MODE>mode);
- rtx ops1[] = {tmp1, operands[1], operands[2]};
- insn_code icode = code_for_pred_dual_widen (PLUS, SIGN_EXTEND, <MODE>mode);
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops1);
-
- /* Then add 1. */
- rtx tmp2 = gen_reg_rtx (<MODE>mode);
- rtx ops2[] = {tmp2, tmp1, const1_rtx};
- icode = code_for_pred_scalar (PLUS, <MODE>mode);
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops2);
-
- /* Finally, a narrowing shift. */
- rtx ops3[] = {operands[0], tmp2, const1_rtx};
- icode = code_for_pred_narrow_scalar (ASHIFTRT, <MODE>mode);
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops3);
- DONE;
-})
+ {
+ insn_code icode = code_for_pred (UNSPEC_VAADD, <V_DOUBLE_TRUNC>mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RNU,
+ operands);
+ DONE;
+ }
+)
;; csrwi vxrm, 2
;; vaaddu.vv vd, vs2, vs1
@@ -2539,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;
})
@@ -2552,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;
})
@@ -2577,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;
}
)
@@ -2587,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;
}
)
@@ -2597,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;
}
)
@@ -2607,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;
}
)
@@ -2617,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;
}
)
@@ -2627,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;
}
)
@@ -2637,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;
}
)
@@ -2694,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;
}
)
@@ -2704,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;
}
)
@@ -2714,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;
}
)
@@ -2724,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;
}
)
@@ -2756,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;
}
)
@@ -2767,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;
}
)
@@ -2778,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;
}
)
@@ -2789,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 97b5766..d0adc2b 100644
--- a/gcc/config/riscv/riscv-ext.def
+++ b/gcc/config/riscv/riscv-ext.def
@@ -1676,6 +1676,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",
@@ -1728,6 +1741,19 @@ DEFINE_RISCV_EXT(
/* EXTRA_EXTENSION_FLAGS */ 0)
DEFINE_RISCV_EXT(
+ /* NAME */ smdbltrp,
+ /* UPPERCAE_NAME */ SMDBLTRP,
+ /* FULL_NAME */ "Double Trap Extensions",
+ /* 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 */ ssaia,
/* UPPERCAE_NAME */ SSAIA,
/* FULL_NAME */ "Advanced interrupt architecture extension for supervisor-mode",
@@ -1819,6 +1845,19 @@ DEFINE_RISCV_EXT(
/* EXTRA_EXTENSION_FLAGS */ 0)
DEFINE_RISCV_EXT(
+ /* NAME */ ssdbltrp,
+ /* UPPERCAE_NAME */ SSDBLTRP,
+ /* FULL_NAME */ "Double Trap Extensions",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
/* NAME */ supm,
/* UPPERCAE_NAME */ SUPM,
/* FULL_NAME */ "supm extension",
diff --git a/gcc/config/riscv/riscv-ext.opt b/gcc/config/riscv/riscv-ext.opt
index 9199aa3..c0dcde6 100644
--- a/gcc/config/riscv/riscv-ext.opt
+++ b/gcc/config/riscv/riscv-ext.opt
@@ -335,6 +335,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)
@@ -343,6 +345,8 @@ Mask(SMNPM) Var(riscv_sm_subext)
Mask(SMSTATEEN) Var(riscv_sm_subext)
+Mask(SMDBLTRP) Var(riscv_sm_subext)
+
Mask(SSAIA) Var(riscv_ss_subext)
Mask(SSCOFPMF) Var(riscv_ss_subext)
@@ -357,6 +361,8 @@ Mask(SSTC) Var(riscv_ss_subext)
Mask(SSSTRICT) Var(riscv_ss_subext)
+Mask(SSDBLTRP) Var(riscv_ss_subext)
+
Mask(SUPM) Var(riscv_su_subext)
Mask(SVINVAL) Var(riscv_sv_subext)
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/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/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 db79783..a8f2b4e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,187 @@
+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
+ unique_ptr.
+ (cxx_dump_pretty_printer::cxx_dump_pretty_printer): Likewise.
+ (cxx_initialize_diagnostics): Likewise.
+
+2025-05-29 Jason Merrill <jason@redhat.com>
+
+ PR c++/113563
+ * lambda.cc (build_capture_proxy): Check pointerness of the
+ member, not the proxy type.
+ (lambda_expr_this_capture): Don't assume current_class_ref.
+ (nonlambda_method_basetype): Likewise.
+ * semantics.cc (finish_non_static_data_member): Don't assume
+ TREE_TYPE (object) is set.
+ (finish_this_expr): Check current_class_type for lambda,
+ not current_class_ref.
+
+2025-05-29 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/109283
+ * coroutines.cc (find_any_await): Only save the statement
+ pointer if the caller passes a place for it.
+ (flatten_await_stmt): When checking that ternary expressions
+ have been handled, also check that they contain a co_await.
+
+2025-05-29 Jason Merrill <jason@redhat.com>
+
+ * decl.cc (start_decl): Also set invalid_constexpr
+ for maybe_constexpr_fn.
+ * parser.cc (cp_parser_jump_statement): Likewise.
+ * constexpr.cc (potential_constant_expression_1): Ignore
+ goto to an artificial label.
+
+2025-05-29 Sandra Loosemore <sloosemore@baylibre.com>
+
+ * parser.cc (cp_parser_omp_metadirective): Do not call
+ cp_parser_skip_to_end_of_block_or_statement after an error.
+
+2025-05-29 Sandra Loosemore <sloosemore@baylibre.com>
+
+ PR c/120180
+ * parser.cc (cp_parser_omp_metadirective): Only consume the
+ token if it is the expected close paren.
+
+2025-05-29 Iain Sandoe <iain@sandoe.co.uk>
+
+ * coroutines.cc (analyze_fn_parms): No longer
+ create a parameter copy guard var.
+ * coroutines.h (struct param_info): Remove the
+ entry for the parameter copy destructor guard.
+
+2025-05-29 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/120453
+ * cp-tree.h (DECL_RAMP_P): New.
+ * typeck.cc (check_return_expr): Use DECL_RAMP_P instead
+ of DECL_RAMP_FN.
+
+2025-05-29 Jason Merrill <jason@redhat.com>
+
+ PR c++/107600
+ * cp-trait.def (IS_DESTRUCTIBLE, IS_NOTHROW_DESTRUCTIBLE)
+ (IS_TRIVIALLY_DESTRUCTIBLE): New.
+ * constraint.cc (diagnose_trait_expr): Explain them.
+ * method.cc (destructible_expr): New.
+ (is_xible_helper): Use it.
+ * semantics.cc (finish_trait_expr): Handle new traits.
+ (trait_expr_value): Likewise. Complain about asking
+ whether a deleted dtor is trivial.
+
2025-05-28 Jason Merrill <jason@redhat.com>
* module.cc (module_state::write_namespaces): Write
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index fa754b9..b9fdc94 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -3529,6 +3529,9 @@ reduced_constant_expression_p (tree t)
/* Even if we can't lower this yet, it's constant. */
return true;
+ case OMP_DECLARE_MAPPER:
+ return true;
+
case CONSTRUCTOR:
/* And we need to handle PTRMEM_CST wrapped in a CONSTRUCTOR. */
tree field;
@@ -7838,6 +7841,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
case LABEL_EXPR:
case CASE_LABEL_EXPR:
case PREDICT_EXPR:
+ case OMP_DECLARE_MAPPER:
return t;
case PARM_DECL:
@@ -9274,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 "
@@ -10532,6 +10535,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
"expression", t);
return false;
+ case OMP_DECLARE_MAPPER:
+ /* This can be used to initialize VAR_DECLs: it's treated as a magic
+ constant. */
+ return true;
+
case ASM_EXPR:
if (flags & tf_error)
inline_asm_in_constexpr_error (loc, fundef_p);
@@ -10979,6 +10987,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
*jump_target = *target;
return true;
}
+ if (DECL_ARTIFICIAL (*target))
+ /* The user didn't write this goto, this isn't the problem. */
+ return true;
if (flags & tf_error)
constexpr_error (loc, fundef_p, "%<goto%> is not a constant "
"expression");
@@ -11012,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 b1e555c..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);
@@ -2865,8 +2849,8 @@ find_any_await (tree *stmt, int *dosub, void *d)
if (TREE_CODE (*stmt) == CO_AWAIT_EXPR)
{
*dosub = 0; /* We don't need to consider this any further. */
- tree **p = (tree **) d;
- *p = stmt;
+ if (d)
+ *(tree **)d = stmt;
return *stmt;
}
return NULL_TREE;
@@ -3116,7 +3100,9 @@ flatten_await_stmt (var_nest_node *n, hash_set<tree> *promoted,
bool already_present = promoted->add (var);
gcc_checking_assert (!already_present);
tree inner = TARGET_EXPR_INITIAL (init);
- gcc_checking_assert (TREE_CODE (inner) != COND_EXPR);
+ gcc_checking_assert
+ (TREE_CODE (inner) != COND_EXPR
+ || !cp_walk_tree (&inner, find_any_await, nullptr, nullptr));
init = cp_build_modify_expr (input_location, var, INIT_EXPR, init,
tf_warning_or_error);
/* Simplify for the case that we have an init containing the temp
@@ -4089,17 +4075,7 @@ analyze_fn_parms (tree orig, hash_map<tree, param_info> *param_uses)
}
parm.field_id = name;
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (parm.frame_type))
- {
- char *buf = xasprintf ("_Coro_q%u_%s_live", parm_num,
- DECL_NAME (arg) ? IDENTIFIER_POINTER (name)
- : "__unnamed");
- parm.guard_var
- = coro_build_artificial_var (UNKNOWN_LOCATION, get_identifier (buf),
- boolean_type_node, orig,
- boolean_false_node);
- free (buf);
- parm.trivial_dtor = false;
- }
+ parm.trivial_dtor = false;
else
parm.trivial_dtor = true;
}
diff --git a/gcc/cp/coroutines.h b/gcc/cp/coroutines.h
index d13bea0..10698cf 100644
--- a/gcc/cp/coroutines.h
+++ b/gcc/cp/coroutines.h
@@ -9,7 +9,6 @@ struct param_info
vec<tree *> *body_uses; /* Worklist of uses, void if there are none. */
tree frame_type; /* The type used to represent this parm in the frame. */
tree orig_type; /* The original type of the parm (not as passed). */
- tree guard_var; /* If we need a DTOR on exception, this bool guards it. */
tree fr_copy_dtor; /* If we need a DTOR on exception, this is it. */
bool by_ref; /* Was passed by reference. */
bool pt_ref; /* Was a pointer to object. */
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 03d5352..16def88 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -2809,6 +2809,12 @@ cxx_omp_finish_clause (tree c, gimple_seq *, bool /* openacc */)
}
}
+tree
+cxx_omp_finish_mapper_clauses (tree clauses)
+{
+ return finish_omp_clauses (clauses, C_ORT_OMP);
+}
+
/* Return true if DECL's DECL_VALUE_EXPR (if any) should be
disregarded in OpenMP construct, because it is going to be
remapped during OpenMP lowering. SHARED is true if DECL
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 13fb80c..ff35428 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -190,6 +190,15 @@ static const scoped_attribute_specs *const cp_objcp_attribute_table[] =
#define LANG_HOOKS_OMP_CLAUSE_DTOR cxx_omp_clause_dtor
#undef LANG_HOOKS_OMP_FINISH_CLAUSE
#define LANG_HOOKS_OMP_FINISH_CLAUSE cxx_omp_finish_clause
+#undef LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES
+#define LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES cxx_omp_finish_mapper_clauses
+#undef LANG_HOOKS_OMP_MAPPER_LOOKUP
+#define LANG_HOOKS_OMP_MAPPER_LOOKUP cxx_omp_mapper_lookup
+#undef LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE
+#define LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE \
+ cxx_omp_extract_mapper_directive
+#undef LANG_HOOKS_OMP_MAP_ARRAY_SECTION
+#define LANG_HOOKS_OMP_MAP_ARRAY_SECTION cxx_omp_map_array_section
#undef LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE
#define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE cxx_omp_privatize_by_reference
#undef LANG_HOOKS_OMP_DISREGARD_VALUE_EXPR
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 19c0b45..3cf4a76 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2975,7 +2975,10 @@ struct GTY(()) lang_decl_base {
unsigned module_keyed_decls_p : 1; /* has keys, applies to all decls */
- /* 11 spare bits. */
+ /* VAR_DECL being used to represent an OpenMP declared mapper. */
+ unsigned omp_declare_mapper_p : 1;
+
+ /* 10 spare bits. */
};
/* True for DECL codes which have template info and access. */
@@ -4530,6 +4533,11 @@ get_vec_init_expr (tree t)
#define DECL_OMP_DECLARE_REDUCTION_P(NODE) \
(LANG_DECL_FN_CHECK (DECL_COMMON_CHECK (NODE))->omp_declare_reduction_p)
+/* Nonzero if NODE is an artificial FUNCTION_DECL for
+ #pragma omp declare mapper. */
+#define DECL_OMP_DECLARE_MAPPER_P(NODE) \
+ (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.omp_declare_mapper_p)
+
/* Nonzero if DECL has been declared threadprivate by
#pragma omp threadprivate. */
#define CP_DECL_THREADPRIVATE_P(DECL) \
@@ -5522,6 +5530,10 @@ decl_template_parm_check (const_tree t, const char *f, int l, const char *fn)
#define DECL_RAMP_FN(NODE) \
(coro_get_ramp_function (NODE))
+/* For a FUNCTION_DECL this is true if it is a coroutine ramp. */
+#define DECL_RAMP_P(NODE) \
+ DECL_COROUTINE_P (NODE) && !DECL_RAMP_FN (NODE)
+
/* True for an OMP_ATOMIC that has dependent parameters. These are stored
as an expr in operand 1, and integer_zero_node or clauses in operand 0. */
#define OMP_ATOMIC_DEPENDENT_P(NODE) \
@@ -7944,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. */
@@ -8092,11 +8105,14 @@ extern tree finish_qualified_id_expr (tree, tree, bool, bool,
extern void simplify_aggr_init_expr (tree *);
extern void finalize_nrv (tree, tree);
extern tree omp_reduction_id (enum tree_code, tree, tree);
+extern tree omp_mapper_id (tree, tree);
extern tree cp_remove_omp_priv_cleanup_stmt (tree *, int *, void *);
extern bool cp_check_omp_declare_reduction (tree);
+extern bool cp_check_omp_declare_mapper (tree);
extern void finish_omp_declare_simd_methods (tree);
extern tree cp_finish_omp_init_prefer_type (tree);
extern tree finish_omp_clauses (tree, enum c_omp_region_type);
+extern tree omp_instantiate_mappers (tree);
extern tree push_omp_privatization_clauses (bool);
extern void pop_omp_privatization_clauses (tree);
extern void save_omp_privatization_clauses (vec<tree> &);
@@ -8692,6 +8708,10 @@ extern tree cxx_omp_clause_copy_ctor (tree, tree, tree);
extern tree cxx_omp_clause_assign_op (tree, tree, tree);
extern tree cxx_omp_clause_dtor (tree, tree);
extern void cxx_omp_finish_clause (tree, gimple_seq *, bool);
+extern tree cxx_omp_finish_mapper_clauses (tree);
+extern tree cxx_omp_mapper_lookup (tree, tree);
+extern tree cxx_omp_extract_mapper_directive (tree);
+extern tree cxx_omp_map_array_section (location_t, tree);
extern bool cxx_omp_privatize_by_reference (const_tree);
extern bool cxx_omp_disregard_value_expr (tree, bool);
extern void cp_fold_function (tree);
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index a9ef28b..9a20ed6 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -6198,22 +6198,28 @@ start_decl (const cp_declarator *declarator,
}
if (current_function_decl && VAR_P (decl)
- && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+ && maybe_constexpr_fn (current_function_decl)
&& cxx_dialect < cxx23)
{
bool ok = false;
if (CP_DECL_THREAD_LOCAL_P (decl) && !DECL_REALLY_EXTERN (decl))
- error_at (DECL_SOURCE_LOCATION (decl),
- "%qD defined %<thread_local%> in %qs function only "
- "available with %<-std=c++23%> or %<-std=gnu++23%>", decl,
- DECL_IMMEDIATE_FUNCTION_P (current_function_decl)
- ? "consteval" : "constexpr");
+ {
+ if (DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qD defined %<thread_local%> in %qs function only "
+ "available with %<-std=c++23%> or %<-std=gnu++23%>", decl,
+ DECL_IMMEDIATE_FUNCTION_P (current_function_decl)
+ ? "consteval" : "constexpr");
+ }
else if (TREE_STATIC (decl))
- error_at (DECL_SOURCE_LOCATION (decl),
- "%qD defined %<static%> in %qs function only available "
- "with %<-std=c++23%> or %<-std=gnu++23%>", decl,
- DECL_IMMEDIATE_FUNCTION_P (current_function_decl)
- ? "consteval" : "constexpr");
+ {
+ if (DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qD defined %<static%> in %qs function only available "
+ "with %<-std=c++23%> or %<-std=gnu++23%>", decl,
+ DECL_IMMEDIATE_FUNCTION_P (current_function_decl)
+ ? "consteval" : "constexpr");
+ }
else
ok = true;
if (!ok)
@@ -7871,6 +7877,12 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
}
else if (!init && DECL_REALLY_EXTERN (decl))
;
+ else if (flag_openmp
+ && VAR_P (decl)
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_OMP_DECLARE_MAPPER_P (decl)
+ && TREE_CODE (init) == OMP_DECLARE_MAPPER)
+ return NULL_TREE;
else if (init || type_build_ctor_call (type)
|| TYPE_REF_P (type))
{
@@ -9191,14 +9203,23 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
varpool_node::get_create (decl);
}
+ if (flag_openmp
+ && VAR_P (decl)
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_OMP_DECLARE_MAPPER_P (decl)
+ && init)
+ {
+ gcc_assert (TREE_CODE (init) == OMP_DECLARE_MAPPER);
+ DECL_INITIAL (decl) = init;
+ }
/* Convert the initializer to the type of DECL, if we have not
already initialized DECL. */
- if (!DECL_INITIALIZED_P (decl)
- /* If !DECL_EXTERNAL then DECL is being defined. In the
- case of a static data member initialized inside the
- class-specifier, there can be an initializer even if DECL
- is *not* defined. */
- && (!DECL_EXTERNAL (decl) || init))
+ else if (!DECL_INITIALIZED_P (decl)
+ /* If !DECL_EXTERNAL then DECL is being defined. In the
+ case of a static data member initialized inside the
+ class-specifier, there can be an initializer even if DECL
+ is *not* defined. */
+ && (!DECL_EXTERNAL (decl) || init))
{
cleanups = make_tree_vector ();
init = check_initializer (decl, init, flags, &cleanups);
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 666ab78..e3fbc40 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -6408,12 +6408,17 @@ mark_used (tree decl, tsubst_flags_t complain /* = tf_warning_or_error */)
/* If DECL has a deduced return type, we need to instantiate it now to
find out its type. For OpenMP user defined reductions, we need them
- instantiated for reduction clauses which inline them by hand directly. */
+ instantiated for reduction clauses which inline them by hand directly.
+ OpenMP declared mappers are used implicitly so must be instantiated
+ before they can be detected. */
if (undeduced_auto_decl (decl)
|| (VAR_P (decl)
&& VAR_HAD_UNKNOWN_BOUND (decl))
|| (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_OMP_DECLARE_REDUCTION_P (decl)))
+ && DECL_OMP_DECLARE_REDUCTION_P (decl))
+ || (TREE_CODE (decl) == VAR_DECL
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_OMP_DECLARE_MAPPER_P (decl)))
maybe_instantiate_decl (decl);
if (!decl_dependent_p (decl)
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index d52dad3..69da381 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -182,9 +182,10 @@ class cxx_format_postprocessor : public format_postprocessor
: m_type_a (), m_type_b ()
{}
- format_postprocessor *clone() const final override
+ std::unique_ptr<format_postprocessor>
+ clone() const final override
{
- return new cxx_format_postprocessor ();
+ return std::make_unique<cxx_format_postprocessor> ();
}
void handle (pretty_printer *pp) final override;
@@ -204,8 +205,7 @@ cxx_dump_pretty_printer (int phase)
if (outf)
{
pp_format_decoder (this) = cp_printer;
- /* This gets deleted in ~pretty_printer. */
- pp_format_postprocessor (this) = new cxx_format_postprocessor ();
+ set_format_postprocessor (std::make_unique<cxx_format_postprocessor> ());
set_output_stream (outf);
}
}
@@ -301,7 +301,7 @@ void
cxx_initialize_diagnostics (diagnostic_context *context)
{
cxx_pretty_printer *pp = new cxx_pretty_printer ();
- pp_format_postprocessor (pp) = new cxx_format_postprocessor ();
+ pp->set_format_postprocessor (std::make_unique<cxx_format_postprocessor> ());
context->set_pretty_printer (std::unique_ptr<pretty_printer> (pp));
c_common_diagnostics_set_defaults (context);
@@ -1282,12 +1282,37 @@ dump_global_iord (cxx_pretty_printer *pp, tree t)
pp_printf (pp, p, DECL_SOURCE_FILE (t));
}
+/* Write a representation of OpenMP "declare mapper" T to PP in a manner
+ suitable for error messages. */
+
+static void
+dump_omp_declare_mapper (cxx_pretty_printer *pp, tree t, int flags)
+{
+ pp_string (pp, "#pragma omp declare mapper");
+ if (t == NULL_TREE || t == error_mark_node)
+ return;
+ pp_space (pp);
+ pp_cxx_left_paren (pp);
+ if (OMP_DECLARE_MAPPER_ID (t))
+ {
+ pp_cxx_tree_identifier (pp, OMP_DECLARE_MAPPER_ID (t));
+ pp_colon (pp);
+ }
+ dump_type (pp, TREE_TYPE (t), flags);
+ pp_cxx_right_paren (pp);
+}
+
static void
dump_simple_decl (cxx_pretty_printer *pp, tree t, tree type, int flags)
{
if (VAR_P (t) && DECL_NTTP_OBJECT_P (t))
return dump_expr (pp, DECL_INITIAL (t), flags);
+ if (TREE_CODE (t) == VAR_DECL
+ && DECL_LANG_SPECIFIC (t)
+ && DECL_OMP_DECLARE_MAPPER_P (t))
+ return dump_omp_declare_mapper (pp, DECL_INITIAL (t), flags);
+
if (flags & TFF_DECL_SPECIFIERS)
{
if (concept_definition_p (t))
@@ -3244,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/lambda.cc b/gcc/cp/lambda.cc
index a2bed9f..2a9061a 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -218,9 +218,7 @@ lambda_capture_field_type (tree expr, bool explicit_init_p,
tree type;
bool is_this = is_this_parameter (tree_strip_nop_conversions (expr));
- if (is_this)
- type = TREE_TYPE (expr);
- else if (explicit_init_p)
+ if (explicit_init_p)
{
tree auto_node = make_auto ();
@@ -259,7 +257,7 @@ lambda_capture_field_type (tree expr, bool explicit_init_p,
type = non_reference (unlowered_expr_type (expr));
- if (by_reference_p || TREE_CODE (type) == FUNCTION_TYPE)
+ if ((by_reference_p && !is_this) || TREE_CODE (type) == FUNCTION_TYPE)
type = build_reference_type (type);
}
@@ -440,13 +438,21 @@ build_capture_proxy (tree member, tree init)
else
name = get_identifier (IDENTIFIER_POINTER (DECL_NAME (member)) + 2);
- type = lambda_proxy_type (object);
-
- if (name == this_identifier && !INDIRECT_TYPE_P (type))
+ if (name == this_identifier && TYPE_PTR_P (TREE_TYPE (member)))
+ /* Avoid DECLTYPE_TYPE for by-ref 'this' capture in an xobj lambda; the
+ constness of the closure doesn't matter just like it doesn't matter to
+ other by-ref capture. It's simpler to handle this special case here
+ than in lambda_proxy_type. */
+ type = TREE_TYPE (member);
+ else
{
- type = build_pointer_type (type);
- type = cp_build_qualified_type (type, TYPE_QUAL_CONST);
- object = build_fold_addr_expr_with_type (object, type);
+ type = lambda_proxy_type (object);
+ if (name == this_identifier)
+ {
+ type = build_pointer_type (type);
+ type = cp_build_qualified_type (type, TYPE_QUAL_CONST);
+ object = build_fold_addr_expr_with_type (object, type);
+ }
}
if (DECL_VLA_CAPTURE_P (member))
@@ -921,8 +927,9 @@ lambda_expr_this_capture (tree lambda, int add_capture_p)
else
{
/* To make sure that current_class_ref is for the lambda. */
- gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref))
- == LAMBDA_EXPR_CLOSURE (lambda));
+ gcc_assert (!current_class_ref
+ || (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref))
+ == LAMBDA_EXPR_CLOSURE (lambda)));
result = this_capture;
@@ -1037,12 +1044,9 @@ current_nonlambda_function (void)
tree
nonlambda_method_basetype (void)
{
- if (!current_class_ref)
- return NULL_TREE;
-
tree type = current_class_type;
if (!type || !LAMBDA_TYPE_P (type))
- return type;
+ return current_class_ref ? type : NULL_TREE;
while (true)
{
@@ -1054,7 +1058,7 @@ nonlambda_method_basetype (void)
tree fn = TYPE_CONTEXT (type);
if (!fn || TREE_CODE (fn) != FUNCTION_DECL
- || !DECL_IOBJ_MEMBER_FUNCTION_P (fn))
+ || !DECL_OBJECT_MEMBER_FUNCTION_P (fn))
/* No enclosing non-lambda method. */
return NULL_TREE;
if (!LAMBDA_FUNCTION_P (fn))
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/parser.cc b/gcc/cp/parser.cc
index d9fc5f7..8633763 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -15431,11 +15431,12 @@ cp_parser_jump_statement (cp_parser* parser, tree &std_attrs)
case RID_GOTO:
if (parser->in_function_body
- && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+ && maybe_constexpr_fn (current_function_decl)
&& cxx_dialect < cxx23)
{
- error ("%<goto%> in %<constexpr%> function only available with "
- "%<-std=c++23%> or %<-std=gnu++23%>");
+ if (DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+ error ("%<goto%> in %<constexpr%> function only available with "
+ "%<-std=c++23%> or %<-std=gnu++23%>");
cp_function_chain->invalid_constexpr = true;
}
@@ -42423,13 +42424,13 @@ cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind,
map ( [map-type-modifier[,] ...] map-kind: variable-list )
map-type-modifier:
- always | close */
+ always | close | mapper ( mapper-name ) */
static tree
-cp_parser_omp_clause_map (cp_parser *parser, tree list)
+cp_parser_omp_clause_map (cp_parser *parser, tree list, bool declare_mapper_p)
{
tree nlist, c;
- enum gomp_map_kind kind = GOMP_MAP_TOFROM;
+ enum gomp_map_kind kind = declare_mapper_p ? GOMP_MAP_UNSET : GOMP_MAP_TOFROM;
if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
return list;
@@ -42447,12 +42448,17 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list)
if (cp_lexer_peek_nth_token (parser->lexer, pos + 1)->type == CPP_COMMA)
pos++;
+ else if (cp_lexer_peek_nth_token (parser->lexer, pos + 1)->type
+ == CPP_OPEN_PAREN)
+ pos = cp_parser_skip_balanced_tokens (parser, pos + 1);
pos++;
}
bool always_modifier = false;
bool close_modifier = false;
bool present_modifier = false;
+ bool mapper_modifier = false;
+ tree mapper_name = NULL_TREE;
for (int pos = 1; pos < map_kind_pos; ++pos)
{
cp_token *tok = cp_lexer_peek_token (parser->lexer);
@@ -42475,6 +42481,7 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list)
return list;
}
always_modifier = true;
+ cp_lexer_consume_token (parser->lexer);
}
else if (strcmp ("close", p) == 0)
{
@@ -42488,6 +42495,77 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list)
return list;
}
close_modifier = true;
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else if (strcmp ("mapper", p) == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+
+ matching_parens parens;
+ if (parens.require_open (parser))
+ {
+ if (mapper_modifier)
+ {
+ cp_parser_error (parser, "too many %<mapper%> modifiers");
+ /* Assume it's a well-formed mapper modifier, even if it
+ seems to be in the wrong place. */
+ cp_lexer_consume_token (parser->lexer);
+ parens.require_close (parser);
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/
+ true);
+ return list;
+ }
+
+ tok = cp_lexer_peek_token (parser->lexer);
+ switch (tok->type)
+ {
+ case CPP_NAME:
+ {
+ cp_expr e = cp_parser_identifier (parser);
+ if (e != error_mark_node)
+ mapper_name = e;
+ else
+ goto err;
+ if (declare_mapper_p)
+ {
+ error_at (e.get_location (),
+ "in %<declare mapper%> directives, parameter "
+ "to %<mapper%> modifier must be %<default%>");
+ }
+ }
+ break;
+
+ case CPP_KEYWORD:
+ if (tok->keyword == RID_DEFAULT)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ break;
+ }
+ /* Fallthrough. */
+
+ default:
+ err:
+ cp_parser_error (parser,
+ "expected identifier or %<default%>");
+ return list;
+ }
+
+ if (!parens.require_close (parser))
+ {
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/
+ true);
+ return list;
+ }
+
+ mapper_modifier = true;
+ pos += 3;
+ }
}
else if (strcmp ("present", p) == 0)
{
@@ -42501,19 +42579,19 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list)
return list;
}
present_modifier = true;
- }
+ cp_lexer_consume_token (parser->lexer);
+ }
else
{
- cp_parser_error (parser, "%<map%> clause with map-type modifier other"
- " than %<always%>, %<close%> or %<present%>");
+ cp_parser_error (parser, "%<map%> clause with map-type modifier "
+ "other than %<always%>, %<close%>, "
+ "%<mapper%> or %<present%>");
cp_parser_skip_to_closing_parenthesis (parser,
/*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
return list;
}
-
- cp_lexer_consume_token (parser->lexer);
}
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
@@ -42569,8 +42647,30 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list)
NULL, true);
finish_scope ();
+ tree last_new = NULL_TREE;
+
for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_SET_MAP_KIND (c, kind);
+ {
+ OMP_CLAUSE_SET_MAP_KIND (c, kind);
+ last_new = c;
+ }
+
+ if (mapper_name)
+ {
+ tree name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_PUSH_MAPPER_NAME);
+ OMP_CLAUSE_DECL (name) = mapper_name;
+ OMP_CLAUSE_CHAIN (name) = nlist;
+ nlist = name;
+
+ gcc_assert (last_new);
+
+ name = build_omp_clause (input_location, OMP_CLAUSE_MAP);
+ OMP_CLAUSE_SET_MAP_KIND (name, GOMP_MAP_POP_MAPPER_NAME);
+ OMP_CLAUSE_DECL (name) = null_pointer_node;
+ OMP_CLAUSE_CHAIN (name) = OMP_CLAUSE_CHAIN (last_new);
+ OMP_CLAUSE_CHAIN (last_new) = name;
+ }
return nlist;
}
@@ -43898,7 +43998,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
c_name = "detach";
break;
case PRAGMA_OMP_CLAUSE_MAP:
- clauses = cp_parser_omp_clause_map (parser, clauses);
+ clauses = cp_parser_omp_clause_map (parser, clauses,
+ /*mapper=*/false);
c_name = "map";
break;
case PRAGMA_OMP_CLAUSE_DEVICE:
@@ -48904,6 +49005,8 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
OMP_CLAUSE_CHAIN (c) = nc;
}
+ if (!processing_template_decl)
+ clauses = c_omp_instantiate_mappers (clauses);
clauses = finish_omp_clauses (clauses, C_ORT_OMP_TARGET);
c_omp_adjust_map_clauses (clauses, true);
@@ -49883,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;
@@ -51457,7 +51573,6 @@ cp_parser_omp_metadirective (cp_parser *parser, cp_token *pragma_tok,
{
error_at (match_loc, "too many %<otherwise%> or %<default%> "
"clauses in %<metadirective%>");
- cp_parser_skip_to_end_of_block_or_statement (parser, true);
goto fail;
}
else
@@ -51467,14 +51582,12 @@ cp_parser_omp_metadirective (cp_parser *parser, cp_token *pragma_tok,
{
error_at (match_loc, "%<otherwise%> or %<default%> clause "
"must appear last in %<metadirective%>");
- cp_parser_skip_to_end_of_block_or_statement (parser, true);
goto fail;
}
if (!default_p && strcmp (p, "when") != 0)
{
error_at (match_loc, "%qs is not valid for %qs",
p, "metadirective");
- cp_parser_skip_to_end_of_block_or_statement (parser, true);
goto fail;
}
@@ -51543,7 +51656,6 @@ cp_parser_omp_metadirective (cp_parser *parser, cp_token *pragma_tok,
if (i == 0)
{
error_at (loc, "expected directive name");
- cp_parser_skip_to_end_of_block_or_statement (parser, true);
goto fail;
}
@@ -51616,7 +51728,10 @@ cp_parser_omp_metadirective (cp_parser *parser, cp_token *pragma_tok,
goto add;
case CPP_CLOSE_PAREN:
if (nesting_depth-- == 0)
- break;
+ {
+ cp_lexer_consume_token (parser->lexer);
+ break;
+ }
goto add;
default:
add:
@@ -51628,8 +51743,6 @@ cp_parser_omp_metadirective (cp_parser *parser, cp_token *pragma_tok,
break;
}
- cp_lexer_consume_token (parser->lexer);
-
if (!skip)
{
cp_token eol_token = {};
@@ -51761,11 +51874,8 @@ cp_parser_omp_metadirective (cp_parser *parser, cp_token *pragma_tok,
return;
fail:
- /* Skip the metadirective pragma. */
+ /* Skip the metadirective pragma. Do not skip the metadirective body. */
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
-
- /* Skip the metadirective body. */
- cp_parser_skip_to_end_of_block_or_statement (parser, true);
}
@@ -52184,6 +52294,175 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
obstack_free (&declarator_obstack, p);
}
+/* OpenMP 5.0
+ #pragma omp declare mapper([mapper-identifier:]type var) \
+ [clause[[,] clause] ... ] new-line */
+
+static void
+cp_parser_omp_declare_mapper (cp_parser *parser, cp_token *pragma_tok,
+ enum pragma_context)
+{
+ cp_token *token = NULL;
+ tree type = NULL_TREE, vardecl = NULL_TREE, block = NULL_TREE;
+ bool block_scope = false;
+ /* Don't create location wrapper nodes within "declare mapper"
+ directives. */
+ auto_suppress_location_wrappers sentinel;
+ tree mapper_name = NULL_TREE;
+ tree mapper_id, id, placeholder, mapper, maplist = NULL_TREE;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ goto fail;
+
+ if (current_function_decl)
+ block_scope = true;
+
+ token = cp_lexer_peek_token (parser->lexer);
+
+ if (cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON))
+ {
+ switch (token->type)
+ {
+ case CPP_NAME:
+ {
+ cp_expr e = cp_parser_identifier (parser);
+ if (e != error_mark_node)
+ mapper_name = e;
+ else
+ goto fail;
+ }
+ break;
+
+ case CPP_KEYWORD:
+ if (token->keyword == RID_DEFAULT)
+ {
+ mapper_name = NULL_TREE;
+ cp_lexer_consume_token (parser->lexer);
+ break;
+ }
+ /* Fallthrough. */
+
+ default:
+ cp_parser_error (parser, "expected identifier or %<default%>");
+ }
+
+ if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+ goto fail;
+ }
+
+ {
+ const char *saved_message = parser->type_definition_forbidden_message;
+ parser->type_definition_forbidden_message
+ = G_("types may not be defined within %<declare mapper%>");
+ type_id_in_expr_sentinel s (parser);
+ type = cp_parser_type_id (parser);
+ parser->type_definition_forbidden_message = saved_message;
+ }
+
+ if (type == error_mark_node)
+ goto fail;
+ if (dependent_type_p (type))
+ mapper_id = omp_mapper_id (mapper_name, NULL_TREE);
+ else
+ mapper_id = omp_mapper_id (mapper_name, type);
+
+ vardecl = build_lang_decl (VAR_DECL, mapper_id, type);
+ DECL_ARTIFICIAL (vardecl) = 1;
+ TREE_STATIC (vardecl) = 1;
+ TREE_PUBLIC (vardecl) = 0;
+ DECL_EXTERNAL (vardecl) = 0;
+ DECL_DECLARED_CONSTEXPR_P (vardecl) = 1;
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (vardecl) = 1;
+ DECL_OMP_DECLARE_MAPPER_P (vardecl) = 1;
+
+ keep_next_level (true);
+ block = begin_omp_structured_block ();
+
+ if (block_scope)
+ DECL_CONTEXT (vardecl) = current_function_decl;
+ else if (current_class_type)
+ DECL_CONTEXT (vardecl) = current_class_type;
+ else
+ DECL_CONTEXT (vardecl) = current_namespace;
+
+ if (processing_template_decl)
+ vardecl = push_template_decl (vardecl);
+
+ if ((id = cp_parser_declarator_id (parser, false)) == error_mark_node)
+ goto fail;
+
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ {
+ finish_omp_structured_block (block);
+ goto fail;
+ }
+
+ placeholder = build_lang_decl (VAR_DECL, id, type);
+ DECL_CONTEXT (placeholder) = DECL_CONTEXT (vardecl);
+ if (processing_template_decl)
+ placeholder = push_template_decl (placeholder);
+ pushdecl (placeholder);
+ cp_finish_decl (placeholder, NULL_TREE, 0, NULL_TREE, 0);
+ DECL_ARTIFICIAL (placeholder) = 1;
+ TREE_USED (placeholder) = 1;
+
+ while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
+ {
+ pragma_omp_clause c_kind = cp_parser_omp_clause_name (parser);
+ if (c_kind != PRAGMA_OMP_CLAUSE_MAP)
+ {
+ if (c_kind != PRAGMA_OMP_CLAUSE_NONE)
+ cp_parser_error (parser, "unexpected clause");
+ finish_omp_structured_block (block);
+ goto fail;
+ }
+ maplist = cp_parser_omp_clause_map (parser, maplist, /*mapper=*/true);
+ if (maplist == NULL_TREE)
+ break;
+ }
+
+ if (maplist == NULL_TREE)
+ {
+ cp_parser_error (parser, "missing %<map%> clause");
+ finish_omp_structured_block (block);
+ goto fail;
+ }
+
+ mapper = make_node (OMP_DECLARE_MAPPER);
+ TREE_TYPE (mapper) = type;
+ OMP_DECLARE_MAPPER_ID (mapper) = mapper_name;
+ OMP_DECLARE_MAPPER_DECL (mapper) = placeholder;
+ OMP_DECLARE_MAPPER_CLAUSES (mapper) = maplist;
+
+ finish_omp_structured_block (block);
+
+ DECL_INITIAL (vardecl) = mapper;
+
+ if (current_class_type)
+ {
+ if (processing_template_decl)
+ {
+ retrofit_lang_decl (vardecl);
+ SET_DECL_VAR_DECLARED_INLINE_P (vardecl);
+ }
+ finish_static_data_member_decl (vardecl, mapper,
+ /*init_const_expr_p=*/true, NULL_TREE, 0);
+ finish_member_declaration (vardecl);
+ }
+ else if (processing_template_decl && block_scope)
+ add_decl_expr (vardecl);
+ else
+ pushdecl (vardecl);
+
+ cp_check_omp_declare_mapper (vardecl);
+
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ return;
+
+fail:
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+}
+
/* OpenMP 4.0
#pragma omp declare simd declare-simd-clauses[optseq] new-line
#pragma omp declare reduction (reduction-id : typename-list : expression) \
@@ -52228,6 +52507,12 @@ cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
context);
return false;
}
+ if (strcmp (p, "mapper") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_omp_declare_mapper (parser, pragma_tok, context);
+ return false;
+ }
if (!flag_openmp) /* flag_openmp_simd */
{
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
@@ -52241,7 +52526,7 @@ cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
}
}
cp_parser_error (parser, "expected %<simd%>, %<reduction%>, "
- "%<target%> or %<variant%>");
+ "%<target%>, %<mapper%> or %<variant%>");
cp_parser_require_pragma_eol (parser, pragma_tok);
return false;
}
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c687fdc..c5a3abe 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -15989,7 +15989,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
= remove_attribute ("visibility", DECL_ATTRIBUTES (r));
}
determine_visibility (r);
- if ((!local_p || TREE_STATIC (t)) && DECL_SECTION_NAME (t))
+ if ((!local_p || TREE_STATIC (t))
+ && !(flag_openmp && DECL_LANG_SPECIFIC (t)
+ && DECL_OMP_DECLARE_MAPPER_P (t))
+ && DECL_SECTION_NAME (t))
set_decl_section_name (r, t);
}
@@ -16041,6 +16044,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (r));
}
+ if (flag_openmp
+ && VAR_P (t)
+ && DECL_LANG_SPECIFIC (t)
+ && DECL_OMP_DECLARE_MAPPER_P (t)
+ && strchr (IDENTIFIER_POINTER (DECL_NAME (t)), '~') == NULL)
+ DECL_NAME (r) = omp_mapper_id (DECL_NAME (t), TREE_TYPE (r));
+
layout_decl (r, 0);
}
break;
@@ -18313,8 +18323,10 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
}
new_clauses = nreverse (new_clauses);
- if (ort != C_ORT_OMP_DECLARE_SIMD)
+ if (ort != C_ORT_OMP_DECLARE_SIMD && ort != C_ORT_OMP_DECLARE_MAPPER)
{
+ if (ort == C_ORT_OMP_TARGET)
+ new_clauses = c_omp_instantiate_mappers (new_clauses);
new_clauses = finish_omp_clauses (new_clauses, ort);
if (linear_no_step)
for (nc = new_clauses; nc; nc = OMP_CLAUSE_CHAIN (nc))
@@ -18368,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:
@@ -18376,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)
@@ -20034,6 +20062,22 @@ tsubst_stmt (tree t, tree args, tsubst_flags_t complain, tree in_decl)
break;
}
+ case OMP_DECLARE_MAPPER:
+ {
+ t = copy_node (t);
+
+ tree decl = OMP_DECLARE_MAPPER_DECL (t);
+ decl = tsubst (decl, args, complain, in_decl);
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree clauses = OMP_DECLARE_MAPPER_CLAUSES (t);
+ clauses = tsubst_omp_clauses (clauses, C_ORT_OMP_DECLARE_MAPPER, args,
+ complain, in_decl);
+ TREE_TYPE (t) = type;
+ OMP_DECLARE_MAPPER_DECL (t) = decl;
+ OMP_DECLARE_MAPPER_CLAUSES (t) = clauses;
+ RETURN (t);
+ }
+
case TRANSACTION_EXPR:
{
int flags = 0;
@@ -21093,6 +21137,23 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
RETURN (build_omp_array_section (EXPR_LOCATION (t), op0, op1, op2));
}
+ case OMP_DECLARE_MAPPER:
+ {
+ t = copy_node (t);
+
+ tree decl = OMP_DECLARE_MAPPER_DECL (t);
+ DECL_OMP_DECLARE_MAPPER_P (decl) = 1;
+ decl = tsubst (decl, args, complain, in_decl);
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree clauses = OMP_DECLARE_MAPPER_CLAUSES (t);
+ clauses = tsubst_omp_clauses (clauses, C_ORT_OMP_DECLARE_MAPPER, args,
+ complain, in_decl);
+ TREE_TYPE (t) = type;
+ OMP_DECLARE_MAPPER_DECL (t) = decl;
+ OMP_DECLARE_MAPPER_CLAUSES (t) = clauses;
+ RETURN (t);
+ }
+
case SIZEOF_EXPR:
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))
|| ARGUMENT_PACK_P (TREE_OPERAND (t, 0)))
@@ -28036,7 +28097,9 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
|| (external_p && VAR_P (d))
/* Handle here a deleted function too, avoid generating
its body (c++/61080). */
- || deleted_p)
+ || deleted_p
+ /* We need the initializer for an OpenMP declare mapper. */
+ || (VAR_P (d) && DECL_LANG_SPECIFIC (d) && DECL_OMP_DECLARE_MAPPER_P (d)))
{
/* The definition of the static data member is now required so
we must substitute the initializer. */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 241f273..7bc346b 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -45,13 +45,13 @@ along with GCC; see the file COPYING3. If not see
#include "gomp-constants.h"
#include "predict.h"
#include "memmodel.h"
+#include "gimplify.h"
/* There routines provide a modular interface to perform many parsing
operations. They may therefore be used during actual parsing, or
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. */
@@ -1116,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. */
@@ -2770,7 +2770,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope,
else if (PACK_EXPANSION_P (type))
/* Don't bother trying to represent this. */
type = NULL_TREE;
- else if (WILDCARD_TYPE_P (TREE_TYPE (object)))
+ else if (!TREE_TYPE (object) || WILDCARD_TYPE_P (TREE_TYPE (object)))
/* We don't know what the eventual quals will be, so punt until
instantiation time.
@@ -3605,16 +3605,11 @@ finish_this_expr (void)
{
tree result = NULL_TREE;
- if (current_class_ptr)
- {
- tree type = TREE_TYPE (current_class_ref);
-
- /* In a lambda expression, 'this' refers to the captured 'this'. */
- if (LAMBDA_TYPE_P (type))
- result = lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (type), true);
- else
- result = current_class_ptr;
- }
+ if (current_class_type && LAMBDA_TYPE_P (current_class_type))
+ result = (lambda_expr_this_capture
+ (CLASSTYPE_LAMBDA_EXPR (current_class_type), /*add*/true));
+ else if (current_class_ptr)
+ result = current_class_ptr;
if (result)
/* The keyword 'this' is a prvalue expression. */
@@ -6745,6 +6740,97 @@ omp_reduction_lookup (location_t loc, tree id, tree type, tree *baselinkp,
return id;
}
+/* Return identifier to look up for omp declare mapper. */
+
+tree
+omp_mapper_id (tree mapper_id, tree type)
+{
+ const char *p = NULL;
+ const char *m = NULL;
+
+ if (mapper_id == NULL_TREE)
+ p = "";
+ else if (TREE_CODE (mapper_id) == IDENTIFIER_NODE)
+ p = IDENTIFIER_POINTER (mapper_id);
+ else
+ return error_mark_node;
+
+ if (type != NULL_TREE)
+ m = mangle_type_string (TYPE_MAIN_VARIANT (type));
+
+ const char prefix[] = "omp declare mapper ";
+ size_t lenp = sizeof (prefix);
+ if (strncmp (p, prefix, lenp - 1) == 0)
+ lenp = 1;
+ size_t len = strlen (p);
+ size_t lenm = m ? strlen (m) + 1 : 0;
+ char *name = XALLOCAVEC (char, lenp + len + lenm);
+ memcpy (name, prefix, lenp - 1);
+ memcpy (name + lenp - 1, p, len + 1);
+ if (m)
+ {
+ name[lenp + len - 1] = '~';
+ memcpy (name + lenp + len, m, lenm);
+ }
+ return get_identifier (name);
+}
+
+tree
+cxx_omp_mapper_lookup (tree id, tree type)
+{
+ if (!RECORD_OR_UNION_TYPE_P (type))
+ return NULL_TREE;
+ id = omp_mapper_id (id, type);
+ return lookup_name (id);
+}
+
+tree
+cxx_omp_extract_mapper_directive (tree vardecl)
+{
+ gcc_assert (TREE_CODE (vardecl) == VAR_DECL);
+
+ /* Instantiate the decl if we haven't already. */
+ mark_used (vardecl);
+ tree body = DECL_INITIAL (vardecl);
+
+ if (TREE_CODE (body) == STATEMENT_LIST)
+ {
+ tree_stmt_iterator tsi = tsi_start (body);
+ gcc_assert (TREE_CODE (tsi_stmt (tsi)) == DECL_EXPR);
+ tsi_next (&tsi);
+ body = tsi_stmt (tsi);
+ }
+
+ gcc_assert (TREE_CODE (body) == OMP_DECLARE_MAPPER);
+
+ return body;
+}
+
+/* For now we can handle singleton OMP_ARRAY_SECTIONs with custom mappers, but
+ nothing more complicated. */
+
+tree
+cxx_omp_map_array_section (location_t loc, tree t)
+{
+ tree low = TREE_OPERAND (t, 1);
+ tree len = TREE_OPERAND (t, 2);
+
+ if (len && integer_onep (len))
+ {
+ t = TREE_OPERAND (t, 0);
+
+ if (!low)
+ low = integer_zero_node;
+
+ if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
+ t = convert_from_reference (t);
+
+ t = build_array_ref (loc, t, low);
+ }
+
+ return t;
+}
+
/* Helper function for cp_parser_omp_declare_reduction_exprs
and tsubst_omp_udr.
Remove CLEANUP_STMT for data (omp_priv variable).
@@ -7226,6 +7312,33 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
return false;
}
+/* Check an instance of an "omp declare mapper" function. */
+
+bool
+cp_check_omp_declare_mapper (tree udm)
+{
+ tree type = TREE_TYPE (udm);
+ location_t loc = DECL_SOURCE_LOCATION (udm);
+
+ if (type == error_mark_node)
+ return false;
+
+ if (!processing_template_decl && !RECORD_OR_UNION_TYPE_P (type))
+ {
+ error_at (loc, "%qT is not a struct, union or class type in "
+ "%<#pragma omp declare mapper%>", type);
+ return false;
+ }
+ if (!processing_template_decl && CLASSTYPE_VBASECLASSES (type))
+ {
+ error_at (loc, "%qT must not be a virtual base class in "
+ "%<#pragma omp declare mapper%>", type);
+ return false;
+ }
+
+ return true;
+}
+
/* Called from finish_struct_1. linear(this) or linear(this:step)
clauses might not be finalized yet because the class has been incomplete
when parsing #pragma omp declare simd methods. Fix those up now. */
@@ -8870,6 +8983,12 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case OMP_CLAUSE_MAP:
if (OMP_CLAUSE_MAP_IMPLICIT (c) && !implicit_moved)
goto move_implicit;
+ if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POP_MAPPER_NAME)
+ {
+ remove = true;
+ break;
+ }
/* FALLTHRU */
case OMP_CLAUSE_TO:
case OMP_CLAUSE_FROM:
@@ -10489,6 +10608,8 @@ struct omp_target_walk_data
/* Local variables declared inside a BIND_EXPR, used to filter out such
variables when recording lambda_objects_accessed. */
hash_set<tree> local_decls;
+
+ omp_mapper_list<tree> *mappers;
};
/* Helper function of finish_omp_target_clauses, called via
@@ -10502,6 +10623,7 @@ finish_omp_target_clauses_r (tree *tp, int *walk_subtrees, void *ptr)
struct omp_target_walk_data *data = (struct omp_target_walk_data *) ptr;
tree current_object = data->current_object;
tree current_closure = data->current_closure;
+ omp_mapper_list<tree> *mlist = data->mappers;
/* References inside of these expression codes shouldn't incur any
form of mapping, so return early. */
@@ -10515,6 +10637,27 @@ finish_omp_target_clauses_r (tree *tp, int *walk_subtrees, void *ptr)
if (TREE_CODE (t) == OMP_CLAUSE)
return NULL_TREE;
+ if (!processing_template_decl)
+ {
+ tree aggr_type = NULL_TREE;
+
+ if (TREE_CODE (t) == COMPONENT_REF
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0))))
+ aggr_type = TREE_TYPE (TREE_OPERAND (t, 0));
+ else if ((TREE_CODE (t) == VAR_DECL
+ || TREE_CODE (t) == PARM_DECL
+ || TREE_CODE (t) == RESULT_DECL)
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
+ aggr_type = TREE_TYPE (t);
+
+ if (aggr_type)
+ {
+ tree mapper_fn = cxx_omp_mapper_lookup (NULL_TREE, aggr_type);
+ if (mapper_fn)
+ mlist->add_mapper (NULL_TREE, aggr_type, mapper_fn);
+ }
+ }
+
if (current_object)
{
tree this_expr = TREE_OPERAND (current_object, 0);
@@ -10617,10 +10760,48 @@ finish_omp_target_clauses (location_t loc, tree body, tree *clauses_ptr)
else
data.current_closure = NULL_TREE;
- cp_walk_tree_without_duplicates (&body, finish_omp_target_clauses_r, &data);
-
auto_vec<tree, 16> new_clauses;
+ if (!processing_template_decl)
+ {
+ hash_set<omp_name_type<tree> > seen_types;
+ auto_vec<tree> mapper_fns;
+ omp_mapper_list<tree> mlist (&seen_types, &mapper_fns);
+ data.mappers = &mlist;
+
+ cp_walk_tree_without_duplicates (&body, finish_omp_target_clauses_r,
+ &data);
+
+ unsigned int i;
+ tree mapper_fn;
+ FOR_EACH_VEC_ELT (mapper_fns, i, mapper_fn)
+ c_omp_find_nested_mappers (&mlist, mapper_fn);
+
+ FOR_EACH_VEC_ELT (mapper_fns, i, mapper_fn)
+ {
+ tree mapper = cxx_omp_extract_mapper_directive (mapper_fn);
+ if (mapper == error_mark_node)
+ continue;
+ tree mapper_name = OMP_DECLARE_MAPPER_ID (mapper);
+ tree decl = OMP_DECLARE_MAPPER_DECL (mapper);
+ if (BASELINK_P (mapper_fn))
+ mapper_fn = BASELINK_FUNCTIONS (mapper_fn);
+
+ tree c = build_omp_clause (loc, OMP_CLAUSE__MAPPER_BINDING_);
+ OMP_CLAUSE__MAPPER_BINDING__ID (c) = mapper_name;
+ OMP_CLAUSE__MAPPER_BINDING__DECL (c) = decl;
+ OMP_CLAUSE__MAPPER_BINDING__MAPPER (c) = mapper_fn;
+
+ new_clauses.safe_push (c);
+ }
+ }
+ else
+ {
+ data.mappers = NULL;
+ cp_walk_tree_without_duplicates (&body, finish_omp_target_clauses_r,
+ &data);
+ }
+
tree omp_target_this_expr = NULL_TREE;
tree *explicit_this_deref_map = NULL;
if (data.this_expr_accessed)
@@ -13238,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/cp/typeck.cc b/gcc/cp/typeck.cc
index af2cbaf..ac1eb39 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -11466,7 +11466,7 @@ check_return_expr (tree retval, bool *no_warning, bool *dangling)
/* Don't check copy-initialization for NRV in a coroutine ramp; we
implement this case as NRV, but it's specified as directly
initializing the return value from get_return_object(). */
- if (DECL_RAMP_FN (current_function_decl) && named_return_value_okay_p)
+ if (DECL_RAMP_P (current_function_decl) && named_return_value_okay_p)
converted = true;
/* First convert the value to the function's return type, then
diff --git a/gcc/diagnostic-format-html.cc b/gcc/diagnostic-format-html.cc
index f2b255b..05d4273 100644
--- a/gcc/diagnostic-format-html.cc
+++ b/gcc/diagnostic-format-html.cc
@@ -472,7 +472,7 @@ diagnostic_html_format_buffer::flush ()
/* class html_builder. */
/* Style information for writing out HTML paths.
- Colors taken from https://www.patternfly.org/v3/styles/color-palette/ */
+ Colors taken from https://pf3.patternfly.org/v3/styles/color-palette/ */
static const char * const HTML_STYLE
= (" <style>\n"
@@ -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.
@@ -700,11 +704,9 @@ html_builder::make_element_for_diagnostic (const diagnostic_info &diagnostic,
class html_token_printer : public token_printer
{
public:
- html_token_printer (html_builder &builder,
- xml::element &parent_element)
- : m_builder (builder)
+ html_token_printer (xml::printer &xp)
+ : m_xp (xp)
{
- m_open_elements.push_back (&parent_element);
}
void print_tokens (pretty_printer */*pp*/,
const pp_token_list &tokens) final override
@@ -722,62 +724,50 @@ html_builder::make_element_for_diagnostic (const diagnostic_info &diagnostic,
pp_token_text *sub = as_a <pp_token_text *> (iter);
/* The value might be in the obstack, so we may need to
copy it. */
- insertion_element ().add_text (sub->m_value.get ());
+ m_xp.add_text (sub->m_value.get ());
}
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:
{
- insertion_element ().add_text (open_quote);
- push_element (make_span ("gcc-quoted-text"));
+ m_xp.add_text (open_quote);
+ m_xp.push_tag_with_class ("span", "gcc-quoted-text");
}
break;
case pp_token::kind::end_quote:
{
- pop_element ();
- insertion_element ().add_text (close_quote);
+ m_xp.pop_tag ();
+ m_xp.add_text (close_quote);
}
break;
case pp_token::kind::begin_url:
{
pp_token_begin_url *sub = as_a <pp_token_begin_url *> (iter);
- auto anchor = std::make_unique<xml::element> ("a", true);
- anchor->set_attr ("href", sub->m_value.get ());
- push_element (std::move (anchor));
+ m_xp.push_tag ("a", true);
+ m_xp.set_attr ("href", sub->m_value.get ());
}
break;
case pp_token::kind::end_url:
- pop_element ();
+ m_xp.pop_tag ();
break;
}
}
private:
- xml::element &insertion_element () const
- {
- return *m_open_elements.back ();
- }
- void push_element (std::unique_ptr<xml::element> new_element)
- {
- xml::element &current_top = insertion_element ();
- m_open_elements.push_back (new_element.get ());
- current_top.add_child (std::move (new_element));
- }
- void pop_element ()
- {
- m_open_elements.pop_back ();
- }
-
- html_builder &m_builder;
- /* We maintain a stack of currently "open" elements.
- Children are added to the topmost open element. */
- std::vector<xml::element *> m_open_elements;
+ xml::printer &m_xp;
};
auto diag_element = make_div ("gcc-diagnostic");
@@ -798,7 +788,8 @@ html_builder::make_element_for_diagnostic (const diagnostic_info &diagnostic,
message_span->set_attr ("id", message_span_id);
add_focus_id (message_span_id);
- html_token_printer tok_printer (*this, *message_span.get ());
+ xml::printer xp (*message_span.get ());
+ html_token_printer tok_printer (xp);
m_printer->set_token_printer (&tok_printer);
pp_output_formatted_text (m_printer, m_context.get_urlifier ());
m_printer->set_token_printer (nullptr);
@@ -897,10 +888,14 @@ html_builder::make_metadata_element (label_text label,
xml::printer xp (*item.get ());
xp.add_text ("[");
{
- xp.push_tag ("a", true);
- xp.set_attr ("href", url.get ());
+ if (url.get ())
+ {
+ xp.push_tag ("a", true);
+ xp.set_attr ("href", url.get ());
+ }
xp.add_text (label.get ());
- xp.pop_tag ();
+ if (url.get ())
+ xp.pop_tag ();
}
xp.add_text ("]");
return item;
diff --git a/gcc/diagnostic-show-locus.cc b/gcc/diagnostic-show-locus.cc
index 397fffb..3654102 100644
--- a/gcc/diagnostic-show-locus.cc
+++ b/gcc/diagnostic-show-locus.cc
@@ -148,6 +148,7 @@ class colorizer
const char *m_fixit_insert;
const char *m_fixit_delete;
const char *m_stop_color;
+ std::string m_current_named_color;
};
/* In order to handle multibyte sources properly, all of this logic needs to be
@@ -538,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)
{}
@@ -619,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
@@ -647,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;
@@ -670,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);
}
@@ -834,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
@@ -843,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
@@ -932,9 +955,13 @@ colorizer::~colorizer ()
void
colorizer::set_named_color (const char *color)
{
+ if (m_current_state == STATE_NAMED_COLOR
+ && color == m_current_named_color)
+ return;
finish_state (m_current_state);
m_current_state = STATE_NAMED_COLOR;
pp_string (&m_pp, colorize_start (pp_show_color (&m_pp), color));
+ m_current_named_color = color;
}
/* Update state, printing color codes if necessary if there's a state
@@ -2297,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
@@ -2330,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;
}
@@ -2472,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. */
@@ -2496,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. */
@@ -2515,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 ();
}
@@ -2601,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 ();
}
@@ -2799,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)
@@ -2832,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++;
}
}
@@ -3671,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)
{
@@ -3852,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 bd3d29c..e64c0d6 100644
--- a/gcc/doc/riscv-ext.texi
+++ b/gcc/doc/riscv-ext.texi
@@ -494,6 +494,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
@@ -510,6 +514,10 @@
@tab 1.0
@tab State enable extension
+@item smdbltrp
+@tab 1.0
+@tab Double Trap Extensions
+
@item ssaia
@tab 1.0
@tab Advanced interrupt architecture extension for supervisor-mode
@@ -538,6 +546,10 @@
@tab 1.0
@tab ssstrict extension
+@item ssdbltrp
+@tab 1.0
+@tab Double Trap Extensions
+
@item supm
@tab 1.0
@tab supm extension
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 0c4edf8..e740ecc 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,36 @@
+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
+ * check.cc(check_c_ptr_2): Rephrase error message
+ for clarity.
+
2025-05-28 Tobias Burnus <tburnus@baylibre.com>
PR fortran/113152
@@ -6,7 +39,7 @@
2025-05-28 Jerry DeLisle <jvdelisle@gcc.gnu.org>
- PR fortran/119586
+ PR fortran/119856
* io.cc: Set missing comma error checks to STD_STD_LEGACY.
2025-05-28 Yuao Ma <c8ef@outlook.com>
diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc
index c693e42..c8904df 100644
--- a/gcc/fortran/check.cc
+++ b/gcc/fortran/check.cc
@@ -6037,8 +6037,8 @@ bool check_c_ptr_2 (gfc_expr *c_ptr_1, gfc_expr *c_ptr_2)
check_2_error:
gfc_error ("Argument C_PTR_2 at %L to C_ASSOCIATED shall have the "
- "same type as C_PTR_1: %s instead of %s", &c_ptr_2->where,
- gfc_typename (&c_ptr_1->ts), gfc_typename (&c_ptr_2->ts));
+ "same type as C_PTR_1, found %s instead of %s", &c_ptr_2->where,
+ gfc_typename (&c_ptr_2->ts), gfc_typename (&c_ptr_1->ts));
return false;
}
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/interface.cc b/gcc/fortran/interface.cc
index 753f589..b854292 100644
--- a/gcc/fortran/interface.cc
+++ b/gcc/fortran/interface.cc
@@ -2547,7 +2547,14 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
}
else if (formal->attr.function)
{
- if (!gfc_compare_types (&global_asym->ts,
+ gfc_typespec ts;
+
+ if (global_asym->result)
+ ts = global_asym->result->ts;
+ else
+ ts = global_asym->ts;
+
+ if (!gfc_compare_types (&ts,
&formal->ts))
{
gfc_error ("Type mismatch at %L passing global "
diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index 538eb65..8d4ca39 100644
--- a/gcc/fortran/parse.cc
+++ b/gcc/fortran/parse.cc
@@ -27,6 +27,9 @@ along with GCC; see the file COPYING3. If not see
#include "match.h"
#include "parse.h"
#include "tree-core.h"
+#include "tree.h"
+#include "fold-const.h"
+#include "tree-hash-traits.h"
#include "omp-general.h"
/* Current statement label. Zero means no statement label. Because new_st
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/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/ggc-page.cc b/gcc/ggc-page.cc
index 0f674c0..ebd1197 100644
--- a/gcc/ggc-page.cc
+++ b/gcc/ggc-page.cc
@@ -426,7 +426,7 @@ static struct ggc_globals
int dev_zero_fd;
#endif
- /* A cache of free system pages. Entry 0 is fallback. */
+ /* A cache of free system pages. Entry 0 is fallback. */
struct free_list free_lists[num_free_list];
#ifdef USING_MALLOC_PAGE_GROUPS
@@ -787,7 +787,7 @@ find_free_list (size_t entry_size)
return &G.free_lists[i];
}
}
- /* Fallback. Does this happen? */
+ /* Fallback. Does this happen? */
if (GATHER_STATISTICS)
G.stats.fallback++;
return &G.free_lists[0];
@@ -955,7 +955,7 @@ alloc_page (unsigned order)
/* If we allocated multiple pages, put the rest on the free list. */
if (multiple_pages)
{
- struct page_entry *e, *f = G.free_pages;
+ struct page_entry *e, *f = free_list->free_pages;
for (a = enda - G.pagesize; a != page; a -= G.pagesize)
{
e = XCNEWVAR (struct page_entry, page_entry_size);
@@ -1073,10 +1073,10 @@ free_page (page_entry *entry)
/* Release the free page cache for FREE_LIST to the system. */
static void
-do_release_pages (struct free_list *free_list)
+do_release_pages (struct free_list *free_list, size_t &n1, size_t &n2)
{
- size_t n1 = 0;
- size_t n2 = 0;
+ (void) n1;
+ (void) n2;
#ifdef USING_MADVISE
page_entry *p, *start_p;
char *start;
@@ -1089,7 +1089,7 @@ do_release_pages (struct free_list *free_list)
This allows other allocators to grab these areas if needed.
This is only done on larger chunks to avoid fragmentation.
This does not always work because the free_pages list is only
- approximately sorted. */
+ approximately sorted. */
p = free_list->free_pages;
prev = NULL;
@@ -1104,7 +1104,7 @@ do_release_pages (struct free_list *free_list)
{
len += p->bytes;
if (!p->discarded)
- mapped_len += p->bytes;
+ mapped_len += p->bytes;
newprev = p;
p = p->next;
}
@@ -1129,7 +1129,7 @@ do_release_pages (struct free_list *free_list)
}
/* Now give back the fragmented pages to the OS, but keep the address
- space to reuse it next time. */
+ space to reuse it next time. */
for (p = free_list->free_pages; p; )
{
@@ -1149,10 +1149,10 @@ do_release_pages (struct free_list *free_list)
}
/* Give the page back to the kernel, but don't free the mapping.
This avoids fragmentation in the virtual memory map of the
- process. Next time we can reuse it by just touching it. */
+ process. Next time we can reuse it by just touching it. */
madvise (start, len, MADV_DONTNEED);
/* Don't count those pages as mapped to not touch the garbage collector
- unnecessarily. */
+ unnecessarily. */
G.bytes_mapped -= len;
n2 += len;
while (start_p != p)
@@ -1195,7 +1195,6 @@ do_release_pages (struct free_list *free_list)
#endif
#ifdef USING_MALLOC_PAGE_GROUPS
page_entry **pp, *p;
- page_group **gp, *g;
/* Remove all pages from free page groups from the list. */
pp = &free_list->free_pages;
@@ -1207,6 +1206,20 @@ do_release_pages (struct free_list *free_list)
}
else
pp = &p->next;
+#endif
+}
+
+/* Release the free page cache to the system. */
+
+static void
+release_pages ()
+{
+ size_t n1 = 0;
+ size_t n2 = 0;
+ for (int i = 0; i < num_free_list; i++)
+ do_release_pages (&G.free_lists[i], n1, n2);
+#ifdef USING_MALLOC_PAGE_GROUPS
+ page_group **gp, *g;
/* Remove all free page groups, and release the storage. */
gp = &G.page_groups;
@@ -1232,15 +1245,6 @@ do_release_pages (struct free_list *free_list)
}
}
-/* Release the free page cache to the system. */
-
-static void
-release_pages ()
-{
- for (int i = 0; i < num_free_list; i++)
- do_release_pages (&G.free_lists[i]);
-}
-
/* This table provides a fast way to determine ceil(log_2(size)) for
allocation requests. The minimum allocation size is eight bytes. */
#define NUM_SIZE_LOOKUP 512
@@ -2008,9 +2012,9 @@ clear_marks (void)
}
}
-/* Check if any blocks with a registered finalizer have become unmarked. If so
+/* Check if any blocks with a registered finalizer have become unmarked. If so
run the finalizer and unregister it because the block is about to be freed.
- Note that no garantee is made about what order finalizers will run in so
+ Note that no guarantee is made about what order finalizers will run in so
touching other objects in gc memory is extremely unwise. */
static void
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/gimple-ssa-sccopy.cc b/gcc/gimple-ssa-sccopy.cc
index ee2a7fa..c933745 100644
--- a/gcc/gimple-ssa-sccopy.cc
+++ b/gcc/gimple-ssa-sccopy.cc
@@ -464,7 +464,7 @@ class scc_copy_prop
public:
scc_copy_prop ();
~scc_copy_prop ();
- void propagate ();
+ bool propagate ();
private:
/* Bitmap tracking statements which were propagated so that they can be
@@ -474,15 +474,16 @@ private:
void visit_op (tree op, hash_set<tree> &outer_ops,
hash_set<gimple *> &scc_set, bool &is_inner,
tree &last_outer_op);
- void replace_scc_by_value (vec<gimple *> scc, tree val);
+ bool replace_scc_by_value (vec<gimple *> scc, tree val);
};
/* For each statement from given SCC, replace its usages by value
VAL. */
-void
+bool
scc_copy_prop::replace_scc_by_value (vec<gimple *> scc, tree val)
{
+ bool didsomething = false;
for (gimple *stmt : scc)
{
tree name = gimple_get_lhs (stmt);
@@ -497,10 +498,12 @@ scc_copy_prop::replace_scc_by_value (vec<gimple *> scc, tree val)
}
replace_uses_by (name, val);
bitmap_set_bit (dead_stmts, SSA_NAME_VERSION (name));
+ didsomething = true;
}
if (dump_file)
fprintf (dump_file, "Replacing SCC of size %d\n", scc.length ());
+ return didsomething;
}
/* Part of 'scc_copy_prop::propagate ()'. */
@@ -566,9 +569,10 @@ scc_copy_prop::visit_op (tree op, hash_set<tree> &outer_ops,
Braun, Buchwald, Hack, Leissa, Mallon, Zwinkau, 2013, LNCS vol. 7791,
Section 3.2. */
-void
+bool
scc_copy_prop::propagate ()
{
+ bool didsomething = false;
auto_vec<gimple *> useful_stmts = get_all_stmt_may_generate_copy ();
scc_discovery discovery;
@@ -636,7 +640,7 @@ scc_copy_prop::propagate ()
{
/* The only operand in outer_ops. */
tree outer_op = last_outer_op;
- replace_scc_by_value (scc, outer_op);
+ didsomething |= replace_scc_by_value (scc, outer_op);
}
else if (outer_ops.elements () > 1)
{
@@ -651,6 +655,7 @@ scc_copy_prop::propagate ()
scc.release ();
}
+ return didsomething;
}
scc_copy_prop::scc_copy_prop ()
@@ -683,7 +688,7 @@ const pass_data pass_data_sccopy =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
+ 0, /* todo_flags_finish */
};
class pass_sccopy : public gimple_opt_pass
@@ -703,8 +708,7 @@ unsigned
pass_sccopy::execute (function *)
{
scc_copy_prop sccopy;
- sccopy.propagate ();
- return 0;
+ return sccopy.propagate () ? TODO_cleanup_cfg : 0;
}
} // anon namespace
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 4f385b1..9f9ff92 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -273,6 +273,7 @@ struct gimplify_omp_ctx
{
struct gimplify_omp_ctx *outer_context;
splay_tree variables;
+ hash_map<omp_name_type<tree>, tree> *implicit_mappers;
hash_set<tree> *privatized_types;
tree clauses;
/* Iteration variables in an OMP_FOR. */
@@ -507,6 +508,7 @@ new_omp_context (enum omp_region_type region_type)
c = XCNEW (struct gimplify_omp_ctx);
c->outer_context = gimplify_omp_ctxp;
c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
+ c->implicit_mappers = new hash_map<omp_name_type<tree>, tree>;
c->privatized_types = new hash_set<tree>;
c->location = input_location;
c->region_type = region_type;
@@ -530,6 +532,7 @@ delete_omp_context (struct gimplify_omp_ctx *c)
{
splay_tree_delete (c->variables);
delete c->privatized_types;
+ delete c->implicit_mappers;
c->loop_iter_var.release ();
XDELETE (c);
}
@@ -12892,6 +12895,218 @@ error_out:
return success;
}
+struct instantiate_mapper_info
+{
+ tree *mapper_clauses_p;
+ struct gimplify_omp_ctx *omp_ctx;
+ gimple_seq *pre_p;
+};
+
+/* Helper function for omp_instantiate_mapper. */
+
+static tree
+remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data)
+{
+ copy_body_data *id = (copy_body_data *) data;
+
+ if (DECL_P (*tp))
+ {
+ tree replacement = remap_decl (*tp, id);
+ if (*tp != replacement)
+ {
+ *tp = unshare_expr (replacement);
+ *walk_subtrees = 0;
+ }
+ }
+
+ return NULL_TREE;
+}
+
+/* A copy_decl implementation (for use with tree-inline.cc functions) that
+ only transform decls or SSA names that are part of a map we already
+ prepared. */
+
+static tree
+omp_mapper_copy_decl (tree var, copy_body_data *cb)
+{
+ tree *repl = cb->decl_map->get (var);
+
+ if (repl)
+ return *repl;
+
+ return var;
+}
+
+static tree *
+omp_instantiate_mapper (gimple_seq *pre_p,
+ hash_map<omp_name_type<tree>, tree> *implicit_mappers,
+ tree mapperfn, tree expr, enum gomp_map_kind outer_kind,
+ tree *mapper_clauses_p)
+{
+ tree mapper_name = NULL_TREE;
+ tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapperfn);
+ gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER);
+
+ tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper);
+ tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper);
+
+ /* The "extraction map" is used to map the mapper variable in the "declare
+ mapper" directive, and also any temporary variables that have been created
+ as part of expanding the mapper function's body (which are expanded as a
+ "bind" expression in the pre_p sequence). */
+ hash_map<tree, tree> extraction_map;
+
+ extraction_map.put (dummy_var, expr);
+ extraction_map.put (expr, expr);
+
+ /* This copy_body_data is only used to remap the decls in the
+ OMP_DECLARE_MAPPER tree node expansion itself. All relevant decls should
+ already be in the current function. */
+ copy_body_data id;
+ memset (&id, 0, sizeof (id));
+ id.src_fn = current_function_decl;
+ id.dst_fn = current_function_decl;
+ id.src_cfun = cfun;
+ id.decl_map = &extraction_map;
+ id.copy_decl = omp_mapper_copy_decl;
+ id.transform_call_graph_edges = CB_CGE_DUPLICATE; // ???
+ id.transform_new_cfg = true; // ???
+
+ for (; clause; clause = OMP_CLAUSE_CHAIN (clause))
+ {
+ enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (clause);
+ tree *nested_mapper_p = NULL;
+
+ if (map_kind == GOMP_MAP_PUSH_MAPPER_NAME)
+ {
+ mapper_name = OMP_CLAUSE_DECL (clause);
+ continue;
+ }
+ else if (map_kind == GOMP_MAP_POP_MAPPER_NAME)
+ {
+ mapper_name = NULL_TREE;
+ continue;
+ }
+
+ tree decl = OMP_CLAUSE_DECL (clause);
+ tree unshared, type;
+ bool nonunit_array_with_mapper = false;
+
+ if (TREE_CODE (decl) == OMP_ARRAY_SECTION)
+ {
+ location_t loc = OMP_CLAUSE_LOCATION (clause);
+ tree tmp = lang_hooks.decls.omp_map_array_section (loc, decl);
+ if (tmp == decl)
+ {
+ unshared = unshare_expr (clause);
+ nonunit_array_with_mapper = true;
+ type = TREE_TYPE (TREE_TYPE (decl));
+ }
+ else
+ {
+ unshared = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
+ OMP_CLAUSE_CODE (clause));
+ OMP_CLAUSE_DECL (unshared) = tmp;
+ OMP_CLAUSE_SIZE (unshared)
+ = DECL_P (tmp) ? DECL_SIZE_UNIT (tmp)
+ : TYPE_SIZE_UNIT (TREE_TYPE (tmp));
+ type = TREE_TYPE (tmp);
+ }
+ }
+ else
+ {
+ unshared = unshare_expr (clause);
+ type = TREE_TYPE (decl);
+ }
+
+ walk_tree (&unshared, remap_mapper_decl_1, &id, NULL);
+
+ if (OMP_CLAUSE_MAP_KIND (unshared) == GOMP_MAP_UNSET)
+ OMP_CLAUSE_SET_MAP_KIND (unshared, outer_kind);
+
+ decl = OMP_CLAUSE_DECL (unshared);
+ type = TYPE_MAIN_VARIANT (type);
+
+ nested_mapper_p = implicit_mappers->get ({ mapper_name, type });
+
+ if (nested_mapper_p && *nested_mapper_p != mapperfn)
+ {
+ if (nonunit_array_with_mapper)
+ {
+ sorry ("user-defined mapper with non-unit length array section");
+ continue;
+ }
+
+ if (map_kind == GOMP_MAP_UNSET)
+ map_kind = outer_kind;
+
+ mapper_clauses_p
+ = omp_instantiate_mapper (pre_p, implicit_mappers,
+ *nested_mapper_p, decl, map_kind,
+ mapper_clauses_p);
+ continue;
+ }
+
+ *mapper_clauses_p = unshared;
+ mapper_clauses_p = &OMP_CLAUSE_CHAIN (unshared);
+ }
+
+ return mapper_clauses_p;
+}
+
+static int
+omp_instantiate_implicit_mappers (splay_tree_node n, void *data)
+{
+ tree decl = (tree) n->key;
+ instantiate_mapper_info *im_info = (instantiate_mapper_info *) data;
+ gimplify_omp_ctx *ctx = im_info->omp_ctx;
+ tree *mapper_p = NULL;
+ tree type = TREE_TYPE (decl);
+ bool ref_p = false;
+ unsigned flags = n->value;
+
+ if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
+ return 0;
+ if ((flags & GOVD_SEEN) == 0)
+ return 0;
+ /* If we already have clauses pertaining to a struct variable, then we don't
+ want to implicitly invoke a user-defined mapper. */
+ if ((flags & GOVD_EXPLICIT) != 0 && AGGREGATE_TYPE_P (TREE_TYPE (decl)))
+ return 0;
+
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ ref_p = true;
+ type = TREE_TYPE (type);
+ }
+
+ type = TYPE_MAIN_VARIANT (type);
+
+ if (DECL_P (decl) && type && AGGREGATE_TYPE_P (type))
+ {
+ gcc_assert (ctx);
+ mapper_p = ctx->implicit_mappers->get ({ NULL_TREE, type });
+ }
+
+ if (mapper_p)
+ {
+ /* If we have a reference, map the pointed-to object rather than the
+ reference itself. */
+ if (ref_p)
+ decl = build_fold_indirect_ref (decl);
+
+ im_info->mapper_clauses_p
+ = omp_instantiate_mapper (im_info->pre_p, ctx->implicit_mappers,
+ *mapper_p, decl, GOMP_MAP_TOFROM,
+ im_info->mapper_clauses_p);
+ /* Make sure we don't map the same variable implicitly in
+ gimplify_adjust_omp_clauses_1 also. */
+ n->value |= GOVD_EXPLICIT;
+ }
+
+ return 0;
+}
+
/* Scan the OMP clauses in *LIST_P, installing mappings into a new
and previous omp contexts. */
@@ -13688,6 +13903,17 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
}
goto do_notice;
+ case OMP_CLAUSE__MAPPER_BINDING_:
+ {
+ tree name = OMP_CLAUSE__MAPPER_BINDING__ID (c);
+ tree var = OMP_CLAUSE__MAPPER_BINDING__DECL (c);
+ tree type = TYPE_MAIN_VARIANT (TREE_TYPE (var));
+ tree fndecl = OMP_CLAUSE__MAPPER_BINDING__MAPPER (c);
+ ctx->implicit_mappers->put ({ name, type }, fndecl);
+ remove = true;
+ break;
+ }
+
case OMP_CLAUSE_USE_DEVICE_PTR:
case OMP_CLAUSE_USE_DEVICE_ADDR:
flags = GOVD_EXPLICIT;
@@ -14772,6 +14998,30 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
|| code == OMP_TARGET_ENTER_DATA
|| code == OMP_TARGET_EXIT_DATA)
{
+ tree mapper_clauses = NULL_TREE;
+ instantiate_mapper_info im_info;
+
+ im_info.mapper_clauses_p = &mapper_clauses;
+ im_info.omp_ctx = ctx;
+ im_info.pre_p = pre_p;
+
+ splay_tree_foreach (ctx->variables,
+ omp_instantiate_implicit_mappers,
+ (void *) &im_info);
+
+ if (mapper_clauses)
+ {
+ mapper_clauses
+ = lang_hooks.decls.omp_finish_mapper_clauses (mapper_clauses);
+
+ /* Stick the implicitly-expanded mapper clauses at the end of the
+ clause list. */
+ tree *tail = list_p;
+ while (*tail)
+ tail = &OMP_CLAUSE_CHAIN (*tail);
+ *tail = mapper_clauses;
+ }
+
vec<omp_mapping_group> *groups;
groups = omp_gather_mapping_groups (list_p);
hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap = NULL;
@@ -19257,6 +19507,15 @@ gimplify_omp_metadirective (tree *expr_p, gimple_seq *pre_p, gimple_seq *,
return GS_OK;
}
+/* Gimplify an OMP_DECLARE_MAPPER node (by just removing it). */
+
+static enum gimplify_status
+gimplify_omp_declare_mapper (tree *expr_p)
+{
+ *expr_p = NULL_TREE;
+ return GS_ALL_DONE;
+}
+
/* Convert the GENERIC expression tree *EXPR_P to GIMPLE. If the
expression produces a value to be used as an operand inside a GIMPLE
statement, the value will be stored back in *EXPR_P. This value will
@@ -20218,6 +20477,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
ret = GS_ALL_DONE;
break;
+ case OMP_DECLARE_MAPPER:
+ ret = gimplify_omp_declare_mapper (expr_p);
+ break;
+
case TRANSACTION_EXPR:
ret = gimplify_transaction (expr_p, pre_p);
break;
diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
index 0398d69..84d4fb5 100644
--- a/gcc/ipa-prop.cc
+++ b/gcc/ipa-prop.cc
@@ -542,6 +542,7 @@ ipa_dump_jump_function (FILE *f, ipa_jump_func *jump_func,
if (jump_func->m_vr)
{
+ fprintf (f, " ");
jump_func->m_vr->dump (f);
fprintf (f, "\n");
}
@@ -3329,6 +3330,10 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
ipa_edge_args *args = ipa_edge_args_sum->get (e);
if (!args)
return;
+ ipa_node_params *old_inline_root_info = ipa_node_params_sum->get (cs->callee);
+ ipa_node_params *new_inline_root_info
+ = ipa_node_params_sum->get (cs->caller->inlined_to
+ ? cs->caller->inlined_to : cs->caller);
int count = ipa_get_cs_argument_count (args);
int i;
@@ -3540,6 +3545,30 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
enum tree_code operation;
operation = ipa_get_jf_pass_through_operation (src);
+ tree old_ir_ptype = ipa_get_type (old_inline_root_info,
+ dst_fid);
+ tree new_ir_ptype = ipa_get_type (new_inline_root_info,
+ formal_id);
+ if (!useless_type_conversion_p (old_ir_ptype, new_ir_ptype))
+ {
+ /* Jump-function construction now permits type-casts
+ from an integer to another if the latter can hold
+ all values or has at least the same precision.
+ However, as we're combining multiple pass-through
+ functions together, we are losing information about
+ signedness and thus if conversions should sign or
+ zero extend. Therefore we must prevent combining
+ such jump-function if signednesses do not match. */
+ if (!INTEGRAL_TYPE_P (old_ir_ptype)
+ || !INTEGRAL_TYPE_P (new_ir_ptype)
+ || (TYPE_UNSIGNED (new_ir_ptype)
+ != TYPE_UNSIGNED (old_ir_ptype)))
+ {
+ ipa_set_jf_unknown (dst);
+ continue;
+ }
+ }
+
if (operation == NOP_EXPR)
{
bool agg_p;
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/langhooks-def.h b/gcc/langhooks-def.h
index 6b34d32..010aaed 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -90,6 +90,9 @@ extern bool lhd_omp_deep_mapping_p (const gimple *, tree);
extern tree lhd_omp_deep_mapping_cnt (const gimple *, tree, gimple_seq *);
extern void lhd_omp_deep_mapping (const gimple *, tree, unsigned HOST_WIDE_INT,
tree, tree, tree, tree, tree, gimple_seq *);
+extern tree lhd_omp_mapper_lookup (tree, tree);
+extern tree lhd_omp_extract_mapper_directive (tree);
+extern tree lhd_omp_map_array_section (location_t, tree);
struct gimplify_omp_ctx;
extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *,
tree);
@@ -279,6 +282,11 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
#define LANG_HOOKS_OMP_DEEP_MAPPING_P lhd_omp_deep_mapping_p
#define LANG_HOOKS_OMP_DEEP_MAPPING_CNT lhd_omp_deep_mapping_cnt
#define LANG_HOOKS_OMP_DEEP_MAPPING lhd_omp_deep_mapping
+#define LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES lhd_pass_through_t
+#define LANG_HOOKS_OMP_MAPPER_LOOKUP lhd_omp_mapper_lookup
+#define LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE \
+ lhd_omp_extract_mapper_directive
+#define LANG_HOOKS_OMP_MAP_ARRAY_SECTION lhd_omp_map_array_section
#define LANG_HOOKS_OMP_ALLOCATABLE_P hook_bool_tree_false
#define LANG_HOOKS_OMP_SCALAR_P lhd_omp_scalar_p
#define LANG_HOOKS_OMP_SCALAR_TARGET_P hook_bool_tree_false
@@ -316,6 +324,10 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
LANG_HOOKS_OMP_DEEP_MAPPING_P, \
LANG_HOOKS_OMP_DEEP_MAPPING_CNT, \
LANG_HOOKS_OMP_DEEP_MAPPING, \
+ LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES, \
+ LANG_HOOKS_OMP_MAPPER_LOOKUP, \
+ LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE, \
+ LANG_HOOKS_OMP_MAP_ARRAY_SECTION, \
LANG_HOOKS_OMP_ALLOCATABLE_P, \
LANG_HOOKS_OMP_SCALAR_P, \
LANG_HOOKS_OMP_SCALAR_TARGET_P, \
diff --git a/gcc/langhooks.cc b/gcc/langhooks.cc
index 77d5a42..194701f 100644
--- a/gcc/langhooks.cc
+++ b/gcc/langhooks.cc
@@ -669,6 +669,32 @@ lhd_omp_deep_mapping (const gimple *, tree, unsigned HOST_WIDE_INT, tree, tree,
{
}
+/* Look up an OpenMP "declare mapper" mapper. */
+
+tree
+lhd_omp_mapper_lookup (tree, tree)
+{
+ return NULL_TREE;
+}
+
+/* Given the representation used by the front-end to contain a mapper
+ directive, return the statement for the directive itself. */
+
+tree
+lhd_omp_extract_mapper_directive (tree)
+{
+ return error_mark_node;
+}
+
+/* Return a simplified form for OMP_ARRAY_SECTION argument, or
+ error_mark_node if impossible. */
+
+tree
+lhd_omp_map_array_section (location_t, tree)
+{
+ return error_mark_node;
+}
+
/* Return true if DECL is a scalar variable (for the purpose of
implicit firstprivatization & mapping). Only if alloc_ptr_ok
are allocatables and pointers accepted. */
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index dc8d878..cb03c83 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -328,6 +328,22 @@ struct lang_hooks_for_decls
tree data, tree sizes, tree kinds,
tree offset_data, tree offset, gimple_seq *seq);
+ /* Finish language-specific processing on mapping nodes after expanding
+ user-defined mappers. */
+ tree (*omp_finish_mapper_clauses) (tree clauses);
+
+ /* Find a mapper in the current parsing context, given a NAME (or
+ NULL_TREE) and TYPE. */
+ tree (*omp_mapper_lookup) (tree name, tree type);
+
+ /* Return the statement for the mapper directive definition, from the
+ representation used to contain it (e.g. an inline function
+ declaration). */
+ tree (*omp_extract_mapper_directive) (tree fndecl);
+
+ /* Return a simplified form for OMP_ARRAY_SECTION argument. */
+ tree (*omp_map_array_section) (location_t, tree t);
+
/* Return true if DECL is an allocatable variable (for the purpose of
implicit mapping). */
bool (*omp_allocatable_p) (tree decl);
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/omp-general.h b/gcc/omp-general.h
index 5d44ff9..37e331b 100644
--- a/gcc/omp-general.h
+++ b/gcc/omp-general.h
@@ -254,6 +254,92 @@ get_openacc_privatization_dump_flags ()
extern tree omp_build_component_ref (tree obj, tree field);
+template <typename T>
+struct omp_name_type
+{
+ tree name;
+ T type;
+};
+
+template <>
+struct default_hash_traits <omp_name_type<tree> >
+ : typed_noop_remove <omp_name_type<tree> >
+{
+ GTY((skip)) typedef omp_name_type<tree> value_type;
+ GTY((skip)) typedef omp_name_type<tree> compare_type;
+
+ static hashval_t
+ hash (omp_name_type<tree> p)
+ {
+ return p.name ? iterative_hash_expr (p.name, TYPE_UID (p.type))
+ : TYPE_UID (p.type);
+ }
+
+ static const bool empty_zero_p = true;
+
+ static bool
+ is_empty (omp_name_type<tree> p)
+ {
+ return p.type == NULL;
+ }
+
+ static bool
+ is_deleted (omp_name_type<tree>)
+ {
+ return false;
+ }
+
+ static bool
+ equal (const omp_name_type<tree> &a, const omp_name_type<tree> &b)
+ {
+ if (a.name == NULL_TREE && b.name == NULL_TREE)
+ return a.type == b.type;
+ else if (a.name == NULL_TREE || b.name == NULL_TREE)
+ return false;
+ else
+ return a.name == b.name && a.type == b.type;
+ }
+
+ static void
+ mark_empty (omp_name_type<tree> &e)
+ {
+ e.type = NULL;
+ }
+};
+
+template <typename T>
+struct omp_mapper_list
+{
+ hash_set<omp_name_type<T>> *seen_types;
+ vec<tree> *mappers;
+
+ omp_mapper_list (hash_set<omp_name_type<T>> *s, vec<tree> *m)
+ : seen_types (s), mappers (m) { }
+
+ void add_mapper (tree name, T type, tree mapperfn)
+ {
+ /* We can't hash a NULL_TREE... */
+ if (!name)
+ name = void_node;
+
+ omp_name_type<T> n_t = { name, type };
+
+ if (seen_types->contains (n_t))
+ return;
+
+ seen_types->add (n_t);
+ mappers->safe_push (mapperfn);
+ }
+
+ bool contains (tree name, T type)
+ {
+ if (!name)
+ name = void_node;
+
+ return seen_types->contains ({ name, type });
+ }
+};
+
namespace omp_addr_tokenizer {
/* These are the ways of accessing a variable that have special-case handling
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/pretty-print.cc b/gcc/pretty-print.cc
index 1f38702..6ecfcb2 100644
--- a/gcc/pretty-print.cc
+++ b/gcc/pretty-print.cc
@@ -2461,7 +2461,7 @@ pretty_printer::pretty_printer (int maximum_length)
m_indent_skip (0),
m_wrapping (),
m_format_decoder (nullptr),
- m_format_postprocessor (NULL),
+ m_format_postprocessor (nullptr),
m_token_printer (nullptr),
m_emitted_prefix (false),
m_need_newline (false),
@@ -2487,7 +2487,7 @@ pretty_printer::pretty_printer (const pretty_printer &other)
m_indent_skip (other.m_indent_skip),
m_wrapping (other.m_wrapping),
m_format_decoder (other.m_format_decoder),
- m_format_postprocessor (NULL),
+ m_format_postprocessor (nullptr),
m_token_printer (other.m_token_printer),
m_emitted_prefix (other.m_emitted_prefix),
m_need_newline (other.m_need_newline),
@@ -2508,8 +2508,6 @@ pretty_printer::pretty_printer (const pretty_printer &other)
pretty_printer::~pretty_printer ()
{
- if (m_format_postprocessor)
- delete m_format_postprocessor;
m_buffer->~output_buffer ();
XDELETE (m_buffer);
free (m_prefix);
diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h
index 066d19d..6cd9150 100644
--- a/gcc/pretty-print.h
+++ b/gcc/pretty-print.h
@@ -196,7 +196,7 @@ class format_postprocessor
{
public:
virtual ~format_postprocessor () {}
- virtual format_postprocessor *clone() const = 0;
+ virtual std::unique_ptr<format_postprocessor> clone() const = 0;
virtual void handle (pretty_printer *) = 0;
};
@@ -229,7 +229,7 @@ inline int & pp_indentation (pretty_printer *pp);
inline bool & pp_translate_identifiers (pretty_printer *pp);
inline bool & pp_show_color (pretty_printer *pp);
inline printer_fn &pp_format_decoder (pretty_printer *pp);
-inline format_postprocessor *& pp_format_postprocessor (pretty_printer *pp);
+inline format_postprocessor *pp_format_postprocessor (pretty_printer *pp);
inline bool & pp_show_highlight_colors (pretty_printer *pp);
class urlifier;
@@ -256,7 +256,7 @@ public:
friend bool & pp_translate_identifiers (pretty_printer *pp);
friend bool & pp_show_color (pretty_printer *pp);
friend printer_fn &pp_format_decoder (pretty_printer *pp);
- friend format_postprocessor *& pp_format_postprocessor (pretty_printer *pp);
+ friend format_postprocessor * pp_format_postprocessor (pretty_printer *pp);
friend bool & pp_show_highlight_colors (pretty_printer *pp);
friend void pp_output_formatted_text (pretty_printer *,
@@ -316,6 +316,11 @@ public:
void set_real_maximum_length ();
int remaining_character_count_for_line ();
+ void set_format_postprocessor (std::unique_ptr<format_postprocessor> p)
+ {
+ m_format_postprocessor = std::move (p);
+ }
+
void dump (FILE *out, int indent) const;
void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
@@ -356,7 +361,7 @@ private:
have been processed, to allow for client-specific postprocessing.
This is used by the C++ frontend for handling the %H and %I
format codes (which interract with each other). */
- format_postprocessor *m_format_postprocessor;
+ std::unique_ptr<format_postprocessor> m_format_postprocessor;
/* This is used by pp_output_formatted_text after it has converted all
formatted chunks into a single list of tokens.
@@ -443,10 +448,10 @@ pp_format_decoder (pretty_printer *pp)
return pp->m_format_decoder;
}
-inline format_postprocessor *&
+inline format_postprocessor *
pp_format_postprocessor (pretty_printer *pp)
{
- return pp->m_format_postprocessor;
+ return pp->m_format_postprocessor.get ();
}
inline bool &
diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc
index eb579ad..f7aa6a6 100644
--- a/gcc/rtl-ssa/changes.cc
+++ b/gcc/rtl-ssa/changes.cc
@@ -1106,6 +1106,24 @@ recog_level2 (insn_change &change, add_regno_clobber_fn add_regno_clobber)
}
}
+ // Per rtl.texi, registers that are modified using RTX_AUTOINC operations
+ // cannot also appear outside an address.
+ vec_rtx_properties properties;
+ properties.add_pattern (pat);
+ for (rtx_obj_reference def : properties.refs ())
+ if (def.is_pre_post_modify ())
+ for (rtx_obj_reference use : properties.refs ())
+ if (def.regno == use.regno && !use.in_address ())
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "register %d is both auto-modified"
+ " and used outside an address:\n", def.regno);
+ print_rtl_single (dump_file, pat);
+ }
+ return false;
+ }
+
// check_asm_operands checks the constraints after RA, so we don't
// need to do it again.
if (reload_completed && !asm_p)
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 86a5e47..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
@@ -2235,7 +2220,7 @@ rtx_properties::try_to_add_src (const_rtx x, unsigned int flags)
{
has_pre_post_modify = true;
- unsigned int addr_flags = (base_flags
+ unsigned int addr_flags = (flags
| rtx_obj_flags::IS_PRE_POST_MODIFY
| rtx_obj_flags::IS_READ);
try_to_add_dest (XEXP (x, 0), addr_flags);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9b97c4a..ff68455 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,358 @@
+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.
+
+2025-05-29 Jason Merrill <jason@redhat.com>
+
+ PR c++/113563
+ * g++.dg/cpp23/explicit-obj-lambda16.C: New test.
+
+2025-05-29 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/109283
+ * g++.dg/coroutines/pr109283.C: New test.
+
+2025-05-29 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp1z/constexpr-lambda29.C: New test.
+
+2025-05-29 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR fortran/120049
+ * gfortran.dg/c_f_pointer_tests_6.f90: Adjust dg-error
+ directive.
+
+2025-05-29 Alice Carlotti <alice.carlotti@arm.com>
+ Alfie Richards <alfie.richards@arm.com>
+
+ * g++.target/i386/mv-symbols1.C: New test.
+ * g++.target/i386/mv-symbols2.C: New test.
+ * g++.target/i386/mv-symbols3.C: New test.
+ * g++.target/i386/mv-symbols4.C: New test.
+ * g++.target/i386/mv-symbols5.C: New test.
+ * g++.target/i386/mvc-symbols1.C: New test.
+ * g++.target/i386/mvc-symbols2.C: New test.
+ * g++.target/i386/mvc-symbols3.C: New test.
+ * g++.target/i386/mvc-symbols4.C: New test.
+
+2025-05-29 Alice Carlotti <alice.carlotti@arm.com>
+ Alfie Richards <alfie.richards@arm.com>
+
+ * g++.target/powerpc/mvc-symbols1.C: New test.
+ * g++.target/powerpc/mvc-symbols2.C: New test.
+ * g++.target/powerpc/mvc-symbols3.C: New test.
+ * g++.target/powerpc/mvc-symbols4.C: New test.
+
+2025-05-29 Sandra Loosemore <sloosemore@baylibre.com>
+
+ * c-c++-common/gomp/declare-variant-2.c: Adjust patterns now that
+ C and C++ now behave similarly.
+ * c-c++-common/gomp/metadirective-error-recovery.c: New.
+
+2025-05-29 Sandra Loosemore <sloosemore@baylibre.com>
+
+ PR c/120180
+ * c-c++-common/gomp/pr120180.c: New.
+
+2025-05-29 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/120453
+ * g++.dg/coroutines/pr120453.C: New test.
+
+2025-05-29 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/120295
+ * gcc.dg/ipa/pr120295.c: New test.
+
+2025-05-29 Pranav Gorantla <Pranav.Gorantla@amd.com>
+
+ * gcc.target/i386/reduc-pshuf.c: New test.
+
+2025-05-29 Jerry Zhang Jian <jerry.zhangjian@sifive.com>
+
+ * gcc.target/riscv/arch-57.c: New test
+ * gcc.target/riscv/arch-58.c: New test
+
+2025-05-29 Pan Li <pan2.li@intel.com>
+
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c: Add asm
+ check for vmul.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-05-29 Pan Li <pan2.li@intel.com>
+
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c: Add asm check
+ for vmul.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 vmul run test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_vmul-run-1-i16.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_vmul-run-1-i32.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_vmul-run-1-i64.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_vmul-run-1-i8.c: New test.
+
+2025-05-29 Jason Merrill <jason@redhat.com>
+
+ PR c++/107600
+ * g++.dg/ext/is_destructible1.C: New test.
+
2025-05-28 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/119586
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-10.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-10.c
new file mode 100644
index 0000000..4020c4b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-10.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-gimple" } */
+
+struct S {
+ int x,y;
+};
+
+#pragma omp declare mapper(default : struct S var) map(mapper(default), tofrom: var)
+#pragma omp declare mapper(only_x : struct S var) map(mapper(default), tofrom: var.x)
+
+void f(){
+ struct S z = {1,2};
+#pragma omp target defaultmap(alloc)
+ z.x += 5;
+#pragma omp target map(z)
+ z.x += 7;
+#pragma omp target map(mapper(default), tofrom: z)
+ z.x += 8;
+#pragma omp target map(mapper(only_x), tofrom: z)
+ z.x += 9;
+if (z.x != 1+5+7+8+9) __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(-2\\) thread_limit\\(0\\) defaultmap\\(alloc\\) map\\(tofrom:z \\\[len: 8\\\]\\)" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(-2\\) thread_limit\\(0\\) map\\(tofrom:z \\\[len: 8\\\]\\)" 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "#pragma omp target num_teams\\(-2\\) thread_limit\\(0\\) map\\(struct:z \\\[len: 1\\\]\\) map\\(tofrom:z.x \\\[len: 4\\\]\\)" 1 "gimple" } } */
+
+int main() {
+ f();
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-11.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-11.c
new file mode 100644
index 0000000..1f65bad
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-11.c
@@ -0,0 +1,70 @@
+#pragma omp declare mapper (int v)
+// { dg-error "missing 'map' clause before end of line" "" { target c++ } .-1 }
+// { dg-error "'int' is not a struct or union type in '#pragma omp declare mapper'" "" { target c } .-2 }
+
+#pragma omp declare mapper (float v) map()
+// { dg-error "expected primary-expression before '\\)' token" "" { target c++ } .-1 }
+// { dg-error "'float' is not a struct, union or class type in '#pragma omp declare mapper'" "" { target c++ } .-2 }
+// { dg-error "'float' is not a struct or union type in '#pragma omp declare mapper'" "" { target c } .-3 }
+
+#pragma omp declare mapper (char v) map(v)
+// { dg-error "'char' is not a struct, union or class type in '#pragma omp declare mapper'" "" { target c++ } .-1 }
+// { dg-error "'char' is not a struct or union type in '#pragma omp declare mapper'" "" { target c } .-2 }
+
+struct XT {
+ int x;
+};
+#pragma omp declare mapper (XT y) map()
+// { dg-error "expected primary-expression before '\\)' token" "" { target c++ } .-1 }
+// { dg-error "unknown type name 'XT'" "" { target c } .-2 }
+// { dg-error "expected end of line before 'y'" "" { target c } .-3 }
+#pragma omp declare mapper ( bar : struct XT y) map()
+// { dg-error "expected primary-expression before '\\)' token" "" { target c++ } .-1 }
+// { dg-error "expected expression before '\\)' token" "" { target c } .-2 }
+
+struct t {
+ int x;
+};
+
+typedef struct t myStruct;
+
+#pragma omp declare mapper(t)
+// { dg-error "expected unqualified-id before '\\)' token" "" { target c++ } .-1 }
+// { dg-error "unknown type name 't'" "" { target c } .-2 }
+// { dg-error "expected end of line before '\\)' token" "" { target c } .-3 }
+#pragma omp declare mapper(struct t)
+// { dg-error "expected unqualified-id before '\\)' token" "" { target c++ } .-1 }
+// { dg-error "expected identifier" "" { target c } .-2 }
+// { dg-error "expected end of line before '\\)' token" "" { target c } .-3 }
+#pragma omp declare mapper(myStruct)
+// { dg-error "expected unqualified-id before '\\)' token" "" { target c++ } .-1 }
+// { dg-error "expected identifier" "" { target c } .-2 }
+// { dg-error "expected end of line before '\\)' token" "" { target c } .-3 }
+
+#pragma omp declare mapper(name : t v) map()
+// { dg-error "expected primary-expression before '\\)' token" "" { target c++ } .-1 }
+// { dg-error "unknown type name 't'" "" { target c } .-2 }
+// { dg-error "expected end of line before 'v'" "" { target c } .-3 }
+
+#pragma omp declare mapper(fancy : struct t v) map(always,present,close,mapper(d),tofrom: v) // { dg-error "in 'declare mapper' directives, parameter to 'mapper' modifier must be 'default'" }
+
+#pragma omp declare mapper(myStruct v) map(v, v.x)
+// { dg-note "'#pragma omp declare mapper \\(myStruct\\)' previously declared here" "" { target c++ } .-1 }
+// { dg-note "'#pragma omp declare mapper' previously declared here" "" { target c } .-2 }
+#pragma omp declare mapper(default : struct t v) map(v, v.x)
+// { dg-error "redefinition of '#pragma omp declare mapper \\(t\\)'" "" { target c++ } .-1 }
+// { dg-error "redeclaration of '<default>' '#pragma omp declare mapper' for type 'struct t'" "" { target c } .-2 }
+
+union u_t { };
+union u_q { };
+
+#pragma omp declare mapper(union u_t v) map()
+// { dg-error "expected primary-expression before '\\)' token" "" { target c++ } .-1 }
+// { dg-error "expected expression before '\\)' token" "" { target c } .-2 }
+
+#pragma omp declare mapper( one : union u_t v) map(v)
+// { dg-note "'#pragma omp declare mapper \\(one: u_t\\)' previously declared here" "" { target c++ } .-1 }
+// { dg-note "'#pragma omp declare mapper' previously declared here" "" { target c } .-2 }
+#pragma omp declare mapper( one : union u_t u) map( u )
+// { dg-error "redefinition of '#pragma omp declare mapper \\(one: u_t\\)'" "" { target c++ } .-1 }
+// { dg-error "redeclaration of 'one' '#pragma omp declare mapper' for type 'union u_t'" "" { target c } .-2 }
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-12.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-12.c
new file mode 100644
index 0000000..dffb19d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-12.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+
+struct XYZ {
+ int a;
+ int *b;
+ int c;
+};
+
+#pragma omp declare mapper(struct XYZ t)
+/* { dg-error "missing 'map' clause" "" { target c } .-1 } */
+/* { dg-error "missing 'map' clause before end of line" "" { target c++ } .-2 } */
+
+struct ABC {
+ int *a;
+ int b;
+ int c;
+};
+
+#pragma omp declare mapper(struct ABC d) firstprivate(d.b)
+/* { dg-error "unexpected clause" "" { target c } .-1 } */
+/* { dg-error "expected end of line before '\\(' token" "" { target c } .-2 } */
+/* { dg-error "unexpected clause before '\\(' token" "" { target c++ } .-3 } */
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-3.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-3.c
new file mode 100644
index 0000000..e491bcd
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-3.c
@@ -0,0 +1,30 @@
+// { dg-do compile }
+// { dg-additional-options "-fdump-tree-gimple" }
+
+#include <stdlib.h>
+
+// Test named mapper invocation.
+
+struct S {
+ int *ptr;
+ int size;
+};
+
+int main (int argc, char *argv[])
+{
+ int N = 1024;
+#pragma omp declare mapper (mapN:struct S s) map(to:s.ptr, s.size) \
+ map(s.ptr[:N])
+
+ struct S s;
+ s.ptr = (int *) malloc (sizeof (int) * N);
+
+#pragma omp target map(mapper(mapN), tofrom: s)
+// { dg-final { scan-tree-dump {map\(struct:s \[len: 2\]\) map\(alloc:s\.ptr \[len: [0-9]+\]\) map\(to:s\.size \[len: [0-9]+\]\) map\(tofrom:\*_[0-9]+ \[len: _[0-9]+\]\) map\(attach:s\.ptr \[bias: 0\]\)} "gimple" } }
+ {
+ for (int i = 0; i < N; i++)
+ s.ptr[i]++;
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-4.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-4.c
new file mode 100644
index 0000000..39e3ab1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-4.c
@@ -0,0 +1,78 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-original" } */
+
+/* Check mapper binding clauses. */
+
+struct Y {
+ int z;
+};
+
+struct Z {
+ int z;
+};
+
+#pragma omp declare mapper (struct Y y) map(tofrom: y)
+#pragma omp declare mapper (struct Z z) map(tofrom: z)
+
+int foo (void)
+{
+ struct Y yy;
+ struct Z zz;
+ int dummy;
+
+#pragma omp target data map(dummy)
+ {
+ #pragma omp target
+ {
+ yy.z++;
+ zz.z++;
+ }
+ yy.z++;
+ }
+ return yy.z;
+}
+
+struct P
+{
+ struct Z *zp;
+};
+
+int bar (void)
+{
+ struct Y yy;
+ struct Z zz;
+ struct P pp;
+ struct Z t;
+ int dummy;
+
+ pp.zp = &t;
+
+#pragma omp declare mapper (struct Y y) map(tofrom: y.z)
+#pragma omp declare mapper (struct Z z) map(tofrom: z.z)
+
+#pragma omp target data map(dummy)
+ {
+ #pragma omp target
+ {
+ yy.z++;
+ zz.z++;
+ }
+ yy.z++;
+ }
+
+ #pragma omp declare mapper(struct P x) map(to:x.zp) map(tofrom:*x.zp)
+
+ #pragma omp target
+ {
+ zz = *pp.zp;
+ }
+
+ return zz.z;
+}
+
+/* { dg-final { scan-tree-dump-times {mapper_binding\(struct Y,omp declare mapper ~1Y\) mapper_binding\(struct Z,omp declare mapper ~1Z\)} 2 "original" { target c++ } } } */
+/* { dg-final { scan-tree-dump {mapper_binding\(struct Z,omp declare mapper ~1Z\) mapper_binding\(struct P,omp declare mapper ~1P\)} "original" { target c++ } } } */
+
+/* { dg-final { scan-tree-dump {mapper_binding\(struct Z,#pragma omp declare mapper \(struct Z z\) map\(tofrom:z\)\) mapper_binding\(struct Y,#pragma omp declare mapper \(struct Y y\) map\(tofrom:y\)\)} "original" { target c } } } */
+/* { dg-final { scan-tree-dump {mapper_binding\(struct Z,#pragma omp declare mapper \(struct Z z\) map\(tofrom:z\.z\)\) mapper_binding\(struct Y,#pragma omp declare mapper \(struct Y y\) map\(tofrom:y\.z\)\)} "original" { target c } } } */
+/* { dg-final { scan-tree-dump {mapper_binding\(struct P,#pragma omp declare mapper \(struct P x\) map\(tofrom:\(x\.zp\)\[0:1\]\) map\(to:x.zp\)\) mapper_binding\(struct Z,#pragma omp declare mapper \(struct Z z\) map\(tofrom:z\.z\)\)} "original" { target c } } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-5.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-5.c
new file mode 100644
index 0000000..e8ab159
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-5.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+
+typedef struct S_ {
+ int *myarr;
+ int size;
+} S;
+
+#pragma omp declare mapper (named: struct S_ v) map(to:v.size, v.myarr) \
+ map(tofrom: v.myarr[0:v.size])
+/* { dg-note "'#pragma omp declare mapper' previously declared here" "" { target c } .-2 } */
+/* { dg-note "'#pragma omp declare mapper \\(named: S_\\)' previously defined here" "" { target c++ } .-3 } */
+
+#pragma omp declare mapper (named: S v) map(to:v.size, v.myarr) \
+ map(tofrom: v.myarr[0:v.size])
+/* { dg-error "redeclaration of 'named' '#pragma omp declare mapper' for type 'S' \\\{aka 'struct S_'\\\}" "" { target c } .-2 } */
+/* { dg-error "redefinition of '#pragma omp declare mapper \\(named: S\\)'" "" { target c++ } .-3 } */
+
+#pragma omp declare mapper (struct S_ v) map(to:v.size, v.myarr) \
+ map(tofrom: v.myarr[0:v.size])
+/* { dg-note "'#pragma omp declare mapper' previously declared here" "" { target c } .-2 } */
+/* { dg-note "'#pragma omp declare mapper \\(S_\\)' previously defined here" "" { target c++ } .-3 } */
+
+#pragma omp declare mapper (S v) map(to:v.size, v.myarr) \
+ map(tofrom: v.myarr[0:v.size])
+/* { dg-error "redeclaration of '<default>' '#pragma omp declare mapper' for type 'S' \\\{aka 'struct S_'\\\}" "" { target c } .-2 } */
+/* { dg-error "redefinition of '#pragma omp declare mapper \\(S\\)'" "" { target c++ } .-3 } */
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-6.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-6.c
new file mode 100644
index 0000000..c13eb8b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-6.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+
+int x = 5;
+
+struct Q {
+ int *arr1;
+ int *arr2;
+ int *arr3;
+};
+
+#pragma omp declare mapper (struct Q myq) map(myq.arr2[0:x])
+
+struct R {
+ int *arr1;
+ int *arr2;
+ int *arr3;
+};
+
+#pragma omp declare mapper (struct R myr) map(myr.arr3[0:y])
+/* { dg-error "'y' undeclared" "" { target c } .-1 } */
+/* { dg-error "'y' was not declared in this scope" "" { target c++ } .-2 } */
+
+int y = 7;
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-7.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-7.c
new file mode 100644
index 0000000..0f8dd25
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-7.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+
+struct Q {
+ int *arr1;
+ int *arr2;
+ int *arr3;
+};
+
+int foo (void)
+{
+ int x = 5;
+ #pragma omp declare mapper (struct Q myq) map(myq.arr2[0:x])
+ return x;
+}
+
+struct R {
+ int *arr1;
+ int *arr2;
+ int *arr3;
+};
+
+int bar (void)
+{
+ #pragma omp declare mapper (struct R myr) map(myr.arr3[0:y])
+ /* { dg-error "'y' undeclared" "" { target c } .-1 } */
+ /* { dg-error "'y' was not declared in this scope" "" { target c++ } .-2 } */
+ int y = 7;
+ return y;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-8.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-8.c
new file mode 100644
index 0000000..dadca28
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-8.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+
+struct Q {
+ int *arr1;
+ int *arr2;
+ int *arr3;
+ int len;
+};
+
+struct R {
+ struct Q qarr[5];
+};
+
+struct R2 {
+ struct Q *qptr;
+};
+
+#pragma omp declare mapper (struct Q myq) map(myq.arr1[0:myq.len]) \
+ map(myq.arr2[0:myq.len]) \
+ map(myq.arr3[0:myq.len])
+
+#pragma omp declare mapper (struct R myr) map(myr.qarr[2:3])
+
+#pragma omp declare mapper (struct R2 myr2) map(myr2.qptr[2:3])
+
+int main (int argc, char *argv[])
+{
+ struct R r;
+ struct R2 r2;
+ int N = 256;
+
+#pragma omp target
+/* { dg-message "sorry, unimplemented: user-defined mapper with non-unit length array section" "" { target *-*-* } .-1 } */
+ {
+ for (int i = 2; i < 5; i++)
+ for (int j = 0; j < N; j++)
+ {
+ r.qarr[i].arr1[j]++;
+ r2.qptr[i].arr2[j]++;
+ }
+ }
+}
+
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-mapper-9.c b/gcc/testsuite/c-c++-common/gomp/declare-mapper-9.c
new file mode 100644
index 0000000..709bc0c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-mapper-9.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+
+int x = 5;
+
+struct Q {
+ int *arr1;
+ int *arr2;
+ int *arr3;
+};
+
+int y = 5;
+
+#pragma omp declare mapper (struct Q myq) map(myq.arr2[0:x])
+/* { dg-note "'#pragma omp declare mapper' previously declared here" "" { target c } .-1 } */
+/* { dg-note "'#pragma omp declare mapper \\(Q\\)' previously defined here" "" { target c++ } .-2 } */
+
+#pragma omp declare mapper (struct Q myq) map(myq.arr2[0:y])
+/* { dg-error "redeclaration of '<default>' '#pragma omp declare mapper' for type 'struct Q'" "" { target c } .-1 } */
+/* { dg-error "redefinition of '#pragma omp declare mapper \\(Q\\)'" "" { target c++ } .-2 } */
+
+struct R {
+ int *arr1;
+};
+
+void foo (void)
+{
+#pragma omp declare mapper (struct R myr) map(myr.arr1[0:x])
+/* { dg-note "'#pragma omp declare mapper' previously declared here" "" { target c } .-1 } */
+/* { dg-note "'#pragma omp declare mapper \\(R\\)' previously declared here" "" { target c++ } .-2 } */
+
+#pragma omp declare mapper (struct R myr) map(myr.arr1[0:y])
+/* { dg-error "redeclaration of '<default>' '#pragma omp declare mapper' for type 'struct R'" "" { target c } .-1 } */
+/* { dg-error "redeclaration of '#pragma omp declare mapper \\(R\\)'" "" { target c++ } .-2 } */
+}
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 7711dbc..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);
@@ -47,10 +47,9 @@ void f23 (void);
#pragma omp declare variant (f1) match(construct={teams,parallel,master,for}) /* { dg-warning "unknown selector 'master' for context selector set 'construct'" } */
void f24 (void);
#pragma omp declare variant (f1) match(construct={parallel(1 /* { dg-error "selector 'parallel' does not accept any properties" } */
-void f25 (void); /* { dg-error "expected '\\\}' before end of line" "" { target c++ } .-1 } */
- /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-2 } */
+void f25 (void); /* { dg-error "expected '\\\}' before end of line" "" { target *-*-* } .-1 } */
#pragma omp declare variant (f1) match(construct={parallel(1)}) /* { dg-error "selector 'parallel' does not accept any properties" } */
-void f26 (void); /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-1 } */
+void f26 (void);
#pragma omp declare variant (f0) match(construct={simd(12)}) /* { dg-error "expected \[^\n\r]* clause before" } */
void f27 (void); /* { dg-error "'\\)' before numeric constant" "" { target c++ } .-1 } */
#pragma omp declare variant (f1) match(construct={parallel},construct={for}) /* { dg-error "selector set 'construct' specified more than once" } */
@@ -96,13 +95,13 @@ void f46 (void);
#pragma omp declare variant (f1) match(implementation={vendor("foobar")}) /* { dg-warning "unknown property '.foobar.' of 'vendor' selector" } */
void f47 (void);
#pragma omp declare variant (f1) match(implementation={unified_address(yes)}) /* { dg-error "selector 'unified_address' does not accept any properties" } */
-void f48 (void); /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-1 } */
+void f48 (void);
#pragma omp declare variant (f1) match(implementation={unified_shared_memory(no)}) /* { dg-error "selector 'unified_shared_memory' does not accept any properties" } */
-void f49 (void); /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-1 } */
+void f49 (void);
#pragma omp declare variant (f1) match(implementation={dynamic_allocators(42)}) /* { dg-error "selector 'dynamic_allocators' does not accept any properties" } */
-void f50 (void); /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-1 } */
+void f50 (void);
#pragma omp declare variant (f1) match(implementation={reverse_offload()}) /* { dg-error "selector 'reverse_offload' does not accept any properties" } */
-void f51 (void); /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-1 } */
+void f51 (void);
#pragma omp declare variant (f1) match(implementation={atomic_default_mem_order}) /* { dg-error "expected '\\(' before '\\\}' token" } */
void f52 (void);
#pragma omp declare variant (f1) match(implementation={atomic_default_mem_order(acquire)})
diff --git a/gcc/testsuite/c-c++-common/gomp/map-6.c b/gcc/testsuite/c-c++-common/gomp/map-6.c
index 014ed35..852839e 100644
--- a/gcc/testsuite/c-c++-common/gomp/map-6.c
+++ b/gcc/testsuite/c-c++-common/gomp/map-6.c
@@ -13,20 +13,20 @@ foo (void)
#pragma omp target map (to:a)
;
- #pragma omp target map (a to: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close' or 'present'" } */
- ;
+ #pragma omp target map (a to: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present'" "" { target c++ } } */
+ ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
- #pragma omp target map (close, a to: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close' or 'present'" } */
- ;
+ #pragma omp target map (close, a to: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present'" "" { target c++ } } */
+ ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
- #pragma omp target enter data map(b7) map (close, a to: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close' or 'present'" } */
- ;
+ #pragma omp target enter data map(b7) map (close, a to: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present'" "" { target c++ } } */
+ ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
- #pragma omp target exit data map(b7) map (close, a from: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close' or 'present'" } */
- ;
+ #pragma omp target exit data map(b7) map (close, a from: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present'" "" { target c++ } } */
+ ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
- #pragma omp target data map(b7) map (close, a from: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close' or 'present'" } */
- ;
+ #pragma omp target data map(b7) map (close, a from: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present'" "" { target c++ } } */
+ ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
#pragma omp target map (close a) /* { dg-error "'close' undeclared" "" { target c } } */
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
new file mode 100644
index 0000000..92995a2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/metadirective-error-recovery.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+
+/* This test used to ICE in C and only diagnose the first error in C++. */
+
+struct s {
+ int a, b;
+};
+
+void f (int aa, int bb)
+{
+ struct s s1, s2;
+ s1.a = aa;
+ s1.b = bb;
+ s2.a = aa + 1;
+ 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 "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/c-c++-common/gomp/pr120180.c b/gcc/testsuite/c-c++-common/gomp/pr120180.c
new file mode 100644
index 0000000..cb5a0d5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr120180.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+
+/* This test used to ICE after erroring on the metadirective in the
+ loop nest. */
+
+int main()
+{
+ int blksize = 15000;
+ double *qq;
+ int i, k, nq;
+
+ #pragma omp metadirective when(user={condition(0)}: target teams distribute parallel for collapse(2) map(qq[:0]) private(i)) \
+ when(user={condition(0)}: target teams distribute parallel for map(qq[:0]) private(i)) \
+ when(user={condition(1)}: target teams loop collapse(2) map(qq[:0]) private(i))
+ for(k=0; k<blksize; k++)
+ {
+#pragma omp metadirective when(user={condition(0)}: simd) default() // { dg-error "intervening code must not contain OpenMP directives" }
+ for (i=0; i<nq; i++)
+ qq[k*nq + i] = 0.0;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr109283.C b/gcc/testsuite/g++.dg/coroutines/pr109283.C
new file mode 100644
index 0000000..d73092b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr109283.C
@@ -0,0 +1,23 @@
+// PR 109283.
+// This used to ICE from a check set too widely.
+#include <coroutine>
+
+struct foo
+{ ~foo(); };
+
+struct task
+{
+ struct promise_type
+ {
+ std::suspend_never initial_suspend();
+ std::suspend_never final_suspend() noexcept;
+ std::suspend_never yield_value(foo);
+ void return_void();
+ void unhandled_exception();
+ task get_return_object();
+ };
+};
+
+task source(int b) {
+ co_yield b ? foo{} : foo{};
+}
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/coroutines/pr120453.C b/gcc/testsuite/g++.dg/coroutines/pr120453.C
new file mode 100644
index 0000000..2f2c4ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr120453.C
@@ -0,0 +1,95 @@
+// PR120453 - reduced testcase amended to add a TaskBase move constructor
+// and a LazyTask destructor, to more closely match the original code.
+// { dg-additional-options "-w" }
+namespace std {
+template <typename> struct __coroutine_traits_impl;
+template <typename _Result>
+ requires requires { typename _Result; }
+struct __coroutine_traits_impl<_Result>;
+template <typename _Result, typename> struct coroutine_traits : _Result {};
+template <typename = void> struct coroutine_handle {
+ static coroutine_handle from_address(void *);
+ operator coroutine_handle<>();
+ void *address();
+};
+struct suspend_never {
+ bool await_ready();
+ void await_suspend(coroutine_handle<>);
+ void await_resume();
+};
+} // namespace std
+
+namespace QCoro {
+namespace detail {
+template <typename T>
+concept has_await_methods = requires(T t) { t; };
+} // namespace detail
+
+template <typename T>
+concept Awaitable = detail::has_await_methods<T>;
+namespace detail {
+struct TaskFinalSuspend {
+ bool await_ready() noexcept;
+ template <typename Promise>
+ void await_suspend(std::coroutine_handle<Promise>) noexcept;
+ void await_resume() noexcept;
+};
+struct TaskPromiseBase {
+ std::suspend_never initial_suspend();
+ auto final_suspend() noexcept { return TaskFinalSuspend{}; }
+ template <Awaitable T> auto &&await_transform(T &&);
+};
+struct TaskPromise : TaskPromiseBase {
+ void unhandled_exception();
+};
+template <typename> struct TaskAwaiterBase {
+ bool await_ready();
+ void await_suspend(std::coroutine_handle<>);
+};
+template <typename, template <typename> class, typename> struct TaskBase {
+ TaskBase() = default;
+ TaskBase(TaskBase &&) = default;
+ void operator=(TaskBase &&);
+ auto operator co_await() const;
+ std::coroutine_handle<> mCoroutine;
+};
+} // namespace detail
+template <typename> struct Task : detail::TaskBase<int, Task, int> {};
+} // namespace QCoro
+
+namespace QCoro::detail {
+template <Awaitable T> auto &&TaskPromiseBase::await_transform(T &&awaitable) {
+ return awaitable;
+}
+
+template <typename T, template <typename> class TaskImpl, typename PromiseType>
+auto TaskBase<T, TaskImpl, PromiseType>::operator co_await() const {
+ class TaskAwaiter : public TaskAwaiterBase<PromiseType> {
+ public:
+ TaskAwaiter(std::coroutine_handle<>);
+ auto await_resume() {}
+ };
+ return TaskAwaiter{mCoroutine};
+}
+
+} // namespace QCoro::detail
+
+namespace QCoro {
+template <typename T> class LazyTask ;
+namespace detail {
+struct LazyTaskPromise : TaskPromise {
+ LazyTask<int> get_return_object();
+};
+} // namespace detail
+
+template <typename T> struct LazyTask : detail::TaskBase<int, LazyTask, int> {
+ typedef detail::LazyTaskPromise promise_type;
+ ~LazyTask();
+};
+
+auto coro = [] -> LazyTask<int>
+{
+ co_await [] -> Task<int> { return {}; }();
+};
+
+} // namespace QCoro
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda29.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda29.C
new file mode 100644
index 0000000..9e661b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda29.C
@@ -0,0 +1,19 @@
+// Test that we don't make lambdas with goto/static implicitly constexpr
+// when an explicitly constexpr function would be ill-formed.
+
+// { dg-do compile { target c++17 } }
+
+int main()
+{
+ constexpr int a = [] {
+ return 42;
+ goto label;
+ label:
+ return 142;
+ }(); // { dg-error "" "" { target c++20_down } }
+
+ constexpr int b = [] {
+ return 42;
+ static int i;
+ }(); // { dg-error "" "" { target c++20_down } }
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda16.C b/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda16.C
new file mode 100644
index 0000000..6993638
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda16.C
@@ -0,0 +1,39 @@
+// PR c++/113563
+// { dg-do compile { target c++23 } }
+
+struct S {
+ int x_;
+ void f() {
+ [this](this auto) {
+ this->x_ = 42;
+ return this;
+ }();
+ }
+};
+
+struct R {
+ int x;
+
+ auto foo() {
+ return [*this](this auto &self) {
+ this->x = 4;
+ };
+ }
+};
+
+
+struct A
+{
+ int n;
+ void fun()
+ {
+ auto _ = [&](this auto self) { return n; };
+ }
+};
+
+struct B {
+ int i = 42;
+ int foo() {
+ return [this](this auto &&self) { auto p = &i; return *p; }();
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda17.C b/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda17.C
new file mode 100644
index 0000000..ee95fff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda17.C
@@ -0,0 +1,144 @@
+// PR c++/113563
+// { dg-do run { target c++23 } }
+
+template <typename T>
+T&& move(T& value) { return static_cast<T&&>(value); }
+
+template <typename T, typename U> constexpr bool is_same = false;
+template <typename T> constexpr bool is_same<T, T> = true;
+
+template <typename T> constexpr bool is_const_ref = false;
+template <typename T> constexpr bool is_const_ref<const T> = true;
+template <typename T> constexpr bool is_const_ref<const T&> = true;
+template <typename T> constexpr bool is_const_ref<const T&&> = true;
+
+template <typename T> constexpr int refqual = 0;
+template <typename T> constexpr int refqual<T&> = 1;
+template <typename T> constexpr int refqual<T&&> = 2;
+
+struct S {
+ int x;
+
+ // 'this' properly acts as a pointer
+ auto byref_a() {
+ return [this](this auto) { return this->x; };
+ }
+ auto byref_b() {
+ return [this](this auto) { return x; };
+ }
+ auto byref_c() {
+ return [&](this auto) { return x; };
+ }
+ auto byref_d() {
+ return [=](this auto) { return x; }; // { dg-warning "implicit capture" }
+ }
+ auto byref_e() {
+ return [this](this auto) {
+ return [this](this auto) {
+ return this->x;
+ }();
+ };
+ }
+ auto byref_f() {
+ return [&](this auto) {
+ return [&](this auto) {
+ return x;
+ }();
+ };
+ }
+
+ // capturing '*this' stores a copy
+ auto byval_a() {
+ return [*this](this auto) { return this->x; };
+ }
+ auto byval_b() {
+ return [*this](this auto) { return x; };
+ }
+ auto byval_c() {
+ return [*this](this auto) {
+ return [=](this auto) { // { dg-warning "implicit capture" }
+ return this->x;
+ }();
+ };
+ }
+ auto byval_d() {
+ return [*this](this auto) {
+ return [&](this auto) {
+ return x;
+ }();
+ };
+ }
+
+ // value category doesn't change with self when capture ref
+ auto byref_cat_1() {
+ return [this](this auto&& self) {
+ static_assert(is_same<decltype((x)), int&>);
+ };
+ }
+ auto byref_cat_2() const {
+ return [this](this auto&& self) {
+ static_assert(is_same<decltype((x)), const int&>);
+ };
+ }
+
+ // value category does change with self when capture val
+ auto byval_cat() {
+ return [*this](this auto&& self) {
+ static_assert(is_const_ref<decltype((x))> == is_const_ref<decltype((self))>);
+ static_assert(refqual<decltype((x))> == refqual<decltype((self))>);
+ };
+ }
+};
+
+int main() {
+ S s{ 5 };
+
+ auto ra = s.byref_a();
+ auto rb = s.byref_b();
+ auto rc = s.byref_c();
+ auto rd = s.byref_d();
+ auto re = s.byref_e();
+ auto rf = s.byref_f();
+
+ auto va = s.byval_a();
+ auto vb = s.byval_b();
+ auto vc = s.byval_c();
+ auto vd = s.byval_d();
+
+ s.x = 10;
+
+ if (ra() != 10
+ || rb() != 10
+ || rc() != 10
+ || rd() != 10
+ || re() != 10
+ || rf() != 10)
+ __builtin_abort();
+
+ if (va() != 5
+ || vb() != 5
+ || vc() != 5
+ || vd() != 5)
+ __builtin_abort();
+
+ auto r_nonconst_1 = s.byref_cat_1();
+ const auto r_const_1 = r_nonconst_1;
+ r_nonconst_1();
+ move(r_nonconst_1)();
+ r_const_1();
+ move(r_nonconst_1)();
+
+ auto r_nonconst_2 = s.byref_cat_2();
+ const auto r_const_2 = r_nonconst_2;
+ r_nonconst_2();
+ move(r_nonconst_2)();
+ r_const_2();
+ move(r_nonconst_2)();
+
+ auto v_nonconst = s.byval_cat();
+ const auto v_const = v_nonconst;
+ v_nonconst();
+ move(v_nonconst)();
+ v_const();
+ move(v_nonconst)();
+}
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/diagnostic/bad-binary-ops-highlight-colors.C b/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops-highlight-colors.C
index 1260345..687af32 100644
--- a/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops-highlight-colors.C
+++ b/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops-highlight-colors.C
@@ -23,8 +23,8 @@ int test_4 (void)
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
- return callee_4a () + callee_4b ();
- ~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
+ return callee_4a () + callee_4b ();
+ ~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
| |
S {aka s} T {aka t}
{ dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/g++.dg/diagnostic/long-short-colorization.C b/gcc/testsuite/g++.dg/diagnostic/long-short-colorization.C
index d2111fe..1c29cea 100644
--- a/gcc/testsuite/g++.dg/diagnostic/long-short-colorization.C
+++ b/gcc/testsuite/g++.dg/diagnostic/long-short-colorization.C
@@ -6,14 +6,14 @@
long short int a;
/* { dg-begin-multiline-output "" }
'long' and 'short' specified together
- long short int a;
- ^~~~ ~~~~~
+ long short int a;
+ ^~~~ ~~~~~
{ dg-end-multiline-output "" } */
short long int b;
/* { dg-begin-multiline-output "" }
'long' and 'short' specified together
- short long int b;
- ~~~~~ ^~~~
+ short long int b;
+ ~~~~~ ^~~~
{ dg-end-multiline-output "" } */
// Discard the remaining colorized output that confuses dejagnu.
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/declare-mapper-1.C b/gcc/testsuite/g++.dg/gomp/declare-mapper-1.C
new file mode 100644
index 0000000..3177d20
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/declare-mapper-1.C
@@ -0,0 +1,58 @@
+// { dg-do compile }
+// { dg-additional-options "-fdump-tree-gimple" }
+
+// "omp declare mapper" support -- check expansion in gimple.
+
+struct S {
+ int *ptr;
+ int size;
+};
+
+#define N 64
+
+#pragma omp declare mapper (S w) map(w.size, w.ptr, w.ptr[:w.size])
+#pragma omp declare mapper (foo:S w) map(to:w.size, w.ptr) map(w.ptr[:w.size])
+
+int main (int argc, char *argv[])
+{
+ S s;
+ s.ptr = new int[N];
+ s.size = N;
+
+#pragma omp declare mapper (bar:S w) map(w.size, w.ptr, w.ptr[:w.size])
+
+#pragma omp target
+ {
+ for (int i = 0; i < N; i++)
+ s.ptr[i]++;
+ }
+
+#pragma omp target map(tofrom: s)
+ {
+ for (int i = 0; i < N; i++)
+ s.ptr[i]++;
+ }
+
+#pragma omp target map(mapper(default), tofrom: s)
+ {
+ for (int i = 0; i < N; i++)
+ s.ptr[i]++;
+ }
+
+#pragma omp target map(mapper(foo), alloc: s)
+ {
+ for (int i = 0; i < N; i++)
+ s.ptr[i]++;
+ }
+
+#pragma omp target map(mapper(bar), tofrom: s)
+ {
+ for (int i = 0; i < N; i++)
+ s.ptr[i]++;
+ }
+
+ return 0;
+}
+
+// { dg-final { scan-tree-dump-times {map\(struct:s \[len: 2\]\) map\(alloc:s\.ptr \[len: [0-9]+\]\) map\(tofrom:s\.size \[len: [0-9]+\]\) map\(tofrom:\*_[0-9]+ \[len: _[0-9]+\]\) map\(attach:s\.ptr \[bias: 0\]\)} 4 "gimple" } }
+// { dg-final { scan-tree-dump-times {map\(struct:s \[len: 2\]\) map\(alloc:s\.ptr \[len: [0-9]+\]\) map\(to:s\.size \[len: [0-9]+\]\) map\(alloc:\*_[0-9]+ \[len: _[0-9]+\]\) map\(attach:s\.ptr \[bias: 0\]\)} 1 "gimple" } }
diff --git a/gcc/testsuite/g++.dg/gomp/declare-mapper-2.C b/gcc/testsuite/g++.dg/gomp/declare-mapper-2.C
new file mode 100644
index 0000000..7df72c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/declare-mapper-2.C
@@ -0,0 +1,30 @@
+// { dg-do compile }
+
+// Error-checking tests for "omp declare mapper".
+
+struct S {
+ int *ptr;
+ int size;
+};
+
+struct Z {
+ int z;
+};
+
+int main (int argc, char *argv[])
+{
+#pragma omp declare mapper (S v) map(v.size, v.ptr[:v.size]) // { dg-note "'#pragma omp declare mapper \\(S\\)' previously declared here" }
+
+ /* This one's a duplicate. */
+#pragma omp declare mapper (default: S v) map (to: v.size) map (v) // { dg-error "redeclaration of '#pragma omp declare mapper \\(S\\)'" }
+
+ /* ...and this one doesn't use a "base language identifier" for the mapper
+ name. */
+#pragma omp declare mapper (case: S v) map (to: v.size) // { dg-error "expected identifier or 'default' before 'case'" }
+ // { dg-error "expected ':' before 'case'" "" { target *-*-* } .-1 }
+
+ /* A non-struct/class/union type isn't supposed to work. */
+#pragma omp declare mapper (name:Z [5]foo) map (foo[0].z) // { dg-error "'Z \\\[5\\\]' is not a struct, union or class type in '#pragma omp declare mapper'" }
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/declare-mapper-3.C b/gcc/testsuite/g++.dg/gomp/declare-mapper-3.C
new file mode 100644
index 0000000..1f019c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/declare-mapper-3.C
@@ -0,0 +1,39 @@
+#pragma omp declare mapper (int v) // { dg-error "missing 'map' clause before end of line" }
+#pragma omp declare mapper (float v) map() // { dg-error "expected primary-expression before '\\)' token" }
+// { dg-error "'float' is not a struct, union or class type in '#pragma omp declare mapper'" "" { target *-*-* } .-1 }
+
+#pragma omp declare mapper (char v) map(v) // { dg-error "'char' is not a struct, union or class type in '#pragma omp declare mapper'" }
+
+struct XT {
+ int x;
+};
+#pragma omp declare mapper (XT y) map() // { dg-error "expected primary-expression before '\\)' token" }
+
+struct t {
+ int x;
+};
+
+typedef struct t myStruct;
+
+#pragma omp declare mapper(t) // { dg-error "expected unqualified-id before '\\)' token" }
+#pragma omp declare mapper(struct t) // { dg-error "expected unqualified-id before '\\)' token" }
+#pragma omp declare mapper(myStruct) // { dg-error "expected unqualified-id before '\\)' token" }
+
+#pragma omp declare mapper(name : t v) map() // { dg-error "expected primary-expression before '\\)' token" }
+
+#pragma omp declare mapper(fancy : struct t v) map(always,present,close,mapper(d),tofrom: v) // { dg-error "in 'declare mapper' directives, parameter to 'mapper' modifier must be 'default'" }
+
+#pragma omp declare mapper(myStruct v) map(v, v.x) // { dg-note "'#pragma omp declare mapper \\(myStruct\\)' previously declared here" }
+#pragma omp declare mapper(default : t v) map(v, v.x) // { dg-error "redefinition of '#pragma omp declare mapper \\(t\\)'" }
+
+
+class A { };
+class B : public virtual A { };
+
+#pragma omp declare mapper(class B ci) map(ci) // { dg-error "'B' must not be a virtual base class in '#pragma omp declare mapper'" }
+
+#pragma omp declare mapper(T v) mapper(v) // { dg-error "'T' does not name a type" }
+
+union u_t { };
+
+#pragma omp declare mapper(u_t v) map() // { dg-error "expected primary-expression before '\\)' token" }
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/plugin/show-template-tree-color-labels.C b/gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C
index 75488cb..3e93126 100644
--- a/gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C
+++ b/gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C
@@ -16,8 +16,8 @@ void test_1 (vector<double> vec)
fn_1 (vec);
/* { dg-begin-multiline-output "" }
could not convert 'vec' from 'vector<double>' to 'vector<int>'
- fn_1 (vec);
- ^~~
+ fn_1 (vec);
+ ^~~
|
vector<double>
{ dg-end-multiline-output "" } */
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/mv-symbols1.C b/gcc/testsuite/g++.target/i386/mv-symbols1.C
new file mode 100644
index 0000000..1290299
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/mv-symbols1.C
@@ -0,0 +1,68 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target("default")))
+int foo ()
+{
+ return 1;
+}
+
+__attribute__((target("arch=slm")))
+int foo ()
+{
+ return 3;
+}
+
+__attribute__((target("sse4.2")))
+int foo ()
+{
+ return 5;
+}
+
+__attribute__((target("sse4.2")))
+int foo (int)
+{
+ return 6;
+}
+
+__attribute__((target("arch=slm")))
+int foo (int)
+{
+ return 4;
+}
+
+__attribute__((target("default")))
+int foo (int)
+{
+ return 2;
+}
+
+int bar()
+{
+ return foo ();
+}
+
+int bar(int x)
+{
+ return foo (x);
+}
+
+/* When updating any of the symbol names in these tests, make sure to also
+ update any tests for their absence in mvc-symbolsN.C */
+
+/* { dg-final { scan-assembler-times "\n_Z3foov:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.arch_slm:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.sse4.2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tcall\t_Z7_Z3foovv\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z7_Z3foovv, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z7_Z3foovv,_Z3foov\.resolver\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n_Z3fooi:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch_slm:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.sse4.2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tcall\t_Z7_Z3fooii\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z7_Z3fooii, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z7_Z3fooii,_Z3fooi\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/g++.target/i386/mv-symbols2.C b/gcc/testsuite/g++.target/i386/mv-symbols2.C
new file mode 100644
index 0000000..8b75565
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/mv-symbols2.C
@@ -0,0 +1,56 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target("default")))
+int foo ()
+{
+ return 1;
+}
+
+__attribute__((target("arch=slm")))
+int foo ()
+{
+ return 3;
+}
+
+__attribute__((target("sse4.2")))
+int foo ()
+{
+ return 5;
+}
+
+__attribute__((target("sse4.2")))
+int foo (int)
+{
+ return 6;
+}
+
+__attribute__((target("arch=slm")))
+int foo (int)
+{
+ return 4;
+}
+
+__attribute__((target("default")))
+int foo (int)
+{
+ return 2;
+}
+
+/* When updating any of the symbol names in these tests, make sure to also
+ update any tests for their absence in mvc-symbolsN.C */
+
+/* { dg-final { scan-assembler-times "\n_Z3foov:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.arch_slm:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.sse4.2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z7_Z3foovv, @gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z7_Z3foovv,_Z3foov\.resolver\n" 0 } } */
+
+/* { dg-final { scan-assembler-times "\n_Z3fooi:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch_slm:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.sse4.2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z7_Z3fooii, @gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z7_Z3fooii,_Z3fooi\.resolver\n" 0 } } */
diff --git a/gcc/testsuite/g++.target/i386/mv-symbols3.C b/gcc/testsuite/g++.target/i386/mv-symbols3.C
new file mode 100644
index 0000000..a5cf344
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/mv-symbols3.C
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target("default")))
+int foo ();
+
+__attribute__((target("arch=slm")))
+int foo ();
+
+__attribute__((target("sse4.2")))
+int foo ();
+
+__attribute__((target("sse4.2")))
+int foo (int);
+
+__attribute__((target("arch=slm")))
+int foo (int);
+
+__attribute__((target("default")))
+int foo (int);
+
+int bar()
+{
+ return foo ();
+}
+
+/* When updating any of the symbol names in these tests, make sure to also
+ update any tests for their absence in mvc-symbolsN.C */
+
+/* { dg-final { scan-assembler-times "\n_Z3foov:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.arch_slm:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.sse4.2:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tcall\t_Z7_Z3foovv\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z7_Z3foovv, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z7_Z3foovv,_Z3foov\.resolver\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n_Z3fooi:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch_slm:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.sse4.2:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z7_Z3fooii, @gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z7_Z3fooii,_Z3fooi\.resolver\n" 0 } } */
diff --git a/gcc/testsuite/g++.target/i386/mv-symbols4.C b/gcc/testsuite/g++.target/i386/mv-symbols4.C
new file mode 100644
index 0000000..bb10f12
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/mv-symbols4.C
@@ -0,0 +1,50 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target("default")))
+int foo ()
+{
+ return 1;
+}
+
+__attribute__((target("arch=slm")))
+int foo ();
+
+__attribute__((target("sse4.2")))
+int foo ();
+
+__attribute__((target("sse4.2")))
+int foo (int);
+
+__attribute__((target("arch=slm")))
+int foo (int);
+
+__attribute__((target("default")))
+int foo (int)
+{
+ return 2;
+}
+
+int bar()
+{
+ return foo ();
+}
+
+/* When updating any of the symbol names in these tests, make sure to also
+ update any tests for their absence in mvc-symbolsN.C */
+
+/* { dg-final { scan-assembler-times "\n_Z3foov:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.arch_slm:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.sse4.2:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tcall\t_Z7_Z3foovv\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z7_Z3foovv, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z7_Z3foovv,_Z3foov\.resolver\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n_Z3fooi:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch_slm:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.sse4.2:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z7_Z3fooii, @gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z7_Z3fooii,_Z3fooi\.resolver\n" 0 } } */
diff --git a/gcc/testsuite/g++.target/i386/mv-symbols5.C b/gcc/testsuite/g++.target/i386/mv-symbols5.C
new file mode 100644
index 0000000..d36e4c3
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/mv-symbols5.C
@@ -0,0 +1,56 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target("default")))
+int foo ();
+
+__attribute__((target("arch=slm")))
+int foo ()
+{
+ return 3;
+}
+
+__attribute__((target("sse4.2")))
+int foo ()
+{
+ return 5;
+}
+
+__attribute__((target("sse4.2")))
+int foo (int)
+{
+ return 6;
+}
+
+__attribute__((target("arch=slm")))
+int foo (int)
+{
+ return 4;
+}
+
+__attribute__((target("default")))
+int foo (int);
+
+int bar()
+{
+ return foo ();
+}
+
+/* When updating any of the symbol names in these tests, make sure to also
+ update any tests for their absence in mvc-symbolsN.C */
+
+/* { dg-final { scan-assembler-times "\n_Z3foov:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.arch_slm:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.sse4.2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tcall\t_Z7_Z3foovv\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z7_Z3foovv, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z7_Z3foovv,_Z3foov\.resolver\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n_Z3fooi:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch_slm:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.sse4.2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z7_Z3fooii, @gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z7_Z3fooii,_Z3fooi\.resolver\n" 0 } } */
diff --git a/gcc/testsuite/g++.target/i386/mvc-symbols1.C b/gcc/testsuite/g++.target/i386/mvc-symbols1.C
new file mode 100644
index 0000000..ea8c434
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/mvc-symbols1.C
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target_clones("default", "arch=slm", "sse4.2")))
+int foo ()
+{
+ return 1;
+}
+
+__attribute__((target_clones("sse4.2", "arch=slm", "default")))
+int foo (int)
+{
+ return 2;
+}
+
+int bar()
+{
+ return foo ();
+}
+
+int bar(int x)
+{
+ return foo (x);
+}
+
+/* When updating any of the symbol names in these tests, make sure to also
+ update any tests for their absence in mvc-symbolsN.C */
+
+/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.arch_slm:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.sse4_2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tcall\t_Z3foov\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n_Z3fooi.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch_slm:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.sse4_2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tcall\t_Z3fooi\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/g++.target/i386/mvc-symbols2.C b/gcc/testsuite/g++.target/i386/mvc-symbols2.C
new file mode 100644
index 0000000..84b54a9
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/mvc-symbols2.C
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target_clones("default", "arch=slm", "sse4.2")))
+int foo ()
+{
+ return 1;
+}
+
+__attribute__((target_clones("sse4.2", "arch=slm", "default")))
+int foo (int)
+{
+ return 2;
+}
+
+/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.arch_slm:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.sse4_2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n_Z3fooi.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch_slm:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.sse4_2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/g++.target/i386/mvc-symbols3.C b/gcc/testsuite/g++.target/i386/mvc-symbols3.C
new file mode 100644
index 0000000..3392707
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/mvc-symbols3.C
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target_clones("default", "arch=slm", "sse4.2")))
+int foo ();
+
+__attribute__((target_clones("sse4.2", "arch=slm", "default")))
+int foo (int);
+
+int bar()
+{
+ return foo ();
+}
+
+int bar(int x)
+{
+ return foo (x);
+}
+
+/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.arch_slm:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.sse4_2:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tcall\t_Z3foov\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n_Z3fooi.default:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch_slm:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.sse4_2:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tcall\t_Z3fooi\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/g++.target/i386/mvc-symbols4.C b/gcc/testsuite/g++.target/i386/mvc-symbols4.C
new file mode 100644
index 0000000..ed9bc8f
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/mvc-symbols4.C
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target_clones("default", "arch=slm", "sse4.2")))
+int foo ();
+
+__attribute__((target_clones("sse4.2", "arch=slm", "default")))
+int foo (int);
+
+/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.arch_slm:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.sse4_2:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 0 } } */
+
+/* { dg-final { scan-assembler-times "\n_Z3fooi.default:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch_slm:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.sse4_2:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 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/g++.target/powerpc/mvc-symbols1.C b/gcc/testsuite/g++.target/powerpc/mvc-symbols1.C
new file mode 100644
index 0000000..9424382
--- /dev/null
+++ b/gcc/testsuite/g++.target/powerpc/mvc-symbols1.C
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target_clones("default", "cpu=power6", "cpu=power6x")))
+int foo ()
+{
+ return 1;
+}
+
+__attribute__((target_clones("cpu=power6x", "cpu=power6", "default")))
+int foo (int)
+{
+ return 2;
+}
+
+int bar()
+{
+ return foo ();
+}
+
+int bar(int x)
+{
+ return foo (x);
+}
+
+/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.cpu_power6:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.cpu_power6x:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tbl _Z3foov\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3foov\.default\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3foov\.cpu_power6\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3foov\.cpu_power6x\n" 0 } } */
+
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.cpu_power6:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.cpu_power6x:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tbl _Z3fooi\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3fooi\.default\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3fooi\.cpu_power6\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3fooi\.cpu_power6x\n" 1 } } */
diff --git a/gcc/testsuite/g++.target/powerpc/mvc-symbols2.C b/gcc/testsuite/g++.target/powerpc/mvc-symbols2.C
new file mode 100644
index 0000000..edf5448
--- /dev/null
+++ b/gcc/testsuite/g++.target/powerpc/mvc-symbols2.C
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target_clones("default", "cpu=power6", "cpu=power6x")))
+int foo ()
+{
+ return 1;
+}
+
+__attribute__((target_clones("cpu=power6x", "cpu=power6", "default")))
+int foo (int)
+{
+ return 2;
+}
+
+/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.cpu_power6:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.cpu_power6x:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3foov\.default\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3foov\.cpu_power6\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3foov\.cpu_power6x\n" 0 } } */
+
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.cpu_power6:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.cpu_power6x:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3fooi\.default\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3fooi\.cpu_power6\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3fooi\.cpu_power6x\n" 1 } } */
diff --git a/gcc/testsuite/g++.target/powerpc/mvc-symbols3.C b/gcc/testsuite/g++.target/powerpc/mvc-symbols3.C
new file mode 100644
index 0000000..ca79c7f
--- /dev/null
+++ b/gcc/testsuite/g++.target/powerpc/mvc-symbols3.C
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target_clones("default", "cpu=power6", "cpu=power6x")))
+int foo ();
+
+__attribute__((target_clones("cpu=power6x", "cpu=power6", "default")))
+int foo (int);
+
+int bar()
+{
+ return foo ();
+}
+
+int bar(int x)
+{
+ return foo (x);
+}
+
+/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.cpu_power6:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.cpu_power6x:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tbl _Z3foov\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3foov\.default\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3foov\.cpu_power6\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3foov\.cpu_power6x\n" 0 } } */
+
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.cpu_power6:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.cpu_power6x:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tbl _Z3fooi\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3foov\.default\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3fooi\.cpu_power6\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.quad\t_Z3fooi\.cpu_power6x\n" 1 } } */
diff --git a/gcc/testsuite/g++.target/powerpc/mvc-symbols4.C b/gcc/testsuite/g++.target/powerpc/mvc-symbols4.C
new file mode 100644
index 0000000..ec111f5
--- /dev/null
+++ b/gcc/testsuite/g++.target/powerpc/mvc-symbols4.C
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target_clones("default", "cpu=power6", "cpu=power6x")))
+int foo ();
+
+__attribute__((target_clones("cpu=power6x", "cpu=power6", "default")))
+int foo (int);
+
+/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.cpu_power6:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.cpu_power6x:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\tlis \[\\d\]+,_Z3foov\.default@ha\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\tlis \[\\d\]+,_Z3foov\.cpu_power6@ha\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\tlis \[\\d\]+,_Z3foov\.cpu_power6x@ha\n" 0 } } */
+
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.cpu_power6:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.cpu_power6x:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\tlis \[\\d\]+,_Z3fooi\.default@ha\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\tlis \[\\d\]+,_Z3fooi\.cpu_power6@ha\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\tlis \[\\d\]+,_Z3fooi\.cpu_power6x@ha\n" 0 } } */
diff --git a/gcc/testsuite/gcc.dg/bad-binary-ops-highlight-colors.c b/gcc/testsuite/gcc.dg/bad-binary-ops-highlight-colors.c
index efbcdf3..da98f1a 100644
--- a/gcc/testsuite/gcc.dg/bad-binary-ops-highlight-colors.c
+++ b/gcc/testsuite/gcc.dg/bad-binary-ops-highlight-colors.c
@@ -23,8 +23,8 @@ int test_4 (void)
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
- return callee_4a () + callee_4b ();
- ~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
+ return callee_4a () + callee_4b ();
+ ~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
| |
| T {aka struct t}
S {aka struct s}
diff --git a/gcc/testsuite/gcc.dg/format/colors.c b/gcc/testsuite/gcc.dg/format/colors.c
index 43484b7..42cfd50 100644
--- a/gcc/testsuite/gcc.dg/format/colors.c
+++ b/gcc/testsuite/gcc.dg/format/colors.c
@@ -15,8 +15,8 @@ void test_mismatching_types (const char *msg)
warning: format '%i' expects argument of type 'int', but argument 2 has type 'const char *' [-Wformat=]
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
- printf("hello %i", msg);
- ~^ ~~~
+ printf("hello %i", msg);
+ ~^ ~~~
| |
int const char *
%s
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
new file mode 100644
index 0000000..2411b04
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu23" } */
+
+int f()
+{
+ typedef struct foo bar;
+ struct foo { typeof(({ (struct foo { bar * x; }){ }; })) * x; } *q;
+ typeof(q->x) p;
+ 1 ? p : q;
+}
+
diff --git a/gcc/testsuite/gcc.dg/gomp/declare-mapper-10.c b/gcc/testsuite/gcc.dg/gomp/declare-mapper-10.c
new file mode 100644
index 0000000..efc9c13
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/declare-mapper-10.c
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-gimple" } */
+
+// "omp declare mapper" support -- check expansion in gimple.
+
+#include <stdlib.h>
+
+struct S {
+ int *ptr;
+ int size;
+};
+
+#define N 64
+
+#pragma omp declare mapper (struct S w) map(w.size, w.ptr, w.ptr[:w.size])
+#pragma omp declare mapper (foo:struct S w) map(to:w.size, w.ptr) \
+ map(w.ptr[:w.size])
+
+int main (int argc, char *argv[])
+{
+ struct S s;
+ s.ptr = (int *) malloc (sizeof (int) * N);
+ s.size = N;
+
+#pragma omp declare mapper (bar:struct S w) map(w.size, w.ptr, w.ptr[:w.size])
+
+#pragma omp target
+ {
+ for (int i = 0; i < N; i++)
+ s.ptr[i]++;
+ }
+
+#pragma omp target map(tofrom: s)
+ {
+ for (int i = 0; i < N; i++)
+ s.ptr[i]++;
+ }
+
+#pragma omp target map(mapper(default), tofrom: s)
+ {
+ for (int i = 0; i < N; i++)
+ s.ptr[i]++;
+ }
+
+#pragma omp target map(mapper(foo), alloc: s)
+ {
+ for (int i = 0; i < N; i++)
+ s.ptr[i]++;
+ }
+
+#pragma omp target map(mapper(bar), tofrom: s)
+ {
+ for (int i = 0; i < N; i++)
+ s.ptr[i]++;
+ }
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times {map\(struct:s \[len: 2\]\) map\(tofrom:s\.ptr \[len: [0-9]+\]\) map\(tofrom:s\.size \[len: [0-9]+\]\) map\(tofrom:\*_[0-9]+ \[len: _[0-9]+\]\) map\(attach:s\.ptr \[bias: 0\]\)} 4 "gimple" { target c++ } } } */
+/* { dg-final { scan-tree-dump-times {map\(struct:s \[len: 2\]\) map\(to:s\.ptr \[len: [0-9]+\]\) map\(to:s\.size \[len: [0-9]+\]\) map\(alloc:\*_[0-9]+ \[len: _[0-9]+\]\) map\(attach:s\.ptr \[bias: 0\]\)} 1 "gimple" { target c++ } } } */
diff --git a/gcc/testsuite/gcc.dg/gomp/declare-mapper-11.c b/gcc/testsuite/gcc.dg/gomp/declare-mapper-11.c
new file mode 100644
index 0000000..108a297
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/declare-mapper-11.c
@@ -0,0 +1,33 @@
+// { dg-do compile }
+
+// Error-checking tests for "omp declare mapper".
+
+typedef struct {
+ int *ptr;
+ int size;
+} S;
+
+typedef struct {
+ int z;
+} Z;
+
+int main (int argc, char *argv[])
+{
+#pragma omp declare mapper (S v) map(v.size, v.ptr[:v.size])
+/* { dg-note "'#pragma omp declare mapper' previously declared here" "" { target c } .-1 } */
+
+ /* This one's a duplicate. */
+#pragma omp declare mapper (default: S v) map (to: v.size) map (v)
+/* { dg-error "redeclaration of '<default>' '#pragma omp declare mapper' for type 'S'" "" { target c } .-1 } */
+
+ /* ...and this one doesn't use a "base language identifier" for the mapper
+ name. */
+#pragma omp declare mapper (case: S v) map (to: v.size)
+/* { dg-error "expected identifier or 'default'" "" { target c } .-1 } */
+
+ /* A non-struct/class/union type isn't supposed to work. */
+#pragma omp declare mapper (name:Z [5]foo) map (foo[0].z)
+/* { dg-error "'Z\\\[5\\\]' is not a struct or union type in '#pragma omp declare mapper'" "" { target c } .-1 } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/declare-mapper-13.c b/gcc/testsuite/gcc.dg/gomp/declare-mapper-13.c
new file mode 100644
index 0000000..df2b4a5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/declare-mapper-13.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+
+struct S { int y; };
+
+struct V
+{
+ int x;
+ #pragma omp declare mapper (bar: struct S s: s) map(s) /* { dg-error "'#pragma omp declare mapper' not at file or block scope" } */
+ /* { dg-error "expected end of line before '\\(' token" "" { target *-*-* } .-1 } */
+ #pragma omp declare mapper (struct V z : z) map(z) /* { dg-error "'#pragma omp declare mapper' not at file or block scope" } */
+ /* { dg-error "expected end of line before '\\(' token" "" { target *-*-* } .-1 } */
+};
+
diff --git a/gcc/testsuite/gcc.dg/gomp/udr-3.c b/gcc/testsuite/gcc.dg/gomp/udr-3.c
index 96450cd..2c7a3bd 100644
--- a/gcc/testsuite/gcc.dg/gomp/udr-3.c
+++ b/gcc/testsuite/gcc.dg/gomp/udr-3.c
@@ -31,13 +31,13 @@ f2 ()
#pragma omp declare reduction (bar: struct S: omp_out.s += omp_in.s) initializer (bar (&omp_orig)) /* { dg-error "one of the initializer call arguments should be" } */
}
-#pragma omp declare reduction (+: struct U: omp_out.u *= omp_in.u) /* { dg-error "previous" } */
+#pragma omp declare reduction (+: struct U: omp_out.u *= omp_in.u) /* { dg-note "'#pragma omp declare reduction' previously declared here" } */
#pragma omp declare reduction (+: struct U: omp_out.u += omp_in.u) /* { dg-error "redeclaration of" } */
void
f3 ()
{
- #pragma omp declare reduction (f3: struct U: omp_out.u *= omp_in.u) /* { dg-error "previous" } */
+ #pragma omp declare reduction (f3: struct U: omp_out.u *= omp_in.u) /* { dg-note "'#pragma omp declare reduction' previously declared here" } */
#pragma omp declare reduction (f3: struct U: omp_out.u += omp_in.u) /* { dg-error "redeclaration of" } */
}
@@ -47,7 +47,7 @@ struct V
#pragma omp declare reduction (bar: struct S: omp_out.s += omp_in.s) /* { dg-error "not at file or block scope" } */
};
-#pragma omp declare reduction (n3: long: omp_out += omp_in) /* { dg-error "previous" } */
+#pragma omp declare reduction (n3: long: omp_out += omp_in) /* { dg-note "'#pragma omp declare reduction' previously declared here" } */
#pragma omp declare reduction (n3: long int: omp_out += omp_in) /* { dg-error "redeclaration of" } */
#pragma omp declare reduction (n3: short unsigned: omp_out += omp_in)
#pragma omp declare reduction (n3: short int: omp_out += omp_in)
@@ -55,7 +55,7 @@ struct V
void
f4 (void)
{
- #pragma omp declare reduction (f4: long: omp_out += omp_in) /* { dg-error "previous" } */
+ #pragma omp declare reduction (f4: long: omp_out += omp_in) /* { dg-note "'#pragma omp declare reduction' previously declared here" } */
#pragma omp declare reduction (f4: long int: omp_out += omp_in) /* { dg-error "redeclaration of" } */
#pragma omp declare reduction (f4: short unsigned: omp_out += omp_in)
#pragma omp declare reduction (f4: short int: omp_out += omp_in)
diff --git a/gcc/testsuite/gcc.dg/ipa/pr120295.c b/gcc/testsuite/gcc.dg/ipa/pr120295.c
new file mode 100644
index 0000000..2033ee9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr120295.c
@@ -0,0 +1,66 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+struct {
+ signed a;
+} b;
+int a, f, j, l;
+char c, k, g, e;
+short d[2] = {0};
+int *i = &j;
+
+volatile int glob;
+void __attribute__((noipa)) sth (const char *, int a)
+{
+ glob = a;
+ return;
+}
+
+void marker_37() {
+ a++;
+ sth ("%d\n", a);
+}
+unsigned long long m(unsigned, char, unsigned, short);
+int n(int, unsigned char, long long);
+int o(long long, unsigned, unsigned);
+unsigned short p(void) {
+ int *r = &l;
+ *r |= ({
+ long long y = (m(c, c, 0, c), b.a);
+ y;
+ });
+ return 0;
+}
+unsigned long long m(unsigned q, char v, unsigned s, short u) {
+ unsigned short ab = 5;
+ if (n(q, ab, d[1]))
+ for (; g; g++)
+ ;
+ return c;
+}
+int n(int af, unsigned char e, long long ae) {
+ unsigned ag = 4;
+ int *ah = &f;
+ *ah = ({ short ad = o(af, f, ag); ad<0 || ad> e; });
+ return *i;
+}
+int o(long long aj, unsigned ai, unsigned ak) {
+ for (; e; e--) {
+ int *al = &f;
+ for (; k; k++)
+ *al = 0;
+ }
+ if (18446744073709551606UL != (unsigned long long) aj)
+ ;
+ else
+ marker_37();
+ return ak;
+}
+int f123() {
+ c = 0xf6;
+ p();
+ return 0;
+}
+int main() {
+ return f123();
+}
diff --git a/gcc/testsuite/gcc.dg/pr120353.c b/gcc/testsuite/gcc.dg/pr120353.c
new file mode 100644
index 0000000..6f8e4ac
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120353.c
@@ -0,0 +1,11 @@
+/* PR120353: Test for -Wflex-array-member-not-at-end on structure with
+ typedef. */
+/* { dg-do compile } */
+/* { dg-options "-Wflex-array-member-not-at-end" } */
+
+typedef struct flex flex_t;
+struct flex { int n; int data[]; };
+struct out_flex_mid {flex_t flex_data; int m; }; /* { dg-warning "structure containing a flexible array member is not at the end of another structure" } */
+
+typedef struct flex flex_t1;
+struct out_flex_mid1 {flex_t1 flex_data1; int n; }; /* { dg-warning "structure containing a flexible array member is not at the end of another structure" } */
diff --git a/gcc/testsuite/gcc.dg/pr120354.c b/gcc/testsuite/gcc.dg/pr120354.c
new file mode 100644
index 0000000..6749737
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120354.c
@@ -0,0 +1,33 @@
+/* PR120354: Test for -Wflex-array-member-not-at-end on union with
+ flexible array members. */
+/* { dg-do compile } */
+/* { dg-options "-Wflex-array-member-not-at-end" } */
+
+struct P {};
+union L {};
+
+union X {
+ int x[];
+ struct P y;
+};
+
+struct T {
+ union X x; /* { dg-warning "structure containing a flexible array member is not at the end of another structure" } */
+ int plug;
+};
+
+struct Q {
+ int len;
+ int data[];
+};
+
+union Y {
+ struct Q q;
+ union L y;
+};
+
+struct S {
+ union Y y; /* { dg-warning "structure containing a flexible array member is not at the end of another structure" } */
+ int plug;
+};
+
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/pr120381.c b/gcc/testsuite/gcc.dg/pr120381.c
new file mode 100644
index 0000000..5c017e6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120381.c
@@ -0,0 +1,10 @@
+/* PR120381 */
+/* { dg-do compile } */
+
+struct A {
+ struct A { /* { dg-error "nested redefinition" } */
+ struct A *p;
+ } *p;
+};
+int foo(const struct A *q) { return q->p == q; }
+
diff --git a/gcc/testsuite/gcc.dg/pr120480.c b/gcc/testsuite/gcc.dg/pr120480.c
new file mode 100644
index 0000000..cf7b47a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120480.c
@@ -0,0 +1,11 @@
+/* PR target/120480 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+struct S { int a, b, c; } s;
+
+void
+foo (void)
+{
+ struct S t = s;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr120341-1.c b/gcc/testsuite/gcc.dg/torture/pr120341-1.c
new file mode 100644
index 0000000..e23185b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr120341-1.c
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fallow-store-data-races" } */
+
+char a, *b;
+int main()
+{
+ b = "0";
+ if (a)
+ b[0]++;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr120341-2.c b/gcc/testsuite/gcc.dg/torture/pr120341-2.c
new file mode 100644
index 0000000..7bcc96f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr120341-2.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fallow-store-data-races" } */
+
+char a, *b;
+int main()
+{
+ while (a)
+ {
+ b = "0";
+ b[0]++;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr120347.c b/gcc/testsuite/gcc.dg/torture/pr120347.c
new file mode 100644
index 0000000..a2d187b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr120347.c
@@ -0,0 +1,13 @@
+/* { dg-do assemble } */
+/* { dg-additional-options "-march=armv7-a -mthumb" { target { arm_arch_v7a_ok && arm_thumb2_ok } } } */
+
+void *end;
+void **start;
+void main(void)
+{
+ for (; end; start++) {
+ if (*start)
+ return;
+ *start = start;
+ }
+}
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/reduc-pshuf.c b/gcc/testsuite/gcc.target/i386/reduc-pshuf.c
new file mode 100644
index 0000000..e46d2ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/reduc-pshuf.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=znver5 " } */
+
+#define N 32
+#define T short
+T
+foo (T *a)
+{
+ T sum = 0;
+ for (int i = 0; i < N; i++)
+ sum += a[i];
+ return sum;
+}
+
+/* { dg-final { scan-assembler-times "vpsrl" 0 } } */
+/* { dg-final { scan-assembler-times "vpshuf" 3 } } */
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-57.c b/gcc/testsuite/gcc.target/riscv/arch-57.c
new file mode 100644
index 0000000..08d3761
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-57.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i_smdbltrp -mabi=lp64" } */
+
+void foo(){}
+
+/* { dg-final { scan-assembler ".attribute arch, \"rv64i2p1_zicsr2p0_smdbltrp1p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/arch-58.c b/gcc/testsuite/gcc.target/riscv/arch-58.c
new file mode 100644
index 0000000..1481da5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-58.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i_ssdbltrp -mabi=lp64" } */
+
+void foo(){}
+
+/* { dg-final { scan-assembler ".attribute arch, \"rv64i2p1_zicsr2p0_ssdbltrp1p0\"" } } */
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/rvv/autovec/avg.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg.h
index 746c635..4aeb637 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg.h
@@ -20,4 +20,21 @@ test_##NAME##_##WT##_##NT##_0(NT * restrict a, NT * restrict b, \
#define RUN_AVG_0_WRAP(NT, WT, NAME, a, b, out, n) \
RUN_AVG_0(NT, WT, NAME, a, b, out, n)
+#define DEF_AVG_1(NT, WT, NAME) \
+__attribute__((noinline)) \
+void \
+test_##NAME##_##WT##_##NT##_1(NT * restrict a, NT * restrict b, \
+ NT * restrict out, int n) \
+{ \
+ for (int i = 0; i < n; i++) { \
+ out[i] = (NT)(((WT)a[i] + (WT)b[i] + 1) >> 1); \
+ } \
+}
+#define DEF_AVG_1_WRAP(NT, WT, NAME) DEF_AVG_1(NT, WT, NAME)
+
+#define RUN_AVG_1(NT, WT, NAME, a, b, out, n) \
+ test_##NAME##_##WT##_##NT##_1(a, b, out, n)
+#define RUN_AVG_1_WRAP(NT, WT, NAME, a, b, out, n) \
+ RUN_AVG_1(NT, WT, NAME, a, b, out, n)
+
#endif
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i32.c
new file mode 100644
index 0000000..138124c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i32.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d" } */
+
+#include "avg.h"
+
+#define NT int16_t
+#define WT int32_t
+
+DEF_AVG_1(NT, WT, avg_ceil)
+
+/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 1 } } */
+/* { dg-final { scan-assembler-times {vaadd.vv} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i64.c
new file mode 100644
index 0000000..30438c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i64.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d" } */
+
+#include "avg.h"
+
+#define NT int16_t
+#define WT int64_t
+
+DEF_AVG_1(NT, WT, avg_ceil)
+
+/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 1 } } */
+/* { dg-final { scan-assembler-times {vaadd.vv} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i32-from-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i32-from-i64.c
new file mode 100644
index 0000000..2e9cfa5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i32-from-i64.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d" } */
+
+#include "avg.h"
+
+#define NT int32_t
+#define WT int64_t
+
+DEF_AVG_1(NT, WT, avg_ceil)
+
+/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 1 } } */
+/* { dg-final { scan-assembler-times {vaadd.vv} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i16.c
new file mode 100644
index 0000000..2ebf294
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i16.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d" } */
+
+#include "avg.h"
+
+#define NT int8_t
+#define WT int16_t
+
+DEF_AVG_1(NT, WT, avg_ceil)
+
+/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 1 } } */
+/* { dg-final { scan-assembler-times {vaadd.vv} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i32.c
new file mode 100644
index 0000000..64fec91
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i32.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d" } */
+
+#include "avg.h"
+
+#define NT int8_t
+#define WT int32_t
+
+DEF_AVG_1(NT, WT, avg_ceil)
+
+/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 1 } } */
+/* { dg-final { scan-assembler-times {vaadd.vv} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i64.c
new file mode 100644
index 0000000..a72642c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i64.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d" } */
+
+#include "avg.h"
+
+#define NT int8_t
+#define WT int64_t
+
+DEF_AVG_1(NT, WT, avg_ceil)
+
+/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 1 } } */
+/* { dg-final { scan-assembler-times {vaadd.vv} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i16-from-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i16-from-i32.c
new file mode 100644
index 0000000..1fa080b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i16-from-i32.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -O3" } */
+
+#include "avg.h"
+#include "avg_data.h"
+
+#define WT int32_t
+#define NT int16_t
+#define NAME avg_ceil
+
+DEF_AVG_1_WRAP(NT, WT, NAME)
+
+#define TEST_DATA TEST_AVG_DATA_WRAP(NT, NAME)
+#define TEST_RUN(NT, WT, NAME, a, b, out, n) RUN_AVG_1_WRAP(NT, WT, NAME, a, b, out, n)
+
+#include "avg_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i16-from-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i16-from-i64.c
new file mode 100644
index 0000000..deec763
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i16-from-i64.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -O3" } */
+
+#include "avg.h"
+#include "avg_data.h"
+
+#define WT int64_t
+#define NT int16_t
+#define NAME avg_ceil
+
+DEF_AVG_1_WRAP(NT, WT, NAME)
+
+#define TEST_DATA TEST_AVG_DATA_WRAP(NT, NAME)
+#define TEST_RUN(NT, WT, NAME, a, b, out, n) RUN_AVG_1_WRAP(NT, WT, NAME, a, b, out, n)
+
+#include "avg_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i32-from-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i32-from-i64.c
new file mode 100644
index 0000000..fa72000
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i32-from-i64.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -O3" } */
+
+#include "avg.h"
+#include "avg_data.h"
+
+#define WT int64_t
+#define NT int32_t
+#define NAME avg_ceil
+
+DEF_AVG_1_WRAP(NT, WT, NAME)
+
+#define TEST_DATA TEST_AVG_DATA_WRAP(NT, NAME)
+#define TEST_RUN(NT, WT, NAME, a, b, out, n) RUN_AVG_1_WRAP(NT, WT, NAME, a, b, out, n)
+
+#include "avg_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i16.c
new file mode 100644
index 0000000..6865cf2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i16.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -O3" } */
+
+#include "avg.h"
+#include "avg_data.h"
+
+#define WT int16_t
+#define NT int8_t
+#define NAME avg_ceil
+
+DEF_AVG_1_WRAP(NT, WT, NAME)
+
+#define TEST_DATA TEST_AVG_DATA_WRAP(NT, NAME)
+#define TEST_RUN(NT, WT, NAME, a, b, out, n) RUN_AVG_1_WRAP(NT, WT, NAME, a, b, out, n)
+
+#include "avg_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i32.c
new file mode 100644
index 0000000..78620f4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i32.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -O3" } */
+
+#include "avg.h"
+#include "avg_data.h"
+
+#define WT int32_t
+#define NT int8_t
+#define NAME avg_ceil
+
+DEF_AVG_1_WRAP(NT, WT, NAME)
+
+#define TEST_DATA TEST_AVG_DATA_WRAP(NT, NAME)
+#define TEST_RUN(NT, WT, NAME, a, b, out, n) RUN_AVG_1_WRAP(NT, WT, NAME, a, b, out, n)
+
+#include "avg_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i64.c
new file mode 100644
index 0000000..b2c763c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i64.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -O3" } */
+
+#include "avg.h"
+#include "avg_data.h"
+
+#define WT int64_t
+#define NT int8_t
+#define NAME avg_ceil
+
+DEF_AVG_1_WRAP(NT, WT, NAME)
+
+#define TEST_DATA TEST_AVG_DATA_WRAP(NT, NAME)
+#define TEST_RUN(NT, WT, NAME, a, b, out, n) RUN_AVG_1_WRAP(NT, WT, NAME, a, b, out, n)
+
+#include "avg_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_data.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_data.h
index cbeed14..12b464a 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_data.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_data.h
@@ -182,4 +182,180 @@ int64_t TEST_AVG_DATA(int64_t, avg_floor)[][3][N] =
},
};
+int8_t TEST_AVG_DATA(int8_t, avg_ceil)[][3][N] =
+{
+ {
+ {
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ 8, 8, 8, 8,
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ -2, -2, -2, -2,
+ 1, 1, 1, 1,
+ },
+ {
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ 5, 5, 5, 5,
+ },
+ },
+ {
+ {
+ 127, 127, 127, 127,
+ 127, 127, 127, 127,
+ -128, -128, -128, -128,
+ -128, -128, -128, -128,
+ },
+ {
+ 126, 126, 126, 126,
+ -2, -2, -2, -2,
+ 127, 127, 127, 127,
+ -127, -127, -127, -127,
+ },
+ {
+ 127, 127, 127, 127,
+ 63, 63, 63, 63,
+ 0, 0, 0, 0,
+ -127, -127, -127, -127,
+ },
+ },
+};
+
+int16_t TEST_AVG_DATA(int16_t, avg_ceil)[][3][N] =
+{
+ {
+ {
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ 8, 8, 8, 8,
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ -2, -2, -2, -2,
+ 1, 1, 1, 1,
+ },
+ {
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ 5, 5, 5, 5,
+ },
+ },
+ {
+ {
+ 32767, 32767, 32767, 32767,
+ 32767, 32767, 32767, 32767,
+ -32768, -32768, -32768, -32768,
+ -32768, -32768, -32768, -32768,
+ },
+ {
+ 32766, 32766, 32766, 32766,
+ -2, -2, -2, -2,
+ 32767, 32767, 32767, 32767,
+ -32767, -32767, -32767, -32767,
+ },
+ {
+ 32767, 32767, 32767, 32767,
+ 16383, 16383, 16383, 16383,
+ 0, 0, 0, 0,
+ -32767, -32767, -32767, -32767,
+ },
+ },
+};
+
+int32_t TEST_AVG_DATA(int32_t, avg_ceil)[][3][N] =
+{
+ {
+ {
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ 8, 8, 8, 8,
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ -2, -2, -2, -2,
+ 1, 1, 1, 1,
+ },
+ {
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ 5, 5, 5, 5,
+ },
+ },
+ {
+ {
+ 2147483647, 2147483647, 2147483647, 2147483647,
+ 2147483647, 2147483647, 2147483647, 2147483647,
+ -2147483648, -2147483648, -2147483648, -2147483648,
+ -2147483648, -2147483648, -2147483648, -2147483648,
+ },
+ {
+ 2147483646, 2147483646, 2147483646, 2147483646,
+ -2, -2, -2, -2,
+ 2147483647, 2147483647, 2147483647, 2147483647,
+ -2147483647, -2147483647, -2147483647, -2147483647,
+ },
+ {
+ 2147483647, 2147483647, 2147483647, 2147483647,
+ 1073741823, 1073741823, 1073741823, 1073741823,
+ 0, 0, 0, 0,
+ -2147483647, -2147483647, -2147483647, -2147483647,
+ },
+ },
+};
+
+int64_t TEST_AVG_DATA(int64_t, avg_ceil)[][3][N] =
+{
+ {
+ {
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ 8, 8, 8, 8,
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ -2, -2, -2, -2,
+ 1, 1, 1, 1,
+ },
+ {
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ -1, -1, -1, -1,
+ 5, 5, 5, 5,
+ },
+ },
+ {
+ {
+ 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull,
+ 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull,
+ -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+ -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull,
+ },
+ {
+ 9223372036854775806ull, 9223372036854775806ull, 9223372036854775806ull, 9223372036854775806ull,
+ 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull,
+ -2ull, -2ull, -2ull, -2ull,
+ -9223372036854775807ull, -9223372036854775807ull, -9223372036854775807ull, -9223372036854775807ull,
+ },
+ {
+ 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull,
+ 4611686018427387903ull, 4611686018427387903ull, 4611686018427387903ull, 4611686018427387903ull,
+ 0ull, 0ull, 0ull, 0ull,
+ -9223372036854775807ull, -9223372036854775807ull, -9223372036854775807ull, -9223372036854775807ull,
+ },
+ },
+};
+
#endif
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/vls/avg-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-4.c
index 8d106aa..986a0ff 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-4.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-4.c
@@ -25,11 +25,9 @@ DEF_AVG_CEIL (uint8_t, uint16_t, 512)
DEF_AVG_CEIL (uint8_t, uint16_t, 1024)
DEF_AVG_CEIL (uint8_t, uint16_t, 2048)
-/* { dg-final { scan-assembler-times {vwadd\.vv} 10 } } */
-/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 10 } } */
-/* { dg-final { scan-assembler-times {vnsra\.wi} 10 } } */
+/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 20 } } */
+/* { dg-final { scan-assembler-times {vaadd\.vv} 10 } } */
/* { dg-final { scan-assembler-times {vaaddu\.vv} 10 } } */
-/* { dg-final { scan-assembler-times {vadd\.vi} 10 } } */
/* { dg-final { scan-assembler-not {csrr} } } */
/* { dg-final { scan-tree-dump-not "1,1" "optimized" } } */
/* { dg-final { scan-tree-dump-not "2,2" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-5.c
index 981abd5..c450f80 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-5.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-5.c
@@ -23,11 +23,9 @@ DEF_AVG_CEIL (uint16_t, uint32_t, 256)
DEF_AVG_CEIL (uint16_t, uint32_t, 512)
DEF_AVG_CEIL (uint16_t, uint32_t, 1024)
-/* { dg-final { scan-assembler-times {vwadd\.vv} 9 } } */
-/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 9 } } */
-/* { dg-final { scan-assembler-times {vnsra\.wi} 9 } } */
+/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 18 } } */
/* { dg-final { scan-assembler-times {vaaddu\.vv} 9 } } */
-/* { dg-final { scan-assembler-times {vadd\.vi} 9 } } */
+/* { dg-final { scan-assembler-times {vaadd\.vv} 9 } } */
/* { dg-final { scan-assembler-not {csrr} } } */
/* { dg-final { scan-tree-dump-not "1,1" "optimized" } } */
/* { dg-final { scan-tree-dump-not "2,2" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-6.c
index bfe4ba3..3473e19 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-6.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-6.c
@@ -21,11 +21,9 @@ DEF_AVG_CEIL (uint16_t, uint32_t, 128)
DEF_AVG_CEIL (uint16_t, uint32_t, 256)
DEF_AVG_CEIL (uint16_t, uint32_t, 512)
-/* { dg-final { scan-assembler-times {vwadd\.vv} 8 } } */
-/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 8 } } */
-/* { dg-final { scan-assembler-times {vnsra\.wi} 8 } } */
+/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 16 } } */
/* { dg-final { scan-assembler-times {vaaddu\.vv} 8 } } */
-/* { dg-final { scan-assembler-times {vadd\.vi} 8 } } */
+/* { dg-final { scan-assembler-times {vaadd\.vv} 8 } } */
/* { dg-final { scan-assembler-not {csrr} } } */
/* { dg-final { scan-tree-dump-not "1,1" "optimized" } } */
/* { dg-final { scan-tree-dump-not "2,2" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv32gcv.c
index b7246a3..a5224e7 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv32gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv32gcv.c
@@ -5,4 +5,4 @@
/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*2} 6 } } */
/* { dg-final { scan-assembler-times {vaaddu\.vv} 6 } } */
-/* { dg-final { scan-assembler-times {vaadd\.vv} 3 } } */
+/* { dg-final { scan-assembler-times {vaadd\.vv} 6 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv64gcv.c
index 3ffe0ef..32446ae 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv64gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv64gcv.c
@@ -5,4 +5,4 @@
/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*2} 6 } } */
/* { dg-final { scan-assembler-times {vaaddu\.vv} 6 } } */
-/* { dg-final { scan-assembler-times {vaadd\.vv} 3 } } */
+/* { dg-final { scan-assembler-times {vaadd\.vv} 6 } } */
diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_tests_6.f90 b/gcc/testsuite/gfortran.dg/c_f_pointer_tests_6.f90
index 23ca88b..bc2206d 100644
--- a/gcc/testsuite/gfortran.dg/c_f_pointer_tests_6.f90
+++ b/gcc/testsuite/gfortran.dg/c_f_pointer_tests_6.f90
@@ -38,6 +38,6 @@ contains
type(my_c_ptr_0) :: my_ptr2
type(c_funptr) :: myfun
print *,c_associated(my_ptr,my_ptr2)
- print *,c_associated(my_ptr,myfun) ! { dg-error "Argument C_PTR_2 at .1. to C_ASSOCIATED shall have the same type as C_PTR_1: TYPE.c_ptr. instead of TYPE.c_funptr." }
+ print *,c_associated(my_ptr,myfun) ! { dg-error "Argument C_PTR_2 at .1. to C_ASSOCIATED shall have the same type as C_PTR_1, found TYPE.c_funptr. instead of TYPE.c_ptr." }
end subroutine
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/interface_62.f90 b/gcc/testsuite/gfortran.dg/interface_62.f90
new file mode 100644
index 0000000..19d4325
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/interface_62.f90
@@ -0,0 +1,39 @@
+! { dg-do compile }
+! PR fortran/120355 - this was rejected because the typespec from
+! the RESULT clause was not picked up.
+! Test case jsberg@bnl.gov.
+
+program p
+ implicit none
+ integer :: i,j
+ interface
+ function s(x) result(y)
+ implicit none
+ integer, intent(in) :: x
+ integer :: y
+ end function s
+ end interface
+ i = 0
+ call t(s,i,j)
+contains
+ subroutine t(f,x,y)
+ implicit none
+ integer, intent(in) :: x
+ integer, intent(out) :: y
+ interface
+ function f(x) result(y)
+ implicit none
+ integer, intent(in) :: x
+ integer :: y
+ end function f
+ end interface
+ y = f(x)
+ end subroutine t
+end program p
+
+function s(x) result(y)
+ implicit none
+ integer, intent(in) :: x
+ integer :: y
+ y = 1 - x
+end function s
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/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 6286e36..dfffe3a 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -759,7 +759,13 @@ proc check_effective_target_keeps_null_pointer_checks { } {
# this allows parallelism of 16 and higher of parallel gcc-auto-profile
proc profopt-perf-wrapper { } {
global srcdir
- return "$srcdir/../config/i386/gcc-auto-profile --all -m8 "
+ if { [check_effective_target_x86] } {
+ return "$srcdir/../config/i386/gcc-auto-profile -m8"
+ }
+ if { [istarget aarch64*-*-*] } {
+ return "$srcdir/../config/aarch64/gcc-auto-profile -m8"
+ }
+ return ""
}
# Return true if profiling is supported on the target.
@@ -778,8 +784,7 @@ proc check_profiling_available { test_what } {
}
if { $test_what == "-fauto-profile" } {
- if { !([check_effective_target_x86] && [istarget *-*-linux*]) } {
- verbose "autofdo only supported on linux"
+ if { !([check_effective_target_autofdo]) } {
return 0
}
# not cross compiling?
@@ -787,13 +792,14 @@ proc check_profiling_available { test_what } {
verbose "autofdo not supported for non native builds"
return 0
}
- set event [profopt-perf-wrapper]
- if {$event == "" } {
+ set wrapper [profopt-perf-wrapper]
+ if {$wrapper == "" } {
verbose "autofdo not supported"
return 0
}
+ puts $wrapper
global srcdir
- set status [remote_exec host "$srcdir/../config/i386/gcc-auto-profile" "-m8 true -v >/dev/null"]
+ set status [remote_exec host "$wrapper true -v >/dev/null"]
if { [lindex $status 0] != 0 } {
verbose "autofdo not supported because perf does not work"
return 0
@@ -1092,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 {} {
@@ -1423,6 +1439,23 @@ proc check_effective_target_fpic { } {
return 0
}
+# Check if target supports autofdo.
+
+proc check_effective_target_autofdo { } {
+ if { !([istarget *-*-linux*]) } {
+ verbose "autofdo only supported on linux"
+ return 0
+ }
+ if { [check_effective_target_x86] } {
+ return 1
+ }
+ if { [istarget aarch64*-*-*] } {
+ return 1
+ }
+ return 0
+}
+
+
# On AArch64, if -fpic is not supported, then we will fall back to -fPIC
# silently. So, we can't rely on above "check_effective_target_fpic" as it
# assumes compiler will give warning if -fpic not supported. Here we check
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index bd19c99..028b6af 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -368,6 +368,10 @@ enum omp_clause_code {
/* OpenMP clause: doacross ({source,sink}:vec). */
OMP_CLAUSE_DOACROSS,
+ /* OpenMP mapper binding: record implicit mappers in scope for aggregate
+ types used within an offload region. */
+ OMP_CLAUSE__MAPPER_BINDING_,
+
/* Internal structure to hold OpenACC cache directive's variable-list.
#pragma acc cache (variable-list). */
OMP_CLAUSE__CACHE_,
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-nrv.cc b/gcc/tree-nrv.cc
index 180ce39..3be97af 100644
--- a/gcc/tree-nrv.cc
+++ b/gcc/tree-nrv.cc
@@ -167,16 +167,21 @@ pass_nrv::execute (function *fun)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
- tree ret_val;
if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
{
- /* In a function with an aggregate return value, the
- gimplifier has changed all non-empty RETURN_EXPRs to
- return the RESULT_DECL. */
- ret_val = gimple_return_retval (return_stmt);
- if (ret_val)
- gcc_assert (ret_val == result);
+ /* We cannot perform NRV optimizations in a function with an
+ aggregate return value if there is a return that does not
+ return RESULT_DECL. We used to assert this scenario doesn't
+ happen: the gimplifier has changed all non-empty RETURN_EXPRs
+ to return the RESULT_DECL. However, per PR119835 we may run
+ into this scenario for offloading compilation, and therefore
+ gracefully bail out. */
+ if (tree ret_val = gimple_return_retval (return_stmt))
+ {
+ if (ret_val != result)
+ return 0;
+ }
}
else if (gimple_has_lhs (stmt)
&& gimple_get_lhs (stmt) == result)
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-pretty-print.cc b/gcc/tree-pretty-print.cc
index 359359d..fadafd6 100644
--- a/gcc/tree-pretty-print.cc
+++ b/gcc/tree-pretty-print.cc
@@ -1122,6 +1122,15 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
pp_string (pp, "always,present,tofrom");
break;
+ case GOMP_MAP_UNSET:
+ pp_string (pp, "unset");
+ break;
+ case GOMP_MAP_PUSH_MAPPER_NAME:
+ pp_string (pp, "push_mapper");
+ break;
+ case GOMP_MAP_POP_MAPPER_NAME:
+ pp_string (pp, "pop_mapper");
+ break;
default:
gcc_unreachable ();
}
@@ -1200,6 +1209,23 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
spc, flags, false);
goto print_clause_size;
+ case OMP_CLAUSE__MAPPER_BINDING_:
+ pp_string (pp, "mapper_binding(");
+ if (OMP_CLAUSE__MAPPER_BINDING__ID (clause))
+ {
+ dump_generic_node (pp, OMP_CLAUSE__MAPPER_BINDING__ID (clause), spc,
+ flags, false);
+ pp_comma (pp);
+ }
+ dump_generic_node (pp,
+ TREE_TYPE (OMP_CLAUSE__MAPPER_BINDING__DECL (clause)),
+ spc, flags, false);
+ pp_comma (pp);
+ dump_generic_node (pp, OMP_CLAUSE__MAPPER_BINDING__MAPPER (clause), spc,
+ flags, false);
+ pp_right_paren (pp);
+ break;
+
case OMP_CLAUSE_NUM_TEAMS:
pp_string (pp, "num_teams(");
if (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (clause))
@@ -4263,6 +4289,21 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
pp_string (pp, ")>");
break;
+ case OMP_DECLARE_MAPPER:
+ pp_string (pp, "#pragma omp declare mapper (");
+ if (OMP_DECLARE_MAPPER_ID (node))
+ {
+ dump_generic_node (pp, OMP_DECLARE_MAPPER_ID (node), spc, flags,
+ false);
+ pp_colon (pp);
+ }
+ dump_generic_node (pp, TREE_TYPE (node), spc, flags, false);
+ pp_space (pp);
+ dump_generic_node (pp, OMP_DECLARE_MAPPER_DECL (node), spc, flags, false);
+ pp_right_paren (pp);
+ dump_omp_clauses (pp, OMP_DECLARE_MAPPER_CLAUSES (node), spc, flags);
+ break;
+
case TRANSACTION_EXPR:
if (TRANSACTION_EXPR_OUTER (node))
pp_string (pp, "__transaction_atomic [[outer]]");
diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
index 4c048a9..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;
@@ -1226,7 +1225,8 @@ optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, tree
gimple *defstmt;
unsigned limit = param_sccvn_max_alias_queries_per_access;
do {
- if (vuse == NULL || TREE_CODE (vuse) != SSA_NAME)
+ /* If the vuse is the default definition, then there is no stores beforhand. */
+ if (SSA_NAME_IS_DEFAULT_DEF (vuse))
return false;
defstmt = SSA_NAME_DEF_STMT (vuse);
if (is_a <gphi*>(defstmt))
@@ -1323,6 +1323,7 @@ optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, tree
tree ctor = build_constructor (TREE_TYPE (dest), NULL);
gimple_assign_set_rhs_from_tree (gsip, ctor);
update_stmt (stmt);
+ statistics_counter_event (cfun, "copy zeroing propagation of aggregate", 1);
}
else /* If stmt is memcpy, transform it into memset. */
{
@@ -1332,6 +1333,7 @@ optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, tree
gimple_call_set_fntype (call, TREE_TYPE (fndecl));
gimple_call_set_arg (call, 1, val);
update_stmt (stmt);
+ statistics_counter_event (cfun, "memcpy to memset changed", 1);
}
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3384,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. */
@@ -3492,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),
@@ -3511,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);
@@ -4164,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
@@ -4401,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)
{
@@ -4440,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-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc
index 50d2ee9..aee419a 100644
--- a/gcc/tree-ssa-loop-im.cc
+++ b/gcc/tree-ssa-loop-im.cc
@@ -3307,7 +3307,8 @@ can_sm_ref_p (class loop *loop, im_mem_ref *ref)
explicitly. */
base = get_base_address (ref->mem.ref);
if ((tree_could_trap_p (ref->mem.ref)
- || (DECL_P (base) && TREE_READONLY (base)))
+ || (DECL_P (base) && TREE_READONLY (base))
+ || TREE_CODE (base) == STRING_CST)
/* ??? We can at least use false here, allowing loads? We
are forcing conditional stores if the ref is not always
stored to later anyway. So this would only guard
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 8c5908e..bf493e1 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -3525,8 +3525,9 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb,
/* tree_could_trap_p is a predicate for rvalues, so check
for readonly memory explicitly. */
|| ((base = get_base_address (lhs))
- && DECL_P (base)
- && TREE_READONLY (base)))
+ && ((DECL_P (base)
+ && TREE_READONLY (base))
+ || TREE_CODE (base) == STRING_CST)))
return false;
}
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-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-vect-slp.cc b/gcc/tree-vect-slp.cc
index fb2262a..dc89da3 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -4557,6 +4557,15 @@ vect_lower_load_permutations (loop_vec_info loop_vinfo,
if (!SLP_TREE_CHILDREN (load).is_empty ())
continue;
+ /* For single-element interleaving spanning multiple vectors avoid
+ lowering, we want to use VMAT_ELEMENTWISE later. */
+ if (ld_lanes_lanes == 0
+ && SLP_TREE_LANES (load) == 1
+ && !DR_GROUP_NEXT_ELEMENT (first)
+ && maybe_gt (group_lanes,
+ TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (load))))
+ return;
+
/* We want to pattern-match special cases here and keep those
alone. Candidates are splats and load-lane. */
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/tree.cc b/gcc/tree.cc
index 98575a5..9759c6b 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -326,6 +326,7 @@ unsigned const char omp_clause_num_ops[] =
2, /* OMP_CLAUSE_MAP */
1, /* OMP_CLAUSE_HAS_DEVICE_ADDR */
1, /* OMP_CLAUSE_DOACROSS */
+ 3, /* OMP_CLAUSE__MAPPER_BINDING_ */
2, /* OMP_CLAUSE__CACHE_ */
1, /* OMP_CLAUSE_DESTROY */
2, /* OMP_CLAUSE_INIT */
@@ -428,6 +429,7 @@ const char * const omp_clause_code_name[] =
"map",
"has_device_addr",
"doacross",
+ "_mapper_binding_",
"_cache_",
"destroy",
"init",
diff --git a/gcc/tree.def b/gcc/tree.def
index 2c37e44..0cd39f9 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -1346,6 +1346,13 @@ DEFTREECODE (OMP_STRUCTURED_BLOCK, "omp_structured_block", tcc_statement, 1)
Operand 0: OMP_MASTER_BODY: Master section body. */
DEFTREECODE (OMP_MASTER, "omp_master", tcc_statement, 1)
+/* OpenMP - #pragma omp declare mapper ([id:] type var) [clause1 ... clauseN]
+ Operand 0: Identifier.
+ Operand 1: Variable decl.
+ Operand 2: List of clauses.
+ The type of the construct is used for the type to be mapped. */
+DEFTREECODE (OMP_DECLARE_MAPPER, "omp_declare_mapper", tcc_statement, 3)
+
/* OpenACC - #pragma acc cache (variable1 ... variableN)
Operand 0: OACC_CACHE_CLAUSES: List of variables (transformed into
OMP_CLAUSE__CACHE_ clauses). */
diff --git a/gcc/tree.h b/gcc/tree.h
index 1e41316..7e4008e 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1625,6 +1625,13 @@ class auto_suppress_location_wrappers
#define OMP_METADIRECTIVE_VARIANT_BODY(v) \
TREE_VALUE (TREE_VALUE (v))
+#define OMP_DECLARE_MAPPER_ID(NODE) \
+ TREE_OPERAND (OMP_DECLARE_MAPPER_CHECK (NODE), 0)
+#define OMP_DECLARE_MAPPER_DECL(NODE) \
+ TREE_OPERAND (OMP_DECLARE_MAPPER_CHECK (NODE), 1)
+#define OMP_DECLARE_MAPPER_CLAUSES(NODE) \
+ TREE_OPERAND (OMP_DECLARE_MAPPER_CHECK (NODE), 2)
+
#define OMP_SCAN_BODY(NODE) TREE_OPERAND (OMP_SCAN_CHECK (NODE), 0)
#define OMP_SCAN_CLAUSES(NODE) TREE_OPERAND (OMP_SCAN_CHECK (NODE), 1)
@@ -2118,6 +2125,18 @@ class auto_suppress_location_wrappers
#define OMP_TARGET_DEVICE_MATCHES_PROPERTIES(NODE) \
TREE_OPERAND (OMP_TARGET_DEVICE_MATCHES_CHECK (NODE), 1)
+#define OMP_CLAUSE__MAPPER_BINDING__ID(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, \
+ OMP_CLAUSE__MAPPER_BINDING_), 0)
+
+#define OMP_CLAUSE__MAPPER_BINDING__DECL(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, \
+ OMP_CLAUSE__MAPPER_BINDING_), 1)
+
+#define OMP_CLAUSE__MAPPER_BINDING__MAPPER(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, \
+ OMP_CLAUSE__MAPPER_BINDING_), 2)
+
/* SSA_NAME accessors. */
/* Whether SSA_NAME NODE is a virtual operand. This simply caches the