aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2022-10-28 10:02:34 +0200
committerMartin Liska <mliska@suse.cz>2022-10-28 10:02:34 +0200
commit1eb021edb27e26f95cda63df121f6bc951647599 (patch)
tree7f132fded85bd7d05d81cd4c1227da2fd0c3c2d5 /gcc
parent62e475bad0d668c432bb97113cbf73fa281b8b55 (diff)
parent0607307768b66a90e27c5bc91a247acc938f070e (diff)
downloadgcc-1eb021edb27e26f95cda63df121f6bc951647599.zip
gcc-1eb021edb27e26f95cda63df121f6bc951647599.tar.gz
gcc-1eb021edb27e26f95cda63df121f6bc951647599.tar.bz2
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog231
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/analyzer/ChangeLog11
-rw-r--r--gcc/analyzer/sm-fd.cc34
-rw-r--r--gcc/analyzer/sm-fd.dot109
-rw-r--r--gcc/c-family/ChangeLog5
-rw-r--r--gcc/c-family/c-common.h24
-rw-r--r--gcc/c-family/c-warn.cc3
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/c/c-convert.cc8
-rw-r--r--gcc/c/c-decl.cc325
-rw-r--r--gcc/c/c-objc-common.cc8
-rw-r--r--gcc/c/c-parser.cc139
-rw-r--r--gcc/c/c-tree.h25
-rw-r--r--gcc/c/c-typeck.cc56
-rw-r--r--gcc/common/config/riscv/riscv-common.cc18
-rw-r--r--gcc/config/aarch64/aarch64-protos.h6
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins-base.cc56
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins-functions.h28
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins-shapes.cc8
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins-sve2.cc12
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins.cc8
-rw-r--r--gcc/config/aarch64/aarch64.cc2
-rw-r--r--gcc/config/aarch64/aarch64.h4
-rw-r--r--gcc/config/aarch64/driver-aarch64.cc4
-rw-r--r--gcc/config/bpf/bpf.cc402
-rw-r--r--gcc/config/bpf/coreout.cc5
-rw-r--r--gcc/config/bpf/coreout.h2
-rw-r--r--gcc/config/i386/i386.md45
-rwxr-xr-xgcc/config/riscv/arch-canonicalize5
-rw-r--r--gcc/config/riscv/constraints.md5
-rw-r--r--gcc/config/riscv/iterators.md6
-rw-r--r--gcc/config/riscv/riscv-builtins.cc4
-rw-r--r--gcc/config/riscv/riscv-c.cc2
-rw-r--r--gcc/config/riscv/riscv-opts.h10
-rw-r--r--gcc/config/riscv/riscv.cc21
-rw-r--r--gcc/config/riscv/riscv.md78
-rw-r--r--gcc/config/riscv/riscv.opt3
-rw-r--r--gcc/config/xtensa/xtensa.md7
-rw-r--r--gcc/cp/ChangeLog31
-rw-r--r--gcc/cp/call.cc148
-rw-r--r--gcc/cp/cp-tree.h28
-rw-r--r--gcc/cp/mangle.cc68
-rw-r--r--gcc/cp/name-lookup.cc7
-rw-r--r--gcc/cp/typeck.cc14
-rw-r--r--gcc/doc/extend.texi77
-rw-r--r--gcc/doc/invoke.texi55
-rw-r--r--gcc/doc/makefile.texi10
-rw-r--r--gcc/fortran/ChangeLog6
-rw-r--r--gcc/fortran/symbol.cc4
-rw-r--r--gcc/gimple-range-fold.cc8
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/ipa-visibility.cc8
-rw-r--r--gcc/ira.cc1
-rw-r--r--gcc/lto/ChangeLog5
-rw-r--r--gcc/lto/lto-dump.cc22
-rw-r--r--gcc/optc-save-gen.awk31
-rw-r--r--gcc/testsuite/ChangeLog108
-rw-r--r--gcc/testsuite/g++.dg/abi/lambda-ctx1-18.C4
-rw-r--r--gcc/testsuite/g++.dg/abi/lambda-ctx1-18vs17.C4
-rw-r--r--gcc/testsuite/g++.dg/abi/lambda-tpl1-17.C20
-rw-r--r--gcc/testsuite/g++.dg/abi/lambda-tpl1-18.C25
-rw-r--r--gcc/testsuite/g++.dg/abi/lambda-tpl1-18vs17.C16
-rw-r--r--gcc/testsuite/g++.dg/abi/lambda-tpl1.h59
-rw-r--r--gcc/testsuite/g++.dg/cpp23/elision4.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp23/elision7.C3
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/bad-binary-ops2.C26
-rw-r--r--gcc/testsuite/g++.dg/warn/Wdangling-pointer-2.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/Wdangling-reference1.C144
-rw-r--r--gcc/testsuite/g++.dg/warn/Wdangling-reference2.C28
-rw-r--r--gcc/testsuite/g++.dg/warn/Wdangling-reference3.C24
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/fd-3.c18
-rw-r--r--gcc/testsuite/gcc.dg/c11-enum-4.c7
-rw-r--r--gcc/testsuite/gcc.dg/c11-enum-5.c7
-rw-r--r--gcc/testsuite/gcc.dg/c11-enum-6.c8
-rw-r--r--gcc/testsuite/gcc.dg/c2x-enum-6.c167
-rw-r--r--gcc/testsuite/gcc.dg/c2x-enum-7.c97
-rw-r--r--gcc/testsuite/gcc.dg/c2x-enum-8.c7
-rw-r--r--gcc/testsuite/gcc.dg/gnu2x-enum-1.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr107394.c22
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-cond-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-bitfield-read-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-bitfield-read-2.c3
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-bitfield-read-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-bitfield-read-4.c3
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-bitfield-read-5.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-bitfield-read-6.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-bitfield-read-7.c1
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-1.c23
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-2.c23
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c34
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c37
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c37
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c37
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c56
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c36
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c35
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c33
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c45
-rw-r--r--gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c43
-rw-r--r--gcc/testsuite/gcc.target/i386/pr107172.c26
-rw-r--r--gcc/testsuite/gcc.target/riscv/_Float16-zhinx-1.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/_Float16-zhinx-2.c9
-rw-r--r--gcc/testsuite/gcc.target/riscv/_Float16-zhinx-3.c9
-rw-r--r--gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-1.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-2.c10
-rw-r--r--gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-3.c10
-rw-r--r--gcc/testsuite/gfortran.dg/illegal_boz_arg_4.f9013
-rw-r--r--gcc/tree-ssa-phiopt.cc35
-rw-r--r--gcc/value-range-storage.cc33
-rw-r--r--gcc/value-range.cc2
111 files changed, 3192 insertions, 489 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6b8ba1d..a318a22 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,234 @@
+2022-10-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/aarch64/aarch64.h (DONT_USE_BUILTIN_SETJMP): Delete.
+
+2022-10-27 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/107172
+ * config/i386/i386.md (UNSPEC_CC_NE): New.
+ Replace ne:CCC/ne:CCO with UNSPEC_CC_NE in neg patterns.
+
+2022-10-27 Andrew Pinski <apinski@marvell.com>
+
+ * tree-ssa-phiopt.cc: Include tree-ssa-dce.h
+ (replace_phi_edge_with_variable):
+ New argument, dce_ssa_names. Call simple_dce_from_worklist.
+ (match_simplify_replacement): If we inserted a sequence,
+ mark the lhs of the new sequence to be possible dce.
+ Always move the statement and mark the lhs (if it is a name)
+ as possible to remove.
+
+2022-10-27 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-protos.h: Replace constexpr with
+ CONSTEXPR.
+ * config/aarch64/aarch64-sve-builtins-base.cc: Likewise.
+ * config/aarch64/aarch64-sve-builtins-functions.h: Likewise.
+ * config/aarch64/aarch64-sve-builtins-shapes.cc: Likewise.
+ * config/aarch64/aarch64-sve-builtins-sve2.cc: Likewise.
+ * config/aarch64/aarch64-sve-builtins.cc: Likewise.
+ * config/aarch64/aarch64.cc: Likewise.
+ * config/aarch64/driver-aarch64.cc: Likewise
+
+2022-10-27 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/107394
+ * value-range-storage.cc (frange_storage_slot::get_frange): Use
+ frange constructor.
+
+2022-10-27 Thomas Schwinge <thomas@codesourcery.com>
+
+ * optc-save-gen.awk: Clarify 'Init' option property usage for
+ streaming optimization.
+
+2022-10-27 Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
+ Yvan ROUX <yvan.roux@foss.st.com>
+
+ * ira.cc: Resize array after reg number increased.
+
+2022-10-27 Jiawei <jiawei@iscas.ac.cn>
+ Sinan Lin <sinan@isrc.iscas.ac.cn>
+
+ * config/riscv/constraints.md (TARGET_ZFINX ? GR_REGS): Set GPRS
+ use while Zfinx is enable.
+ * config/riscv/riscv.cc (riscv_hard_regno_mode_ok): Limit odd
+ registers use when Zdinx enable in RV32 cases.
+ (riscv_option_override): New target enable MASK_FDIV.
+ (riscv_libgcc_floating_mode_supported_p): New error info when
+ use incompatible arch&abi.
+ (riscv_excess_precision): New target enable FLOAT16.
+
+2022-10-27 Jiawei <jiawei@iscas.ac.cn>
+
+ * config/riscv/iterators.md (TARGET_ZFINX):New target.
+ (TARGET_ZDINX): Ditto.
+ (TARGET_ZHINX): Ditto.
+ * config/riscv/riscv-builtins.cc (AVAIL): Ditto.
+ (riscv_atomic_assign_expand_fenv): Ditto.
+ * config/riscv/riscv-c.cc (riscv_cpu_cpp_builtins): Ditto.
+ * config/riscv/riscv.md: Ditto.
+
+2022-10-27 Jiawei <jiawei@iscas.ac.cn>
+ Sinan Lin <sinan@isrc.iscas.ac.cn>
+
+ * common/config/riscv/riscv-common.cc: New extensions.
+ * config/riscv/arch-canonicalize: New imply relations.
+ * config/riscv/riscv-opts.h (MASK_ZFINX): New mask.
+ (MASK_ZDINX): Ditto.
+ (MASK_ZHINX): Ditto.
+ (MASK_ZHINXMIN): Ditto.
+ (TARGET_ZFINX): New target.
+ (TARGET_ZDINX): Ditto.
+ (TARGET_ZHINX): Ditto.
+ (TARGET_ZHINXMIN): Ditto.
+ * config/riscv/riscv.opt: New target variable.
+
+2022-10-26 David Faust <david.faust@oracle.com>
+
+ * config/bpf/bpf.cc: Support __builtin_preserve_field_info.
+ (enum bpf_builtins): Add new builtin.
+ (bpf_init_builtins): Likewise.
+ (bpf_core_field_info): New function.
+ (bpf_expand_builtin): Accomodate new builtin. Refactor adding new
+ relocation to...
+ (maybe_make_core_relo): ... here. New function.
+ (bpf_resolve_overloaded_builtin): Accomodate new builtin.
+ (bpf_core_newdecl): Likewise.
+ (bpf_core_walk): Likewise.
+ (bpf_core_is_maybe_aggregate_access): Improve logic.
+ (struct core_walk_data): New.
+ * config/bpf/coreout.cc (bpf_core_reloc_add): Allow adding different
+ relocation kinds.
+ * config/bpf/coreout.h: Analogous change.
+ * doc/extend.texi: Document BPF __builtin_preserve_field_info.
+
+2022-10-26 Marek Polacek <polacek@redhat.com>
+
+ PR c++/106393
+ * doc/invoke.texi: Document -Wdangling-reference.
+
+2022-10-26 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>
+
+ * config/xtensa/xtensa.md (movdi):
+ Copy operands[0...1] to ops[0...3] and then use the latter before
+ calling xtensa_split_DI_reg_imm() and emitting insns.
+
+2022-10-26 Alexander Monakov <amonakov@ispras.ru>
+
+ PR other/107353
+ * ipa-visibility.cc (function_and_variable_visibility):
+ Conditionally upgrade TLS model instead of asserting.
+
+2022-10-26 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple-range-fold.cc (fold_using_range::fold_stmt): Check if
+ stmt is non-negative and adjust the range.
+
+2022-10-26 Martin Liska <mliska@suse.cz>
+
+ * common/config/i386/cpuinfo.h (has_cpu_feature): Add comment.
+ (reset_cpu_feature): New.
+ (get_zhaoxin_cpu): Use reset_cpu_feature.
+
+2022-10-26 Ju-Zhe Zhong <juzhe.zhong@rivai.ai>
+
+ * config/riscv/riscv.cc (riscv_expand_epilogue): Fix statement.
+
+2022-10-26 Ju-Zhe Zhong <juzhe.zhong@rivai.ai>
+
+ PR target/107357
+ * config/riscv/riscv-modes.def (VECTOR_BOOL_MODE): Set to minimum size.
+ (ADJUST_NUNITS): Adjust according to -march.
+ (ADJUST_BYTESIZE): Ditto.
+ * config/riscv/riscv-protos.h (riscv_v_ext_enabled_vector_mode_p):
+ Remove.
+ (riscv_v_ext_vector_mode_p): Change function implementation.
+ * config/riscv/riscv-vector-builtins.cc (rvv_switcher::rvv_switcher):
+ Change to riscv_v_ext_vector_mode_p.
+ (register_builtin_type): Ditto.
+ * config/riscv/riscv.cc (riscv_v_ext_vector_mode_p): Change to enabled
+ modes.
+ (ENTRY): Ditto.
+ (riscv_v_ext_enabled_vector_mode_p): Remove.
+ (riscv_v_adjust_nunits): New function.
+ (riscv_vector_mode_supported_p): Use riscv_v_ext_vector_mode_p instead.
+ * config/riscv/riscv.h (riscv_v_adjust_nunits): New function.
+
+2022-10-26 Ju-Zhe Zhong <juzhe.zhong@rivai.ai>
+
+ * config.gcc (riscv*): Add riscv-v.o to extra_objs.
+ * config/riscv/constraints.md (vu): New constraint.
+ (vi): Ditto.
+ (Wc0): Ditto.
+ (Wc1): Ditto.
+ * config/riscv/predicates.md (vector_length_operand): New.
+ (reg_or_mem_operand): Ditto.
+ (vector_move_operand): Ditto.
+ (vector_mask_operand): Ditto.
+ (vector_merge_operand): Ditto.
+ * config/riscv/riscv-protos.h (riscv_regmode_natural_size) New.
+ (riscv_vector::const_vec_all_same_in_range_p): Ditto.
+ (riscv_vector::legitimize_move): Ditto.
+ (tail_policy): Ditto.
+ (mask_policy): Ditto.
+ * config/riscv/riscv-v.cc: New.
+ * config/riscv/riscv-vector-builtins-bases.cc
+ (vsetvl::expand): Refactor how LMUL encoding.
+ * config/riscv/riscv.cc (riscv_print_operand): Update how LMUL
+ print and mask operand print.
+ (riscv_regmode_natural_size): New.
+ * config/riscv/riscv.h (REGMODE_NATURAL_SIZE): New.
+ * config/riscv/riscv.md (mode): Add vector modes.
+ * config/riscv/t-riscv (riscv-v.o) New.
+ * config/riscv/vector-iterators.md: New.
+ * config/riscv/vector.md (vundefined<mode>): New.
+ (mov<mode>): New.
+ (*mov<mode>): New.
+ (@vsetvl<mode>_no_side_effects): New.
+ (@pred_mov<mode>): New.
+
+2022-10-26 Monk Chiang <monk.chiang@sifive.com>
+
+ * common/config/riscv/riscv-common.cc (riscv_ext_version_table):
+ Add svinval and svnapot extension.
+ (riscv_ext_flag_table): Ditto.
+ * config/riscv/riscv-opts.h (MASK_SVINVAL): New.
+ (MASK_SVNAPOT): Ditto.
+ (TARGET_SVINVAL): Ditto.
+ (TARGET_SVNAPOT): Ditto.
+ * config/riscv/riscv.opt (riscv_sv_subext): New.
+
+2022-10-26 Ju-Zhe Zhong <juzhe.zhong@rivai.ai>
+
+ * config/riscv/riscv-modes.def: Adjust table indentation in commnet.
+
+2022-10-26 Martin Liska <mliska@suse.cz>
+
+ * configure: Regenerate.
+
+2022-10-26 Aldy Hernandez <aldyh@redhat.com>
+
+ * value-range.cc (frange::set): Use HONOR_*.
+ (frange::verify_range): Same.
+ * value-range.h (frange_val_min): Same.
+ (frange_val_max): Same.
+
+2022-10-26 Jiufu Guo <guojiufu@linux.ibm.com>
+
+ PR target/106460
+ * config/rs6000/rs6000.cc (rs6000_cannot_force_const_mem): Return true
+ for HIGH code rtx.
+
+2022-10-26 Kito Cheng <kito.cheng@sifive.com>
+
+ * common/config/riscv/riscv-common.cc (riscv_ext_version_table):
+ Add `h`.
+ (riscv_supported_std_ext): Ditto.
+ (multi_letter_subset_rank): Remove `h`.
+ (riscv_subset_list::parse_std_ext): Handle `h` as single letter
+ extension.
+ (riscv_subset_list::parse): Ditto.
+
2022-10-25 Eugene Rozenfeld <erozen@microsoft.com>
* auto-profile.cc (get_combined_location): Include discriminator in the
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 03e9228..7109ae3 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20221026
+20221028
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index 733580a..6e6b056 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,14 @@
+2022-10-26 David Malcolm <dmalcolm@redhat.com>
+
+ * sm-fd.cc (fd_state_machine::on_open): Transition to "unchecked"
+ when the mode is symbolic, rather than just on integer constants.
+ (fd_state_machine::check_for_open_fd): Don't complain about
+ unchecked values in the start state.
+
+2022-10-26 David Malcolm <dmalcolm@redhat.com>
+
+ * sm-fd.dot: New file.
+
2022-10-24 David Malcolm <dmalcolm@redhat.com>
PR analyzer/107349
diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc
index 8a4c208..ae846cd 100644
--- a/gcc/analyzer/sm-fd.cc
+++ b/gcc/analyzer/sm-fd.cc
@@ -940,25 +940,25 @@ fd_state_machine::on_open (sm_context *sm_ctxt, const supernode *node,
if (lhs)
{
tree arg = gimple_call_arg (call, 1);
+ enum access_mode mode = READ_WRITE;
if (TREE_CODE (arg) == INTEGER_CST)
{
int flag = TREE_INT_CST_LOW (arg);
- enum access_mode mode = get_access_mode_from_flag (flag);
-
- switch (mode)
- {
- case READ_ONLY:
- sm_ctxt->on_transition (node, stmt, lhs, m_start,
- m_unchecked_read_only);
- break;
- case WRITE_ONLY:
- sm_ctxt->on_transition (node, stmt, lhs, m_start,
- m_unchecked_write_only);
- break;
- default:
- sm_ctxt->on_transition (node, stmt, lhs, m_start,
- m_unchecked_read_write);
- }
+ mode = get_access_mode_from_flag (flag);
+ }
+ switch (mode)
+ {
+ case READ_ONLY:
+ sm_ctxt->on_transition (node, stmt, lhs, m_start,
+ m_unchecked_read_only);
+ break;
+ case WRITE_ONLY:
+ sm_ctxt->on_transition (node, stmt, lhs, m_start,
+ m_unchecked_write_only);
+ break;
+ default:
+ sm_ctxt->on_transition (node, stmt, lhs, m_start,
+ m_unchecked_read_write);
}
}
else
@@ -1096,7 +1096,7 @@ fd_state_machine::check_for_open_fd (
else
{
- if (!(is_valid_fd_p (state) || (state == m_stop)))
+ if (!(is_valid_fd_p (state) || state == m_start || state == m_stop))
{
if (!is_constant_fd_p (state))
sm_ctxt->warn (
diff --git a/gcc/analyzer/sm-fd.dot b/gcc/analyzer/sm-fd.dot
new file mode 100644
index 0000000..175daae
--- /dev/null
+++ b/gcc/analyzer/sm-fd.dot
@@ -0,0 +1,109 @@
+/* An overview of the state machine from sm-fd.cc.
+ Copyright (C) 2022 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* Keep this in-sync with sm-dot.cc */
+
+digraph "fd" {
+
+ /* STATES. */
+
+ /* Start state. */
+ start;
+
+ /* States representing a file descriptor that hasn't yet been
+ checked for validity after opening, for three different
+ access modes. */
+ unchecked_read_write;
+ unchecked_read_only;
+ unchecked_write_only;
+
+ /* States for representing a file descriptor that is known to be valid (>=
+ 0), for three different access modes. */
+ valid_read_write;
+ valid_read_only;
+ valid_write_only;
+
+ /* State for a file descriptor that is known to be invalid (< 0). */
+ invalid;
+
+ /* State for a file descriptor that has been closed. */
+ closed;
+
+ /* State for a file descriptor that we do not want to track anymore . */
+ stop;
+
+ /* TRANSITIONS. */
+
+ /* On "open". */
+ start -> unchecked_read_only [label="on 'X = open(..., O_RDONLY);'"];
+ start -> unchecked_write_only [label="on 'X = open(..., O_WRONLY);'"];
+ start -> unchecked_read_write [label="on 'X = open(..., ...);'"];
+
+ /* On "creat". */
+ start -> unchecked_write_only [label="on 'X = create(...);'"];
+
+ /* On "close". */
+ start -> closed [label="on 'close(X);'"];
+ unchecked_read_write -> closed [label="on 'close(X);'"];
+ unchecked_read_only -> closed [label="on 'close(X);'"];
+ unchecked_write_only -> closed [label="on 'close(X);'"];
+ valid_read_write -> closed [label="on 'close(X);'"];
+ valid_read_only -> closed [label="on 'close(X);'"];
+ valid_write_only -> closed [label="on 'close(X);'"];
+ constant_fd -> closed [label="on 'close(X);'"];
+ closed -> stop [label="on 'close(X);':\nWarn('double close')"];
+
+ /* On "read". */
+ closed -> closed [label="on 'read(X);':\nWarn('use after close')"];
+ unchecked_read_write -> unchecked_read_write [label="on 'read(X);:\nWarn('use without check')'"];
+ unchecked_read_only -> unchecked_read_only [label="on 'read(X);:\nWarn('use without check')'"];
+ unchecked_write_only -> unchecked_write_only [label="on 'read(X);:\nWarn('use without check')'"];
+ valid_write_only -> valid_write_only [label="on 'read(X);:\nWarn('access mode mismatch')'"];
+
+ /* On "write". */
+ closed -> closed [label="on 'write(X);':\nWarn('use after close')"];
+ unchecked_read_write -> unchecked_read_write [label="on 'write(X);:\nWarn('use without check')'"];
+ unchecked_read_only -> unchecked_read_only [label="on 'write(X);:\nWarn('use without check')'"];
+ unchecked_write_only -> unchecked_write_only [label="on 'write(X);:\nWarn('use without check')'"];
+ valid_read_only -> valid_read_only [label="on 'write(X);:\nWarn('access mode mismatch')'"];
+
+ /* On "dup". */
+ closed -> closed [label="on 'dup(X);':\nWarn('use after close')"];
+ /* plus stuff for the new fd. */
+
+ /* On "pipe". */
+ start -> valid_read_write [label="when 'pipe()' succeeds"];
+
+ /* on_condition. */
+ unchecked_read_write -> valid_read_write [label="on 'X >= 0'"];
+ unchecked_read_only -> valid_read_only [label="on 'X >= 0'"];
+ unchecked_write_only -> valid_write_only [label="on 'X >= 0'"];
+ unchecked_read_write -> invalid [label="on 'X < 0'"];
+ unchecked_read_only -> invalid [label="on 'X < 0'"];
+ unchecked_write_only -> invalid [label="on 'X < 0'"];
+
+ /* Leaks. */
+ unchecked_read_write -> stop [label="on leak:\nWarn('leak')"];
+ unchecked_read_only -> stop [label="on leak:\nWarn('leak')"];
+ unchecked_write_only -> stop [label="on leak:\nWarn('leak')"];
+ valid_read_write -> stop [label="on leak:\nWarn('leak')"];
+ valid_read_only -> stop [label="on leak:\nWarn('leak')"];
+ valid_write_only -> stop [label="on leak:\nWarn('leak')"];
+}
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index bb85e78..ee7b511 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,8 @@
+2022-10-26 Marek Polacek <polacek@redhat.com>
+
+ PR c++/106393
+ * c.opt (Wdangling-reference): New.
+
2022-10-19 Joseph Myers <joseph@codesourcery.com>
* c-format.h (enum format_lengths): Add FMT_LEN_w8, FMT_LEN_w16,
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 62ab4ba..f9d0d29 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1004,6 +1004,30 @@ extern void c_parse_final_cleanups (void);
/* True iff TYPE is cv decltype(nullptr). */
#define NULLPTR_TYPE_P(TYPE) (TREE_CODE (TYPE) == NULLPTR_TYPE)
+/* Returns the underlying type of the given enumeration type. The
+ underlying type is determined in different ways, depending on the
+ properties of the enum:
+
+ - In C++0x or C2x, the underlying type can be explicitly specified, e.g.,
+
+ enum E1 : char { ... } // underlying type is char
+
+ - In a C++0x scoped enumeration, the underlying type is int
+ unless otherwises specified:
+
+ enum class E2 { ... } // underlying type is int
+
+ - Otherwise, the underlying type is determined based on the
+ values of the enumerators. In this case, the
+ ENUM_UNDERLYING_TYPE will not be set until after the definition
+ of the enumeration is completed by finish_enum. */
+#define ENUM_UNDERLYING_TYPE(TYPE) \
+ TREE_TYPE (ENUMERAL_TYPE_CHECK (TYPE))
+
+/* Determines whether an ENUMERAL_TYPE has an explicit
+ underlying type. */
+#define ENUM_FIXED_UNDERLYING_TYPE_P(NODE) (TYPE_LANG_FLAG_5 (NODE))
+
extern tree do_case (location_t, tree, tree, tree);
extern tree build_stmt (location_t, enum tree_code, ...);
extern tree build_real_imag_expr (location_t, enum tree_code, tree);
diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index 6742f44..cd59c3c 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -1415,7 +1415,8 @@ warnings_for_convert_and_check (location_t loc, tree type, tree expr,
if (TREE_CODE (expr) == INTEGER_CST
&& (TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
+ || (TREE_CODE (type) == ENUMERAL_TYPE
+ && TREE_CODE (ENUM_UNDERLYING_TYPE (type)) != BOOLEAN_TYPE))
&& !int_fits_type_p (expr, type))
{
/* Do not diagnose overflow in a constant expression merely
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 01d4807..070f85c 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -555,6 +555,10 @@ Wdangling-pointer=
C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_dangling_pointer) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall, 2, 0) IntegerRange(0, 2)
Warn for uses of pointers to auto variables whose lifetime has ended.
+Wdangling-reference
+C++ ObjC++ Var(warn_dangling_reference) Warning LangEnabledBy(C++ ObjC++, Wall)
+Warn when a reference is bound to a temporary whose lifetime has ended.
+
Wdate-time
C ObjC C++ ObjC++ CPP(warn_date_time) CppReason(CPP_W_DATE_TIME) Var(cpp_warn_date_time) Init(0) Warning
Warn about __TIME__, __DATE__ and __TIMESTAMP__ usage.
diff --git a/gcc/c/c-convert.cc b/gcc/c/c-convert.cc
index 6e74913..8a43e5f 100644
--- a/gcc/c/c-convert.cc
+++ b/gcc/c/c-convert.cc
@@ -110,8 +110,13 @@ c_convert (tree type, tree expr, bool init_const)
case VOID_TYPE:
return fold_convert_loc (loc, type, e);
- case INTEGER_TYPE:
case ENUMERAL_TYPE:
+ if (ENUM_UNDERLYING_TYPE (type) != NULL_TREE
+ && TREE_CODE (ENUM_UNDERLYING_TYPE (type)) == BOOLEAN_TYPE)
+ goto convert_to_boolean;
+ gcc_fallthrough ();
+
+ case INTEGER_TYPE:
if (sanitize_flags_p (SANITIZE_FLOAT_CAST)
&& current_function_decl != NULL_TREE
&& TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
@@ -129,6 +134,7 @@ c_convert (tree type, tree expr, bool init_const)
goto maybe_fold;
case BOOLEAN_TYPE:
+ convert_to_boolean:
return fold_convert_loc
(loc, type, c_objc_common_truthvalue_conversion (input_location, expr));
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 4746e31..2b83900 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -4817,7 +4817,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
else if (declspecs->typespec_kind != ctsk_tagdef
&& declspecs->typespec_kind != ctsk_tagfirstref
&& declspecs->typespec_kind != ctsk_tagfirstref_attrs
- && code == ENUMERAL_TYPE)
+ && code == ENUMERAL_TYPE
+ && !declspecs->enum_type_specifier_ref_p)
{
bool warned_enum = false;
if (warned != 1)
@@ -4883,6 +4884,38 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
warned = 1;
}
+ if (declspecs->enum_type_specifier_ref_p && !warned)
+ {
+ if (declspecs->storage_class != csc_none)
+ {
+ error ("storage class specifier in empty declaration with %<enum%> "
+ "underlying type");
+ warned = 1;
+ }
+ else if (declspecs->thread_p)
+ {
+ error ("%qs in empty declaration with %<enum%> underlying type",
+ declspecs->thread_gnu_p ? "__thread" : "_Thread_local");
+ warned = 1;
+ }
+ else if (declspecs->const_p
+ || declspecs->volatile_p
+ || declspecs->atomic_p
+ || declspecs->restrict_p
+ || declspecs->address_space)
+ {
+ error ("type qualifier in empty declaration with %<enum%> "
+ "underlying type");
+ warned = 1;
+ }
+ else if (declspecs->alignas_p)
+ {
+ error ("%<alignas%> in empty declaration with %<enum%> "
+ "underlying type");
+ warned = 1;
+ }
+ }
+
if (!warned && !in_system_header_at (input_location)
&& declspecs->storage_class != csc_none)
{
@@ -6496,6 +6529,16 @@ grokdeclarator (const struct c_declarator *declarator,
}
}
+ /* An enum type specifier (": specifier-qualifier-list") may only be
+ specified when the enum is being defined or in an empty
+ declaration of the form "enum identifier enum-type-specifier;".
+ Except for the case of an empty declaration that has additional
+ declaration specifiers, all invalid contexts (declarations that
+ aren't empty, type names, parameter declarations, member
+ declarations) pass through grokdeclarator. */
+ if (declspecs->enum_type_specifier_ref_p)
+ error_at (loc, "%<enum%> underlying type may not be specified here");
+
/* A function definition's declarator must have the form of
a function declarator. */
@@ -8285,12 +8328,15 @@ get_parm_info (bool ellipsis, tree expr)
Define the tag as a forward-reference with location LOC if it is
not defined. HAVE_STD_ATTRS says whether any standard attributes
were present after the struct, union or enum keyword; ATTRS are the
- standard attributes present there. Return a c_typespec structure
- for the type specifier. */
+ standard attributes present there. HAS_ENUM_TYPE_SPECIFIER says
+ whether an enum type specifier (": specifier-qualifier-list") is
+ present; if so, this is called before that specifier is parsed, so
+ that the tag is in scope for that specifier. Return a c_typespec
+ structure for the type specifier. */
struct c_typespec
parser_xref_tag (location_t loc, enum tree_code code, tree name,
- bool have_std_attrs, tree attrs)
+ bool have_std_attrs, tree attrs, bool has_enum_type_specifier)
{
struct c_typespec ret;
tree ref;
@@ -8298,11 +8344,13 @@ parser_xref_tag (location_t loc, enum tree_code code, tree name,
ret.expr = NULL_TREE;
ret.expr_const_operands = true;
+ ret.has_enum_type_specifier = has_enum_type_specifier;
- /* If a cross reference is requested, look up the type
- already defined for this tag and return it. */
+ /* If a cross reference is requested, look up the type already
+ defined for this tag and return it. If an enum type specifier is
+ present, only a definition in the current scope is relevant. */
- ref = lookup_tag (code, name, false, &refloc);
+ ref = lookup_tag (code, name, has_enum_type_specifier, &refloc);
/* If this is the right type of tag, return what we found.
(This reference will be shadowed by shadow_tag later if appropriate.)
If this is the wrong type of tag, do not return it. If it was the
@@ -8371,6 +8419,7 @@ parser_xref_tag (location_t loc, enum tree_code code, tree name,
TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
+ ENUM_FIXED_UNDERLYING_TYPE_P (ref) = has_enum_type_specifier;
}
pushtag (loc, name, ref);
@@ -8387,7 +8436,8 @@ parser_xref_tag (location_t loc, enum tree_code code, tree name,
tree
xref_tag (enum tree_code code, tree name)
{
- return parser_xref_tag (input_location, code, name, false, NULL_TREE).spec;
+ return parser_xref_tag (input_location, code, name, false, NULL_TREE,
+ false).spec;
}
/* Make sure that the tag NAME is defined *in the current scope*
@@ -9288,12 +9338,15 @@ layout_array_type (tree t)
/* Begin compiling the definition of an enumeration type.
NAME is its name (or null if anonymous).
LOC is the enum's location.
+ FIXED_UNDERLYING_TYPE is the (C2x) underlying type specified in the
+ definition.
Returns the type object, as yet incomplete.
Also records info about it so that build_enumerator
may be used to declare the individual values as they are read. */
tree
-start_enum (location_t loc, struct c_enum_contents *the_enum, tree name)
+start_enum (location_t loc, struct c_enum_contents *the_enum, tree name,
+ tree fixed_underlying_type)
{
tree enumtype = NULL_TREE;
location_t enumloc = UNKNOWN_LOCATION;
@@ -9309,6 +9362,23 @@ start_enum (location_t loc, struct c_enum_contents *the_enum, tree name)
{
enumtype = make_node (ENUMERAL_TYPE);
pushtag (loc, name, enumtype);
+ if (fixed_underlying_type != NULL_TREE)
+ {
+ /* For an enum definition with a fixed underlying type, the
+ type is complete during the definition and the
+ enumeration constants have that type. If there was a
+ tag, the type was completed in c_parser_enum_specifier.
+ If not, it must be completed here. */
+ ENUM_FIXED_UNDERLYING_TYPE_P (enumtype) = true;
+ TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (fixed_underlying_type);
+ TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (fixed_underlying_type);
+ TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (fixed_underlying_type);
+ SET_TYPE_ALIGN (enumtype, TYPE_ALIGN (fixed_underlying_type));
+ TYPE_SIZE (enumtype) = NULL_TREE;
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (fixed_underlying_type);
+ ENUM_UNDERLYING_TYPE (enumtype) = fixed_underlying_type;
+ layout_type (enumtype);
+ }
}
/* Update type location to the one of the definition, instead of e.g.
a forward declaration. */
@@ -9336,10 +9406,16 @@ start_enum (location_t loc, struct c_enum_contents *the_enum, tree name)
TYPE_VALUES (enumtype) = NULL_TREE;
}
+ if (ENUM_FIXED_UNDERLYING_TYPE_P (enumtype)
+ && fixed_underlying_type == NULL_TREE)
+ error_at (loc, "%<enum%> declared with but defined without "
+ "fixed underlying type");
+
the_enum->enum_next_value = integer_zero_node;
+ the_enum->enum_type = enumtype;
the_enum->enum_overflow = 0;
- if (flag_short_enums)
+ if (flag_short_enums && !ENUM_FIXED_UNDERLYING_TYPE_P (enumtype))
for (tree v = TYPE_MAIN_VARIANT (enumtype); v; v = TYPE_NEXT_VARIANT (v))
TYPE_PACKED (v) = 1;
@@ -9403,54 +9479,61 @@ finish_enum (tree enumtype, tree values, tree attributes)
(tree_int_cst_lt (minnode, TYPE_MIN_VALUE (integer_type_node))
|| tree_int_cst_lt (TYPE_MAX_VALUE (integer_type_node), maxnode));
- /* If the precision of the type was specified with an attribute and it
- was too small, give an error. Otherwise, use it. */
- if (TYPE_PRECISION (enumtype) && lookup_attribute ("mode", attributes))
+
+ if (!ENUM_FIXED_UNDERLYING_TYPE_P (enumtype))
{
- if (precision > TYPE_PRECISION (enumtype))
+ /* If the precision of the type was specified with an attribute and it
+ was too small, give an error. Otherwise, use it. */
+ if (TYPE_PRECISION (enumtype) && lookup_attribute ("mode", attributes))
{
- TYPE_PRECISION (enumtype) = 0;
- error ("specified mode too small for enumerated values");
+ if (precision > TYPE_PRECISION (enumtype))
+ {
+ TYPE_PRECISION (enumtype) = 0;
+ error ("specified mode too small for enumerated values");
+ }
+ else
+ precision = TYPE_PRECISION (enumtype);
}
else
- precision = TYPE_PRECISION (enumtype);
- }
- else
- TYPE_PRECISION (enumtype) = 0;
-
- if (TYPE_PACKED (enumtype)
- || precision > TYPE_PRECISION (integer_type_node)
- || TYPE_PRECISION (enumtype))
- {
- tem = c_common_type_for_size (precision, sign == UNSIGNED ? 1 : 0);
- if (tem == NULL)
- {
- /* This should only occur when both signed and unsigned
- values of maximum precision occur among the
- enumerators. */
- pedwarn (input_location, 0,
- "enumeration values exceed range of largest integer");
- tem = widest_integer_literal_type_node;
- }
- else if (precision > TYPE_PRECISION (intmax_type_node)
- && !tree_int_cst_lt (minnode, TYPE_MIN_VALUE (intmax_type_node))
- && !tree_int_cst_lt (TYPE_MAX_VALUE (uintmax_type_node),
- maxnode))
- pedwarn (input_location, OPT_Wpedantic,
- "enumeration values exceed range of %qs",
- sign == UNSIGNED ? "uintmax_t" : "intmax_t");
- }
- else
- tem = sign == UNSIGNED ? unsigned_type_node : integer_type_node;
+ TYPE_PRECISION (enumtype) = 0;
+
+ if (TYPE_PACKED (enumtype)
+ || precision > TYPE_PRECISION (integer_type_node)
+ || TYPE_PRECISION (enumtype))
+ {
+ tem = c_common_type_for_size (precision, sign == UNSIGNED ? 1 : 0);
+ if (tem == NULL)
+ {
+ /* This should only occur when both signed and unsigned
+ values of maximum precision occur among the
+ enumerators. */
+ pedwarn (input_location, 0,
+ "enumeration values exceed range of largest integer");
+ tem = widest_integer_literal_type_node;
+ }
+ else if (precision > TYPE_PRECISION (intmax_type_node)
+ && !tree_int_cst_lt (minnode,
+ TYPE_MIN_VALUE (intmax_type_node))
+ && !tree_int_cst_lt (TYPE_MAX_VALUE (uintmax_type_node),
+ maxnode))
+ pedwarn (input_location, OPT_Wpedantic,
+ "enumeration values exceed range of %qs",
+ sign == UNSIGNED ? "uintmax_t" : "intmax_t");
+ }
+ else
+ tem = sign == UNSIGNED ? unsigned_type_node : integer_type_node;
- TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem);
- TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem);
- TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem);
- SET_TYPE_ALIGN (enumtype, TYPE_ALIGN (tem));
- TYPE_SIZE (enumtype) = NULL_TREE;
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem);
+ TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem);
+ TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem);
+ TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem);
+ SET_TYPE_ALIGN (enumtype, TYPE_ALIGN (tem));
+ TYPE_SIZE (enumtype) = NULL_TREE;
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem);
+ ENUM_UNDERLYING_TYPE (enumtype) =
+ c_common_type_for_size (TYPE_PRECISION (tem), TYPE_UNSIGNED (tem));
- layout_type (enumtype);
+ layout_type (enumtype);
+ }
if (values != error_mark_node)
{
@@ -9477,8 +9560,10 @@ finish_enum (tree enumtype, tree values, tree attributes)
fit in int are given type int in build_enumerator (which
is the correct type while the enumeration is being
parsed), so no conversions are needed here if all
- enumerators fit in int. */
- if (wider_than_int)
+ enumerators fit in int. If the enum has a fixed
+ underlying type, the correct type was also given in
+ build_enumerator. */
+ if (!ENUM_FIXED_UNDERLYING_TYPE_P (enumtype) && wider_than_int)
ini = convert (enumtype, ini);
DECL_INITIAL (enu) = ini;
@@ -9516,6 +9601,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
TYPE_UNSIGNED (tem) = TYPE_UNSIGNED (enumtype);
TYPE_LANG_SPECIFIC (tem) = TYPE_LANG_SPECIFIC (enumtype);
+ ENUM_UNDERLYING_TYPE (tem) = ENUM_UNDERLYING_TYPE (enumtype);
}
/* Finish debugging output for this type. */
@@ -9595,56 +9681,89 @@ build_enumerator (location_t decl_loc, location_t loc,
if (the_enum->enum_overflow)
error_at (loc, "overflow in enumeration values");
}
- /* Even though the underlying type of an enum is unspecified, the
- type of enumeration constants is explicitly defined as int
- (6.4.4.3/2 in the C99 Standard). C2X allows any integer type, and
- GCC allows such types for older standards as an extension. */
- bool warned_range = false;
- if (!int_fits_type_p (value,
- (TYPE_UNSIGNED (TREE_TYPE (value))
- ? uintmax_type_node
- : intmax_type_node)))
- /* GCC does not consider its types larger than intmax_t to be
- extended integer types (although C2X would permit such types to
- be considered extended integer types if all the features
- required by <stdint.h> and <inttypes.h> macros, such as support
- for integer constants and I/O, were present), so diagnose if
- such a wider type is used. (If the wider type arose from a
- constant of such a type, that will also have been diagnosed,
- but this is the only diagnostic in the case where it arises
- from choosing a wider type automatically when adding 1
- overflows.) */
- warned_range = pedwarn (loc, OPT_Wpedantic,
- "enumerator value outside the range of %qs",
+ if (ENUM_FIXED_UNDERLYING_TYPE_P (the_enum->enum_type))
+ {
+ /* Enumeration constants must fit in the fixed underlying type. */
+ if (!int_fits_type_p (value, ENUM_UNDERLYING_TYPE (the_enum->enum_type)))
+ error_at (loc,
+ "enumerator value outside the range of underlying type");
+ /* Enumeration constants for an enum with fixed underlying type
+ have the enum type, both inside and outside the
+ definition. */
+ value = convert (the_enum->enum_type, value);
+ }
+ else
+ {
+ /* Even though the underlying type of an enum is unspecified, the
+ type of enumeration constants is explicitly defined as int
+ (6.4.4.3/2 in the C99 Standard). C2X allows any integer type, and
+ GCC allows such types for older standards as an extension. */
+ bool warned_range = false;
+ if (!int_fits_type_p (value,
(TYPE_UNSIGNED (TREE_TYPE (value))
- ? "uintmax_t"
- : "intmax_t"));
- if (!warned_range && !int_fits_type_p (value, integer_type_node))
- pedwarn_c11 (loc, OPT_Wpedantic,
- "ISO C restricts enumerator values to range of %<int%> "
- "before C2X");
-
- /* The ISO C Standard mandates enumerators to have type int before
- C2X, even though the underlying type of an enum type is
- unspecified. C2X allows enumerators of any integer type. During
- the parsing of the enumeration, C2X specifies that constants
- representable in int have type int, constants not representable
- in int have the type of the given expression if any, and
- constants not representable in int and derived by adding 1 to the
- previous constant have the type of that constant unless the
- addition would overflow or wraparound, in which case a wider type
- of the same signedness is chosen automatically; after the
- enumeration is parsed, all the constants have the type of the
- enumeration if any do not fit in int. */
- if (int_fits_type_p (value, integer_type_node))
- value = convert (integer_type_node, value);
+ ? uintmax_type_node
+ : intmax_type_node)))
+ /* GCC does not consider its types larger than intmax_t to be
+ extended integer types (although C2X would permit such types to
+ be considered extended integer types if all the features
+ required by <stdint.h> and <inttypes.h> macros, such as support
+ for integer constants and I/O, were present), so diagnose if
+ such a wider type is used. (If the wider type arose from a
+ constant of such a type, that will also have been diagnosed,
+ but this is the only diagnostic in the case where it arises
+ from choosing a wider type automatically when adding 1
+ overflows.) */
+ warned_range = pedwarn (loc, OPT_Wpedantic,
+ "enumerator value outside the range of %qs",
+ (TYPE_UNSIGNED (TREE_TYPE (value))
+ ? "uintmax_t"
+ : "intmax_t"));
+ if (!warned_range && !int_fits_type_p (value, integer_type_node))
+ pedwarn_c11 (loc, OPT_Wpedantic,
+ "ISO C restricts enumerator values to range of %<int%> "
+ "before C2X");
+
+ /* The ISO C Standard mandates enumerators to have type int before
+ C2X, even though the underlying type of an enum type is
+ unspecified. C2X allows enumerators of any integer type. During
+ the parsing of the enumeration, C2X specifies that constants
+ representable in int have type int, constants not representable
+ in int have the type of the given expression if any, and
+ constants not representable in int and derived by adding 1 to the
+ previous constant have the type of that constant unless the
+ addition would overflow or wraparound, in which case a wider type
+ of the same signedness is chosen automatically; after the
+ enumeration is parsed, all the constants have the type of the
+ enumeration if any do not fit in int. */
+ if (int_fits_type_p (value, integer_type_node))
+ value = convert (integer_type_node, value);
+ }
/* Set basis for default for next value. */
- the_enum->enum_next_value
- = build_binary_op (EXPR_LOC_OR_LOC (value, input_location),
- PLUS_EXPR, value, integer_one_node, false);
+ if (ENUM_FIXED_UNDERLYING_TYPE_P (the_enum->enum_type))
+ {
+ tree underlying_type = ENUM_UNDERLYING_TYPE (the_enum->enum_type);
+ if (TREE_CODE (underlying_type) == BOOLEAN_TYPE)
+ /* A value of 2 following a value of 1 overflows bool, but we
+ cannot carry out addition directly on bool without
+ promotion, and converting the result of arithmetic in a
+ wider type back to bool would not produce the right result
+ for this overflow check. */
+ the_enum->enum_next_value = invert_truthvalue_loc (loc, value);
+ else
+ the_enum->enum_next_value
+ = build_binary_op (EXPR_LOC_OR_LOC (value, input_location),
+ PLUS_EXPR, convert (underlying_type, value),
+ convert (underlying_type, integer_one_node),
+ false);
+ }
+ else
+ the_enum->enum_next_value
+ = build_binary_op (EXPR_LOC_OR_LOC (value, input_location),
+ PLUS_EXPR, value, integer_one_node, false);
the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value);
- if (the_enum->enum_overflow)
+ if (the_enum->enum_overflow
+ && !ENUM_FIXED_UNDERLYING_TYPE_P (the_enum->enum_type))
{
/* Choose a wider type with the same signedness if
available. */
@@ -9691,7 +9810,8 @@ c_simulate_enum_decl (location_t loc, const char *name,
input_location = loc;
struct c_enum_contents the_enum;
- tree enumtype = start_enum (loc, &the_enum, get_identifier (name));
+ tree enumtype = start_enum (loc, &the_enum, get_identifier (name),
+ NULL_TREE);
tree value_chain = NULL_TREE;
string_int_pair *value;
@@ -11980,6 +12100,9 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
}
}
specs->type = type;
+ if (spec.has_enum_type_specifier
+ && spec.kind != ctsk_tagdef)
+ specs->enum_type_specifier_ref_p = true;
}
return specs;
diff --git a/gcc/c/c-objc-common.cc b/gcc/c/c-objc-common.cc
index b468091..1a8b162 100644
--- a/gcc/c/c-objc-common.cc
+++ b/gcc/c/c-objc-common.cc
@@ -387,13 +387,7 @@ c_get_alias_set (tree t)
/* Allow aliasing between enumeral types and the underlying
integer type. This is required since those are compatible types. */
if (TREE_CODE (t) == ENUMERAL_TYPE)
- {
- tree t1 = c_common_type_for_size (tree_to_uhwi (TYPE_SIZE (t)),
- /* short-cut commoning to signed
- type. */
- false);
- return get_alias_set (t1);
- }
+ return get_alias_set (ENUM_UNDERLYING_TYPE (t));
return c_common_get_alias_set (t);
}
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 602e023..5bdcd93 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -3011,6 +3011,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
}
t.expr = NULL_TREE;
t.expr_const_operands = true;
+ t.has_enum_type_specifier = false;
declspecs_add_type (name_token->location, specs, t);
continue;
}
@@ -3027,6 +3028,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
t.expr = NULL_TREE;
t.expr_const_operands = true;
+ t.has_enum_type_specifier = false;
declspecs_add_type (loc, specs, t);
continue;
}
@@ -3087,6 +3089,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
t.spec = c_parser_peek_token (parser)->value;
t.expr = NULL_TREE;
t.expr_const_operands = true;
+ t.has_enum_type_specifier = false;
declspecs_add_type (loc, specs, t);
c_parser_consume_token (parser);
break;
@@ -3151,6 +3154,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
t.spec = error_mark_node;
t.expr = NULL_TREE;
t.expr_const_operands = true;
+ t.has_enum_type_specifier = false;
if (type != NULL)
t.spec = groktypename (type, &t.expr,
&t.expr_const_operands);
@@ -3218,17 +3222,20 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2, C11 6.7.2.2).
enum-specifier:
- enum gnu-attributes[opt] identifier[opt] { enumerator-list }
- gnu-attributes[opt]
- enum gnu-attributes[opt] identifier[opt] { enumerator-list , }
- gnu-attributes[opt]
+ enum gnu-attributes[opt] identifier[opt] enum-type-specifier[opt]
+ { enumerator-list } gnu-attributes[opt]
+ enum gnu-attributes[opt] identifier[opt] enum-type-specifier[opt]
+ { enumerator-list , } gnu-attributes[opt] enum-type-specifier[opt]
enum gnu-attributes[opt] identifier
- The form with trailing comma is new in C99. The forms with
- gnu-attributes are GNU extensions. In GNU C, we accept any expression
- without commas in the syntax (assignment expressions, not just
- conditional expressions); assignment expressions will be diagnosed
- as non-constant.
+ The form with trailing comma is new in C99; enum-type-specifiers
+ are new in C2x. The forms with gnu-attributes are GNU extensions.
+ In GNU C, we accept any expression without commas in the syntax
+ (assignment expressions, not just conditional expressions);
+ assignment expressions will be diagnosed as non-constant.
+
+ enum-type-specifier:
+ : specifier-qualifier-list
enumerator-list:
enumerator
@@ -3256,6 +3263,7 @@ c_parser_enum_specifier (c_parser *parser)
tree std_attrs = NULL_TREE;
tree attrs;
tree ident = NULL_TREE;
+ tree fixed_underlying_type = NULL_TREE;
location_t enum_loc;
location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */
gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
@@ -3274,6 +3282,83 @@ c_parser_enum_specifier (c_parser *parser)
enum_loc = ident_loc;
c_parser_consume_token (parser);
}
+ if (c_parser_next_token_is (parser, CPP_COLON)
+ /* Distinguish an enum-type-specifier from a bit-field
+ declaration of the form "enum e : constant-expression;". */
+ && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+ {
+ pedwarn_c11 (enum_loc, OPT_Wpedantic,
+ "ISO C does not support specifying %<enum%> underlying "
+ "types before C2X");
+ if (ident)
+ {
+ /* The tag is in scope during the enum-type-specifier (which
+ may refer to the tag inside typeof). */
+ ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident,
+ have_std_attrs, std_attrs, true);
+ if (!ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec))
+ error_at (enum_loc, "%<enum%> declared both with and without "
+ "fixed underlying type");
+ }
+ else
+ {
+ /* There must be an enum definition, so this initialization
+ (to avoid possible warnings about uninitialized data)
+ will be replaced later (either with the results of that
+ definition, or with the results of error handling for the
+ case of no tag and no definition). */
+ ret.spec = NULL_TREE;
+ ret.kind = ctsk_tagdef;
+ ret.expr = NULL_TREE;
+ ret.expr_const_operands = true;
+ ret.has_enum_type_specifier = true;
+ }
+ c_parser_consume_token (parser);
+ struct c_declspecs *specs = build_null_declspecs ();
+ c_parser_declspecs (parser, specs, false, true, false, false, false,
+ false, true, cla_prefer_id);
+ finish_declspecs (specs);
+ if (specs->default_int_p)
+ error_at (enum_loc, "no %<enum%> underlying type specified");
+ else if (TREE_CODE (specs->type) != INTEGER_TYPE
+ && TREE_CODE (specs->type) != BOOLEAN_TYPE)
+ {
+ error_at (enum_loc, "invalid %<enum%> underlying type");
+ specs->type = integer_type_node;
+ }
+ else if (specs->restrict_p)
+ error_at (enum_loc, "invalid use of %<restrict%>");
+ fixed_underlying_type = TYPE_MAIN_VARIANT (specs->type);
+ if (ident)
+ {
+ /* The type specified must be consistent with any previously
+ specified underlying type. If this is a newly declared
+ type, it is now a complete type. */
+ if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
+ && ENUM_UNDERLYING_TYPE (ret.spec) == NULL_TREE)
+ {
+ TYPE_MIN_VALUE (ret.spec) =
+ TYPE_MIN_VALUE (fixed_underlying_type);
+ TYPE_MAX_VALUE (ret.spec) =
+ TYPE_MAX_VALUE (fixed_underlying_type);
+ TYPE_UNSIGNED (ret.spec) = TYPE_UNSIGNED (fixed_underlying_type);
+ SET_TYPE_ALIGN (ret.spec, TYPE_ALIGN (fixed_underlying_type));
+ TYPE_SIZE (ret.spec) = NULL_TREE;
+ TYPE_PRECISION (ret.spec) =
+ TYPE_PRECISION (fixed_underlying_type);
+ ENUM_UNDERLYING_TYPE (ret.spec) = fixed_underlying_type;
+ layout_type (ret.spec);
+ }
+ else if (ENUM_FIXED_UNDERLYING_TYPE_P (ret.spec)
+ && !comptypes (fixed_underlying_type,
+ ENUM_UNDERLYING_TYPE (ret.spec)))
+ {
+ error_at (enum_loc, "%<enum%> underlying type incompatible with "
+ "previous declaration");
+ fixed_underlying_type = ENUM_UNDERLYING_TYPE (ret.spec);
+ }
+ }
+ }
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
{
/* Parse an enum definition. */
@@ -3284,7 +3369,7 @@ c_parser_enum_specifier (c_parser *parser)
forward order at the end. */
tree values;
timevar_push (TV_PARSE_ENUM);
- type = start_enum (enum_loc, &the_enum, ident);
+ type = start_enum (enum_loc, &the_enum, ident, fixed_underlying_type);
values = NULL_TREE;
c_parser_consume_token (parser);
while (true)
@@ -3368,6 +3453,7 @@ c_parser_enum_specifier (c_parser *parser)
ret.kind = ctsk_tagdef;
ret.expr = NULL_TREE;
ret.expr_const_operands = true;
+ ret.has_enum_type_specifier = fixed_underlying_type != NULL_TREE;
timevar_pop (TV_PARSE_ENUM);
return ret;
}
@@ -3378,6 +3464,7 @@ c_parser_enum_specifier (c_parser *parser)
ret.kind = ctsk_tagref;
ret.expr = NULL_TREE;
ret.expr_const_operands = true;
+ ret.has_enum_type_specifier = false;
return ret;
}
/* Attributes may only appear when the members are defined or in
@@ -3386,15 +3473,18 @@ c_parser_enum_specifier (c_parser *parser)
standard C). */
if (have_std_attrs && c_parser_next_token_is_not (parser, CPP_SEMICOLON))
c_parser_error (parser, "expected %<;%>");
- ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident, have_std_attrs,
- std_attrs);
- /* In ISO C, enumerated types can be referred to only if already
- defined. */
- if (pedantic && !COMPLETE_TYPE_P (ret.spec))
+ if (fixed_underlying_type == NULL_TREE)
{
- gcc_assert (ident);
- pedwarn (enum_loc, OPT_Wpedantic,
- "ISO C forbids forward references to %<enum%> types");
+ ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident, have_std_attrs,
+ std_attrs, false);
+ /* In ISO C, enumerated types without a fixed underlying type
+ can be referred to only if already defined. */
+ if (pedantic && !COMPLETE_TYPE_P (ret.spec))
+ {
+ gcc_assert (ident);
+ pedwarn (enum_loc, OPT_Wpedantic,
+ "ISO C forbids forward references to %<enum%> types");
+ }
}
return ret;
}
@@ -3590,6 +3680,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
ret.kind = ctsk_tagdef;
ret.expr = NULL_TREE;
ret.expr_const_operands = true;
+ ret.has_enum_type_specifier = false;
timevar_pop (TV_PARSE_STRUCT);
return ret;
}
@@ -3600,6 +3691,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
ret.kind = ctsk_tagref;
ret.expr = NULL_TREE;
ret.expr_const_operands = true;
+ ret.has_enum_type_specifier = false;
return ret;
}
/* Attributes may only appear when the members are defined or in
@@ -3608,7 +3700,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
c_parser_error (parser, "expected %<;%>");
/* ??? Existing practice is that GNU attributes are ignored after
the struct or union keyword when not defining the members. */
- ret = parser_xref_tag (ident_loc, code, ident, have_std_attrs, std_attrs);
+ ret = parser_xref_tag (ident_loc, code, ident, have_std_attrs, std_attrs,
+ false);
return ret;
}
@@ -3817,6 +3910,7 @@ c_parser_typeof_specifier (c_parser *parser)
ret.spec = error_mark_node;
ret.expr = NULL_TREE;
ret.expr_const_operands = true;
+ ret.has_enum_type_specifier = false;
if (c_parser_next_token_is_keyword (parser, RID_TYPEOF))
{
is_unqual = false;
@@ -19153,15 +19247,14 @@ restart:
&& TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
&& TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
&& TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
- (TREE_OPERAND (lhs, 1), 0), 0)))
- == BOOLEAN_TYPE)
+ && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
+ (TREE_OPERAND (lhs, 1), 0), 0))))
/* Undo effects of boolean_increment for post {in,de}crement. */
lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
/* FALLTHRU */
case MODIFY_EXPR:
if (TREE_CODE (lhs) == MODIFY_EXPR
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE)
+ && C_BOOLEAN_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0))))
{
/* Undo effects of boolean_increment. */
if (integer_onep (TREE_OPERAND (lhs, 1)))
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index e7cdd2f..d787dd4 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -122,6 +122,14 @@ along with GCC; see the file COPYING3. If not see
been folded. */
#define SAVE_EXPR_FOLDED_P(EXP) TREE_LANG_FLAG_1 (SAVE_EXPR_CHECK (EXP))
+/* Whether a type has boolean semantics: either a boolean type or an
+ enumeration type with a boolean type as its underlying type. */
+#define C_BOOLEAN_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == BOOLEAN_TYPE \
+ || (TREE_CODE (TYPE) == ENUMERAL_TYPE \
+ && ENUM_UNDERLYING_TYPE (TYPE) != NULL_TREE \
+ && TREE_CODE (ENUM_UNDERLYING_TYPE (TYPE)) == BOOLEAN_TYPE))
+
/* Record parser information about an expression that is irrelevant
for code generation alongside a tree representing its value. */
struct c_expr
@@ -216,6 +224,10 @@ struct c_typespec {
/* Whether the expression has operands suitable for use in constant
expressions. */
bool expr_const_operands;
+ /* Whether the type specifier includes an enum type specifier (that
+ is, ": specifier-qualifier-list" in a declaration using
+ "enum"). */
+ bool has_enum_type_specifier;
/* The specifier itself. */
tree spec;
/* An expression to be evaluated before the type specifier, in the
@@ -412,6 +424,12 @@ struct c_declspecs {
/* Whether any alignment specifier (even with zero alignment) was
specified. */
BOOL_BITFIELD alignas_p : 1;
+ /* Whether an enum type specifier (": specifier-qualifier-list") was
+ specified other than in a definition of that enum (if so, this is
+ invalid unless it is an empty declaration "enum identifier
+ enum-type-specifier;", but such an empty declaration is valid in
+ C2x when "enum identifier;" would not be). */
+ BOOL_BITFIELD enum_type_specifier_ref_p : 1;
/* The address space that the declaration belongs to. */
addr_space_t address_space;
};
@@ -525,6 +543,9 @@ struct c_enum_contents
constant value. */
tree enum_next_value;
+ /* The enumeration type itself. */
+ tree enum_type;
+
/* Nonzero means that there was overflow computing enum_next_value. */
int enum_overflow;
};
@@ -625,7 +646,7 @@ extern void c_warn_unused_attributes (tree);
extern tree c_warn_type_attributes (tree);
extern void shadow_tag (const struct c_declspecs *);
extern void shadow_tag_warned (const struct c_declspecs *, int);
-extern tree start_enum (location_t, struct c_enum_contents *, tree);
+extern tree start_enum (location_t, struct c_enum_contents *, tree, tree);
extern bool start_function (struct c_declspecs *, struct c_declarator *, tree);
extern tree start_decl (struct c_declarator *, struct c_declspecs *, bool,
tree, location_t * = NULL);
@@ -637,7 +658,7 @@ extern void temp_store_parm_decls (tree, tree);
extern void temp_pop_parm_decls (void);
extern tree xref_tag (enum tree_code, tree);
extern struct c_typespec parser_xref_tag (location_t, enum tree_code, tree,
- bool, tree);
+ bool, tree, bool);
extern struct c_parm *build_c_parm (struct c_declspecs *, tree,
struct c_declarator *, location_t);
extern struct c_declarator *build_attrs_declarator (tree,
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 92f3afc..6c16647 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -420,9 +420,11 @@ composite_type (tree t1, tree t2)
(DR#013 question 3). For consistency, use the enumerated type as
the composite type. */
- if (code1 == ENUMERAL_TYPE && code2 == INTEGER_TYPE)
+ if (code1 == ENUMERAL_TYPE
+ && (code2 == INTEGER_TYPE || code2 == BOOLEAN_TYPE))
return t1;
- if (code2 == ENUMERAL_TYPE && code1 == INTEGER_TYPE)
+ if (code2 == ENUMERAL_TYPE
+ && (code1 == INTEGER_TYPE || code1 == BOOLEAN_TYPE))
return t2;
gcc_assert (code1 == code2);
@@ -1025,9 +1027,9 @@ tree
common_type (tree t1, tree t2)
{
if (TREE_CODE (t1) == ENUMERAL_TYPE)
- t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1);
+ t1 = ENUM_UNDERLYING_TYPE (t1);
if (TREE_CODE (t2) == ENUMERAL_TYPE)
- t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1);
+ t2 = ENUM_UNDERLYING_TYPE (t2);
/* If both types are BOOLEAN_TYPE, then return boolean_type_node. */
if (TREE_CODE (t1) == BOOLEAN_TYPE
@@ -1125,7 +1127,7 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p,
&& COMPLETE_TYPE_P (t1)
&& TREE_CODE (t2) != ENUMERAL_TYPE)
{
- t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1));
+ t1 = ENUM_UNDERLYING_TYPE (t1);
if (TREE_CODE (t2) != VOID_TYPE)
{
if (enum_and_int_p != NULL)
@@ -1138,7 +1140,7 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p,
&& COMPLETE_TYPE_P (t2)
&& TREE_CODE (t1) != ENUMERAL_TYPE)
{
- t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2));
+ t2 = ENUM_UNDERLYING_TYPE (t2);
if (TREE_CODE (t1) != VOID_TYPE)
{
if (enum_and_int_p != NULL)
@@ -2193,15 +2195,19 @@ perform_integral_promotions (tree exp)
gcc_assert (INTEGRAL_TYPE_P (type));
- /* Normally convert enums to int,
- but convert wide enums to something wider. */
+ /* Convert enums to the result of applying the integer promotions to
+ their underlying type. */
if (code == ENUMERAL_TYPE)
{
- type = c_common_type_for_size (MAX (TYPE_PRECISION (type),
- TYPE_PRECISION (integer_type_node)),
- ((TYPE_PRECISION (type)
- >= TYPE_PRECISION (integer_type_node))
- && TYPE_UNSIGNED (type)));
+ type = ENUM_UNDERLYING_TYPE (type);
+ if (c_promoting_integer_type_p (type))
+ {
+ if (TYPE_UNSIGNED (type)
+ && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
+ type = unsigned_type_node;
+ else
+ type = integer_type_node;
+ }
return convert (type, exp);
}
@@ -3932,7 +3938,7 @@ parser_build_binary_op (location_t location, enum tree_code code,
}
while (1);
}
- if (TREE_CODE (TREE_TYPE (t)) != BOOLEAN_TYPE)
+ if (!C_BOOLEAN_TYPE_P (TREE_TYPE (t)))
warn_logical_not_parentheses (location, code, arg1.value, arg2.value);
}
@@ -4537,7 +4543,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
while (TREE_CODE (e) == COMPOUND_EXPR)
e = TREE_OPERAND (e, 1);
- if ((TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE
+ if ((C_BOOLEAN_TYPE_P (TREE_TYPE (arg))
|| truth_value_p (TREE_CODE (e))))
{
auto_diagnostic_group d;
@@ -4669,7 +4675,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
"decrement of enumeration value is invalid in C++");
}
- if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
+ if (C_BOOLEAN_TYPE_P (TREE_TYPE (arg)))
{
if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
warning_at (location, OPT_Wbool_operation,
@@ -4831,7 +4837,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
goto return_build_unary_op;
}
- if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
+ if (C_BOOLEAN_TYPE_P (TREE_TYPE (arg)))
val = boolean_increment (code, arg);
else
val = build2 (code, TREE_TYPE (arg), arg, inc);
@@ -7087,7 +7093,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
rhstype);
bool save = in_late_binary_op;
- if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE
+ if (C_BOOLEAN_TYPE_P (type) || codel == COMPLEX_TYPE
|| (coder == REAL_TYPE
&& (codel == INTEGER_TYPE || codel == ENUMERAL_TYPE)
&& sanitize_flags_p (SANITIZE_FLOAT_CAST)))
@@ -7734,7 +7740,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
return convert (type, rhs);
}
- else if (codel == BOOLEAN_TYPE
+ else if (C_BOOLEAN_TYPE_P (type)
/* The type nullptr_t may be converted to bool. The
result is false. */
&& (coder == POINTER_TYPE || coder == NULLPTR_TYPE))
@@ -11002,7 +11008,7 @@ c_finish_return (location_t loc, tree retval, tree origtype)
return NULL_TREE;
save = in_late_binary_op;
- if (TREE_CODE (TREE_TYPE (res)) == BOOLEAN_TYPE
+ if (C_BOOLEAN_TYPE_P (TREE_TYPE (res))
|| TREE_CODE (TREE_TYPE (res)) == COMPLEX_TYPE
|| (TREE_CODE (TREE_TYPE (t)) == REAL_TYPE
&& (TREE_CODE (TREE_TYPE (res)) == INTEGER_TYPE
@@ -11164,7 +11170,7 @@ c_start_switch (location_t switch_loc,
while (TREE_CODE (e) == COMPOUND_EXPR)
e = TREE_OPERAND (e, 1);
- if ((TREE_CODE (type) == BOOLEAN_TYPE
+ if ((C_BOOLEAN_TYPE_P (type)
|| truth_value_p (TREE_CODE (e)))
/* Explicit cast to int suppresses this warning. */
&& !(TREE_CODE (type) == INTEGER_TYPE
@@ -12493,9 +12499,9 @@ build_binary_op (location_t location, enum tree_code code,
else if (code1 == NULLPTR_TYPE && null_pointer_constant_p (orig_op0))
result_type = (INTEGRAL_TYPE_P (type0)
? build_pointer_type (type0) : type0);
- if ((TREE_CODE (TREE_TYPE (orig_op0)) == BOOLEAN_TYPE
+ if ((C_BOOLEAN_TYPE_P (TREE_TYPE (orig_op0))
|| truth_value_p (TREE_CODE (orig_op0)))
- ^ (TREE_CODE (TREE_TYPE (orig_op1)) == BOOLEAN_TYPE
+ ^ (C_BOOLEAN_TYPE_P (TREE_TYPE (orig_op1))
|| truth_value_p (TREE_CODE (orig_op1))))
maybe_warn_bool_compare (location, code, orig_op0, orig_op1);
break;
@@ -12638,9 +12644,9 @@ build_binary_op (location_t location, enum tree_code code,
instrument_expr = build_call_expr_loc (location, tt, 2, op0, op1);
}
- if ((TREE_CODE (TREE_TYPE (orig_op0)) == BOOLEAN_TYPE
+ if ((C_BOOLEAN_TYPE_P (TREE_TYPE (orig_op0))
|| truth_value_p (TREE_CODE (orig_op0)))
- ^ (TREE_CODE (TREE_TYPE (orig_op1)) == BOOLEAN_TYPE
+ ^ (C_BOOLEAN_TYPE_P (TREE_TYPE (orig_op1))
|| truth_value_p (TREE_CODE (orig_op1))))
maybe_warn_bool_compare (location, code, orig_op0, orig_op1);
break;
diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index bd356ce..d6404a0 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -51,6 +51,11 @@ static const riscv_implied_info_t riscv_implied_info[] =
{"d", "f"},
{"f", "zicsr"},
{"d", "zicsr"},
+
+ {"zdinx", "zfinx"},
+ {"zfinx", "zicsr"},
+ {"zdinx", "zicsr"},
+
{"zk", "zkn"},
{"zk", "zkr"},
{"zk", "zkt"},
@@ -99,6 +104,9 @@ static const riscv_implied_info_t riscv_implied_info[] =
{"zfh", "zfhmin"},
{"zfhmin", "f"},
+
+ {"zhinx", "zhinxmin"},
+ {"zhinxmin", "zfinx"},
{NULL, NULL}
};
@@ -160,6 +168,11 @@ static const struct riscv_ext_version riscv_ext_version_table[] =
{"zbc", ISA_SPEC_CLASS_NONE, 1, 0},
{"zbs", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"zfinx", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"zdinx", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"zhinx", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"zhinxmin", ISA_SPEC_CLASS_NONE, 1, 0},
+
{"zbkb", ISA_SPEC_CLASS_NONE, 1, 0},
{"zbkc", ISA_SPEC_CLASS_NONE, 1, 0},
{"zbkx", ISA_SPEC_CLASS_NONE, 1, 0},
@@ -1172,6 +1185,11 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
{"zbc", &gcc_options::x_riscv_zb_subext, MASK_ZBC},
{"zbs", &gcc_options::x_riscv_zb_subext, MASK_ZBS},
+ {"zfinx", &gcc_options::x_riscv_zinx_subext, MASK_ZFINX},
+ {"zdinx", &gcc_options::x_riscv_zinx_subext, MASK_ZDINX},
+ {"zhinx", &gcc_options::x_riscv_zinx_subext, MASK_ZHINX},
+ {"zhinxmin", &gcc_options::x_riscv_zinx_subext, MASK_ZHINXMIN},
+
{"zbkb", &gcc_options::x_riscv_zk_subext, MASK_ZBKB},
{"zbkc", &gcc_options::x_riscv_zk_subext, MASK_ZBKC},
{"zbkx", &gcc_options::x_riscv_zk_subext, MASK_ZBKX},
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 1a71f02..2388205 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -254,7 +254,7 @@ typedef struct simd_vec_cost advsimd_vec_cost;
/* SVE-specific extensions to the information provided by simd_vec_cost. */
struct sve_vec_cost : simd_vec_cost
{
- constexpr sve_vec_cost (const simd_vec_cost &base,
+ CONSTEXPR sve_vec_cost (const simd_vec_cost &base,
unsigned int clast_cost,
unsigned int fadda_f16_cost,
unsigned int fadda_f32_cost,
@@ -354,7 +354,7 @@ using aarch64_scalar_vec_issue_info = aarch64_base_vec_issue_info;
Advanced SIMD and SVE. */
struct aarch64_simd_vec_issue_info : aarch64_base_vec_issue_info
{
- constexpr aarch64_simd_vec_issue_info (aarch64_base_vec_issue_info base,
+ CONSTEXPR aarch64_simd_vec_issue_info (aarch64_base_vec_issue_info base,
unsigned int ld2_st2_general_ops,
unsigned int ld3_st3_general_ops,
unsigned int ld4_st4_general_ops)
@@ -382,7 +382,7 @@ using aarch64_advsimd_vec_issue_info = aarch64_simd_vec_issue_info;
is a concept of "predicate operations". */
struct aarch64_sve_vec_issue_info : aarch64_simd_vec_issue_info
{
- constexpr aarch64_sve_vec_issue_info
+ CONSTEXPR aarch64_sve_vec_issue_info
(aarch64_simd_vec_issue_info base,
unsigned int pred_ops_per_cycle,
unsigned int while_pred_ops,
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
index 23b4d42..6347407 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
@@ -177,7 +177,7 @@ public:
class svac_impl : public function_base
{
public:
- constexpr svac_impl (int unspec) : m_unspec (unspec) {}
+ CONSTEXPR svac_impl (int unspec) : m_unspec (unspec) {}
rtx
expand (function_expander &e) const override
@@ -209,7 +209,7 @@ public:
class svadr_bhwd_impl : public function_base
{
public:
- constexpr svadr_bhwd_impl (unsigned int shift) : m_shift (shift) {}
+ CONSTEXPR svadr_bhwd_impl (unsigned int shift) : m_shift (shift) {}
rtx
expand (function_expander &e) const override
@@ -259,7 +259,7 @@ public:
class svbrk_binary_impl : public function_base
{
public:
- constexpr svbrk_binary_impl (int unspec) : m_unspec (unspec) {}
+ CONSTEXPR svbrk_binary_impl (int unspec) : m_unspec (unspec) {}
rtx
expand (function_expander &e) const override
@@ -275,7 +275,7 @@ public:
class svbrk_unary_impl : public function_base
{
public:
- constexpr svbrk_unary_impl (int unspec) : m_unspec (unspec) {}
+ CONSTEXPR svbrk_unary_impl (int unspec) : m_unspec (unspec) {}
rtx
expand (function_expander &e) const override
@@ -309,7 +309,7 @@ public:
class svclast_impl : public quiet<function_base>
{
public:
- constexpr svclast_impl (int unspec) : m_unspec (unspec) {}
+ CONSTEXPR svclast_impl (int unspec) : m_unspec (unspec) {}
rtx
expand (function_expander &e) const override
@@ -381,7 +381,7 @@ public:
class svcmp_impl : public function_base
{
public:
- constexpr svcmp_impl (tree_code code, int unspec_for_fp)
+ CONSTEXPR svcmp_impl (tree_code code, int unspec_for_fp)
: m_code (code), m_unspec_for_fp (unspec_for_fp) {}
gimple *
@@ -437,7 +437,7 @@ public:
class svcmp_wide_impl : public function_base
{
public:
- constexpr svcmp_wide_impl (tree_code code, int unspec_for_sint,
+ CONSTEXPR svcmp_wide_impl (tree_code code, int unspec_for_sint,
int unspec_for_uint)
: m_code (code), m_unspec_for_sint (unspec_for_sint),
m_unspec_for_uint (unspec_for_uint) {}
@@ -512,7 +512,7 @@ public:
class svcnt_bhwd_impl : public function_base
{
public:
- constexpr svcnt_bhwd_impl (machine_mode ref_mode) : m_ref_mode (ref_mode) {}
+ CONSTEXPR svcnt_bhwd_impl (machine_mode ref_mode) : m_ref_mode (ref_mode) {}
gimple *
fold (gimple_folder &f) const override
@@ -949,7 +949,7 @@ public:
class svext_bhw_impl : public function_base
{
public:
- constexpr svext_bhw_impl (scalar_int_mode from_mode)
+ CONSTEXPR svext_bhw_impl (scalar_int_mode from_mode)
: m_from_mode (from_mode) {}
rtx
@@ -1053,7 +1053,7 @@ public:
class svlast_impl : public quiet<function_base>
{
public:
- constexpr svlast_impl (int unspec) : m_unspec (unspec) {}
+ CONSTEXPR svlast_impl (int unspec) : m_unspec (unspec) {}
rtx
expand (function_expander &e) const override
@@ -1399,7 +1399,7 @@ public:
class svldxf1_impl : public full_width_access
{
public:
- constexpr svldxf1_impl (int unspec) : m_unspec (unspec) {}
+ CONSTEXPR svldxf1_impl (int unspec) : m_unspec (unspec) {}
unsigned int
call_properties (const function_instance &) const override
@@ -1426,7 +1426,7 @@ public:
class svldxf1_extend_impl : public extending_load
{
public:
- constexpr svldxf1_extend_impl (type_suffix_index memory_type, int unspec)
+ CONSTEXPR svldxf1_extend_impl (type_suffix_index memory_type, int unspec)
: extending_load (memory_type), m_unspec (unspec) {}
unsigned int
@@ -1616,7 +1616,7 @@ public:
class svnot_impl : public rtx_code_function
{
public:
- constexpr svnot_impl () : rtx_code_function (NOT, NOT, -1) {}
+ CONSTEXPR svnot_impl () : rtx_code_function (NOT, NOT, -1) {}
rtx
expand (function_expander &e) const override
@@ -1664,7 +1664,7 @@ public:
class svpfirst_svpnext_impl : public function_base
{
public:
- constexpr svpfirst_svpnext_impl (int unspec) : m_unspec (unspec) {}
+ CONSTEXPR svpfirst_svpnext_impl (int unspec) : m_unspec (unspec) {}
rtx
expand (function_expander &e) const override
@@ -1682,7 +1682,7 @@ public:
class svprf_bhwd_impl : public function_base
{
public:
- constexpr svprf_bhwd_impl (machine_mode mode) : m_mode (mode) {}
+ CONSTEXPR svprf_bhwd_impl (machine_mode mode) : m_mode (mode) {}
unsigned int
call_properties (const function_instance &) const override
@@ -1706,7 +1706,7 @@ public:
class svprf_bhwd_gather_impl : public function_base
{
public:
- constexpr svprf_bhwd_gather_impl (machine_mode mode) : m_mode (mode) {}
+ CONSTEXPR svprf_bhwd_gather_impl (machine_mode mode) : m_mode (mode) {}
unsigned int
call_properties (const function_instance &) const override
@@ -1744,7 +1744,7 @@ public:
class svptest_impl : public function_base
{
public:
- constexpr svptest_impl (rtx_code compare) : m_compare (compare) {}
+ CONSTEXPR svptest_impl (rtx_code compare) : m_compare (compare) {}
rtx
expand (function_expander &e) const override
@@ -1849,7 +1849,7 @@ public:
class svqdec_svqinc_bhwd_impl : public function_base
{
public:
- constexpr svqdec_svqinc_bhwd_impl (rtx_code code_for_sint,
+ CONSTEXPR svqdec_svqinc_bhwd_impl (rtx_code code_for_sint,
rtx_code code_for_uint,
scalar_int_mode elem_mode)
: m_code_for_sint (code_for_sint),
@@ -1896,7 +1896,7 @@ public:
class svqdec_bhwd_impl : public svqdec_svqinc_bhwd_impl
{
public:
- constexpr svqdec_bhwd_impl (scalar_int_mode elem_mode)
+ CONSTEXPR svqdec_bhwd_impl (scalar_int_mode elem_mode)
: svqdec_svqinc_bhwd_impl (SS_MINUS, US_MINUS, elem_mode) {}
};
@@ -1904,7 +1904,7 @@ public:
class svqinc_bhwd_impl : public svqdec_svqinc_bhwd_impl
{
public:
- constexpr svqinc_bhwd_impl (scalar_int_mode elem_mode)
+ CONSTEXPR svqinc_bhwd_impl (scalar_int_mode elem_mode)
: svqdec_svqinc_bhwd_impl (SS_PLUS, US_PLUS, elem_mode) {}
};
@@ -1912,7 +1912,7 @@ public:
class svqdecp_svqincp_impl : public function_base
{
public:
- constexpr svqdecp_svqincp_impl (rtx_code code_for_sint,
+ CONSTEXPR svqdecp_svqincp_impl (rtx_code code_for_sint,
rtx_code code_for_uint)
: m_code_for_sint (code_for_sint),
m_code_for_uint (code_for_uint)
@@ -2275,7 +2275,7 @@ public:
class svsub_impl : public rtx_code_function
{
public:
- constexpr svsub_impl ()
+ CONSTEXPR svsub_impl ()
: rtx_code_function (MINUS, MINUS, UNSPEC_COND_FSUB) {}
rtx
@@ -2304,7 +2304,7 @@ public:
class svtrn_impl : public binary_permute
{
public:
- constexpr svtrn_impl (int base)
+ CONSTEXPR svtrn_impl (int base)
: binary_permute (base ? UNSPEC_TRN2 : UNSPEC_TRN1), m_base (base) {}
gimple *
@@ -2345,7 +2345,7 @@ public:
class svunpk_impl : public quiet<function_base>
{
public:
- constexpr svunpk_impl (bool high_p) : m_high_p (high_p) {}
+ CONSTEXPR svunpk_impl (bool high_p) : m_high_p (high_p) {}
gimple *
fold (gimple_folder &f) const override
@@ -2387,7 +2387,7 @@ public:
class svusdot_impl : public function_base
{
public:
- constexpr svusdot_impl (bool su) : m_su (su) {}
+ CONSTEXPR svusdot_impl (bool su) : m_su (su) {}
rtx
expand (function_expander &e) const override
@@ -2415,7 +2415,7 @@ private:
class svuzp_impl : public binary_permute
{
public:
- constexpr svuzp_impl (unsigned int base)
+ CONSTEXPR svuzp_impl (unsigned int base)
: binary_permute (base ? UNSPEC_UZP2 : UNSPEC_UZP1), m_base (base) {}
gimple *
@@ -2438,7 +2438,7 @@ public:
class svwhilelx_impl : public while_comparison
{
public:
- constexpr svwhilelx_impl (int unspec_for_sint, int unspec_for_uint, bool eq_p)
+ CONSTEXPR svwhilelx_impl (int unspec_for_sint, int unspec_for_uint, bool eq_p)
: while_comparison (unspec_for_sint, unspec_for_uint), m_eq_p (eq_p)
{}
@@ -2525,7 +2525,7 @@ public:
class svzip_impl : public binary_permute
{
public:
- constexpr svzip_impl (unsigned int base)
+ CONSTEXPR svzip_impl (unsigned int base)
: binary_permute (base ? UNSPEC_ZIP2 : UNSPEC_ZIP1), m_base (base) {}
gimple *
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-functions.h b/gcc/config/aarch64/aarch64-sve-builtins-functions.h
index ec943c5..472e26c 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-functions.h
+++ b/gcc/config/aarch64/aarch64-sve-builtins-functions.h
@@ -44,7 +44,7 @@ public:
class multi_vector_function : public function_base
{
public:
- constexpr multi_vector_function (unsigned int vectors_per_tuple)
+ CONSTEXPR multi_vector_function (unsigned int vectors_per_tuple)
: m_vectors_per_tuple (vectors_per_tuple) {}
unsigned int
@@ -63,7 +63,7 @@ public:
class full_width_access : public multi_vector_function
{
public:
- constexpr full_width_access (unsigned int vectors_per_tuple = 1)
+ CONSTEXPR full_width_access (unsigned int vectors_per_tuple = 1)
: multi_vector_function (vectors_per_tuple) {}
tree
@@ -88,7 +88,7 @@ public:
class extending_load : public function_base
{
public:
- constexpr extending_load (type_suffix_index memory_type)
+ CONSTEXPR extending_load (type_suffix_index memory_type)
: m_memory_type (memory_type) {}
unsigned int
@@ -131,7 +131,7 @@ public:
class truncating_store : public function_base
{
public:
- constexpr truncating_store (scalar_int_mode to_mode) : m_to_mode (to_mode) {}
+ CONSTEXPR truncating_store (scalar_int_mode to_mode) : m_to_mode (to_mode) {}
unsigned int
call_properties (const function_instance &) const override
@@ -168,7 +168,7 @@ public:
class rtx_code_function_base : public function_base
{
public:
- constexpr rtx_code_function_base (rtx_code code_for_sint,
+ CONSTEXPR rtx_code_function_base (rtx_code code_for_sint,
rtx_code code_for_uint,
int unspec_for_fp = -1)
: m_code_for_sint (code_for_sint), m_code_for_uint (code_for_uint),
@@ -227,7 +227,7 @@ public:
class unspec_based_function_base : public function_base
{
public:
- constexpr unspec_based_function_base (int unspec_for_sint,
+ CONSTEXPR unspec_based_function_base (int unspec_for_sint,
int unspec_for_uint,
int unspec_for_fp)
: m_unspec_for_sint (unspec_for_sint),
@@ -434,7 +434,7 @@ public:
class fixed_insn_function : public function_base
{
public:
- constexpr fixed_insn_function (insn_code code) : m_code (code) {}
+ CONSTEXPR fixed_insn_function (insn_code code) : m_code (code) {}
rtx
expand (function_expander &e) const override
@@ -476,7 +476,7 @@ public:
class binary_permute : public permute
{
public:
- constexpr binary_permute (int unspec) : m_unspec (unspec) {}
+ CONSTEXPR binary_permute (int unspec) : m_unspec (unspec) {}
rtx
expand (function_expander &e) const override
@@ -493,13 +493,13 @@ public:
class reduction : public function_base
{
public:
- constexpr reduction (int unspec)
+ CONSTEXPR reduction (int unspec)
: m_unspec_for_sint (unspec),
m_unspec_for_uint (unspec),
m_unspec_for_fp (unspec)
{}
- constexpr reduction (int unspec_for_sint, int unspec_for_uint,
+ CONSTEXPR reduction (int unspec_for_sint, int unspec_for_uint,
int unspec_for_fp)
: m_unspec_for_sint (unspec_for_sint),
m_unspec_for_uint (unspec_for_uint),
@@ -532,7 +532,7 @@ public:
class shift_wide : public function_base
{
public:
- constexpr shift_wide (rtx_code code, int wide_unspec)
+ CONSTEXPR shift_wide (rtx_code code, int wide_unspec)
: m_code (code), m_wide_unspec (wide_unspec) {}
rtx
@@ -567,7 +567,7 @@ public:
class unary_count : public quiet<function_base>
{
public:
- constexpr unary_count (rtx_code code) : m_code (code) {}
+ CONSTEXPR unary_count (rtx_code code) : m_code (code) {}
rtx
expand (function_expander &e) const override
@@ -590,7 +590,7 @@ public:
class while_comparison : public function_base
{
public:
- constexpr while_comparison (int unspec_for_sint, int unspec_for_uint)
+ CONSTEXPR while_comparison (int unspec_for_sint, int unspec_for_uint)
: m_unspec_for_sint (unspec_for_sint),
m_unspec_for_uint (unspec_for_uint)
{}
@@ -619,7 +619,7 @@ public:
/* Declare the global function base NAME, creating it from an instance
of class CLASS with constructor arguments ARGS. */
#define FUNCTION(NAME, CLASS, ARGS) \
- namespace { static constexpr const CLASS NAME##_obj ARGS; } \
+ namespace { static CONSTEXPR const CLASS NAME##_obj ARGS; } \
namespace functions { const function_base *const NAME = &NAME##_obj; }
#endif
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
index bf1d05e..8e26bd8 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
@@ -447,7 +447,7 @@ long_type_suffix (function_resolver &r, type_suffix_index type)
/* Declare the function shape NAME, pointing it to an instance
of class <NAME>_def. */
#define SHAPE(NAME) \
- static constexpr const NAME##_def NAME##_obj; \
+ static CONSTEXPR const NAME##_def NAME##_obj; \
namespace shapes { const function_shape *const NAME = &NAME##_obj; }
/* Base class for functions that are not overloaded. */
@@ -587,7 +587,7 @@ struct binary_imm_long_base : public overloaded_base<0>
/* Base class for inc_dec and inc_dec_pat. */
struct inc_dec_base : public overloaded_base<0>
{
- constexpr inc_dec_base (bool pat_p) : m_pat_p (pat_p) {}
+ CONSTEXPR inc_dec_base (bool pat_p) : m_pat_p (pat_p) {}
/* Resolve based on the first argument only, which must be either a
scalar or a vector. If it's a scalar, it must be a 32-bit or
@@ -1924,7 +1924,7 @@ SHAPE (get)
whose size is tied to the [bhwd] suffix of "svfoo". */
struct inc_dec_def : public inc_dec_base
{
- constexpr inc_dec_def () : inc_dec_base (false) {}
+ CONSTEXPR inc_dec_def () : inc_dec_base (false) {}
void
build (function_builder &b, const function_group_info &group) const override
@@ -1949,7 +1949,7 @@ SHAPE (inc_dec)
whose size is tied to the [bhwd] suffix of "svfoo". */
struct inc_dec_pat_def : public inc_dec_base
{
- constexpr inc_dec_pat_def () : inc_dec_base (true) {}
+ CONSTEXPR inc_dec_pat_def () : inc_dec_base (true) {}
void
build (function_builder &b, const function_group_info &group) const override
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc b/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
index ca8f20d..a7d7435 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
@@ -158,7 +158,7 @@ public:
class svmatch_svnmatch_impl : public function_base
{
public:
- constexpr svmatch_svnmatch_impl (int unspec) : m_unspec (unspec) {}
+ CONSTEXPR svmatch_svnmatch_impl (int unspec) : m_unspec (unspec) {}
rtx
expand (function_expander &e) const override
@@ -233,7 +233,7 @@ public:
class svqrshl_impl : public unspec_based_function
{
public:
- constexpr svqrshl_impl ()
+ CONSTEXPR svqrshl_impl ()
: unspec_based_function (UNSPEC_SQRSHL, UNSPEC_UQRSHL, -1) {}
gimple *
@@ -267,7 +267,7 @@ public:
class svqshl_impl : public unspec_based_function
{
public:
- constexpr svqshl_impl ()
+ CONSTEXPR svqshl_impl ()
: unspec_based_function (UNSPEC_SQSHL, UNSPEC_UQSHL, -1) {}
gimple *
@@ -303,7 +303,7 @@ public:
class svrshl_impl : public unspec_based_function
{
public:
- constexpr svrshl_impl ()
+ CONSTEXPR svrshl_impl ()
: unspec_based_function (UNSPEC_SRSHL, UNSPEC_URSHL, -1) {}
gimple *
@@ -403,7 +403,7 @@ public:
class svtbl2_impl : public quiet<multi_vector_function>
{
public:
- constexpr svtbl2_impl () : quiet<multi_vector_function> (2) {}
+ CONSTEXPR svtbl2_impl () : quiet<multi_vector_function> (2) {}
rtx
expand (function_expander &e) const override
@@ -431,7 +431,7 @@ public:
class svwhilerw_svwhilewr_impl : public full_width_access
{
public:
- constexpr svwhilerw_svwhilewr_impl (int unspec) : m_unspec (unspec) {}
+ CONSTEXPR svwhilerw_svwhilewr_impl (int unspec) : m_unspec (unspec) {}
rtx
expand (function_expander &e) const override
diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
index 37228f6..e168c83 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
@@ -99,7 +99,7 @@ struct registered_function_hasher : nofree_ptr_hash <registered_function>
};
/* Information about each single-predicate or single-vector type. */
-static constexpr const vector_type_info vector_types[] = {
+static CONSTEXPR const vector_type_info vector_types[] = {
#define DEF_SVE_TYPE(ACLE_NAME, NCHARS, ABI_NAME, SCALAR_TYPE) \
{ #ACLE_NAME, #ABI_NAME, "u" #NCHARS #ABI_NAME },
#include "aarch64-sve-builtins.def"
@@ -116,7 +116,7 @@ static const char *const pred_suffixes[NUM_PREDS + 1] = {
};
/* Static information about each mode_suffix_index. */
-constexpr const mode_suffix_info mode_suffixes[] = {
+CONSTEXPR const mode_suffix_info mode_suffixes[] = {
#define VECTOR_TYPE_none NUM_VECTOR_TYPES
#define DEF_SVE_MODE(NAME, BASE, DISPLACEMENT, UNITS) \
{ "_" #NAME, VECTOR_TYPE_##BASE, VECTOR_TYPE_##DISPLACEMENT, UNITS_##UNITS },
@@ -126,7 +126,7 @@ constexpr const mode_suffix_info mode_suffixes[] = {
};
/* Static information about each type_suffix_index. */
-constexpr const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1] = {
+CONSTEXPR const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1] = {
#define DEF_SVE_TYPE_SUFFIX(NAME, ACLE_TYPE, CLASS, BITS, MODE) \
{ "_" #NAME, \
VECTOR_TYPE_##ACLE_TYPE, \
@@ -522,7 +522,7 @@ static const predication_index preds_z_or_none[] = {
static const predication_index preds_z[] = { PRED_z, NUM_PREDS };
/* A list of all SVE ACLE functions. */
-static constexpr const function_group_info function_groups[] = {
+static CONSTEXPR const function_group_info function_groups[] = {
#define DEF_SVE_FUNCTION(NAME, SHAPE, TYPES, PREDS) \
{ #NAME, &functions::NAME, &shapes::SHAPE, types_##TYPES, preds_##PREDS, \
REQUIRED_EXTENSIONS | AARCH64_FL_SVE },
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 5d1ab5a..0458c65 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -2679,7 +2679,7 @@ struct processor
};
/* Architectures implementing AArch64. */
-static constexpr processor all_architectures[] =
+static CONSTEXPR const processor all_architectures[] =
{
#define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, D, E) \
{NAME, CORE, CORE, AARCH64_ARCH_##ARCH_IDENT, \
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 05da9af..e60f9bc 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -571,10 +571,6 @@ enum class aarch64_feature : unsigned char {
#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, R4_REGNUM)
#define EH_RETURN_HANDLER_RTX aarch64_eh_return_handler_rtx ()
-/* Don't use __builtin_setjmp until we've defined it. */
-#undef DONT_USE_BUILTIN_SETJMP
-#define DONT_USE_BUILTIN_SETJMP 1
-
#undef TARGET_COMPUTE_FRAME_LAYOUT
#define TARGET_COMPUTE_FRAME_LAYOUT aarch64_layout_frame
diff --git a/gcc/config/aarch64/driver-aarch64.cc b/gcc/config/aarch64/driver-aarch64.cc
index 2ae47c0..a1d412c 100644
--- a/gcc/config/aarch64/driver-aarch64.cc
+++ b/gcc/config/aarch64/driver-aarch64.cc
@@ -64,7 +64,7 @@ struct aarch64_core_data
#define AARCH64_CORE(CORE_NAME, CORE_IDENT, SCHED, ARCH, FLAGS, COSTS, IMP, PART, VARIANT) \
{ CORE_NAME, #ARCH, IMP, PART, VARIANT, feature_deps::cpu_##CORE_IDENT },
-static constexpr aarch64_core_data aarch64_cpu_data[] =
+static CONSTEXPR const aarch64_core_data aarch64_cpu_data[] =
{
#include "aarch64-cores.def"
{ NULL, NULL, INVALID_IMP, INVALID_CORE, ALL_VARIANTS, 0 }
@@ -82,7 +82,7 @@ struct aarch64_arch_driver_info
#define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH_REV, FLAGS) \
{ #ARCH_IDENT + 1, NAME, feature_deps::ARCH_IDENT ().enable },
-static constexpr aarch64_arch_driver_info aarch64_arches[] =
+static CONSTEXPR const aarch64_arch_driver_info aarch64_arches[] =
{
#include "aarch64-arches.def"
{NULL, NULL, 0}
diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index 5105565..ea8ca64 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -184,13 +184,13 @@ enum bpf_builtins
/* Compile Once - Run Everywhere (CO-RE) support. */
BPF_BUILTIN_PRESERVE_ACCESS_INDEX,
+ BPF_BUILTIN_PRESERVE_FIELD_INFO,
BPF_BUILTIN_MAX,
};
static GTY (()) tree bpf_builtins[(int) BPF_BUILTIN_MAX];
-
void bpf_register_coreattr_pass (void);
/* Initialize the per-function machine status. */
@@ -966,6 +966,9 @@ bpf_init_builtins (void)
def_builtin ("__builtin_preserve_access_index",
BPF_BUILTIN_PRESERVE_ACCESS_INDEX,
build_function_type_list (ptr_type_node, ptr_type_node, 0));
+ def_builtin ("__builtin_preserve_field_info",
+ BPF_BUILTIN_PRESERVE_FIELD_INFO,
+ build_function_type_list (unsigned_type_node, ptr_type_node, unsigned_type_node, 0));
}
#undef TARGET_INIT_BUILTINS
@@ -975,6 +978,199 @@ static tree bpf_core_compute (tree, vec<unsigned int> *);
static int bpf_core_get_index (const tree);
static bool is_attr_preserve_access (tree);
+/* BPF Compile Once - Run Everywhere (CO-RE) support. Construct a CO-RE
+ relocation record for EXPR of kind KIND to be emitted in the .BTF.ext
+ section. Does nothing if we are not targetting BPF CO-RE, or if the
+ constructed relocation would be a no-op. */
+
+static void
+maybe_make_core_relo (tree expr, enum btf_core_reloc_kind kind)
+{
+ /* If we are not targetting BPF CO-RE, do not make a relocation. We
+ might not be generating any debug info at all. */
+ if (!TARGET_BPF_CORE)
+ return;
+
+ auto_vec<unsigned int, 16> accessors;
+ tree container = bpf_core_compute (expr, &accessors);
+
+ /* Any valid use of the builtin must have at least one access. Otherwise,
+ there is nothing to record and nothing to do. This is primarily a
+ guard against optimizations leading to unexpected expressions in the
+ argument of the builtin. For example, if the builtin is used to read
+ a field of a structure which can be statically determined to hold a
+ constant value, the argument to the builtin will be optimized to that
+ constant. This is OK, and means the builtin call is superfluous.
+ e.g.
+ struct S foo;
+ foo.a = 5;
+ int x = __preserve_access_index (foo.a);
+ ... do stuff with x
+ 'foo.a' in the builtin argument will be optimized to '5' with -01+.
+ This sequence does not warrant recording a CO-RE relocation. */
+
+ if (accessors.length () < 1)
+ return;
+ accessors.reverse ();
+
+ rtx_code_label *label = gen_label_rtx ();
+ LABEL_PRESERVE_P (label) = 1;
+ emit_label (label);
+
+ /* Determine what output section this relocation will apply to.
+ If this function is associated with a section, use that. Otherwise,
+ fall back on '.text'. */
+ const char * section_name;
+ if (current_function_decl && DECL_SECTION_NAME (current_function_decl))
+ section_name = DECL_SECTION_NAME (current_function_decl);
+ else
+ section_name = ".text";
+
+ /* Add the CO-RE relocation information to the BTF container. */
+ bpf_core_reloc_add (TREE_TYPE (container), section_name, &accessors, label,
+ kind);
+}
+
+/* Expand a call to __builtin_preserve_field_info by evaluating the requested
+ information about SRC according to KIND, and return a tree holding
+ the result. */
+
+static tree
+bpf_core_field_info (tree src, enum btf_core_reloc_kind kind)
+{
+ unsigned int result;
+ poly_int64 bitsize, bitpos;
+ tree var_off = NULL_TREE;
+ machine_mode mode;
+ int unsignedp, reversep, volatilep;
+ location_t loc = EXPR_LOCATION (src);
+
+ get_inner_reference (src, &bitsize, &bitpos, &var_off, &mode, &unsignedp,
+ &reversep, &volatilep);
+
+ /* Note: Use DECL_BIT_FIELD_TYPE rather than DECL_BIT_FIELD here, because it
+ remembers whether the field in question was originally declared as a
+ bitfield, regardless of how it has been optimized. */
+ bool bitfieldp = (TREE_CODE (src) == COMPONENT_REF
+ && DECL_BIT_FIELD_TYPE (TREE_OPERAND (src, 1)));
+
+ unsigned int align = TYPE_ALIGN (TREE_TYPE (src));
+ if (TREE_CODE (src) == COMPONENT_REF)
+ {
+ tree field = TREE_OPERAND (src, 1);
+ if (DECL_BIT_FIELD_TYPE (field))
+ align = TYPE_ALIGN (DECL_BIT_FIELD_TYPE (field));
+ else
+ align = TYPE_ALIGN (TREE_TYPE (field));
+ }
+
+ unsigned int start_bitpos = bitpos & ~(align - 1);
+ unsigned int end_bitpos = start_bitpos + align;
+
+ switch (kind)
+ {
+ case BPF_RELO_FIELD_BYTE_OFFSET:
+ {
+ if (var_off != NULL_TREE)
+ {
+ error_at (loc, "unsupported variable field offset");
+ return error_mark_node;
+ }
+
+ if (bitfieldp)
+ result = start_bitpos / 8;
+ else
+ result = bitpos / 8;
+ }
+ break;
+
+ case BPF_RELO_FIELD_BYTE_SIZE:
+ {
+ if (mode == BLKmode && bitsize == -1)
+ {
+ error_at (loc, "unsupported variable size field access");
+ return error_mark_node;
+ }
+
+ if (bitfieldp)
+ {
+ /* To match LLVM behavior, byte size of bitfields is recorded as
+ the full size of the base type. A 3-bit bitfield of type int is
+ therefore recorded as having a byte size of 4 bytes. */
+ result = end_bitpos - start_bitpos;
+ if (result & (result - 1))
+ {
+ error_at (loc, "unsupported field expression");
+ return error_mark_node;
+ }
+ result = result / 8;
+ }
+ else
+ result = bitsize / 8;
+ }
+ break;
+
+ case BPF_RELO_FIELD_EXISTS:
+ /* The field always exists at compile time. */
+ result = 1;
+ break;
+
+ case BPF_RELO_FIELD_SIGNED:
+ result = !unsignedp;
+ break;
+
+ case BPF_RELO_FIELD_LSHIFT_U64:
+ case BPF_RELO_FIELD_RSHIFT_U64:
+ {
+ if (mode == BLKmode && bitsize == -1)
+ {
+ error_at (loc, "unsupported variable size field access");
+ return error_mark_node;
+ }
+ if (var_off != NULL_TREE)
+ {
+ error_at (loc, "unsupported variable field offset");
+ return error_mark_node;
+ }
+
+ if (!bitfieldp)
+ {
+ if (bitsize > 64)
+ {
+ error_at (loc, "field size too large");
+ return error_mark_node;
+ }
+ result = 64 - bitsize;
+ break;
+ }
+
+ if (end_bitpos - start_bitpos > 64)
+ {
+ error_at (loc, "field size too large");
+ return error_mark_node;
+ }
+
+ if (kind == BPF_RELO_FIELD_LSHIFT_U64)
+ {
+ if (TARGET_BIG_ENDIAN)
+ result = bitpos + 64 - start_bitpos - align;
+ else
+ result = start_bitpos + 64 - bitpos - bitsize;
+ }
+ else /* RSHIFT_U64 */
+ result = 64 - bitsize;
+ }
+ break;
+
+ default:
+ error ("invalid second argument to built-in function");
+ return error_mark_node;
+ break;
+ }
+
+ return build_int_cst (unsigned_type_node, result);
+}
+
/* Expand a call to a BPF-specific built-in function that was set up
with bpf_init_builtins. */
@@ -1025,17 +1221,15 @@ bpf_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
/* The result of the load is in R0. */
return gen_rtx_REG (ops[0].mode, BPF_R0);
}
+
else if (code == -1)
{
- /* A resolved overloaded builtin, e.g. __bpf_preserve_access_index_si */
+ /* A resolved overloaded __builtin_preserve_access_index. */
tree arg = CALL_EXPR_ARG (exp, 0);
if (arg == NULL_TREE)
return NULL_RTX;
- auto_vec<unsigned int, 16> accessors;
- tree container;
-
if (TREE_CODE (arg) == SSA_NAME)
{
gimple *def_stmt = SSA_NAME_DEF_STMT (arg);
@@ -1049,51 +1243,42 @@ bpf_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
/* Avoid double-recording information if the argument is an access to
a struct/union marked __attribute__((preserve_access_index)). This
Will be handled by the attribute handling pass. */
- if (is_attr_preserve_access (arg))
- return expand_normal (arg);
-
- container = bpf_core_compute (arg, &accessors);
-
- /* Any valid use of the builtin must have at least one access. Otherwise,
- there is nothing to record and nothing to do. This is primarily a
- guard against optimizations leading to unexpected expressions in the
- argument of the builtin. For example, if the builtin is used to read
- a field of a structure which can be statically determined to hold a
- constant value, the argument to the builtin will be optimized to that
- constant. This is OK, and means the builtin call is superfluous.
- e.g.
- struct S foo;
- foo.a = 5;
- int x = __preserve_access_index (foo.a);
- ... do stuff with x
- 'foo.a' in the builtin argument will be optimized to '5' with -01+.
- This sequence does not warrant recording a CO-RE relocation. */
-
- if (accessors.length () < 1)
- return expand_normal (arg);
-
- accessors.reverse ();
-
- container = TREE_TYPE (container);
-
- rtx_code_label *label = gen_label_rtx ();
- LABEL_PRESERVE_P (label) = 1;
- emit_label (label);
-
- /* Determine what output section this relocation will apply to.
- If this function is associated with a section, use that. Otherwise,
- fall back on '.text'. */
- const char * section_name;
- if (current_function_decl && DECL_SECTION_NAME (current_function_decl))
- section_name = DECL_SECTION_NAME (current_function_decl);
+ if (!is_attr_preserve_access (arg))
+ maybe_make_core_relo (arg, BPF_RELO_FIELD_BYTE_OFFSET);
+
+ return expand_normal (arg);
+ }
+
+ else if (code == -2)
+ {
+ /* A resolved overloaded __builtin_preserve_field_info. */
+ tree src = CALL_EXPR_ARG (exp, 0);
+ tree kind_tree = CALL_EXPR_ARG (exp, 1);
+ unsigned HOST_WIDE_INT kind_val;
+ if (tree_fits_uhwi_p (kind_tree))
+ kind_val = tree_to_uhwi (kind_tree);
else
- section_name = ".text";
+ error ("invalid argument to built-in function");
- /* Add the CO-RE relocation information to the BTF container. */
- bpf_core_reloc_add (container, section_name, &accessors, label);
+ enum btf_core_reloc_kind kind = (enum btf_core_reloc_kind) kind_val;
- return expand_normal (arg);
+ if (TREE_CODE (src) == SSA_NAME)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (src);
+ if (is_gimple_assign (def_stmt))
+ src = gimple_assign_rhs1 (def_stmt);
+ }
+ if (TREE_CODE (src) == ADDR_EXPR)
+ src = TREE_OPERAND (src, 0);
+
+ tree result = bpf_core_field_info (src, kind);
+
+ if (result != error_mark_node)
+ maybe_make_core_relo (src, kind);
+
+ return expand_normal (result);
}
+
gcc_unreachable ();
}
@@ -1259,41 +1444,64 @@ bpf_core_get_index (const tree node)
__builtin_preserve_access_index. */
static tree
-bpf_core_newdecl (tree type)
+bpf_core_newdecl (tree type, bool is_pai)
{
- tree rettype = build_function_type_list (type, type, NULL);
+ tree rettype;
char name[80];
- int len = snprintf (name, sizeof (name), "%s", "__builtin_pai_");
+ static unsigned long pai_count = 0;
+ static unsigned long pfi_count = 0;
- static unsigned long cnt = 0;
- len = snprintf (name + len, sizeof (name) - len, "%lu", cnt++);
+ if (is_pai)
+ {
+ rettype = build_function_type_list (type, type, NULL);
+ int len = snprintf (name, sizeof (name), "%s", "__builtin_pai_");
+ len = snprintf (name + len, sizeof (name) - len, "%lu", pai_count++);
+ }
+ else
+ {
+ rettype = build_function_type_list (unsigned_type_node, type,
+ unsigned_type_node, NULL);
+ int len = snprintf (name, sizeof (name), "%s", "__builtin_pfi_");
+ len = snprintf (name + len, sizeof (name) - len, "%lu", pfi_count++);
+ }
- return add_builtin_function_ext_scope (name, rettype, -1, BUILT_IN_MD, NULL,
- NULL_TREE);
+ return add_builtin_function_ext_scope (name, rettype, is_pai ? -1 : -2,
+ BUILT_IN_MD, NULL, NULL_TREE);
}
/* Return whether EXPR could access some aggregate data structure that
BPF CO-RE support needs to know about. */
-static int
+static bool
bpf_core_is_maybe_aggregate_access (tree expr)
{
- enum tree_code code = TREE_CODE (expr);
- if (code == COMPONENT_REF || code == ARRAY_REF)
- return 1;
-
- if (code == ADDR_EXPR)
+ switch (TREE_CODE (expr))
+ {
+ case COMPONENT_REF:
+ case BIT_FIELD_REF:
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ return true;
+ case ADDR_EXPR:
+ case NOP_EXPR:
return bpf_core_is_maybe_aggregate_access (TREE_OPERAND (expr, 0));
-
- return 0;
+ default:
+ return false;
+ }
}
+struct core_walk_data {
+ location_t loc;
+ tree arg;
+};
+
/* Callback function used with walk_tree from bpf_resolve_overloaded_builtin. */
static tree
bpf_core_walk (tree *tp, int *walk_subtrees, void *data)
{
- location_t loc = *((location_t *) data);
+ struct core_walk_data *dat = (struct core_walk_data *) data;
+ bool is_pai = dat->arg == NULL_TREE;
/* If this is a type, don't do anything. */
if (TYPE_P (*tp))
@@ -1302,10 +1510,18 @@ bpf_core_walk (tree *tp, int *walk_subtrees, void *data)
return NULL_TREE;
}
+ /* Build a new function call to a resolved builtin for the desired operation.
+ If this is a preserve_field_info call, pass along the argument to the
+ resolved builtin call. */
if (bpf_core_is_maybe_aggregate_access (*tp))
{
- tree newdecl = bpf_core_newdecl (TREE_TYPE (*tp));
- tree newcall = build_call_expr_loc (loc, newdecl, 1, *tp);
+ tree newdecl = bpf_core_newdecl (TREE_TYPE (*tp), is_pai);
+ tree newcall;
+ if (is_pai)
+ newcall = build_call_expr_loc (dat->loc, newdecl, 1, *tp);
+ else
+ newcall = build_call_expr_loc (dat->loc, newdecl, 2, *tp, dat->arg);
+
*tp = newcall;
*walk_subtrees = 0;
}
@@ -1330,6 +1546,30 @@ bpf_small_register_classes_for_mode_p (machine_mode mode)
#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P \
bpf_small_register_classes_for_mode_p
+/* Return whether EXPR is a valid first argument for a call to
+ __builtin_preserve_field_info. */
+
+static bool
+bpf_is_valid_preserve_field_info_arg (tree expr)
+{
+ switch (TREE_CODE (expr))
+ {
+ case COMPONENT_REF:
+ case BIT_FIELD_REF:
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ return true;
+ case NOP_EXPR:
+ return bpf_is_valid_preserve_field_info_arg (TREE_OPERAND (expr, 0));
+ case ADDR_EXPR:
+ /* Do not accept ADDR_EXPRs like &foo.bar, but do accept accesses like
+ foo.baz where baz is an array. */
+ return (TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == ARRAY_TYPE);
+ default:
+ return false;
+ }
+}
+
/* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN (see gccint manual section
Target Macros::Misc.).
We use this for the __builtin_preserve_access_index builtin for CO-RE
@@ -1344,7 +1584,12 @@ bpf_small_register_classes_for_mode_p (machine_mode mode)
static tree
bpf_resolve_overloaded_builtin (location_t loc, tree fndecl, void *arglist)
{
- if (DECL_MD_FUNCTION_CODE (fndecl) != BPF_BUILTIN_PRESERVE_ACCESS_INDEX)
+ bool is_pai = DECL_MD_FUNCTION_CODE (fndecl)
+ == BPF_BUILTIN_PRESERVE_ACCESS_INDEX;
+ bool is_pfi = DECL_MD_FUNCTION_CODE (fndecl)
+ == BPF_BUILTIN_PRESERVE_FIELD_INFO;
+
+ if (!is_pai && !is_pfi)
return NULL_TREE;
/* We only expect one argument, but it may be an arbitrarily-complicated
@@ -1352,18 +1597,26 @@ bpf_resolve_overloaded_builtin (location_t loc, tree fndecl, void *arglist)
vec<tree, va_gc> *params = static_cast<vec<tree, va_gc> *> (arglist);
unsigned n_params = params ? params->length() : 0;
- if (n_params != 1)
+ if ((is_pai && n_params != 1) || (is_pfi && n_params != 2))
{
- error_at (loc, "expected exactly 1 argument");
- return NULL_TREE;
+ error_at (loc, "wrong number of arguments");
+ return error_mark_node;
}
tree param = (*params)[0];
- /* If not generating BPF_CORE information, the builtin does nothing. */
- if (!TARGET_BPF_CORE)
+ /* If not generating BPF_CORE information, preserve_access_index does nothing,
+ and simply "resolves to" the argument. */
+ if (!TARGET_BPF_CORE && is_pai)
return param;
+ if (is_pfi && !bpf_is_valid_preserve_field_info_arg (param))
+ {
+ error_at (EXPR_LOC_OR_LOC (param, loc),
+ "argument is not a field access");
+ return error_mark_node;
+ }
+
/* Do remove_c_maybe_const_expr for the arg.
TODO: WHY do we have to do this here? Why doesn't c-typeck take care
of it before or after this hook? */
@@ -1387,7 +1640,11 @@ bpf_resolve_overloaded_builtin (location_t loc, tree fndecl, void *arglist)
This ensures that all the relevant information remains within the
expression trees the builtin finally gets. */
- walk_tree (&param, bpf_core_walk, (void *) &loc, NULL);
+ struct core_walk_data data;
+ data.loc = loc;
+ data.arg = is_pai ? NULL_TREE : (*params)[1];
+
+ walk_tree (&param, bpf_core_walk, (void *) &data, NULL);
return param;
}
@@ -1524,7 +1781,8 @@ handle_attr_preserve (function *fn)
emit_label (label);
/* Add the CO-RE relocation information to the BTF container. */
- bpf_core_reloc_add (container, section_name, &accessors, label);
+ bpf_core_reloc_add (container, section_name, &accessors, label,
+ BPF_RELO_FIELD_BYTE_OFFSET);
}
}
}
diff --git a/gcc/config/bpf/coreout.cc b/gcc/config/bpf/coreout.cc
index 8897a04..9f71040 100644
--- a/gcc/config/bpf/coreout.cc
+++ b/gcc/config/bpf/coreout.cc
@@ -152,7 +152,8 @@ static GTY (()) vec<bpf_core_section_ref, va_gc> *bpf_core_sections;
void
bpf_core_reloc_add (const tree type, const char * section_name,
- vec<unsigned int> *accessors, rtx_code_label *label)
+ vec<unsigned int> *accessors, rtx_code_label *label,
+ enum btf_core_reloc_kind kind)
{
char buf[40];
unsigned int i, n = 0;
@@ -173,7 +174,7 @@ bpf_core_reloc_add (const tree type, const char * section_name,
bpfcr->bpfcr_type = get_btf_id (ctf_lookup_tree_type (ctfc, type));
bpfcr->bpfcr_insn_label = label;
- bpfcr->bpfcr_kind = BPF_RELO_FIELD_BYTE_OFFSET;
+ bpfcr->bpfcr_kind = kind;
/* Add the CO-RE reloc to the appropriate section. */
bpf_core_section_ref sec;
diff --git a/gcc/config/bpf/coreout.h b/gcc/config/bpf/coreout.h
index 3c7bdfd..498853f 100644
--- a/gcc/config/bpf/coreout.h
+++ b/gcc/config/bpf/coreout.h
@@ -103,7 +103,7 @@ extern void btf_ext_init (void);
extern void btf_ext_output (void);
extern void bpf_core_reloc_add (const tree, const char *, vec<unsigned int> *,
- rtx_code_label *);
+ rtx_code_label *, enum btf_core_reloc_kind);
extern int bpf_core_get_sou_member_index (ctf_container_ref, const tree);
#ifdef __cplusplus
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index baf1f1f..aaa678e 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -113,6 +113,7 @@
UNSPEC_PEEPSIB
UNSPEC_INSN_FALSE_DEP
UNSPEC_SBB
+ UNSPEC_CC_NE
;; For SSE/MMX support:
UNSPEC_FIX_NOTRUNC
@@ -11470,7 +11471,7 @@
"&& reload_completed"
[(parallel
[(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_dup 1) (const_int 0)))
+ (unspec:CCC [(match_dup 1) (const_int 0)] UNSPEC_CC_NE))
(set (match_dup 0) (neg:DWIH (match_dup 1)))])
(parallel
[(set (match_dup 2)
@@ -11499,7 +11500,8 @@
(match_operand:SWI48 1 "nonimmediate_gr_operand"))
(parallel
[(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_operand:SWI48 2 "general_reg_operand") (const_int 0)))
+ (unspec:CCC [(match_operand:SWI48 2 "general_reg_operand")
+ (const_int 0)] UNSPEC_CC_NE))
(set (match_dup 2) (neg:SWI48 (match_dup 2)))])
(parallel
[(set (match_dup 0)
@@ -11517,7 +11519,7 @@
&& !reg_mentioned_p (operands[2], operands[1])"
[(parallel
[(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_dup 2) (const_int 0)))
+ (unspec:CCC [(match_dup 2) (const_int 0)] UNSPEC_CC_NE))
(set (match_dup 2) (neg:SWI48 (match_dup 2)))])
(parallel
[(set (match_dup 0)
@@ -11543,7 +11545,8 @@
(clobber (reg:CC FLAGS_REG))])
(parallel
[(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_operand:SWI48 1 "general_reg_operand") (const_int 0)))
+ (unspec:CCC [(match_operand:SWI48 1 "general_reg_operand")
+ (const_int 0)] UNSPEC_CC_NE))
(set (match_dup 1) (neg:SWI48 (match_dup 1)))])
(parallel
[(set (match_dup 0)
@@ -11559,7 +11562,7 @@
"REGNO (operands[0]) != REGNO (operands[1])"
[(parallel
[(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_dup 1) (const_int 0)))
+ (unspec:CCC [(match_dup 1) (const_int 0)] UNSPEC_CC_NE))
(set (match_dup 1) (neg:SWI48 (match_dup 1)))])
(parallel
[(set (match_dup 0)
@@ -11635,9 +11638,9 @@
(define_insn "*neg<mode>_ccc_1"
[(set (reg:CCC FLAGS_REG)
- (ne:CCC
- (match_operand:SWI 1 "nonimmediate_operand" "0")
- (const_int 0)))
+ (unspec:CCC
+ [(match_operand:SWI 1 "nonimmediate_operand" "0")
+ (const_int 0)] UNSPEC_CC_NE))
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
(neg:SWI (match_dup 1)))]
""
@@ -11647,9 +11650,9 @@
(define_insn "*neg<mode>_ccc_2"
[(set (reg:CCC FLAGS_REG)
- (ne:CCC
- (match_operand:SWI 1 "nonimmediate_operand" "0")
- (const_int 0)))
+ (unspec:CCC
+ [(match_operand:SWI 1 "nonimmediate_operand" "0")
+ (const_int 0)] UNSPEC_CC_NE))
(clobber (match_scratch:SWI 0 "=<r>"))]
""
"neg{<imodesuffix>}\t%0"
@@ -11659,8 +11662,8 @@
(define_expand "x86_neg<mode>_ccc"
[(parallel
[(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_operand:SWI48 1 "register_operand")
- (const_int 0)))
+ (unspec:CCC [(match_operand:SWI48 1 "register_operand")
+ (const_int 0)] UNSPEC_CC_NE))
(set (match_operand:SWI48 0 "register_operand")
(neg:SWI48 (match_dup 1)))])])
@@ -11686,8 +11689,9 @@
;; Negate with jump on overflow.
(define_expand "negv<mode>3"
[(parallel [(set (reg:CCO FLAGS_REG)
- (ne:CCO (match_operand:SWI 1 "register_operand")
- (match_dup 3)))
+ (unspec:CCO
+ [(match_operand:SWI 1 "register_operand")
+ (match_dup 3)] UNSPEC_CC_NE))
(set (match_operand:SWI 0 "register_operand")
(neg:SWI (match_dup 1)))])
(set (pc) (if_then_else
@@ -11703,8 +11707,9 @@
(define_insn "*negv<mode>3"
[(set (reg:CCO FLAGS_REG)
- (ne:CCO (match_operand:SWI 1 "nonimmediate_operand" "0")
- (match_operand:SWI 2 "const_int_operand")))
+ (unspec:CCO [(match_operand:SWI 1 "nonimmediate_operand" "0")
+ (match_operand:SWI 2 "const_int_operand")]
+ UNSPEC_CC_NE))
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
(neg:SWI (match_dup 1)))]
"ix86_unary_operator_ok (NEG, <MODE>mode, operands)
@@ -11770,7 +11775,7 @@
"&& 1"
[(parallel
[(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_dup 1) (const_int 0)))
+ (unspec:CCC [(match_dup 1) (const_int 0)] UNSPEC_CC_NE))
(set (match_dup 2) (neg:DWIH (match_dup 1)))])
(parallel
[(set (match_dup 5)
@@ -11814,7 +11819,7 @@
"&& 1"
[(parallel
[(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_dup 1) (const_int 0)))
+ (unspec:CCC [(match_dup 1) (const_int 0)] UNSPEC_CC_NE))
(set (match_dup 2) (neg:DWIH (match_dup 1)))])
(parallel
[(set (match_dup 5)
@@ -21456,7 +21461,7 @@
(const_int 0))))]
""
[(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_dup 1) (const_int 0)))
+ (unspec:CCC [(match_dup 1) (const_int 0)] UNSPEC_CC_NE))
(set (match_dup 0)
(neg:SWI (ltu:SWI (reg:CCC FLAGS_REG) (const_int 0))))])
diff --git a/gcc/config/riscv/arch-canonicalize b/gcc/config/riscv/arch-canonicalize
index fd7651a..2498db5 100755
--- a/gcc/config/riscv/arch-canonicalize
+++ b/gcc/config/riscv/arch-canonicalize
@@ -41,6 +41,11 @@ LONG_EXT_PREFIXES = ['z', 's', 'h', 'x']
IMPLIED_EXT = {
"d" : ["f", "zicsr"],
"f" : ["zicsr"],
+ "zdinx" : ["zfinx", "zicsr"],
+ "zfinx" : ["zicsr"],
+ "zhinx" : ["zhinxmin", "zfinx", "zicsr"],
+ "zhinxmin" : ["zfinx", "zicsr"],
+
"zk" : ["zkn", "zkr", "zkt"],
"zkn" : ["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"],
"zks" : ["zbkb", "zbkc", "zbkx", "zksed", "zksh"],
diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index 951dcc5..4088c48 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -21,8 +21,9 @@
;; Register constraints
-(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS : NO_REGS"
- "A floating-point register (if available).")
+(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS :
+ (TARGET_ZFINX ? GR_REGS : NO_REGS)"
+ "A floating-point register (if available, reuse GPR as FPR when use zfinx).")
(define_register_constraint "j" "SIBCALL_REGS"
"@internal")
diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index 39dffab..50380ec 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -59,9 +59,9 @@
(define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")])
;; Iterator for hardware-supported floating-point modes.
-(define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT")
- (DF "TARGET_DOUBLE_FLOAT")
- (HF "TARGET_ZFH")])
+(define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT || TARGET_ZFINX")
+ (DF "TARGET_DOUBLE_FLOAT || TARGET_ZDINX")
+ (HF "TARGET_ZFH || TARGET_ZHINX")])
;; Iterator for floating-point modes that can be loaded into X registers.
(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")])
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index 9fa4d6c..021f6c6 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -87,7 +87,7 @@ struct riscv_builtin_description {
unsigned int (*avail) (void);
};
-AVAIL (hard_float, TARGET_HARD_FLOAT)
+AVAIL (hard_float, TARGET_HARD_FLOAT || TARGET_ZFINX)
AVAIL (clean32, TARGET_ZICBOM && !TARGET_64BIT)
@@ -342,7 +342,7 @@ riscv_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
void
riscv_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
{
- if (!TARGET_HARD_FLOAT)
+ if (!(TARGET_HARD_FLOAT || TARGET_ZFINX))
return;
tree frflags = GET_BUILTIN_DECL (CODE_FOR_riscv_frflags);
diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc
index 78f6eac..826ae00 100644
--- a/gcc/config/riscv/riscv-c.cc
+++ b/gcc/config/riscv/riscv-c.cc
@@ -61,7 +61,7 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile)
if (TARGET_HARD_FLOAT)
builtin_define_with_int_value ("__riscv_flen", UNITS_PER_FP_REG * 8);
- if (TARGET_HARD_FLOAT && TARGET_FDIV)
+ if ((TARGET_HARD_FLOAT || TARGET_ZFINX) && TARGET_FDIV)
{
builtin_define ("__riscv_fdiv");
builtin_define ("__riscv_fsqrt");
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 63ac56a..1dfe8c8 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -83,6 +83,16 @@ enum stack_protector_guard {
#define TARGET_ZBC ((riscv_zb_subext & MASK_ZBC) != 0)
#define TARGET_ZBS ((riscv_zb_subext & MASK_ZBS) != 0)
+#define MASK_ZFINX (1 << 0)
+#define MASK_ZDINX (1 << 1)
+#define MASK_ZHINX (1 << 2)
+#define MASK_ZHINXMIN (1 << 3)
+
+#define TARGET_ZFINX ((riscv_zinx_subext & MASK_ZFINX) != 0)
+#define TARGET_ZDINX ((riscv_zinx_subext & MASK_ZDINX) != 0)
+#define TARGET_ZHINX ((riscv_zinx_subext & MASK_ZHINX) != 0)
+#define TARGET_ZHINXMIN ((riscv_zinx_subext & MASK_ZHINXMIN) != 0)
+
#define MASK_ZBKB (1 << 0)
#define MASK_ZBKC (1 << 1)
#define MASK_ZBKX (1 << 2)
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 3d02954..77bc65b 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -5420,6 +5420,13 @@ riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
!= call_used_or_fixed_reg_p (regno + i))
return false;
+ /* Only use even registers in RV32 ZDINX */
+ if (!TARGET_64BIT && TARGET_ZDINX){
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT &&
+ GET_MODE_UNIT_SIZE (mode) == GET_MODE_SIZE (DFmode))
+ return !(regno & 1);
+ }
+
return true;
}
@@ -5659,7 +5666,7 @@ riscv_option_override (void)
error ("%<-mdiv%> requires %<-march%> to subsume the %<M%> extension");
/* Likewise floating-point division and square root. */
- if (TARGET_HARD_FLOAT && (target_flags_explicit & MASK_FDIV) == 0)
+ if ((TARGET_HARD_FLOAT || TARGET_ZFINX) && (target_flags_explicit & MASK_FDIV) == 0)
target_flags |= MASK_FDIV;
/* Handle -mtune, use -mcpu if -mtune is not given, and use default -mtune
@@ -5705,6 +5712,11 @@ riscv_option_override (void)
if (TARGET_RVE && riscv_abi != ABI_ILP32E)
error ("rv32e requires ilp32e ABI");
+ // Zfinx require abi ilp32,ilp32e or lp64.
+ if (TARGET_ZFINX && riscv_abi != ABI_ILP32
+ && riscv_abi != ABI_LP64 && riscv_abi != ABI_ILP32E)
+ error ("z*inx requires ABI ilp32, ilp32e or lp64");
+
/* We do not yet support ILP32 on RV64. */
if (BITS_PER_WORD != POINTER_SIZE)
error ("ABI requires %<-march=rv%d%>", POINTER_SIZE);
@@ -6337,7 +6349,7 @@ riscv_libgcc_floating_mode_supported_p (scalar_float_mode mode)
precision of the _FloatN type; evaluate all other operations and
constants to the range and precision of the semantic type;
- If we have the zfh extensions then we support _Float16 in native
+ If we have the zfh/zhinx extensions then we support _Float16 in native
precision, so we should set this to 16. */
static enum flt_eval_method
riscv_excess_precision (enum excess_precision_type type)
@@ -6346,8 +6358,9 @@ riscv_excess_precision (enum excess_precision_type type)
{
case EXCESS_PRECISION_TYPE_FAST:
case EXCESS_PRECISION_TYPE_STANDARD:
- return (TARGET_ZFH ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
- : FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
+ return ((TARGET_ZFH || TARGET_ZHINX)
+ ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
+ : FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
case EXCESS_PRECISION_TYPE_IMPLICIT:
case EXCESS_PRECISION_TYPE_FLOAT16:
return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index ae907a7..798f737 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -441,7 +441,7 @@
[(set (match_operand:ANYF 0 "register_operand" "=f")
(plus:ANYF (match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fadd.<fmt>\t%0,%1,%2"
[(set_attr "type" "fadd")
(set_attr "mode" "<UNITMODE>")])
@@ -572,7 +572,7 @@
[(set (match_operand:ANYF 0 "register_operand" "=f")
(minus:ANYF (match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fsub.<fmt>\t%0,%1,%2"
[(set_attr "type" "fadd")
(set_attr "mode" "<UNITMODE>")])
@@ -742,7 +742,7 @@
[(set (match_operand:ANYF 0 "register_operand" "=f")
(mult:ANYF (match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fmul.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmul")
(set_attr "mode" "<UNITMODE>")])
@@ -1049,7 +1049,7 @@
[(set (match_operand:ANYF 0 "register_operand" "=f")
(div:ANYF (match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")))]
- "TARGET_HARD_FLOAT && TARGET_FDIV"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX) && TARGET_FDIV"
"fdiv.<fmt>\t%0,%1,%2"
[(set_attr "type" "fdiv")
(set_attr "mode" "<UNITMODE>")])
@@ -1064,7 +1064,7 @@
(define_insn "sqrt<mode>2"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(sqrt:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
- "TARGET_HARD_FLOAT && TARGET_FDIV"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX) && TARGET_FDIV"
{
return "fsqrt.<fmt>\t%0,%1";
}
@@ -1079,7 +1079,7 @@
(fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")
(match_operand:ANYF 3 "register_operand" " f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fmadd.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -1090,7 +1090,7 @@
(fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")
(neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fmsub.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -1102,7 +1102,7 @@
(neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
(match_operand:ANYF 2 "register_operand" " f")
(neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fnmadd.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -1114,7 +1114,7 @@
(neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
(match_operand:ANYF 2 "register_operand" " f")
(match_operand:ANYF 3 "register_operand" " f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fnmsub.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -1127,7 +1127,7 @@
(neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
(match_operand:ANYF 2 "register_operand" " f")
(neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
- "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
"fmadd.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -1140,7 +1140,7 @@
(neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
(match_operand:ANYF 2 "register_operand" " f")
(match_operand:ANYF 3 "register_operand" " f"))))]
- "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
"fmsub.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -1153,7 +1153,7 @@
(match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")
(match_operand:ANYF 3 "register_operand" " f"))))]
- "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
"fnmadd.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -1166,7 +1166,7 @@
(match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")
(neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
- "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
"fnmsub.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -1181,7 +1181,7 @@
(define_insn "abs<mode>2"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(abs:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fabs.<fmt>\t%0,%1"
[(set_attr "type" "fmove")
(set_attr "mode" "<UNITMODE>")])
@@ -1191,7 +1191,7 @@
(unspec:ANYF [(match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")]
UNSPEC_COPYSIGN))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fsgnj.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmove")
(set_attr "mode" "<UNITMODE>")])
@@ -1199,7 +1199,7 @@
(define_insn "neg<mode>2"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(neg:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fneg.<fmt>\t%0,%1"
[(set_attr "type" "fmove")
(set_attr "mode" "<UNITMODE>")])
@@ -1216,7 +1216,7 @@
(unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f"))
(use (match_operand:ANYF 2 "register_operand" " f"))]
UNSPEC_FMIN))]
- "TARGET_HARD_FLOAT && !HONOR_SNANS (<MODE>mode)"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SNANS (<MODE>mode)"
"fmin.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmove")
(set_attr "mode" "<UNITMODE>")])
@@ -1226,7 +1226,7 @@
(unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f"))
(use (match_operand:ANYF 2 "register_operand" " f"))]
UNSPEC_FMAX))]
- "TARGET_HARD_FLOAT && !HONOR_SNANS (<MODE>mode)"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SNANS (<MODE>mode)"
"fmax.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmove")
(set_attr "mode" "<UNITMODE>")])
@@ -1235,7 +1235,7 @@
[(set (match_operand:ANYF 0 "register_operand" "=f")
(smin:ANYF (match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fmin.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmove")
(set_attr "mode" "<UNITMODE>")])
@@ -1244,7 +1244,7 @@
[(set (match_operand:ANYF 0 "register_operand" "=f")
(smax:ANYF (match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fmax.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmove")
(set_attr "mode" "<UNITMODE>")])
@@ -1305,7 +1305,7 @@
[(set (match_operand:SF 0 "register_operand" "=f")
(float_truncate:SF
(match_operand:DF 1 "register_operand" " f")))]
- "TARGET_DOUBLE_FLOAT"
+ "TARGET_DOUBLE_FLOAT || TARGET_ZDINX"
"fcvt.s.d\t%0,%1"
[(set_attr "type" "fcvt")
(set_attr "mode" "SF")])
@@ -1314,7 +1314,7 @@
[(set (match_operand:HF 0 "register_operand" "=f")
(float_truncate:HF
(match_operand:SF 1 "register_operand" " f")))]
- "TARGET_ZFHMIN"
+ "TARGET_ZFHMIN || TARGET_ZHINXMIN"
"fcvt.h.s\t%0,%1"
[(set_attr "type" "fcvt")
(set_attr "mode" "HF")])
@@ -1323,7 +1323,8 @@
[(set (match_operand:HF 0 "register_operand" "=f")
(float_truncate:HF
(match_operand:DF 1 "register_operand" " f")))]
- "TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT"
+ "(TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT) ||
+ (TARGET_ZHINXMIN && TARGET_ZDINX)"
"fcvt.h.d\t%0,%1"
[(set_attr "type" "fcvt")
(set_attr "mode" "HF")])
@@ -1449,7 +1450,7 @@
[(set (match_operand:SF 0 "register_operand" "=f")
(float_extend:SF
(match_operand:HF 1 "register_operand" " f")))]
- "TARGET_ZFHMIN"
+ "TARGET_ZFHMIN || TARGET_ZHINXMIN"
"fcvt.s.h\t%0,%1"
[(set_attr "type" "fcvt")
(set_attr "mode" "SF")])
@@ -1458,7 +1459,7 @@
[(set (match_operand:DF 0 "register_operand" "=f")
(float_extend:DF
(match_operand:SF 1 "register_operand" " f")))]
- "TARGET_DOUBLE_FLOAT"
+ "TARGET_DOUBLE_FLOAT || TARGET_ZDINX"
"fcvt.d.s\t%0,%1"
[(set_attr "type" "fcvt")
(set_attr "mode" "DF")])
@@ -1467,7 +1468,8 @@
[(set (match_operand:DF 0 "register_operand" "=f")
(float_extend:DF
(match_operand:HF 1 "register_operand" " f")))]
- "TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT"
+ "(TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT) ||
+ (TARGET_ZHINXMIN && TARGET_ZDINX)"
"fcvt.d.h\t%0,%1"
[(set_attr "type" "fcvt")
(set_attr "mode" "DF")])
@@ -1513,7 +1515,7 @@
[(set (match_operand:GPR 0 "register_operand" "=r")
(fix:GPR
(match_operand:ANYF 1 "register_operand" " f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,rtz"
[(set_attr "type" "fcvt")
(set_attr "mode" "<ANYF:MODE>")])
@@ -1522,7 +1524,7 @@
[(set (match_operand:GPR 0 "register_operand" "=r")
(unsigned_fix:GPR
(match_operand:ANYF 1 "register_operand" " f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fcvt.<GPR:ifmt>u.<ANYF:fmt> %0,%1,rtz"
[(set_attr "type" "fcvt")
(set_attr "mode" "<ANYF:MODE>")])
@@ -1531,7 +1533,7 @@
[(set (match_operand:ANYF 0 "register_operand" "= f")
(float:ANYF
(match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fcvt.<ANYF:fmt>.<GPR:ifmt>\t%0,%z1"
[(set_attr "type" "fcvt")
(set_attr "mode" "<ANYF:MODE>")])
@@ -1540,7 +1542,7 @@
[(set (match_operand:ANYF 0 "register_operand" "= f")
(unsigned_float:ANYF
(match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fcvt.<ANYF:fmt>.<GPR:ifmt>u\t%0,%z1"
[(set_attr "type" "fcvt")
(set_attr "mode" "<ANYF:MODE>")])
@@ -1550,7 +1552,7 @@
(unspec:GPR
[(match_operand:ANYF 1 "register_operand" " f")]
RINT))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,<rint_rm>"
[(set_attr "type" "fcvt")
(set_attr "mode" "<ANYF:MODE>")])
@@ -2278,7 +2280,7 @@
(match_operand:ANYF 2 "register_operand")])
(label_ref (match_operand 3 ""))
(pc)))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
{
riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
operands[1], operands[2]);
@@ -2367,7 +2369,7 @@
(match_operator:SI 1 "fp_scc_comparison"
[(match_operand:ANYF 2 "register_operand")
(match_operand:ANYF 3 "register_operand")]))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
{
riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2],
operands[3]);
@@ -2379,7 +2381,7 @@
(match_operator:X 1 "fp_native_comparison"
[(match_operand:ANYF 2 "register_operand" " f")
(match_operand:ANYF 3 "register_operand" " f")]))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"f%C1.<fmt>\t%0,%2,%3"
[(set_attr "type" "fcmp")
(set_attr "mode" "<UNITMODE>")])
@@ -2389,7 +2391,7 @@
(unspec:X [(match_operand:ANYF 1 "register_operand")
(match_operand:ANYF 2 "register_operand")]
QUIET_COMPARISON))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
{
rtx op0 = operands[0];
rtx op1 = operands[1];
@@ -2809,19 +2811,19 @@
(define_insn "riscv_frflags"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"frflags\t%0")
(define_insn "riscv_fsflags"
[(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"fsflags\t%0")
(define_insn "*riscv_fsnvsnan<mode>2"
[(unspec_volatile [(match_operand:ANYF 0 "register_operand" "f")
(match_operand:ANYF 1 "register_operand" "f")]
UNSPECV_FSNVSNAN)]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT || TARGET_ZFINX"
"feq.<fmt>\tzero,%0,%1"
[(set_attr "type" "fcmp")
(set_attr "mode" "<UNITMODE>")])
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 9493117..426ea95 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -207,6 +207,9 @@ TargetVariable
int riscv_zb_subext
TargetVariable
+int riscv_zinx_subext
+
+TargetVariable
int riscv_zk_subext
TargetVariable
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 2e7f76a..de9bcbf 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -940,9 +940,10 @@
because of offering further optimization opportunities. */
if (register_operand (operands[0], DImode))
{
- xtensa_split_DI_reg_imm (operands);
- emit_move_insn (operands[0], operands[1]);
- emit_move_insn (operands[2], operands[3]);
+ rtx ops[4] = { operands[0], operands[1] };
+ xtensa_split_DI_reg_imm (ops);
+ emit_move_insn (ops[0], ops[1]);
+ emit_move_insn (ops[2], ops[3]);
DONE;
}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 550515c..d065fd1 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,34 @@
+2022-10-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/107379
+ * name-lookup.cc (push_namespace): Call find_namespace_slot again
+ after pushdecl as the hash table might be expanded during pushdecl.
+
+2022-10-27 Nathan Sidwell <nathan@acm.org>
+
+ * mangle.cc (write_closure_template_head): New.
+ (write_closure_type_name): Call it.
+
+2022-10-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/107382
+ PR c++/107383
+ * typeck.cc (cp_build_binary_op): Don't compute semantic_result_type
+ if result_type is NULL.
+
+2022-10-26 Marek Polacek <polacek@redhat.com>
+
+ PR c++/106393
+ * call.cc (expr_represents_temporary_p): New, factored out of...
+ (conv_binds_ref_to_temporary): ...here. Don't return false just
+ because a ck_base is missing. Use expr_represents_temporary_p.
+ (do_warn_dangling_reference): New.
+ (maybe_warn_dangling_reference): New.
+ (extend_ref_init_temps): Call maybe_warn_dangling_reference.
+ * cp-tree.h: Adjust comment.
+ * typeck.cc (check_return_expr): Suppress -Wdangling-reference
+ warnings.
+
2022-10-25 Nathan Sidwell <nathan@acm.org>
* parser.cc (synthesize_implicit_template_parm): Fix thinko about
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 6a34e9c..951b9fd 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -9313,6 +9313,16 @@ conv_binds_ref_to_prvalue (conversion *c)
return conv_is_prvalue (next_conversion (c));
}
+/* True iff EXPR represents a (subobject of a) temporary. */
+
+static bool
+expr_represents_temporary_p (tree expr)
+{
+ while (handled_component_p (expr))
+ expr = TREE_OPERAND (expr, 0);
+ return TREE_CODE (expr) == TARGET_EXPR;
+}
+
/* True iff C is a conversion that binds a reference to a temporary.
This is a superset of conv_binds_ref_to_prvalue: here we're also
interested in xvalues. */
@@ -9330,18 +9340,14 @@ conv_binds_ref_to_temporary (conversion *c)
struct Derived : Base {};
const Base& b(Derived{});
where we bind 'b' to the Base subobject of a temporary object of type
- Derived. The subobject is an xvalue; the whole object is a prvalue. */
- if (c->kind != ck_base)
- return false;
- c = next_conversion (c);
- if (c->kind == ck_identity && c->u.expr)
- {
- tree expr = c->u.expr;
- while (handled_component_p (expr))
- expr = TREE_OPERAND (expr, 0);
- if (TREE_CODE (expr) == TARGET_EXPR)
- return true;
- }
+ Derived. The subobject is an xvalue; the whole object is a prvalue.
+
+ The ck_base doesn't have to be present for cases like X{}.m. */
+ if (c->kind == ck_base)
+ c = next_conversion (c);
+ if (c->kind == ck_identity && c->u.expr
+ && expr_represents_temporary_p (c->u.expr))
+ return true;
return false;
}
@@ -13428,6 +13434,121 @@ initialize_reference (tree type, tree expr,
return expr;
}
+/* Helper for maybe_warn_dangling_reference to find a problematic CALL_EXPR
+ that initializes the LHS (and at least one of its arguments represents
+ a temporary, as outlined in maybe_warn_dangling_reference), or NULL_TREE
+ if none found. For instance:
+
+ const S& s = S().self(); // S::self (&TARGET_EXPR <...>)
+ const int& r = (42, f(1)); // f(1)
+ const int& t = b ? f(1) : f(2); // f(1)
+ const int& u = b ? f(1) : f(g); // f(1)
+ const int& v = b ? f(g) : f(2); // f(2)
+ const int& w = b ? f(g) : f(g); // NULL_TREE
+ const int& y = (f(1), 42); // NULL_TREE
+ const int& z = f(f(1)); // f(f(1))
+
+ EXPR is the initializer. */
+
+static tree
+do_warn_dangling_reference (tree expr)
+{
+ STRIP_NOPS (expr);
+ switch (TREE_CODE (expr))
+ {
+ case CALL_EXPR:
+ {
+ tree fndecl = cp_get_callee_fndecl_nofold (expr);
+ if (!fndecl
+ || warning_suppressed_p (fndecl, OPT_Wdangling_reference)
+ || !warning_enabled_at (DECL_SOURCE_LOCATION (fndecl),
+ OPT_Wdangling_reference)
+ /* If the function doesn't return a reference, don't warn. This
+ can be e.g.
+ const int& z = std::min({1, 2, 3, 4, 5, 6, 7});
+ which doesn't dangle: std::min here returns an int. */
+ || !TYPE_REF_OBJ_P (TREE_TYPE (TREE_TYPE (fndecl))))
+ return NULL_TREE;
+
+ /* Here we're looking to see if any of the arguments is a temporary
+ initializing a reference parameter. */
+ for (int i = 0; i < call_expr_nargs (expr); ++i)
+ {
+ tree arg = CALL_EXPR_ARG (expr, i);
+ /* Check that this argument initializes a reference, except for
+ the argument initializing the object of a member function. */
+ if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
+ && !TYPE_REF_P (TREE_TYPE (arg)))
+ continue;
+ /* It could also be another call taking a temporary and returning
+ it and initializing this reference parameter. */
+ if (do_warn_dangling_reference (arg))
+ return expr;
+ STRIP_NOPS (arg);
+ if (TREE_CODE (arg) == ADDR_EXPR)
+ arg = TREE_OPERAND (arg, 0);
+ if (expr_represents_temporary_p (arg))
+ return expr;
+ /* Don't warn about member function like:
+ std::any a(...);
+ S& s = a.emplace<S>({0}, 0);
+ which constructs a new object and returns a reference to it, but
+ we still want to detect:
+ struct S { const S& self () { return *this; } };
+ const S& s = S().self();
+ where 's' dangles. If we've gotten here, the object this function
+ is invoked on is not a temporary. */
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl))
+ break;
+ }
+ return NULL_TREE;
+ }
+ case COMPOUND_EXPR:
+ return do_warn_dangling_reference (TREE_OPERAND (expr, 1));
+ case COND_EXPR:
+ if (tree t = do_warn_dangling_reference (TREE_OPERAND (expr, 1)))
+ return t;
+ return do_warn_dangling_reference (TREE_OPERAND (expr, 2));
+ case PAREN_EXPR:
+ return do_warn_dangling_reference (TREE_OPERAND (expr, 0));
+ default:
+ return NULL_TREE;
+ }
+}
+
+/* Implement -Wdangling-reference, to detect cases like
+
+ int n = 1;
+ const int& r = std::max(n - 1, n + 1); // r is dangling
+
+ This creates temporaries from the arguments, returns a reference to
+ one of the temporaries, but both temporaries are destroyed at the end
+ of the full expression.
+
+ This works by checking if a reference is initialized with a function
+ that returns a reference, and at least one parameter of the function
+ is a reference that is bound to a temporary. It assumes that such a
+ function actually returns one of its arguments.
+
+ DECL is the reference being initialized, INIT is the initializer. */
+
+static void
+maybe_warn_dangling_reference (const_tree decl, tree init)
+{
+ if (!warn_dangling_reference)
+ return;
+ if (!TYPE_REF_P (TREE_TYPE (decl)))
+ return;
+ if (tree call = do_warn_dangling_reference (init))
+ {
+ auto_diagnostic_group d;
+ if (warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wdangling_reference,
+ "possibly dangling reference to a temporary"))
+ inform (EXPR_LOCATION (call), "the temporary was destroyed at "
+ "the end of the full expression %qE", call);
+ }
+}
+
/* If *P is an xvalue expression, prevent temporary lifetime extension if it
gets used to initialize a reference. */
@@ -13525,6 +13646,9 @@ extend_ref_init_temps (tree decl, tree init, vec<tree, va_gc> **cleanups,
tree type = TREE_TYPE (init);
if (processing_template_decl)
return init;
+
+ maybe_warn_dangling_reference (decl, init);
+
if (TYPE_REF_P (type))
init = extend_ref_init_temps_1 (decl, init, cleanups, cond_guard);
else
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 867096b..6d84514 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -459,7 +459,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
DELETE_EXPR_USE_VEC (in DELETE_EXPR).
- (TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
ICS_ELLIPSIS_FLAG (in _CONV)
DECL_INITIALIZED_P (in VAR_DECL)
TYPENAME_IS_CLASS_P (in TYPENAME_TYPE)
@@ -4508,30 +4507,6 @@ get_vec_init_expr (tree t)
#define OPAQUE_ENUM_P(TYPE) \
(TREE_CODE (TYPE) == ENUMERAL_TYPE && ENUM_IS_OPAQUE (TYPE))
-/* Determines whether an ENUMERAL_TYPE has an explicit
- underlying type. */
-#define ENUM_FIXED_UNDERLYING_TYPE_P(NODE) (TYPE_LANG_FLAG_5 (NODE))
-
-/* Returns the underlying type of the given enumeration type. The
- underlying type is determined in different ways, depending on the
- properties of the enum:
-
- - In C++0x, the underlying type can be explicitly specified, e.g.,
-
- enum E1 : char { ... } // underlying type is char
-
- - In a C++0x scoped enumeration, the underlying type is int
- unless otherwises specified:
-
- enum class E2 { ... } // underlying type is int
-
- - Otherwise, the underlying type is determined based on the
- values of the enumerators. In this case, the
- ENUM_UNDERLYING_TYPE will not be set until after the definition
- of the enumeration is completed by finish_enum. */
-#define ENUM_UNDERLYING_TYPE(TYPE) \
- TREE_TYPE (ENUMERAL_TYPE_CHECK (TYPE))
-
/* [dcl.init.aggr]
An aggregate is an array or a class with no user-provided
@@ -4567,6 +4542,9 @@ get_vec_init_expr (tree t)
When appearing in a CONSTRUCTOR, the expression is an unconverted
compound literal.
+ When appearing in a CALL_EXPR, it means that it is a call to
+ a constructor.
+
When appearing in a FIELD_DECL, it means that this field
has been duly initialized in its constructor. */
#define TREE_HAS_CONSTRUCTOR(NODE) (TREE_LANG_FLAG_4 (NODE))
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 1215463..e396218 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -1727,6 +1727,66 @@ write_unnamed_type_name (const tree type)
write_compact_number (discriminator);
}
+// A template head, for templated lambdas.
+// <template-head> ::= Tp* Ty
+// Tp* Tn <type>
+// Tp* Tt <template-head> E
+// New in ABI=18. Returns true iff we emitted anything -- used for ABI
+// version warning.
+
+static bool
+write_closure_template_head (tree tmpl)
+{
+ bool any = false;
+
+ // We only need one level of template parms
+ tree inner = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
+
+ for (int ix = 0, len = TREE_VEC_LENGTH (inner); ix != len; ix++)
+ {
+ tree parm = TREE_VEC_ELT (inner, ix);
+ if (parm == error_mark_node)
+ continue;
+ parm = TREE_VALUE (parm);
+
+ if (DECL_VIRTUAL_P (parm))
+ // A synthetic parm, we're done.
+ break;
+
+ any = true;
+ if (abi_version_at_least (18))
+ {
+ if (TREE_CODE (parm) == PARM_DECL
+ ? TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))
+ : TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
+ write_string ("Tp");
+
+ switch (TREE_CODE (parm))
+ {
+ default:
+ gcc_unreachable ();
+
+ case TYPE_DECL:
+ write_string ("Ty");
+ break;
+
+ case PARM_DECL:
+ write_string ("Tn");
+ write_type (TREE_TYPE (parm));
+ break;
+
+ case TEMPLATE_DECL:
+ write_string ("Tt");
+ write_closure_template_head (parm);
+ write_string ("E");
+ break;
+ }
+ }
+ }
+
+ return any;
+}
+
/* <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
<lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters */
@@ -1740,6 +1800,14 @@ write_closure_type_name (const tree type)
MANGLE_TRACE_TREE ("closure-type-name", type);
write_string ("Ul");
+
+ if (auto ti = maybe_template_info (fn))
+ if (write_closure_template_head (TI_TEMPLATE (ti)))
+ // If there were any explicit template parms, we may need to
+ // issue a mangling diagnostic.
+ if (abi_warn_or_compat_version_crosses (18))
+ G.need_abi_warning = true;
+
write_method_parms (parms, /*method_p=*/1, fn);
write_char ('E');
write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda));
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 14e937d..dfa6fb4 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -8596,6 +8596,13 @@ push_namespace (tree name, bool make_inline)
/* This should find the slot created by pushdecl. */
gcc_checking_assert (slot && *slot == ns);
}
+ else
+ {
+ /* pushdecl could have expanded the hash table, so
+ slot might be invalid. */
+ slot = find_namespace_slot (current_namespace, name);
+ gcc_checking_assert (slot);
+ }
make_namespace_finish (ns, slot);
/* Add the anon using-directive here, we don't do it in
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index ab6979b..2e0fd8f 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -6179,7 +6179,8 @@ cp_build_binary_op (const op_location_t &location,
}
if (may_need_excess_precision
&& (orig_type0 != type0 || orig_type1 != type1)
- && build_type == NULL_TREE)
+ && build_type == NULL_TREE
+ && result_type)
{
gcc_assert (common);
semantic_result_type = cp_common_type (orig_type0, orig_type1);
@@ -11246,6 +11247,17 @@ check_return_expr (tree retval, bool *no_warning)
if (processing_template_decl)
return saved_retval;
+ /* A naive attempt to reduce the number of -Wdangling-reference false
+ positives: if we know that this function can return a variable with
+ static storage duration rather than one of its parameters, suppress
+ the warning. */
+ if (warn_dangling_reference
+ && TYPE_REF_P (functype)
+ && bare_retval
+ && VAR_P (bare_retval)
+ && TREE_STATIC (bare_retval))
+ suppress_warning (current_function_decl, OPT_Wdangling_reference);
+
/* Actually copy the value returned into the appropriate location. */
if (retval && retval != result)
retval = cp_build_init_expr (result, retval);
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 3a1d4a5..48f3b9a 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -15750,6 +15750,83 @@ Load 32-bits from the @code{struct sk_buff} packet data pointed by the register
BPF Compile Once-Run Everywhere (CO-RE) support. Instruct GCC to generate CO-RE relocation records for any accesses to aggregate data structures (struct, union, array types) in @var{expr}. This builtin is otherwise transparent, the return value is whatever @var{expr} evaluates to. It is also overloaded: @var{expr} may be of any type (not necessarily a pointer), the return type is the same. Has no effect if @code{-mco-re} is not in effect (either specified or implied).
@end deftypefn
+@deftypefn {Built-in Function} unsigned int __builtin_preserve_field_info (@var{expr}, unsigned int @var{kind})
+BPF Compile Once-Run Everywhere (CO-RE) support. This builtin is used to
+extract information to aid in struct/union relocations. @var{expr} is
+an access to a field of a struct or union. Depending on @var{kind}, different
+information is returned to the program. A CO-RE relocation for the access in
+@var{expr} with kind @var{kind} is recorded if @code{-mco-re} is in effect.
+
+The following values are supported for @var{kind}:
+@table @var
+@item FIELD_BYTE_OFFSET = 0
+The returned value is the offset, in bytes, of the field from the
+beginning of the containing structure. For bitfields, the byte offset
+of the containing word.
+
+@item FIELD_BYTE_SIZE = 1
+The returned value is the size, in bytes, of the field. For bitfields,
+the size in bytes of the containing word.
+
+@item FIELD_EXISTENCE = 2
+The returned value is 1 if the field exists, 0 otherwise. Always 1 at
+compile time.
+
+@item FIELD_SIGNEDNESS = 3
+The returned value is 1 if the field is signed, 0 otherwise.
+
+@item FIELD_LSHIFT_U64 = 4
+@itemx FIELD_RSHIFT_U64 = 5
+The returned value is the number of bits of left- or right-shifting
+respectively needed in order to recover the original value of the field,
+after it has been loaded by a read of FIELD_BYTE_SIZE bytes into an
+unsigned 64-bit value. Primarily useful for reading bitfield values
+from structures which may change between kernel versions.
+
+@end table
+
+Note that the return value is a constant which is known at
+compile-time. If the field has a variable offset then
+FIELD_BYTE_OFFSET, FIELD_LSHIFT_U64 and FIELD_RSHIFT_U64 are not
+supported. Similarly, if the field has a variable size then
+FIELD_BYTE_SIZE, FIELD_LSHIFT_U64 and FIELD_RSHIFT_U64 are not
+supported.
+
+For example, __builtin_preserve_field_info can be used to reliably
+extract bitfield values from a structure which may change between
+kernel versions:
+
+@example
+struct S
+@{
+ short a;
+ int x:7;
+ int y:5;
+@};
+
+int
+read_y (struct S *arg)
+@{
+ unsigned long long val;
+ unsigned int offset = __builtin_preserve_field_info (arg->y, FIELD_BYTE_OFFSET);
+ unsigned int size = __builtin_presrve_field_info (arg->y, FIELD_BYTE_SIZE);
+
+ /* Read size bytes from arg + offset into val. */
+ bpf_probe_read (&val, size, arg + offset);
+
+ val <<= __builtin_preserve_field_info (arg->y, FIELD_LSHIFT_U64);
+
+ if (__builtin_preserve_field_info (arg->y, FIELD_SIGNEDNESS))
+ val = ((long long) val >> __builtin_preserve_field_info (arg->y, FIELD_RSHIFT_U64));
+ else
+ val >>= __builtin_preserve_field_info (arg->y, FIELD_RSHIFT_U64);
+
+ return val;
+@}
+
+@end example
+@end deftypefn
+
@node FR-V Built-in Functions
@subsection FR-V Built-in Functions
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ed79440..f138db2 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -211,7 +211,8 @@ in the following sections.
-Wno-class-conversion -Wclass-memaccess @gol
-Wcomma-subscript -Wconditionally-supported @gol
-Wno-conversion-null -Wctad-maybe-unsupported @gol
--Wctor-dtor-privacy -Wno-delete-incomplete @gol
+-Wctor-dtor-privacy -Wdangling-reference @gol
+-Wno-delete-incomplete @gol
-Wdelete-non-virtual-dtor -Wno-deprecated-array-compare @gol
-Wdeprecated-copy -Wdeprecated-copy-dtor @gol
-Wno-deprecated-enum-enum-conversion -Wno-deprecated-enum-float-conversion @gol
@@ -3589,6 +3590,54 @@ public static member functions. Also warn if there are no non-private
methods, and there's at least one private member function that isn't
a constructor or destructor.
+@item -Wdangling-reference @r{(C++ and Objective-C++ only)}
+@opindex Wdangling-reference
+@opindex Wno-dangling-reference
+Warn when a reference is bound to a temporary whose lifetime has ended.
+For example:
+
+@smallexample
+int n = 1;
+const int& r = std::max(n - 1, n + 1); // r is dangling
+@end smallexample
+
+In the example above, two temporaries are created, one for each
+argument, and a reference to one of the temporaries is returned.
+However, both temporaries are destroyed at the end of the full
+expression, so the reference @code{r} is dangling. This warning
+also detects dangling references in member initializer lists:
+
+@smallexample
+const int& f(const int& i) @{ return i; @}
+struct S @{
+ const int &r; // r is dangling
+ S() : r(f(10)) @{ @}
+@};
+@end smallexample
+
+Member functions are checked as well, but only their object argument:
+
+@smallexample
+struct S @{
+ const S& self () @{ return *this; @}
+@};
+const S& s = S().self(); // s is dangling
+@end smallexample
+
+Certain functions are safe in this respect, for example @code{std::use_facet}:
+they take and return a reference, but they don't return one of its arguments,
+which can fool the warning. Such functions can be excluded from the warning
+by wrapping them in a @code{#pragma}:
+
+@smallexample
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdangling-reference"
+const T& foo (const T&) @{ @dots{} @}
+#pragma GCC diagnostic pop
+@end smallexample
+
+This warning is enabled by @option{-Wall}.
+
@item -Wdelete-non-virtual-dtor @r{(C++ and Objective-C++ only)}
@opindex Wdelete-non-virtual-dtor
@opindex Wno-delete-non-virtual-dtor
@@ -16422,6 +16471,10 @@ by this option.
@end table
+Note the enabled sanitizer options tend to increase a false-positive rate
+of selected warnings, most notably @option{-Wmaybe-uninitialized}.
+And thus we recommend to disable @option{-Werror}.
+
While @option{-ftrapv} causes traps for signed overflows to be emitted,
@option{-fsanitize=undefined} gives a diagnostic message.
This currently works only for the C family of languages.
diff --git a/gcc/doc/makefile.texi b/gcc/doc/makefile.texi
index fe0bbcd..5186c1c 100644
--- a/gcc/doc/makefile.texi
+++ b/gcc/doc/makefile.texi
@@ -135,6 +135,16 @@ Compares the results of stages 2 and 3. This ensures that the compiler
is running properly, since it should produce the same object files
regardless of how it itself was compiled.
+@item distclean-stage@var{N} (@var{N} = 1@dots{}4, profile, feedback)
+Wipe stage @var{N} and all the following ones.
+
+For example,
+@samp{make distclean-stage3} wipes stage 3 and all the following ones,
+so that another @command{make} then rebuilds them from scratch.
+This can be useful if you're doing changes where
+``bubbling'' the changes as described above is not sufficient,
+but a full @command{make restrap} isn't necessary either.
+
@item profiledbootstrap
Builds a compiler with profiling feedback information. In this case,
the second and third stages are named @samp{profile} and @samp{feedback},
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index f764113..1ca82cd 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,9 @@
+2022-10-26 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/103413
+ * symbol.cc (gfc_type_compatible): A boz-literal-constant has no type
+ and thus is not considered compatible to any type.
+
2022-10-21 José Rui Faustino de Sousa <jrfsousa@gmail.com>
PR fortran/100097
diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc
index 6050359..49fb378 100644
--- a/gcc/fortran/symbol.cc
+++ b/gcc/fortran/symbol.cc
@@ -5139,6 +5139,10 @@ gfc_type_compatible (gfc_typespec *ts1, gfc_typespec *ts2)
bool is_union1 = (ts1->type == BT_UNION);
bool is_union2 = (ts2->type == BT_UNION);
+ /* A boz-literal-constant has no type. */
+ if (ts1->type == BT_BOZ || ts2->type == BT_BOZ)
+ return false;
+
if (is_class1
&& ts1->u.derived->components
&& ((ts1->u.derived->attr.is_class
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index f919237..a899d82 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -494,6 +494,14 @@ fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name)
else if (is_a<gassign *> (s) && gimple_assign_rhs_code (s) == COND_EXPR)
res = range_of_cond_expr (r, as_a<gassign *> (s), src);
+ // If the result is varying, check for basic nonnegativeness.
+ // Specifically this helps for now with strict enum in cases like
+ // g++.dg/warn/pr33738.C.
+ bool so_p;
+ if (res && r.varying_p () && INTEGRAL_TYPE_P (r.type ())
+ && gimple_stmt_nonnegative_warnv_p (s, &so_p))
+ r.set_nonnegative (r.type ());
+
if (!res)
{
// If no name specified or range is unsupported, bail.
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 5b95b38..7e531c3 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-6c188108858e3ae8c8ea8e4cc55427d8cf01bbc8
+5e658f4659c551330ea68f5667e4f951b218f32d
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/ipa-visibility.cc b/gcc/ipa-visibility.cc
index 3ed2b7c..238f7eb 100644
--- a/gcc/ipa-visibility.cc
+++ b/gcc/ipa-visibility.cc
@@ -886,8 +886,12 @@ function_and_variable_visibility (bool whole_program)
&& vnode->ref_list.referring.length ())
{
enum tls_model new_model = decl_default_tls_model (decl);
- gcc_checking_assert (new_model >= decl_tls_model (decl));
- set_decl_tls_model (decl, new_model);
+ STATIC_ASSERT (TLS_MODEL_GLOBAL_DYNAMIC < TLS_MODEL_LOCAL_DYNAMIC);
+ STATIC_ASSERT (TLS_MODEL_INITIAL_EXEC < TLS_MODEL_LOCAL_EXEC);
+ /* We'd prefer to assert that recomputed model is not weaker than
+ what the front-end assigned, but cannot: see PR 107353. */
+ if (new_model >= decl_tls_model (decl))
+ set_decl_tls_model (decl, new_model);
}
}
}
diff --git a/gcc/ira.cc b/gcc/ira.cc
index 42c9cea..d28a67b 100644
--- a/gcc/ira.cc
+++ b/gcc/ira.cc
@@ -5718,6 +5718,7 @@ ira (FILE *f)
regstat_free_ri ();
regstat_init_n_sets_and_refs ();
regstat_compute_ri ();
+ resize_reg_info ();
};
int max_regno_before_rm = max_reg_num ();
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 84fc5a4..e36fa44 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,8 @@
+2022-10-27 Martin Liska <mliska@suse.cz>
+
+ PR lto/107418
+ * lto-dump.cc (lto_main): Do not load LTO stream for aliases.
+
2022-09-15 Richard Biener <rguenther@suse.de>
* lto-lang.cc (lto_build_c_type_nodes): Do not initialize
diff --git a/gcc/lto/lto-dump.cc b/gcc/lto/lto-dump.cc
index f3d852d..5c4dbf5 100644
--- a/gcc/lto/lto-dump.cc
+++ b/gcc/lto/lto-dump.cc
@@ -227,7 +227,6 @@ void dump_list (void)
{
dump_list_functions ();
dump_list_variables ();
- return;
}
/* Dump specific variables and functions used in IL. */
@@ -243,7 +242,6 @@ void dump_symbol ()
printf ("\n");
}
}
- return;
}
/* Dump specific gimple body of specified function. */
@@ -259,19 +257,17 @@ void dump_body ()
return;
}
cgraph_node *cnode;
- FOR_EACH_FUNCTION (cnode)
- if (cnode->definition
- && !cnode->alias
- && !strcmp (cnode->name (), flag_dump_body))
+ FOR_EACH_DEFINED_FUNCTION (cnode)
+ if (!cnode->alias
+ && !strcmp (cnode->asm_name (), flag_dump_body))
{
- printf ("Gimple Body of Function: %s\n", cnode->name ());
+ printf ("GIMPLE body of function: %s\n\n", cnode->asm_name ());
cnode->get_untransformed_body ();
debug_function (cnode->decl, flags);
flag = 1;
}
if (!flag)
error_at (input_location, "Function not found.");
- return;
}
/* List of command line options for dumping. */
@@ -292,13 +288,12 @@ void dump_tool_help ()
" -callgraph Dump the callgraph in graphviz format.\n"
" -type-stats Dump statistics of tree types.\n"
" -tree-stats Dump statistics of trees.\n"
- " -gimple-stats Dump statistics of gimple statements.\n"
- " -dump-body= Dump the specific gimple body.\n"
+ " -gimple-stats Dump statistics of GIMPLE statements.\n"
+ " -dump-body= Dump the specific GIMPLE body.\n"
" -dump-level= Deciding the optimization level of body.\n"
" -help Display the dump tool help.\n";
fputs (msg, stdout);
- return;
}
unsigned int
@@ -347,7 +342,8 @@ lto_main (void)
/* Dump gimple statement statistics. */
cgraph_node *node;
FOR_EACH_DEFINED_FUNCTION (node)
- node->get_untransformed_body ();
+ if (!node->alias)
+ node->get_untransformed_body ();
if (!GATHER_STATISTICS)
warning_at (input_location, 0,
"Not configured with "
@@ -364,7 +360,7 @@ lto_main (void)
"%<--enable-gather-detailed-mem-stats%>.");
else
{
- printf ("Tree Statistics\n");
+ printf ("Tree statistics\n");
dump_tree_statistics ();
}
}
diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk
index 49065ce..2b8557f 100644
--- a/gcc/optc-save-gen.awk
+++ b/gcc/optc-save-gen.awk
@@ -1291,7 +1291,22 @@ for (i = 0; i < n_opts; i++) {
var_opt_val_type[n_opt_val] = otype;
var_opt_val[n_opt_val] = "x_" name;
var_opt_hash[n_opt_val] = flag_set_p("Optimization", flags[i]);
- var_opt_init[n_opt_val] = opt_args("Init", flags[i]);
+
+ # If applicable, optimize streaming for the common case that
+ # the current value is unchanged from the 'Init' value:
+ # XOR-encode it so that we stream value zero.
+ # Not handling non-parameters as those really generally don't
+ # have large initializers.
+ # Not handling enums as we don't know if '(enum ...) 10' is
+ # even valid (see synthesized 'if' conditionals below).
+ if (flag_set_p("Param", flags[i]) \
+ && !(otype ~ "^enum ")) {
+ # Those without 'Init' are zero-initialized and thus
+ # already encoded ideally.
+ init = opt_args("Init", flags[i])
+ var_opt_optimize_init[n_opt_val] = init;
+ }
+
n_opt_val++;
}
}
@@ -1369,9 +1384,10 @@ for (i = 0; i < n_opt_val; i++) {
} else {
sgn = "int";
}
- if (name ~ "^x_param" && !(otype ~ "^enum ") && var_opt_init[i]) {
- print " if (" var_opt_init[i] " > (" var_opt_val_type[i] ") 10)";
- print " bp_pack_var_len_" sgn " (bp, ptr->" name" ^ " var_opt_init[i] ");";
+ # If applicable, encode the streamed value.
+ if (var_opt_optimize_init[i]) {
+ print " if (" var_opt_optimize_init[i] " > (" var_opt_val_type[i] ") 10)";
+ print " bp_pack_var_len_" sgn " (bp, ptr->" name" ^ " var_opt_optimize_init[i] ");";
print " else";
print " bp_pack_var_len_" sgn " (bp, ptr->" name");";
} else {
@@ -1405,9 +1421,10 @@ for (i = 0; i < n_opt_val; i++) {
sgn = "int";
}
print " ptr->" name" = (" var_opt_val_type[i] ") bp_unpack_var_len_" sgn " (bp);";
- if (name ~ "^x_param" && !(otype ~ "^enum ") && var_opt_init[i]) {
- print " if (" var_opt_init[i] " > (" var_opt_val_type[i] ") 10)";
- print " ptr->" name" ^= " var_opt_init[i] ";";
+ # If applicable, decode the streamed value.
+ if (var_opt_optimize_init[i]) {
+ print " if (" var_opt_optimize_init[i] " > (" var_opt_val_type[i] ") 10)";
+ print " ptr->" name" ^= " var_opt_optimize_init[i] ";";
}
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 09c4108..83d372a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,111 @@
+2022-10-27 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/107172
+ * gcc.target/i386/pr107172.c: New test.
+
+2022-10-27 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/abi/lambda-ctx1-18.C: Adjust.
+ * g++.dg/abi/lambda-ctx1-18vs17.C: Adjust.
+ * g++.dg/abi/lambda-tpl1-17.C: New.
+ * g++.dg/abi/lambda-tpl1-18.C: New.
+ * g++.dg/abi/lambda-tpl1-18vs17.C: New.
+ * g++.dg/abi/lambda-tpl1.h: New.
+
+2022-10-27 Aldy Hernandez <aldyh@redhat.com>
+
+ PR tree-optimization/107394
+ * gcc.dg/tree-ssa/pr107394.c: New test.
+
+2022-10-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/107382
+ PR c++/107383
+ * g++.dg/diagnostic/bad-binary-ops2.C: New test.
+
+2022-10-27 Jiawei <jiawei@iscas.ac.cn>
+
+ * gcc.target/riscv/_Float16-zhinx-1.c: New test.
+ * gcc.target/riscv/_Float16-zhinx-2.c: New test.
+ * gcc.target/riscv/_Float16-zhinx-3.c: New test.
+ * gcc.target/riscv/_Float16-zhinxmin-1.c: New test.
+ * gcc.target/riscv/_Float16-zhinxmin-2.c: New test.
+ * gcc.target/riscv/_Float16-zhinxmin-3.c: New test.
+
+2022-10-26 David Malcolm <dmalcolm@redhat.com>
+
+ * gcc.dg/analyzer/fd-3.c (test_5): Expect "opened here" message
+ even when flags are symbolic.
+ (test_read_from_symbolic_fd): New.
+ (test_write_to_symbolic_fd): New.
+
+2022-10-26 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/103413
+ * gfortran.dg/illegal_boz_arg_4.f90: New test.
+
+2022-10-26 David Faust <david.faust@oracle.com>
+
+ * gcc.target/bpf/core-builtin-fieldinfo-errors-1.c: New test.
+ * gcc.target/bpf/core-builtin-fieldinfo-errors-2.c: New test.
+ * gcc.target/bpf/core-builtin-fieldinfo-existence-1.c: New test.
+ * gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c: New test.
+ * gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c: New test.
+ * gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c: New test.
+ * gcc.target/bpf/core-builtin-fieldinfo-offset-1.c: New test.
+ * gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c: New test.
+ * gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c: New test.
+ * gcc.target/bpf/core-builtin-fieldinfo-sign-1.c: New test.
+ * gcc.target/bpf/core-builtin-fieldinfo-sign-2.c: New test.
+ * gcc.target/bpf/core-builtin-fieldinfo-size-1.c: New test.
+
+2022-10-26 Marek Polacek <polacek@redhat.com>
+
+ PR c++/106393
+ * g++.dg/cpp23/elision4.C: Use -Wdangling-reference, add dg-warning.
+ * g++.dg/cpp23/elision7.C: Likewise.
+ * g++.dg/warn/Wdangling-pointer-2.C: Use -Wno-dangling-reference.
+ * g++.dg/warn/Wdangling-reference1.C: New test.
+ * g++.dg/warn/Wdangling-reference2.C: New test.
+ * g++.dg/warn/Wdangling-reference3.C: New test.
+
+2022-10-26 Ju-Zhe Zhong <juzhe.zhong@rivai.ai>
+
+ * gcc.target/riscv/rvv/base/mov-1.c: New.
+ * gcc.target/riscv/rvv/base/mov-10.c: New.
+ * gcc.target/riscv/rvv/base/mov-11.c: New.
+ * gcc.target/riscv/rvv/base/mov-12.c: New.
+ * gcc.target/riscv/rvv/base/mov-13.c: New.
+ * gcc.target/riscv/rvv/base/mov-2.c: New.
+ * gcc.target/riscv/rvv/base/mov-3.c: New.
+ * gcc.target/riscv/rvv/base/mov-4.c: New.
+ * gcc.target/riscv/rvv/base/mov-5.c: New.
+ * gcc.target/riscv/rvv/base/mov-6.c: New.
+ * gcc.target/riscv/rvv/base/mov-7.c: New.
+ * gcc.target/riscv/rvv/base/mov-8.c: New.
+ * gcc.target/riscv/rvv/base/mov-9.c: New.
+
+2022-10-26 Monk Chiang <monk.chiang@sifive.com>
+
+ * gcc.target/riscv/predef-24.c:New.
+ * gcc.target/riscv/predef-25.c:New.
+
+2022-10-26 Jiufu Guo <guojiufu@linux.ibm.com>
+
+ PR target/106460
+ * gcc.target/powerpc/pr106460.c: New test.
+
+2022-10-26 Kito Cheng <kito.cheng@sifive.com>
+
+ * gcc.target/riscv/arch-18.c: New.
+ * gcc.target/riscv/arch-5.c: Remove test for prefixed
+ with `h`.
+ * gcc.target/riscv/predef-23.c: New.
+
+2022-10-26 Eugene Rozenfeld <erozen@microsoft.com>
+
+ * lib/profopt.exp: Don't force DWARF4 for AutoFDO tests
+
2022-10-25 Patrick Palka <ppalka@redhat.com>
PR c++/106848
diff --git a/gcc/testsuite/g++.dg/abi/lambda-ctx1-18.C b/gcc/testsuite/g++.dg/abi/lambda-ctx1-18.C
index c1c9e27..3dd68a4 100644
--- a/gcc/testsuite/g++.dg/abi/lambda-ctx1-18.C
+++ b/gcc/testsuite/g++.dg/abi/lambda-ctx1-18.C
@@ -6,6 +6,6 @@
// These correctly include the lambda's extra context as a
// substitution candidate, and thus demangle as expected
// { dg-final { scan-assembler {_ZNK1C1fMUlT_E_clIMS_iEEDaS1_:} } }
-// { dg-final { scan-assembler {_ZNK2L2MUlT_T0_E_clIifEEvS0_S1_:} } }
-// { dg-final { scan-assembler {_ZNK1B2L3MUlT_T0_E_clIjdEEvS1_S2_:} } }
+// { dg-final { scan-assembler {_ZNK2L2MUlTyTyT_T0_E_clIifEEvS0_S1_:} } }
+// { dg-final { scan-assembler {_ZNK1B2L3MUlTyTyT_T0_E_clIjdEEvS1_S2_:} } }
// { dg-final { scan-assembler {_Z3fooIN1qMUlvE_ENS0_UlvE0_EEiOT_OT0_:} } }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-ctx1-18vs17.C b/gcc/testsuite/g++.dg/abi/lambda-ctx1-18vs17.C
index f5ec905..ec6709a 100644
--- a/gcc/testsuite/g++.dg/abi/lambda-ctx1-18vs17.C
+++ b/gcc/testsuite/g++.dg/abi/lambda-ctx1-18vs17.C
@@ -3,7 +3,7 @@
#include "lambda-ctx1.h"
-// { dg-regexp {[^\n]*lambda-ctx1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK1B2L3MUlT_T0_E_clIjdEEvS0_S1_'\) and '-fabi-version=18' \('_ZNK1B2L3MUlT_T0_E_clIjdEEvS1_S2_'\) [^\n]*\n} }
-// { dg-regexp {[^\n]*lambda-ctx1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK2L2MUlT_T0_E_clIifEEvS_S0_'\) and '-fabi-version=18' \('_ZNK2L2MUlT_T0_E_clIifEEvS0_S1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-ctx1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK1B2L3MUlT_T0_E_clIjdEEvS0_S1_'\) and '-fabi-version=18' \('_ZNK1B2L3MUlTyTyT_T0_E_clIjdEEvS1_S2_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-ctx1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK2L2MUlT_T0_E_clIifEEvS_S0_'\) and '-fabi-version=18' \('_ZNK2L2MUlTyTyT_T0_E_clIifEEvS0_S1_'\) [^\n]*\n} }
// { dg-regexp {[^\n]*lambda-ctx1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK1C1fMUlT_E_clIMS_iEEDaS0_'\) and '-fabi-version=18' \('_ZNK1C1fMUlT_E_clIMS_iEEDaS1_'\) [^\n]*\n} }
// { dg-regexp {[^\n]*lambda-ctx1.h:[:0-9]* warning: the mangled name [^\n]* \('_Z3fooIN1qMUlvE_EN1qMUlvE0_EEiOT_OT0_'\) and '-fabi-version=18' \('_Z3fooIN1qMUlvE_ENS0_UlvE0_EEiOT_OT0_'\) [^\n]*\n} }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-tpl1-17.C b/gcc/testsuite/g++.dg/abi/lambda-tpl1-17.C
new file mode 100644
index 0000000..b61aaf9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/lambda-tpl1-17.C
@@ -0,0 +1,20 @@
+// { dg-do compile { target c++20 } }
+// { dg-options -fabi-version=17 }
+
+#include "lambda-tpl1.h"
+
+// { dg-final { scan-assembler {_ZNK6l_autoMUlT_E_clIiEEDaS_:} } }
+// { dg-final { scan-assembler {_ZNK5l_tplMUlT_E_clIiEEDaS_:} } }
+// { dg-final { scan-assembler {_ZNK10l_tpl_autoMUlT_T0_E_clIiiEEDaS_S0_:} } }
+// { dg-final { scan-assembler {_ZNK12l_tpl_nt_aryMUlRAT__iE_clILi2EEEDaS0_:} } }
+// { dg-final { scan-assembler {_ZNK13l_tpl_nt_autoMUlvE_clILi0EEEDav:} } }
+// { dg-final { scan-assembler {_ZNK9l_tpl_tplMUlR3TPLIT_EE_clI1UEEDaS2_:} } }
+// { dg-final { scan-assembler {_ZNK13l_tpl_tpl_tplMUlR6TPLTPLIT_EE_clI3TPLEEDaS2_:} } }
+// { dg-final { scan-assembler {_ZNK5l_varMUlDpT_E_clIJiiiEEEDaS0_:} } }
+
+// This mangling might not be correct, it is my best guess:
+// { FIXMEdg-final { scan-assembler {_ZNK6l_var2MUlDpRAT__iE_clIJLi2ELi2EEEEDaS1_:} } }
+
+// { dg-final { scan-assembler {_ZNK6l_var3MUlRT_IJXspT0_EEEE_clI1XJLi1ELi2ELi3EEEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZNK6l_var4MUlR1YIJDpT_EEE_clIJ1US6_EEEDaS3_:} } }
+// { dg-final { scan-assembler {_ZZ2FnILi1EEvvENKUlT_E_clIiEEDaS0_:} } }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-tpl1-18.C b/gcc/testsuite/g++.dg/abi/lambda-tpl1-18.C
new file mode 100644
index 0000000..dbeea40
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/lambda-tpl1-18.C
@@ -0,0 +1,25 @@
+// { dg-do compile { target c++20 } }
+
+#include "lambda-tpl1.h"
+
+// { dg-final { scan-assembler {_ZNK6l_autoMUlT_E_clIiEEDaS0_:} } }
+// { dg-final { scan-assembler {_ZNK5l_tplMUlTyT_E_clIiEEDaS0_:} } }
+// { dg-final { scan-assembler {_ZNK10l_tpl_autoMUlTyT_T0_E_clIiiEEDaS0_S1_:} } }
+// { dg-final { scan-assembler {_ZNK12l_tpl_nt_aryMUlTniRAT__iE_clILi2EEEDaS1_:} } }
+// { dg-final { scan-assembler {_ZNK13l_tpl_nt_autoMUlTnDavE_clILi0EEEDav:} } }
+// { dg-final { scan-assembler {_ZNK9l_tpl_tplMUlTtTyTnjER3TPLIT_EE_clI1UEEDaS3_:} } }
+// { dg-final { scan-assembler {_ZNK13l_tpl_tpl_tplMUlTtTtTyTnjEER6TPLTPLIT_EE_clI3TPLEEDaS3_:} } }
+// { dg-final { scan-assembler {_ZNK5l_varMUlTpTyDpT_E_clIJiiiEEEDaS1_:} } }
+
+// { FIXMEdg-final { scan-assembler {_ZNK6l_var2MUlTpTniDpRAT__iE_clIJLi2ELi2EEEEDaS2_:} } }
+
+// { dg-final { scan-assembler {_ZNK6l_var3MUlTtTpTniETpTniRT_IJXspT0_EEEE_clI1XJLi1ELi2ELi3EEEEDaS2_:} } }
+
+// { dg-final { scan-assembler {_ZNK6l_var4MUlTpTtTyTnjER1YIJDpT_EEE_clIJ1US7_EEEDaS4_:} } }
+// This is a different mangling to clang, which gets
+// _ZNK6l_var4MUlTpTtTyTnjER1YIJDpT_EEE_clIJ1US6_EEEDaS3_
+// However, I think that is incorrect -- it doesn't demangle as
+// expected (using the llvm demangler).
+// https://github.com/llvm/llvm-project/issues/58631
+
+// { dg-final { scan-assembler {_ZZ2FnILi1EEvvENKUlTyT_E_clIiEEDaS0_:} } }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-tpl1-18vs17.C b/gcc/testsuite/g++.dg/abi/lambda-tpl1-18vs17.C
new file mode 100644
index 0000000..8bead73
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/lambda-tpl1-18vs17.C
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++20 } }
+// { dg-options {-fabi-version=18 -Wabi=17} }
+
+#include "lambda-tpl1.h"
+
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZ2FnILi1EEvvENKUlT_E_clIiEEDaS0_'\) and '-fabi-version=18' \('_ZZ2FnILi1EEvvENKUlTyT_E_clIiEEDaS0_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK6l_var4MUlR1YIJDpT_EEE_clIJ1US6_EEEDaS3_'\) and '-fabi-version=18' \('_ZNK6l_var4MUlTpTtTyTnjER1YIJDpT_EEE_clIJ1US7_EEEDaS4_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK6l_var3MUlRT_IJXspT0_EEEE_clI1XJLi1ELi2ELi3EEEEDaS1_'\) and '-fabi-version=18' \('_ZNK6l_var3MUlTtTpTniETpTniRT_IJXspT0_EEEE_clI1XJLi1ELi2ELi3EEEEDaS2_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK5l_varMUlDpT_E_clIJiiiEEEDaS0_'\) and '-fabi-version=18' \('_ZNK5l_varMUlTpTyDpT_E_clIJiiiEEEDaS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK13l_tpl_tpl_tplMUlR6TPLTPLIT_EE_clI3TPLEEDaS2_'\) and '-fabi-version=18' \('_ZNK13l_tpl_tpl_tplMUlTtTtTyTnjEER6TPLTPLIT_EE_clI3TPLEEDaS3_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK9l_tpl_tplMUlR3TPLIT_EE_clI1UEEDaS2_'\) and '-fabi-version=18' \('_ZNK9l_tpl_tplMUlTtTyTnjER3TPLIT_EE_clI1UEEDaS3_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK13l_tpl_nt_autoMUlvE_clILi0EEEDav'\) and '-fabi-version=18' \('_ZNK13l_tpl_nt_autoMUlTnDavE_clILi0EEEDav'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK12l_tpl_nt_aryMUlRAT__iE_clILi2EEEDaS0_'\) and '-fabi-version=18' \('_ZNK12l_tpl_nt_aryMUlTniRAT__iE_clILi2EEEDaS1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK10l_tpl_autoMUlT_T0_E_clIiiEEDaS_S0_'\) and '-fabi-version=18' \('_ZNK10l_tpl_autoMUlTyT_T0_E_clIiiEEDaS0_S1_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK5l_tplMUlT_E_clIiEEDaS_'\) and '-fabi-version=18' \('_ZNK5l_tplMUlTyT_E_clIiEEDaS0_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK6l_autoMUlT_E_clIiEEDaS_'\) and '-fabi-version=18' \('_ZNK6l_autoMUlT_E_clIiEEDaS0_'\) [^\n]*\n} }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-tpl1.h b/gcc/testsuite/g++.dg/abi/lambda-tpl1.h
new file mode 100644
index 0000000..5d6fe5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/lambda-tpl1.h
@@ -0,0 +1,59 @@
+inline auto l_auto = [] (auto) {};
+
+inline auto l_tpl = [] <typename T> (T) {};
+
+inline auto l_tpl_auto = [] <typename T> (T, auto) {};
+
+inline auto l_tpl_nt_ary = [] <int I> (int (&)[I]) {};
+
+inline auto l_tpl_nt_auto = [] <auto I = 0> () {};
+
+template<typename T, unsigned I> class U;
+
+template<template<typename, unsigned> typename> class TPL {};
+inline auto l_tpl_tpl = [] <template<typename, unsigned> typename T> (TPL<T> &) {};
+
+template<template<template<typename, unsigned> typename> typename> class TPLTPL {};
+inline auto l_tpl_tpl_tpl = []<template<template<typename, unsigned> typename> typename T> (TPLTPL<T> &) {};
+
+inline auto l_var = []<typename... Args> (Args...) {};
+
+#if FIXME // we fail to parse (&...) correctly
+inline auto l_var2 = []<int... I> (int (&...)[I]) {};
+#endif
+
+template<int...I> class X {};
+inline auto l_var3 = []<template<int...> typename T, int...I> (T<I...> &a) {};
+
+template<template<typename, unsigned> typename...T> class Y{};
+inline auto l_var4 = []<template<typename, unsigned> typename... T> (Y<T...> &a) {};
+
+template<int I> inline void Fn ()
+{
+ auto l = []<typename T> (T) {};
+ l (1);
+}
+
+void f ()
+{
+ l_auto (1);
+ l_tpl (1);
+ l_tpl_auto (1, 1);
+ int ary[2];
+ l_tpl_nt_ary (ary);
+ l_tpl_nt_auto ();
+ TPL<U> v;
+ l_tpl_tpl (v);
+ TPLTPL<TPL> u;
+ l_tpl_tpl_tpl (u);
+ l_var (1, 2, 3);
+#if FIXME
+ l_var2 (ary, ary);
+#endif
+ X<1,2,3> x;
+ l_var3 (x);
+ Y<U,U> y;
+ l_var4 (y);
+
+ Fn<1> ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/elision4.C b/gcc/testsuite/g++.dg/cpp23/elision4.C
index c19b86b..d39053a 100644
--- a/gcc/testsuite/g++.dg/cpp23/elision4.C
+++ b/gcc/testsuite/g++.dg/cpp23/elision4.C
@@ -1,5 +1,6 @@
// PR c++/101165 - P2266R1 - Simpler implicit move
// { dg-do compile { target c++23 } }
+// { dg-options "-Wdangling-reference" }
// Test from P2266R1, $ 5.2. LibreOffice OString constructor.
struct X {
@@ -33,6 +34,6 @@ T& temporary2(T&& x) { return static_cast<T&>(x); }
void
test ()
{
- int& r1 = temporary1 (42);
- int& r2 = temporary2 (42);
+ int& r1 = temporary1 (42); // { dg-warning "dangling reference" }
+ int& r2 = temporary2 (42); // { dg-warning "dangling reference" }
}
diff --git a/gcc/testsuite/g++.dg/cpp23/elision7.C b/gcc/testsuite/g++.dg/cpp23/elision7.C
index 19fa89a..0045842 100644
--- a/gcc/testsuite/g++.dg/cpp23/elision7.C
+++ b/gcc/testsuite/g++.dg/cpp23/elision7.C
@@ -1,5 +1,6 @@
// PR c++/101165 - P2266R1 - Simpler implicit move
// { dg-do compile { target c++23 } }
+// { dg-options "-Wdangling-reference" }
struct X {
X ();
@@ -68,5 +69,5 @@ f7 (T &&t)
void
do_f7 ()
{
- const int &x = f7 (0);
+ const int &x = f7 (0); // { dg-warning "dangling reference" }
}
diff --git a/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops2.C b/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops2.C
new file mode 100644
index 0000000..627e8a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops2.C
@@ -0,0 +1,26 @@
+// PR c++/107382
+// PR c++/107383
+// { dg-do compile }
+// { dg-options "-O2 -fexcess-precision=standard" }
+
+void
+foo ()
+{
+ float t[2] = { 1, 2 };
+ int const *s = 0;
+ t[1] / s; // { dg-error "invalid operands of types 'float' and 'const int\\\*' to binary 'operator/'" }
+}
+
+void
+bar ()
+{
+ float t[2] = { 1, 2 };
+ int const *s[2] = { 0, 0 };
+ t[1] / s[0]; // { dg-error "invalid operands of types 'float' and 'const int\\\*' to binary 'operator/'" }
+}
+
+void
+baz (float a, int* b)
+{
+ a -= b; // { dg-error "invalid operands of types 'float' and 'int\\\*' to binary 'operator-'" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-pointer-2.C b/gcc/testsuite/g++.dg/warn/Wdangling-pointer-2.C
index 151418f..802ac9c 100644
--- a/gcc/testsuite/g++.dg/warn/Wdangling-pointer-2.C
+++ b/gcc/testsuite/g++.dg/warn/Wdangling-pointer-2.C
@@ -1,5 +1,5 @@
/* { dg-do compile }
- { dg-options "-O1 -Wall -Wno-class-memaccess" } */
+ { dg-options "-O1 -Wall -Wno-class-memaccess -Wno-dangling-reference" } */
struct A { A (); };
diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C
new file mode 100644
index 0000000..97c81ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C
@@ -0,0 +1,144 @@
+// PR c++/106393
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wdangling-reference" }
+
+const int& f(const int& i) { return i; }
+const int& f_(const int& i) { return i; }
+const int& h(int);
+const int& rp(const int *);
+int g;
+const int& globref(const int&) { return g; }
+struct X {
+ int* i;
+ operator const int&() const { return *i; }
+};
+X x{&g};
+
+const int& r1 = f(10); // { dg-warning "dangling reference" }
+// r2 = _ZGR2r2_ = (int) *f ((const int &) &TARGET_EXPR <D.2429, 10>) + 1; (const int &) &_ZGR2r2_
+const int& r2 = f(10) + 1;
+// Don't warn here, we have
+// r3 = f (X::operator const int& (&x))
+const int& r3 = f(x);
+// Don't warn here, because we've seen the definition of globref
+// and could figure out that it may not return one of its parms.
+// Questionable -- it can also hide bugs --, but it helps here.
+const int& r4 = globref(1);
+const int& r5 = (42, f(10)); // { dg-warning "dangling reference" }
+const int& r6 = (f(10), 42);
+const int& r7 = (f(10)); // { dg-warning "dangling reference" }
+const int& r8 = g ? f(10) : f(9); // { dg-warning "dangling reference" }
+const int& r9 = (42, g ? f(10) : f(9)); // { dg-warning "dangling reference" }
+const int& r10 = (g ? f(10) : f(9), 42);
+// Binds to a reference temporary for r11. No dangling reference.
+const int& r11 = g ? f(10) : 9;
+const int& r12 = g ? 9 : f(10);
+// r12 = f (f ((const int &) &TARGET_EXPR <D.2459, 1>))
+const int& r13 = f(f(1)); // { dg-warning "dangling reference" }
+const int& r14 = f(f_(1)); // { dg-warning "dangling reference" }
+const int& r15 = f(g ? f(1) : f(2)); // { dg-warning "dangling reference" }
+const int& r16 = f(*&f(1)); // { dg-warning "dangling reference" }
+const int& r17 = rp(&f(1));
+const int& r18 = rp(&f(g));
+const int& r19 = h(f(1));
+// Other forms of initializers.
+const int& r20(f(10)); // { dg-warning "dangling reference" }
+const int& r21(f(10)); // { dg-warning "dangling reference" }
+// Returns a ref, but doesn't have a parameter of reference type.
+const int& r22 = h(10);
+const int& r23 = g ? h(10) : f(10); // { dg-warning "dangling reference" }
+const int& r24 = g ? f(10) : h(10); // { dg-warning "dangling reference" }
+const int& r25 = g ? h(10) : (1, f(10)); // { dg-warning "dangling reference" }
+const int& r26 = g ? (1, f(10)) : h(10); // { dg-warning "dangling reference" }
+const int& r29 = f((f_(1), 1)); // { dg-warning "dangling reference" }
+const int& r30 = f((f_(1), g));
+
+struct Z {
+ operator int() { return 42; }
+};
+
+const int& r27 = f(Z()); // { dg-warning "dangling reference" }
+const int& r28 = f(true ? Z() : Z()); // { dg-warning "dangling reference" }
+
+const int& operator|(const int &, Z);
+const int& r31 = 1 | Z(); // { dg-warning "dangling reference" }
+
+// OK: the reference is bound to the 10 so still valid at the point
+// where it's copied into i1.
+int i1 = f(10);
+
+int
+test1 ()
+{
+ const int &lr = f(10); // { dg-warning "dangling reference" }
+ int i2 = f(10);
+ return lr;
+}
+
+struct B { };
+struct D : B { };
+struct C {
+ D d;
+};
+
+C c;
+D d;
+
+using U = D[3];
+
+const B& frotz(const D&);
+const B& b1 = frotz(C{}.d); // { dg-warning "dangling reference" }
+const B& b2 = frotz(D{}); // { dg-warning "dangling reference" }
+const B& b3 = frotz(c.d);
+const B& b4 = frotz(d);
+const B& b5 = frotz(U{}[0]); // { dg-warning "dangling reference" }
+
+// Try returning a subobject.
+const B& bar (const D& d) { return d; }
+const B& b6 = bar (D{}); // { dg-warning "dangling reference" }
+const B& baz (const C& c) { return c.d; }
+const B& b7 = baz (C{}); // { dg-warning "dangling reference" }
+const D& qux (const C& c) { return c.d; }
+const D& d1 = qux (C{}); // { dg-warning "dangling reference" }
+
+struct E {
+ E(int);
+};
+const E& operator*(const E&);
+const E& b8 = *E(1); // { dg-warning "dangling reference" }
+
+struct F : virtual B { };
+struct G : virtual B { };
+struct H : F, G { };
+const B& yum (const F& f) { return f; }
+const B& b9 = yum (F{}); // { dg-warning "dangling reference" }
+const B& lox (const H& h) { return h; }
+const B& b10 = lox (H{}); // { dg-warning "dangling reference" }
+
+struct S {
+ const int &r; // { dg-warning "dangling reference" }
+ S() : r(f(10)) { } // { dg-message "destroyed" }
+};
+
+// From cppreference.
+template<class T>
+const T& max(const T& a, const T& b)
+{
+ return (a < b) ? b : a;
+}
+
+int n = 1;
+const int& refmax = max(n - 1, n + 1); // { dg-warning "dangling reference" }
+
+struct Y {
+ operator int&();
+ operator int&&();
+ const int& foo(const int&);
+};
+
+// x1 = Y::operator int&& (&TARGET_EXPR <D.2410, {}>)
+int&& x1 = Y(); // { dg-warning "dangling reference" }
+int&& x2 = Y{}; // { dg-warning "dangling reference" }
+int& x3 = Y(); // { dg-warning "dangling reference" }
+int& x4 = Y{}; // { dg-warning "dangling reference" }
+const int& t1 = Y().foo(10); // { dg-warning "dangling reference" }
diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference2.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference2.C
new file mode 100644
index 0000000..dafdb43
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference2.C
@@ -0,0 +1,28 @@
+// PR c++/106393
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wdangling-reference" }
+
+namespace std {
+struct any {};
+template <typename _ValueType> _ValueType any_cast(any &&);
+template <typename _Tp> struct remove_reference { using type = _Tp; };
+template <typename _Tp> _Tp forward(typename remove_reference<_Tp>::type);
+template <typename _Tp> typename remove_reference<_Tp>::type move(_Tp);
+} // namespace std
+
+const int &r = std::any_cast<int&>(std::any()); // { dg-warning "dangling reference" }
+
+template <class T> struct C {
+ T t_; // { dg-warning "dangling reference" }
+ C(T);
+ template <class U> C(U c) : t_(std::forward<T>(c.t_)) {}
+};
+struct A {};
+struct B {
+ B(A);
+};
+int main() {
+ A a;
+ C<A> ca(a);
+ C<B &&>(std::move(ca));
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference3.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference3.C
new file mode 100644
index 0000000..4bc20c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference3.C
@@ -0,0 +1,24 @@
+// PR c++/106393
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wdangling-reference" }
+
+struct A {
+ int ar[4];
+ int& operator[](int i) { return ar[i]; }
+};
+const int &r = A()[2]; // { dg-warning "dangling reference" }
+
+struct S {
+ const S& self () { return *this; }
+};
+const S& s = S().self(); // { dg-warning "dangling reference" }
+
+struct G {
+ const G& g() { return *this; }
+};
+
+struct F {
+ G& f();
+};
+
+const G& g = F().f().g(); // { dg-warning "dangling reference" }
diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-3.c b/gcc/testsuite/gcc.dg/analyzer/fd-3.c
index 55e84e3..8e71b14 100644
--- a/gcc/testsuite/gcc.dg/analyzer/fd-3.c
+++ b/gcc/testsuite/gcc.dg/analyzer/fd-3.c
@@ -50,9 +50,9 @@ test_5 (char *path, void *buf)
int flags = O_RDONLY;
if (some_condition())
flags |= O_NOATIME;
- int fd = open (path, flags);
+ int fd = open (path, flags); /* { dg-message "\\(1\\) opened here" } */
read (fd, buf, 1); /* { dg-warning "'read' on possibly invalid file descriptor 'fd'" } */
- /* { dg-message "\\(1\\) 'fd' could be invalid" "" { target *-*-* } .-1 } */
+ /* { dg-message "\\(2\\) 'fd' could be invalid" "" { target *-*-* } .-1 } */
close (fd);
}
@@ -82,4 +82,16 @@ test_7 (char *path, void *buf)
}
close(fd);
-} \ No newline at end of file
+}
+
+void
+test_read_from_symbolic_fd (int fd, void *buf)
+{
+ read (fd, buf, 1);
+}
+
+void
+test_write_to_symbolic_fd (int fd, void *buf)
+{
+ write (fd, buf, 1);
+}
diff --git a/gcc/testsuite/gcc.dg/c11-enum-4.c b/gcc/testsuite/gcc.dg/c11-enum-4.c
new file mode 100644
index 0000000..57dd92a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-enum-4.c
@@ -0,0 +1,7 @@
+/* Test C2x enumerations with fixed underlying type are diagnosed for C11. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+enum e1 : int; /* { dg-error "ISO C does not support specifying 'enum' underlying types" } */
+enum e2 : short { A }; /* { dg-error "ISO C does not support specifying 'enum' underlying types" } */
+enum : short { B }; /* { dg-error "ISO C does not support specifying 'enum' underlying types" } */
diff --git a/gcc/testsuite/gcc.dg/c11-enum-5.c b/gcc/testsuite/gcc.dg/c11-enum-5.c
new file mode 100644
index 0000000..91d681f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-enum-5.c
@@ -0,0 +1,7 @@
+/* Test C2x enumerations with fixed underlying type are diagnosed for C11. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic" } */
+
+enum e1 : int; /* { dg-warning "ISO C does not support specifying 'enum' underlying types" } */
+enum e2 : short { A }; /* { dg-warning "ISO C does not support specifying 'enum' underlying types" } */
+enum : short { B }; /* { dg-warning "ISO C does not support specifying 'enum' underlying types" } */
diff --git a/gcc/testsuite/gcc.dg/c11-enum-6.c b/gcc/testsuite/gcc.dg/c11-enum-6.c
new file mode 100644
index 0000000..cd708bd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-enum-6.c
@@ -0,0 +1,8 @@
+/* Test C2x enumerations with fixed underlying type are not diagnosed for C11
+ with -pedantic-errors -Wno-c11-c2x-compat. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors -Wno-c11-c2x-compat" } */
+
+enum e1 : int;
+enum e2 : short { A };
+enum : short { B };
diff --git a/gcc/testsuite/gcc.dg/c2x-enum-6.c b/gcc/testsuite/gcc.dg/c2x-enum-6.c
new file mode 100644
index 0000000..5ab9694
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-enum-6.c
@@ -0,0 +1,167 @@
+/* Test C2x enumerations with fixed underlying type. Valid code. */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+/* Check a type while defining an enum (via a diagnostic for incompatible
+ pointer types if the wrong type was chosen). */
+#define TYPE_CHECK(cst, type) \
+ cst ## _type_check = sizeof (1 ? (type *) 0 : (typeof (cst) *) 0)
+
+extern int i;
+
+enum e1 : short { e1a = __SHRT_MAX__,
+ TYPE_CHECK (e1a, short),
+ e1z = (long long) 0,
+ TYPE_CHECK (e1z, enum e1),
+ e1b = -__SHRT_MAX__ - 1,
+ e1c,
+ TYPE_CHECK (e1c, enum e1) };
+extern enum e1 e1v;
+extern typeof (e1a) e1v;
+extern typeof (e1b) e1v;
+extern typeof (e1c) e1v;
+extern typeof (e1z) e1v;
+extern short e1v;
+static_assert (e1a == __SHRT_MAX__);
+static_assert (e1b == -__SHRT_MAX__ - 1);
+static_assert (e1c == -__SHRT_MAX__);
+static_assert (e1a > 0);
+static_assert (e1b < 0);
+static_assert (e1c < 0);
+static_assert (e1z == 0);
+extern typeof (+e1v) i;
+extern typeof (+e1a) i;
+extern typeof (e1a + e1b) i;
+enum e1 : short;
+enum e1 : volatile short;
+enum e1 : _Atomic short;
+enum e1 : typeof (short);
+
+enum e2 : bool { b0, b1, b0a = 0, b1a = 1 };
+extern enum e2 e2v;
+extern typeof (b0) e2v;
+extern typeof (b0a) e2v;
+extern typeof (b1) e2v;
+extern typeof (b1a) e2v;
+extern bool e2v;
+extern typeof (+e2v) i;
+extern typeof (+b0) i;
+static_assert (b0 == 0);
+static_assert (b1 == 1);
+static_assert (b0a == 0);
+static_assert (b1a == 1);
+
+enum e3 : volatile const _Atomic unsigned short;
+enum e3 : unsigned short { e3a, e3b };
+extern enum e3 e3v;
+extern typeof (e3a) e3v;
+extern typeof (e3b) e3v;
+extern unsigned short e3v;
+
+/* The enum type is complete from the end of the first enum type specifier
+ (which is nested inside another enum type specifier in this example). */
+enum e4 : typeof ((enum e4 : long { e4a = sizeof (enum e4) })0, 0L);
+extern enum e4 e4v;
+extern typeof (e4a) e4v;
+extern long e4v;
+
+enum e5 : unsigned int;
+extern enum e5 e5v;
+extern typeof (e5v + e5v) e5v;
+extern unsigned int e5v;
+
+enum : unsigned short { e6a, e6b, TYPE_CHECK (e6a, unsigned short) } e6v;
+extern typeof (e6a) e6v;
+extern typeof (e6b) e6v;
+extern unsigned short e6v;
+
+struct s1;
+struct s2 { int a; };
+union u1;
+union u2 { int a; };
+enum xe1 { XE1 };
+enum xe2 : long long { XE2 };
+enum xe3 : unsigned long;
+
+void
+f ()
+{
+ /* Tags can be redeclared in an inner scope. */
+ enum s1 : char;
+ enum s2 : int { S2 };
+ enum u1 : long { U1 };
+ enum u2 : unsigned char;
+ enum xe1 : long long;
+ enum xe2 : short;
+ enum xe3 : char { XE3 };
+ static_assert (sizeof (enum xe3) == 1);
+ static_assert (sizeof (enum xe2) == sizeof (short));
+ static_assert (sizeof (enum xe1) == sizeof (long long));
+}
+
+void *p;
+typeof (nullptr) np;
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main ()
+{
+ /* Conversions to enums with fixed underlying type have the same semantics as
+ converting to the underlying type. */
+ volatile enum e1 e1vm;
+ volatile enum e2 e2vm;
+ e1vm = __LONG_LONG_MAX__; /* { dg-warning "overflow" } */
+ if (e1vm != (short) __LONG_LONG_MAX__)
+ abort ();
+ e2vm = 10;
+ if (e2vm != 1)
+ abort ();
+ e2vm = 0;
+ if (e2vm != 0)
+ abort ();
+ /* Arithmetic on enums with fixed underlying type has the same semantics as
+ arithmetic on the underlying type; in particular, the special semantics
+ for bool apply to enums with bool as fixed underlying type. */
+ if (e2vm++ != 0)
+ abort ();
+ if (e2vm != 1)
+ abort ();
+ if (e2vm++ != 1)
+ abort ();
+ if (e2vm != 1)
+ abort ();
+ if (e2vm-- != 1)
+ abort ();
+ if (e2vm != 0)
+ abort ();
+ if (e2vm-- != 0)
+ abort ();
+ if (e2vm != 1)
+ abort ();
+ if (++e2vm != 1)
+ abort ();
+ if (e2vm != 1)
+ abort ();
+ e2vm = 0;
+ if (++e2vm != 1)
+ abort ();
+ if (e2vm != 1)
+ abort ();
+ if (--e2vm != 0)
+ abort ();
+ if (e2vm != 0)
+ abort ();
+ if (--e2vm != 1)
+ abort ();
+ if (e2vm != 1)
+ abort ();
+ e2vm = p;
+ e2vm = np;
+ e2vm = (bool) p;
+ e2vm = (bool) np;
+ if (e2vm != 0)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-enum-7.c b/gcc/testsuite/gcc.dg/c2x-enum-7.c
new file mode 100644
index 0000000..08bae31
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-enum-7.c
@@ -0,0 +1,97 @@
+/* Test C2x enumerations with fixed underlying type. Invalid code. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+/* An enum type specifier may only be used when the enum is defined, or in a
+ declaration of the form "enum name enum-type-specifier;". */
+extern enum e1 : int; /* { dg-error "storage class specifier in empty declaration with 'enum' underlying type" } */
+_Thread_local enum e2 : short; /* { dg-error "'_Thread_local' in empty declaration with 'enum' underlying type" } */
+const enum e3 : long; /* { dg-error "type qualifier in empty declaration with 'enum' underlying type" } */
+alignas (8) enum e4 : long; /* { dg-error "'alignas' in empty declaration with 'enum' underlying type" } */
+inline enum e5 : unsigned; /* { dg-error "'inline' in empty declaration" } */
+_Noreturn enum e6 : unsigned; /* { dg-error "'_Noreturn' in empty declaration" } */
+auto enum e7 : unsigned; /* { dg-error "'auto' in file-scope empty declaration" } */
+register enum e8 : unsigned; /* { dg-error "'register' in file-scope empty declaration" } */
+
+/* When the enum is defined, some extra declaration specifiers are permitted,
+ but diagnosed as useless. */
+extern enum e9 : int { E9 }; /* { dg-warning "useless storage class specifier in empty declaration" } */
+_Thread_local enum e10 : short { E10 }; /* { dg-warning "useless '_Thread_local' in empty declaration" } */
+const enum e11 : long { E11 }; /* { dg-warning "useless type qualifier in empty declaration" } */
+alignas (8) enum e12 : long { E12 }; /* { dg-warning "useless '_Alignas' in empty declaration" } */
+
+/* Nothing else may be declared with an enum type specifier for an enum not
+ being defined in that declaration. */
+enum e13 : short x13; /* { dg-error "'enum' underlying type may not be specified here" } */
+enum e14 : short f14 (); /* { dg-error "'enum' underlying type may not be specified here" } */
+typeof (enum e15 : long) x15; /* { dg-error "'enum' underlying type may not be specified here" } */
+int f16 (enum e16 : char p); /* { dg-error "'enum' underlying type may not be specified here" } */
+/* { dg-warning "will not be visible outside of this definition or declaration" "warning" { target *-*-* } .-1 } */
+int f17 (enum e17 : char); /* { dg-error "'enum' underlying type may not be specified here" } */
+/* { dg-warning "will not be visible outside of this definition or declaration" "warning" { target *-*-* } .-1 } */
+struct s18 { enum e18 : int x; }; /* { dg-error "'enum' underlying type may not be specified here" } */
+
+/* But those are OK if the enum content is defined. */
+enum e19 : short { E19 } x19;
+enum e20 : long { E20 } f20 ();
+typeof (enum e21 : long { E21 }) x21;
+int f22 (enum e22 : long long { E22 } p); /* { dg-warning "will not be visible outside of this definition or declaration" } */
+int f23 (enum e23 : long long { E23 } p); /* { dg-warning "will not be visible outside of this definition or declaration" } */
+struct s24 { enum e24 : int { E24 } x; };
+
+/* Incompatible kinds of tags in the same scope are errors. */
+struct s25;
+enum s25 : int; /* { dg-error "wrong kind of tag" } */
+struct s26;
+enum s26 : int { E26 }; /* { dg-error "wrong kind of tag" } */
+struct s27 { int x; };
+enum s27 : int; /* { dg-error "wrong kind of tag" } */
+struct s28 { int x; };
+enum s28 : int { E28 }; /* { dg-error "wrong kind of tag" } */
+union u29;
+enum u29 : int; /* { dg-error "wrong kind of tag" } */
+union u30;
+enum u30 : int { E30 }; /* { dg-error "wrong kind of tag" } */
+union u31 { int x; };
+enum u31 : int; /* { dg-error "wrong kind of tag" } */
+union u32 { int x; };
+enum u32 : int { E32 }; /* { dg-error "wrong kind of tag" } */
+
+/* If an enum has a fixed underlying type, that must be given when defining the
+ enum. */
+enum e33 : short;
+enum e33 { E33 }; /* { dg-error "'enum' declared with but defined without fixed underlying type" } */
+
+/* An enum defined without a fixed underlying type cannot then be declared with
+ one. */
+enum e34 { E34A = -__INT_MAX__, E34B = __INT_MAX__ };
+enum e34 : int; /* { dg-error "'enum' declared both with and without fixed underlying type" } */
+
+/* An enum with a fixed underlying type cannot be declared with an incompatible
+ fixed underlying type. */
+enum e35 : int;
+enum e35 : unsigned int; /* { dg-error "'enum' underlying type incompatible with previous declaration" } */
+enum e36 : int;
+enum e36 : unsigned int { E36 }; /* { dg-error "'enum' underlying type incompatible with previous declaration" } */
+enum e37 : unsigned int { E37 };
+enum e37 : int; /* { dg-error "'enum' underlying type incompatible with previous declaration" } */
+
+/* Enumeration constants must fit in the fixed underlying type. */
+enum e38 : unsigned char { E38 = (unsigned long long)((unsigned char) -1) + 1 }; /* { dg-error "enumerator value outside the range of underlying type" } */
+enum e39 : unsigned int { E39 = -1 }; /* { dg-error "enumerator value outside the range of underlying type" } */
+enum e40 : int { E40 = __INT_MAX__, E40A }; /* { dg-error "overflow in enumeration values" } */
+enum e41 : unsigned int { E41 = (unsigned int) -1, E41A }; /* { dg-error "overflow in enumeration values" } */
+enum e42 : bool { E42 = 2 }; /* { dg-error "enumerator value outside the range of underlying type" } */
+enum e43 : bool { E43 = 1, E43A }; /* { dg-error "overflow in enumeration values" } */
+
+/* The underlying type must be an integer type, not itself an enum (or
+ bit-precise) type. */
+enum e44 : double; /* { dg-error "invalid 'enum' underlying type" } */
+typedef int T;
+enum e45 : T;
+typedef int *TP;
+enum e46 : TP; /* { dg-error "invalid 'enum' underlying type" } */
+enum e47 : enum e45; /* { dg-error "invalid 'enum' underlying type" } */
+enum e48 : const; /* { dg-error "no 'enum' underlying type specified" } */
+/* 'restrict' is not valid on integer types. */
+enum e49 : int restrict; /* { dg-error "invalid use of 'restrict'" } */
diff --git a/gcc/testsuite/gcc.dg/c2x-enum-8.c b/gcc/testsuite/gcc.dg/c2x-enum-8.c
new file mode 100644
index 0000000..f7757fc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-enum-8.c
@@ -0,0 +1,7 @@
+/* Test C2x enumerations with fixed underlying type. Test -Wc11-c2x-compat
+ warnings. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors -Wc11-c2x-compat" } */
+
+enum e1 : int; /* { dg-warning "ISO C does not support specifying 'enum' underlying types before" } */
+enum e2 : short { E2 }; /* { dg-warning "ISO C does not support specifying 'enum' underlying types before" } */
diff --git a/gcc/testsuite/gcc.dg/gnu2x-enum-1.c b/gcc/testsuite/gcc.dg/gnu2x-enum-1.c
new file mode 100644
index 0000000..b72ed73
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu2x-enum-1.c
@@ -0,0 +1,11 @@
+/* Test C2x enumerations with fixed underlying type together with GNU
+ extensions: an enum cannot be forward declared without a fixed underlying
+ type and then declared or defined with one. */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu2x" } */
+
+enum e1;
+enum e1 : int; /* { dg-error "'enum' declared both with and without fixed underlying type" } */
+
+enum e2;
+enum e2 : long { A }; /* { dg-error "'enum' declared both with and without fixed underlying type" } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr107394.c b/gcc/testsuite/gcc.dg/tree-ssa/pr107394.c
new file mode 100644
index 0000000..0e1e5ac
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr107394.c
@@ -0,0 +1,22 @@
+// { dg-do compile }
+// { dg-options "-O2" }
+
+static double
+quux (double x)
+{
+ return __builtin_fabs (x);
+}
+
+__attribute__ ((flatten, optimize ("-ffinite-math-only"))) static int
+bar (int *p)
+{
+ *p = quux (0.0);
+
+ return 0;
+}
+
+void
+foo (int *p)
+{
+ (void) bar (p);
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-cond-1.c b/gcc/testsuite/gcc.dg/vect/bb-slp-cond-1.c
index 1f5c621..ccb4ef6 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-cond-1.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-cond-1.c
@@ -46,6 +46,6 @@ int main ()
}
/* { dg-final { scan-tree-dump {(no need for alias check [^\n]* when VF is 1|no alias between [^\n]* when [^\n]* is outside \(-16, 16\))} "vect" { target vect_element_align } } } */
-/* { dg-final { scan-tree-dump-times "loop vectorized" 1 "vect" { target { vect_element_align && !amdgcn-*-* } } } } */
+/* { dg-final { scan-tree-dump-times "loop vectorized" 1 "vect" { target { vect_element_align && { ! amdgcn-*-* } } } } } */
/* { dg-final { scan-tree-dump-times "loop vectorized" 2 "vect" { target amdgcn-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-1.c b/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-1.c
index 01cf34f..42e50d9 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-1.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-1.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
#include <stdarg.h>
#include "tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-2.c b/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-2.c
index 1a4a157..a9aeefc 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-2.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-2.c
@@ -1,4 +1,5 @@
-/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
+/* { dg-require-effective-target vect_long_long } */
#include <stdarg.h>
#include "tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-3.c b/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-3.c
index 849f4a0..c7d0fd2 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-3.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-3.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
#include <stdarg.h>
#include "tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-4.c b/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-4.c
index 5bc9c41..6a3ed8c 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-4.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-4.c
@@ -1,4 +1,5 @@
-/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
+/* { dg-require-effective-target vect_long_long } */
#include <stdarg.h>
#include "tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-5.c b/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-5.c
index 1dc24d3..b2889df 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-5.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-5.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
#include <stdarg.h>
#include "tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-6.c b/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-6.c
index 7d24c29..2445f53 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-6.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-6.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
#include <stdarg.h>
#include "tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-7.c b/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-7.c
index 3b505db..4b1ec8a 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-7.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-bitfield-read-7.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
#include <stdarg.h>
#include "tree-vect.h"
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-1.c
new file mode 100644
index 0000000..2c67c38
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-1.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+struct F {
+ int bar;
+ char c;
+ int baz;
+ int arr[];
+};
+
+enum {
+ FIELD_BYTE_OFFSET = 0,
+ FIELD_BYTE_SIZE = 1,
+};
+
+unsigned int test (struct F *f) {
+
+ unsigned x = __builtin_preserve_field_info (f->arr, FIELD_BYTE_SIZE); /* { dg-error "unsupported variable size field access" } */
+
+ unsigned y = __builtin_preserve_field_info (f->baz, 99); /* { dg-error "invalid second argument to built-in function" } */
+
+ return x + y;
+}
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-2.c
new file mode 100644
index 0000000..31d7a03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+struct F {
+ int bar;
+ char c;
+ int baz;
+};
+
+enum {
+ FIELD_BYTE_OFFSET = 0,
+ FIELD_BYTE_SIZE = 1,
+};
+
+int test (struct F *f) {
+ int a;
+ unsigned x = __builtin_preserve_field_info (({ a = f->bar + f->baz; }), FIELD_BYTE_OFFSET); /* { dg-error "argument is not a field access" } */
+
+ int b;
+ unsigned y = __builtin_preserve_field_info (&(f->c), FIELD_BYTE_SIZE); /* { dg-error "argument is not a field access" } */
+
+ return a + b + x + y;
+}
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c
new file mode 100644
index 0000000..c55f21a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+enum {
+ FIELD_EXISTENCE = 2,
+};
+
+typedef unsigned uint;
+
+struct S {
+ unsigned char c;
+ int d;
+ uint u;
+ short ar[3];
+};
+
+unsigned int foo (struct S *s)
+{
+ unsigned c = __builtin_preserve_field_info (s->c, FIELD_EXISTENCE);
+ unsigned d = __builtin_preserve_field_info (s->d, FIELD_EXISTENCE);
+ unsigned u = __builtin_preserve_field_info (s->u, FIELD_EXISTENCE);
+ unsigned ar = __builtin_preserve_field_info (s->ar[1], FIELD_EXISTENCE);
+
+ return c + d + u + ar;
+}
+
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],1" 4 } } */
+
+/* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:3:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "0x2\[\t \]+\[^\n\]*bpfcr_kind" 4 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c
new file mode 100644
index 0000000..dabf73d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re -mbig-endian" } */
+
+struct S {
+ int x1: 6;
+ int x2: 3;
+ int x3: 7;
+ int x4: 16;
+};
+
+enum {
+ FIELD_LSHIFT_U64 = 4,
+};
+
+unsigned int foo (struct S *s)
+{
+ /* little endian: x1=58, x2=55, x3=48, x4=32 */
+ /* big endian: x1=32, x2=38, x3=41, x4=48 */
+ unsigned x1 = __builtin_preserve_field_info (s->x1, FIELD_LSHIFT_U64);
+ unsigned x2 = __builtin_preserve_field_info (s->x2, FIELD_LSHIFT_U64);
+ unsigned x3 = __builtin_preserve_field_info (s->x3, FIELD_LSHIFT_U64);
+ unsigned x4 = __builtin_preserve_field_info (s->x4, FIELD_LSHIFT_U64);
+
+ return x1 + x2 + x3 + x4;
+}
+
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],32" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],38" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],41" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
+
+/* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "0x4\[\t \]+\[^\n\]*bpfcr_kind" 4 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c
new file mode 100644
index 0000000..99e3982
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re -mlittle-endian" } */
+
+struct S {
+ int x1: 6;
+ int x2: 3;
+ int x3: 7;
+ int x4: 16;
+};
+
+enum {
+ FIELD_LSHIFT_U64 = 4,
+};
+
+unsigned int foo (struct S *s)
+{
+ /* little endian: x1=58, x2=55, x3=48, x4=32 */
+ /* big endian: x1=32, x2=38, x3=41, x4=48 */
+ unsigned x1 = __builtin_preserve_field_info (s->x1, FIELD_LSHIFT_U64);
+ unsigned x2 = __builtin_preserve_field_info (s->x2, FIELD_LSHIFT_U64);
+ unsigned x3 = __builtin_preserve_field_info (s->x3, FIELD_LSHIFT_U64);
+ unsigned x4 = __builtin_preserve_field_info (s->x4, FIELD_LSHIFT_U64);
+
+ return x1 + x2 + x3 + x4;
+}
+
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],58" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],55" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],32" 1 } } */
+
+/* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "0x4\[\t \]+\[^\n\]*bpfcr_kind" 4 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c
new file mode 100644
index 0000000..25be969
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+struct S {
+ char c;
+ short s;
+ int x;
+};
+
+union U {
+ struct S s[2];
+ long long ll;
+};
+
+enum {
+ FIELD_LSHIFT_U64 = 4,
+};
+
+unsigned int foo (union U *u)
+{
+ /* s0s = 48, s1c = 56, ll = 0; endianness independent. */
+ unsigned s0s = __builtin_preserve_field_info (u->s[0].s, FIELD_LSHIFT_U64);
+ unsigned s1c = __builtin_preserve_field_info (u->s[1].c, FIELD_LSHIFT_U64);
+ unsigned ll = __builtin_preserve_field_info (u->ll, FIELD_LSHIFT_U64);
+
+ return s0s + s1c + ll;
+}
+
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],56" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],0" 1 } } */
+
+/* { dg-final { scan-assembler-times "ascii \"0:0:0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:0:1:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "0x4\[\t \]+\[^\n\]*bpfcr_kind" 3 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c
new file mode 100644
index 0000000..590eea0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c
@@ -0,0 +1,56 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+struct S {
+ unsigned int a1: 7;
+ unsigned int a2: 4;
+ unsigned int a3: 13;
+ unsigned int a4: 5;
+ int x;
+};
+
+struct T {
+ unsigned int y;
+ struct S s[2];
+ char c;
+ char d;
+};
+
+enum {
+ FIELD_BYTE_OFFSET = 0,
+};
+
+
+unsigned int foo (struct T *t)
+{
+ unsigned s0a1 = __builtin_preserve_field_info (t->s[0].a1, FIELD_BYTE_OFFSET);
+ unsigned s0a4 = __builtin_preserve_field_info (t->s[0].a4, FIELD_BYTE_OFFSET);
+ unsigned s0x = __builtin_preserve_field_info (t->s[0].x, FIELD_BYTE_OFFSET);
+
+ unsigned s1a1 = __builtin_preserve_field_info (t->s[1].a1, FIELD_BYTE_OFFSET);
+ unsigned s1a4 = __builtin_preserve_field_info (t->s[1].a4, FIELD_BYTE_OFFSET);
+ unsigned s1x = __builtin_preserve_field_info (t->s[1].x, FIELD_BYTE_OFFSET);
+
+ unsigned c = __builtin_preserve_field_info (t->c, FIELD_BYTE_OFFSET);
+ unsigned d = __builtin_preserve_field_info (t->d, FIELD_BYTE_OFFSET);
+
+ return s0a1 + s0a4 + s0x + s1a1 + s1a4 + s1x + c + d;
+}
+
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],4" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],8" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],12" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],16" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],20" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],21" 1 } } */
+
+/* { dg-final { scan-assembler-times "ascii \"0:1:0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1:0:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1:0:4.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1:1:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1:1:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1:1:4.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "0\[\t \]+\[^\n\]*bpfcr_kind" 8 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c
new file mode 100644
index 0000000..d0c75d9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+struct S {
+ int x1: 6;
+ int x2: 3;
+ int x3: 7;
+ int x4: 16;
+};
+
+enum {
+ FIELD_RSHIFT_U64 = 5,
+};
+
+unsigned int foo (struct S *s)
+{
+ /* x1=58, x2=61, x3=57, x4=48; endianness independent. */
+ unsigned x1 = __builtin_preserve_field_info (s->x1, FIELD_RSHIFT_U64);
+ unsigned x2 = __builtin_preserve_field_info (s->x2, FIELD_RSHIFT_U64);
+ unsigned x3 = __builtin_preserve_field_info (s->x3, FIELD_RSHIFT_U64);
+ unsigned x4 = __builtin_preserve_field_info (s->x4, FIELD_RSHIFT_U64);
+
+ return x1 + x2 + x3 + x4;
+}
+
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],58" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],61" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],57" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
+
+/* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "0x5\[\t \]+\[^\n\]*bpfcr_kind" 4 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c
new file mode 100644
index 0000000..a71ddc1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+struct S {
+ int x;
+ char c;
+};
+
+union U {
+ int i;
+ struct S s;
+};
+
+enum {
+ FIELD_RSHIFT_U64 = 5,
+};
+
+unsigned int foo (union U *u)
+{
+ /* sx = 32, sc = 56, i = 32; endianness independent. */
+ unsigned sx = __builtin_preserve_field_info (u->s.x, FIELD_RSHIFT_U64);
+ unsigned sc = __builtin_preserve_field_info (u->s.c, FIELD_RSHIFT_U64);
+ unsigned i = __builtin_preserve_field_info (u->i, FIELD_RSHIFT_U64);
+
+ return sx + sc + i;
+}
+
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],32" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],56" 1 } } */
+
+/* { dg-final { scan-assembler-times "ascii \"0:1:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "0x5\[\t \]+\[^\n\]*bpfcr_kind" 3 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c
new file mode 100644
index 0000000..3b2081e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+enum {
+ FIELD_SIGNEDNESS = 3,
+};
+
+typedef unsigned uint;
+
+struct S {
+ unsigned char c;
+ int d;
+ uint u;
+ short ar[3];
+};
+
+unsigned int foo (struct S *s)
+{
+ unsigned d = __builtin_preserve_field_info (s->d, FIELD_SIGNEDNESS);
+ unsigned u = __builtin_preserve_field_info (s->u, FIELD_SIGNEDNESS);
+ unsigned ar = __builtin_preserve_field_info (s->ar[1], FIELD_SIGNEDNESS);
+
+ return d + u + ar;
+}
+
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],1" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],0" 1 } } */
+
+/* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:3:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "0x3\[\t \]+\[^\n\]*bpfcr_kind" 3 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c
new file mode 100644
index 0000000..bf18429
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+enum {
+ FIELD_SIGNEDNESS = 3,
+};
+
+enum Esig {
+ SA = -1,
+ SB,
+ SC,
+};
+
+enum Eun {
+ UA = 0,
+ UB,
+};
+
+struct S {
+ enum Esig sig : 3;
+ enum Eun un : 3;
+};
+
+union U {
+ int i;
+ struct S s;
+};
+
+unsigned int foo (union U *u)
+{
+ unsigned i = __builtin_preserve_field_info (u->i, FIELD_SIGNEDNESS);
+ unsigned sig = __builtin_preserve_field_info (u->s.sig, FIELD_SIGNEDNESS);
+ unsigned un = __builtin_preserve_field_info (u->s.un, FIELD_SIGNEDNESS);
+
+ return i + sig + un;
+}
+
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],1" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],0" 1 } } */
+
+/* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "3\[\t \]+\[^\n\]*bpfcr_kind" 3 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c
new file mode 100644
index 0000000..8747bde
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+struct S {
+ unsigned int a1: 7;
+ unsigned int a2: 4;
+ unsigned int a3: 13;
+ unsigned int a4: 5;
+ char carr[5][3];
+};
+
+enum {
+ FIELD_BYTE_SIZE = 1,
+};
+
+union U {
+ long long l[3];
+ struct S s;
+};
+
+unsigned int foo (union U *u)
+{
+ unsigned ls = __builtin_preserve_field_info (u->l, FIELD_BYTE_SIZE);
+ unsigned s = __builtin_preserve_field_info (u->s, FIELD_BYTE_SIZE);
+ unsigned a2 = __builtin_preserve_field_info (u->s.a2, FIELD_BYTE_SIZE);
+ unsigned a3 = __builtin_preserve_field_info (u->s.a3, FIELD_BYTE_SIZE);
+ unsigned ca = __builtin_preserve_field_info (u->s.carr, FIELD_BYTE_SIZE);
+
+ return ls + s + a2 + a3 + ca;
+}
+
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],24" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],20" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],4" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],15" 1 } } */
+
+/* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:1:4.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "0x1\[\t \]+\[^\n\]*bpfcr_kind" 5 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr107172.c b/gcc/testsuite/gcc.target/i386/pr107172.c
new file mode 100644
index 0000000..d2c85f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr107172.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O1 -ftree-vrp" } */
+
+int a, c, d;
+int
+main()
+{
+ long e = 1;
+ int f = a = 1;
+L1:
+ if (a)
+ a = 2;
+ int h = e = ~e;
+ c = -1;
+ if (e >= a)
+ goto L2;
+ if (-1 > a)
+ goto L1;
+ if (a)
+ f = -1;
+L2:
+ d = (-f + d) & h;
+ if (d)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zhinx-1.c b/gcc/testsuite/gcc.target/riscv/_Float16-zhinx-1.c
new file mode 100644
index 0000000..90172b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zhinx-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i_zhinx -mabi=lp64 -O" } */
+
+_Float16 foo1 (_Float16 a, _Float16 b)
+{
+ return b;
+}
+
+/* { dg-final { scan-assembler-not "fmv.h" } } */
+/* { dg-final { scan-assembler-times "mv" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zhinx-2.c b/gcc/testsuite/gcc.target/riscv/_Float16-zhinx-2.c
new file mode 100644
index 0000000..26f0119
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zhinx-2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i_zhinx -mabi=lp64 -O" } */
+
+_Float16 foo1 (_Float16 a, _Float16 b)
+{
+ /* { dg-final { scan-assembler-not "fadd.h fa" } } */
+ /* { dg-final { scan-assembler-times "fadd.h a" 1 } } */
+ return a + b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zhinx-3.c b/gcc/testsuite/gcc.target/riscv/_Float16-zhinx-3.c
new file mode 100644
index 0000000..5739135
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zhinx-3.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i_zhinx -mabi=lp64 -O" } */
+
+int foo1 (_Float16 a, _Float16 b)
+{
+ /* { dg-final { scan-assembler-not "fgt.h fa" } } */
+ /* { dg-final { scan-assembler-times "fgt.h a" 1 } } */
+ return a > b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-1.c b/gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-1.c
new file mode 100644
index 0000000..0070ebf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i_zhinxmin -mabi=lp64 -O" } */
+
+_Float16 foo1 (_Float16 a, _Float16 b)
+{
+ /* { dg-final { scan-assembler-not "fmv.h" } } */
+ /* { dg-final { scan-assembler-not "fmv.s" } } */
+ /* { dg-final { scan-assembler-times "mv" 1 } } */
+ return b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-2.c b/gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-2.c
new file mode 100644
index 0000000..17f45a9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i_zhinxmin -mabi=lp64 -O" } */
+
+_Float16 foo1 (_Float16 a, _Float16 b)
+{
+ /* { dg-final { scan-assembler-not "fadd.h" } } */
+ /* { dg-final { scan-assembler-not "fadd.s fa" } } */
+ /* { dg-final { scan-assembler-times "fadd.s a" 1 } } */
+ return a + b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-3.c b/gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-3.c
new file mode 100644
index 0000000..7a43641
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if_zfhmin -mabi=lp64f -O" } */
+
+int foo1 (_Float16 a, _Float16 b)
+{
+ /* { dg-final { scan-assembler-not "fgt.h" } } */
+ /* { dg-final { scan-assembler-not "fgt.s fa" } } */
+ /* { dg-final { scan-assembler-times "fgt.s a" 1 } } */
+ return a > b;
+}
diff --git a/gcc/testsuite/gfortran.dg/illegal_boz_arg_4.f90 b/gcc/testsuite/gfortran.dg/illegal_boz_arg_4.f90
new file mode 100644
index 0000000..856cfa9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/illegal_boz_arg_4.f90
@@ -0,0 +1,13 @@
+! { dg-do compile }
+! { dg-options "-std=f2018" }
+! PR fortran/103413
+! Contributed by G.Steinmetz
+
+program p
+ type t
+ class(*), allocatable :: a
+ end type
+ type(t) :: x
+ allocate (x%a, source=z'1') ! { dg-error "type incompatible" }
+ allocate (x%a, mold=z'1') ! { dg-error "type incompatible" }
+end
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 925bd7d..996700b 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-match.h"
#include "dbgcnt.h"
#include "tree-ssa-propagate.h"
+#include "tree-ssa-dce.h"
static unsigned int tree_ssa_phiopt_worker (bool, bool, bool);
static bool two_value_replacement (basic_block, basic_block, edge, gphi *,
@@ -74,7 +75,6 @@ static bool cond_store_replacement (basic_block, basic_block, edge, edge,
hash_set<tree> *);
static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
static hash_set<tree> * get_non_trapping ();
-static void replace_phi_edge_with_variable (basic_block, edge, gphi *, tree);
static void hoist_adjacent_loads (basic_block, basic_block,
basic_block, basic_block);
static bool gate_hoist_loads (void);
@@ -402,7 +402,8 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
static void
replace_phi_edge_with_variable (basic_block cond_block,
- edge e, gphi *phi, tree new_tree)
+ edge e, gphi *phi, tree new_tree,
+ bitmap dce_ssa_names = auto_bitmap())
{
basic_block bb = gimple_bb (phi);
gimple_stmt_iterator gsi;
@@ -477,6 +478,8 @@ replace_phi_edge_with_variable (basic_block cond_block,
gimple_cond_make_true (cond);
}
+ simple_dce_from_worklist (dce_ssa_names);
+
statistics_counter_event (cfun, "Replace PHI with variable", 1);
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -986,6 +989,7 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
gimple_seq seq = NULL;
tree result;
gimple *stmt_to_move = NULL;
+ auto_bitmap inserted_exprs;
/* Special case A ? B : B as this will always simplify to B. */
if (operand_equal_for_phi_arg_p (arg0, arg1))
@@ -1060,14 +1064,22 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
gsi = gsi_last_bb (cond_bb);
/* Insert the sequence generated from gimple_simplify_phiopt. */
if (seq)
+ {
+ // Mark the lhs of the new statements maybe for dce
+ gimple_stmt_iterator gsi1 = gsi_start (seq);
+ for (; !gsi_end_p (gsi1); gsi_next (&gsi1))
+ {
+ gimple *stmt = gsi_stmt (gsi1);
+ tree name = gimple_get_lhs (stmt);
+ if (name && TREE_CODE (name) == SSA_NAME)
+ bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (name));
+ }
gsi_insert_seq_before (&gsi, seq, GSI_CONTINUE_LINKING);
+ }
- /* If there was a statement to move and the result of the statement
- is going to be used, move it to right before the original
- conditional. */
- if (stmt_to_move
- && (gimple_assign_lhs (stmt_to_move) == result
- || !has_single_use (gimple_assign_lhs (stmt_to_move))))
+ /* If there was a statement to move, move it to right before
+ the original conditional. */
+ if (stmt_to_move)
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -1075,12 +1087,17 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
print_gimple_stmt (dump_file, stmt_to_move, 0,
TDF_VOPS|TDF_MEMSYMS);
}
+
+ tree name = gimple_get_lhs (stmt_to_move);
+ // Mark the name to be renamed if there is one.
+ if (name && TREE_CODE (name) == SSA_NAME)
+ bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (name));
gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt_to_move);
gsi_move_before (&gsi1, &gsi);
reset_flow_sensitive_info (gimple_assign_lhs (stmt_to_move));
}
- replace_phi_edge_with_variable (cond_bb, e1, phi, result);
+ replace_phi_edge_with_variable (cond_bb, e1, phi, result, inserted_exprs);
/* Add Statistic here even though replace_phi_edge_with_variable already
does it as we want to be able to count when match-simplify happens vs
diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc
index 6e05462..462447b 100644
--- a/gcc/value-range-storage.cc
+++ b/gcc/value-range-storage.cc
@@ -261,17 +261,28 @@ frange_storage_slot::get_frange (frange &r, tree type) const
{
gcc_checking_assert (r.supports_type_p (type));
- r.set_undefined ();
- r.m_kind = m_kind;
- r.m_type = type;
- r.m_min = m_min;
- r.m_max = m_max;
- r.m_pos_nan = m_pos_nan;
- r.m_neg_nan = m_neg_nan;
- r.normalize_kind ();
-
- if (flag_checking)
- r.verify_range ();
+ // Handle explicit NANs.
+ if (m_kind == VR_NAN)
+ {
+ if (HONOR_NANS (type))
+ {
+ if (m_pos_nan && m_neg_nan)
+ r.set_nan (type);
+ else
+ r.set_nan (type, m_neg_nan);
+ }
+ else
+ r.set_undefined ();
+ return;
+ }
+
+ // Use the constructor because it will canonicalize the range.
+ r = frange (type, m_min, m_max, m_kind);
+
+ // The constructor will set the NAN bits for HONOR_NANS, but we must
+ // make sure to set the NAN sign if known.
+ if (HONOR_NANS (type) && (m_pos_nan ^ m_neg_nan) == 1)
+ r.update_nan (m_neg_nan);
}
bool
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 77e5a2c..03b3c4b 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -4031,7 +4031,7 @@ range_tests_floats ()
r0.intersect (r1);
ASSERT_TRUE (r0.undefined_p ());
- if (!flag_finite_math_only)
+ if (HONOR_INFINITIES (float_type_node))
{
// Make sure [-Inf, -Inf] doesn't get normalized.
r0 = frange_float ("-Inf", "-Inf");