[gcc r16-1124] Revert "libstdc++: sstream from string_view (P2495R3) [PR119741]"

2025-06-04 Thread Nathan Myers via Libstdc++-cvs
https://gcc.gnu.org/g:a31e76a26435537056d467eb6a08b8c4ec886bf2

commit r16-1124-ga31e76a26435537056d467eb6a08b8c4ec886bf2
Author: Nathan Myers 
Date:   Wed Jun 4 23:19:52 2025 -0400

Revert "libstdc++: sstream from string_view (P2495R3) [PR119741]"

This reverts commit 8537e4851072ea1f1982c4c6ab0d24c9383e9edd.

Diff:
---
 libstdc++-v3/include/bits/version.def  |  11 +-
 libstdc++-v3/include/bits/version.h|  10 -
 libstdc++-v3/include/std/sstream   | 198 ++--
 .../basic_istringstream/cons/char/string_view.cc   | 195 
 .../cons/wchar_t/string_view.cc|   3 -
 .../basic_ostringstream/cons/char/string_view.cc   | 194 ---
 .../cons/wchar_t/string_view.cc|   3 -
 .../27_io/basic_stringbuf/cons/char/string_view.cc | 205 -
 .../basic_stringbuf/cons/wchar_t/string_view.cc|   3 -
 .../basic_stringstream/cons/char/string_view.cc| 204 
 .../basic_stringstream/cons/wchar_t/string_view.cc |   3 -
 11 files changed, 19 insertions(+), 1010 deletions(-)

diff --git a/libstdc++-v3/include/bits/version.def 
b/libstdc++-v3/include/bits/version.def
index 7cf62e989aa7..9ab22cc519f9 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -649,7 +649,7 @@ ftms = {
   };
   values = {
 v = 1;
-// For when there is no gthread.
+/* For when there's no gthread.  */
 cxxmin = 17;
 hosted = yes;
 gthread = no;
@@ -1995,15 +1995,6 @@ ftms = {
   };
 };
 
-ftms = {
-  name = sstream_from_string_view;
-  values = {
-v = 202306;
-cxxmin = 26;
-hosted = yes;
-  };
-};
-
 // Standard test specifications.
 stds[97] = ">= 199711L";
 stds[03] = ">= 199711L";
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index 9f4cf9a3425e..371a7ba3b1a0 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -2233,14 +2233,4 @@
 #endif /* !defined(__cpp_lib_polymorphic) && 
defined(__glibcxx_want_polymorphic) */
 #undef __glibcxx_want_polymorphic
 
-#if !defined(__cpp_lib_sstream_from_string_view)
-# if (__cplusplus >  202302L) && _GLIBCXX_HOSTED
-#  define __glibcxx_sstream_from_string_view 202306L
-#  if defined(__glibcxx_want_all) || 
defined(__glibcxx_want_sstream_from_string_view)
-#   define __cpp_lib_sstream_from_string_view 202306L
-#  endif
-# endif
-#endif /* !defined(__cpp_lib_sstream_from_string_view) && 
defined(__glibcxx_want_sstream_from_string_view) */
-#undef __glibcxx_want_sstream_from_string_view
-
 #undef __glibcxx_want_all
diff --git a/libstdc++-v3/include/std/sstream b/libstdc++-v3/include/std/sstream
index edef599bd6f8..ad0c16a91e86 100644
--- a/libstdc++-v3/include/std/sstream
+++ b/libstdc++-v3/include/std/sstream
@@ -41,12 +41,8 @@
 
 #include 
 #include 
-
 #include  // allocator_traits, __allocator_like
 
-#define __glibcxx_want_sstream_from_string_view
-#include 
-
 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
 # define _GLIBCXX_LVAL_REF_QUAL &
 # define _GLIBCXX_SSTREAM_ALWAYS_INLINE
@@ -56,6 +52,8 @@
 # define _GLIBCXX_SSTREAM_ALWAYS_INLINE [[__gnu__::__always_inline__]]
 #endif
 
+
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -161,7 +159,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   { __rhs._M_sync(const_cast(__rhs._M_string.data()), 0, 0); }
 
 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
-   // P0408 Efficient access to basic_stringbuf buffer
   explicit
   basic_stringbuf(const allocator_type& __a)
   : basic_stringbuf(ios_base::in | std::ios_base::out, __a)
@@ -200,36 +197,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
| ios_base::out)
: basic_stringbuf(__s, __mode, allocator_type{})
{ }
-#endif
-
-#ifdef __cpp_lib_sstream_from_string_view
-  template
-   explicit
-   basic_stringbuf(const _Tp& __t,
-   ios_base::openmode __mode = ios_base::in | ios_base::out)
- requires (is_convertible_v>)
-   : basic_stringbuf(__t, __mode, allocator_type{})
-   { }
-
-  template
-   basic_stringbuf(const _Tp& __t, const allocator_type& __a)
- requires (is_convertible_v>)
-   : basic_stringbuf(__t, ios_base::in | ios_base::out, __a)
-   { }
 
-  template
-   basic_stringbuf(const _Tp& __t, ios_base::openmode __mode,
-   const allocator_type& __a)
- requires (is_convertible_v>)
-   : _M_string(__t, __a)
-   { _M_stringbuf_init(__mode); }
-#endif // C++26
-
-#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
-   // P0408 Efficient access to basic_stringbuf buffer
   basic_stringbuf(basic_stringbuf&& __rhs, const allocator_type& __a)
   : basic_stringbuf(std::move(__rhs), __a, __xfer_bufptrs(__rhs, this))
   { __rhs._M_sync(const_cast(__rhs._M_string.data()), 0, 0); }
@

[gcc r16-1125] i386: Fix vmovvdup's mem attribute

2025-06-04 Thread Hu via Gcc-cvs
https://gcc.gnu.org/g:24cbcc49277a0ac40fc2d82831f6db5e8d6d890d

commit r16-1125-g24cbcc49277a0ac40fc2d82831f6db5e8d6d890d
Author: Hu, Lin1 
Date:   Tue May 27 19:09:04 2025 +0800

i386: Fix vmovvdup's mem attribute

Some vmovvdup pattern's type attribute is sselog1 and then mem attribute is
both. Modify type attribute according to other patterns about vmovvdup.

gcc/ChangeLog:

* config/i386/sse.md
(avx512f_movddup512): Change sselog1 to ssemov.
(avx_movddup256): Ditto.
(*vec_dupv2di): Change alternative 4's type attribute from sselog1
to ssemov.

Diff:
---
 gcc/config/i386/sse.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index aea5e2cad7e1..c40b0fd49978 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -13418,7 +13418,7 @@
 (const_int 6) (const_int 14)])))]
   "TARGET_AVX512F"
   "vmovddup\t{%1, %0|%0, %1}"
-  [(set_attr "type" "sselog1")
+  [(set_attr "type" "ssemov")
(set_attr "prefix" "evex")
(set_attr "mode" "V8DF")])
 
@@ -13449,7 +13449,7 @@
 (const_int 2) (const_int 6)])))]
   "TARGET_AVX && "
   "vmovddup\t{%1, %0|%0, %1}"
-  [(set_attr "type" "sselog1")
+  [(set_attr "type" "ssemov")
(set_attr "prefix" "")
(set_attr "mode" "V4DF")])
 
@@ -27839,7 +27839,7 @@
%vmovddup\t{%1, %0|%0, %1}
movlhps\t%0, %0"
   [(set_attr "isa" "sse2_noavx,avx,avx512f,sse3,noavx")
-   (set_attr "type" "sselog1,sselog1,ssemov,sselog1,ssemov")
+   (set_attr "type" "sselog1,sselog1,ssemov,ssemov,ssemov")
(set_attr "prefix" "orig,maybe_evex,evex,maybe_vex,orig")
(set (attr "mode")
(cond [(and (eq_attr "alternative" "2")


[gcc r16-1127] c++, coroutines: Make analyze_fn_params into a class method.

2025-06-04 Thread Iain D Sandoe via Gcc-cvs
https://gcc.gnu.org/g:2a8af97e3528f812201687334f64b27b94d01271

commit r16-1127-g2a8af97e3528f812201687334f64b27b94d01271
Author: Iain Sandoe 
Date:   Thu May 29 16:45:44 2025 +0100

c++, coroutines: Make analyze_fn_params into a class method.

This continues code cleanups and migration to encapsulation of the
whole coroutine transform.

gcc/cp/ChangeLog:

* coroutines.cc (analyze_fn_parms): Move from free function..
(cp_coroutine_transform::analyze_fn_parms):... to method.
(cp_coroutine_transform::apply_transforms): Adjust call to
analyze_fn_parms.
* coroutines.h: Declare analyze_fn_parms.

Signed-off-by: Iain Sandoe 

Diff:
---
 gcc/cp/coroutines.cc | 20 +++-
 gcc/cp/coroutines.h  |  1 +
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 8ec309af3ca6..97eee6e8ea4d 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -4027,12 +4027,14 @@ rewrite_param_uses (tree *stmt, int *do_subtree 
ATTRIBUTE_UNUSED, void *d)
 }
 
 /* Build up a set of info that determines how each param copy will be
-   handled.  */
+   handled.  We store this in a hash map so that we can access it from
+   a tree walk callback that re-writes the original parameters to their
+   copies.  */
 
-static void
-analyze_fn_parms (tree orig, hash_map *param_uses)
+void
+cp_coroutine_transform::analyze_fn_parms ()
 {
-  if (!DECL_ARGUMENTS (orig))
+  if (!DECL_ARGUMENTS (orig_fn_decl))
 return;
 
   /* Build a hash map with an entry for each param.
@@ -4042,19 +4044,19 @@ analyze_fn_parms (tree orig, hash_map 
*param_uses)
  Then a tree list of the uses.
  The second two entries start out empty - and only get populated
  when we see uses.  */
-  bool lambda_p = LAMBDA_FUNCTION_P (orig);
+  bool lambda_p = LAMBDA_FUNCTION_P (orig_fn_decl);
 
   /* Count the param copies from 1 as per the std.  */
   unsigned parm_num = 1;
-  for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
+  for (tree arg = DECL_ARGUMENTS (orig_fn_decl); arg != NULL;
++parm_num, arg = DECL_CHAIN (arg))
 {
   bool existed;
-  param_info &parm = param_uses->get_or_insert (arg, &existed);
+  param_info &parm = param_uses.get_or_insert (arg, &existed);
   gcc_checking_assert (!existed);
   parm.body_uses = NULL;
   tree actual_type = TREE_TYPE (arg);
-  actual_type = complete_type_or_else (actual_type, orig);
+  actual_type = complete_type_or_else (actual_type, orig_fn_decl);
   if (actual_type == NULL_TREE)
actual_type = error_mark_node;
   parm.orig_type = actual_type;
@@ -5249,7 +5251,7 @@ cp_coroutine_transform::apply_transforms ()
 
   /* Collect information on the original function params and their use in the
  function body.  */
-  analyze_fn_parms (orig_fn_decl, ¶m_uses);
+  analyze_fn_parms ();
 
   /* Declare the actor and destroyer functions, the following code needs to
  see these.  */
diff --git a/gcc/cp/coroutines.h b/gcc/cp/coroutines.h
index 10698cf2e129..55caa6e61e36 100644
--- a/gcc/cp/coroutines.h
+++ b/gcc/cp/coroutines.h
@@ -126,6 +126,7 @@ private:
   bool inline_p = false;
   bool valid_coroutine = false;
 
+  void analyze_fn_parms ();
   void wrap_original_function_body ();
   bool build_ramp_function ();
 };


[gcc r16-1096] Fortran: Fix missing substring ref for allocatable saved vars [PR120483]

2025-06-04 Thread Andre Vehreschild via Gcc-cvs
https://gcc.gnu.org/g:afa2de8093a0cd47394df42c7092aa6a357d2f9c

commit r16-1096-gafa2de8093a0cd47394df42c7092aa6a357d2f9c
Author: Andre Vehreschild 
Date:   Mon Jun 2 10:41:48 2025 +0200

Fortran: Fix missing substring ref for allocatable saved vars [PR120483]

Compute a substring ref on an allocatable static character array
using pointer arithmetic.  Using an array type corrupts type
layouting and crashes omp generation.

PR fortran/120483

gcc/fortran/ChangeLog:

* trans-expr.cc (gfc_conv_substring): Use pointer arithmetic on
static allocatable char arrays.

gcc/testsuite/ChangeLog:

* gfortran.dg/save_8.f90: New test.

Diff:
---
 gcc/fortran/trans-expr.cc| 16 +---
 gcc/testsuite/gfortran.dg/save_8.f90 | 13 +
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 8d9448eb9b6d..74d4265f27d8 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -2782,9 +2782,11 @@ gfc_conv_substring (gfc_se * se, gfc_ref * ref, int kind,
start.expr = gfc_evaluate_now (start.expr, &se->pre);
 
   /* Change the start of the string.  */
-  if ((TREE_CODE (TREE_TYPE (se->expr)) == ARRAY_TYPE
-  || TREE_CODE (TREE_TYPE (se->expr)) == INTEGER_TYPE)
- && TYPE_STRING_FLAG (TREE_TYPE (se->expr)))
+  if (((TREE_CODE (TREE_TYPE (se->expr)) == ARRAY_TYPE
+   || TREE_CODE (TREE_TYPE (se->expr)) == INTEGER_TYPE)
+  && TYPE_STRING_FLAG (TREE_TYPE (se->expr)))
+ || (POINTER_TYPE_P (TREE_TYPE (se->expr))
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (se->expr))) != ARRAY_TYPE))
tmp = se->expr;
   else
tmp = build_fold_indirect_ref_loc (input_location,
@@ -2795,6 +2797,14 @@ gfc_conv_substring (gfc_se * se, gfc_ref * ref, int kind,
  tmp = gfc_build_array_ref (tmp, start.expr, NULL_TREE, true);
  se->expr = gfc_build_addr_expr (type, tmp);
}
+  else if (POINTER_TYPE_P (TREE_TYPE (tmp)))
+   {
+ tree diff;
+ diff = fold_build2 (MINUS_EXPR, size_type_node, start.expr,
+ build_one_cst (size_type_node));
+ se->expr
+   = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (tmp), tmp, diff);
+   }
 }
 
   /* Length = end + 1 - start.  */
diff --git a/gcc/testsuite/gfortran.dg/save_8.f90 
b/gcc/testsuite/gfortran.dg/save_8.f90
new file mode 100644
index ..8e9198caeb18
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/save_8.f90
@@ -0,0 +1,13 @@
+!{ dg-do run }
+
+! Check PR120483 is fixed.
+! Contributed by Thomas Koenig  
+!and Peter Güntert   
+
+program save_8
+  implicit none
+  character(len=:), allocatable, save :: s1
+  s1 = 'ABC'
+  if (s1(3:3) /= 'C') stop 1
+end program save_8
+


[gcc r16-1098] RISC-V: Leverage get_vector_binary_rtx_cost to avoid code dup [NFC]

2025-06-04 Thread Pan Li via Gcc-cvs
https://gcc.gnu.org/g:a8b38447efe2c74094b865e1cc44723659dac2e4

commit r16-1098-ga8b38447efe2c74094b865e1cc44723659dac2e4
Author: Pan Li 
Date:   Wed Jun 4 11:06:52 2025 +0800

RISC-V: Leverage get_vector_binary_rtx_cost to avoid code dup [NFC]

Some similar code could be wrapped to func get_vector_binary_rtx_cost,
thus leverage this function to avoid code duplication.

The below test suites are passed for this patch series.
* The rv64gcv fully regression test.

gcc/ChangeLog:

* config/riscv/riscv.cc (get_vector_binary_rtx_cost): Rename
the args to scalar2vr.
(riscv_rtx_costs): Leverage above func to avoid code dup.

Signed-off-by: Pan Li 

Diff:
---
 gcc/config/riscv/riscv.cc | 44 
 1 file changed, 16 insertions(+), 28 deletions(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index b168a6414988..3254ec9f9e13 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3892,11 +3892,11 @@ riscv_extend_cost (rtx op, bool unsigned_p)
 }
 
 /* Return the cost of the vector binary rtx like add, minus, mult.
-   The cost of gr2vr will be appended if there one of the op comes
-   from the VEC_DUPLICATE.  */
+   The cost of scalar2vr_cost will be appended if there one of the
+   op comes from the VEC_DUPLICATE.  */
 
 static int
-get_vector_binary_rtx_cost (rtx x, int gr2vr_cost)
+get_vector_binary_rtx_cost (rtx x, int scalar2vr_cost)
 {
   gcc_assert (riscv_v_ext_mode_p (GET_MODE (x)));
 
@@ -3905,7 +3905,7 @@ get_vector_binary_rtx_cost (rtx x, int gr2vr_cost)
 
   if (GET_CODE (op_0) == VEC_DUPLICATE
   || GET_CODE (op_1) == VEC_DUPLICATE)
-return (gr2vr_cost + 1) * COSTS_N_INSNS (1);
+return (scalar2vr_cost + 1) * COSTS_N_INSNS (1);
   else
 return COSTS_N_INSNS (1);
 }
@@ -3924,6 +3924,8 @@ riscv_rtx_costs (rtx x, machine_mode mode, int 
outer_code, int opno ATTRIBUTE_UN
 {
   int gr2vr_cost = get_gr2vr_cost ();
   int fr2vr_cost = get_fr2vr_cost ();
+  int scalar2vr_cost = FLOAT_MODE_P (GET_MODE_INNER (mode))
+   ? fr2vr_cost : gr2vr_cost;
 
   switch (outer_code)
{
@@ -3936,12 +3938,12 @@ riscv_rtx_costs (rtx x, machine_mode mode, int 
outer_code, int opno ATTRIBUTE_UN
break;
  case IF_THEN_ELSE:
{
- rtx op_1 = XEXP (x, 1);
+ rtx op = XEXP (x, 1);
 
- switch (GET_CODE (op_1))
+ switch (GET_CODE (op))
{
case DIV:
- *total = get_vector_binary_rtx_cost (op_1, gr2vr_cost);
+ *total = get_vector_binary_rtx_cost (op, scalar2vr_cost);
  break;
default:
  *total = COSTS_N_INSNS (1);
@@ -3956,31 +3958,17 @@ riscv_rtx_costs (rtx x, machine_mode mode, int 
outer_code, int opno ATTRIBUTE_UN
  case XOR:
  case MULT:
{
+ rtx op;
  rtx op_0 = XEXP (x, 0);
  rtx op_1 = XEXP (x, 1);
- rtx op;
 
- if (GET_CODE (op_0) == VEC_DUPLICATE
- || GET_CODE (op_1) == VEC_DUPLICATE)
-   {
- *total = (gr2vr_cost + 1) * COSTS_N_INSNS (1);
- break;
-   }
- else if (GET_CODE (op = op_0) == MULT
-  || GET_CODE (op = op_1) == MULT)
-   {
- rtx mult_op0 = XEXP (op, 0);
- if (GET_CODE (mult_op0) == VEC_DUPLICATE)
-   {
- if (FLOAT_MODE_P (mode))
-   *total = (fr2vr_cost + 1) * COSTS_N_INSNS (1);
- else
-   *total = (gr2vr_cost + 1) * COSTS_N_INSNS (1);
- break;
-   }
-   }
+ if (GET_CODE (op = op_0) == MULT
+ || GET_CODE (op = op_1) == MULT)
+   *total = get_vector_binary_rtx_cost (op, scalar2vr_cost);
+ else
+   *total = get_vector_binary_rtx_cost (x, scalar2vr_cost);
}
-   /* Fall through.  */
+   break;
  default:
*total = COSTS_N_INSNS (1);
break;


[gcc r16-1099] libstdc++: Fix format call and test formatting with empty specs for durations.

2025-06-04 Thread Tomasz Kaminski via Gcc-cvs
https://gcc.gnu.org/g:ac0a04b7a254fb8e1d8d7088336bcb4375807b1e

commit r16-1099-gac0a04b7a254fb8e1d8d7088336bcb4375807b1e
Author: Tomasz Kamiński 
Date:   Wed Jun 4 11:05:11 2025 +0200

libstdc++: Fix format call and test formatting with empty specs for 
durations.

This patches fixes an obvious error, where the output iterator argument was
missing for call to format_to, when duration with custom representation 
types
are used.

It's also adding the test for behavior of ostream operator and the 
formatting
with empty chron-spec for the chrono types. Current coverage is:
 * duration and hh_mm_ss in this commit,
 * calendar types in r16-1016-g28a17985dd34b7.

libstdc++-v3/ChangeLog:

* include/bits/chrono_io.h (__formatter_chrono:_M_s): Add missing
__out argument to format_to call.
* testsuite/std/time/format/empty_spec.cc: New test.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/chrono_io.h  |   3 +-
 .../testsuite/std/time/format/empty_spec.cc| 271 +
 2 files changed, 273 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/bits/chrono_io.h 
b/libstdc++-v3/include/bits/chrono_io.h
index 346eb8b3c33b..239f9c780094 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -1296,7 +1296,8 @@ namespace __format
  else
{
  auto __str = std::format(_S_empty_spec, __ss.count());
- __out = std::format_to(_GLIBCXX_WIDEN("{:0>{}s}"),
+ __out = std::format_to(std::move(__out),
+_GLIBCXX_WIDEN("{:0>{}s}"),
 __str,
 __hms.fractional_width);
}
diff --git a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc 
b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
index 322faa1939d9..46942dc30fc6 100644
--- a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
+++ b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
@@ -1,7 +1,9 @@
 // { dg-do run { target c++20 } }
+// { dg-require-effective-target hosted }
 // { dg-timeout-factor 2 }
 
 #include 
+#include 
 #include 
 #include 
 
@@ -49,6 +51,274 @@ void verify(const T& t, const _CharT* str)
   VERIFY( res == str );
 }
 
+template
+struct Rep
+{
+  using Return
+= std::conditional_t, Rep, Ret>;
+
+  Rep(long v = 0) : val(v) {}
+
+  operator long() const
+  { return val; }
+
+  Return
+  operator+() const
+  { return val; }
+
+  Rep
+  operator-() const
+  { return -val; }
+
+  friend Rep
+  operator+(Rep lhs, Rep rhs)
+  { return lhs.val + rhs.val; }
+
+  friend Rep
+  operator-(Rep lhs, Rep rhs)
+  { return lhs.val - rhs.val; }
+
+  friend Rep
+  operator*(Rep lhs, Rep rhs)
+  { return lhs.val * rhs.val; }
+
+  friend Rep
+  operator/(Rep lhs, Rep rhs)
+  { return lhs.val / rhs.val; }
+
+  friend auto operator<=>(Rep, Rep) = default;
+
+  template
+  friend std::basic_ostream<_CharT>&
+  operator<<(std::basic_ostream<_CharT>& os, const Rep& t)
+  { return os << t.val << WIDEN("[via <<]"); }
+
+  long val;
+};
+
+template
+  requires std::is_integral_v
+struct std::common_type, Other>
+{
+  using type = Rep;
+};
+
+template
+  requires std::is_integral_v
+struct std::common_type>
+  : std::common_type, Other>
+{ };
+
+template
+struct std::numeric_limits>
+  : std::numeric_limits
+{ };
+
+template
+struct std::formatter, _CharT>
+  : std::formatter
+{
+  template
+  typename std::basic_format_context::iterator
+  format(const Rep& t, std::basic_format_context& ctx) const
+  {
+constexpr std::basic_string_view<_CharT> suffix = WIDEN("[via format]");
+auto out = std::formatter::format(t.val, ctx);
+return std::ranges::copy(suffix, out).out;
+  }
+};
+
+using deciseconds = duration;
+
+template
+void
+test_duration()
+{
+  std::basic_string<_CharT> res;
+
+  const milliseconds di(40);
+  verify( di, WIDEN("40ms") );
+  res = std::format(WIDEN("{:>6}"), di);
+  VERIFY( res == WIDEN("  40ms") );
+
+  verify( -di, WIDEN("-40ms") );
+  res = std::format(WIDEN("{:>6}"), -di);
+  VERIFY( res == WIDEN(" -40ms") );
+
+  const duration df(11.22);
+  verify( df, WIDEN("11.22s") );
+  res = std::format(WIDEN("{:=^12}"), df);
+  VERIFY( res == WIDEN("===11.22s===") );
+
+  verify( -df, WIDEN("-11.22s") );
+  res = std::format(WIDEN("{:=^12}"), -df);
+  VERIFY( res == WIDEN("==-11.22s===") );
+}
+
+template
+void
+test_duration_cust()
+{
+  std::basic_string<_CharT> res;
+  const duration> charRep(123);
+  verify( charRep, WIDEN("123ds") );
+
+  // +asLong returns long, so formatted as long
+  const duration> asLong(20);
+  verify( asLong, WIDEN("20s") );
+  res = std::format(WIDEN("{:>6}"), asLong);
+  VERIFY( res == WIDEN("   20s") );
+
+  verify( -asLong, WIDEN("-20s") );
+  res

[gcc r16-1100] libgomp.texi (omp_interop_*): Add note about 5.2-to-6.0 incompatibility

2025-06-04 Thread Tobias Burnus via Gcc-cvs
https://gcc.gnu.org/g:0f56d67a498fb5f6223c36589bb1f5d7ae219e45

commit r16-1100-g0f56d67a498fb5f6223c36589bb1f5d7ae219e45
Author: Tobias Burnus 
Date:   Wed Jun 4 13:25:05 2025 +0200

libgomp.texi (omp_interop_*): Add note about 5.2-to-6.0 incompatibility

GCC uses the 6.0 types - which are unfortunately not quite compatible with
code expecting 5.1/5.2 data types.  Therefore, this commit adds a note to
hopefully reduce surprises. Namely:

For C/C++: while OpenMP 5.1 and 5.2 used 'int *ret_code', OpenMP 6.0 uses
'omp_interop_rc_t *ret_code' in omp_interop_{int,ptr,str} and 'int' instead
of 'omp_interop_rc_t ret_code' in omp_get_interop_rc_desc.

Neither C nor C++ like passing the wrong pointer type, albeit for C, GCC < 
14
and clang only warn (gcc >= r14-6037-g9715c545d33b3a has an error) and
using -fpermissive turns it into a warning and 
-Wno-incompatible-pointer-types
silences it for C.

C++ also dislikes passing an int to an enum, albeit -fpermissive turns the
error into a warning with g++ (but not clang++). And, here, using an enum
on the caller side works with both int and enum on the callee side.

libgomp/ChangeLog:

* libgomp.texi (omp_interop_{int,ptr,str,rc_desc}): Add note about
the 'ret_code' type change in OpenMP 6.

Co-authored-by: Sandra Loosemore 

Diff:
---
 libgomp/libgomp.texi | 20 
 1 file changed, 20 insertions(+)

diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index 8e487bcd168c..7116fcda13fe 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -3130,6 +3130,11 @@ and Fortran or used with @code{NULL} as argument in C 
and C++.  If successful,
 In GCC, the effect of running this routine in a @code{target} region that is 
not
 the initial device is unspecified.
 
+GCC implements the OpenMP 6.0 version of this function for C and C++, which is 
not
+compatible with its type signature in previous versions of the OpenMP 
specification.
+In older versions, the type @code{int*} was used for the @var{ret_code} 
argument
+in place of a pointer to the enumerated type @code{omp_interop_rc_t}.
+
 @c Implementation remark: In GCC, the Fortran interface differs from the one 
shown
 @c below: the function has C binding and @var{interop} and @var{property_id} 
are
 @c passed by value, which permits use of the same ABI as the C function.  This 
does
@@ -3176,6 +3181,11 @@ and Fortran or used with @code{NULL} as argument in C 
and C++.  If successful,
 In GCC, the effect of running this routine in a @code{target} region that is 
not
 the initial device is unspecified.
 
+GCC implements the OpenMP 6.0 version of this function for C and C++, which is 
not
+compatible with its type signature in previous versions of the OpenMP 
specification.
+In older versions, the type @code{int*} was used for the @var{ret_code} 
argument
+in place of a pointer to the enumerated type @code{omp_interop_rc_t}.
+
 @c Implementation remark: In GCC, the Fortran interface differs from the one 
shown
 @c below: the function has C binding and @var{interop} and @var{property_id} 
are
 @c passed by value, which permits use of the same ABI as the C function.  This 
does
@@ -3222,6 +3232,11 @@ and Fortran or used with @code{NULL} as argument in C 
and C++.  If successful,
 In GCC, the effect of running this routine in a @code{target} region that is 
not
 the initial device is unspecified.
 
+GCC implements the OpenMP 6.0 version of this function for C and C++, which is 
not
+compatible with its type signature in previous versions of the OpenMP 
specification.
+In older versions, the type @code{int*} was used for the @var{ret_code} 
argument
+in place of a pointer to the enumerated type @code{omp_interop_rc_t}.
+
 @c Implementation remark: In GCC, the Fortran interface differs from the one 
shown
 @c below: @var{interop} and @var{property_id} are passed by value.  This does 
not
 @c affect the usage of the function when GCC's @code{omp_lib} module or
@@ -3348,6 +3363,11 @@ the @var{ret_code} in human-readable form.
 The behavior is unspecified if value of @var{ret_code} was not set by an
 interoperability routine invoked for @var{interop}.
 
+GCC implements the OpenMP 6.0 version of this function for C and C++, which is 
not
+compatible with its type signature in previous versions of the OpenMP 
specification.
+In older versions, the type @code{int} was used for the @var{ret_code} argument
+in place of the enumerated type @code{omp_interop_rc_t}.
+
 @item @emph{C/C++}:
 @multitable @columnfractions .20 .80
 @item @emph{Prototype}: @tab @code{const char *omp_get_interop_rc_desc(const 
omp_interop_t interop,


[gcc r16-1101] emit-rtl: Tweak validate_subreg ordered_p condition [PR120447]

2025-06-04 Thread Richard Sandiford via Gcc-cvs
https://gcc.gnu.org/g:5cb46d8fff07afee5ca828303544025e4a2e17b7

commit r16-1101-g5cb46d8fff07afee5ca828303544025e4a2e17b7
Author: Richard Sandiford 
Date:   Wed Jun 4 13:36:51 2025 +0100

emit-rtl: Tweak validate_subreg ordered_p condition [PR120447]

In the comment trail for PR119966, I'd said that the validate_subreg
condition:

  /* The outer size must be ordered wrt the register size, otherwise
 we wouldn't know at compile time how many registers the outer
 mode occupies.  */
  if (!ordered_p (osize, regsize))
return false;

"is also potentially relevant" for paradoxical subregs.  But I'd
forgotten an important caveat.  If the inner size is smaller than
a register, we know that the inner value will only occupy a single
register.  Although the paradoxical subreg might extend that single
register to multiple registers by padding with undefined bits,
the register size that matters for the extension is:

   REGMODE_NATURAL_SIZE (omode)

rather than regsize's:

   REGMODE_NATURAL_SIZE (imode)

The ordered check is still relevant if the inner value spans
multiple registers.

Enabling the check above for paradoxical subregs led to an ICE in the
testcase, where we tried to generate a VNx4QI paradoxical subreg of a
QI scalar.  This was previously allowed, and AFAIK worked correctly.

The patch doesn't have the effect of relaxing the condition for
non-paradoxical subregs, since:

  known_le (osize, isize) && known_le (isize, regsize)
=> known_le (osize, regsize)
=> ordered_p (osize, regsize)

So even before the patch for PR119966, the condition only existed for
the maybe_gt (isize, regsize) case.

The term "block" used in the comment is taken from the rtl.texi
documentation of subregs.

gcc/
PR rtl-optimization/120447
* emit-rtl.cc (validate_subreg): Restrict ordered_p test
between osize and regsize to cases where the inner value
occupies multiple blocks.

gcc/testsuite/
PR rtl-optimization/120447
* gcc.dg/pr120447.c: New test.

Diff:
---
 gcc/emit-rtl.cc |  9 +
 gcc/testsuite/gcc.dg/pr120447.c | 24 
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
index 3f453cda67ed..50e3bfcb777a 100644
--- a/gcc/emit-rtl.cc
+++ b/gcc/emit-rtl.cc
@@ -998,10 +998,11 @@ validate_subreg (machine_mode omode, machine_mode imode,
   && known_le (osize, isize))
 return false;
 
-  /* The outer size must be ordered wrt the register size, otherwise
- we wouldn't know at compile time how many registers the outer
- mode occupies.  */
-  if (!ordered_p (osize, regsize))
+  /* If ISIZE is greater than REGSIZE, the inner value is split into blocks
+ of size REGSIZE.  The outer size must then be ordered wrt REGSIZE,
+ otherwise we wouldn't know at compile time how many blocks the
+ outer mode occupies.  */
+  if (maybe_gt (isize, regsize) && !ordered_p (osize, regsize))
 return false;
 
   /* For normal pseudo registers, we want most of the same checks.  Namely:
diff --git a/gcc/testsuite/gcc.dg/pr120447.c b/gcc/testsuite/gcc.dg/pr120447.c
new file mode 100644
index ..bd51f9b174d4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120447.c
@@ -0,0 +1,24 @@
+/* { dg-options "-Ofast" } */
+/* { dg-additional-options "-mcpu=neoverse-v2" { target aarch64*-*-* } } */
+
+char g;
+long h;
+typedef struct {
+  void *data;
+} i;
+i* a;
+void b(i *j, char *p2);
+void c(char *d) {
+  d = d ? " and " : " or ";
+  b(a, d);
+}
+void b(i *j, char *p2) {
+  h = __builtin_strlen(p2);
+  while (g)
+;
+  int *k = j->data;
+  char *l = p2, *m = p2 + h;
+  l += 4;
+  while (l < m)
+*k++ = *l++;
+}


[gcc r16-1097] Use MEM_EXPR only if MEM_P is true

2025-06-04 Thread H.J. Lu via Gcc-cvs
https://gcc.gnu.org/g:f7df645956459c559f254d622090d4dd09159890

commit r16-1097-gf7df645956459c559f254d622090d4dd09159890
Author: H.J. Lu 
Date:   Wed Jun 4 08:48:40 2025 +0800

Use MEM_EXPR only if MEM_P is true

On s390x, for input:

(call_insn/u 7 6 11 2 (parallel [
(set (reg:SI 2 %r2)
(call (subreg:QI (symbol_ref:SI ("__tls_get_offset") [flags 
0x1]) 3)
(const_int 0 [0])))
(clobber (reg:SI 14 %r14))
(use (unspec:SI [
(const_int 0 [0])
] UNSPEC_TLSLDM))
]) "/tmp/foo.c":12:26 2602 {*brasl_tls}
 (expr_list:REG_EH_REGION (const_int -2147483648 [0x8000])
(nil))
(expr_list (use (reg:SI 2 %r2))
(expr_list (use (reg:SI 12 %r12))
(nil

after r16-1041-g2da641d0170090, get_call_rtx_from returns:

(call (subreg:QI (symbol_ref:SI ("__tls_get_offset") [flags 0x1]) 3)
(const_int 0 [0]))

and we got

Program received signal SIGSEGV, Segmentation fault.
0x0131174f in prepare_call_arguments (
bb=, insn=0x7fffe980cc60)
at /export/gnu/import/git/sources/gcc/gcc/var-tracking.cc:6277
6277fndecl = MEM_EXPR (XEXP (call, 0));
(gdb) bt
bb=, insn=0x7fffe980cc60)
at /export/gnu/import/git/sources/gcc/gcc/var-tracking.cc:6277
at /export/gnu/import/git/sources/gcc/gcc/var-tracking.cc:10297
at /export/gnu/import/git/sources/gcc/gcc/var-tracking.cc:10526
at /export/gnu/import/git/sources/gcc/gcc/var-tracking.cc:10579
at /export/gnu/import/git/sources/gcc/gcc/var-tracking.cc:10616

Update prepare_call_arguments to check MEM_P before using MEM_EXPR.

gcc/

PR debug/120525
* var-tracking.cc (prepare_call_arguments): Use MEM_EXPR only
if MEM_P is true.

gcc/testsuite/

PR debug/120525
* gcc.dg/pr120525.c: New test.

Signed-off-by: H.J. Lu 

Diff:
---
 gcc/testsuite/gcc.dg/pr120525.c | 22 ++
 gcc/var-tracking.cc |  2 +-
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.dg/pr120525.c b/gcc/testsuite/gcc.dg/pr120525.c
new file mode 100644
index ..5ab7a2244dc2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120525.c
@@ -0,0 +1,22 @@
+/* { dg-do compile { target fpic } } */
+/* { dg-options "-O2 -fpic -g" } */
+/* { dg-additional-options "-m31" { target s390x-*-* } } */
+
+typedef __SIZE_TYPE__ uintptr_t;
+static __thread uintptr_t start_sp;
+static inline uintptr_t
+__thread_stack_pointer (void)
+{
+  return (uintptr_t) __builtin_frame_address (0);
+}
+
+void
+update_data (void)
+{
+  if (__builtin_expect ((!start_sp), 0))
+start_sp = __thread_stack_pointer ();
+
+  uintptr_t sp = __thread_stack_pointer ();
+  if (__builtin_expect ((sp > start_sp), 0))
+start_sp = sp;
+}
diff --git a/gcc/var-tracking.cc b/gcc/var-tracking.cc
index d70ed02e98cd..8732c3ba62aa 100644
--- a/gcc/var-tracking.cc
+++ b/gcc/var-tracking.cc
@@ -6273,7 +6273,7 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn)
  if (SYMBOL_REF_DECL (symbol))
fndecl = SYMBOL_REF_DECL (symbol);
}
-  if (fndecl == NULL_TREE)
+  if (fndecl == NULL_TREE && MEM_P (XEXP (call, 0)))
fndecl = MEM_EXPR (XEXP (call, 0));
   if (fndecl
  && TREE_CODE (TREE_TYPE (fndecl)) != FUNCTION_TYPE


[gcc r16-1102] libstdc++: Fix std::counting_semaphore::acquire deadlock [PR104928]

2025-06-04 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:7be4913b8f8b1e1474751656d45b301aa0c20790

commit r16-1102-g7be4913b8f8b1e1474751656d45b301aa0c20790
Author: Jonathan Wakely 
Date:   Mon Jun 2 13:06:27 2025 +0100

libstdc++: Fix std::counting_semaphore::acquire deadlock [PR104928]

There's a deadlock in std::counting_semaphore that occurs when the
semaphore is under contention. The bug happens when one thread tries to
acquire the mutex, calling __semaphore_base::_S_do_try_acquire to
atomically decrement the counter using compare_exchange_strong. If the
counter is non-zero (and so should be possible to decrement) but another
thread changes it (either incrementing or decrementing it) then the
compare_exchange fails and _S_do_try_acquire returns false. Because that
function is used by the predicate passed to __atomic_wait_address, when
it returns false the thread does a futex wait until the value changes.
However, when the predicate is false because the compare_exchange failed
due to not matching the expected value, waiting for the value to change
is incorrect. The correct behaviour would be to retry the
compare_exchange using the new value (as long as it's still non-zero).
Waiting for the value to change again means we can block forever,
because it might never change again.

The predicate should only test the value, not also attempt to alter it,
and its return value should mean only one thing, not conflate a busy
semaphore that cannot be acquired with a contended one that can be
acquired by retrying.

The correct behaviour of __semaphore_base::_M_acquire would be to
attempt the decrement, and to retry immediately if it failed due to
contention on the variable (i.e. due to the variable not having the
expected value).  It should only wait for the value to change when the
value is zero, because that's the only time we can't decrement it.

This commit moves the _S_do_try_acquire call out of the predicate and
loops while it is false, only doing an atomic wait when the counter's
value is zero. The predicate used for the atomic wait now only checks
whether the value is decrementable (non-zero), without also trying to
perform that decrement.

In order for the caller to tell whether it should retry a failed
_S_do_try_acquire or should wait for the value to be non-zero, the value
obtained by a failed compare_exchange needs to be passed back to the
caller. _S_do_try_acquire is changed to take its parameter by reference,
so that the caller gets the new value and can check whether it's zero.

In order to avoid doing another atomic load after returning from an
atomic wait, the predicate is also changed to capture the local __val by
reference, and then assign to __val when it sees a non-zero value. That
makes the new value available to _M_acquire, so it can be passed to
_S_do_try_acquire as the expected value of the compare_exchange.
Although this means that the predicate is modifying data again, not just
checking a value, this modification is safe. It's not changing the
semaphore's counter, only changing a local variable in the caller to
avoid a redundant atomic load.

Equivalent changes are made to _M_try_acquire_until and
_M_try_acquire_for. They have the same bug, although they can escape the
deadlock if the wait is interrupted by timing out. For _M_acquire
there's no time out so it potentially waits forever.

_M_try_acquire also has the same bug, but can be simplified to just
calling _M_try_acquire_for(0ns). A timeout of zero results in calling
__wait_impl with the __spin_only flag set, so that the value is loaded
and checked in a spin loop but there is no futex wait. This means that
_M_try_acquire can still succeed under light contention if the counter
is being changed concurrently, at the cost of a little extra overhead.
It would be possible to implement _M_try_acquire as nothing more than an
atomic load and a compare_exchange, but it would fail when there is any
contention.

libstdc++-v3/ChangeLog:

PR libstdc++/104928
* include/bits/semaphore_base.h (_S_do_try_acquire): Take old
value by reference.
(_M_acquire): Move _S_do_try_acquire call out of the predicate
and loop on its result. Make the predicate capture and update
the local copy of the value.
(_M_try_acquire_until, _M_try_acquire_for): Likewise.
(_M_try_acquire): Just call _M_try_acquire_for.
* testsuite/30_threads/semaphore/104928-2.cc: New test.
* testsuite/30_threads/semaphore/104928.cc: New test.

Reviewed-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/semaphore_base.h |  74 ++-
 .../testsuite/30_threads/semaphore/104928-2.cc | 101 +

[gcc r16-1103] libstdc++: Refactor __semaphore_base member functions

2025-06-04 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:5dc3c5c16480e0fac0df248639960cfa26d774a0

commit r16-1103-g5dc3c5c16480e0fac0df248639960cfa26d774a0
Author: Jonathan Wakely 
Date:   Mon Jun 2 23:01:40 2025 +0100

libstdc++: Refactor __semaphore_base member functions

Replace the _S_get_current and _S_do_try_acquire static member functions
with non-static member functions _M_get_current and _M_do_try_acquire.
This means they don't need the address of _M_counter passed in.

libstdc++-v3/ChangeLog:

* include/bits/semaphore_base.h (_S_get_current): Replace with
non-static _M_get_current.
(_S_do_try_acquire): Replace with non-static _M_do_try_acquire.

Reviewed-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/semaphore_base.h | 41 --
 1 file changed, 22 insertions(+), 19 deletions(-)

diff --git a/libstdc++-v3/include/bits/semaphore_base.h 
b/libstdc++-v3/include/bits/semaphore_base.h
index 526da4d82b6a..3f7a33ccd51a 100644
--- a/libstdc++-v3/include/bits/semaphore_base.h
+++ b/libstdc++-v3/include/bits/semaphore_base.h
@@ -64,20 +64,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 __semaphore_base(const __semaphore_base&) = delete;
 __semaphore_base& operator=(const __semaphore_base&) = delete;
 
-static _GLIBCXX_ALWAYS_INLINE __count_type
-_S_get_current(__count_type* __counter) noexcept
+// Load the current counter value.
+_GLIBCXX_ALWAYS_INLINE __count_type
+_M_get_current() const noexcept
+{ return __atomic_impl::load(&_M_counter, memory_order::acquire); }
+
+// Try to acquire the semaphore (i.e. decrement the counter).
+// Returns false if the current counter is zero, or if another thread
+// decrements the value first. In the latter case, __cur is set to the
+// new value.
+_GLIBCXX_ALWAYS_INLINE bool
+_M_do_try_acquire(__count_type& __cur) noexcept
 {
-  return __atomic_impl::load(__counter, memory_order::acquire);
-}
-
-static _GLIBCXX_ALWAYS_INLINE bool
-_S_do_try_acquire(__count_type* __counter, __count_type& __old) noexcept
-{
-  if (__old == 0)
-   return false;
+  if (__cur == 0)
+   return false; // Cannot decrement when it's already zero.
 
-  return __atomic_impl::compare_exchange_strong(__counter,
-   __old, __old - 1,
+  return __atomic_impl::compare_exchange_strong(&_M_counter,
+   __cur, __cur - 1,
memory_order::acquire,
memory_order::relaxed);
 }
@@ -85,7 +88,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 void
 _M_acquire() noexcept
 {
-  auto const __vfn = [this]{ return _S_get_current(&this->_M_counter); };
+  auto const __vfn = [this]{ return _M_get_current(); };
   auto __val = __vfn();
   auto const __pred = [&__val](__count_type __cur) {
if (__cur > 0)
@@ -95,7 +98,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  }
return false;
   };
-  while (!_S_do_try_acquire(&_M_counter, __val))
+  while (!_M_do_try_acquire(__val))
if (__val == 0)
  std::__atomic_wait_address(&_M_counter, __pred, __vfn, true);
 }
@@ -103,7 +106,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 bool
 _M_try_acquire() noexcept
 {
-  // The fastest implementation of this function is just _S_do_try_acquire
+  // The fastest implementation of this function is just _M_do_try_acquire
   // but that can fail under contention even when _M_count > 0.
   // Using _M_try_acquire_for(0ns) will retry a few times in a loop.
   return _M_try_acquire_for(__detail::__wait_clock_t::duration{});
@@ -113,7 +116,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   bool
   _M_try_acquire_until(const chrono::time_point<_Clock, _Duration>& 
__atime) noexcept
   {
-   auto const __vfn = [this]{ return _S_get_current(&this->_M_counter); };
+   auto const __vfn = [this]{ return _M_get_current(); };
auto __val = __vfn();
auto const __pred = [&__val](__count_type __cur) {
  if (__cur > 0)
@@ -123,7 +126,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
  return false;
};
-   while (!_S_do_try_acquire(&this->_M_counter, __val))
+   while (!_M_do_try_acquire(__val))
  if (__val == 0)
{
  if (!std::__atomic_wait_address_until(&_M_counter, __pred,
@@ -137,7 +140,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   bool
   _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) 
noexcept
   {
-   auto const __vfn = [this]{ return _S_get_current(&this->_M_counter); };
+   auto const __vfn = [this]{ return _M_get_current(); };
auto __val = __vfn();
auto const __pred = [&__val](__count_type __cur) {
  if (__cur > 0)
@@ -147,7 +150,7 @@ _GLIBCXX_BEGIN_NA

[gcc r16-1104] [PATCH v2] RISC-V: Add svbare extension.

2025-06-04 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:07e3ed74a2b648c0ce8e823bbf5bd8f23383efa1

commit r16-1104-g07e3ed74a2b648c0ce8e823bbf5bd8f23383efa1
Author: Dongyan Chen 
Date:   Wed Jun 4 07:57:01 2025 -0600

[PATCH v2] RISC-V: Add svbare extension.

This patch support svbare extension, which is an extension in RVA23 profile.
To enable GCC to recognize and process svbare extension correctly at 
compile time.

gcc/ChangeLog:

* config/riscv/riscv-ext.def: New extension defs.
* config/riscv/riscv-ext.opt: Ditto.
* doc/riscv-ext.texi: Ditto.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/arch-60.c: New test.

Diff:
---
 gcc/config/riscv/riscv-ext.def   | 13 +
 gcc/config/riscv/riscv-ext.opt   |  2 ++
 gcc/doc/riscv-ext.texi   |  4 
 gcc/testsuite/gcc.target/riscv/arch-60.c |  5 +
 4 files changed, 24 insertions(+)

diff --git a/gcc/config/riscv/riscv-ext.def b/gcc/config/riscv/riscv-ext.def
index 2d052c152068..c3d0bd42b200 100644
--- a/gcc/config/riscv/riscv-ext.def
+++ b/gcc/config/riscv/riscv-ext.def
@@ -1961,6 +1961,19 @@ DEFINE_RISCV_EXT(
   /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
   /* EXTRA_EXTENSION_FLAGS */ 0)
 
+DEFINE_RISCV_EXT(
+  /* NAME */ svbare,
+  /* UPPERCAE_NAME */ SVBARE,
+  /* FULL_NAME */ "Satp mode bare is supported",
+  /* DESC */ "",
+  /* URL */ ,
+  /* DEP_EXTS */ ({"zicsr"}),
+  /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+  /* FLAG_GROUP */ sv,
+  /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+  /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+  /* EXTRA_EXTENSION_FLAGS */ 0)
+
 #include "riscv-ext-corev.def"
 #include "riscv-ext-sifive.def"
 #include "riscv-ext-thead.def"
diff --git a/gcc/config/riscv/riscv-ext.opt b/gcc/config/riscv/riscv-ext.opt
index e0314430ffb1..3e5cbb34898e 100644
--- a/gcc/config/riscv/riscv-ext.opt
+++ b/gcc/config/riscv/riscv-ext.opt
@@ -379,6 +379,8 @@ Mask(SVADU) Var(riscv_sv_subext)
 
 Mask(SVADE) Var(riscv_sv_subext)
 
+Mask(SVBARE) Var(riscv_sv_subext)
+
 Mask(XCVALU) Var(riscv_xcv_subext)
 
 Mask(XCVBI) Var(riscv_xcv_subext)
diff --git a/gcc/doc/riscv-ext.texi b/gcc/doc/riscv-ext.texi
index e7e1f75cca6d..3e6541ac732b 100644
--- a/gcc/doc/riscv-ext.texi
+++ b/gcc/doc/riscv-ext.texi
@@ -582,6 +582,10 @@
 @tab 1.0
 @tab Cause exception when hardware updating of A/D bits is disabled
 
+@item svbare
+@tab 1.0
+@tab Satp mode bare is supported
+
 @item xcvalu
 @tab 1.0
 @tab Core-V miscellaneous ALU extension
diff --git a/gcc/testsuite/gcc.target/riscv/arch-60.c 
b/gcc/testsuite/gcc.target/riscv/arch-60.c
new file mode 100644
index ..ea599f20522d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-60.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i_svbare -mabi=lp64" } */
+int foo()
+{
+}


[gcc r16-1105] [PATCH] RISC-V: Imply zicsr for svade and svadu extensions.

2025-06-04 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:28106a0c5d18173832d8013dccbb6fcc71646868

commit r16-1105-g28106a0c5d18173832d8013dccbb6fcc71646868
Author: Dongyan Chen 
Date:   Wed Jun 4 08:03:31 2025 -0600

[PATCH] RISC-V: Imply zicsr for svade and svadu extensions.

This patch implies zicsr for svade and svadu extensions.
According to the riscv-privileged spec, the svade and svadu extensions
are privileged instructions, so they should imply zicsr.

gcc/ChangeLog:

* config/riscv/riscv-ext.def: Imply zicsr.

Diff:
---
 gcc/config/riscv/riscv-ext.def | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/config/riscv/riscv-ext.def b/gcc/config/riscv/riscv-ext.def
index c3d0bd42b200..0e989e122195 100644
--- a/gcc/config/riscv/riscv-ext.def
+++ b/gcc/config/riscv/riscv-ext.def
@@ -1941,7 +1941,7 @@ DEFINE_RISCV_EXT(
   /* FULL_NAME */ "Hardware Updating of A/D Bits extension",
   /* DESC */ "",
   /* URL */ ,
-  /* DEP_EXTS */ ({}),
+  /* DEP_EXTS */ ({"zicsr"}),
   /* SUPPORTED_VERSIONS */ ({{1, 0}}),
   /* FLAG_GROUP */ sv,
   /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
@@ -1954,7 +1954,7 @@ DEFINE_RISCV_EXT(
   /* FULL_NAME */ "Cause exception when hardware updating of A/D bits is 
disabled",
   /* DESC */ "",
   /* URL */ ,
-  /* DEP_EXTS */ ({}),
+  /* DEP_EXTS */ ({"zicsr"}),
   /* SUPPORTED_VERSIONS */ ({{1, 0}}),
   /* FLAG_GROUP */ sv,
   /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,


[gcc r16-1106] libstdc++: Implement C++23 P1659R3 starts_with and ends_with

2025-06-04 Thread Patrick Palka via Libstdc++-cvs
https://gcc.gnu.org/g:6545e2f301cc1c276dd039e8739f7cc912ec5ae9

commit r16-1106-g6545e2f301cc1c276dd039e8739f7cc912ec5ae9
Author: Patrick Palka 
Date:   Wed Jun 4 10:29:47 2025 -0400

libstdc++: Implement C++23 P1659R3 starts_with and ends_with

This implements ranges::starts_with and ranges::ends_with from the C++23
paper P1659R3.  The corresponding_S_impl member functions take optional
optional size parameters __n1 and __n2 of the two ranges, where -1 means
the corresponding size is not known.

libstdc++-v3/ChangeLog:

* include/bits/ranges_algo.h (__starts_with_fn, starts_with):
Define.
(__ends_with_fn, ends_with): Define.
* include/bits/version.def (ranges_starts_ends_with): Define.
* include/bits/version.h: Regenerate.
* include/std/algorithm: Provide __cpp_lib_ranges_starts_ends_with.
* src/c++23/std.cc.in (ranges::starts_with): Export.
(ranges::ends_with): Export.
* testsuite/25_algorithms/ends_with/1.cc: New test.
* testsuite/25_algorithms/starts_with/1.cc: New test.

Reviewed-by: Tomasz Kamiński 
Reviewed-by: Jonathan Wakely 

Diff:
---
 libstdc++-v3/include/bits/ranges_algo.h| 248 +
 libstdc++-v3/include/bits/version.def  |   8 +
 libstdc++-v3/include/bits/version.h|  10 +
 libstdc++-v3/include/std/algorithm |   1 +
 libstdc++-v3/src/c++23/std.cc.in   |   4 +
 .../testsuite/25_algorithms/ends_with/1.cc | 165 ++
 .../testsuite/25_algorithms/starts_with/1.cc   | 158 +
 7 files changed, 594 insertions(+)

diff --git a/libstdc++-v3/include/bits/ranges_algo.h 
b/libstdc++-v3/include/bits/ranges_algo.h
index 7b1408452128..a62c3cd3954d 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -438,6 +438,254 @@ namespace ranges
 
   inline constexpr __search_n_fn search_n{};
 
+#if __glibcxx_ranges_starts_ends_with // C++ >= 23
+  struct __starts_with_fn
+  {
+template _Sent1,
+input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+typename _Pred = ranges::equal_to,
+typename _Proj1 = identity, typename _Proj2 = identity>
+  requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
+  constexpr bool
+  operator()(_Iter1 __first1, _Sent1 __last1,
+_Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
+_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
+  {
+   iter_difference_t<_Iter1> __n1 = -1;
+   iter_difference_t<_Iter2> __n2 = -1;
+   if constexpr (sized_sentinel_for<_Sent1, _Iter1>)
+ __n1 = __last1 - __first1;
+   if constexpr (sized_sentinel_for<_Sent2, _Iter2>)
+ __n2 = __last2 - __first2;
+   return _S_impl(std::move(__first1), __last1, __n1,
+  std::move(__first2), __last2, __n2,
+  std::move(__pred),
+  std::move(__proj1), std::move(__proj2));
+  }
+
+template
+  requires indirectly_comparable, iterator_t<_Range2>,
+_Pred, _Proj1, _Proj2>
+  constexpr bool
+  operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
+_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
+  {
+   range_difference_t<_Range1> __n1 = -1;
+   range_difference_t<_Range2> __n2 = -1;
+   if constexpr (sized_range<_Range1>)
+ __n1 = ranges::size(__r1);
+   if constexpr (sized_range<_Range2>)
+ __n2 = ranges::size(__r2);
+   return _S_impl(ranges::begin(__r1), ranges::end(__r1), __n1,
+  ranges::begin(__r2), ranges::end(__r2), __n2,
+  std::move(__pred),
+  std::move(__proj1), std::move(__proj2));
+  }
+
+  private:
+template
+  static constexpr bool
+  _S_impl(_Iter1 __first1, _Sent1 __last1, iter_difference_t<_Iter1> __n1,
+ _Iter2 __first2, _Sent2 __last2, iter_difference_t<_Iter2> __n2,
+ _Pred __pred, _Proj1 __proj1, _Proj2 __proj2)
+  {
+   if (__first2 == __last2) [[unlikely]]
+ return true;
+   else if (__n1 == -1 || __n2 == -1)
+ return ranges::mismatch(std::move(__first1), __last1,
+ std::move(__first2), __last2,
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2)).in2 
== __last2;
+   else if (__n1 < __n2)
+ return false;
+   else if constexpr (random_access_iterator<_Iter1>)
+ return ranges::equal(__first1, __first1 + 
iter_difference_t<_Iter1>(__n2),
+  std::move(__first2), __last2,
+  std::move(__pred),
+  std::move(__proj1), std::move(__proj

[gcc r16-1107] libstdc++: Test for formatting with empty spec for time points.

2025-06-04 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:3cfa53aa95a19c3b5fc711ad4d9f39ec9b8e7c3f

commit r16-1107-g3cfa53aa95a19c3b5fc711ad4d9f39ec9b8e7c3f
Author: Tomasz Kamiński 
Date:   Tue Jun 3 11:40:17 2025 +0200

libstdc++: Test for formatting with empty spec for time points.

Adding a tests for behavior of the ostream operator and the formatting
with empty chrono-spec for the chrono types. Current coverage is:
 * time point, zoned_time and local_time_format in this commit,
 * duration and hh_mm_ss in r16-1099-gac0a04b7a254fb,
 * calendar types in r16-1016-g28a17985dd34b7.

libstdc++-v3/ChangeLog:

* testsuite/std/time/format/empty_spec.cc: New tests.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 .../testsuite/std/time/format/empty_spec.cc| 208 +++--
 1 file changed, 194 insertions(+), 14 deletions(-)

diff --git a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc 
b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
index 46942dc30fc6..ec57a6f0d209 100644
--- a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
+++ b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
@@ -12,6 +12,46 @@ using namespace std::chrono;
 #define WIDEN_(C, S) ::std::__format::_Widen(S, L##S)
 #define WIDEN(S) WIDEN_(_CharT, S)
 
+template
+void
+test_no_empty_spec()
+{
+  try
+  {
+T t{};
+
+if constexpr (std::is_same_v)
+  (void)std::vformat("{}", std::make_format_args(t));
+#ifdef _GLIBCXX_USE_WCHAR_T
+else
+  (void)std::vformat(L"{}", std::make_wformat_args(t));
+#endif // _GLIBCXX_USE_WCHAR_T
+VERIFY(false);
+  }
+  catch (const std::format_error&)
+  {
+VERIFY(true);
+  }
+}
+
+template
+void verify(const T& t, std::basic_string_view<_CharT> str)
+{
+  std::basic_string<_CharT> res;
+
+  res = std::format(WIDEN("{}"), t);
+  VERIFY( res == str );
+
+  std::basic_stringstream<_CharT> os;
+  os << t;
+  res = std::move(os).str();
+  VERIFY( res == str );
+}
+
+template
+void verify(const T& t, const CharT* str)
+{ verify(t, std::basic_string_view(str)); }
+
 template
 void
 test_padding()
@@ -37,20 +77,6 @@ test_padding()
   VERIFY( res == WIDEN("==16 is not a valid month==") );
 }
 
-template
-void verify(const T& t, const _CharT* str)
-{
-  std::basic_string<_CharT> res;
-
-  res = std::format(WIDEN("{}"), t);
-  VERIFY( res == str );
-
-  std::basic_stringstream<_CharT> os;
-  os << t;
-  res = std::move(os).str();
-  VERIFY( res == str );
-}
-
 template
 struct Rep
 {
@@ -553,6 +579,159 @@ test_calendar()
   test_year_month_weekday_last();
 }
 
+template
+constexpr auto
+wall_cast(const local_time& tp)
+{
+  using TP = time_point>;
+  if constexpr (std::is_same_v || std::is_same_v)
+return clock_cast(wall_cast(tp));
+  else if constexpr (std::is_same_v)
+return TP(floor(tp.time_since_epoch()) + days(4383));
+  else if constexpr (std::is_same_v)
+return TP(floor(tp.time_since_epoch()) - days(3657));
+  else // system_clock, local_t
+return time_point(floor(tp.time_since_epoch()));
+}
+
+using decadays = duration>;
+using kilodays = duration>;
+
+template
+void
+test_time_point(bool daysAsTime)
+{
+  std::basic_string<_CharT> res;
+
+  const auto lt = local_days(2024y/March/22) + 13h + 24min + 54s + 111222333ns;
+  auto strip_time = [daysAsTime](std::basic_string_view<_CharT> sv)
+  { return daysAsTime ? sv : sv.substr(0, 10); };
+
+  verify( wall_cast(lt),
+ WIDEN("2024-03-22 13:24:54.111222333") );
+  verify( wall_cast(lt),
+ WIDEN("2024-03-22 13:24:54.111222") );
+  verify( wall_cast(lt),
+ WIDEN("2024-03-22 13:24:54.111") );
+  verify( wall_cast(lt),
+ WIDEN("2024-03-22 13:24:54") );
+  verify( wall_cast(lt),
+ WIDEN("2024-03-22 13:24:00") );
+  verify( wall_cast(lt),
+ WIDEN("2024-03-22 13:00:00") );
+  verify( wall_cast(lt),
+ strip_time(WIDEN("2024-03-22 00:00:00")) );
+  verify( wall_cast(lt),
+ strip_time(WIDEN("2024-03-18 00:00:00")) );
+  verify( wall_cast(lt),
+ strip_time(WIDEN("2022-01-08 00:00:00")) );
+}
+
+template
+void
+test_leap_second()
+{
+  std::basic_string<_CharT> res;
+
+  const auto st = sys_days(2012y/June/30) + 23h + 59min + 59s + 111222333ns;
+  auto tp = clock_cast(st);
+  tp += 1s;
+
+  verify( floor(tp),
+ WIDEN("2012-06-30 23:59:60.111222333") );
+  verify( floor(tp),
+ WIDEN("2012-06-30 23:59:60.111222") );
+  verify( floor(tp),
+ WIDEN("2012-06-30 23:59:60.111") );
+  verify( floor(tp),
+ WIDEN("2012-06-30 23:59:60") );
+}
+
+template
+auto
+make_zoned(const sys_time& st, const time_zone* tz)
+{ return zoned_time(tz, floor(st)); }
+
+template
+void
+test_zoned_time()
+{
+  const auto st = sys_days(2024y/March/22) + 13h + 24min + 54s + 111222333ns;
+  const time_zone* tz = locate_zone("Europe/Sofia");
+  VERIFY( tz != nullptr );
+
+  verify( make_zoned(st, tz),
+ WIDEN("2024-03-22 15:24:54.111222333 EET") );
+  verify( make_zoned(st, tz),

[gcc r16-1108] ranger: Add support for float <-> float casts [PR120231]

2025-06-04 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:b7960a3f966a0f87888de0fc588999d026918449

commit r16-1108-gb7960a3f966a0f87888de0fc588999d026918449
Author: Jakub Jelinek 
Date:   Wed Jun 4 17:21:51 2025 +0200

ranger: Add support for float <-> float casts [PR120231]

I've noticed we don't even support say float -> double and other
scalar floating point to scalar floating point conversions in the
ranger, we just end up with VARYING for those.

The following patch attempts to fix that.
The reverse cast case uses float_binary_op_range_finish e.g. because
if the result isn't infinite, then the source couldn't be infinite
either even if the reverse fold_range would suggest that.
And special cases the case of guaranteed widening cast (where
we have assurance that all the source type values are exactly
representable in the destination type; using ieee_bits for that).

2025-06-04  Jakub Jelinek  

PR tree-optimization/120231
* range-op-mixed.h (operator_cast::fold_range): Add overload
with 3 {,const} frange & operands.  Change parameter names and
add final override keywords for float <-> integer cast overloads.
(operator_cast::op1_range): Likewise.
* range-op-float.cc (operator_cast::fold_range): New overload
with 3 {,const} frange & operands.
(operator_cast::op1_range): Likewise.

* gcc.dg/tree-ssa/pr120231-1.c: New test.

Diff:
---
 gcc/range-op-float.cc  | 121 +
 gcc/range-op-mixed.h   |  26 ---
 gcc/testsuite/gcc.dg/tree-ssa/pr120231-1.c |  67 
 3 files changed, 202 insertions(+), 12 deletions(-)

diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index dafd9c0688c0..1543b94b878e 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -2899,6 +2899,127 @@ private:
   }
 } fop_div;
 
+bool
+operator_cast::fold_range (frange &r, tree type, const frange &op1,
+  const frange &, relation_trio) const
+{
+  REAL_VALUE_TYPE lb, ub;
+  enum machine_mode mode = TYPE_MODE (type);
+  bool mode_composite = MODE_COMPOSITE_P (mode);
+
+  if (empty_range_varying (r, type, op1, op1))
+return true;
+  if (!MODE_HAS_NANS (mode) && op1.maybe_isnan ())
+{
+  r.set_varying (type);
+  return true;
+}
+  if (op1.known_isnan ())
+{
+  r.set_nan (type);
+  return true;
+}
+
+  const REAL_VALUE_TYPE &lh_lb = op1.lower_bound ();
+  const REAL_VALUE_TYPE &lh_ub = op1.upper_bound ();
+  real_convert (&lb, mode, &lh_lb);
+  real_convert (&ub, mode, &lh_ub);
+
+  if (flag_rounding_math)
+{
+  if (real_less (&lh_lb, &lb))
+   {
+ if (mode_composite
+ && (real_isdenormal (&lb, mode) || real_iszero (&lb)))
+   {
+ // IBM extended denormals only have DFmode precision.
+ REAL_VALUE_TYPE tmp, tmp2;
+ real_convert (&tmp2, DFmode, &lh_lb);
+ real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
+ &dconstninf);
+ real_convert (&lb, mode, &tmp);
+   }
+ else
+   frange_nextafter (mode, lb, dconstninf);
+   }
+  if (real_less (&ub, &lh_ub))
+   {
+ if (mode_composite
+ && (real_isdenormal (&ub, mode) || real_iszero (&ub)))
+   {
+ // IBM extended denormals only have DFmode precision.
+ REAL_VALUE_TYPE tmp, tmp2;
+ real_convert (&tmp2, DFmode, &lh_ub);
+ real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
+ &dconstinf);
+ real_convert (&ub, mode, &tmp);
+   }
+ else
+   frange_nextafter (mode, ub, dconstinf);
+   }
+}
+
+  r.set (type, lb, ub, op1.get_nan_state ());
+
+  if (flag_trapping_math
+  && MODE_HAS_INFINITIES (TYPE_MODE (type))
+  && r.known_isinf ()
+  && !op1.known_isinf ())
+{
+  REAL_VALUE_TYPE inf = r.lower_bound ();
+  if (real_isneg (&inf))
+   {
+ REAL_VALUE_TYPE min = real_min_representable (type);
+ r.set (type, inf, min);
+   }
+  else
+   {
+ REAL_VALUE_TYPE max = real_max_representable (type);
+ r.set (type, max, inf);
+   }
+}
+
+  r.flush_denormals_to_zero ();
+  return true;
+}
+
+// Implement fold for a cast from float to another float.
+bool
+operator_cast::op1_range (frange &r, tree type, const frange &lhs,
+ const frange &op2, relation_trio) const
+{
+  if (lhs.undefined_p ())
+return false;
+  tree lhs_type = lhs.type ();
+  enum machine_mode mode = TYPE_MODE (type);
+  enum machine_mode lhs_mode = TYPE_MODE (lhs_type);
+  frange wlhs;
+  bool rm;
+  if (REAL_MODE_FORMAT (mode)->ieee_bits
+  && REAL_MODE_FORMAT (lhs_mode)->ieee_bits
+  && (REAL_MODE_FORMAT (lhs_mode)->ieee_bits
+   

[gcc(refs/users/mikael/heads/refactor_descriptor_v05)] Correction régression pr68864

2025-06-04 Thread Mikael Morin via Gcc-cvs
https://gcc.gnu.org/g:7470b2f120badc9d947e51ad193f7de83880be98

commit 7470b2f120badc9d947e51ad193f7de83880be98
Author: Mikael Morin 
Date:   Wed Jun 4 16:12:40 2025 +0200

Correction régression pr68864

Diff:
---
 gcc/fortran/trans-stmt.cc | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 02d3e9e5a397..6949e00a3460 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -7838,7 +7838,12 @@ gfc_trans_deallocate (gfc_code *code)
 
  if (al->expr->ts.type == BT_CLASS)
{
- gfc_reset_vptr (&se.pre, al->expr);
+ if (is_subref_array (al->expr))
+   /* Finalisation code can create bogus
+  array subreferences, ignore those.  */
+   ;
+ else
+   gfc_reset_vptr (&se.pre, al->expr);
  if (UNLIMITED_POLY (al->expr)
  || (al->expr->ts.type == BT_DERIVED
  && al->expr->ts.u.derived->attr.unlimited_polymorphic))


[gcc r16-1110] ext-dce: Don't refine live width with SUBREG mode if !TRULY_NOOP_TRUNCATION_MODES_P [PR 120050]

2025-06-04 Thread Xi Ruoyao via Gcc-cvs
https://gcc.gnu.org/g:65f3a439c4f76fe780a30ac66969f51035c4bf98

commit r16-1110-g65f3a439c4f76fe780a30ac66969f51035c4bf98
Author: Xi Ruoyao 
Date:   Sun May 11 16:44:31 2025 +0800

ext-dce: Don't refine live width with SUBREG mode if 
!TRULY_NOOP_TRUNCATION_MODES_P [PR 120050]

If we see a promoted subreg and TRULY_NOOP_TRUNCATION says the
truncation is not a noop, then all bits of the inner reg are live.  We
cannot reduce the live mask to that of the mode of the subreg.

gcc/ChangeLog:

PR rtl-optimization/120050
* ext-dce.cc (ext_dce_process_uses): Break early if a SUBREG in
rhs is promoted and the truncation from the inner mode to the
outer mode is not a noop when handling SETs.

Diff:
---
 gcc/ext-dce.cc | 17 +++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/gcc/ext-dce.cc b/gcc/ext-dce.cc
index a03439501419..aa80c0483d61 100644
--- a/gcc/ext-dce.cc
+++ b/gcc/ext-dce.cc
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "print-rtl.h"
 #include "dbgcnt.h"
 #include "diagnostic-core.h"
+#include "target.h"
 
 /* These should probably move into a C++ class.  */
 static vec livein;
@@ -764,13 +765,25 @@ ext_dce_process_uses (rtx_insn *insn, rtx obj,
 We don't want to mark those bits live unnecessarily
 as that inhibits extension elimination in important
 cases such as those in Coremark.  So we need that
-outer code.  */
+outer code.
+
+But if !TRULY_NOOP_TRUNCATION_MODES_P, the mode
+change performed by Y would normally need to be a
+TRUNCATE rather than a SUBREG.  It is probably the
+guarantee provided by SUBREG_PROMOTED_VAR_P that
+allows the SUBREG in Y as an exception.  We must
+therefore preserve that guarantee and treat the
+upper bits of the inner register as live
+regardless of the outer code.  See PR 120050.  */
  if (!REG_P (SUBREG_REG (y))
  || (SUBREG_PROMOTED_VAR_P (y)
  && ((GET_CODE (SET_SRC (x)) == SIGN_EXTEND
   && SUBREG_PROMOTED_SIGNED_P (y))
  || (GET_CODE (SET_SRC (x)) == ZERO_EXTEND
- && SUBREG_PROMOTED_UNSIGNED_P (y)
+ && SUBREG_PROMOTED_UNSIGNED_P (y))
+ || !TRULY_NOOP_TRUNCATION_MODES_P (
+   GET_MODE (y),
+   GET_MODE (SUBREG_REG (y))
break;
 
  bit = subreg_lsb (y).to_constant ();


[gcc r16-1109] ranger: Some parameter formatting fixes

2025-06-04 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:b876a7fc805b9c7999c933a943eeb3b833780256

commit r16-1109-gb876a7fc805b9c7999c933a943eeb3b833780256
Author: Jakub Jelinek 
Date:   Wed Jun 4 17:22:58 2025 +0200

ranger: Some parameter formatting fixes

When reading the code, I've noticed various function definitions
with misaligned parameters, they should IMHO always align below the first
character after opening ( and in most cases they do, but in some
cases they were indented more or less.  Perhaps the functions changed
name or something.

2025-06-04  Jakub Jelinek  

* range-op-float.cc (range_operator::fold_range,
range_operator::op1_range, range_operator::op2_range,
range_operator::lhs_op1_relation, range_operator::lhs_op2_relation,
operator_equal::op1_range, foperator_unordered_gt::op1_range): Fix
up parameter indentation.
* range-op.cc (range_operator::fold_range, 
range_operator::op1_range,
range_operator::op1_op2_relation_effect,
range_operator::update_bitmask, plus_minus_ranges,
operator_bitwise_and::lhs_op1_relation): Likewise.

Diff:
---
 gcc/range-op-float.cc | 82 +--
 gcc/range-op.cc   | 27 +
 2 files changed, 56 insertions(+), 53 deletions(-)

diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index 1543b94b878e..ea344a4d043f 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -51,8 +51,8 @@ along with GCC; see the file COPYING3.  If not see
 
 bool
 range_operator::fold_range (frange &r, tree type,
- const frange &op1, const frange &op2,
- relation_trio trio) const
+   const frange &op1, const frange &op2,
+   relation_trio trio) const
 {
   if (empty_range_varying (r, type, op1, op2))
 return true;
@@ -112,20 +112,20 @@ range_operator::rv_fold (frange &r, tree type,
 
 bool
 range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
- tree type ATTRIBUTE_UNUSED,
- const frange &lh ATTRIBUTE_UNUSED,
- const irange &rh ATTRIBUTE_UNUSED,
- relation_trio) const
+   tree type ATTRIBUTE_UNUSED,
+   const frange &lh ATTRIBUTE_UNUSED,
+   const irange &rh ATTRIBUTE_UNUSED,
+   relation_trio) const
 {
   return false;
 }
 
 bool
 range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
- tree type ATTRIBUTE_UNUSED,
- const frange &lh ATTRIBUTE_UNUSED,
- const frange &rh ATTRIBUTE_UNUSED,
- relation_trio) const
+   tree type ATTRIBUTE_UNUSED,
+   const frange &lh ATTRIBUTE_UNUSED,
+   const frange &rh ATTRIBUTE_UNUSED,
+   relation_trio) const
 {
   return false;
 }
@@ -142,10 +142,10 @@ range_operator::fold_range (frange &r ATTRIBUTE_UNUSED,
 
 bool
 range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
-tree type ATTRIBUTE_UNUSED,
-const frange &lhs ATTRIBUTE_UNUSED,
-const frange &op2 ATTRIBUTE_UNUSED,
-relation_trio) const
+  tree type ATTRIBUTE_UNUSED,
+  const frange &lhs ATTRIBUTE_UNUSED,
+  const frange &op2 ATTRIBUTE_UNUSED,
+  relation_trio) const
 {
   return false;
 }
@@ -162,56 +162,56 @@ range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
 
 bool
 range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
-tree type ATTRIBUTE_UNUSED,
-const frange &lhs ATTRIBUTE_UNUSED,
-const frange &op1 ATTRIBUTE_UNUSED,
-relation_trio) const
+  tree type ATTRIBUTE_UNUSED,
+  const frange &lhs ATTRIBUTE_UNUSED,
+  const frange &op1 ATTRIBUTE_UNUSED,
+  relation_trio) const
 {
   return false;
 }
 
 bool
 range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
-tree type ATTRIBUTE_UNUSED,
-const irange &lhs ATTRIBUTE_UNUSED,
-const frange &op1 ATTRIBUTE_UNUSED,
-relation_trio) const
+  tree type ATTRIBUTE_UNUSED,
+  const irange &lhs ATTRIBUTE_UNUSED,
+  const frange &op1 ATTRIBUTE_UNUSED,
+  

[gcc(refs/users/mikael/heads/refactor_descriptor_v05)] Correction régression associate_target_5

2025-06-04 Thread Mikael Morin via Gcc-cvs
https://gcc.gnu.org/g:0b82f23024b41a8775e2ec90ed1ecaf24e8b96a2

commit 0b82f23024b41a8775e2ec90ed1ecaf24e8b96a2
Author: Mikael Morin 
Date:   Wed Jun 4 17:25:14 2025 +0200

Correction régression associate_target_5

Diff:
---
 gcc/fortran/trans-array.cc  | 33 -
 gcc/fortran/trans-descriptor.cc | 13 +++--
 gcc/fortran/trans-descriptor.h  |  2 +-
 3 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index bc902c5a89fb..43b5ec7339d2 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -7862,9 +7862,40 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
  gfc_get_array_span (desc, expr)));
}
 
+  tree elem_len = NULL_TREE;
+  if (subref_array_target)
+   {
+ /* In case of subreferences, don't pick element size from the original
+descriptor.  */
+ if (expr->ts.type == BT_CLASS)
+   {
+ tree class_container = ss->info->class_container;
+ tree vptr = gfc_class_vptr_get (class_container);
+ elem_len = gfc_vptr_size_get (vptr);
+   }
+ else if (expr->ts.type == BT_CHARACTER)
+   {
+ tree slen = ss->info->string_length;
+ slen = fold_convert_loc (input_location, gfc_array_index_type,
+  slen);
+ tree kind = build_int_cst (gfc_array_index_type,
+expr->ts.kind);
+ elem_len = fold_build2_loc (input_location, MULT_EXPR,
+ gfc_array_index_type, slen, kind);
+   }
+ else 
+   {
+ tree elem_type = gfc_get_element_type (TREE_TYPE (parm));
+ elem_len = TYPE_SIZE_UNIT (elem_type);
+   }
+
+ elem_len = fold_convert_loc (input_location, gfc_array_index_type,
+  elem_len);
+   }
+
   gfc_set_descriptor (&loop.pre, parm, desc, expr, loop.dimen, codim,
  ss, info, loop.from, loop.to, !se->data_not_needed,
- subref_array_target, !se->direct_byref);
+ subref_array_target, !se->direct_byref, elem_len);
 
   desc = parm;
 }
diff --git a/gcc/fortran/trans-descriptor.cc b/gcc/fortran/trans-descriptor.cc
index 23e1cd09a8e9..acbdceac77db 100644
--- a/gcc/fortran/trans-descriptor.cc
+++ b/gcc/fortran/trans-descriptor.cc
@@ -3064,13 +3064,19 @@ gfc_set_descriptor (stmtblock_t *block, tree dest, tree 
src, gfc_expr *src_expr,
int rank, int corank, gfc_ss *ss, gfc_array_info *info,
tree lowers[GFC_MAX_DIMENSIONS],
tree uppers[GFC_MAX_DIMENSIONS], bool data_needed,
-   bool subref, bool update_spacing_in_type)
+   bool subref, bool update_spacing_in_type,
+   tree elem_len)
 {
   int ndim = info->ref ? info->ref->u.ar.dimen : rank;
 
   /* Set the span field.  */
   tree tmp = NULL_TREE;
-  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src)))
+  if (subref)
+{
+  gcc_assert (elem_len != NULL_TREE);
+  tmp = elem_len;
+}
+  else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src)))
 tmp = gfc_conv_descriptor_span_get (src);
   else
 tmp = gfc_get_array_span (src, src_expr);
@@ -3101,6 +3107,9 @@ gfc_set_descriptor (stmtblock_t *block, tree dest, tree 
src, gfc_expr *src_expr,
 dtype = get_descriptor_dtype (src, &rank);
   gfc_conv_descriptor_dtype_set (block, dest, dtype);
 
+  if (subref)
+gfc_conv_descriptor_elem_len_set (block, dest, elem_len);
+
   /* The 1st element in the section.  */
   tree base = gfc_index_zero_node;
 
diff --git a/gcc/fortran/trans-descriptor.h b/gcc/fortran/trans-descriptor.h
index 37dd4ea68243..7285157466b9 100644
--- a/gcc/fortran/trans-descriptor.h
+++ b/gcc/fortran/trans-descriptor.h
@@ -91,7 +91,7 @@ void gfc_set_temporary_descriptor (stmtblock_t *, tree, tree, 
tree, tree,
 
 void gfc_set_descriptor (stmtblock_t *, tree, tree, gfc_expr *, int, int,
 gfc_ss *, gfc_array_info *, tree [GFC_MAX_DIMENSIONS],
-tree [GFC_MAX_DIMENSIONS], bool, bool, bool);
+tree [GFC_MAX_DIMENSIONS], bool, bool, bool, tree);
 
 tree gfc_descr_init_count (tree, int, int, gfc_expr **, gfc_expr **,
   stmtblock_t *, stmtblock_t *, tree *, tree,


[gcc(refs/users/mikael/heads/refactor_descriptor_v05)] Correction régression pointer_array_3

2025-06-04 Thread Mikael Morin via Gcc-cvs
https://gcc.gnu.org/g:a87a08ac1b12efd6dc084dc33d7f0b444be80dbe

commit a87a08ac1b12efd6dc084dc33d7f0b444be80dbe
Author: Mikael Morin 
Date:   Wed Jun 4 17:40:48 2025 +0200

Correction régression pointer_array_3

Diff:
---
 gcc/fortran/trans-array.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 43b5ec7339d2..5b18df0e9679 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -7875,7 +7875,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
}
  else if (expr->ts.type == BT_CHARACTER)
{
- tree slen = ss->info->string_length;
+ tree slen = se->string_length;
  slen = fold_convert_loc (input_location, gfc_array_index_type,
   slen);
  tree kind = build_int_cst (gfc_array_index_type,


[gcc r16-1112] match.pd: Fold (x + y) >> 1 into IFN_AVG_FLOOR (x, y) for vectors

2025-06-04 Thread Tamar Christina via Gcc-cvs
https://gcc.gnu.org/g:7bb1933c1fcca8cb99132ff5d08b3f3efca4ff07

commit r16-1112-g7bb1933c1fcca8cb99132ff5d08b3f3efca4ff07
Author: Pengfei Li 
Date:   Wed Jun 4 16:59:44 2025 +0100

match.pd: Fold (x + y) >> 1 into IFN_AVG_FLOOR (x, y) for vectors

This patch folds vector expressions of the form (x + y) >> 1 into
IFN_AVG_FLOOR (x, y), reducing instruction count on platforms that
support averaging operations. For example, it can help improve the
codegen on AArch64 from:
add v0.4s, v0.4s, v31.4s
ushrv0.4s, v0.4s, 1
to:
uhadd   v0.4s, v0.4s, v31.4s

As this folding is only valid when the most significant bit of each
element in both x and y is known to be zero, this patch checks leading
zero bits of elements in x and y, and extends get_nonzero_bits_1() to
handle uniform vectors. When the input is a uniform vector, the function
now returns the nonzero bits of its element.

Additionally, this patch adds more checks to reject vector types in bit
constant propagation (tree-bit-ccp), since tree-bit-ccp was designed for
scalar values only, and the new vector logic in get_non_zero_bits_1()
could lead to incorrect propagation results.

gcc/ChangeLog:

* match.pd: Add folding rule for vector average.
* tree-ssa-ccp.cc (get_default_value): Reject vector types.
(evaluate_stmt): Reject vector types.
* tree-ssanames.cc (get_nonzero_bits_1): Extend to handle
uniform vectors.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/acle/uhadd_1.c: New test.

Diff:
---
 gcc/match.pd| 12 +
 gcc/testsuite/gcc.target/aarch64/acle/uhadd_1.c | 34 +
 gcc/tree-ssa-ccp.cc |  8 +++---
 gcc/tree-ssanames.cc|  8 ++
 4 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index bde9bd649a70..656572423aa7 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2177,6 +2177,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 (view_convert (rshift (view_convert:ntype @0) @1))
 (convert (rshift (convert:ntype @0) @1))
 
+#if GIMPLE
+ /* Fold ((x + y) >> 1 into IFN_AVG_FLOOR (x, y) if x and y are vectors in
+which each element is known to have at least one leading zero bit.  */
+(simplify
+ (rshift (plus:cs @0 @1) integer_onep)
+ (if (VECTOR_TYPE_P (type)
+  && direct_internal_fn_supported_p (IFN_AVG_FLOOR, type, 
OPTIMIZE_FOR_BOTH)
+  && wi::clz (get_nonzero_bits (@0)) > 0
+  && wi::clz (get_nonzero_bits (@1)) > 0)
+  (IFN_AVG_FLOOR @0 @1)))
+#endif
+
 /* Try to fold (type) X op CST -> (type) (X op ((type-x) CST))
when profitable.
For bitwise binary operations apply operand conversions to the
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/uhadd_1.c 
b/gcc/testsuite/gcc.target/aarch64/acle/uhadd_1.c
new file mode 100644
index ..f1748a199ade
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/uhadd_1.c
@@ -0,0 +1,34 @@
+/* Test if SIMD fused unsigned halving adds are generated */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include 
+
+#define FUSED_SIMD_UHADD(vectype, q, ts, mask) \
+  vectype simd_uhadd ## q ## _ ## ts ## _1 (vectype a) \
+  { \
+vectype v1 = vand ## q ## _ ## ts (a, vdup ## q ## _n_ ## ts (mask)); \
+vectype v2 = vdup ## q ## _n_ ## ts (mask); \
+return vshr ## q ## _n_ ## ts (vadd ## q ## _ ## ts (v1, v2), 1); \
+  } \
+  \
+  vectype simd_uhadd ## q ## _ ## ts ## _2 (vectype a, vectype b) \
+  { \
+vectype v1 = vand ## q ## _ ## ts (a, vdup ## q ## _n_ ## ts (mask)); \
+vectype v2 = vand ## q ## _ ## ts (b, vdup ## q ## _n_ ## ts (mask)); \
+return vshr ## q ## _n_ ## ts (vadd ## q ## _ ## ts (v1, v2), 1); \
+  }
+
+FUSED_SIMD_UHADD (uint8x8_t, , u8, 0x7f)
+FUSED_SIMD_UHADD (uint8x16_t, q, u8, 0x7f)
+FUSED_SIMD_UHADD (uint16x4_t, , u16, 0x7fff)
+FUSED_SIMD_UHADD (uint16x8_t, q, u16, 0x7fff)
+FUSED_SIMD_UHADD (uint32x2_t, , u32, 0x7fff)
+FUSED_SIMD_UHADD (uint32x4_t, q, u32, 0x7fff)
+
+/* { dg-final { scan-assembler-times {\tuhadd\tv[0-9]+\.8b,} 2 } } */
+/* { dg-final { scan-assembler-times {\tuhadd\tv[0-9]+\.16b,} 2 } } */
+/* { dg-final { scan-assembler-times {\tuhadd\tv[0-9]+\.4h,} 2 } } */
+/* { dg-final { scan-assembler-times {\tuhadd\tv[0-9]+\.8h,} 2 } } */
+/* { dg-final { scan-assembler-times {\tuhadd\tv[0-9]+\.2s,} 2 } } */
+/* { dg-final { scan-assembler-times {\tuhadd\tv[0-9]+\.4s,} 2 } } */
diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc
index 8d2cbb384c46..3e0c75cf2be8 100644
--- a/gcc/tree-ssa-ccp.cc
+++ b/gcc/tree-ssa-ccp.cc
@@ -298,7 +298,7 @@ get_default_value (tree var)
{
  val.lattice_val = VARYING;
  val.mask = -1;
- if (flag_tree_bit_ccp)
+ if (flag_tree_bit_ccp && !VECTOR_TYPE_P (TREE_TYPE (var)))

[gcc r16-1113] gimple-fold: Implement simple copy propagation for aggregates [PR14295]

2025-06-04 Thread Andrew Pinski via Gcc-cvs
https://gcc.gnu.org/g:069caa5cea91fab3f1579ee1fdf50b923b75a6de

commit r16-1113-g069caa5cea91fab3f1579ee1fdf50b923b75a6de
Author: Andrew Pinski 
Date:   Thu Feb 20 22:05:38 2025 -0800

gimple-fold: Implement simple copy propagation for aggregates [PR14295]

This implements a simple copy propagation for aggregates in the similar
fashion as we already do for copy prop of zeroing.

Right now this only looks at the previous vdef statement but this allows us
to catch a lot of cases that show up in C++ code.

This used to deleted aggregate copies that are to the same location 
(PR57361)
But that was found to delete statements that are needed for aliasing 
markers reason.
So we need to keep them around until that is solved. Note DSE will delete 
the statements
anyways so there is no testcase added since we expose the latent bug in the 
same way.
See https://gcc.gnu.org/pipermail/gcc-patches/2025-May/685003.html for the 
testcase and
explaintation there.

Also adds a variant of pr22237.c which was found while working on this 
patch.

Changes since v1:
* v2: change check for vuse to use default definition.
  Remove dest/src arguments for optimize_agr_copyprop
  Changed dump messages slightly.
  Added stats
  Don't delete `a = a` until aliasing markers are added.

PR tree-optimization/14295
PR tree-optimization/108358
PR tree-optimization/114169

gcc/ChangeLog:

* tree-ssa-forwprop.cc (optimize_agr_copyprop): New function.
(pass_forwprop::execute): Call optimize_agr_copyprop for load/store 
statements.

gcc/testsuite/ChangeLog:

* gcc.dg/tree-ssa/20031106-6.c: Un-xfail. Add scan for forwprop1.
* g++.dg/opt/pr66119.C: Disable forwprop since that does
the copy prop now.
* gcc.dg/tree-ssa/pr108358-a.c: New test.
* gcc.dg/tree-ssa/pr114169-1.c: New test.
* gcc.c-torture/execute/builtins/pr22237-1-lib.c: New test.
* gcc.c-torture/execute/builtins/pr22237-1.c: New test.
* gcc.dg/tree-ssa/pr57361.c: Disable forwprop1.
* gcc.dg/tree-ssa/pr57361-1.c: New test.

Signed-off-by: Andrew Pinski 

Diff:
---
 gcc/testsuite/g++.dg/opt/pr66119.C |  2 +-
 .../gcc.c-torture/execute/builtins/pr22237-1-lib.c | 27 +++
 .../gcc.c-torture/execute/builtins/pr22237-1.c | 57 ++
 gcc/testsuite/gcc.dg/tree-ssa/20031106-6.c |  8 +-
 gcc/testsuite/gcc.dg/tree-ssa/pr108358-a.c | 33 
 gcc/testsuite/gcc.dg/tree-ssa/pr114169-1.c | 39 ++
 gcc/testsuite/gcc.dg/tree-ssa/pr57361-1.c  | 10 +++
 gcc/testsuite/gcc.dg/tree-ssa/pr57361.c|  2 +-
 gcc/tree-ssa-forwprop.cc   | 87 ++
 9 files changed, 261 insertions(+), 4 deletions(-)

diff --git a/gcc/testsuite/g++.dg/opt/pr66119.C 
b/gcc/testsuite/g++.dg/opt/pr66119.C
index d1b1845a2586..52362e44434b 100644
--- a/gcc/testsuite/g++.dg/opt/pr66119.C
+++ b/gcc/testsuite/g++.dg/opt/pr66119.C
@@ -3,7 +3,7 @@
the value of MOVE_RATIO now is.  */
 
 /* { dg-do compile  { target { { i?86-*-* x86_64-*-* } && c++11 } }  }  */
-/* { dg-options "-O3 -mavx -fdump-tree-sra -march=slm -mtune=slm 
-fno-early-inlining" } */
+/* { dg-options "-O3 -mavx -fdump-tree-sra -fno-tree-forwprop -march=slm 
-mtune=slm -fno-early-inlining" } */
 // { dg-skip-if "requires hosted libstdc++ for cstdlib malloc" { ! hostedlib } 
}
 
 #include 
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-1-lib.c 
b/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-1-lib.c
new file mode 100644
index ..440323574056
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-1-lib.c
@@ -0,0 +1,27 @@
+extern void abort (void);
+
+void *
+memcpy (void *dst, const void *src, __SIZE_TYPE__ n)
+{
+  const char *srcp;
+  char *dstp;
+
+  srcp = src;
+  dstp = dst;
+
+  if (dst < src)
+{
+  if (dst + n > src)
+   abort ();
+}
+  else
+{
+  if (src + n > dst)
+   abort ();
+}
+
+  while (n-- != 0)
+*dstp++ = *srcp++;
+
+  return dst;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-1.c 
b/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-1.c
new file mode 100644
index ..0a12b0fc9a15
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-1.c
@@ -0,0 +1,57 @@
+extern void abort (void);
+extern void exit (int);
+struct s { unsigned char a[256]; };
+union u { struct { struct s b; int c; } d; struct { int c; struct s b; } e; };
+static union u v;
+static union u v0;
+static struct s *p = &v.d.b;
+static struct s *q = &v.e.b;
+
+struct outers
+{
+  struct s inner;
+};
+
+static inline struct s rp (void) { return *p; }
+static inline struct s rq (void) { return *q; }
+static void pq (void)
+{
+  s

[gcc r15-9763] Fortran: ICE due to missing locus with data statement for coarray [PR99838]

2025-06-04 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:c77dd2d7d40d4fb0d141bf61544d8a57d501f981

commit r15-9763-gc77dd2d7d40d4fb0d141bf61544d8a57d501f981
Author: Harald Anlauf 
Date:   Tue Jun 3 20:48:31 2025 +0200

Fortran: ICE due to missing locus with data statement for coarray [PR99838]

PR fortran/99838

gcc/fortran/ChangeLog:

* data.cc (gfc_assign_data_value): For a new initializer use the
location from the constructor as fallback.

gcc/testsuite/ChangeLog:

* gfortran.dg/coarray_data_2.f90: New test.

(cherry picked from commit 0768ec0d32f570b1db13ca41b0a1506275c44053)

Diff:
---
 gcc/fortran/data.cc  |  8 +++-
 gcc/testsuite/gfortran.dg/coarray_data_2.f90 | 14 ++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/data.cc b/gcc/fortran/data.cc
index 5c83f6948b8a..a438c268cdae 100644
--- a/gcc/fortran/data.cc
+++ b/gcc/fortran/data.cc
@@ -593,7 +593,13 @@ gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, 
mpz_t index,
{
  /* Point the container at the new expression.  */
  if (last_con == NULL)
-   symbol->value = expr;
+   {
+ symbol->value = expr;
+ /* For a new initializer use the location from the
+constructor as fallback.  */
+ if (!GFC_LOCUS_IS_SET(expr->where) && con != NULL)
+   symbol->value->where = con->where;
+   }
  else
last_con->expr = expr;
}
diff --git a/gcc/testsuite/gfortran.dg/coarray_data_2.f90 
b/gcc/testsuite/gfortran.dg/coarray_data_2.f90
new file mode 100644
index ..bda57f3df890
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_data_2.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+! { dg-additional-options "-fcoarray=lib -Warray-temporaries" }
+!
+! PR fortran/99838 - ICE due to missing locus with data statement for coarray
+!
+! Contributed by Gerhard Steinmetz
+
+program p
+  type t
+ integer :: a
+  end type
+  type(t) :: x(3)[*]
+  data x%a /1, 2, 3/ ! { dg-warning "Creating array temporary" }
+end


[gcc r16-1114] Avoid SIGSEGV in nvptx 'mkoffload' for voluminous PTX code

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:01044e0ee27093a3990996578b15f6ab69ed3395

commit r16-1114-g01044e0ee27093a3990996578b15f6ab69ed3395
Author: Thomas Schwinge 
Date:   Mon May 26 13:31:54 2025 +0200

Avoid SIGSEGV in nvptx 'mkoffload' for voluminous PTX code

In commit 50be486dff4ea2676ed022e9524ef190b92ae2b1
"nvptx: libgomp+mkoffload.cc: Prepare for reverse offload fn lookup", some
additional tracking of the PTX code was added, and this assumes that
potentially every single character of PTX code needs to be tracked as a new
chunk of PTX code.  That's problematic if we're dealing with voluminous PTX
code (for example, non-trivial C++ code), and the 'file_idx' 'alloca'tion 
then
causes stack overflow.  For example:

FAIL: libgomp.c++/target-std__valarray-1.C (test for excess errors)
UNRESOLVED: libgomp.c++/target-std__valarray-1.C compilation failed to 
produce executable

lto-wrapper: fatal error: 
[...]/build-gcc/gcc//accel/nvptx-none/mkoffload terminated with signal 11 
[Segmentation fault], core dumped

gcc/
* config/nvptx/mkoffload.cc (process): Use an 'auto_vec' for
'file_idx'.

Diff:
---
 gcc/config/nvptx/mkoffload.cc | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/gcc/config/nvptx/mkoffload.cc b/gcc/config/nvptx/mkoffload.cc
index e7ec0ef4f6ac..bb3f0fcee6bd 100644
--- a/gcc/config/nvptx/mkoffload.cc
+++ b/gcc/config/nvptx/mkoffload.cc
@@ -260,8 +260,10 @@ process (FILE *in, FILE *out, uint32_t omp_requires)
   unsigned ix;
   const char *sm_ver = NULL, *version = NULL;
   const char *sm_ver2 = NULL, *version2 = NULL;
-  size_t file_cnt = 0;
-  size_t *file_idx = XALLOCAVEC (size_t, len);
+  /* To reduce the number of reallocations for 'file_idx', guess 'file_cnt'
+ (very roughly...), based on 'len'.  */
+  const size_t file_cnt_guessed = 13 + len / 27720;
+  auto_vec file_idx (file_cnt_guessed);
 
   fprintf (out, "#include \n\n");
 
@@ -269,9 +271,10 @@ process (FILE *in, FILE *out, uint32_t omp_requires)
  terminated by a NUL.  */
   for (size_t i = 0; i != len;)
 {
+  file_idx.safe_push (i);
+
   char c;
   bool output_fn_ptr = false;
-  file_idx[file_cnt++] = i;
 
   fprintf (out, "static const char ptx_code_%u[] =\n\t\"", obj_count++);
   while ((c = input[i++]))
@@ -349,6 +352,9 @@ process (FILE *in, FILE *out, uint32_t omp_requires)
}
 }
 
+  const size_t file_cnt = file_idx.length ();
+  gcc_checking_assert (file_cnt == obj_count);
+
   /* Create function-pointer array, required for reverse
  offload function-pointer lookup.  */


[gcc/devel/omp/gcc-15] Avoid SIGSEGV in nvptx 'mkoffload' for voluminous PTX code

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:d283eba8b886921424ef86ce1804ecfcbc49b8fc

commit d283eba8b886921424ef86ce1804ecfcbc49b8fc
Author: Thomas Schwinge 
Date:   Mon May 26 13:31:54 2025 +0200

Avoid SIGSEGV in nvptx 'mkoffload' for voluminous PTX code

In commit 50be486dff4ea2676ed022e9524ef190b92ae2b1
"nvptx: libgomp+mkoffload.cc: Prepare for reverse offload fn lookup", some
additional tracking of the PTX code was added, and this assumes that
potentially every single character of PTX code needs to be tracked as a new
chunk of PTX code.  That's problematic if we're dealing with voluminous PTX
code (for example, non-trivial C++ code), and the 'file_idx' 'alloca'tion 
then
causes stack overflow.  For example:

FAIL: libgomp.c++/target-std__valarray-1.C (test for excess errors)
UNRESOLVED: libgomp.c++/target-std__valarray-1.C compilation failed to 
produce executable

lto-wrapper: fatal error: 
[...]/build-gcc/gcc//accel/nvptx-none/mkoffload terminated with signal 11 
[Segmentation fault], core dumped

gcc/
* config/nvptx/mkoffload.cc (process): Use an 'auto_vec' for
'file_idx'.

(cherry picked from commit 01044e0ee27093a3990996578b15f6ab69ed3395)

Diff:
---
 gcc/config/nvptx/mkoffload.cc | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/gcc/config/nvptx/mkoffload.cc b/gcc/config/nvptx/mkoffload.cc
index 205bc2df14b1..bee18e75bb3c 100644
--- a/gcc/config/nvptx/mkoffload.cc
+++ b/gcc/config/nvptx/mkoffload.cc
@@ -260,8 +260,10 @@ process (FILE *in, FILE *out, uint32_t omp_requires)
   unsigned ix;
   const char *sm_ver = NULL, *version = NULL;
   const char *sm_ver2 = NULL, *version2 = NULL;
-  size_t file_cnt = 0;
-  size_t *file_idx = XALLOCAVEC (size_t, len);
+  /* To reduce the number of reallocations for 'file_idx', guess 'file_cnt'
+ (very roughly...), based on 'len'.  */
+  const size_t file_cnt_guessed = 13 + len / 27720;
+  auto_vec file_idx (file_cnt_guessed);
 
   fprintf (out, "#include \n\n");
 
@@ -269,9 +271,10 @@ process (FILE *in, FILE *out, uint32_t omp_requires)
  terminated by a NUL.  */
   for (size_t i = 0; i != len;)
 {
+  file_idx.safe_push (i);
+
   char c;
   bool output_fn_ptr = false;
-  file_idx[file_cnt++] = i;
 
   fprintf (out, "static const char ptx_code_%u[] =\n\t\"", obj_count++);
   while ((c = input[i++]))
@@ -349,6 +352,9 @@ process (FILE *in, FILE *out, uint32_t omp_requires)
}
 }
 
+  const size_t file_cnt = file_idx.length ();
+  gcc_checking_assert (file_cnt == obj_count);
+
   /* Create function-pointer array, required for reverse
  offload function-pointer lookup.  */


[gcc/devel/omp/gcc-15] ChangeLog.omp bump

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:de723918517e92278be34960fb9ef9bc3f65fda1

commit de723918517e92278be34960fb9ef9bc3f65fda1
Author: Thomas Schwinge 
Date:   Wed Jun 4 19:49:24 2025 +0200

ChangeLog.omp bump

Diff:
---
 gcc/ChangeLog.omp | 8 
 gcc/DATESTAMP.omp | 2 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/gcc/ChangeLog.omp b/gcc/ChangeLog.omp
index b832b2a2d325..34e615771b1f 100644
--- a/gcc/ChangeLog.omp
+++ b/gcc/ChangeLog.omp
@@ -1,3 +1,11 @@
+2025-06-04  Thomas Schwinge  
+
+   Backported from master:
+   2025-06-04  Thomas Schwinge  
+
+   * config/nvptx/mkoffload.cc (process): Use an 'auto_vec' for
+   'file_idx'.
+
 2025-05-30  Thomas Schwinge  
 
Backported from master:
diff --git a/gcc/DATESTAMP.omp b/gcc/DATESTAMP.omp
index ac2743335765..932c2dd9fa20 100644
--- a/gcc/DATESTAMP.omp
+++ b/gcc/DATESTAMP.omp
@@ -1 +1 @@
-20250530
+20250604


[gcc r16-1115] c++: constexpr prvalues vs genericize [PR120502]

2025-06-04 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:0292e066d5e87e84ff00510724987501b3931518

commit r16-1115-g0292e066d5e87e84ff00510724987501b3931518
Author: Jason Merrill 
Date:   Wed Jun 4 13:31:02 2025 -0400

c++: constexpr prvalues vs genericize [PR120502]

Here constexpr evaluation was getting confused by the result of
split_nonconstant_init, which leaves an INIT_EXPR from an empty CONSTRUCTOR
to be followed by member initialization.  As a result
CONSTRUCTOR_NO_CLEARING was set for the time_zone, and
cxx_eval_store_expression didn't set it again for the initial clobber in the
basic_string constructor, so when cxx_fold_indirect_ref wants to check
whether the anonymous union active member had type non_trivial_if, we see
that we don't currently have a value for the anonymous union, try to add
one, and fail.

So let's do constexpr evaluation before split_nonconstant_init.

PR c++/120502

gcc/cp/ChangeLog:

* cp-gimplify.cc (cp_fold_r) [TARGET_EXPR]: Do constexpr evaluation
before genericize.
* constexpr.cc (cxx_eval_store_expression): Add comment.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/constexpr-prvalue2.C: New test.

Diff:
---
 gcc/cp/constexpr.cc |  3 ++-
 gcc/cp/cp-gimplify.cc   | 21 
 gcc/testsuite/g++.dg/cpp2a/constexpr-prvalue2.C | 26 +
 3 files changed, 41 insertions(+), 9 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index b9fdc94b961a..c0e37b2fd35c 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -6413,7 +6413,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree 
t,
 
   if (TREE_CLOBBER_P (init)
   && CLOBBER_KIND (init) < CLOBBER_OBJECT_END)
-/* Only handle clobbers ending the lifetime of objects.  */
+/* Only handle clobbers ending the lifetime of objects.
+   ??? We should probably set CONSTRUCTOR_NO_CLEARING.  */
 return void_node;
 
   /* First we figure out where we're storing to.  */
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 16def885127e..0fcfa16d2c59 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -1473,6 +1473,19 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_)
   break;
 
 case TARGET_EXPR:
+  if (!flag_no_inline)
+   if (tree &init = TARGET_EXPR_INITIAL (stmt))
+ {
+   tree folded = maybe_constant_init (init, TARGET_EXPR_SLOT (stmt),
+  (data->flags & ff_mce_false
+   ? mce_false : mce_unknown));
+   if (folded != init && TREE_CONSTANT (folded))
+ init = folded;
+ }
+
+  /* This needs to happen between the constexpr evaluation (which wants
+pre-generic trees) and fold (which wants the cp_genericize_init
+transformations).  */
   if (data->flags & ff_genericize)
cp_genericize_target_expr (stmt_p);
 
@@ -1481,14 +1494,6 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_)
  cp_walk_tree (&init, cp_fold_r, data, NULL);
  cp_walk_tree (&TARGET_EXPR_CLEANUP (stmt), cp_fold_r, data, NULL);
  *walk_subtrees = 0;
- if (!flag_no_inline)
-   {
- tree folded = maybe_constant_init (init, TARGET_EXPR_SLOT (stmt),
-(data->flags & ff_mce_false
- ? mce_false : mce_unknown));
- if (folded != init && TREE_CONSTANT (folded))
-   init = folded;
-   }
  /* Folding might replace e.g. a COND_EXPR with a TARGET_EXPR; in
 that case, strip it in favor of this one.  */
  if (TREE_CODE (init) == TARGET_EXPR)
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-prvalue2.C 
b/gcc/testsuite/g++.dg/cpp2a/constexpr-prvalue2.C
new file mode 100644
index ..c2dc7cd49456
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-prvalue2.C
@@ -0,0 +1,26 @@
+// PR c++/120502
+// { dg-do compile { target c++20 } }
+// { dg-additional-options -O }
+
+struct non_trivial_if {
+  constexpr non_trivial_if() {}
+};
+struct allocator : non_trivial_if {};
+struct padding {};
+struct __short {
+  [[no_unique_address]] padding p;
+};
+struct basic_string {
+  union {
+__short s;
+int l;
+  };
+  [[no_unique_address]] allocator a;
+  constexpr basic_string() {}
+  ~basic_string() {}
+};
+struct time_zone {
+  basic_string __abbrev;
+  long __offset;
+};
+time_zone convert_to_time_zone() { return {}; }


[gcc r16-1116] libstdc++: Implement P0849R8 auto(x) library changes

2025-06-04 Thread Patrick Palka via Libstdc++-cvs
https://gcc.gnu.org/g:e73a6d982789746d4bce9d0e595203f2a8dbbaa7

commit r16-1116-ge73a6d982789746d4bce9d0e595203f2a8dbbaa7
Author: Patrick Palka 
Date:   Wed Jun 4 14:55:40 2025 -0400

libstdc++: Implement P0849R8 auto(x) library changes

This implements the library changes in P0849R8 "auto(x): decay-copy
in the language" which consist of replacing most uses of the
exposition-only function decay-copy with auto(x) throughout the library
wording.  We implement this as a DR against C++20 since there should be
no behavior change in practice (especially in light of LWG 3724 which
makes decay-copy SFINAE-friendly).

The main difference between decay-copy and auto(x) is that decay-copy
materializes its argument unlike auto(x), and so the latter is a no-op
when its argument is a prvalue.  Effectively the former could introduce
an unnecessary move constructor call in some contexts.  In C++20 and
earlier we could emulate auto(x) with decay_t(x).

After this paper the only remaining uses of decay-copy in the standard
are in the specification of some range adaptors.  In our implementation
of those range adaptors I believe decay-copy is already implied which is
why we don't use __decay_copy explicitly there.  So since it's apparently
no longer needed this patch goes ahead and removes __decay_copy.

libstdc++-v3/ChangeLog:

* include/bits/c++config (_GLIBCXX_AUTO_CAST): Define.
* include/bits/iterator_concepts.h (_Decay_copy, __decay_copy):
Remove.
(__member_begin, __adl_begin): Use _GLIBCXX_AUTO_CAST instead of
__decay_copy as per P0849R8.
* include/bits/ranges_base.h (_Begin): Likewise.
(__member_end, __adl_end, _End): Likewise.
(__member_rbegin, __adl_rbegin, _RBegin): Likewise.
(__member_rend, __adl_rend, _Rend): Likewise.
(__member_size, __adl_size, _Size): Likewise.
(_Data): Likewise.

Reviewed-by: Jonathan Wakely 

Diff:
---
 libstdc++-v3/include/bits/c++config   |  6 
 libstdc++-v3/include/bits/iterator_concepts.h | 13 ++---
 libstdc++-v3/include/bits/ranges_base.h   | 40 +--
 3 files changed, 28 insertions(+), 31 deletions(-)

diff --git a/libstdc++-v3/include/bits/c++config 
b/libstdc++-v3/include/bits/c++config
index 676f5eecbbb6..eec3a4a499dd 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -273,6 +273,12 @@
 #define _GLIBCXX_NOEXCEPT_QUAL
 #endif
 
+#if __cpp_auto_cast
+# define _GLIBCXX_AUTO_CAST(X) auto(X)
+#else
+# define _GLIBCXX_AUTO_CAST(X) ::std::__decay_t(X)
+#endif
+
 // Macro for extern template, ie controlling template linkage via use
 // of extern keyword on template declaration. As documented in the g++
 // manual, it inhibits all implicit instantiations and is used
diff --git a/libstdc++-v3/include/bits/iterator_concepts.h 
b/libstdc++-v3/include/bits/iterator_concepts.h
index 3b73ff9b6b59..d31e4f145107 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -1022,19 +1022,10 @@ namespace ranges
   {
 using std::__detail::__class_or_enum;
 
-struct _Decay_copy final
-{
-  template
-   constexpr decay_t<_Tp>
-   operator()(_Tp&& __t) const
-   noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>)
-   { return std::forward<_Tp>(__t); }
-} inline constexpr __decay_copy{};
-
 template
   concept __member_begin = requires(_Tp& __t)
{
- { __decay_copy(__t.begin()) } -> input_or_output_iterator;
+ { _GLIBCXX_AUTO_CAST(__t.begin()) } -> input_or_output_iterator;
};
 
 // Poison pill so that unqualified lookup doesn't find std::begin.
@@ -1044,7 +1035,7 @@ namespace ranges
   concept __adl_begin = __class_or_enum>
&& requires(_Tp& __t)
{
- { __decay_copy(begin(__t)) } -> input_or_output_iterator;
+ { _GLIBCXX_AUTO_CAST(begin(__t)) } -> input_or_output_iterator;
};
 
 // Simplified version of std::ranges::begin that only supports lvalues,
diff --git a/libstdc++-v3/include/bits/ranges_base.h 
b/libstdc++-v3/include/bits/ranges_base.h
index dde164988569..c09f7292067d 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -119,9 +119,9 @@ namespace ranges
  if constexpr (is_array_v>)
return true;
  else if constexpr (__member_begin<_Tp>)
-   return noexcept(__decay_copy(std::declval<_Tp&>().begin()));
+   return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().begin()));
  else
-   return noexcept(__decay_copy(begin(std::declval<_Tp&>(;
+   return noexcept(_GLIBCXX_AUTO_CAST(begin(std::declval<_Tp&>(;
}
 
 public:
@@ -146,7 +146,7 @@ namespace ranges
 template
   concep

[gcc r16-1117] libstdc++: sstream from string_view (P2495R3) [PR119741]

2025-06-04 Thread Nathan Myers via Libstdc++-cvs
https://gcc.gnu.org/g:8537e4851072ea1f1982c4c6ab0d24c9383e9edd

commit r16-1117-g8537e4851072ea1f1982c4c6ab0d24c9383e9edd
Author: Nathan Myers 
Date:   Wed Jun 4 14:52:29 2025 -0400

libstdc++: sstream from string_view (P2495R3) [PR119741]

Add constructors to stringbuf, stringstream, istringstream, and 
ostringstream,
and a matching overload of str(sv) in each, that take anything convertible 
to
a string_view in places where the existing ctors and function take a string.
Note this change omits the constraint applied to the istringstream 
constructor
from string cited as a "drive-by" in P2495R3, as we have determined it is
redundant.

libstdc++-v3/ChangeLog:

PR libstdc++/119741
* include/std/sstream: full implementation, really just
decls, requires clause and plumbing.
* include/bits/version.def, include/bits/version.h:
new preprocessor symbol
__cpp_lib_sstream_from_string_view.
* testsuite/27_io/basic_stringbuf/cons/char/string_view.cc:
New tests.
* testsuite/27_io/basic_istringstream/cons/char/string_view.cc:
New tests.
* testsuite/27_io/basic_ostringstream/cons/char/string_view.cc:
New tests.
* testsuite/27_io/basic_stringstream/cons/char/string_view.cc:
New tests.
* testsuite/27_io/basic_stringbuf/cons/wchar_t/string_view.cc:
New tests.
* testsuite/27_io/basic_istringstream/cons/wchar_t/string_view.cc:
New tests.
* testsuite/27_io/basic_ostringstream/cons/wchar_t/string_view.cc:
New tests.
* testsuite/27_io/basic_stringstream/cons/wchar_t/string_view.cc:
New tests.

Diff:
---
 libstdc++-v3/include/bits/version.def  |  11 +-
 libstdc++-v3/include/bits/version.h|  10 +
 libstdc++-v3/include/std/sstream   | 198 ++--
 .../basic_istringstream/cons/char/string_view.cc   | 195 
 .../cons/wchar_t/string_view.cc|   3 +
 .../basic_ostringstream/cons/char/string_view.cc   | 194 +++
 .../cons/wchar_t/string_view.cc|   3 +
 .../27_io/basic_stringbuf/cons/char/string_view.cc | 205 +
 .../basic_stringbuf/cons/wchar_t/string_view.cc|   3 +
 .../basic_stringstream/cons/char/string_view.cc| 204 
 .../basic_stringstream/cons/wchar_t/string_view.cc |   3 +
 11 files changed, 1010 insertions(+), 19 deletions(-)

diff --git a/libstdc++-v3/include/bits/version.def 
b/libstdc++-v3/include/bits/version.def
index 9ab22cc519f9..7cf62e989aa7 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -649,7 +649,7 @@ ftms = {
   };
   values = {
 v = 1;
-/* For when there's no gthread.  */
+// For when there is no gthread.
 cxxmin = 17;
 hosted = yes;
 gthread = no;
@@ -1995,6 +1995,15 @@ ftms = {
   };
 };
 
+ftms = {
+  name = sstream_from_string_view;
+  values = {
+v = 202306;
+cxxmin = 26;
+hosted = yes;
+  };
+};
+
 // Standard test specifications.
 stds[97] = ">= 199711L";
 stds[03] = ">= 199711L";
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index 371a7ba3b1a0..9f4cf9a3425e 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -2233,4 +2233,14 @@
 #endif /* !defined(__cpp_lib_polymorphic) && 
defined(__glibcxx_want_polymorphic) */
 #undef __glibcxx_want_polymorphic
 
+#if !defined(__cpp_lib_sstream_from_string_view)
+# if (__cplusplus >  202302L) && _GLIBCXX_HOSTED
+#  define __glibcxx_sstream_from_string_view 202306L
+#  if defined(__glibcxx_want_all) || 
defined(__glibcxx_want_sstream_from_string_view)
+#   define __cpp_lib_sstream_from_string_view 202306L
+#  endif
+# endif
+#endif /* !defined(__cpp_lib_sstream_from_string_view) && 
defined(__glibcxx_want_sstream_from_string_view) */
+#undef __glibcxx_want_sstream_from_string_view
+
 #undef __glibcxx_want_all
diff --git a/libstdc++-v3/include/std/sstream b/libstdc++-v3/include/std/sstream
index ad0c16a91e86..edef599bd6f8 100644
--- a/libstdc++-v3/include/std/sstream
+++ b/libstdc++-v3/include/std/sstream
@@ -41,8 +41,12 @@
 
 #include 
 #include 
+
 #include  // allocator_traits, __allocator_like
 
+#define __glibcxx_want_sstream_from_string_view
+#include 
+
 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
 # define _GLIBCXX_LVAL_REF_QUAL &
 # define _GLIBCXX_SSTREAM_ALWAYS_INLINE
@@ -52,8 +56,6 @@
 # define _GLIBCXX_SSTREAM_ALWAYS_INLINE [[__gnu__::__always_inline__]]
 #endif
 
-
-
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -159,6 +161,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   { __rhs._M_sync(const_cast(__rhs._M_string.data()), 0, 0); }
 
 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX

[gcc r16-1118] libstdc++: Make system_clock::to_time_t always_inline [PR99832]

2025-06-04 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:d045eb13b0b42870a1f081895df3901112a358f0

commit r16-1118-gd045eb13b0b42870a1f081895df3901112a358f0
Author: Jonathan Wakely 
Date:   Wed May 28 15:19:18 2025 +0100

libstdc++: Make system_clock::to_time_t always_inline [PR99832]

For some 32-bit targets Glibc supports changing the size of time_t to be
64 bits by defining _TIME_BITS=64. That causes an ABI change which
would affect std::chrono::system_clock::to_time_t. Because to_time_t is
not a function template, its mangled name does not depend on the return
type, so it has the same mangled name whether it returns a 32-bit time_t
or a 64-bit time_t. On targets where the size of time_t can be selected
at preprocessing time, that can cause ODR violations, e.g. the linker
selects a definition of to_time_t that returns a 32-bit value but a
caller expects 64-bit and so reads 32 bits of garbage from the stack.

This commit adds always_inline to to_time_t so that all callers inline
the conversion to time_t, and will do so using whatever type time_t
happens to be in that translation unit.

Existing objects compiled before this change will either have inlined
the function anyway (which is likely if compiled with any optimization
enabled) or will contain a COMDAT definition of the inline function and
so still be able to find it at link-time.

The attribute is also added to system_clock::from_time_t, because that's
an equally simple function and it seems reasonable for them to both be
always inlined.

libstdc++-v3/ChangeLog:

PR libstdc++/99832
* include/bits/chrono.h (system_clock::to_time_t): Add
always_inline attribute to be agnostic to the underlying type of
time_t.
(system_clock::from_time_t): Add always_inline for consistency
with to_time_t.
* testsuite/20_util/system_clock/99832.cc: New test.

Diff:
---
 libstdc++-v3/include/bits/chrono.h   |  2 ++
 libstdc++-v3/testsuite/20_util/system_clock/99832.cc | 14 ++
 2 files changed, 16 insertions(+)

diff --git a/libstdc++-v3/include/bits/chrono.h 
b/libstdc++-v3/include/bits/chrono.h
index fad216203d2f..8de8e756c714 100644
--- a/libstdc++-v3/include/bits/chrono.h
+++ b/libstdc++-v3/include/bits/chrono.h
@@ -1244,6 +1244,7 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
   now() noexcept;
 
   // Map to C API
+  [[__gnu__::__always_inline__]]
   static std::time_t
   to_time_t(const time_point& __t) noexcept
   {
@@ -1251,6 +1252,7 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
   (__t.time_since_epoch()).count());
   }
 
+  [[__gnu__::__always_inline__]]
   static time_point
   from_time_t(std::time_t __t) noexcept
   {
diff --git a/libstdc++-v3/testsuite/20_util/system_clock/99832.cc 
b/libstdc++-v3/testsuite/20_util/system_clock/99832.cc
new file mode 100644
index ..693d4d647d9b
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/system_clock/99832.cc
@@ -0,0 +1,14 @@
+// { dg-options "-O0 -g0" }
+// { dg-do compile { target c++20 } }
+// { dg-final { scan-assembler-not "system_clock9to_time_t" } }
+
+// Bug libstdc++/99832
+// std::chrono::system_clock::to_time_t needs ABI tag for 32-bit time_t
+
+#include 
+
+std::time_t
+test_pr99832(std::chrono::system_clock::time_point t)
+{
+  return std::chrono::system_clock::to_time_t(t);
+}


[gcc r16-1119] OpenMP: Fix regressions in metadirective-target-device-2.c [PR120518]

2025-06-04 Thread Sandra Loosemore via Gcc-cvs
https://gcc.gnu.org/g:9788a1e2486b55dd1ab521e34bfaf9f4974d

commit r16-1119-g9788a1e2486b55dd1ab521e34bfaf9f4974d
Author: Sandra Loosemore 
Date:   Wed Jun 4 04:03:03 2025 +

OpenMP: Fix regressions in metadirective-target-device-2.c [PR120518]

My previous patch that added a CLEANUP_POINT_EXPR around the device_num
selector expression in the C++ front end broke the testcase
c-c++-common/gomp/metadirective-target-device-2.c on offload targets.
It confused the code in omp_device_num_check that tries to bypass error
checking and do early resolution when the expression is a call to one
of the OpenMP library functions.  The solution is to make that code smart
enough to look inside a CLEANUP_POINT_EXPR.

gcc/ChangeLog
PR c++/120518
* omp-general.cc (omp_device_num_check): Look inside a
CLEANUP_POINT_EXPR when trying to optimize special cases.

Diff:
---
 gcc/omp-general.cc | 14 ++
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc
index 0b7c3b9d3181..c799b8936f99 100644
--- a/gcc/omp-general.cc
+++ b/gcc/omp-general.cc
@@ -2659,10 +2659,16 @@ omp_selector_is_dynamic (tree ctx)
 static tree
 omp_device_num_check (tree *device_num, bool *is_host)
 {
+  /* C++ may wrap the device_num expr in a CLEANUP_POINT_EXPR; we want
+ to look inside of it for the special cases.  */
+  tree t = *device_num;
+  if (TREE_CODE (t) == CLEANUP_POINT_EXPR)
+t = TREE_OPERAND (t, 0);
+
   /* First check for some constant values we can treat specially.  */
-  if (tree_fits_shwi_p (*device_num))
+  if (tree_fits_shwi_p (t))
 {
-  HOST_WIDE_INT num = tree_to_shwi (*device_num);
+  HOST_WIDE_INT num = tree_to_shwi (t);
   if (num < -1)
return integer_zero_node;
   /* Initial device?  */
@@ -2681,9 +2687,9 @@ omp_device_num_check (tree *device_num, bool *is_host)
 
   /* Also test for direct calls to OpenMP routines that return valid
  device numbers.  */
-  if (TREE_CODE (*device_num) == CALL_EXPR)
+  if (TREE_CODE (t) == CALL_EXPR)
 {
-  tree fndecl = get_callee_fndecl (*device_num);
+  tree fndecl = get_callee_fndecl (t);
   if (fndecl && omp_runtime_api_call (fndecl))
{
  const char *fnname = IDENTIFIER_POINTER (DECL_NAME (fndecl));


[gcc r16-1120] libstdc++: Skip time zone format testing for COW std::string

2025-06-04 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:fc198521cd3e135bc07f6a86a5ffa9c70fc3abca

commit r16-1120-gfc198521cd3e135bc07f6a86a5ffa9c70fc3abca
Author: Jonathan Wakely 
Date:   Wed Jun 4 21:49:54 2025 +0100

libstdc++: Skip time zone format testing for COW std::string

This is needed when testing with -D_GLIBCXX_USE_CXX11_ABI=0 to fix:
FAIL: std/time/format/empty_spec.cc  -std=gnu++20 (test for excess errors)

libstdc++-v3/ChangeLog:

* testsuite/std/time/format/empty_spec.cc: Only test time zones
for cxx11 string ABI.

Diff:
---
 libstdc++-v3/testsuite/std/time/format/empty_spec.cc | 4 
 1 file changed, 4 insertions(+)

diff --git a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc 
b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
index ec57a6f0d209..a3c64f5211ef 100644
--- a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
+++ b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
@@ -647,6 +647,7 @@ test_leap_second()
  WIDEN("2012-06-30 23:59:60") );
 }
 
+#if _GLIBCXX_USE_CXX11_ABI
 template
 auto
 make_zoned(const sys_time& st, const time_zone* tz)
@@ -679,6 +680,7 @@ test_zoned_time()
   verify( make_zoned(st, tz),
  WIDEN("2022-01-08 02:00:00 EET") );
 }
+#endif
 
 template
 auto
@@ -725,7 +727,9 @@ test_time_points()
   test_time_point(true);
   test_time_point(true);
   test_leap_second();
+#if _GLIBCXX_USE_CXX11_ABI
   test_zoned_time();
+#endif
   test_local_time_format();
 
   test_no_empty_spec>();


[gcc r16-1121] [AutoFDO] Profile merging for clone test

2025-06-04 Thread Kugan Vivekanandarajah via Gcc-cvs
https://gcc.gnu.org/g:74e691a8e31a81019e0fda0f919d721d3092ad54

commit r16-1121-g74e691a8e31a81019e0fda0f919d721d3092ad54
Author: Kugan Vivekanandarajah 
Date:   Thu Jun 5 07:15:34 2025 +1000

[AutoFDO] Profile merging for clone test

This patch introduces a new testcase to verify the merging of profiles
is performed for cloned functions.

Since this is invoked very early, before the pass manager, we need to
set up the dumping explicitly. This is similar to the handling in
finish_optimization_passes.

gcc/ChangeLog:

* auto-profile.cc (autofdo_source_profile::read): Dump message
while merging profile.
* pass_manager.h (get_pass_auto_profile): New.

gcc/testsuite/ChangeLog:

* gcc.dg/tree-prof/clone-merge-1.c: New test.

Signed-off-by: Kugan Vivekanandarajah 

Diff:
---
 gcc/auto-profile.cc| 20 +++-
 gcc/pass_manager.h |  1 +
 gcc/testsuite/gcc.dg/tree-prof/clone-merge-1.c | 32 ++
 3 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/gcc/auto-profile.cc b/gcc/auto-profile.cc
index 91cc8db2c832..215dadf87c21 100644
--- a/gcc/auto-profile.cc
+++ b/gcc/auto-profile.cc
@@ -35,6 +35,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-core.h"
 #include "profile.h"
 #include "langhooks.h"
+#include "context.h"
+#include "pass_manager.h"
 #include "cfgloop.h"
 #include "tree-cfg.h"
 #include "tree-cfgcleanup.h"
@@ -858,6 +860,9 @@ autofdo_source_profile::read ()
   /* Read in the function/callsite profile, and store it in local
  data structure.  */
   unsigned function_num = gcov_read_unsigned ();
+  int profile_pass_num
+ = g->get_passes ()->get_pass_auto_profile ()->static_pass_number;
+  g->get_dumps ()->dump_start (profile_pass_num, NULL);
   for (unsigned i = 0; i < function_num; i++)
 {
   function_instance::function_instance_stack stack;
@@ -870,8 +875,21 @@ autofdo_source_profile::read ()
   if (map_.count (fun_id) == 0)
map_[fun_id] = s;
   else
-   map_[fun_id]->merge (s);
+   {
+ /* Since this is invoked very early, before the pass
+manager, we need to set up the dumping explicitly.  This is
+similar to the handling in finish_optimization_passes.  */
+ if (dump_enabled_p ())
+   {
+ dump_user_location_t loc
+ = dump_user_location_t::from_location_t (input_location);
+ dump_printf_loc (MSG_NOTE, loc, "Merging profile for %s\n",
+   afdo_string_table->get_name (s->name ()));
+   }
+ map_[fun_id]->merge (s);
+   }
 }
+  g->get_dumps ()->dump_finish (profile_pass_num);
   return true;
 }
 
diff --git a/gcc/pass_manager.h b/gcc/pass_manager.h
index d4f89004559b..4de4a482ca1e 100644
--- a/gcc/pass_manager.h
+++ b/gcc/pass_manager.h
@@ -74,6 +74,7 @@ public:
   }
   opt_pass *get_pass_peephole2 () const { return m_pass_peephole2_1; }
   opt_pass *get_pass_profile () const { return m_pass_profile_1; }
+  opt_pass *get_pass_auto_profile () const { return m_pass_ipa_auto_profile_1; 
}
 
   void register_pass_name (opt_pass *pass, const char *name);
 
diff --git a/gcc/testsuite/gcc.dg/tree-prof/clone-merge-1.c 
b/gcc/testsuite/gcc.dg/tree-prof/clone-merge-1.c
new file mode 100644
index ..40aab9fdfca3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-prof/clone-merge-1.c
@@ -0,0 +1,32 @@
+/* { dg-options "-O3 -fno-early-inlining -fdump-ipa-afdo-all" } */
+__attribute__ ((used))
+int a[1000];
+
+__attribute__ ((noinline))
+void
+test2(int sz)
+{
+  a[sz]++;
+  asm volatile (""::"m"(a));
+}
+
+__attribute__ ((noinline))
+void
+test1 (int sz)
+{
+  for (int i = 0; i < 1000; i++)
+if (i % 2)
+  test2 (sz);
+else
+  test2 (i);
+
+}
+int main()
+{
+  for (int i = 0; i < 1000; i++)
+test1 (1000);
+  return 0;
+}
+/* We will have profiles for test2 and test2.constprop.0 that will have to be
+   merged,  */
+/* { dg-final-use-autofdo { scan-ipa-dump "note: Merging profile for test2" 
"afdo"} } */


[gcc/devel/rust/master] gccrs: We cant clone types as it will dup the node-id

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:4e63248e89a026e4bce4c79b1697ad0243f0f3aa

commit 4e63248e89a026e4bce4c79b1697ad0243f0f3aa
Author: Philip Herron 
Date:   Sun May 11 15:03:05 2025 +0100

gccrs: We cant clone types as it will dup the node-id

This patch ensuers we reuse the Builder for new type to
ensure we create a new type from scratch ensuring consistent
new node-ids.

gcc/rust/ChangeLog:

* expand/rust-derive-default.cc (DeriveDefault::visit_struct): use 
builder
(DeriveDefault::visit_tuple): likewise
* expand/rust-derive-eq.cc (DeriveEq::visit_tuple): likewise
(DeriveEq::visit_struct): likewise
(DeriveEq::visit_enum): likewise
(DeriveEq::visit_union): likewise

gcc/testsuite/ChangeLog:

* rust/compile/nr2/exclude: these are fixed now

Signed-off-by: Philip Herron 

Diff:
---
 gcc/rust/expand/rust-derive-default.cc |  5 +++--
 gcc/rust/expand/rust-derive-eq.cc  | 26 --
 gcc/testsuite/rust/compile/nr2/exclude |  2 --
 3 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/gcc/rust/expand/rust-derive-default.cc 
b/gcc/rust/expand/rust-derive-default.cc
index 2e8b45681994..1b497b5923b0 100644
--- a/gcc/rust/expand/rust-derive-default.cc
+++ b/gcc/rust/expand/rust-derive-default.cc
@@ -98,7 +98,8 @@ DeriveDefault::visit_struct (StructStruct &item)
   for (auto &field : item.get_fields ())
 {
   auto name = field.get_field_name ().as_string ();
-  auto expr = default_call (field.get_field_type ().clone_type ());
+  auto type = Builder::new_type (field.get_field_type ());
+  auto expr = default_call (std::move (type));
 
   cloned_fields.emplace_back (
builder.struct_expr_field (std::move (name), std::move (expr)));
@@ -119,7 +120,7 @@ DeriveDefault::visit_tuple (TupleStruct &tuple_item)
 
   for (auto &field : tuple_item.get_fields ())
 {
-  auto type = field.get_field_type ().clone_type ();
+  auto type = Builder::new_type (field.get_field_type ());
 
   defaulted_fields.emplace_back (default_call (std::move (type)));
 }
diff --git a/gcc/rust/expand/rust-derive-eq.cc 
b/gcc/rust/expand/rust-derive-eq.cc
index 5e7a8946dfdb..04c987dc96e3 100644
--- a/gcc/rust/expand/rust-derive-eq.cc
+++ b/gcc/rust/expand/rust-derive-eq.cc
@@ -142,7 +142,10 @@ DeriveEq::visit_tuple (TupleStruct &item)
   auto types = std::vector> ();
 
   for (auto &field : item.get_fields ())
-types.emplace_back (field.get_field_type ().clone_type ());
+{
+  auto type = Builder::new_type (field.get_field_type ());
+  types.emplace_back (std::move (type));
+}
 
   expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)),
   item.get_identifier ().as_string (),
@@ -155,7 +158,10 @@ DeriveEq::visit_struct (StructStruct &item)
   auto types = std::vector> ();
 
   for (auto &field : item.get_fields ())
-types.emplace_back (field.get_field_type ().clone_type ());
+{
+  auto type = Builder::new_type (field.get_field_type ());
+  types.emplace_back (std::move (type));
+}
 
   expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)),
   item.get_identifier ().as_string (),
@@ -179,15 +185,20 @@ DeriveEq::visit_enum (Enum &item)
auto &tuple = static_cast (*variant);
 
for (auto &field : tuple.get_tuple_fields ())
- types.emplace_back (field.get_field_type ().clone_type ());
-
+ {
+   auto type = Builder::new_type (field.get_field_type ());
+   types.emplace_back (std::move (type));
+ }
break;
  }
  case EnumItem::Kind::Struct: {
auto &tuple = static_cast (*variant);
 
for (auto &field : tuple.get_struct_fields ())
- types.emplace_back (field.get_field_type ().clone_type ());
+ {
+   auto type = Builder::new_type (field.get_field_type ());
+   types.emplace_back (std::move (type));
+ }
 
break;
  }
@@ -205,7 +216,10 @@ DeriveEq::visit_union (Union &item)
   auto types = std::vector> ();
 
   for (auto &field : item.get_variants ())
-types.emplace_back (field.get_field_type ().clone_type ());
+{
+  auto type = Builder::new_type (field.get_field_type ());
+  types.emplace_back (std::move (type));
+}
 
   expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)),
   item.get_identifier ().as_string (),
diff --git a/gcc/testsuite/rust/compile/nr2/exclude 
b/gcc/testsuite/rust/compile/nr2/exclude
index 312964c6b144..d4e066a5f723 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -6,8 +6,6 @@ pub_restricted_1.rs
 pub_restricted_2.rs
 pub_restricted_3.rs
 issue-2905-2.rs
-derive-default1.rs
-derive-eq-invalid.rs
 torture/alt_pa

[gcc/devel/rust/master] nr2.0: Fix borrow checking

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:dfc026ce0acf9a24f14c3ff1c019a35abfee2c27

commit dfc026ce0acf9a24f14c3ff1c019a35abfee2c27
Author: Owen Avery 
Date:   Fri May 9 18:02:29 2025 -0400

nr2.0: Fix borrow checking

gcc/rust/ChangeLog:

* checks/errors/borrowck/rust-bir-builder-internal.h: Include
"rust-immutable-name-resolution-context.h" and "options.h".
(AbstractBuilder::resolve_label): Use the 2.0 name resolver when
it's enabled.
(AbstractBuilder::resolve_variable): Likewise.
(AbstractBuilder::resolve_variable_or_fn): Likewise.

Signed-off-by: Owen Avery 

Diff:
---
 .../errors/borrowck/rust-bir-builder-internal.h| 54 ++
 1 file changed, 44 insertions(+), 10 deletions(-)

diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
index 8de6b8b00a91..f636bda7e648 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
@@ -27,6 +27,8 @@
 #include "rust-name-resolver.h"
 #include "rust-bir.h"
 #include "rust-bir-free-region.h"
+#include "rust-immutable-name-resolution-context.h"
+#include "options.h"
 
 namespace Rust {
 
@@ -402,19 +404,40 @@ protected: // HIR resolution helpers
   template  NodeId resolve_label (T &expr)
   {
 NodeId resolved_label;
-bool ok
-  = ctx.resolver.lookup_resolved_label (expr.get_mappings ().get_nodeid (),
-   &resolved_label);
-rust_assert (ok);
+if (flag_name_resolution_2_0)
+  {
+   auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+   auto res = nr_ctx.lookup (expr.get_mappings ().get_nodeid ());
+   rust_assert (res.has_value ());
+   resolved_label = res.value ();
+  }
+else
+  {
+   bool ok = ctx.resolver.lookup_resolved_label (
+ expr.get_mappings ().get_nodeid (), &resolved_label);
+   rust_assert (ok);
+  }
 return resolved_label;
   }
 
   template  PlaceId resolve_variable (T &variable)
   {
 NodeId variable_id;
-bool ok = ctx.resolver.lookup_resolved_name (
-  variable.get_mappings ().get_nodeid (), &variable_id);
-rust_assert (ok);
+if (flag_name_resolution_2_0)
+  {
+   auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+   auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ());
+   rust_assert (res.has_value ());
+   variable_id = res.value ();
+  }
+else
+  {
+   bool ok = ctx.resolver.lookup_resolved_name (
+ variable.get_mappings ().get_nodeid (), &variable_id);
+   rust_assert (ok);
+  }
 return ctx.place_db.lookup_variable (variable_id);
   }
 
@@ -425,9 +448,20 @@ protected: // HIR resolution helpers
 // Unlike variables,
 // functions do not have to be declared in PlaceDB before use.
 NodeId variable_id;
-bool ok = ctx.resolver.lookup_resolved_name (
-  variable.get_mappings ().get_nodeid (), &variable_id);
-rust_assert (ok);
+if (flag_name_resolution_2_0)
+  {
+   auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+   auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ());
+   rust_assert (res.has_value ());
+   variable_id = res.value ();
+  }
+else
+  {
+   bool ok = ctx.resolver.lookup_resolved_name (
+ variable.get_mappings ().get_nodeid (), &variable_id);
+   rust_assert (ok);
+  }
 if (ty->is ())
   return ctx.place_db.get_constant (ty);
 else


[gcc/devel/rust/master] Fix test same_field_name.rs

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:f33bae65a16b6d8c9d4f491638c4728f9c231ed4

commit f33bae65a16b6d8c9d4f491638c4728f9c231ed4
Author: Owen Avery 
Date:   Fri May 9 20:48:18 2025 -0400

Fix test same_field_name.rs

gcc/rust/ChangeLog:

* hir/rust-ast-lower-item.cc
(ASTLoweringItem::visit): Keep going after a duplicate field is
found.

gcc/testsuite/ChangeLog:

* rust/execute/same_field_name.rs: Move to...
* rust/compile/same_field_name.rs: ...here and adjust expected
errors.

Signed-off-by: Owen Avery 

Diff:
---
 gcc/rust/hir/rust-ast-lower-item.cc| 2 +-
 gcc/testsuite/rust/{execute => compile}/same_field_name.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/hir/rust-ast-lower-item.cc 
b/gcc/rust/hir/rust-ast-lower-item.cc
index 9bb968f028f8..07b1c9d6c78c 100644
--- a/gcc/rust/hir/rust-ast-lower-item.cc
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -217,7 +217,7 @@ ASTLoweringItem::visit (AST::StructStruct &struct_decl)
 field.get_outer_attrs ());
 
   if (struct_field_name_exists (fields, translated_field))
-   break;
+   continue;
 
   fields.push_back (std::move (translated_field));
 }
diff --git a/gcc/testsuite/rust/execute/same_field_name.rs 
b/gcc/testsuite/rust/compile/same_field_name.rs
similarity index 76%
rename from gcc/testsuite/rust/execute/same_field_name.rs
rename to gcc/testsuite/rust/compile/same_field_name.rs
index d57562b39a64..8e5b78c74365 100644
--- a/gcc/testsuite/rust/execute/same_field_name.rs
+++ b/gcc/testsuite/rust/compile/same_field_name.rs
@@ -1,7 +1,7 @@
 // https://doc.rust-lang.org/error_codes/E0124.html
 fn main() {
 struct Foo {
-field1: i32, // { dg-error "field .field1. is already declared" }
+field1: i32,
 field1: i32, // { dg-error "field .field1. is already declared" }
 field1: i32, // { dg-error "field .field1. is already declared" }
 }


[gcc/devel/rust/master] Fix Attr metavariable binding

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:dceaabbe556051101ef1c39b5a323ca7d5bf2f1e

commit dceaabbe556051101ef1c39b5a323ca7d5bf2f1e
Author: Owen Avery 
Date:   Fri May 9 22:17:55 2025 -0400

Fix Attr metavariable binding

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h
(Parser::parse_attr_input): Handle more delimeter tokens and the
END_OF_FILE token.
(Parser::skip_after_end_attribute): Handle the END_OF_FILE
token.

gcc/testsuite/ChangeLog:

* rust/compile/macros/mbe/meta-param.rs: New test.

Signed-off-by: Owen Avery 

Diff:
---
 gcc/rust/parse/rust-parse-impl.h| 5 -
 gcc/testsuite/rust/compile/macros/mbe/meta-param.rs | 7 +++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index e165998e2cb9..bbe75ad88c27 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -877,7 +877,10 @@ Parser::parse_attr_input ()
return attr_input_lit;
   }
   break;
+case RIGHT_PAREN:
 case RIGHT_SQUARE:
+case RIGHT_CURLY:
+case END_OF_FILE:
   // means AttrInput is missing, which is allowed
   return nullptr;
 default:
@@ -11911,7 +11914,7 @@ Parser::skip_after_end_attribute ()
 {
   const_TokenPtr t = lexer.peek_token ();
 
-  while (t->get_id () != RIGHT_SQUARE)
+  while (t->get_id () != RIGHT_SQUARE && t->get_id () != END_OF_FILE)
 {
   lexer.skip_token ();
   t = lexer.peek_token ();
diff --git a/gcc/testsuite/rust/compile/macros/mbe/meta-param.rs 
b/gcc/testsuite/rust/compile/macros/mbe/meta-param.rs
new file mode 100644
index ..ed6e100e5fd0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macros/mbe/meta-param.rs
@@ -0,0 +1,7 @@
+macro_rules! foo {
+($x:meta) => {0}
+}
+
+pub fn main() -> i32 {
+foo!(Clone)
+}


[gcc/devel/rust/master] gccrs: remove unused file

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:7a562bcec1f7604e6df1b604979ce4c1456e6049

commit 7a562bcec1f7604e6df1b604979ce4c1456e6049
Author: Marc Poulhiès 
Date:   Tue May 13 21:21:18 2025 +0200

gccrs: remove unused file

gcc/rust/ChangeLog:

* Make-lang.in (GRS_OBJS): Remove rust-macro.o.
* ast/rust-macro.cc: Removed.

Signed-off-by: Marc Poulhiès 

Diff:
---
 gcc/rust/Make-lang.in  |  1 -
 gcc/rust/ast/rust-macro.cc | 25 -
 2 files changed, 26 deletions(-)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 38235f188e64..c68b4fd34471 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -123,7 +123,6 @@ GRS_OBJS = \
 rust/rust-keyword-values.o \
 rust/rust-abi.o \
 rust/rust-token-converter.o \
-rust/rust-macro.o \
 rust/rust-ast-lower.o \
 rust/rust-ast-lower-base.o \
 rust/rust-ast-lower-pattern.o \
diff --git a/gcc/rust/ast/rust-macro.cc b/gcc/rust/ast/rust-macro.cc
deleted file mode 100644
index f36feda9970f..
--- a/gcc/rust/ast/rust-macro.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2020-2024 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3.  If not see
-// .
-
-#include "rust-macro.h"
-
-namespace Rust {
-namespace AST {
-
-} // namespace AST
-} // namespace Rust


[gcc/devel/rust/master] gccrs: Fix NR2 ICE in visit_attributes

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:f870c29e2c450253b48a2c6246de48d4f5e275ea

commit f870c29e2c450253b48a2c6246de48d4f5e275ea
Author: Tom Schollenberger 
Date:   Sun May 11 22:57:28 2025 -0400

gccrs: Fix NR2 ICE in visit_attributes

Undefined attribute macros have no proc macro definition, which results
in a failing `rust_assert`. This changes that assert to an if statement,
that returns early if there is no proc macro definition. Fixes #3661.

gcc/rust/ChangeLog:

* resolve/rust-early-name-resolver-2.0.cc 
(Early::visit_attributes): rust_assert to if

gcc/testsuite/ChangeLog:

* rust/compile/issue-3661.rs: Test NR2 has expected behavior

Signed-off-by: Tom Schollenberger 

Diff:
---
 gcc/rust/resolve/rust-early-name-resolver-2.0.cc |  3 ++-
 gcc/testsuite/rust/compile/issue-3661.rs | 10 ++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 73d71ca185a2..1dc63f417e2c 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -350,7 +350,8 @@ Early::visit_attributes (std::vector &attrs)
  auto pm_def = mappings.lookup_attribute_proc_macro_def (
definition->get_node_id ());
 
- rust_assert (pm_def.has_value ());
+ if (!pm_def.has_value ())
+   return;
 
  mappings.insert_attribute_proc_macro_invocation (attr.get_path (),
   pm_def.value ());
diff --git a/gcc/testsuite/rust/compile/issue-3661.rs 
b/gcc/testsuite/rust/compile/issue-3661.rs
new file mode 100644
index ..8d03c3630d56
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3661.rs
@@ -0,0 +1,10 @@
+pub macro m($inner_str:expr) {
+#[m = $inner_str] 
+// { dg-error "macro not found" "" { target *-*-* } .-1 }
+
+struct S;
+}
+
+fn main() {
+m!(stringify!(foo));
+}


[gcc/devel/rust/master] nr2.0: Fix some paths in test files

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:c087dd8bb06038248917ec1968a5acfac1d1a88c

commit c087dd8bb06038248917ec1968a5acfac1d1a88c
Author: Owen Avery 
Date:   Wed May 14 18:22:33 2025 -0400

nr2.0: Fix some paths in test files

This is similar to 9faba024ef18b9c4d67f22bd3b020b5e445fad0a, but it
applies to execute tests.

gcc/testsuite/ChangeLog:

* rust/execute/torture/for-loop1.rs: Adjust paths.
* rust/execute/torture/for-loop2.rs: Likewise.
* rust/execute/torture/iter1.rs: Likewise.

Signed-off-by: Owen Avery 

Diff:
---
 gcc/testsuite/rust/execute/torture/for-loop1.rs | 38 -
 gcc/testsuite/rust/execute/torture/for-loop2.rs | 38 -
 gcc/testsuite/rust/execute/torture/iter1.rs | 38 -
 3 files changed, 57 insertions(+), 57 deletions(-)

diff --git a/gcc/testsuite/rust/execute/torture/for-loop1.rs 
b/gcc/testsuite/rust/execute/torture/for-loop1.rs
index 5a6a70c37d64..334218927b13 100644
--- a/gcc/testsuite/rust/execute/torture/for-loop1.rs
+++ b/gcc/testsuite/rust/execute/torture/for-loop1.rs
@@ -102,30 +102,30 @@ mod ptr {
 #[lang = "const_ptr"]
 impl *const T {
 pub unsafe fn offset(self, count: isize) -> *const T {
-intrinsics::offset(self, count)
+crate::intrinsics::offset(self, count)
 }
 }
 
 #[lang = "mut_ptr"]
 impl *mut T {
 pub unsafe fn offset(self, count: isize) -> *mut T {
-intrinsics::offset(self, count) as *mut T
+crate::intrinsics::offset(self, count) as *mut T
 }
 }
 
 pub unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) {
 let x = x as *mut u8;
 let y = y as *mut u8;
-let len = mem::size_of::() * count;
+let len = crate::mem::size_of::() * count;
 swap_nonoverlapping_bytes(x, y, len)
 }
 
 pub unsafe fn swap_nonoverlapping_one(x: *mut T, y: *mut T) {
 // For types smaller than the block optimization below,
 // just swap directly to avoid pessimizing codegen.
-if mem::size_of::() < 32 {
+if crate::mem::size_of::() < 32 {
 let z = read(x);
-intrinsics::copy_nonoverlapping(y, x, 1);
+crate::intrinsics::copy_nonoverlapping(y, x, 1);
 write(y, z);
 } else {
 swap_nonoverlapping(x, y, 1);
@@ -133,12 +133,12 @@ mod ptr {
 }
 
 pub unsafe fn write(dst: *mut T, src: T) {
-intrinsics::move_val_init(&mut *dst, src)
+crate::intrinsics::move_val_init(&mut *dst, src)
 }
 
 pub unsafe fn read(src: *const T) -> T {
-let mut tmp: T = mem::uninitialized();
-intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
+let mut tmp: T = crate::mem::uninitialized();
+crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
 tmp
 }
 
@@ -146,7 +146,7 @@ mod ptr {
 struct Block(u64, u64, u64, u64);
 struct UnalignedBlock(u64, u64, u64, u64);
 
-let block_size = mem::size_of::();
+let block_size = crate::mem::size_of::();
 
 // Loop through x & y, copying them `Block` at a time
 // The optimizer should unroll the loop fully for most types
@@ -155,31 +155,31 @@ mod ptr {
 while i + block_size <= len {
 // Create some uninitialized memory as scratch space
 // Declaring `t` here avoids aligning the stack when this loop is 
unused
-let mut t: Block = mem::uninitialized();
+let mut t: Block = crate::mem::uninitialized();
 let t = &mut t as *mut _ as *mut u8;
 let x = x.offset(i as isize);
 let y = y.offset(i as isize);
 
 // Swap a block of bytes of x & y, using t as a temporary buffer
 // This should be optimized into efficient SIMD operations where 
available
-intrinsics::copy_nonoverlapping(x, t, block_size);
-intrinsics::copy_nonoverlapping(y, x, block_size);
-intrinsics::copy_nonoverlapping(t, y, block_size);
+crate::intrinsics::copy_nonoverlapping(x, t, block_size);
+crate::intrinsics::copy_nonoverlapping(y, x, block_size);
+crate::intrinsics::copy_nonoverlapping(t, y, block_size);
 i += block_size;
 }
 
 if i < len {
 // Swap any remaining bytes
-let mut t: UnalignedBlock = mem::uninitialized();
+let mut t: UnalignedBlock = crate::mem::uninitialized();
 let rem = len - i;
 
 let t = &mut t as *mut _ as *mut u8;
 let x = x.offset(i as isize);
 let y = y.offset(i as isize);
 
-intrinsics::copy_nonoverlapping(x, t, rem);
-intrinsics::copy_nonoverlapping(y, x, rem);
-intrinsics::copy_nonoverlapping(t, y, rem);
+crate::intrinsics::copy_nonoverlapping(x, t, rem);
+ 

[gcc/devel/rust/master] gccrs: refactor default infer vars to be its own function

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:457b3d1e29ce72bda6ac74a7c761decd657aab12

commit 457b3d1e29ce72bda6ac74a7c761decd657aab12
Author: Philip Herron 
Date:   Mon May 19 17:55:53 2025 +0100

gccrs: refactor default infer vars to be its own function

This is just a simple refactor to pull all the logic outside of the
closure which makes it more readable.

gcc/rust/ChangeLog:

* typecheck/rust-hir-type-check.h: new function
* typecheck/rust-typecheck-context.cc 
(TypeCheckContext::compute_inference_variables):
call the new helper
(TypeCheckContext::compute_infer_var): refactored code

Signed-off-by: Philip Herron 

Diff:
---
 gcc/rust/typecheck/rust-hir-type-check.h |  4 +-
 gcc/rust/typecheck/rust-typecheck-context.cc | 67 +++-
 2 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-type-check.h 
b/gcc/rust/typecheck/rust-hir-type-check.h
index 65f38c6099cd..b9238808b9fd 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -263,13 +263,15 @@ public:
   WARN_UNUSED_RESULT std::vector
   regions_from_generic_args (const HIR::GenericArgs &args) const;
 
-  void compute_inference_variables (bool error);
+  void compute_inference_variables (bool emit_error);
 
   TyTy::VarianceAnalysis::CrateCtx &get_variance_analysis_ctx ();
 
 private:
   TypeCheckContext ();
 
+  bool compute_infer_var (HirId id, TyTy::BaseType *ty, bool emit_error);
+
   std::map node_id_refs;
   std::map resolved;
   std::vector> builtins;
diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc 
b/gcc/rust/typecheck/rust-typecheck-context.cc
index 95c78a7008ec..7092fede6ee0 100644
--- a/gcc/rust/typecheck/rust-typecheck-context.cc
+++ b/gcc/rust/typecheck/rust-typecheck-context.cc
@@ -575,43 +575,48 @@ TypeCheckContext::regions_from_generic_args (const 
HIR::GenericArgs &args) const
 }
 
 void
-TypeCheckContext::compute_inference_variables (bool error)
+TypeCheckContext::compute_inference_variables (bool emit_error)
 {
-  auto &mappings = Analysis::Mappings::get ();
-
   // default inference variables if possible
   iterate ([&] (HirId id, TyTy::BaseType *ty) mutable -> bool {
-// nothing to do
-if (ty->get_kind () != TyTy::TypeKind::INFER)
-  return true;
+return compute_infer_var (id, ty, emit_error);
+  });
+}
 
-TyTy::InferType *infer_var = static_cast (ty);
-TyTy::BaseType *default_type;
-
-rust_debug_loc (mappings.lookup_location (id),
-   "trying to default infer-var: %s",
-   infer_var->as_string ().c_str ());
-bool ok = infer_var->default_type (&default_type);
-if (!ok)
-  {
-   if (error)
- rust_error_at (mappings.lookup_location (id), ErrorCode::E0282,
-"type annotations needed");
-   return true;
-  }
-
-auto result
-  = unify_site (id, TyTy::TyWithLocation (ty),
-   TyTy::TyWithLocation (default_type), UNDEF_LOCATION);
-rust_assert (result);
-rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
-result->set_ref (id);
-insert_type (Analysis::NodeMapping (mappings.get_current_crate (), 0, id,
-   UNKNOWN_LOCAL_DEFID),
-result);
+bool
+TypeCheckContext::compute_infer_var (HirId id, TyTy::BaseType *ty,
+bool emit_error)
+{
+  auto &mappings = Analysis::Mappings::get ();
 
+  // nothing to do
+  if (ty->get_kind () != TyTy::TypeKind::INFER)
 return true;
-  });
+
+  TyTy::InferType *infer_var = static_cast (ty);
+  TyTy::BaseType *default_type;
+
+  rust_debug_loc (mappings.lookup_location (id),
+ "trying to default infer-var: %s",
+ infer_var->as_string ().c_str ());
+  bool ok = infer_var->default_type (&default_type);
+  if (!ok)
+{
+  if (emit_error)
+   rust_error_at (mappings.lookup_location (id), ErrorCode::E0282,
+  "type annotations needed");
+  return true;
+}
+
+  auto result
+= unify_site (id, TyTy::TyWithLocation (ty),
+ TyTy::TyWithLocation (default_type), UNDEF_LOCATION);
+  rust_assert (result);
+  rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
+  result->set_ref (id);
+  insert_implicit_type (id, result);
+
+  return true;
 }
 
 TyTy::VarianceAnalysis::CrateCtx &


[gcc/devel/rust/master] nr2.0: Fix test builtin_abort.rs

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:d188df1814f5592bfaa58bcfdb43e4884d0b884e

commit d188df1814f5592bfaa58bcfdb43e4884d0b884e
Author: Owen Avery 
Date:   Wed May 14 20:05:55 2025 -0400

nr2.0: Fix test builtin_abort.rs

gcc/testsuite/ChangeLog:

* rust/execute/torture/builtin_abort.rs: Fix path to
intrinsics::abort.

Signed-off-by: Owen Avery 

Diff:
---
 gcc/testsuite/rust/execute/torture/builtin_abort.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/rust/execute/torture/builtin_abort.rs 
b/gcc/testsuite/rust/execute/torture/builtin_abort.rs
index 9f2d8c2d9f38..8c8259adcb7c 100644
--- a/gcc/testsuite/rust/execute/torture/builtin_abort.rs
+++ b/gcc/testsuite/rust/execute/torture/builtin_abort.rs
@@ -9,6 +9,6 @@ mod intrinsics {
 }
 
 pub fn main () -> i32 {
-abort();
+intrinsics::abort();
 0
 }


[gcc/devel/rust/master] gccrs: Remove unneeded clones untill we have an arena allocator for these tmps

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:894e6951cfdd4868a396bde68ac01f0ad28326f0

commit 894e6951cfdd4868a396bde68ac01f0ad28326f0
Author: Philip Herron 
Date:   Mon May 19 17:42:17 2025 +0100

gccrs: Remove unneeded clones untill we have an arena allocator for these 
tmps

Cloning inference variables is very expensive because it means we are 
indirectly
creating an implicit new inference variable added to the reference chain.

gcc/rust/ChangeLog:

* checks/errors/privacy/rust-privacy-reporter.cc 
(PrivacyReporter::check_base_type_privacy):
no need for unreachable here
* typecheck/rust-unify.cc (UnifyRules::commit): dont clone infer 
vars
(UnifyRules::expect_inference_variable): likewise

Signed-off-by: Philip Herron 

Diff:
---
 .../checks/errors/privacy/rust-privacy-reporter.cc |  3 ++-
 gcc/rust/typecheck/rust-unify.cc   | 18 ++
 2 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc 
b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
index c78a2f5dcc6d..4a5a6aa7cf19 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
@@ -219,8 +219,9 @@ PrivacyReporter::check_base_type_privacy 
(Analysis::NodeMapping &node_mappings,
auto ref_id = ty->get_ref ();
if (auto lookup_id = mappings.lookup_hir_to_node (ref_id))
  return check_for_privacy_violation (*lookup_id, locus);
-   rust_unreachable ();
   }
+  break;
+
 case TyTy::REF:
   return recursive_check (
static_cast (ty)->get_base ());
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index 45c4cbaa7df8..4cfc197c430a 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -69,7 +69,6 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType 
*other,
TyTy::BaseType *resolved)
 {
   TypeCheckContext &context = *TypeCheckContext::get ();
-  Analysis::Mappings &mappings = Analysis::Mappings::get ();
 
   TyTy::BaseType *b = base->destructure ();
   TyTy::BaseType *o = other->destructure ();
@@ -102,13 +101,8 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType 
*other,
continue;
 
  // if any of the types are inference variables lets fix them
- if (ref_tyty->get_kind () == TyTy::TypeKind::INFER)
-   {
- auto node = Analysis::NodeMapping (mappings.get_current_crate (),
-UNKNOWN_NODEID, ref,
-UNKNOWN_LOCAL_DEFID);
- context.insert_type (node, resolved->clone ());
-   }
+ if (ref_tyty->is ())
+   context.insert_implicit_type (ref, resolved);
}
 }
 }
@@ -341,7 +335,7 @@ UnifyRules::expect_inference_variable (TyTy::InferType 
*ltype,
  || r->get_infer_kind ()
   == TyTy::InferType::InferTypeKind::GENERAL;
  if (is_valid)
-   return rtype->clone ();
+   return rtype;
}
break;
 
@@ -351,7 +345,7 @@ UnifyRules::expect_inference_variable (TyTy::InferType 
*ltype,
  || r->get_infer_kind ()
   == TyTy::InferType::InferTypeKind::GENERAL;
  if (is_valid)
-   return rtype->clone ();
+   return rtype;
}
break;
  }
@@ -369,7 +363,7 @@ UnifyRules::expect_inference_variable (TyTy::InferType 
*ltype,
if (is_valid)
  {
ltype->apply_primitive_type_hint (*rtype);
-   return rtype->clone ();
+   return rtype;
  }
   }
   break;
@@ -382,7 +376,7 @@ UnifyRules::expect_inference_variable (TyTy::InferType 
*ltype,
if (is_valid)
  {
ltype->apply_primitive_type_hint (*rtype);
-   return rtype->clone ();
+   return rtype;
  }
   }
   break;


[gcc/devel/rust/master] gccrs: Fix non canonical type bug with tuples

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:b401e72ba547d2fa595e13f119e3e5e337afc0d9

commit b401e72ba547d2fa595e13f119e3e5e337afc0d9
Author: Philip Herron 
Date:   Mon May 26 19:30:45 2025 +0100

gccrs: Fix non canonical type bug with tuples

When working on rpit we needed to change to use a monomorphized clone of
the result of function calls. This ended up causing a verify gimple issue
with tuples because:

  fn test(a: A, b: B) -> (A, B)

When passing for example:

  let a = test:: (123, 456) -> (A=i32, B=i32)

The resulting gimple types became:

  const struct (A=i32, B=i32) vs struct (i32, i32)

We removed the VIEW_CONVERT_EXPR support to auto fix this stuff a good
while ago because it hides these kinds of issues because the type hasher
included the A=i32, B=i32 vs the i32, i32 name so updating this to use
get_name instead keeps the naming the same as well as the fields meaning
these types are 100% equivilant and therefore no conversion is required.
This only occurs because tuples are not named types we should really add
more rust specific info on our gimple TYPES.

gcc/rust/ChangeLog:

* backend/rust-compile-type.cc (TyTyResolveCompile::visit): use 
get_name
* typecheck/rust-tyty.cc (TupleType::get_name): likewise

Signed-off-by: Philip Herron 

Diff:
---
 gcc/rust/backend/rust-compile-type.cc | 2 +-
 gcc/rust/typecheck/rust-tyty.cc   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-type.cc 
b/gcc/rust/backend/rust-compile-type.cc
index 5be2b9e317e4..903d0ce85416 100644
--- a/gcc/rust/backend/rust-compile-type.cc
+++ b/gcc/rust/backend/rust-compile-type.cc
@@ -454,7 +454,7 @@ TyTyResolveCompile::visit (const TyTy::TupleType &type)
 }
 
   tree struct_type_record = Backend::struct_type (fields);
-  translated = Backend::named_type (type.as_string (), struct_type_record,
+  translated = Backend::named_type (type.get_name (), struct_type_record,
type.get_ident ().locus);
 }
 
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 4da51ffdbfd1..09a9b97354be 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -1992,7 +1992,7 @@ TupleType::get_name () const
   std::string fields_buffer;
   for (const TyVar &field : get_fields ())
 {
-  fields_buffer += field.get_tyty ()->as_string ();
+  fields_buffer += field.get_tyty ()->get_name ();
   bool has_next = (i + 1) < get_fields ().size ();
   fields_buffer += has_next ? ", " : "";
   i++;


[gcc/devel/rust/master] gccrs: Initial support for Return Position Impl Trait

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:a497ed083516891db184e4e87a4b954dbd23ef06

commit a497ed083516891db184e4e87a4b954dbd23ef06
Author: Philip Herron 
Date:   Mon May 19 18:02:13 2025 +0100

gccrs: Initial support for Return Position Impl Trait

This is the initial patch for RPIT, we can build on this to handle the
more complex cases but there are enough distinct changes going on here
that it should just get merged now.

RPIT is really a sneaky generic so for example:

  fn foo() -> impl Bar {
  Baz
  }

This is represented as: fn () -> OpaqueType Bar. But when we handle the
coercion site for Baz on impl Bar when we type resolve the function we
know that the underlying type  is Baz. Note this function is _not_ generic
so its using this special OpaqueType and keeping track of the underlying 
type
in its ty_ref reference hir-id which will resolve to Baz.

This also means if we have a case where maybe this was in an if statement:

  fn foo(a: i32) -> impl Bar {
  if a > 10 {
Baz
  } else {
Qux
  }
  }

The rules of impl Bar is that Baz is handled but Baz and Qux are different
underlying types so this is not allowed. The reason is impl traits are not
generic and although from a programmer perspective the callers dont know 
what
the underlying type is, the compiler _knows_ what it is. So really when
you call a function and get its return position impl trait the compiler 
knows
what to do and does all whats nessecary to handle calling functions using 
that
type etc.

gcc/rust/ChangeLog:

* backend/rust-compile-type.cc (TyTyResolveCompile::visit): we need 
to resolve the
underlying type
* typecheck/rust-substitution-mapper.cc 
(SubstMapperInternal::visit): just clone
* typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit):
ensure we monomphize to get the underlying
* typecheck/rust-tyty.cc (BaseType::destructure): handle opaque 
types
(OpaqueType::resolve): this is much simpler now
(OpaqueType::handle_substitions): no longer needed
* typecheck/rust-tyty.h: update header
* typecheck/rust-unify.cc (UnifyRules::expect_opaque): unify rules 
for opaque

gcc/testsuite/ChangeLog:

* rust/compile/bad-rpit1.rs: New test.
* rust/execute/torture/impl_rpit1.rs: New test.
* rust/execute/torture/impl_rpit2.rs: New test.
* rust/execute/torture/impl_rpit3.rs: New test.

Signed-off-by: Philip Herron 

Diff:
---
 gcc/rust/backend/rust-compile-type.cc|  4 +-
 gcc/rust/typecheck/rust-substitution-mapper.cc   |  2 +-
 gcc/rust/typecheck/rust-tyty-call.cc |  2 +-
 gcc/rust/typecheck/rust-tyty.cc  | 72 +++
 gcc/rust/typecheck/rust-tyty.h   |  2 -
 gcc/rust/typecheck/rust-unify.cc | 90 +++-
 gcc/testsuite/rust/compile/bad-rpit1.rs  | 26 +++
 gcc/testsuite/rust/execute/torture/impl_rpit1.rs | 28 
 gcc/testsuite/rust/execute/torture/impl_rpit2.rs | 36 ++
 gcc/testsuite/rust/execute/torture/impl_rpit3.rs | 25 +++
 10 files changed, 169 insertions(+), 118 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-type.cc 
b/gcc/rust/backend/rust-compile-type.cc
index 903d0ce85416..5ca1d82b3d40 100644
--- a/gcc/rust/backend/rust-compile-type.cc
+++ b/gcc/rust/backend/rust-compile-type.cc
@@ -755,7 +755,9 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType 
&type)
 void
 TyTyResolveCompile::visit (const TyTy::OpaqueType &type)
 {
-  translated = error_mark_node;
+  rust_assert (type.can_resolve ());
+  auto underlying = type.resolve ();
+  translated = TyTyResolveCompile::compile (ctx, underlying, 
trait_object_mode);
 }
 
 tree
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc 
b/gcc/rust/typecheck/rust-substitution-mapper.cc
index 878c4d54a0a8..23116ff80401 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.cc
+++ b/gcc/rust/typecheck/rust-substitution-mapper.cc
@@ -374,7 +374,7 @@ SubstMapperInternal::visit (TyTy::DynamicObjectType &type)
 void
 SubstMapperInternal::visit (TyTy::OpaqueType &type)
 {
-  resolved = type.handle_substitions (mappings);
+  resolved = type.clone ();
 }
 
 // SubstMapperFromExisting
diff --git a/gcc/rust/typecheck/rust-tyty-call.cc 
b/gcc/rust/typecheck/rust-tyty-call.cc
index 75cf58faf89e..0d187f37ee38 100644
--- a/gcc/rust/typecheck/rust-tyty-call.cc
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -246,7 +246,7 @@ TypeCheckCallExpr::visit (FnType &type)
 }
 
   type.monomorphize ();
-  resolved = type.get_return_type ()->clone ();
+  resolved = type.get_return_type ()->monomorphized_clone ();
 }
 
 void
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 09a9b97354be.

[gcc/devel/rust/master] Remove rvalue reference binding

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:2dc57afa16fe10616acb7660fa7d68d2a9666860

commit 2dc57afa16fe10616acb7660fa7d68d2a9666860
Author: Owen Avery 
Date:   Tue May 13 18:01:33 2025 -0400

Remove rvalue reference binding

This should be unnecessary, since even C++11 has implicit move.

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h (Parser::parse_expr_stmt): Avoid
reference binding and remove std::move in return statements.

Signed-off-by: Owen Avery 

Diff:
---
 gcc/rust/parse/rust-parse-impl.h | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index bbe75ad88c27..20b17b6292e9 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -7077,10 +7077,7 @@ Parser::parse_expr_stmt 
(AST::AttrVec outer_attrs,
 
if (lexer.peek_token ()->get_id () == EXCLAM)
  {
-   // Bind a reference to avoid -Wredundant-move on post-P1825R0
-   // compilers. Change to non-reference type and remove the moves
-   // below once C++20 is required to build gcc.
-   std::unique_ptr &&invoc
+   std::unique_ptr invoc
  = parse_macro_invocation_partial (std::move (path),
std::move (outer_attrs));
 
@@ -7088,7 +7085,7 @@ Parser::parse_expr_stmt (AST::AttrVec 
outer_attrs,
  {
invoc->add_semicolon ();
// Macro invocation with semicolon.
-   return std::move (invoc);
+   return invoc;
  }
 
TokenId after_macro = lexer.peek_token ()->get_id ();
@@ -7096,14 +7093,14 @@ Parser::parse_expr_stmt 
(AST::AttrVec outer_attrs,
if (restrictions.allow_close_after_expr_stmt
&& (after_macro == RIGHT_PAREN || after_macro == RIGHT_CURLY
|| after_macro == RIGHT_SQUARE))
- return std::move (invoc);
+ return invoc;
 
if (invoc->get_invoc_data ().get_delim_tok_tree ().get_delim_type ()
  == AST::CURLY
&& after_macro != DOT && after_macro != QUESTION_MARK)
  {
rust_debug ("braced macro statement");
-   return std::move (invoc);
+   return invoc;
  }
 
null_denotation = std::move (invoc);


[gcc/devel/rust/master] Small improvements to DefaultASTVisitor and nr2.0

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:4f772da8df444fbcb84821d4c4c60cf1cc2f5479

commit 4f772da8df444fbcb84821d4c4c60cf1cc2f5479
Author: Owen Avery 
Date:   Thu May 8 17:32:05 2025 -0400

Small improvements to DefaultASTVisitor and nr2.0

gcc/rust/ChangeLog:

* ast/rust-ast-visitor.cc
(DefaultASTVisitor::visit): Only visit the path of an instance
of Visibility if the instance has a path.
* ast/rust-ast.h
(SimplePath::SimplePath): Make sure constructors are explicit.
* resolve/rust-early-name-resolver-2.0.cc
(Early::visit_attributes): Pass entire paths to
NameResolutionContext::resolve_path.
(Early::visit): Likewise and avoid copying a path.
* resolve/rust-forever-stack.hxx
(ForeverStack::resolve_path): Assert that at least one path
segment has been passed in.

Signed-off-by: Owen Avery 

Diff:
---
 gcc/rust/ast/rust-ast-visitor.cc |  3 ++-
 gcc/rust/ast/rust-ast.h  |  8 
 gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 12 ++--
 gcc/rust/resolve/rust-forever-stack.hxx  |  2 +-
 4 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index 105417baa636..8b47a81f4ed7 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -755,7 +755,8 @@ DefaultASTVisitor::visit (AST::TypeBoundWhereClauseItem 
&item)
 void
 DefaultASTVisitor::visit (AST::Visibility &vis)
 {
-  visit (vis.get_path ());
+  if (vis.has_path ())
+visit (vis.get_path ());
 }
 
 void
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 9581dd57b739..34d6c093ab34 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -403,15 +403,15 @@ class SimplePath
 
 public:
   // Constructor
-  SimplePath (std::vector path_segments,
- bool has_opening_scope_resolution = false,
- location_t locus = UNDEF_LOCATION)
+  explicit SimplePath (std::vector path_segments,
+  bool has_opening_scope_resolution = false,
+  location_t locus = UNDEF_LOCATION)
 : opening_scope_resolution (has_opening_scope_resolution),
   segments (std::move (path_segments)), locus (locus),
   node_id (Analysis::Mappings::get ().get_next_node_id ())
   {}
 
-  SimplePath (Identifier ident)
+  explicit SimplePath (Identifier ident)
 : opening_scope_resolution (false),
   segments ({SimplePathSegment (ident.as_string (), ident.get_locus ())}),
   locus (ident.get_locus ()),
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 3060b2904ec4..73d71ca185a2 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -249,7 +249,7 @@ Early::visit (AST::Module &module)
 void
 Early::visit (AST::MacroInvocation &invoc)
 {
-  auto path = invoc.get_invoc_data ().get_path ();
+  auto &path = invoc.get_invoc_data ().get_path ();
 
   if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
 for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
@@ -272,7 +272,7 @@ Early::visit (AST::MacroInvocation &invoc)
   // we won't have changed `definition` from `nullopt` if there are more
   // than one segments in our path
   if (!definition.has_value ())
-definition = ctx.resolve_path (path.get_segments (), Namespace::Macros);
+definition = ctx.resolve_path (path, Namespace::Macros);
 
   // if the definition still does not have a value, then it's an error
   if (!definition.has_value ())
@@ -314,8 +314,8 @@ Early::visit_attributes (std::vector &attrs)
  auto traits = attr.get_traits_to_derive ();
  for (auto &trait : traits)
{
- auto definition = ctx.resolve_path (trait.get ().get_segments (),
- Namespace::Macros);
+ auto definition
+   = ctx.resolve_path (trait.get (), Namespace::Macros);
  if (!definition.has_value ())
{
  // FIXME: Change to proper error message
@@ -337,8 +337,8 @@ Early::visit_attributes (std::vector &attrs)
 ->lookup_builtin (name)
 .is_error ()) // Do not resolve builtins
{
- auto definition = ctx.resolve_path (attr.get_path ().get_segments (),
- Namespace::Macros);
+ auto definition
+   = ctx.resolve_path (attr.get_path (), Namespace::Macros);
  if (!definition.has_value ())
{
  // FIXME: Change to proper error message
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx 
b/gcc/rust/resolve/rust-forever-stack.hxx
index abf3a531fae0..f814c896f465 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx

[gcc/devel/rust/master] Adjust included headers in rust-lang.cc

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:57a1b013474f7724e547d03d8da4f4f179a005a4

commit 57a1b013474f7724e547d03d8da4f4f179a005a4
Author: Owen Avery 
Date:   Mon May 26 17:11:19 2025 -0400

Adjust included headers in rust-lang.cc

This was upstreamed as part of ea34614225d4d255e58f63206eb12178b870cb4c
but never made it to our downstream repo. I've added Philip as a
co-author, since he wrote the upstream commit.

gcc/rust/ChangeLog:

* rust-lang.cc: Remove direct inclusion of "config.h" and
"system.h", move inclusion of "rust-system.h" upwards.

Co-authored-by: Philip Herron 
Signed-off-by: Owen Avery 

Diff:
---
 gcc/rust/rust-lang.cc | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc
index 2776333db59f..9409d8141ac4 100644
--- a/gcc/rust/rust-lang.cc
+++ b/gcc/rust/rust-lang.cc
@@ -16,9 +16,8 @@
 // along with GCC; see the file COPYING3.  If not see
 // .
 
+#include "rust-system.h"
 #include "rust-diagnostics.h"
-#include "config.h"
-#include "system.h"
 #include "coretypes.h"
 #include "target.h"
 #include "tree.h"
@@ -66,7 +65,6 @@
  * e.g. HIR conversion.
  */
 
-#include "rust-system.h"
 #include "rust-session-manager.h"
 #include "rust-tree.h"


[gcc/devel/rust/master] gccrs: Always emit the error highest in the type hierarchy

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:c77c3494f82da01c85a294a5f9c3a0c5496f8572

commit c77c3494f82da01c85a294a5f9c3a0c5496f8572
Author: Philip Herron 
Date:   Tue May 20 18:44:57 2025 +0100

gccrs: Always emit the error highest in the type hierarchy

The unify code was a bit dumb here where we always set emit_error to false 
for any
subtypes for example in comparing tuples we always emitted the whole tuple 
didnt
match the other tuple but really its much better to say expected bool got 
i32 because
the element types didn't match.

gcc/rust/ChangeLog:

* typecheck/rust-coercion.cc (TypeCoercionRules::coerce_unsized): 
dont emit error here
* typecheck/rust-unify.cc (UnifyRules::resolve_subtype): new helper 
to handle emit error
(UnifyRules::expect_adt): call resolve_subtype
(UnifyRules::expect_reference): likewise
(UnifyRules::expect_pointer): likewise
(UnifyRules::expect_array): likewise
(UnifyRules::expect_slice): likewise
(UnifyRules::expect_fndef): likewise
(UnifyRules::expect_fnptr): likewise
(UnifyRules::expect_tuple): likewise
(UnifyRules::expect_closure): likewise
(UnifyRules::expect_opaque): likeiwse
* typecheck/rust-unify.h: add new helper to header

gcc/testsuite/ChangeLog:

* rust/compile/traits9.rs: update errors
* rust/compile/unify-errors1.rs: New test.

Signed-off-by: Philip Herron 

Diff:
---
 gcc/rust/typecheck/rust-coercion.cc |   2 +-
 gcc/rust/typecheck/rust-unify.cc| 128 
 gcc/rust/typecheck/rust-unify.h |   3 +
 gcc/testsuite/rust/compile/traits9.rs   |   3 +-
 gcc/testsuite/rust/compile/unify-errors1.rs |  49 +++
 5 files changed, 110 insertions(+), 75 deletions(-)

diff --git a/gcc/rust/typecheck/rust-coercion.cc 
b/gcc/rust/typecheck/rust-coercion.cc
index f9956b0eeccb..36582de70483 100644
--- a/gcc/rust/typecheck/rust-coercion.cc
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -393,7 +393,7 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
 
   if (expect_dyn && need_unsize)
 {
-  bool bounds_compatible = b->bounds_compatible (*a, locus, true);
+  bool bounds_compatible = b->bounds_compatible (*a, locus, false);
   if (!bounds_compatible)
{
  unsafe_error = true;
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index 219db9a6df9e..e3413a2fea47 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -52,6 +52,22 @@ UnifyRules::Resolve (TyTy::TyWithLocation lhs, 
TyTy::TyWithLocation rhs,
   return result;
 }
 
+TyTy::BaseType *
+UnifyRules::resolve_subtype (TyTy::TyWithLocation lhs, TyTy::TyWithLocation 
rhs)
+{
+  TyTy::BaseType *result
+= UnifyRules::Resolve (lhs, rhs, locus, commit_flag, emit_error, 
infer_flag,
+  commits, infers);
+
+  // If the recursive call resulted in an error and would have emitted an error
+  // message, disable error emission for the current level to avoid duplicate
+  // errors
+  if (result->get_kind () == TyTy::TypeKind::ERROR && emit_error)
+emit_error = false;
+
+  return result;
+}
+
 TyTy::BaseType *
 UnifyRules::get_base ()
 {
@@ -463,11 +479,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, 
TyTy::BaseType *rtype)
TyTy::BaseType *other_field_ty = other_field->get_field_type ();
 
TyTy::BaseType *unified_ty
- = UnifyRules::Resolve (TyTy::TyWithLocation (this_field_ty),
-TyTy::TyWithLocation (other_field_ty),
-locus, commit_flag,
-false /* emit_error */, infer_flag,
-commits, infers);
+ = resolve_subtype (TyTy::TyWithLocation (this_field_ty),
+TyTy::TyWithLocation (other_field_ty));
if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
  {
return new TyTy::ErrorType (0);
@@ -489,11 +502,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, 
TyTy::BaseType *rtype)
auto pa = a.get_param_ty ();
auto pb = b.get_param_ty ();
 
-   auto res
- = UnifyRules::Resolve (TyTy::TyWithLocation (pa),
-TyTy::TyWithLocation (pb), locus,
-commit_flag, false /* emit_error */,
-infer_flag, commits, infers);
+   auto res = resolve_subtype (TyTy::TyWithLocation (pa),
+   TyTy::TyWithLocation (pb));
if (res->get_kind () == TyTy::TypeKind::ERROR)
  {
return new TyTy::

[gcc/devel/rust/master] nr2.0: Fix IfLet pattern handling

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:ba32a6e460813a94e5f129dbc0e259c300690385

commit ba32a6e460813a94e5f129dbc0e259c300690385
Author: Owen Avery 
Date:   Wed May 14 20:03:01 2025 -0400

nr2.0: Fix IfLet pattern handling

gcc/rust/ChangeLog:

* resolve/rust-default-resolver.cc
(DefaultResolver::visit_if_let_patterns): New function
definition.
(DefaultResolver::visit): New IfLetExpr visitor definition.
* resolve/rust-default-resolver.h
(DefaultResolver::visit_if_let_patterns): New function
declaration.
(DefaultResolver::visit): New IfLetExpr visitor declaration.
* resolve/rust-late-name-resolver-2.0.cc (Late::visit): Remove
IfLetExpr visitor definition.
(Late::visit_if_let_patterns): New function definition.
* resolve/rust-late-name-resolver-2.0.h (Late::visit): Remove
IfLetExpr visitor declaration.
(Late::visit_if_let_patterns): New function declaration.
* resolve/rust-name-resolution-context.h (BindingSource::IfLet):
New enumerator.

Signed-off-by: Owen Avery 

Diff:
---
 gcc/rust/resolve/rust-default-resolver.cc   | 22 ++
 gcc/rust/resolve/rust-default-resolver.h|  2 ++
 gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 12 +++-
 gcc/rust/resolve/rust-late-name-resolver-2.0.h  |  2 +-
 gcc/rust/resolve/rust-name-resolution-context.h |  1 +
 5 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/gcc/rust/resolve/rust-default-resolver.cc 
b/gcc/rust/resolve/rust-default-resolver.cc
index 7d8029fe3bfd..2dafa8861f61 100644
--- a/gcc/rust/resolve/rust-default-resolver.cc
+++ b/gcc/rust/resolve/rust-default-resolver.cc
@@ -60,6 +60,28 @@ DefaultResolver::visit (AST::ForLoopExpr &expr)
  [this, &expr] () { AST::DefaultASTVisitor::visit (expr); });
 }
 
+void
+DefaultResolver::visit_if_let_patterns (AST::IfLetExpr &expr)
+{
+  for (auto &pattern : expr.get_patterns ())
+visit (pattern);
+}
+
+void
+DefaultResolver::visit (AST::IfLetExpr &expr)
+{
+  auto inner_vis = [this, &expr] () {
+visit_if_let_patterns (expr);
+visit (expr.get_if_block ());
+  };
+
+  visit_outer_attrs (expr);
+
+  visit (expr.get_value_expr ());
+
+  ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), inner_vis);
+}
+
 void
 DefaultResolver::visit (AST::Trait &trait)
 {
diff --git a/gcc/rust/resolve/rust-default-resolver.h 
b/gcc/rust/resolve/rust-default-resolver.h
index 14ada236b7a8..6fa977b26a78 100644
--- a/gcc/rust/resolve/rust-default-resolver.h
+++ b/gcc/rust/resolve/rust-default-resolver.h
@@ -46,6 +46,8 @@ public:
   void visit (AST::Module &) override;
   void visit (AST::Function &) override;
   void visit (AST::ForLoopExpr &expr) override;
+  virtual void visit_if_let_patterns (AST::IfLetExpr &expr);
+  void visit (AST::IfLetExpr &expr) override;
   void visit (AST::Trait &) override;
   // used to handle Self insertion in TopLevel
   virtual void maybe_insert_big_self (AST::Impl &) {}
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
index 4ed5528c9110..da6820e02fff 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -147,19 +147,13 @@ Late::visit (AST::ForLoopExpr &expr)
 }
 
 void
-Late::visit (AST::IfLetExpr &expr)
+Late::visit_if_let_patterns (AST::IfLetExpr &expr)
 {
-  visit_outer_attrs (expr);
+  ctx.bindings.enter (BindingSource::IfLet);
 
-  ctx.bindings.enter (BindingSource::Let);
-
-  for (auto &pattern : expr.get_patterns ())
-visit (pattern);
+  DefaultResolver::visit_if_let_patterns (expr);
 
   ctx.bindings.exit ();
-
-  visit (expr.get_value_expr ());
-  visit (expr.get_if_block ());
 }
 
 void
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h 
b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
index 896b72ce4399..6b777cc76d66 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -50,7 +50,7 @@ public:
   void visit (AST::SelfParam &) override;
   void visit (AST::MatchArm &) override;
   void visit (AST::ForLoopExpr &) override;
-  void visit (AST::IfLetExpr &) override;
+  void visit_if_let_patterns (AST::IfLetExpr &) override;
 
   // resolutions
   void visit (AST::IdentifierExpr &) override;
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h 
b/gcc/rust/resolve/rust-name-resolution-context.h
index aab04ccc18eb..6d990fd60760 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -177,6 +177,7 @@ enum class BindingSource
 {
   Match,
   Let,
+  IfLet,
   For,
   /* Closure param or function param */
   Param


[gcc/devel/rust/master] parser: Add base for parsing const blocks

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:01b433d67a6774007b81258c89b11c2b6c84aaab

commit 01b433d67a6774007b81258c89b11c2b6c84aaab
Author: Arthur Cohen 
Date:   Tue Apr 15 17:33:11 2025 +0200

parser: Add base for parsing const blocks

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h (Parser::parse_const_block_expr): New 
function.
* parse/rust-parse.h: Declare it.

Diff:
---
 gcc/rust/parse/rust-parse-impl.h | 27 +++
 gcc/rust/parse/rust-parse.h  |  5 +
 2 files changed, 32 insertions(+)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 20b17b6292e9..35f6c899ea22 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -7238,6 +7238,30 @@ Parser::parse_block_expr (
std::move (label), locus, end_locus));
 }
 
+/* Parse a "const block", a block preceded by the `const` keyword whose
+ * statements can be const evaluated and used in constant contexts */
+template 
+std::unique_ptr
+Parser::parse_const_block_expr (AST::AttrVec outer_attrs,
+   location_t locus)
+{
+  auto block = parse_block_expr ();
+
+  if (!block)
+{
+  add_error (Error (locus, "failed to parse inner block in const block"));
+  skip_after_end_block ();
+
+  return nullptr;
+}
+
+  auto block_locus = block->get_locus ();
+
+  return std::make_unique (AST::AnonConst (std::move (block),
+   block_locus),
+   locus, std::move (outer_attrs));
+}
+
 /* Parses a "grouped" expression (expression in parentheses), used to control
  * precedence. */
 template 
@@ -12460,6 +12484,9 @@ Parser::null_denotation_not_path (
   "use of %qs is not allowed on the right-side of an assignment",
   tok->get_token_description ()));
   return nullptr;
+case CONST:
+  return parse_const_block_expr (std::move (outer_attrs),
+tok->get_locus ());
 default:
   if (!restrictions.expr_can_be_null)
add_error (Error (tok->get_locus (),
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 827d91d6cbb1..1dc12af0a3aa 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -17,6 +17,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef RUST_PARSE_H
 #define RUST_PARSE_H
 
+#include "rust-ast.h"
 #include "rust-item.h"
 #include "rust-lex.h"
 #include "rust-ast-full.h"
@@ -165,6 +166,10 @@ public:
tl::optional = tl::nullopt,
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
 
+  std::unique_ptr
+  parse_const_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
+ location_t loc = UNKNOWN_LOCATION);
+
   bool is_macro_rules_def (const_TokenPtr t);
   std::unique_ptr parse_item (bool called_from_statement);
   std::unique_ptr parse_pattern ();


[gcc/devel/rust/master] hir: Add const blocks

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:70fab4b0ce318ca7de67f5f26726ff5d403025f3

commit 70fab4b0ce318ca7de67f5f26726ff5d403025f3
Author: Arthur Cohen 
Date:   Tue Apr 15 13:34:38 2025 +0200

hir: Add const blocks

gcc/rust/ChangeLog:

* hir/tree/rust-hir-expr.h: New classes.
* hir/tree/rust-hir-full-decls.h: Likewise.
* hir/tree/rust-hir.cc: Handle AnonConst and ConstBlock.
* backend/rust-compile-block.cc: Likewise.
* backend/rust-compile-block.h: Likewise.
* backend/rust-compile-expr.cc (CompileExpr::visit): Likewise.
* backend/rust-compile-expr.h: Likewise.
* checks/errors/borrowck/rust-bir-builder-expr-stmt.cc 
(ExprStmtBuilder::visit): Likewise.
* checks/errors/borrowck/rust-bir-builder-expr-stmt.h: Likewise.
* checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Likewise.
* checks/errors/borrowck/rust-bir-builder-struct.h: Likewise.
* checks/errors/borrowck/rust-function-collector.h: Likewise.
* checks/errors/privacy/rust-privacy-reporter.cc 
(PrivacyReporter::visit): Likewise.
* checks/errors/privacy/rust-privacy-reporter.h: Likewise.
* checks/errors/rust-const-checker.cc (ConstChecker::visit): 
Likewise.
* checks/errors/rust-const-checker.h: Likewise.
* checks/errors/rust-hir-pattern-analysis.cc 
(PatternChecker::visit): Likewise.
* checks/errors/rust-hir-pattern-analysis.h: Likewise.
* checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): 
Likewise.
* checks/errors/rust-unsafe-checker.h: Likewise.
* hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
(translate_operand_out): Likewise.
(translate_operand_inout): Likewise.
(translate_operand_const): Likewise.
* hir/rust-ast-lower-expr.h: Likewise.
* hir/rust-hir-dump.cc (Dump::visit): Likewise.
* hir/rust-hir-dump.h: Likewise.
* hir/tree/rust-hir-expr-abstract.h: Likewise.
* hir/tree/rust-hir-expr.cc (AnonConst::AnonConst): Likewise.
(AnonConst::operator=): Likewise.
(ConstBlock::ConstBlock): Likewise.
(ConstBlock::operator=): Likewise.
* hir/tree/rust-hir-visitor.h:
* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): 
Likewise.
(typecheck_inline_asm_operand): Likewise.
* typecheck/rust-hir-type-check-expr.h: Likewise.

Diff:
---
 gcc/rust/backend/rust-compile-block.cc |  1 +
 gcc/rust/backend/rust-compile-block.h  |  9 +++
 gcc/rust/backend/rust-compile-expr.cc  | 13 
 gcc/rust/backend/rust-compile-expr.h   |  2 +
 .../errors/borrowck/rust-bir-builder-expr-stmt.cc  | 12 
 .../errors/borrowck/rust-bir-builder-expr-stmt.h   |  2 +
 .../borrowck/rust-bir-builder-lazyboolexpr.h   |  8 +++
 .../errors/borrowck/rust-bir-builder-struct.h  |  2 +
 .../errors/borrowck/rust-function-collector.h  |  2 +
 .../checks/errors/privacy/rust-privacy-reporter.cc | 12 
 .../checks/errors/privacy/rust-privacy-reporter.h  |  2 +
 gcc/rust/checks/errors/rust-const-checker.cc   | 20 ++
 gcc/rust/checks/errors/rust-const-checker.h|  2 +
 .../checks/errors/rust-hir-pattern-analysis.cc | 12 
 gcc/rust/checks/errors/rust-hir-pattern-analysis.h |  2 +
 gcc/rust/checks/errors/rust-unsafe-checker.cc  | 12 
 gcc/rust/checks/errors/rust-unsafe-checker.h   |  2 +
 gcc/rust/hir/rust-ast-lower-expr.cc| 60 +---
 gcc/rust/hir/rust-ast-lower-expr.h |  2 +
 gcc/rust/hir/rust-hir-dump.cc  | 22 ++
 gcc/rust/hir/rust-hir-dump.h   |  2 +
 gcc/rust/hir/tree/rust-hir-expr-abstract.h |  4 +-
 gcc/rust/hir/tree/rust-hir-expr.cc | 64 --
 gcc/rust/hir/tree/rust-hir-expr.h  | 79 ++
 gcc/rust/hir/tree/rust-hir-full-decls.h|  3 +-
 gcc/rust/hir/tree/rust-hir-visitor.h   |  6 ++
 gcc/rust/hir/tree/rust-hir.cc  | 51 ++
 gcc/rust/typecheck/rust-hir-type-check-expr.cc | 14 +++-
 gcc/rust/typecheck/rust-hir-type-check-expr.h  |  2 +
 29 files changed, 380 insertions(+), 44 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-block.cc 
b/gcc/rust/backend/rust-compile-block.cc
index 56d0c417f0ab..b55fe68ca940 100644
--- a/gcc/rust/backend/rust-compile-block.cc
+++ b/gcc/rust/backend/rust-compile-block.cc
@@ -19,6 +19,7 @@
 #include "rust-compile-block.h"
 #include "rust-compile-stmt.h"
 #include "rust-compile-expr.h"
+#include "rust-hir-expr.h"
 
 namespace Rust {
 namespace Compile {
diff --git a/gcc/rust/backend/rust-compile-block.h 
b/gcc/rust/backend/rust-compile-block.h
index 896ff7584421..e288bd89f261 100644
--- a

[gcc/devel/rust/master] const-block: Add testcase

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:7e42c1ee80f2b4836f81f546e8c1bf7ecca57210

commit 7e42c1ee80f2b4836f81f546e8c1bf7ecca57210
Author: Arthur Cohen 
Date:   Tue Apr 15 13:41:41 2025 +0200

const-block: Add testcase

gcc/testsuite/ChangeLog:

* rust/execute/torture/const_block1.rs: New test.

Diff:
---
 gcc/testsuite/rust/execute/torture/const_block1.rs | 9 +
 1 file changed, 9 insertions(+)

diff --git a/gcc/testsuite/rust/execute/torture/const_block1.rs 
b/gcc/testsuite/rust/execute/torture/const_block1.rs
new file mode 100644
index ..eaf343249d13
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/const_block1.rs
@@ -0,0 +1,9 @@
+const X: i32 = const {
+let a = 15;
+let b = 14;
+a + b
+};
+
+fn main() -> i32 {
+X - 29
+}


[gcc/devel/rust/master] ast: Add ConstBlock and AnonConst nodes

2025-06-04 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:81836d352866d83cd9f521d65d516b125accd2dd

commit 81836d352866d83cd9f521d65d516b125accd2dd
Author: Arthur Cohen 
Date:   Wed Apr 9 18:18:30 2025 +0200

ast: Add ConstBlock and AnonConst nodes

gcc/rust/ChangeLog:

* ast/rust-expr.h: Declare AnonConst and ConstBlock and use them.
* ast/rust-ast-full-decls.h: Likewise.
* ast/rust-ast.cc: Add implementation for AnonConst and ConstBlock.
* ast/rust-ast.h: Likewise.
* ast/rust-ast-collector.cc (TokenCollector::visit): Likewise.
* ast/rust-ast-collector.h: Likewise.
* ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
* ast/rust-ast-visitor.h: Likewise.
* expand/rust-derive.h: Likewise.
* hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise.
* hir/rust-ast-lower-base.h: Likewise.
* hir/rust-ast-lower-expr.cc (translate_operand_const): Likewise.
* resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise.
* resolve/rust-ast-resolve-base.h: Likewise.
* resolve/rust-ast-resolve-expr.h: Likewise.
* resolve/rust-ast-resolve-expr.cc: Likewise.

Diff:
---
 gcc/rust/ast/rust-ast-collector.cc|  18 +++-
 gcc/rust/ast/rust-ast-collector.h |   2 +
 gcc/rust/ast/rust-ast-full-decls.h|   4 +-
 gcc/rust/ast/rust-ast-visitor.cc  |  14 ++-
 gcc/rust/ast/rust-ast-visitor.h   |   4 +
 gcc/rust/ast/rust-ast.cc  |  24 +
 gcc/rust/ast/rust-ast.h   |   2 +
 gcc/rust/ast/rust-expr.h  | 151 ++
 gcc/rust/expand/rust-derive.h |   2 +
 gcc/rust/hir/rust-ast-lower-base.cc   |   6 ++
 gcc/rust/hir/rust-ast-lower-base.h|   2 +
 gcc/rust/hir/rust-ast-lower-expr.cc   |   8 +-
 gcc/rust/resolve/rust-ast-resolve-base.cc |   8 ++
 gcc/rust/resolve/rust-ast-resolve-base.h  |   3 +
 gcc/rust/resolve/rust-ast-resolve-expr.cc |  15 ++-
 gcc/rust/resolve/rust-ast-resolve-expr.h  |   2 +
 16 files changed, 237 insertions(+), 28 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-collector.cc 
b/gcc/rust/ast/rust-ast-collector.cc
index 004b4f3831dd..709908bd5445 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -1263,6 +1263,22 @@ TokenCollector::visit (BlockExpr &expr)
   newline ();
 }
 
+void
+TokenCollector::visit (AnonConst &expr)
+{
+  visit (expr.get_inner_expr ());
+}
+
+void
+TokenCollector::visit (ConstBlock &expr)
+{
+  push (Rust::Token::make (CONST, expr.get_locus ()));
+
+  // The inner expression is already a block expr, so we don't need to add
+  // curlies
+  visit (expr.get_const_expr ());
+}
+
 void
 TokenCollector::visit (ClosureExprInnerTyped &expr)
 {
@@ -1553,7 +1569,7 @@ TokenCollector::visit (InlineAsm &expr)
break;
  }
  case RegisterType::Const: {
-   visit (operand.get_const ().anon_const.expr);
+   visit (operand.get_const ().anon_const.get_inner_expr ());
break;
  }
  case RegisterType::Sym: {
diff --git a/gcc/rust/ast/rust-ast-collector.h 
b/gcc/rust/ast/rust-ast-collector.h
index b0f1ff5fd7f1..fa835ce4c4a0 100644
--- a/gcc/rust/ast/rust-ast-collector.h
+++ b/gcc/rust/ast/rust-ast-collector.h
@@ -277,6 +277,8 @@ public:
   void visit (ClosureParam ¶m);
   void visit (ClosureExprInner &expr);
   void visit (BlockExpr &expr);
+  void visit (AnonConst &expr);
+  void visit (ConstBlock &expr);
   void visit (ClosureExprInnerTyped &expr);
   void visit (ContinueExpr &expr);
   void visit (BreakExpr &expr);
diff --git a/gcc/rust/ast/rust-ast-full-decls.h 
b/gcc/rust/ast/rust-ast-full-decls.h
index 418edd27cbc7..aabb1e4bd38d 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -115,6 +115,8 @@ struct ClosureParam;
 class ClosureExpr;
 class ClosureExprInner;
 class BlockExpr;
+class AnonConst;
+class ConstBlock;
 class ClosureExprInnerTyped;
 class ContinueExpr;
 class BreakExpr;
@@ -145,7 +147,7 @@ struct MatchCase;
 class MatchExpr;
 class AwaitExpr;
 class AsyncBlockExpr;
-struct AnonConst;
+enum class InlineAsmOption;
 struct InlineAsmRegOrRegClass;
 class InlineAsmOperand;
 struct InlineAsmPlaceHolder;
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index 8b47a81f4ed7..7caa54ba2003 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -455,6 +455,18 @@ DefaultASTVisitor::visit (AST::BlockExpr &expr)
 visit (expr.get_tail_expr ());
 }
 
+void
+DefaultASTVisitor::visit (AST::ConstBlock &expr)
+{
+  visit (expr.get_const_expr ());
+}
+
+void
+DefaultASTVisitor::visit (AST::AnonConst &expr)
+{
+  visit (expr.get_inner_expr ());
+}
+
 void
 DefaultASTVisitor::visit (AST::ClosureExprInnerTyped &expr)
 {
@@ -699,7 +711,7 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr

[gcc r16-1123] RISC-V: Update extension defination.

2025-06-04 Thread Jiawei Chen via Gcc-cvs
https://gcc.gnu.org/g:d99af4e12bf85048eeef26fb939a97e153ddee9f

commit r16-1123-gd99af4e12bf85048eeef26fb939a97e153ddee9f
Author: Jiawei 
Date:   Thu Jun 5 09:38:40 2025 +0800

RISC-V: Update extension defination.

Update the defination of RISC-V extensions in riscv-ext.def.

gcc/ChangeLog:

* config/riscv/riscv-ext.def: Update declaration.

Signed-off-by: Jiawei 

Diff:
---
 gcc/config/riscv/riscv-ext.def | 282 -
 1 file changed, 141 insertions(+), 141 deletions(-)

diff --git a/gcc/config/riscv/riscv-ext.def b/gcc/config/riscv/riscv-ext.def
index 0e989e122195..0d715a163c74 100644
--- a/gcc/config/riscv/riscv-ext.def
+++ b/gcc/config/riscv/riscv-ext.def
@@ -73,7 +73,7 @@ Format of DEFINE_RISCV_EXT:
 
 DEFINE_RISCV_EXT(
   /* NAME */ e,
-  /* UPPERCAE_NAME */ RVE,
+  /* UPPERCASE_NAME */ RVE,
   /* FULL_NAME */ "Reduced base integer extension",
   /* DESC */ "",
   /* URL */ ,
@@ -86,7 +86,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ i,
-  /* UPPERCAE_NAME */ RVI,
+  /* UPPERCASE_NAME */ RVI,
   /* FULL_NAME */ "Base integer extension",
   /* DESC */ "",
   /* URL */ ,
@@ -101,7 +101,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ m,
-  /* UPPERCAE_NAME */ MUL,
+  /* UPPERCASE_NAME */ MUL,
   /* FULL_NAME */ "Integer multiplication and division extension",
   /* DESC */ "",
   /* URL */ ,
@@ -114,7 +114,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ a,
-  /* UPPERCAE_NAME */ ATOMIC,
+  /* UPPERCASE_NAME */ ATOMIC,
   /* FULL_NAME */ "Atomic extension",
   /* DESC */ "",
   /* URL */ ,
@@ -129,7 +129,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ f,
-  /* UPPERCAE_NAME */ HARD_FLOAT,
+  /* UPPERCASE_NAME */ HARD_FLOAT,
   /* FULL_NAME */ "Single-precision floating-point extension",
   /* DESC */ "",
   /* URL */ ,
@@ -144,7 +144,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ d,
-  /* UPPERCAE_NAME */ DOUBLE_FLOAT,
+  /* UPPERCASE_NAME */ DOUBLE_FLOAT,
   /* FULL_NAME */ "Double-precision floating-point extension",
   /* DESC */ "",
   /* URL */ ,
@@ -159,7 +159,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ c,
-  /* UPPERCAE_NAME */ RVC,
+  /* UPPERCASE_NAME */ RVC,
   /* FULL_NAME */ "Compressed extension",
   /* DESC */ "",
   /* URL */ ,
@@ -183,7 +183,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ b,
-  /* UPPERCAE_NAME */ RVB,
+  /* UPPERCASE_NAME */ RVB,
   /* FULL_NAME */ "b extension",
   /* DESC */ "",
   /* URL */ ,
@@ -196,7 +196,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ v,
-  /* UPPERCAE_NAME */ RVV,
+  /* UPPERCASE_NAME */ RVV,
   /* FULL_NAME */ "Vector extension",
   /* DESC */ "",
   /* URL */ ,
@@ -209,7 +209,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ h,
-  /* UPPERCAE_NAME */ RVH,
+  /* UPPERCASE_NAME */ RVH,
   /* FULL_NAME */ "Hypervisor extension",
   /* DESC */ "",
   /* URL */ ,
@@ -222,7 +222,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ zic64b,
-  /* UPPERCAE_NAME */ ZIC64B,
+  /* UPPERCASE_NAME */ ZIC64B,
   /* FULL_NAME */ "Cache block size isf 64 bytes",
   /* DESC */ "",
   /* URL */ ,
@@ -235,7 +235,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ zicbom,
-  /* UPPERCAE_NAME */ ZICBOM,
+  /* UPPERCASE_NAME */ ZICBOM,
   /* FULL_NAME */ "Cache-block management extension",
   /* DESC */ "",
   /* URL */ ,
@@ -248,7 +248,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ zicbop,
-  /* UPPERCAE_NAME */ ZICBOP,
+  /* UPPERCASE_NAME */ ZICBOP,
   /* FULL_NAME */ "Cache-block prefetch extension",
   /* DESC */ "",
   /* URL */ ,
@@ -261,7 +261,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ zicboz,
-  /* UPPERCAE_NAME */ ZICBOZ,
+  /* UPPERCASE_NAME */ ZICBOZ,
   /* FULL_NAME */ "Cache-block zero extension",
   /* DESC */ "",
   /* URL */ ,
@@ -274,7 +274,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ ziccamoa,
-  /* UPPERCAE_NAME */ ZICCAMOA,
+  /* UPPERCASE_NAME */ ZICCAMOA,
   /* FULL_NAME */ "Main memory supports all atomics in A",
   /* DESC */ "",
   /* URL */ ,
@@ -287,7 +287,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ ziccif,
-  /* UPPERCAE_NAME */ ZICCIF,
+  /* UPPERCASE_NAME */ ZICCIF,
   /* FULL_NAME */ "Main memory supports instruction fetch with atomicity 
requirement",
   /* DESC */ "",
   /* URL */ ,
@@ -300,7 +300,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ zicclsm,
-  /* UPPERCAE_NAME */ ZICCLSM,
+  /* UPPERCASE_NAME */ ZICCLSM,
   /* FULL_NAME */ "Main memory supports misaligned loads/stores",
   /* DESC */ "",
   /* URL */ ,
@@ -313,7 +313,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ ziccrse,
-  /* UPPERCAE_NAME */ ZICCRSE,
+  /* UPPERCASE_NAME */ ZICCRSE,
   /* FULL_NAME */ "Main memory supports forward progress on LR/SC sequences",
   /* DESC */ "",
   /* URL */ ,
@@ -326,7 +326,7 @@ DEFINE_RISCV_EXT(
 
 DEFINE_RISCV_EXT(
   /* NAME */ zicfilp,
-  /* UPPERCAE_NAME */ ZICFILP,
+  /* UPPE