[gcc r16-1006] Defuse 'RESULT_DECL' check in 'pass_nrv' (for offloading compilation) [PR119835]

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:543f7e1d59f0b6628e0de6610ad5e1cf7150090b

commit r16-1006-g543f7e1d59f0b6628e0de6610ad5e1cf7150090b
Author: Thomas Schwinge 
Date:   Wed May 28 18:40:31 2025 +0200

Defuse 'RESULT_DECL' check in 'pass_nrv' (for offloading compilation) 
[PR119835]

... to avoid running into ICEs per PR119835, until that's resolved properly.

PR middle-end/119835
gcc/
* tree-nrv.cc (pass_nrv::execute): Defuse 'RESULT_DECL' check.
libgomp/
* testsuite/libgomp.oacc-c-c++-common/abi-struct-1.c:
'#pragma GCC optimize "-fno-inline"'.
* testsuite/libgomp.c-c++-common/target-abi-struct-1.c: New.
* testsuite/libgomp.c-c++-common/target-abi-struct-1-O0.c: Adjust.

Co-authored-by: Richard Biener 

Diff:
---
 gcc/tree-nrv.cc   | 19 ---
 .../libgomp.c-c++-common/target-abi-struct-1-O0.c |  2 +-
 .../libgomp.c-c++-common/target-abi-struct-1.c|  1 +
 .../libgomp.oacc-c-c++-common/abi-struct-1.c  |  6 +-
 4 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/gcc/tree-nrv.cc b/gcc/tree-nrv.cc
index 180ce39de4c5..3be97afb319e 100644
--- a/gcc/tree-nrv.cc
+++ b/gcc/tree-nrv.cc
@@ -167,16 +167,21 @@ pass_nrv::execute (function *fun)
   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
  gimple *stmt = gsi_stmt (gsi);
- tree ret_val;
 
  if (greturn *return_stmt = dyn_cast  (stmt))
{
- /* In a function with an aggregate return value, the
-gimplifier has changed all non-empty RETURN_EXPRs to
-return the RESULT_DECL.  */
- ret_val = gimple_return_retval (return_stmt);
- if (ret_val)
-   gcc_assert (ret_val == result);
+ /* We cannot perform NRV optimizations in a function with an
+aggregate return value if there is a return that does not
+return RESULT_DECL.  We used to assert this scenario doesn't
+happen: the gimplifier has changed all non-empty RETURN_EXPRs
+to return the RESULT_DECL.  However, per PR119835 we may run
+into this scenario for offloading compilation, and therefore
+gracefully bail out.  */
+ if (tree ret_val = gimple_return_retval (return_stmt))
+   {
+ if (ret_val != result)
+   return 0;
+   }
}
  else if (gimple_has_lhs (stmt)
   && gimple_get_lhs (stmt) == result)
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-abi-struct-1-O0.c 
b/libgomp/testsuite/libgomp.c-c++-common/target-abi-struct-1-O0.c
index 35ec75d648d3..9bf949a1f066 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/target-abi-struct-1-O0.c
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-abi-struct-1-O0.c
@@ -1,3 +1,3 @@
 /* { dg-additional-options -O0 } */
 
-#include "../libgomp.oacc-c-c++-common/abi-struct-1.c"
+#include "target-abi-struct-1.c"
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-abi-struct-1.c 
b/libgomp/testsuite/libgomp.c-c++-common/target-abi-struct-1.c
new file mode 100644
index ..d9268af55cfe
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-abi-struct-1.c
@@ -0,0 +1 @@
+#include "../libgomp.oacc-c-c++-common/abi-struct-1.c"
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/abi-struct-1.c 
b/libgomp/testsuite/libgomp.oacc-c-c++-common/abi-struct-1.c
index 80786555fe21..4b541711f363 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/abi-struct-1.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/abi-struct-1.c
@@ -1,6 +1,10 @@
 /* Inspired by 'gcc.target/nvptx/abi-struct-arg.c', 
'gcc.target/nvptx/abi-struct-ret.c'.  */
 
-/* See also '../libgomp.c-c++-common/target-abi-struct-1-O0.c'.  */
+/* See also '../libgomp.c-c++-common/target-abi-struct-1.c'.  */
+
+/* To exercise PR119835 (if optimizations enabled): disable inlining, so that
+   GIMPLE passes still see the functions that return aggregate types.  */
+#pragma GCC optimize "-fno-inline"
 
 typedef struct {} empty;  /* See 'gcc/doc/extend.texi', "Empty Structures".  */
 typedef struct {char a;} schar;


[gcc r13-9730] testsuite: Add testcase for GCC 13 branch s390 bug [PR120480]

2025-05-30 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:ec78a0d9962f144b13c6da3ebec1f76c61a701d5

commit r13-9730-gec78a0d9962f144b13c6da3ebec1f76c61a701d5
Author: Jakub Jelinek 
Date:   Fri May 30 14:35:12 2025 +0200

testsuite: Add testcase for GCC 13 branch s390 bug [PR120480]

This got broken with r13-9727 and fixed with either of
r13-9729 or r13-9728.

2025-05-30  Jakub Jelinek  

PR target/120480
* gcc.dg/pr120480.c: New test.

(cherry picked from commit c13d5b939fee565047394475952878dc5394fb74)

Diff:
---
 gcc/testsuite/gcc.dg/pr120480.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/pr120480.c b/gcc/testsuite/gcc.dg/pr120480.c
new file mode 100644
index ..cf7b47a1151d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120480.c
@@ -0,0 +1,11 @@
+/* PR target/120480 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+struct S { int a, b, c; } s;
+
+void
+foo (void)
+{
+  struct S t = s;
+}


[gcc r16-1004] OpenMP: Support OpenMP 5.0 "declare mapper" directives for C

2025-05-30 Thread Tobias Burnus via Gcc-cvs
https://gcc.gnu.org/g:0c8d92a9ac08d4bc4982f636a577166709312403

commit r16-1004-g0c8d92a9ac08d4bc4982f636a577166709312403
Author: Julian Brown 
Date:   Fri May 30 14:19:40 2025 +0200

OpenMP: Support OpenMP 5.0 "declare mapper" directives for C

This patch adds support for "declare mapper" directives (and the "mapper"
modifier on "map" clauses) for C.

gcc/c/ChangeLog:

* c-decl.cc (c_omp_mapper_id, c_omp_mapper_decl, 
c_omp_mapper_lookup,
c_omp_extract_mapper_directive, c_omp_map_array_section,
c_omp_scan_mapper_bindings_r, c_omp_scan_mapper_bindings): New
functions.
* c-objc-common.h (LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES,
LANG_HOOKS_OMP_MAPPER_LOOKUP, 
LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE,
LANG_HOOKS_OMP_MAP_ARRAY_SECTION): Define langhooks for C.
* c-parser.cc (c_parser_omp_clause_map): Add declare_mapper_p
parameter; handle mapper modifier.
(c_parser_omp_all_clauses): Update call to c_parser_omp_clause_map.
(c_parser_omp_target): Instantiate explicit mappers and record 
bindings
for implicit mappers.
(c_parser_omp_declare_mapper): Parse "declare mapper" directives.
(c_parser_omp_declare): Support "declare mapper".
(c_parser_omp_declare_reduction): Use inform not error_at.
* c-tree.h (c_omp_finish_mapper_clauses, c_omp_mapper_lookup,
c_omp_extract_mapper_directive, c_omp_map_array_section,
c_omp_mapper_id, c_omp_mapper_decl, c_omp_scan_mapper_bindings,
c_omp_instantiate_mappers): Add prototypes.
* c-typeck.cc (c_finish_omp_clauses): Handle 
GOMP_MAP_PUSH_MAPPER_NAME
and GOMP_MAP_POP_MAPPER_NAME.
(c_omp_finish_mapper_clauses): New function (langhook).

libgomp/ChangeLog:

* testsuite/libgomp.c-c++-common/declare-mapper-9.c: Enable for C.
* testsuite/libgomp.c-c++-common/declare-mapper-10.c: Likewise.
* testsuite/libgomp.c-c++-common/declare-mapper-11.c: Likewise.
* testsuite/libgomp.c-c++-common/declare-mapper-12.c: Likewise.
* testsuite/libgomp.c-c++-common/declare-mapper-13.c: Likewise.
* testsuite/libgomp.c-c++-common/declare-mapper-14.c: Likewise.

gcc/testsuite/ChangeLog:

* c-c++-common/gomp/declare-mapper-3.c: Enable for C.
* c-c++-common/gomp/declare-mapper-4.c: Likewise.
* c-c++-common/gomp/declare-mapper-5.c: Likewise.
* c-c++-common/gomp/declare-mapper-6.c: Likewise.
* c-c++-common/gomp/declare-mapper-7.c: Likewise.
* c-c++-common/gomp/declare-mapper-8.c: Likewise.
* c-c++-common/gomp/declare-mapper-9.c: Likewise.
* c-c++-common/gomp/declare-mapper-10.c: Likewise.
* c-c++-common/gomp/declare-mapper-12.c: Likewise.
* c-c++-common/gomp/map-6.c: Update dg-error.
* gcc.dg/gomp/udr-3.c: Update for change to dg-note.
* c-c++-common/gomp/declare-mapper-11.c: New.
* gcc.dg/gomp/declare-mapper-10.c: New test.
* gcc.dg/gomp/declare-mapper-11.c: New test.
* gcc.dg/gomp/declare-mapper-13.c: New test.

Diff:
---
 gcc/c/c-decl.cc| 168 
 gcc/c/c-objc-common.h  |  12 +
 gcc/c/c-parser.cc  | 290 +++--
 gcc/c/c-tree.h |   8 +
 gcc/c/c-typeck.cc  |  15 ++
 .../c-c++-common/gomp/declare-mapper-10.c  |   2 +-
 .../c-c++-common/gomp/declare-mapper-11.c  |  70 +
 .../c-c++-common/gomp/declare-mapper-12.c  |   2 +-
 gcc/testsuite/c-c++-common/gomp/declare-mapper-3.c |   2 +-
 gcc/testsuite/c-c++-common/gomp/declare-mapper-4.c |   2 +-
 gcc/testsuite/c-c++-common/gomp/declare-mapper-5.c |   6 +-
 gcc/testsuite/c-c++-common/gomp/declare-mapper-6.c |   2 +-
 gcc/testsuite/c-c++-common/gomp/declare-mapper-7.c |   2 +-
 gcc/testsuite/c-c++-common/gomp/declare-mapper-8.c |   2 +-
 gcc/testsuite/c-c++-common/gomp/declare-mapper-9.c |   6 +-
 gcc/testsuite/c-c++-common/gomp/map-6.c|  10 +-
 gcc/testsuite/gcc.dg/gomp/declare-mapper-10.c  |  61 +
 gcc/testsuite/gcc.dg/gomp/declare-mapper-11.c  |  33 +++
 gcc/testsuite/gcc.dg/gomp/declare-mapper-13.c  |  13 +
 gcc/testsuite/gcc.dg/gomp/udr-3.c  |   8 +-
 .../libgomp.c-c++-common/declare-mapper-10.c   |   2 +-
 .../libgomp.c-c++-common/declare-mapper-11.c   |   2 +-
 .../libgomp.c-c++-common/declare-mapper-12.c   |   2 +-
 .../libgomp.c-c++-common/declare-mapper-13.c   |   2 +-
 .../libgomp.c-c++-common/declare-mapper-14.c   |   2 +-
 .../libgomp.c-c++-common/declare-mapper-9.c|   2 +-
 26 files changed, 679 insertions(+), 47 deleti

[gcc r16-1016] libstdc++: Test for formatting with empty spec for calendar types.

2025-05-30 Thread Tomasz Kaminski via Gcc-cvs
https://gcc.gnu.org/g:28a17985dd34b7ad154c6fcd399ce10616db7a92

commit r16-1016-g28a17985dd34b7ad154c6fcd399ce10616db7a92
Author: Tomasz Kamiński 
Date:   Fri May 30 11:31:35 2025 +0200

libstdc++: Test for formatting with empty spec for calendar types.

Adding a test for behavior of the ostream operator and the formatting
with empty chron-spec for the chrono types. This commit covers calendar
types.

libstdc++-v3/ChangeLog:

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

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

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

diff --git a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc 
b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
new file mode 100644
index ..322faa1939d9
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
@@ -0,0 +1,301 @@
+// { dg-do run { target c++20 } }
+// { dg-timeout-factor 2 }
+
+#include 
+#include 
+#include 
+
+using namespace std::chrono;
+
+#define WIDEN_(C, S) ::std::__format::_Widen(S, L##S)
+#define WIDEN(S) WIDEN_(_CharT, S)
+
+template
+void
+test_padding()
+{
+  std::basic_string<_CharT> res;
+
+  res = std::format(WIDEN("{:5}"), day(2));
+  VERIFY( res == WIDEN("02   ") );
+
+  res = std::format(WIDEN("{:>6}"), weekday(4));
+  VERIFY( res == WIDEN("   Thu") );
+
+  res = std::format(WIDEN("{:^7}"), month(3));
+  VERIFY( res == WIDEN("  Mar  ") );
+
+  res = std::format(WIDEN("{:-<4}"), day(30));
+  VERIFY( res == WIDEN("30--") );
+
+  res = std::format(WIDEN("{:+>30}"), weekday(9));
+  VERIFY( res == WIDEN("++9 is not a valid weekday") );
+
+  res = std::format(WIDEN("{:=^27}"), month(16));
+  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
+void
+test_day()
+{
+  verify( day(0),   WIDEN("00 is not a valid day") );
+  verify( day(1),   WIDEN("01") );
+  verify( day(10),  WIDEN("10") );
+  verify( day(32),  WIDEN("32 is not a valid day") );
+  verify( day(110), WIDEN("110 is not a valid day") );
+  verify( day(255), WIDEN("255 is not a valid day") );
+}
+
+template
+void
+test_month()
+{
+  verify( month(0),   WIDEN("0 is not a valid month") );
+  verify( month(1),   WIDEN("Jan") );
+  verify( month(10),  WIDEN("Oct") );
+  verify( month(32),  WIDEN("32 is not a valid month") );
+  verify( month(110), WIDEN("110 is not a valid month") );
+  verify( month(100), WIDEN("100 is not a valid month") );
+  verify( month(110), WIDEN("110 is not a valid month") );
+  verify( month(255), WIDEN("255 is not a valid month") );
+}
+
+template
+void
+test_year()
+{
+  verify( year(-32768), WIDEN("-32768 is not a valid year") );
+  verify( year(-32767), WIDEN("-32767") );
+  verify( year(-67),WIDEN( "-0067") );
+  verify( year(-1), WIDEN( "-0001") );
+  verify( year(0),  WIDEN(  "") );
+  verify( year(1),  WIDEN(  "0001") );
+  verify( year(123),WIDEN(  "0123") );
+  verify( year(2025),   WIDEN(  "2025") );
+  verify( year(32767),  WIDEN( "32767") );
+}
+
+template
+void
+test_weekday()
+{
+  verify( weekday(0),   WIDEN("Sun") );
+  verify( weekday(2),   WIDEN("Tue") );
+  verify( weekday(6),   WIDEN("Sat") );
+  verify( weekday(7),   WIDEN("Sun") );
+  verify( weekday(9),   WIDEN("9 is not a valid weekday") );
+  verify( weekday(32),  WIDEN("32 is not a valid weekday") );
+  verify( weekday(110), WIDEN("110 is not a valid weekday") );
+  verify( weekday(255), WIDEN("255 is not a valid weekday") );
+}
+
+template
+void
+test_weekday_indexed()
+{
+  verify( weekday(0)[0],   WIDEN("Sun[0 is not a valid index]") );
+  verify( weekday(2)[1],   WIDEN("Tue[1]") );
+  verify( weekday(6)[5],   WIDEN("Sat[5]") );
+  verify( weekday(7)[6],   WIDEN("Sun[6 is not a valid index]") );
+  verify( weekday(7)[12],  WIDEN("Sun[12 is not a valid index]") );
+  verify( weekday(5)[117], WIDEN("Fri[117 is not a valid index]") );
+  verify( weekday(7)[255], WIDEN("Sun[255 is not a valid index]") );
+  verify( weekday(9)[1],   WIDEN("9 is not a valid weekday[1]") );
+  verify( weekday(32)[7],  WIDEN("32 is not a valid weekday[7 is not a valid 
index]") );
+}
+
+template
+void
+test_weekday_last()
+{
+  verify( weekday(0)[last], WIDEN("Sun[last]") );
+  verify( weekday(9)[last], WIDEN("9 is not a valid weekday[last]") );
+}
+
+template
+void
+test_month_day()
+{
+  verify( month(1)/30,  WIDEN("Jan/30") );
+  verify( month(3)/32,  WIDEN("Mar/32 is not a valid day") );
+  verify( month(13)/30, WIDEN("13 is not a valid month/30") );
+  verify( month(13)/32, WIDEN("13 is not a valid month/32 is not a valid day") 
);
+}
+
+template
+void
+test_month_day_last()
+

[gcc r16-1017] C: Flex array in the middle via type alias is not reported [PR120353]

2025-05-30 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:f37c5f1d88c9da17f16cdb33e7c9d43e4bb5f64d

commit r16-1017-gf37c5f1d88c9da17f16cdb33e7c9d43e4bb5f64d
Author: Qing Zhao 
Date:   Wed May 28 21:13:38 2025 +

C: Flex array in the middle via type alias is not reported [PR120353]

The root cause of the bug is: the TYPE_INCLUDES_FLEXARRAY marking of the
structure type is not copied to its aliased type.
The fix is to copy this marking to all the variant types of the current
structure type.

PR c/120353

gcc/c/ChangeLog:

* c-decl.cc (finish_struct): Copy TYPE_INCLUDES_FLEXARRAY marking
to all the variant types of the current structure type.

gcc/testsuite/ChangeLog:

* gcc.dg/pr120353.c: New test.

Diff:
---
 gcc/c/c-decl.cc |  1 +
 gcc/testsuite/gcc.dg/pr120353.c | 11 +++
 2 files changed, 12 insertions(+)

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index e10f9c1ea7b6..38de96e12876 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9893,6 +9893,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
tree attributes,
   C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t);
   C_TYPE_VARIABLY_MODIFIED (x) = C_TYPE_VARIABLY_MODIFIED (t);
   C_TYPE_INCOMPLETE_VARS (x) = NULL_TREE;
+  TYPE_INCLUDES_FLEXARRAY (x) = TYPE_INCLUDES_FLEXARRAY (t);
 }
 
   /* Update type location to the one of the definition, instead of e.g.
diff --git a/gcc/testsuite/gcc.dg/pr120353.c b/gcc/testsuite/gcc.dg/pr120353.c
new file mode 100644
index ..6f8e4acf7f26
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120353.c
@@ -0,0 +1,11 @@
+/* PR120353: Test for -Wflex-array-member-not-at-end on structure with 
+   typedef.  */ 
+/* { dg-do compile } */
+/* { dg-options "-Wflex-array-member-not-at-end" } */
+
+typedef struct flex flex_t;
+struct flex { int n; int data[]; };
+struct out_flex_mid {flex_t flex_data;  int m; }; /* { dg-warning "structure 
containing a flexible array member is not at the end of another structure" } */
+
+typedef struct flex flex_t1;
+struct out_flex_mid1 {flex_t1 flex_data1; int n; }; /* { dg-warning "structure 
containing a flexible array member is not at the end of another structure" } */


[gcc r16-1018] C: Flex array in union followed by a structure field is not reported [PR120354]

2025-05-30 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:70418e6c0120cfce33ab69628602dfdadbed683a

commit r16-1018-g70418e6c0120cfce33ab69628602dfdadbed683a
Author: Qing Zhao 
Date:   Thu May 29 15:59:41 2025 +

C: Flex array in union followed by a structure field is not reported 
[PR120354]

There is only one last_field for a structure type, but there might
be multiple last_fields for a union type, therefore we should ORed
the result of TYPE_INCLUDES_FLEXARRAY for multiple last_fields of
a union type.

PR c/120354

gcc/c/ChangeLog:

* c-decl.cc (finish_struct): Or the results for 
TYPE_INCLUDES_FLEXARRAY.

gcc/testsuite/ChangeLog:

* gcc.dg/pr120354.c: New test.

Diff:
---
 gcc/c/c-decl.cc |  9 ++---
 gcc/testsuite/gcc.dg/pr120354.c | 33 +
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 38de96e12876..1008bcaebdc9 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9649,15 +9649,18 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
tree attributes,
   DECL_NOT_FLEXARRAY (x) = !is_flexible_array_member_p (is_last_field, x);
 
   /* Set TYPE_INCLUDES_FLEXARRAY for the context of x, t.
-when x is an array and is the last field.  */
+when x is an array and is the last field.
+There is only one last_field for a structure type, but there might
+be multiple last_fields for a union type, therefore we should ORed
+the result for multiple last_fields.  */
   if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
TYPE_INCLUDES_FLEXARRAY (t)
- = is_last_field && c_flexible_array_member_type_p (TREE_TYPE (x));
+ |= is_last_field && c_flexible_array_member_type_p (TREE_TYPE (x));
   /* Recursively set TYPE_INCLUDES_FLEXARRAY for the context of x, t
 when x is an union or record and is the last field.  */
   else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
TYPE_INCLUDES_FLEXARRAY (t)
- = is_last_field && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (x));
+ |= is_last_field && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (x));
 
   if (warn_flex_array_member_not_at_end
  && !is_last_field
diff --git a/gcc/testsuite/gcc.dg/pr120354.c b/gcc/testsuite/gcc.dg/pr120354.c
new file mode 100644
index ..6749737a1737
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120354.c
@@ -0,0 +1,33 @@
+/* PR120354: Test for -Wflex-array-member-not-at-end on union with 
+   flexible array members.  */ 
+/* { dg-do compile } */
+/* { dg-options "-Wflex-array-member-not-at-end" } */
+
+struct P {};
+union L {};
+
+union X {
+int x[];
+struct P y;
+};
+
+struct T {
+union X x; /* { dg-warning "structure containing a flexible array member 
is not at the end of another structure" } */
+int plug;
+};
+
+struct Q {
+int len;
+int data[];
+};
+
+union Y {
+struct Q q;
+union L y;
+};
+
+struct S {
+union Y y;  /* { dg-warning "structure containing a flexible array member 
is not at the end of another structure" } */
+int plug;
+};
+


[gcc r16-984] rtl-ssa: Reject non-address uses of autoinc regs [PR120347]

2025-05-30 Thread Richard Sandiford via Gcc-cvs
https://gcc.gnu.org/g:e322dff09d011f65f5cae4e95c3a24ccfae7b1e1

commit r16-984-ge322dff09d011f65f5cae4e95c3a24ccfae7b1e1
Author: Richard Sandiford 
Date:   Fri May 30 09:36:35 2025 +0100

rtl-ssa: Reject non-address uses of autoinc regs [PR120347]

As the rtl.texi documentation of RTX_AUTOINC expressions says:

  If a register used as the operand of these expressions is used in
  another address in an insn, the original value of the register is
  used.  Uses of the register outside of an address are not permitted
  within the same insn as a use in an embedded side effect expression
  because such insns behave differently on different machines and hence
  must be treated as ambiguous and disallowed.

late-combine was failing to follow this rule.  One option would have
been to enforce it during the substitution phase, like combine does.
This could either be a dedicated condition in the substitution code
or, more generally, an extra condition in can_merge_accesses.
(The latter would include extending is_pre_post_modify to uses.)

However, since the restriction applies to patterns rather than to
actions on patterns, the more robust fix seemed to be test and reject
this case in (a subroutine of) rtl_ssa::recog.  We already do something
similar for hard-coded register clobbers.

Using vec_rtx_properties isn't the lightest-weight operation
out there.  I did wonder about relying on the is_pre_post_modify
flag of the definitions in the new_defs array, but that would
require callers that create new autoincs to set the flag before
calling recog.  Normally these flags are instead updated
automatically based on the final pattern.

Besides, recog itself has had to traverse the whole pattern,
and it is even less light-weight than vec_rtx_properties.
At least the pattern should be in cache.

The rtl-ssa fix showed up a mistake (of mine) in the rtl_properties
walker: try_to_add_src would drop all flags except IN_NOTE before
recursing into RTX_AUTOINC addresses.

RTX_AUTOINCs only occur in addresses, and so for them, the flags coming
into try_to_add_src are set by:

  unsigned int base_flags = flags & rtx_obj_flags::STICKY_FLAGS;
  ...
  if (MEM_P (x))
{
  ...

  unsigned int addr_flags = base_flags | rtx_obj_flags::IN_MEM_STORE;
  if (flags & rtx_obj_flags::IS_READ)
addr_flags |= rtx_obj_flags::IN_MEM_LOAD;
  try_to_add_src (XEXP (x, 0), addr_flags);
  return;
}

This means that the only flags that can be set are:

- IN_NOTE (the sole member of STICKY_FLAGS)
- IN_MEM_STORE
- IN_MEM_LOAD

Thus dropping all flags except IN_NOTE had the effect of dropping
IN_MEM_STORE and IN_MEM_LOAD, and nothing else.  But those flags
are the ones that mark something as being part of a mem address.
The exclusion was therefore exactly wrong.

gcc/
PR rtl-optimization/120347
* rtlanal.cc (rtx_properties::try_to_add_src): Don't drop the
IN_MEM_LOAD and IN_MEM_STORE flags for autoinc registers.
* rtl-ssa/changes.cc (recog_level2): Check whether an
RTX_AUTOINCed register also appears outside of an address.

gcc/testsuite/
PR rtl-optimization/120347
* gcc.dg/torture/pr120347.c: New test.

Diff:
---
 gcc/rtl-ssa/changes.cc  | 18 ++
 gcc/rtlanal.cc  |  2 +-
 gcc/testsuite/gcc.dg/torture/pr120347.c | 13 +
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc
index eb579ad3ad7e..f7aa6a66cdf5 100644
--- a/gcc/rtl-ssa/changes.cc
+++ b/gcc/rtl-ssa/changes.cc
@@ -1106,6 +1106,24 @@ recog_level2 (insn_change &change, add_regno_clobber_fn 
add_regno_clobber)
}
}
 
+  // Per rtl.texi, registers that are modified using RTX_AUTOINC operations
+  // cannot also appear outside an address.
+  vec_rtx_properties properties;
+  properties.add_pattern (pat);
+  for (rtx_obj_reference def : properties.refs ())
+if (def.is_pre_post_modify ())
+  for (rtx_obj_reference use : properties.refs ())
+   if (def.regno == use.regno && !use.in_address ())
+ {
+   if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+   fprintf (dump_file, "register %d is both auto-modified"
+" and used outside an address:\n", def.regno);
+   print_rtl_single (dump_file, pat);
+ }
+   return false;
+ }
+
   // check_asm_operands checks the constraints after RA, so we don't
   // need to do it again.
   if (reload_completed && !asm_p)
diff --git a/gcc/rtlanal.cc b/gcc/rtlanal.cc
index 86a5e4733088..900f53e252a9 100644
--- a/gcc/rtlanal.cc
+++ b/gcc/rtlanal.cc
@@

[gcc r16-985] libstdc++: Atomic wait/notify ABI stabilization

2025-05-30 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:437c147f72eab2839277d0a659b7ea833d8c102d

commit r16-985-g437c147f72eab2839277d0a659b7ea833d8c102d
Author: Thomas Rodgers 
Date:   Wed Apr 12 17:49:27 2023 -0700

libstdc++: Atomic wait/notify ABI stabilization

This represents a major refactoring of the previous atomic::wait
and atomic::notify implementation detail. The aim of this change
is to simplify the implementation details and position the resulting
implementation so that much of the current header-only detail
can be moved into the shared library, while also accounting for
anticipated changes to wait/notify functionality for C++26.

The previous implementation implemented spin logic in terms of
the types __default_spin_policy, __timed_backoff_spin_policy, and
the free function __atomic_spin. These are replaced in favor of
two new free functions; __spin_impl and __spin_until_impl. These
currently inline free functions are expected to be moved into the
libstdc++ shared library in a future commit.

The previous implementation derived untimed and timed wait
implementation detail from __detail::__waiter_pool_base. This
is-a relationship is removed in the new version and the previous
implementation detail is renamed to reflect this change. The
static _S_for member has been renamed as well to indicate that it
returns the __waiter_pool_impl entry in the static 'side table'
for a given awaited address.

This new implementation replaces all of the non-templated waiting
detail of __waiter_base, __waiter_pool, __waiter, __enters_wait, and
__bare_wait with the __wait_impl free function, and the supporting
__wait_flags enum and __wait_args struct. This currenly inline free
function is expected to be moved into the libstdc++ shared library
in a future commit.

This new implementation replaces all of the non-templated notifying
detail of __waiter_base, __waiter_pool, and __waiter with the
__notify_impl free function. This currently inline free function
is expected to be moved into the libstdc++ shared library in a
future commit.

The __atomic_wait_address template function is updated to account
for the above changes and to support the expected C++26 change to
pass the most recent observed value to the caller supplied predicate.

A new non-templated __atomic_wait_address_v free function is added
that only works for atomic types that operate only on __platform_wait_t
and requires the caller to supply a memory order. This is intended
to be the simplest code path for such types.

The __atomic_wait_address_v template function is now implemented in
terms of new __atomic_wait_address template and continues to accept
a user supplied "value function" to retrieve the current value of
the atomic.

The __atomic_notify_address template function is updated to account
for the above changes.

The template __platform_wait_until_impl is renamed to
__wait_clock_t. The previous __platform_wait_until template is deleted
and the functionality previously provided is moved t the new tempalate
function __wait_until. A similar change is made to the
__cond_wait_until_impl/__cond_wait_until implementation.

This new implementation similarly replaces all of the non-templated
waiting detail of __timed_waiter_pool, __timed_waiter, etc. with
the new __wait_until_impl free function. This currently inline free
function is expected to be moved into the libstdc++ shared library
in a future commit.

This implementation replaces all templated waiting functions that
manage clock conversion as well as relative waiting (wait_for) with
the new template functions __wait_until and __wait_for.

Similarly the previous implementation detail for the various
__atomic_wait_address_Xxx templates is adjusted to account for the
implementation changes outlined above.

All of the "bare wait" versions of __atomic_wait_Xxx have been removed
and replaced with a defaulted boolean __bare_wait parameter on the
new version of these templates.

libstdc++-v3/ChangeLog:

* include/bits/atomic_timed_wait.h:
(__detail::__platform_wait_until_impl): Rename to
__platform_wait_until.
(__detail::__platform_wait_until): Remove previous
definition.
(__detail::__cond_wait_until_impl): Rename to
__cond_wait_until.
(__detail::__cond_wait_until): Remove previous
definition.
(__detail::__spin_until_impl): New function.
(__detail::__wait_until_impl): New function.
(__detail::__wait_until): New function.
(__detail::__wait_for): New function.
(__detail::__timed_waiter_pool): Remove type.
(__detail::__timed_backoff_spin_policy): Remo

[gcc r16-986] libstdc++: Pass __wait_args to internal API by const pointer

2025-05-30 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:e071cd60347d81c52aa5815e0308264ce190ffc8

commit r16-986-ge071cd60347d81c52aa5815e0308264ce190ffc8
Author: Thomas Rodgers 
Date:   Mon Apr 24 14:06:09 2023 -0700

libstdc++: Pass __wait_args to internal API by const pointer

This change splits the __wait_args data members to a new struct
__wait_args_base and then passes that type by const pointer to the low
level implementation functions.

libstdc++-v3/ChangeLog:

* include/bits/atomic_timed_wait.h (__spin_until_impl): Accept
__wait_args as const __wait_args_base*.
(__wait_until_impl): Likewise.
(__wait_until): Likewise.
(__wait_for): Likewise.
(__atomic_wait_address_until): Pass __wait_args by address.
(__atomic_wait_address_for): Likewise.
* include/bits/atomic_wait.h (__wait_args_base): New struct.
(__wait_args): Derive from __wait_args_base.
(__wait_args::__wait_args()): Adjust ctors to call call base ctor.
(__wait_args::__wait_args(const __wait_args_base&)): New ctor.
(__wait_args::operator|=): New method.
(__wait_args::_S_flags_for): Change return type to
__wait_flags.
(__spin_impl): Accept __wait_args as const __wait_args_base*.
(__wait_impl): Likewise.
(__notify_impl): Likewise.
(__atomic_wait_address): Pass __wait_args by address.
(__atomic_wait_address_v): Likewise.
(__atomic_notify_address): Likewise.

Diff:
---
 libstdc++-v3/include/bits/atomic_timed_wait.h | 35 +--
 libstdc++-v3/include/bits/atomic_wait.h   | 62 ++-
 2 files changed, 64 insertions(+), 33 deletions(-)

diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h 
b/libstdc++-v3/include/bits/atomic_timed_wait.h
index 196548484024..4504b1b84bb8 100644
--- a/libstdc++-v3/include/bits/atomic_timed_wait.h
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -135,9 +135,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif // _GLIBCXX_HAS_GTHREADS
 
 inline __wait_result_type
-__spin_until_impl(const __platform_wait_t* __addr, __wait_args __args,
+__spin_until_impl(const __platform_wait_t* __addr,
+ const __wait_args_base* __a,
  const __wait_clock_t::time_point& __deadline)
 {
+  __wait_args __args{ *__a };
   auto __t0 = __wait_clock_t::now();
   using namespace literals::chrono_literals;
 
@@ -163,7 +165,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
else
{
- auto __res = __detail::__spin_impl(__addr, __args);
+ auto __res = __detail::__spin_impl(__addr, __a);
  if (__res.first)
return __res;
}
@@ -176,9 +178,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 }
 
 inline __wait_result_type
-__wait_until_impl(const __platform_wait_t* __addr, __wait_args __args,
+__wait_until_impl(const __platform_wait_t* __addr,
+ const __wait_args_base* __a,
  const __wait_clock_t::time_point& __atime)
 {
+  __wait_args __args{ *__a };
 #ifdef _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT
   __waiter_pool_impl* __pool = nullptr;
 #else
@@ -200,7 +204,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   if (__args & __wait_flags::__do_spin)
{
- auto __res = __detail::__spin_until_impl(__wait_addr, __args, 
__atime);
+ auto __res = __detail::__spin_until_impl(__wait_addr, __a, __atime);
  if (__res.first)
return __res;
  if (__args & __wait_flags::__spin_only)
@@ -246,7 +250,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 template
   __wait_result_type
-  __wait_until(const __platform_wait_t* __addr, __wait_args __args,
+  __wait_until(const __platform_wait_t* __addr, const __wait_args* __args,
   const chrono::time_point<_Clock, _Dur>& __atime) noexcept
   {
if constexpr (is_same_v<__wait_clock_t, _Clock>)
@@ -269,15 +273,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 template
   __wait_result_type
-  __wait_for(const __platform_wait_t* __addr, __wait_args __args,
+  __wait_for(const __platform_wait_t* __addr, const __wait_args_base* __a,
 const chrono::duration<_Rep, _Period>& __rtime) noexcept
 {
+  __wait_args __args{ *__a };
   if (!__rtime.count())
-   // no rtime supplied, just spin a bit
-   return __detail::__wait_impl(__addr, __args | 
__wait_flags::__spin_only);
+   {
+ // no rtime supplied, just spin a bit
+ __args |= __wait_flags::__spin_only;
+ return __detail::__wait_impl(__addr, &__args);
+   }
+
   auto const __reltime = chrono::ceil<__wait_clock_t::duration>(__rtime);
   auto const __atime = chrono::steady_clock::now() + __reltime;
-  return __detail::__wait_until(__addr, __args, __atime);
+  return __detail::__wait

[gcc r16-987] libstdc++: Whitespace fixes in atomic wait/notify code

2025-05-30 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:8e2c4d22fcbcd3c98268fcb9756899c3703839dd

commit r16-987-g8e2c4d22fcbcd3c98268fcb9756899c3703839dd
Author: Jonathan Wakely 
Date:   Thu Jan 9 23:09:03 2025 +

libstdc++: Whitespace fixes in atomic wait/notify code

libstdc++-v3/ChangeLog:

* include/bits/atomic_timed_wait.h: Whitespace fixes.
* include/bits/atomic_wait.h: Likewise.

Diff:
---
 libstdc++-v3/include/bits/atomic_timed_wait.h | 208 +-
 libstdc++-v3/include/bits/atomic_wait.h   |   8 +-
 2 files changed, 105 insertions(+), 111 deletions(-)

diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h 
b/libstdc++-v3/include/bits/atomic_timed_wait.h
index 4504b1b84bb8..e5a5f283bca0 100644
--- a/libstdc++-v3/include/bits/atomic_timed_wait.h
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -101,8 +101,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  if (errno != EINTR && errno != EAGAIN)
__throw_system_error(errno);
}
-   return true;
-  }
+  return true;
+}
 #else
 // define _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT and implement 
__platform_wait_until()
 // if there is a more efficient primitive supported by the platform
@@ -115,23 +115,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 __cond_wait_until(__condvar& __cv, mutex& __mx,
  const __wait_clock_t::time_point& __atime)
 {
-   auto __s = chrono::time_point_cast(__atime);
-   auto __ns = chrono::duration_cast(__atime - __s);
+  auto __s = chrono::time_point_cast(__atime);
+  auto __ns = chrono::duration_cast(__atime - __s);
 
-   __gthread_time_t __ts =
- {
-   static_cast(__s.time_since_epoch().count()),
-   static_cast(__ns.count())
- };
+  __gthread_time_t __ts =
+   {
+ static_cast(__s.time_since_epoch().count()),
+ static_cast(__ns.count())
+   };
 
 #ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
-   if constexpr (is_same_v)
- __cv.wait_until(__mx, CLOCK_MONOTONIC, __ts);
-   else
+  if constexpr (is_same_v)
+   __cv.wait_until(__mx, CLOCK_MONOTONIC, __ts);
+  else
 #endif
- __cv.wait_until(__mx, __ts);
-   return __wait_clock_t::now() < __atime;
-  }
+   __cv.wait_until(__mx, __ts);
+  return __wait_clock_t::now() < __atime;
+}
 #endif // _GLIBCXX_HAS_GTHREADS
 
 inline __wait_result_type
@@ -146,34 +146,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   __platform_wait_t __val;
   auto __now = __wait_clock_t::now();
   for (; __now < __deadline; __now = __wait_clock_t::now())
-  {
-   auto __elapsed = __now - __t0;
-#ifndef _GLIBCXX_NO_SLEEP
-   if (__elapsed > 128ms)
-   {
- this_thread::sleep_for(64ms);
-   }
-   else if (__elapsed > 64us)
{
- this_thread::sleep_for(__elapsed / 2);
-   }
-   else
+ auto __elapsed = __now - __t0;
+#ifndef _GLIBCXX_NO_SLEEP
+ if (__elapsed > 128ms)
+   this_thread::sleep_for(64ms);
+ else if (__elapsed > 64us)
+   this_thread::sleep_for(__elapsed / 2);
+ else
 #endif
-   if (__elapsed > 4us)
-   {
- __thread_yield();
-   }
-   else
-   {
- auto __res = __detail::__spin_impl(__addr, __a);
- if (__res.first)
-   return __res;
-   }
+ if (__elapsed > 4us)
+   __thread_yield();
+ else
+   {
+ auto __res = __detail::__spin_impl(__addr, __a);
+ if (__res.first)
+   return __res;
+   }
 
-   __atomic_load(__addr, &__val, __args._M_order);
-   if (__val != __args._M_old)
-   return make_pair(true, __val);
-  }
+ __atomic_load(__addr, &__val, __args._M_order);
+ if (__val != __args._M_old)
+ return make_pair(true, __val);
+   }
   return make_pair(false, __val);
 }
 
@@ -212,14 +206,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
 
   if (!(__args & __wait_flags::__track_contention))
-  {
-   // caller does not externally track contention
+   {
+ // caller does not externally track contention
 #ifdef _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT
-   __pool = (__pool == nullptr) ? &__waiter_pool_impl::_S_impl_for(__addr)
-: __pool;
+ __pool = (__pool == nullptr) ? 
&__waiter_pool_impl::_S_impl_for(__addr)
+  : __pool;
 #endif
-   __pool->_M_enter_wait();
-  }
+ __pool->_M_enter_wait();
+   }
 
   __wait_result_type __res;
 #ifdef _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT
@@ -232,19 +226,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   __atomic_load(__wait_addr, &__val, __args._M_order);
   if (__val == __args._M_old)
{
-  lock_guard __l{ __pool->_M_mtx };
-  __atomic_load(__wait_addr, &__val, __args._M_order);
-  if (__val == __args._M_old &&
- 

[gcc r16-995] libstdc++: Move atomic wait/notify entry points into the library

2025-05-30 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:da9b2ea04c084ddf440ad9cbfd3bce03be6d27ef

commit r16-995-gda9b2ea04c084ddf440ad9cbfd3bce03be6d27ef
Author: Jonathan Wakely 
Date:   Sat Jan 18 21:00:36 2025 +

libstdc++: Move atomic wait/notify entry points into the library

This moves the implementation details of atomic wait/notify functions
into the library, so that only a small API surface is exposed to users.

This also fixes some race conditions present in the design for proxied
waits:

- The stores to _M_ver in __notify_impl must be protected by the mutex,
  and the loads from _M_ver in __wait_impl and __wait_until_impl to
  check for changes must also be protected by the mutex. This ensures
  that checking _M_ver for updates and waiting on the condition_variable
  happens atomically. Otherwise it's possible to have: _M_ver == old
  happens-before {++_M_ver; cv.notify;} which happens-before cv.wait.
  That scenario results in a missed notification, and so the waiting
  function never wakes. This wasn't a problem for Linux, because the
  futex wait call re-checks the _M_ver value before sleeping, so the
  increment cannot interleave between the check and the wait.

- The initial load from _M_ver that reads the 'old' value used for the
  _M_ver == old checks must be done before loading and checking the
  value of the atomic variable. Otherwise it's possible to have:
  var.load() == val happens-before {++_M_ver; _M_cv.notify_all();}
  happens-before {old = _M_ver; lock mutex; if (_M_ver == old) cv.wait}.
  This results in the waiting thread seeing the already-incremented
  value of _M_ver and then waiting for it to change again, which doesn't
  happen. This race was present even for Linux, because using a futex
  instead of mutex+condvar doesn't prevent the increment from happening
  before the waiting threads checks for the increment.

The first race can be solved locally in the waiting and notifying
functions, by acquiring the mutex lock earlier in the function. The
second race cannot be fixed locally, because the load of the atomic
variable and the check for updates to _M_ver happen in different
functions (one in a function template in the headers and one in the
library). We do have an _M_old data member in the __wait_args_base
struct which was previously only used for non-proxy waits using a futex.
We can add a new entry point into the library to look up the waitable
state for the address and then load its _M_ver into the _M_old member.
This allows the inline function template to ensure that loading _M_ver
happens-before testing whether the atomic variable has been changed, so
that we can reliably tell if _M_ver changes after we've already tested
the atomic variable. This isn't 100% reliable, because _M_ver could be
incremented 2^32 times and wrap back to the same value, but that seems
unlikely in practice. If/when we support waiting on user-defined
predicates (which could execute long enough for _M_ver to wrap) we might
want to always wait with a timeout, so that we get a chance to re-check
the predicate even in the rare case that _M_ver wraps.

Another change is to make the __wait_until_impl function take a
__wait_clock_t::duration instead of a __wait_clock_t::time_point, so
that the __wait_until_impl function doesn't depend on the symbol name of
chrono::steady_clock. Inside the library it can be converted back to a
time_point for the clock. This would potentially allow using a different
clock, if we made a different __abi_version in the __wait_args imply
waiting with a different clock.

This also adds a void* to the __wait_args_base structure, so that
__wait_impl can store the __waitable_state* in there the first time it's
looked up for a given wait, so that it doesn't need to be retrieved
again on each loop. This requires passing the __wait_args_base structure
by non-const reference.

The __waitable_state::_S_track function can be removed now that it's all
internal to the library, and namespace-scope RAII types added for
locking and tracking contention.

libstdc++-v3/ChangeLog:

* config/abi/pre/gnu.ver: Add new symbol version and exports.
* include/bits/atomic_timed_wait.h (__platform_wait_until): Move
to atomic.cc.
(__cond_wait_until, __spin_until_impl): Likewise.
(__wait_until_impl): Likewise. Change __wait_args_base parameter
to non-const reference and change third parameter to
__wait_clock_t::duration.
(__wait_until): Change __wait_args_base parameter to non-const
reference. Change Call time_since_epoch() to get duration from
time_point.
(__wait_for): Change __wait_args_base parameter to non-const
ref

[gcc r16-996] libstdc++: Optimise std::latch::arrive_and_wait

2025-05-30 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:88e41d761e02f77345ad88b42500e2ef3861c245

commit r16-996-g88e41d761e02f77345ad88b42500e2ef3861c245
Author: Jonathan Wakely 
Date:   Thu Jan 9 22:03:15 2025 +

libstdc++: Optimise std::latch::arrive_and_wait

We don't need to wait if we know the counter has reached zero.

libstdc++-v3/ChangeLog:

* include/std/latch (latch::arrive_and_wait): Optimise.

Diff:
---
 libstdc++-v3/include/std/latch | 17 +++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/std/latch b/libstdc++-v3/include/std/latch
index 52a2b1489f6a..9504df0a7224 100644
--- a/libstdc++-v3/include/std/latch
+++ b/libstdc++-v3/include/std/latch
@@ -101,8 +101,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 _GLIBCXX_ALWAYS_INLINE void
 arrive_and_wait(ptrdiff_t __update = 1) noexcept
 {
-  count_down(__update);
-  wait();
+  // The standard specifies this functions as count_down(update); wait();
+  // but we combine those two calls into one and avoid the wait() if we
+  // know the counter reached zero.
+
+  __glibcxx_assert(__update >= 0 && __update <= max());
+  // Use acq_rel here because an omitted wait() would have used acquire:
+  auto const __old = __atomic_impl::fetch_sub(&_M_counter, __update,
+ memory_order::acq_rel);
+  if (std::cmp_equal(__old, __update))
+   __atomic_impl::notify_all(&_M_counter);
+  else
+   {
+ __glibcxx_assert(std::cmp_less(__update, __old));
+ wait();
+   }
 }
 
   private:


[gcc r16-999] libstdc++: Rewrite std::counting_semaphore base class [PR118494]

2025-05-30 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:3e9fff1b7f9a31e6bc635880b09cbc32f8be353d

commit r16-999-g3e9fff1b7f9a31e6bc635880b09cbc32f8be353d
Author: Jonathan Wakely 
Date:   Wed Jan 15 09:05:28 2025 +

libstdc++: Rewrite std::counting_semaphore base class [PR118494]

Remove __platform_semaphore. Replace __atomic_semaphore with
__semaphore_base and change its counter to be ptrdiff_t when the
count doesn't fit in __platform_wait_t (PR 118494).

Make the std::counting_semaphore constructor constexpr to support
constant initialization (PR 110854).

Add precondition checks to the constructor and release member functions
(PR 98749).

libstdc++-v3/ChangeLog:

PR libstdc++/118494
PR libstdc++/110854
PR libstdc++/98749
* acinclude.m4 (GLIBCXX_CHECK_GTHREADS): Remove checks for
sem_timedwait. Do not define _GLIBCXX_HAVE_POSIX_SEMAPHORE.
* config.h.in: Regenerate.
* configure: Regenerate.
* include/bits/semaphore_base.h (__platform_semaphore): Remove.
(__atomic_semaphore): Replace with __semaphore_base and
make type of _M_count depend on template parameter. Fix _S_max
constant to use correct type.
(__semaphore_base::_M_try_acquire): Qualify to avoid ADL.
(__semaphore_base::_M_release): Return old value. Remove FIXME
comment.
(__semaphore_impl): Replace typedef with alias template.
* include/bits/version.def (semaphore): Do not depend on
_GLIBCXX_HAVE_POSIX_SEMAPHORE.
* include/bits/version.h: Regenerate.
* include/std/semaphore (semaphore): Adjust type of _M_sem
member. Add constexpr to constructor. Add assertions to
(semaphore::semaphore(ptrdiff_t)): Add constexpr. Add assertion
for precondition.
(semaphore::release): Add assertion using value returned from
_M_release.
* testsuite/30_threads/semaphore/100806.cc: Increase template
argument for std::counting_semaphore, so constructor
precondition is met.
* testsuite/30_threads/semaphore/cons.cc: New test.
* testsuite/30_threads/semaphore/try_acquire_posix.cc: Remove.
* testsuite/30_threads/semaphore/platform_try_acquire_for.cc:
Removed.

Diff:
---
 libstdc++-v3/acinclude.m4  |  37 
 libstdc++-v3/config.h.in   |   4 -
 libstdc++-v3/configure |  60 +-
 libstdc++-v3/include/bits/semaphore_base.h | 224 +
 libstdc++-v3/include/bits/version.def  |   2 +-
 libstdc++-v3/include/bits/version.h|   2 +-
 libstdc++-v3/include/std/semaphore |  32 +--
 .../testsuite/30_threads/semaphore/100806.cc   |   2 +-
 .../testsuite/30_threads/semaphore/cons.cc |   7 +
 .../semaphore/platform_try_acquire_for.cc  |   9 -
 .../30_threads/semaphore/try_acquire_posix.cc  | 153 --
 11 files changed, 82 insertions(+), 450 deletions(-)

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index d1ecb1ad9566..080a4fca9b57 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -4293,43 +4293,6 @@ AC_DEFUN([GLIBCXX_CHECK_GTHREADS], [
 fi
   fi
 
-  AC_CHECK_HEADER(semaphore.h, [
-AC_MSG_CHECKING([for POSIX Semaphores and sem_timedwait])
-AC_TRY_COMPILE([
-   #include 
-   #include 
-   #include 
-  ],
-  [
-   #if !defined _POSIX_TIMEOUTS || _POSIX_TIMEOUTS <= 0
-   # error "POSIX Timeouts option not supported"
-   #elif !defined _POSIX_SEMAPHORES || _POSIX_SEMAPHORES <= 0
-   # error "POSIX Semaphores option not supported"
-   #else
-   #if defined SEM_VALUE_MAX
-   constexpr int sem_value_max = SEM_VALUE_MAX;
-   #elif defined _POSIX_SEM_VALUE_MAX
-   constexpr int sem_value_max = _POSIX_SEM_VALUE_MAX;
-   #else
-   # error "SEM_VALUE_MAX not available"
-   #endif
-   sem_t sem;
-   sem_init(&sem, 0, sem_value_max);
-   struct timespec ts = { 0 };
-   sem_timedwait(&sem, &ts);
-   #endif
-  ],
-  [ac_have_posix_semaphore=yes],
-  [ac_have_posix_semaphore=no])],
-  [ac_have_posix_semaphore=no])
-
-  if test $ac_have_posix_semaphore = yes ; then
-AC_DEFINE(HAVE_POSIX_SEMAPHORE,
- 1,
- [Define to 1 if POSIX Semaphores with sem_timedwait are available 
in .])
-  fi
-  AC_MSG_RESULT([$ac_have_posix_semaphore])
-
   CXXFLAGS="$ac_save_CXXFLAGS"
   AC_LANG_RESTORE
 ])
diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
index 3dbe00bae508..ffacdabac854 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -314,10 +314,6 @@
 /* Define to 1 if you have the `posix_memalign' function. */
 #undef HAVE_POSIX_MEMALIGN

[gcc r16-998] libstdc++: Create new base class of std::barrier for non-dependent code

2025-05-30 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:42fc1e9712c8e0d929b23009095c6e14b32fda93

commit r16-998-g42fc1e9712c8e0d929b23009095c6e14b32fda93
Author: Jonathan Wakely 
Date:   Fri Jan 10 17:00:48 2025 +

libstdc++: Create new base class of std::barrier for non-dependent code

This moves all non-dependent state and logic for std::barrier into a
new non-template base class, to avoid template bloat.

This would permit moving the _M_arrive function into the library instead
of the header.

libstdc++-v3/ChangeLog:

* include/std/barrier (__tree_barrier_base): New class.
(__tree_barrier): Move non-dependent code into
__tree_barrier_base and derive from it.

Diff:
---
 libstdc++-v3/include/std/barrier | 170 +--
 1 file changed, 91 insertions(+), 79 deletions(-)

diff --git a/libstdc++-v3/include/std/barrier b/libstdc++-v3/include/std/barrier
index 9c1de411f9ce..56270c99e056 100644
--- a/libstdc++-v3/include/std/barrier
+++ b/libstdc++-v3/include/std/barrier
@@ -81,76 +81,101 @@ It looks different from literature pseudocode for two main 
reasons:
 
   enum class __barrier_phase_t : unsigned char { };
 
-  template
-class __tree_barrier
+  struct __tree_barrier_base
+  {
+static constexpr ptrdiff_t
+max() noexcept
+{ return __PTRDIFF_MAX__ - 1; }
+
+  protected:
+using __atomic_phase_ref_t = std::__atomic_ref<__barrier_phase_t>;
+using __atomic_phase_const_ref_t = std::__atomic_ref;
+static constexpr auto __phase_alignment =
+   __atomic_phase_ref_t::required_alignment;
+
+using __tickets_t = std::array<__barrier_phase_t, 64>;
+struct alignas(64) /* naturally-align the heap state */ __state_t
 {
-  using __atomic_phase_ref_t = std::__atomic_ref<__barrier_phase_t>;
-  using __atomic_phase_const_ref_t = std::__atomic_ref;
-  static constexpr auto __phase_alignment =
- __atomic_phase_ref_t::required_alignment;
+  alignas(__phase_alignment) __tickets_t __tickets;
+};
 
-  using __tickets_t = std::array<__barrier_phase_t, 64>;
-  struct alignas(64) /* naturally-align the heap state */ __state_t
-  {
-   alignas(__phase_alignment) __tickets_t __tickets;
-  };
+ptrdiff_t _M_expected;
+__atomic_base<__state_t*> _M_state{nullptr};
+__atomic_base _M_expected_adjustment{0};
+alignas(__phase_alignment) __barrier_phase_t  _M_phase{};
 
-  ptrdiff_t _M_expected;
-  __atomic_base<__state_t*> _M_state{nullptr};
-  __atomic_base _M_expected_adjustment{0};
-  [[no_unique_address]] _CompletionF _M_completion;
+explicit constexpr
+__tree_barrier_base(ptrdiff_t __expected)
+: _M_expected(__expected)
+{
+  __glibcxx_assert(__expected >= 0 && __expected <= max());
 
-  alignas(__phase_alignment) __barrier_phase_t  _M_phase{};
+  if (!std::is_constant_evaluated())
+   _M_state.store(_M_alloc_state().release(), memory_order_release);
+}
 
-  bool
-  _M_arrive(__barrier_phase_t __old_phase, size_t __current)
-  {
-   const auto __old_phase_val = static_cast(__old_phase);
-   const auto __half_step =
-  static_cast<__barrier_phase_t>(__old_phase_val + 1);
-   const auto __full_step =
-  static_cast<__barrier_phase_t>(__old_phase_val + 2);
-
-   size_t __current_expected = _M_expected;
-   __current %= ((_M_expected + 1) >> 1);
+unique_ptr<__state_t[]>
+_M_alloc_state()
+{
+  size_t const __count = (_M_expected + 1) >> 1;
+  return std::make_unique<__state_t[]>(__count);
+}
 
-   __state_t* const __state = _M_state.load(memory_order_relaxed);
+bool
+_M_arrive(__barrier_phase_t __old_phase, size_t __current)
+{
+  const auto __old_phase_val = static_cast(__old_phase);
+  const auto __half_step =
+static_cast<__barrier_phase_t>(__old_phase_val + 1);
+  const auto __full_step =
+static_cast<__barrier_phase_t>(__old_phase_val + 2);
+
+  size_t __current_expected = _M_expected;
+  __current %= ((_M_expected + 1) >> 1);
+
+  __state_t* const __state = _M_state.load(memory_order_relaxed);
+
+  for (int __round = 0; ; ++__round)
+   {
+ if (__current_expected <= 1)
+ return true;
+ size_t const __end_node = ((__current_expected + 1) >> 1),
+  __last_node = __end_node - 1;
+ for ( ; ; ++__current)
+   {
+ if (__current == __end_node)
+   __current = 0;
+ auto __expect = __old_phase;
+ __atomic_phase_ref_t __phase(__state[__current]
+ .__tickets[__round]);
+ if (__current == __last_node && (__current_expected & 1))
+   {
+ if (__phase.compare_exchange_strong(__expect, __full_step,
+  

[gcc r16-988] libstdc++: Various fixes for atomic wait/notify code

2025-05-30 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:219bb905a60d95d0d6b4197eadf7f680e832c6ea

commit r16-988-g219bb905a60d95d0d6b4197eadf7f680e832c6ea
Author: Jonathan Wakely 
Date:   Thu Jan 9 23:10:13 2025 +

libstdc++: Various fixes for atomic wait/notify code

Pass __wait_args_base by const reference instead of const pointer. I
don't see a reason it needs to be passed by pointer to the internals.
We can also avoid constructing a __wait_args from __wait_args_base in
some places, instaad just using the latter directly.

The code using the __wait_flags bitmask type is broken, because the
__spin_only constant includes the __do_spin element. This means that
testing (__args & __wait_flags::__spin_only) will be inadvertently true
when only __do_spin is set. This causes the __wait_until_impl function
to never actually wait on the futex (or condition variable), turning all
uses of that function into expensive busy spins. Change __spin_only to
be a single bit (i.e. a bitmask element) and adjust the places where
that bit is set so that they also use the __do_spin element.

Update the __args._M_old value when looping in __atomic_wait_address, so
that the next wait doesn't fail spuriously.

With the new __atomic_wait_address logic, the value function needs to
return the correct type, not just a bool. Without that change, the
boolean value returned by the value function is used as the value
passed to the futex wait, but that mean we're comparing (_M_a == 0) to
_M_a and so can block on the futex when we shouldn't, and then never
wake up.

libstdc++-v3/ChangeLog:

* include/bits/atomic_timed_wait.h (__cond_wait_impl): Add
missing inline keyword.
(__spin_until_impl): Change parameter from pointer to reference.
Replace make_pair with list-initialization.  Initialize variable
for return value.
(__wait_until_impl): Likewise. Remove some preprocessor
conditional logic. Use _S_track for contention tracking.
Avoid unnecessary const_cast.
(__wait_until): Change parameter from pointer to reference.
Replace make_pair with list-initialization.
(__wait_for):  Change parameter from pointer to reference. Add
__do_spin flag to args.
* include/bits/atomic_wait.h (__waiter_pool_impl::_S_track): New
function returning an RAII object for contention tracking.
(__wait_flags): Do not set the __do_spin flag in the __spin_only
enumerator. Comment out the unused __abi_version_mask
enumerator.  Define operator| and operator|= overloads.
(__wait_args_base::operator&): Define.
(__wait_args::operator&, __wait_args::_S_default_flags): Remove.
(__wait_args::operator|, __wait_args::operator|=): Remove.
(__spin_impl): Change parameter from pointer to reference.
Replace make_pair call with list-initialization.
(__wait_impl): Likewise.  Remove some preprocessor conditional
logic.  Always store old value in __args._M_old. Avoid
unnecessary const_cast. Use _S_track.
(__notify_impl): Change parameter to reference. Remove some
preprocessor conditional logic.
(__atomic_wait_address): Add comment. Update __args._M_old on
each iteration.
(__atomic_wait_address_v): Add comment.
* include/std/latch (latch::wait): Adjust predicates for new
logic.
* testsuite/29_atomics/atomic_integral/wait_notify.cc: Improve
test.

Diff:
---
 libstdc++-v3/include/bits/atomic_timed_wait.h  |  98 +++-
 libstdc++-v3/include/bits/atomic_wait.h| 263 +++--
 libstdc++-v3/include/std/latch |   8 +-
 .../29_atomics/atomic_integral/wait_notify.cc  |   8 +-
 4 files changed, 189 insertions(+), 188 deletions(-)

diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h 
b/libstdc++-v3/include/bits/atomic_timed_wait.h
index e5a5f283bca0..9fc28f3d2696 100644
--- a/libstdc++-v3/include/bits/atomic_timed_wait.h
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -104,14 +104,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   return true;
 }
 #else
-// define _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT and implement 
__platform_wait_until()
+// define _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT and implement __platform_wait_until
 // if there is a more efficient primitive supported by the platform
-// (e.g. __ulock_wait())which is better than pthread_cond_clockwait
-#endif // ! PLATFORM_TIMED_WAIT
+// (e.g. __ulock_wait) which is better than pthread_cond_clockwait.
+#endif // ! HAVE_LINUX_FUTEX
 
 #ifdef _GLIBCXX_HAS_GTHREADS
 // Returns true if wait ended before timeout.
-bool
+inline bool
 __cond_wait_until(__condvar& __cv, mutex& __mx,
  

[gcc r16-994] libstdc++: Rename __waiter_pool_impl to __waitable_state

2025-05-30 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:5b110bbb70f75d034228d83086b9a49a208a1520

commit r16-994-g5b110bbb70f75d034228d83086b9a49a208a1520
Author: Jonathan Wakely 
Date:   Sat Jan 18 21:11:26 2025 +

libstdc++: Rename __waiter_pool_impl to __waitable_state

The name __waiter_pool_impl is misleading. An object of that type is a
member of the pool, not the pool itself, and it's not an "impl" of
any abstract base class or generic concept. Just call it
__waitable_state since it maintains the state used for waiting/notifying
a waitable atomic object.

Similarly, rename _S_impl_for to _S_state_for.

Once these functions move into the shared library they won't be exported
and so the naming won't matter much anyway.

libstdc++-v3/ChangeLog:

* include/bits/atomic_timed_wait.h (__wait_until_impl): Adjust
to use new naming.
* include/bits/atomic_wait.h (__waiter_pool_impl): Rename to
__waitable_state.
(__waiter_pool_impl::_S_wait): Rename to _M_waiters.
(__waiter_pool_impl::_S_impl_for): Rename to _S_state_for.
(__waiter_pool_impl::_S_track): Adjust to use new naming.
(__wait_impl, __notify_impl): Likewise.
* testsuite/29_atomics/atomic/wait_notify/100334.cc: Adjust to
use new naming.

Diff:
---
 libstdc++-v3/include/bits/atomic_timed_wait.h  | 16 ++---
 libstdc++-v3/include/bits/atomic_wait.h| 81 --
 .../29_atomics/atomic/wait_notify/100334.cc|  5 +-
 3 files changed, 53 insertions(+), 49 deletions(-)

diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h 
b/libstdc++-v3/include/bits/atomic_timed_wait.h
index 800f461e9e48..19a0225c63b2 100644
--- a/libstdc++-v3/include/bits/atomic_timed_wait.h
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -174,12 +174,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  const __wait_clock_t::time_point& __atime)
 {
   __wait_args_base __args = __a;
-  __waiter_pool_impl* __pool = nullptr;
+  __waitable_state* __state = nullptr;
   const __platform_wait_t* __wait_addr;
   if (__args & __wait_flags::__proxy_wait)
{
- __pool = &__waiter_pool_impl::_S_impl_for(__addr);
- __wait_addr = &__pool->_M_ver;
+ __state = &__waitable_state::_S_state_for(__addr);
+ __wait_addr = &__state->_M_ver;
  __atomic_load(__wait_addr, &__args._M_old, __args._M_order);
}
   else
@@ -194,7 +194,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __res;
}
 
-  auto __tracker = __waiter_pool_impl::_S_track(__pool, __args, __addr);
+  auto __tracker = __waitable_state::_S_track(__state, __args, __addr);
 
 #ifdef _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT
   if (__platform_wait_until(__wait_addr, __args._M_old, __atime))
@@ -206,12 +206,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   __atomic_load(__wait_addr, &__val, __args._M_order);
   if (__val == __args._M_old)
{
- if (!__pool)
-   __pool = &__waiter_pool_impl::_S_impl_for(__addr);
- lock_guard __l{ __pool->_M_mtx };
+ if (!__state)
+   __state = &__waitable_state::_S_state_for(__addr);
+ lock_guard __l{ __state->_M_mtx };
  __atomic_load(__wait_addr, &__val, __args._M_order);
  if (__val == __args._M_old
-   && __cond_wait_until(__pool->_M_cv, __pool->_M_mtx, __atime))
+   && __cond_wait_until(__state->_M_cv, __state->_M_mtx, __atime))
return { true, __val };
}
   return { false, __val };
diff --git a/libstdc++-v3/include/bits/atomic_wait.h 
b/libstdc++-v3/include/bits/atomic_wait.h
index 40d8471413a2..bdc8677e9ea9 100644
--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -163,47 +163,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 struct __wait_args_base;
 
-struct __waiter_pool_impl
+// The state used by atomic waiting and notifying functions.
+struct __waitable_state
 {
   // Don't use std::hardware_destructive_interference_size here because we
   // don't want the layout of library types to depend on compiler options.
   static constexpr auto _S_align = 64;
 
-  alignas(_S_align) __platform_wait_t _M_wait = 0;
+  // Count of threads blocked waiting on this state.
+  alignas(_S_align) __platform_wait_t _M_waiters = 0;
 
 #ifndef _GLIBCXX_HAVE_PLATFORM_WAIT
   mutex _M_mtx;
 #endif
 
+  // If we can't do a platform wait on the atomic variable itself,
+  // we use this member as a proxy for the atomic variable and we
+  // use this for waiting and notifying functions instead.
   alignas(_S_align) __platform_wait_t _M_ver = 0;
 
 #ifndef _GLIBCXX_HAVE_PLATFORM_WAIT
   __condvar _M_cv;
 #endif
 
-  __waiter_pool_impl() = default;
+  __waitable_state() = default;
 
   void
   _M_enter_wait()

[gcc r16-997] libstdc++: Fix std::barrier for constant initialization [PR118395]

2025-05-30 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:ef632273a90657acb45e89df12bce9e96035f52c

commit r16-997-gef632273a90657acb45e89df12bce9e96035f52c
Author: Jonathan Wakely 
Date:   Fri Jan 10 12:22:21 2025 +

libstdc++: Fix std::barrier for constant initialization [PR118395]

The std::barrier constructor should be constexpr, which means we need to
defer the dynamic allocation if the constructor is called during
constant-initialization. We can defer it to the first call to
barrier::arrive, using compare-and-swap on an atomic (instead of the
unique_ptr currently used).

Also add precondition checks to the constructor and arrive member
function. Also implement the proposed resolution of LWG 3898.

libstdc++-v3/ChangeLog:

PR libstdc++/118395
PR libstdc++/108974
PR libstdc++/98749
* include/std/barrier (__tree_barrier): Use default
member-initializers. Change _M_state member from
unique_ptr<__state_t[]> to atomic<__state_t*>. Add
no_unique_address attribute to _M_completion.
(__tree_barrier::_M_arrive): Load value from _M_state.
(__tree_barrier::_M_invoke_completion): New member function to
ensure a throwing completion function will terminate, as
proposed in LWG 3898.
(__tree_barrier::max): Reduce by one to avoid overflow.
(__tree_barrier::__tree_barrier): Add constexpr. Qualify call to
std::move. Remove mem-initializers made unnecessary by default
member-initializers. Add precondition check. Only allocate state
array if not constant evaluated.
(__tree_barrier::arrive): Add precondition check. Do deferred
initialization of _M_state if needed.
(barrier): Add static_assert, as proposed in LWG 3898.
(barrier::barrier): Add constexpr.
* testsuite/30_threads/barrier/cons.cc: New test.
* testsuite/30_threads/barrier/lwg3898.cc: New test.

Diff:
---
 libstdc++-v3/include/std/barrier   | 57 --
 libstdc++-v3/testsuite/30_threads/barrier/cons.cc  |  6 +++
 .../testsuite/30_threads/barrier/lwg3898.cc| 45 +
 3 files changed, 93 insertions(+), 15 deletions(-)

diff --git a/libstdc++-v3/include/std/barrier b/libstdc++-v3/include/std/barrier
index 62b03d0223f4..9c1de411f9ce 100644
--- a/libstdc++-v3/include/std/barrier
+++ b/libstdc++-v3/include/std/barrier
@@ -96,11 +96,11 @@ It looks different from literature pseudocode for two main 
reasons:
   };
 
   ptrdiff_t _M_expected;
-  unique_ptr<__state_t[]> _M_state;
-  __atomic_base _M_expected_adjustment;
-  _CompletionF _M_completion;
+  __atomic_base<__state_t*> _M_state{nullptr};
+  __atomic_base _M_expected_adjustment{0};
+  [[no_unique_address]] _CompletionF _M_completion;
 
-  alignas(__phase_alignment) __barrier_phase_t  _M_phase;
+  alignas(__phase_alignment) __barrier_phase_t  _M_phase{};
 
   bool
   _M_arrive(__barrier_phase_t __old_phase, size_t __current)
@@ -114,6 +114,8 @@ It looks different from literature pseudocode for two main 
reasons:
size_t __current_expected = _M_expected;
__current %= ((_M_expected + 1) >> 1);
 
+   __state_t* const __state = _M_state.load(memory_order_relaxed);
+
for (int __round = 0; ; ++__round)
  {
if (__current_expected <= 1)
@@ -125,7 +127,7 @@ It looks different from literature pseudocode for two main 
reasons:
if (__current == __end_node)
  __current = 0;
auto __expect = __old_phase;
-   __atomic_phase_ref_t __phase(_M_state[__current]
+   __atomic_phase_ref_t __phase(__state[__current]
.__tickets[__round]);
if (__current == __last_node && (__current_expected & 1))
  {
@@ -150,36 +152,59 @@ It looks different from literature pseudocode for two 
main reasons:
  }
   }
 
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 3898. Possibly unintended preconditions for completion functions
+  void _M_invoke_completion() noexcept { _M_completion(); }
+
 public:
   using arrival_token = __barrier_phase_t;
 
   static constexpr ptrdiff_t
   max() noexcept
-  { return __PTRDIFF_MAX__; }
+  { return __PTRDIFF_MAX__ - 1; }
 
+  constexpr
   __tree_barrier(ptrdiff_t __expected, _CompletionF __completion)
- : _M_expected(__expected), _M_expected_adjustment(0),
-   _M_completion(move(__completion)),
-   _M_phase(static_cast<__barrier_phase_t>(0))
+  : _M_expected(__expected), _M_completion(std::move(__completion))
   {
-   size_t const __count = (_M_expected + 1) >> 1;
+   __glibcxx_assert(__expected >= 0 && __expected <= max());
 
-   _M_state = std::make_unique<__

[gcc r16-992] libstdc++: Remove reinterpret_cast uses in atomic wait/notify

2025-05-30 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:5729a28e994e28df73088bcd87042fd9383085a5

commit r16-992-g5729a28e994e28df73088bcd87042fd9383085a5
Author: Jonathan Wakely 
Date:   Sat Jan 18 21:10:41 2025 +

libstdc++: Remove reinterpret_cast uses in atomic wait/notify

We can pass around void* instead of casting incompatible pointers to
__platform_wait_t*, and then only static_cast to __platform_wait_t* when
we know that's valid.

libstdc++-v3/ChangeLog:

* include/bits/atomic_timed_wait.h (__wait_until_impl): Change
first parameter to const void* and then static_cast to const
__platform_wait_t* when not using proxied wait.
(__wait_until): Change first parameter to const void*.
(__wait_for): Likewise.
(__atomic_wait_address_until): Remove reinterpret_cast and allow
address to implicitly convert to const void* instead.
(__atomic_wait_address_for): Likewise.
* include/bits/atomic_wait.h: (__wait_impl, __notify_impl):
Change first parameter to const void* and then static_cast to
const __platform_wait_t* when not using proxied wait.
(__atomic_wait_address, __atomic_notify_address) Remove
reinterpret_cast and allow address to implicitly convert to
const void* instead.

Diff:
---
 libstdc++-v3/include/bits/atomic_timed_wait.h | 17 ++---
 libstdc++-v3/include/bits/atomic_wait.h   | 16 ++--
 2 files changed, 12 insertions(+), 21 deletions(-)

diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h 
b/libstdc++-v3/include/bits/atomic_timed_wait.h
index a916c10879b7..cbf9187f2bb8 100644
--- a/libstdc++-v3/include/bits/atomic_timed_wait.h
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -170,8 +170,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 }
 
 inline __wait_result_type
-__wait_until_impl(const __platform_wait_t* __addr,
- const __wait_args_base& __a,
+__wait_until_impl(const void* __addr, const __wait_args_base& __a,
  const __wait_clock_t::time_point& __atime)
 {
   __wait_args_base __args = __a;
@@ -184,7 +183,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  __atomic_load(__wait_addr, &__args._M_old, __args._M_order);
}
   else
-   __wait_addr = __addr;
+   __wait_addr = static_cast(__addr);
 
   if (__args & __wait_flags::__do_spin)
{
@@ -222,7 +221,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 // Returns {true, val} if wait ended before a timeout.
 template
   __wait_result_type
-  __wait_until(const __platform_wait_t* __addr, const __wait_args_base& 
__args,
+  __wait_until(const void* __addr, const __wait_args_base& __args,
   const chrono::time_point<_Clock, _Dur>& __atime) noexcept
   {
auto __at = __detail::__to_wait_clock(__atime);
@@ -243,7 +242,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 // Returns {true, val} if wait ended before a timeout.
 template
   __wait_result_type
-  __wait_for(const __platform_wait_t* __addr, const __wait_args_base& 
__args,
+  __wait_for(const void* __addr, const __wait_args_base& __args,
 const chrono::duration<_Rep, _Period>& __rtime) noexcept
   {
if (!__rtime.count())
@@ -270,13 +269,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const chrono::time_point<_Clock, _Dur>& __atime,
bool __bare_wait = false) noexcept
 {
-  const auto __wait_addr =
-   reinterpret_cast(__addr);
   __detail::__wait_args __args{ __addr, __bare_wait };
   _Tp __val = __vfn();
   while (!__pred(__val))
{
- auto __res = __detail::__wait_until(__wait_addr, __args, __atime);
+ auto __res = __detail::__wait_until(__addr, __args, __atime);
  if (!__res.first)
// timed out
return __res.first; // C++26 will also return last observed __val
@@ -320,13 +317,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  const chrono::duration<_Rep, _Period>& __rtime,
  bool __bare_wait = false) noexcept
 {
-  const auto __wait_addr =
- reinterpret_cast(__addr);
   __detail::__wait_args __args{ __addr, __bare_wait };
   _Tp __val = __vfn();
   while (!__pred(__val))
{
- auto __res = __detail::__wait_for(__wait_addr, __args, __rtime);
+ auto __res = __detail::__wait_for(__addr, __args, __rtime);
  if (!__res.first)
// timed out
return __res.first; // C++26 will also return last observed __val
diff --git a/libstdc++-v3/include/bits/atomic_wait.h 
b/libstdc++-v3/include/bits/atomic_wait.h
index 5fd00c22565b..cfda323a3ab6 100644
--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -355,7 +355,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 }
 
 

[gcc r16-991] libstdc++: Simplify futex wrapper functions for atomic wait/notify

2025-05-30 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:f52948bf8e5f3b0a72a903b3b26e5d54d2929723

commit r16-991-gf52948bf8e5f3b0a72a903b3b26e5d54d2929723
Author: Jonathan Wakely 
Date:   Thu Jan 9 23:03:50 2025 +

libstdc++: Simplify futex wrapper functions for atomic wait/notify

libstdc++-v3/ChangeLog:

* include/bits/atomic_wait.h (__platform_wait): Change function
template to a normal function. The parameter is always
__platform_wait_t* which is just int* for this implementation of
the function.
(__platform_notify): Likewise.

Diff:
---
 libstdc++-v3/include/bits/atomic_wait.h | 40 -
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/libstdc++-v3/include/bits/atomic_wait.h 
b/libstdc++-v3/include/bits/atomic_wait.h
index 725ea030245d..5fd00c22565b 100644
--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -108,27 +108,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   __bitset_match_any = -1
 };
 
-template
-  void
-  __platform_wait(const _Tp* __addr, __platform_wait_t __val) noexcept
-  {
-   auto __e = syscall (SYS_futex, static_cast(__addr),
-   
static_cast(__futex_wait_flags::__wait_private),
-   __val, nullptr);
-   if (!__e || errno == EAGAIN)
- return;
-   if (errno != EINTR)
- __throw_system_error(errno);
-  }
+// If the futex *__addr is equal to __val, wait on the futex until woken.
+inline void
+__platform_wait(const int* __addr, int __val) noexcept
+{
+  auto __e = syscall (SYS_futex, __addr,
+ static_cast(__futex_wait_flags::__wait_private),
+ __val, nullptr);
+  if (!__e || errno == EAGAIN)
+   return;
+  if (errno != EINTR)
+   __throw_system_error(errno);
+}
 
-template
-  void
-  __platform_notify(const _Tp* __addr, bool __all) noexcept
-  {
-   syscall (SYS_futex, static_cast(__addr),
-static_cast(__futex_wait_flags::__wake_private),
-__all ? INT_MAX : 1);
-  }
+// Wake threads waiting on the futex *__addr.
+inline void
+__platform_notify(const int* __addr, bool __all) noexcept
+{
+  syscall (SYS_futex, __addr,
+  static_cast(__futex_wait_flags::__wake_private),
+  __all ? INT_MAX : 1);
+}
 #endif
 
 inline void


[gcc r16-990] libstdc++: Fix time_point conversion in atomic timed waits

2025-05-30 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:aeaa9ba8fb631bf0562f9a82c1daa774af3d81ed

commit r16-990-gaeaa9ba8fb631bf0562f9a82c1daa774af3d81ed
Author: Jonathan Wakely 
Date:   Fri Jan 17 22:16:08 2025 +

libstdc++: Fix time_point conversion in atomic timed waits

Even if a time_point already uses the right clock, we might still need
to convert it to use the expected duration. Calling __to_wait_clock will
perform that conversion, so use that even when the clock is correct.

libstdc++-v3/ChangeLog:

* include/bits/atomic_timed_wait.h (__to_wait_clock): Do not use
chrono::ceil if clock and duration are already correct type.
(__wait_until): Always call __to_wait_clock.

Diff:
---
 libstdc++-v3/include/bits/atomic_timed_wait.h | 34 +--
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h 
b/libstdc++-v3/include/bits/atomic_timed_wait.h
index 9fc28f3d2696..a916c10879b7 100644
--- a/libstdc++-v3/include/bits/atomic_timed_wait.h
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -70,7 +70,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   _Dur>& __atime) noexcept
   {
using __w_dur = typename __wait_clock_t::duration;
-   return chrono::ceil<__w_dur>(__atime);
+   if constexpr (is_same_v<__w_dur, _Dur>)
+ return __atime;
+   else
+ return chrono::ceil<__w_dur>(__atime);
   }
 
 #ifdef _GLIBCXX_HAVE_LINUX_FUTEX
@@ -222,22 +225,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   __wait_until(const __platform_wait_t* __addr, const __wait_args_base& 
__args,
   const chrono::time_point<_Clock, _Dur>& __atime) noexcept
   {
-   if constexpr (is_same_v<__wait_clock_t, _Clock>)
- return __detail::__wait_until_impl(__addr, __args, __atime);
-   else
- {
-   auto __res = __detail::__wait_until_impl(__addr, __args,
-__to_wait_clock(__atime));
-   if (!__res.first)
- {
-   // We got a timeout when measured against __clock_t but
-   // we need to check against the caller-supplied clock
-   // to tell whether we should return a timeout.
-   if (_Clock::now() < __atime)
- __res.first = true;
- }
-   return __res;
- }
+   auto __at = __detail::__to_wait_clock(__atime);
+   auto __res = __detail::__wait_until_impl(__addr, __args, __at);
+
+   if constexpr (!is_same_v<__wait_clock_t, _Clock>)
+ if (!__res.first)
+   {
+ // We got a timeout when measured against __clock_t but
+ // we need to check against the caller-supplied clock
+ // to tell whether we should return a timeout.
+ if (_Clock::now() < __atime)
+   __res.first = true;
+   }
+   return __res;
   }
 
 // Returns {true, val} if wait ended before a timeout.


[gcc r16-993] libstdc++: Rename __atomic_compare to __atomic_eq

2025-05-30 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:ba56ed29d9c3be4ab79c012539a938dea7372357

commit r16-993-gba56ed29d9c3be4ab79c012539a938dea7372357
Author: Jonathan Wakely 
Date:   Thu Jan 9 22:24:52 2025 +

libstdc++: Rename __atomic_compare to __atomic_eq

This is an equality comparison rather than a three-way comparison like
memcmp and <=>, so name it more precisely.

libstdc++-v3/ChangeLog:

* include/bits/atomic_timed_wait.h
(__atomic_wait_address_until_v): Replace __atomic_compare with
__atomic_eq.
(__atomic_wait_address_for_v): Likewise.
* include/bits/atomic_wait.h (__atomic_compare): Rename to
__atomic_eq.
(__atomic_wait_address_v): Replace __atomic_compare with
__atomic_eq.

Diff:
---
 libstdc++-v3/include/bits/atomic_timed_wait.h | 10 ++
 libstdc++-v3/include/bits/atomic_wait.h   |  5 +++--
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h 
b/libstdc++-v3/include/bits/atomic_timed_wait.h
index cbf9187f2bb8..800f461e9e48 100644
--- a/libstdc++-v3/include/bits/atomic_timed_wait.h
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -302,8 +302,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  const chrono::time_point<_Clock, _Dur>& 
__atime,
  bool __bare_wait = false) noexcept
 {
-  auto __pfn = [&](const _Tp& __val)
- { return !__detail::__atomic_compare(__old, __val); };
+  auto __pfn = [&](const _Tp& __val) {
+   return !__detail::__atomic_eq(__old, __val);
+  };
   return __atomic_wait_address_until(__addr, __pfn, forward<_ValFn>(__vfn),
 __atime, __bare_wait);
 }
@@ -350,8 +351,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const chrono::duration<_Rep, _Period>& __rtime,
bool __bare_wait = false) noexcept
 {
-  auto __pfn = [&](const _Tp& __val)
- { return !__detail::__atomic_compare(__old, __val); };
+  auto __pfn = [&](const _Tp& __val) {
+   return !__detail::__atomic_eq(__old, __val);
+  };
   return __atomic_wait_address_for(__addr, __pfn, forward<_ValFn>(__vfn),
   __rtime, __bare_wait);
 }
diff --git a/libstdc++-v3/include/bits/atomic_wait.h 
b/libstdc++-v3/include/bits/atomic_wait.h
index cfda323a3ab6..40d8471413a2 100644
--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -154,7 +154,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 // return true if equal
 template
-  bool __atomic_compare(const _Tp& __a, const _Tp& __b)
+  inline bool
+  __atomic_eq(const _Tp& __a, const _Tp& __b)
   {
// TODO make this do the correct padding bit ignoring comparison
return __builtin_memcmp(&__a, &__b, sizeof(_Tp)) == 0;
@@ -483,7 +484,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_ValFn __vfn) noexcept
 {
   auto __pfn = [&](const _Tp& __val)
- { return !__detail::__atomic_compare(__old, __val); };
+ { return !__detail::__atomic_eq(__old, __val); };
   __atomic_wait_address(__addr, __pfn, forward<_ValFn>(__vfn));
 }


[gcc r16-1000] libstdc++: Define __wait_result_type for atomic waiting

2025-05-30 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:225622398a9631c627abfaf5c854792d0110847c

commit r16-1000-g225622398a9631c627abfaf5c854792d0110847c
Author: Jonathan Wakely 
Date:   Fri Jan 31 22:10:21 2025 +

libstdc++: Define __wait_result_type for atomic waiting

libstdc++-v3/ChangeLog:

* include/bits/atomic_timed_wait.h: Use __wait_result_type.
* include/bits/atomic_wait.h (__wait_result_type): New struct.
(__wait_args::_M_prep_for_wait_on): Rename to _M_setup_wait, use
__wait_result_type.
(__atomic_wait_address): Adjust to call _M_setup_wait.
* src/c++20/atomic.cc (__spin_impl): Use __wait_result_type.
(__wait_impl): Likewise.
(__spin_until_impl): Likewise.
(__wait_until_impl): Likewise.

Diff:
---
 libstdc++-v3/include/bits/atomic_timed_wait.h | 25 ++--
 libstdc++-v3/include/bits/atomic_wait.h   | 48 +++
 libstdc++-v3/src/c++20/atomic.cc  | 55 ++-
 3 files changed, 80 insertions(+), 48 deletions(-)

diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h 
b/libstdc++-v3/include/bits/atomic_timed_wait.h
index 3e25607b7d4c..230afbc96e7d 100644
--- a/libstdc++-v3/include/bits/atomic_timed_wait.h
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -98,18 +98,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 __at.time_since_epoch());
 
if constexpr (!is_same_v<__wait_clock_t, _Clock>)
- if (!__res.first)
+ if (__res._M_timeout)
{
  // We got a timeout when measured against __clock_t but
  // we need to check against the caller-supplied clock
  // to tell whether we should return a timeout.
  if (_Clock::now() < __atime)
-   __res.first = true;
+   __res._M_timeout = false;
}
return __res;
   }
 
-// Returns {true, val} if wait ended before a timeout.
 template
   __wait_result_type
   __wait_for(const void* __addr, __wait_args_base& __args,
@@ -139,14 +138,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool __bare_wait = false) noexcept
 {
   __detail::__wait_args __args{ __addr, __bare_wait };
-  _Tp __val = __args._M_prep_for_wait_on(__addr, __vfn);
+  _Tp __val = __args._M_setup_wait(__addr, __vfn);
   while (!__pred(__val))
{
  auto __res = __detail::__wait_until(__addr, __args, __atime);
- if (!__res.first)
-   // timed out
-   return __res.first; // C++26 will also return last observed __val
- __val = __args._M_prep_for_wait_on(__addr, __vfn);
+ if (__res._M_timeout)
+   return false; // C++26 will also return last observed __val
+ __val = __args._M_setup_wait(__addr, __vfn, __res);
}
   return true; // C++26 will also return last observed __val
 }
@@ -189,14 +187,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  bool __bare_wait = false) noexcept
 {
   __detail::__wait_args __args{ __addr, __bare_wait };
-  _Tp __val = __args._M_prep_for_wait_on(__addr, __vfn);
+  _Tp __val = __args._M_setup_wait(__addr, __vfn);
   while (!__pred(__val))
{
  auto __res = __detail::__wait_for(__addr, __args, __rtime);
- if (!__res.first)
-   // timed out
-   return __res.first; // C++26 will also return last observed __val
- __val = __args._M_prep_for_wait_on(__addr, __vfn);
+ if (__res._M_timeout)
+   return false; // C++26 will also return last observed __val
+ __val = __args._M_setup_wait(__addr, __vfn);
}
   return true; // C++26 will also return last observed __val
 }
@@ -211,7 +208,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 {
   __detail::__wait_args __args{ __addr, __old, __order, __bare_wait };
   auto __res = __detail::__wait_for(__addr, __args, __rtime);
-  return __res.first; // C++26 will also return last observed __Val
+  return !__res._M_timeout; // C++26 will also return last observed __val
 }
 
   template
+struct __wait_result_type
+{
+  __platform_wait_t _M_val;
+  unsigned char _M_has_val : 1; // _M_val value was loaded before return.
+  unsigned char _M_timeout : 1; // Waiting function ended with timeout.
+  unsigned char _M_unused : 6;  // padding
+};
+
 enum class __wait_flags : __UINT_LEAST32_TYPE__
 {
__abi_version = 0,
@@ -166,21 +175,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template()())>>
_Tp
-   _M_prep_for_wait_on(const void* __addr, _ValFn __vfn)
+   _M_setup_wait(const void* __addr, _ValFn __vfn,
+ __wait_result_type __res = {})
{
  if constexpr (__platform_wait_uses_type<_Tp>)
{
- _Tp __val = __vfn();
- // If the wait is 

[gcc r16-989] libstdc++: Fix race condition in new atomic notify code

2025-05-30 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:97ea9d7b021c3e9f8d0c7e371d40ded811f76dac

commit r16-989-g97ea9d7b021c3e9f8d0c7e371d40ded811f76dac
Author: Jonathan Wakely 
Date:   Thu Jan 9 22:32:02 2025 +

libstdc++: Fix race condition in new atomic notify code

When using a proxy object for atomic waiting and notifying operations,
we need to ensure that the _M_ver value is always incremented by a
notifying operation, even if we return early without doing the futex
wake syscall. Otherwise we get missed wake-ups because the notifying
thread doesn't modify the value that other threads are doing a futex
wait on.

libstdc++-v3/ChangeLog:

* include/bits/atomic_wait.h (__notify_impl): Increment the
proxy value before returning early for the uncontended case.

Diff:
---
 libstdc++-v3/include/bits/atomic_wait.h | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/libstdc++-v3/include/bits/atomic_wait.h 
b/libstdc++-v3/include/bits/atomic_wait.h
index 172910a4e34f..725ea030245d 100644
--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -406,18 +406,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 {
   __waiter_pool_impl* __pool = nullptr;
 
-  if (__args & __wait_flags::__track_contention)
-   {
- __pool = &__waiter_pool_impl::_S_impl_for(__addr);
- if (!__pool->_M_waiting())
-   return;
-   }
-
   const __platform_wait_t* __wait_addr;
   if (__args & __wait_flags::__proxy_wait)
{
- if (!__pool)
-   __pool = &__waiter_pool_impl::_S_impl_for(__addr);
+ __pool = &__waiter_pool_impl::_S_impl_for(__addr);
  // Waiting for *__addr is actually done on the proxy's _M_ver.
  __wait_addr = &__pool->_M_ver;
  __atomic_fetch_add(&__pool->_M_ver, 1, __ATOMIC_RELAXED);
@@ -430,6 +422,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   else // Use the atomic variable's own address.
__wait_addr = __addr;
 
+  if (__args & __wait_flags::__track_contention)
+   {
+ if (!__pool)
+   __pool = &__waiter_pool_impl::_S_impl_for(__addr);
+ if (!__pool->_M_waiting())
+   return;
+   }
+
 #ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
   __platform_notify(__wait_addr, __all);
 #else


[gcc r16-1001] tree-optimization/120457 - avoid lowering of some single-element interleave

2025-05-30 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:0291f53f8d2343ca0d39589ebffc31d9c328d6ab

commit r16-1001-g0291f53f8d2343ca0d39589ebffc31d9c328d6ab
Author: Richard Biener 
Date:   Fri May 30 08:54:10 2025 +0200

tree-optimization/120457 - avoid lowering of some single-element interleave

The following makes sure we are not lowering single-element interleaving
schemes in a way that defeats load vectorizing later but allows the
VMAT_ELEMENTWISE fallback to be used.

PR tree-optimization/120457
* tree-vect-slp.cc (vect_lower_load_permutations): Implement
the same heuristics as load vectorization for single-element
interleaving that spans multiple vectors.

Diff:
---
 gcc/tree-vect-slp.cc | 9 +
 1 file changed, 9 insertions(+)

diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index fb2262a61376..dc89da3bf177 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -4557,6 +4557,15 @@ vect_lower_load_permutations (loop_vec_info loop_vinfo,
   if (!SLP_TREE_CHILDREN (load).is_empty ())
continue;
 
+  /* For single-element interleaving spanning multiple vectors avoid
+lowering, we want to use VMAT_ELEMENTWISE later.  */
+  if (ld_lanes_lanes == 0
+ && SLP_TREE_LANES (load) == 1
+ && !DR_GROUP_NEXT_ELEMENT (first)
+ && maybe_gt (group_lanes,
+  TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (load
+   return;
+
   /* We want to pattern-match special cases here and keep those
 alone.  Candidates are splats and load-lane.  */


[gcc/devel/omp/gcc-15] libgomp: Add OpenACC's acc_memcpy_device{, _async} routines [PR93226]

2025-05-30 Thread Tobias Burnus via Gcc-cvs
https://gcc.gnu.org/g:25bbaa8fdeeb9b9b5b04d14cd4f124dae85bb85b

commit 25bbaa8fdeeb9b9b5b04d14cd4f124dae85bb85b
Author: Tobias Burnus 
Date:   Thu May 29 22:47:06 2025 +0200

libgomp: Add OpenACC's acc_memcpy_device{,_async} routines [PR93226]

libgomp/ChangeLog:

PR libgomp/93226
* libgomp-plugin.h (GOMP_OFFLOAD_openacc_async_dev2dev): New
prototype.
* libgomp.h (struct acc_dispatch_t): Add dev2dev_func.
(gomp_copy_dev2dev): New prototype.
* libgomp.map (OACC_2.6.1): New; add acc_memcpy_device{,_async}.
* libgomp.texi (acc_memcpy_device): New.
* oacc-mem.c (memcpy_tofrom_device): Change to take from/to
device boolean; use memcpy not memmove; add early return if
size == 0 or same device + same ptr.
(acc_memcpy_to_device, acc_memcpy_to_device_async,
acc_memcpy_from_device, acc_memcpy_from_device_async): Update.
(acc_memcpy_device, acc_memcpy_device_async): New.
* openacc.f90 (acc_memcpy_device, acc_memcpy_device_async):
Add interface.
* openacc_lib.h (acc_memcpy_device, acc_memcpy_device_async):
Likewise.
* openacc.h (acc_memcpy_device, acc_memcpy_device_async): Add
prototype.
* plugin/plugin-gcn.c (GOMP_OFFLOAD_openacc_async_host2dev):
Update comment.
(GOMP_OFFLOAD_openacc_async_dev2host): Update call.
(GOMP_OFFLOAD_openacc_async_dev2dev): New.
* plugin/plugin-nvptx.c (cuda_memcpy_dev_sanity_check): New.
(GOMP_OFFLOAD_dev2dev): Call it.
(GOMP_OFFLOAD_openacc_async_dev2dev): New.
* target.c (gomp_copy_dev2dev): New.
(gomp_load_plugin_for_device): Load dev2dev and async_dev2dev.
* testsuite/libgomp.oacc-c-c++-common/acc_memcpy_device-1.c: New 
test.
* testsuite/libgomp.oacc-fortran/acc_memcpy_device-1.f90: New test.

(cherry picked from commit f4aa6b5a8d63050f5d61fcec222ed87be4c0a266)

Diff:
---
 libgomp/libgomp-plugin.h   |   2 +
 libgomp/libgomp.h  |   4 +
 libgomp/libgomp.map|   6 ++
 libgomp/libgomp.texi   |  39 +++
 libgomp/oacc-mem.c |  44 +---
 libgomp/openacc.f90|  22 
 libgomp/openacc.h  |   4 +-
 libgomp/openacc_lib.h  |  24 +
 libgomp/plugin/plugin-gcn.c|  17 +++-
 libgomp/plugin/plugin-nvptx.c  |  43 
 libgomp/target.c   |  14 +++
 .../acc_memcpy_device-1.c  |  96 +
 .../libgomp.oacc-fortran/acc_memcpy_device-1.f90   | 113 +
 13 files changed, 409 insertions(+), 19 deletions(-)

diff --git a/libgomp/libgomp-plugin.h b/libgomp/libgomp-plugin.h
index 479264be0f05..3c7741bcef88 100644
--- a/libgomp/libgomp-plugin.h
+++ b/libgomp/libgomp-plugin.h
@@ -202,6 +202,8 @@ extern bool GOMP_OFFLOAD_openacc_async_dev2host (int, void 
*, const void *, size
 struct goacc_asyncqueue *);
 extern bool GOMP_OFFLOAD_openacc_async_host2dev (int, void *, const void *, 
size_t,
 struct goacc_asyncqueue *);
+extern bool GOMP_OFFLOAD_openacc_async_dev2dev (int, void *, const void *, 
size_t,
+   struct goacc_asyncqueue *);
 extern void *GOMP_OFFLOAD_openacc_cuda_get_current_device (void);
 extern void *GOMP_OFFLOAD_openacc_cuda_get_current_context (void);
 extern void *GOMP_OFFLOAD_openacc_cuda_get_stream (struct goacc_asyncqueue *);
diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h
index 04f3c6de6592..571ac62ca998 100644
--- a/libgomp/libgomp.h
+++ b/libgomp/libgomp.h
@@ -1378,6 +1378,7 @@ typedef struct acc_dispatch_t
 __typeof (GOMP_OFFLOAD_openacc_async_exec) *exec_func;
 __typeof (GOMP_OFFLOAD_openacc_async_dev2host) *dev2host_func;
 __typeof (GOMP_OFFLOAD_openacc_async_host2dev) *host2dev_func;
+__typeof (GOMP_OFFLOAD_openacc_async_dev2dev) *dev2dev_func;
   } async;
 
   __typeof (GOMP_OFFLOAD_openacc_get_property) *get_property_func;
@@ -1485,6 +1486,9 @@ extern void gomp_copy_host2dev (struct gomp_device_descr 
*,
 extern void gomp_copy_dev2host (struct gomp_device_descr *,
struct goacc_asyncqueue *, void *, const void *,
size_t);
+extern void gomp_copy_dev2dev (struct gomp_device_descr *,
+  struct goacc_asyncqueue *, void *, const void *,
+  size_t);
 extern uintptr_t gomp_map_val (struct target_mem_desc *, void **, size_t);
 extern bool gomp_attach_pointer (struct gomp

[gcc r12-11118] aarch64: Fix CFA offsets in non-initial stack probes [PR119610]

2025-05-30 Thread Richard Sandiford via Gcc-cvs
https://gcc.gnu.org/g:e591109238fad430e94ae58f8f90b4bc9c8592a3

commit r12-8-ge591109238fad430e94ae58f8f90b4bc9c8592a3
Author: Richard Sandiford 
Date:   Fri May 30 16:35:54 2025 +0100

aarch64: Fix CFA offsets in non-initial stack probes [PR119610]

PR119610 is about incorrect CFI output for a stack probe when that
probe is not the initial allocation.  The main aarch64 stack probe
function, aarch64_allocate_and_probe_stack_space, implicitly assumed
that the incoming stack pointer pointed to the top of the frame,
and thus held the CFA.

aarch64_save_callee_saves and aarch64_restore_callee_saves use a
parameter called bytes_below_sp to track how far the stack pointer
is above the base of the static frame.  This patch does the same
thing for aarch64_allocate_and_probe_stack_space.

Also, I noticed that the SVE path was attaching the first CFA note
to the wrong instruction: it was attaching the note to the calculation
of the stack size, rather than to the r11<-sp copy.

gcc/
PR target/119610
* config/aarch64/aarch64.cc 
(aarch64_allocate_and_probe_stack_space):
Add a bytes_below_sp parameter and use it to calculate the CFA
offsets.  Attach the first SVE CFA note to the move into the
associated temporary register.
(aarch64_allocate_and_probe_stack_space): Update calls accordingly.
Start out with bytes_per_sp set to the frame size and decrement
it after each allocation.

gcc/testsuite/
PR target/119610
* g++.dg/torture/pr119610.C: New test.
* g++.target/aarch64/sve/pr119610-sve.C: Likewise.

(cherry picked from commit fa61afef18a8566d1907a5ae0e7754e1eac207d9)

Diff:
---
 gcc/config/aarch64/aarch64.cc  | 63 +-
 gcc/testsuite/g++.dg/torture/pr119610.C| 18 +++
 .../g++.target/aarch64/sve/pr119610-sve.C  | 20 +++
 3 files changed, 77 insertions(+), 24 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 74d74976f4a3..5fae003800df 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -9392,13 +9392,16 @@ aarch64_stack_clash_protection_alloca_probe_range (void)
 
 
 /* Allocate POLY_SIZE bytes of stack space using TEMP1 and TEMP2 as scratch
-   registers.  If POLY_SIZE is not large enough to require a probe this 
function
-   will only adjust the stack.  When allocating the stack space
-   FRAME_RELATED_P is then used to indicate if the allocation is frame related.
-   FINAL_ADJUSTMENT_P indicates whether we are allocating the area below
-   the saved registers.  If we are then we ensure that any allocation
-   larger than the ABI defined buffer needs a probe so that the
-   invariant of having a 1KB buffer is maintained.
+   registers, given that the stack pointer is currently BYTES_BELOW_SP bytes
+   above the bottom of the static frame.
+
+   If POLY_SIZE is not large enough to require a probe this function will only
+   adjust the stack.  When allocating the stack space FRAME_RELATED_P is then
+   used to indicate if the allocation is frame related.  FINAL_ADJUSTMENT_P
+   indicates whether we are allocating the area below the saved registers.
+   If we are then we ensure that any allocation larger than the ABI defined
+   buffer needs a probe so that the invariant of having a 1KB buffer is
+   maintained.
 
We emit barriers after each stack adjustment to prevent optimizations from
breaking the invariant that we never drop the stack more than a page.  This
@@ -9411,6 +9414,7 @@ aarch64_stack_clash_protection_alloca_probe_range (void)
 static void
 aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
poly_int64 poly_size,
+   poly_int64 bytes_below_sp,
bool frame_related_p,
bool final_adjustment_p)
 {
@@ -9471,8 +9475,8 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx 
temp2,
   aarch64_add_offset (Pmode, temp1, CONST0_RTX (Pmode),
  poly_size, temp1, temp2, false, true);
 
-  rtx_insn *insn = get_last_insn ();
-
+  auto initial_cfa_offset = frame.frame_size - bytes_below_sp;
+  auto final_cfa_offset = initial_cfa_offset + poly_size;
   if (frame_related_p)
{
  /* This is done to provide unwinding information for the stack
@@ -9482,28 +9486,31 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx 
temp2,
 The tie will expand to nothing but the optimizers will not touch
 the instruction.  */
  rtx stack_ptr_copy = gen_rtx_REG (Pmode, STACK_CLASH_SVE_CFA_REGNUM);
- emit_move_insn (stack_ptr_copy, stack_pointer_rtx);
+ auto *insn = emit_move_insn (stack_ptr_copy, stack_poin

[gcc r16-1019] c++: more xobj lambda 'this' capture [PR113563]

2025-05-30 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:611d59589d8c48db051b31e727d7f52910a4cbcd

commit r16-1019-g611d59589d8c48db051b31e727d7f52910a4cbcd
Author: Jason Merrill 
Date:   Fri May 30 08:59:31 2025 -0400

c++: more xobj lambda 'this' capture [PR113563]

Nathaniel shared a more extensive test, which revealed more needed fixes.

PR c++/113563

gcc/cp/ChangeLog:

* lambda.cc (lambda_capture_field_type): Handle 'this' normally.
(build_capture_proxy): Special-case 'this' by-ref capture more.
(nonlambda_method_basetype): Look through xobj lambdas.

gcc/testsuite/ChangeLog:

* g++.dg/cpp23/explicit-obj-lambda17.C: New test.

Diff:
---
 gcc/cp/lambda.cc   |  28 ++--
 gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda17.C | 144 +
 2 files changed, 161 insertions(+), 11 deletions(-)

diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index 34c7defb6049..2a9061acf550 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -218,9 +218,7 @@ lambda_capture_field_type (tree expr, bool explicit_init_p,
   tree type;
   bool is_this = is_this_parameter (tree_strip_nop_conversions (expr));
 
-  if (is_this)
-type = TREE_TYPE (expr);
-  else if (explicit_init_p)
+  if (explicit_init_p)
 {
   tree auto_node = make_auto ();
 
@@ -259,7 +257,7 @@ lambda_capture_field_type (tree expr, bool explicit_init_p,
 
   type = non_reference (unlowered_expr_type (expr));
 
-  if (by_reference_p || TREE_CODE (type) == FUNCTION_TYPE)
+  if ((by_reference_p && !is_this) || TREE_CODE (type) == FUNCTION_TYPE)
type = build_reference_type (type);
 }
 
@@ -440,13 +438,21 @@ build_capture_proxy (tree member, tree init)
   else
 name = get_identifier (IDENTIFIER_POINTER (DECL_NAME (member)) + 2);
 
-  type = lambda_proxy_type (object);
-
-  if (name == this_identifier && !INDIRECT_TYPE_P (TREE_TYPE (member)))
+  if (name == this_identifier && TYPE_PTR_P (TREE_TYPE (member)))
+/* Avoid DECLTYPE_TYPE for by-ref 'this' capture in an xobj lambda; the
+   constness of the closure doesn't matter just like it doesn't matter to
+   other by-ref capture.  It's simpler to handle this special case here
+   than in lambda_proxy_type.  */
+type = TREE_TYPE (member);
+  else
 {
-  type = build_pointer_type (type);
-  type = cp_build_qualified_type (type, TYPE_QUAL_CONST);
-  object = build_fold_addr_expr_with_type (object, type);
+  type = lambda_proxy_type (object);
+  if (name == this_identifier)
+   {
+ type = build_pointer_type (type);
+ type = cp_build_qualified_type (type, TYPE_QUAL_CONST);
+ object = build_fold_addr_expr_with_type (object, type);
+   }
 }
 
   if (DECL_VLA_CAPTURE_P (member))
@@ -1052,7 +1058,7 @@ nonlambda_method_basetype (void)
 
   tree fn = TYPE_CONTEXT (type);
   if (!fn || TREE_CODE (fn) != FUNCTION_DECL
- || !DECL_IOBJ_MEMBER_FUNCTION_P (fn))
+ || !DECL_OBJECT_MEMBER_FUNCTION_P (fn))
/* No enclosing non-lambda method.  */
return NULL_TREE;
   if (!LAMBDA_FUNCTION_P (fn))
diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda17.C 
b/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda17.C
new file mode 100644
index ..ee95fff52b3b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda17.C
@@ -0,0 +1,144 @@
+// PR c++/113563
+// { dg-do run { target c++23 } }
+
+template 
+T&& move(T& value) { return static_cast(value); }
+
+template  constexpr bool is_same = false;
+template  constexpr bool is_same = true;
+
+template  constexpr bool is_const_ref = false;
+template  constexpr bool is_const_ref = true;
+template  constexpr bool is_const_ref = true;
+template  constexpr bool is_const_ref = true;
+
+template  constexpr int refqual = 0;
+template  constexpr int refqual = 1;
+template  constexpr int refqual = 2;
+
+struct S {
+  int x;
+
+  // 'this' properly acts as a pointer
+  auto byref_a() {
+return [this](this auto) { return this->x; };
+  }
+  auto byref_b() {
+return [this](this auto) { return x; };
+  }
+  auto byref_c() {
+return [&](this auto) { return x; };
+  }
+  auto byref_d() {
+return [=](this auto) { return x; };  // { dg-warning "implicit capture" }
+  }
+  auto byref_e() {
+return [this](this auto) {
+  return [this](this auto) {
+   return this->x;
+  }();
+};
+  }
+  auto byref_f() {
+return [&](this auto) {
+  return [&](this auto) {
+   return x;
+  }();
+};
+  }
+
+  // capturing '*this' stores a copy
+  auto byval_a() {
+return [*this](this auto) { return this->x; };
+  }
+  auto byval_b() {
+return [*this](this auto) { return x; };
+  }
+  auto byval_c() {
+return [*this](this auto) {
+  return [=](this auto) {  // { dg-warning "implicit capture" }
+   return this->x;
+  }();
+};
+  }
+  auto byval_d() {
+return [*this

[gcc r16-1020] Fortran: parameter inquiries of constant complex arrays [PR102599, PR114022]

2025-05-30 Thread Harald Anlauf via Gcc-cvs
https://gcc.gnu.org/g:490072b927dac2f57e541b0ee680896e23c5d998

commit r16-1020-g490072b927dac2f57e541b0ee680896e23c5d998
Author: Harald Anlauf 
Date:   Fri May 30 19:25:15 2025 +0200

Fortran: parameter inquiries of constant complex arrays [PR102599,PR114022]

PR fortran/102599
PR fortran/114022

gcc/fortran/ChangeLog:

* expr.cc (simplify_complex_array_inquiry_ref): Helper function for
simplification of inquiry references (%re/%im) of constant complex
arrays.
(find_inquiry_ref): Use it for handling %re/%im inquiry references
of complex arrays.
(scalarize_intrinsic_call): Fix frontend memleak.
* primary.cc (gfc_match_varspec): When the reference is NULL, the
previous simplification has succeeded in evaluating inquiry
references also of arrays.

gcc/testsuite/ChangeLog:

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

Diff:
---
 gcc/fortran/expr.cc  |  84 -
 gcc/fortran/primary.cc   |   3 +
 gcc/testsuite/gfortran.dg/inquiry_type_ref_8.f90 | 214 +++
 3 files changed, 297 insertions(+), 4 deletions(-)

diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc
index bf858ea5791f..b0495b7733ee 100644
--- a/gcc/fortran/expr.cc
+++ b/gcc/fortran/expr.cc
@@ -1838,6 +1838,55 @@ find_substring_ref (gfc_expr *p, gfc_expr **newp)
 }
 
 
+/* Simplify inquiry references (%re/%im) of constant complex arrays.
+   Used by find_inquiry_ref.  */
+
+static gfc_expr *
+simplify_complex_array_inquiry_ref (gfc_expr *p, inquiry_type inquiry)
+{
+  gfc_expr *e, *r, *result;
+  gfc_constructor_base base;
+  gfc_constructor *c;
+
+  if ((inquiry != INQUIRY_RE && inquiry != INQUIRY_IM)
+  || p->expr_type != EXPR_ARRAY
+  || p->ts.type != BT_COMPLEX
+  || p->rank <= 0
+  || p->value.constructor == NULL
+  || !gfc_is_constant_array_expr (p))
+return NULL;
+
+  /* Simplify array sections.  */
+  gfc_simplify_expr (p, 0);
+
+  result = gfc_get_array_expr (BT_REAL, p->ts.kind, &p->where);
+  result->rank = p->rank;
+  result->shape = gfc_copy_shape (p->shape, p->rank);
+
+  base = p->value.constructor;
+  for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
+{
+  e = c->expr;
+  if (e->expr_type != EXPR_CONSTANT)
+   goto fail;
+
+  r = gfc_get_constant_expr (BT_REAL, e->ts.kind, &e->where);
+  if (inquiry == INQUIRY_RE)
+   mpfr_set (r->value.real, mpc_realref (e->value.complex), GFC_RND_MODE);
+  else
+   mpfr_set (r->value.real, mpc_imagref (e->value.complex), GFC_RND_MODE);
+
+  gfc_constructor_append_expr (&result->value.constructor, r, &e->where);
+}
+
+  return result;
+
+fail:
+  gfc_free_expr (result);
+  return NULL;
+}
+
+
 /* Pull an inquiry result out of an expression.  */
 
 static bool
@@ -1848,6 +1897,7 @@ find_inquiry_ref (gfc_expr *p, gfc_expr **newp)
   gfc_ref *inquiry_head;
   gfc_ref *ref_ss = NULL;
   gfc_expr *tmp;
+  bool nofail = false;
 
   tmp = gfc_copy_expr (p);
 
@@ -1947,24 +1997,50 @@ find_inquiry_ref (gfc_expr *p, gfc_expr **newp)
  break;
 
case INQUIRY_RE:
- if (tmp->ts.type != BT_COMPLEX || tmp->expr_type != EXPR_CONSTANT)
+ if (tmp->ts.type != BT_COMPLEX)
goto cleanup;
 
  if (!gfc_notify_std (GFC_STD_F2008, "RE part_ref at %C"))
goto cleanup;
 
+ if (tmp->expr_type == EXPR_ARRAY)
+   {
+ *newp = simplify_complex_array_inquiry_ref (tmp, INQUIRY_RE);
+ if (*newp != NULL)
+   {
+ nofail = true;
+ break;
+   }
+   }
+
+ if (tmp->expr_type != EXPR_CONSTANT)
+   goto cleanup;
+
  *newp = gfc_get_constant_expr (BT_REAL, tmp->ts.kind, &tmp->where);
  mpfr_set ((*newp)->value.real,
mpc_realref (tmp->value.complex), GFC_RND_MODE);
  break;
 
case INQUIRY_IM:
- if (tmp->ts.type != BT_COMPLEX || tmp->expr_type != EXPR_CONSTANT)
+ if (tmp->ts.type != BT_COMPLEX)
goto cleanup;
 
  if (!gfc_notify_std (GFC_STD_F2008, "IM part_ref at %C"))
goto cleanup;
 
+ if (tmp->expr_type == EXPR_ARRAY)
+   {
+ *newp = simplify_complex_array_inquiry_ref (tmp, INQUIRY_IM);
+ if (*newp != NULL)
+   {
+ nofail = true;
+ break;
+   }
+   }
+
+ if (tmp->expr_type != EXPR_CONSTANT)
+   goto cleanup;
+
  *newp = gfc_get_constant_expr (BT_REAL, tmp->ts.kind, &tmp->where);
  mpfr_set ((*newp)->value.real,
mpc_imagref (tmp->value.complex), GFC_RND_MODE);
@@ -1977,7 +2053,7 @@ find_inquiry_ref (gfc_expr *p, gfc_expr **newp)
 
   if (!(*newp))
 goto cleanup;
-  else if

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

2025-05-30 Thread Mikael Morin via Gcc-cvs
https://gcc.gnu.org/g:9b35083d58c92a70a47c16be0d1d84d09f7a6e23

commit 9b35083d58c92a70a47c16be0d1d84d09f7a6e23
Author: Mikael Morin 
Date:   Fri May 30 15:33:58 2025 +0200

Correction régression char_length_23

Diff:
---
 gcc/fortran/Make-lang.in|   2 +-
 gcc/fortran/trans-descriptor.cc | 123 +++-
 gcc/fortran/trans-types.cc  | 307 +++-
 3 files changed, 299 insertions(+), 133 deletions(-)

diff --git a/gcc/fortran/Make-lang.in b/gcc/fortran/Make-lang.in
index 2ddb0366e9dc..2914855eb225 100644
--- a/gcc/fortran/Make-lang.in
+++ b/gcc/fortran/Make-lang.in
@@ -45,7 +45,7 @@ GFORTRAN_TARGET_INSTALL_NAME := 
$(target_noncanonical)-$(shell echo gfortran|sed
 #^L
 
 # Use strict warnings for this front end.
-fortran-warn = $(STRICT_WARN)
+fortran-warn = $(STRICT_WARN) -Wno-error=infinite-recursion
 
 # These are the groups of object files we have.  The F95_PARSER_OBJS are
 # all the front end files, the F95_OBJS are the files for the translation
diff --git a/gcc/fortran/trans-descriptor.cc b/gcc/fortran/trans-descriptor.cc
index 3fdc2f4c5d72..d2f882d7076c 100644
--- a/gcc/fortran/trans-descriptor.cc
+++ b/gcc/fortran/trans-descriptor.cc
@@ -174,6 +174,85 @@ gfc_get_cfi_dim_sm (tree desc, tree idx)
 #define UBOUND_SUBFIELD 2
 
 
+static tree
+substitute_placeholder_in_type (tree type, tree root_struct)
+{
+  tree type_size = TYPE_SIZE (type);
+  tree modified_type_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (type_size,
+   root_struct);
+  tree type_size_unit = TYPE_SIZE_UNIT (type);
+  tree modified_type_size_unit = SUBSTITUTE_PLACEHOLDER_IN_EXPR 
(type_size_unit,
+root_struct);
+
+  switch (TREE_CODE (type))
+{
+case POINTER_TYPE:
+  {
+   tree subtype = TREE_TYPE (type);
+   tree modified_subtype = substitute_placeholder_in_type (subtype,
+   root_struct);
+   if (modified_subtype == subtype
+   && modified_type_size == type_size
+   && modified_type_size_unit == type_size_unit)
+ return type;
+   else
+ return build_pointer_type (modified_subtype);
+  }
+  break;
+
+case ARRAY_TYPE:
+  {
+   tree elt_type = TREE_TYPE (type);
+   tree modified_elt_type = substitute_placeholder_in_type (elt_type,
+root_struct);
+   tree idx_type = TYPE_DOMAIN (type);
+   tree modified_idx_type = substitute_placeholder_in_type (idx_type,
+root_struct);
+   if (modified_elt_type == elt_type
+   && modified_idx_type == idx_type
+   && modified_type_size == type_size
+   && modified_type_size_unit == type_size_unit)
+ return type;
+   else
+ {
+   tree new_type = build_array_type (modified_elt_type,
+ modified_idx_type);
+   TYPE_STRING_FLAG (new_type) = TYPE_STRING_FLAG (type);
+   return new_type;
+ }
+  }
+  break;
+
+case INTEGER_TYPE:
+  {
+   tree min_val = TYPE_MIN_VALUE (type);
+   tree modified_min_val = SUBSTITUTE_PLACEHOLDER_IN_EXPR (min_val,
+   root_struct);
+   tree max_val = TYPE_MAX_VALUE (type);
+   tree modified_max_val = SUBSTITUTE_PLACEHOLDER_IN_EXPR (max_val,
+   root_struct);
+   if (modified_min_val == min_val
+   && modified_max_val == max_val
+   && modified_type_size == type_size
+   && modified_type_size_unit == type_size_unit)
+ return type;
+   else
+ {
+   tree new_type = build_range_type (type, modified_min_val,
+ modified_max_val);
+   TYPE_SIZE (new_type) = modified_type_size;
+   TYPE_SIZE_UNIT (new_type) = modified_type_size_unit;
+   return new_type;
+ }
+  }
+  break;
+
+default:
+  gcc_unreachable ();
+}
+}
+
+
 namespace gfc_descriptor
 {
 
@@ -223,7 +302,11 @@ conv_data_get (tree desc)
   gcc_assert (TREE_CODE (type) != REFERENCE_TYPE);
 
   tree field = get_data (desc);
-  tree t = fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), field);
+  tree target_type = GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
+  gcc_assert (TREE_CODE (target_type) == POINTER_TYPE);
+  if (type_contains_placeholder_p (TREE_TYPE (target_type)))
+target_type = substitute_placeholder_in_type (target_type, desc);
+  tree t = fold_convert (target_type, field);
   return non_lvalue_loc (input_location, t);
 }
 
@@ -3025,6 +3108,42 @@ gfc_conv_descriptor_cosize (tree desc, int rank, int 
corank)
 }
 
 
+static bool
+placeholder_free_element_type (tree type

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

2025-05-30 Thread Mikael Morin via Gcc-cvs
https://gcc.gnu.org/g:88e247296d234abb9545f02fb4f50cd9a9cf36a4

commit 88e247296d234abb9545f02fb4f50cd9a9cf36a4
Author: Mikael Morin 
Date:   Fri May 30 19:40:58 2025 +0200

Correction régression associated_target_6

Diff:
---
 gcc/fortran/trans-types.cc | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc
index 7fe372be4397..a22367fe7e9d 100644
--- a/gcc/fortran/trans-types.cc
+++ b/gcc/fortran/trans-types.cc
@@ -3225,7 +3225,8 @@ gfc_get_derived_type (gfc_symbol * derived, int codimen)
do_loop = false;
for (c = derived->components, i = 0; c; c = c->next, i++)
  {
-   if (c->backend_decl)
+   if (fields.length () > i
+   && fields[i] != nullptr)
  continue;
 
bool same_alloc_type = c->attr.allocatable


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

2025-05-30 Thread Mikael Morin via Gcc-cvs
https://gcc.gnu.org/g:4f145c0ee81b675c9ff428bea963da237234b31c

commit 4f145c0ee81b675c9ff428bea963da237234b31c
Author: Mikael Morin 
Date:   Fri May 30 18:59:44 2025 +0200

Correction régression associate_47

Diff:
---
 gcc/fortran/trans-descriptor.cc |  97 ---
 gcc/fortran/trans-expr.cc   |   6 ++-
 gcc/fortran/trans-types.cc  | 109 
 gcc/fortran/trans-types.h   |   3 ++
 4 files changed, 127 insertions(+), 88 deletions(-)

diff --git a/gcc/fortran/trans-descriptor.cc b/gcc/fortran/trans-descriptor.cc
index d2f882d7076c..9907aaa7e7a6 100644
--- a/gcc/fortran/trans-descriptor.cc
+++ b/gcc/fortran/trans-descriptor.cc
@@ -174,85 +174,6 @@ gfc_get_cfi_dim_sm (tree desc, tree idx)
 #define UBOUND_SUBFIELD 2
 
 
-static tree
-substitute_placeholder_in_type (tree type, tree root_struct)
-{
-  tree type_size = TYPE_SIZE (type);
-  tree modified_type_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (type_size,
-   root_struct);
-  tree type_size_unit = TYPE_SIZE_UNIT (type);
-  tree modified_type_size_unit = SUBSTITUTE_PLACEHOLDER_IN_EXPR 
(type_size_unit,
-root_struct);
-
-  switch (TREE_CODE (type))
-{
-case POINTER_TYPE:
-  {
-   tree subtype = TREE_TYPE (type);
-   tree modified_subtype = substitute_placeholder_in_type (subtype,
-   root_struct);
-   if (modified_subtype == subtype
-   && modified_type_size == type_size
-   && modified_type_size_unit == type_size_unit)
- return type;
-   else
- return build_pointer_type (modified_subtype);
-  }
-  break;
-
-case ARRAY_TYPE:
-  {
-   tree elt_type = TREE_TYPE (type);
-   tree modified_elt_type = substitute_placeholder_in_type (elt_type,
-root_struct);
-   tree idx_type = TYPE_DOMAIN (type);
-   tree modified_idx_type = substitute_placeholder_in_type (idx_type,
-root_struct);
-   if (modified_elt_type == elt_type
-   && modified_idx_type == idx_type
-   && modified_type_size == type_size
-   && modified_type_size_unit == type_size_unit)
- return type;
-   else
- {
-   tree new_type = build_array_type (modified_elt_type,
- modified_idx_type);
-   TYPE_STRING_FLAG (new_type) = TYPE_STRING_FLAG (type);
-   return new_type;
- }
-  }
-  break;
-
-case INTEGER_TYPE:
-  {
-   tree min_val = TYPE_MIN_VALUE (type);
-   tree modified_min_val = SUBSTITUTE_PLACEHOLDER_IN_EXPR (min_val,
-   root_struct);
-   tree max_val = TYPE_MAX_VALUE (type);
-   tree modified_max_val = SUBSTITUTE_PLACEHOLDER_IN_EXPR (max_val,
-   root_struct);
-   if (modified_min_val == min_val
-   && modified_max_val == max_val
-   && modified_type_size == type_size
-   && modified_type_size_unit == type_size_unit)
- return type;
-   else
- {
-   tree new_type = build_range_type (type, modified_min_val,
- modified_max_val);
-   TYPE_SIZE (new_type) = modified_type_size;
-   TYPE_SIZE_UNIT (new_type) = modified_type_size_unit;
-   return new_type;
- }
-  }
-  break;
-
-default:
-  gcc_unreachable ();
-}
-}
-
-
 namespace gfc_descriptor
 {
 
@@ -303,9 +224,9 @@ conv_data_get (tree desc)
 
   tree field = get_data (desc);
   tree target_type = GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
-  gcc_assert (TREE_CODE (target_type) == POINTER_TYPE);
-  if (type_contains_placeholder_p (TREE_TYPE (target_type)))
-target_type = substitute_placeholder_in_type (target_type, desc);
+  if (gfc_type_contains_placeholder_p (target_type))
+target_type = gfc_substitute_placeholder_in_type (target_type, desc,
+ nullptr);
   tree t = fold_convert (target_type, field);
   return non_lvalue_loc (input_location, t);
 }
@@ -314,7 +235,10 @@ void
 conv_data_set (stmtblock_t *block, tree desc, tree value)
 {
   tree field = get_data (desc);
-  gfc_add_modify (block, field, fold_convert (TREE_TYPE (field), value));
+  tree type = TREE_TYPE (field);
+  if (gfc_type_contains_placeholder_p (type))
+type = gfc_substitute_placeholder_in_type (type, desc, block);
+  gfc_add_modify (block, field, fold_convert (type, value));
 }
 
 tree
@@ -3115,9 +3039,7 @@ placeholder_free_element_type (tree type)
 return true;
 
   tree data_ptr_type = GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
-  gcc_assert (TRE

[gcc r16-982] c: fix ICE for mutually recursive structures [PR120381]

2025-05-30 Thread Martin Uecker via Gcc-cvs
https://gcc.gnu.org/g:0e0f963bcfbfce351dd4aad82e6dbc6fc84a0724

commit r16-982-g0e0f963bcfbfce351dd4aad82e6dbc6fc84a0724
Author: Martin Uecker 
Date:   Thu May 29 19:13:46 2025 +0200

c: fix ICE for mutually recursive structures [PR120381]

For invalid nesting of a structure definition in a definition
of itself or when using a rather obscure construction using statement
expressions, we can create mutually recursive pairs of non-identical
but compatible structure types.  This can lead to invalid composite
types and an ICE.  If we detect recursion even for swapped pairs
when forming composite types, this is avoided.

PR c/120381

gcc/c/ChangeLog:
* c-typeck.cc (composite_type_internal): Stop recursion for
swapped pairs.

gcc/testsuite/ChangeLog:
* gcc.dg/pr120381.c: New test.
* gcc.dg/gnu23-tag-composite-6.c: New test.

Diff:
---
 gcc/c/c-typeck.cc|  2 +-
 gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c | 11 +++
 gcc/testsuite/gcc.dg/pr120381.c  | 10 ++
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 360216b96621..e5dd8d54c516 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -776,7 +776,7 @@ composite_type_internal (tree t1, tree t2, struct 
composite_cache* cache)
 construction, return it.  */
 
  for (struct composite_cache *c = cache; c != NULL; c = c->next)
-   if (c->t1 == t1 && c->t2 == t2)
+   if ((c->t1 == t1 && c->t2 == t2) || (c->t1 == t2 && c->t2 == t1))
   return c->composite;
 
  /* Otherwise, create a new type node and link it into the cache.  */
diff --git a/gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c 
b/gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c
new file mode 100644
index ..2411b04d3884
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu23-tag-composite-6.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu23" } */
+
+int f()
+{
+typedef struct foo bar;
+struct foo { typeof(({ (struct foo { bar * x; }){ }; })) * x; } *q;
+typeof(q->x) p;
+1 ? p : q;
+}
+
diff --git a/gcc/testsuite/gcc.dg/pr120381.c b/gcc/testsuite/gcc.dg/pr120381.c
new file mode 100644
index ..5c017e60c6b2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120381.c
@@ -0,0 +1,10 @@
+/* PR120381 */
+/* { dg-do compile } */
+
+struct A {
+  struct A {   /* { dg-error "nested redefinition" } */
+struct A *p;
+  } *p;
+};
+int foo(const struct A *q) { return q->p == q; }
+


[gcc r16-983] OpenMP: C++ "declare mapper" support

2025-05-30 Thread Tobias Burnus via Gcc-cvs
https://gcc.gnu.org/g:48973e8783e59462ab6e34d5d48b74a2146a05f1

commit r16-983-g48973e8783e59462ab6e34d5d48b74a2146a05f1
Author: Julian Brown 
Date:   Fri May 30 08:41:00 2025 +0200

OpenMP: C++ "declare mapper" support

This patch adds support for OpenMP 5.0 "declare mapper" functionality
for C++.  I've merged it to og13 based on the last version
posted upstream, with some minor changes due to the newly-added
'present' map modifier support.  There's also a fix to splay-tree
traversal in gimplify.cc:omp_instantiate_implicit_mappers, and this patch
omits the rearrangement of gimplify.cc:gimplify_{scan,adjust}_omp_clauses
that I separated out into its own patch and applied (to og13) already.

gcc/c-family/
* c-common.h (c_omp_region_type): Add C_ORT_DECLARE_MAPPER and
C_ORT_OMP_DECLARE_MAPPER codes.
(omp_mapper_list): Add forward declaration.
(c_omp_find_nested_mappers, c_omp_instantiate_mappers): Add 
prototypes.
* c-omp.cc (c_omp_find_nested_mappers): New function.
(remap_mapper_decl_info): New struct.
(remap_mapper_decl_1, omp_instantiate_mapper,
c_omp_instantiate_mappers): New functions.

gcc/cp/
* constexpr.cc (reduced_constant_expression_p): Add 
OMP_DECLARE_MAPPER
case.
(cxx_eval_constant_expression, potential_constant_expression_1):
Likewise.
* cp-gimplify.cc (cxx_omp_finish_mapper_clauses): New function.
* cp-objcp-common.h (LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES,
LANG_HOOKS_OMP_MAPPER_LOOKUP, 
LANG_HOOKS_OMP_EXTRACT_MAPPER_DIRECTIVE,
LANG_HOOKS_OMP_MAP_ARRAY_SECTION): Define langhooks.
* cp-tree.h (lang_decl_base): Add omp_declare_mapper_p field.  
Recount
spare bits comment.
(DECL_OMP_DECLARE_MAPPER_P): New macro.
(omp_mapper_id): Add prototype.
(cp_check_omp_declare_mapper): Add prototype.
(omp_instantiate_mappers): Add prototype.
(cxx_omp_finish_mapper_clauses): Add prototype.
(cxx_omp_mapper_lookup): Add prototype.
(cxx_omp_extract_mapper_directive): Add prototype.
(cxx_omp_map_array_section): Add prototype.
* decl.cc (check_initializer): Add OpenMP declare mapper support.
(cp_finish_decl): Set DECL_INITIAL for OpenMP declare mapper var 
decls
as appropriate.
* decl2.cc (mark_used): Instantiate OpenMP "declare mapper" magic 
var
decls.
* error.cc (dump_omp_declare_mapper): New function.
(dump_simple_decl): Use above.
* parser.cc (cp_parser_omp_clause_map): Add KIND parameter.  Support
"mapper" modifier.
(cp_parser_omp_all_clauses): Add KIND argument to
cp_parser_omp_clause_map call.
(cp_parser_omp_target): Call omp_instantiate_mappers before
finish_omp_clauses.
(cp_parser_omp_declare_mapper): New function.
(cp_parser_omp_declare): Add "declare mapper" support.
* pt.cc (tsubst_decl): Adjust name of "declare mapper" magic var 
decls
once we know their type.
(tsubst_omp_clauses): Call omp_instantiate_mappers before
finish_omp_clauses, for target regions.
(tsubst_expr): Support OMP_DECLARE_MAPPER nodes.
(instantiate_decl): Instantiate initialiser (i.e definition) for 
OpenMP
declare mappers.
* semantics.cc (gimplify.h): Include.
(omp_mapper_id, omp_mapper_lookup, omp_extract_mapper_directive,
cxx_omp_map_array_section, cp_check_omp_declare_mapper): New 
functions.
(finish_omp_clauses): Delete GOMP_MAP_PUSH_MAPPER_NAME and
GOMP_MAP_POP_MAPPER_NAME artificial clauses.
(omp_target_walk_data): Add MAPPERS field.
(finish_omp_target_clauses_r): Scan for uses of struct/union/class 
type
variables.
(finish_omp_target_clauses): Create artificial mapper binding 
clauses
for used structs/unions/classes in offload region.

gcc/fortran/
* parse.cc (tree.h, fold-const.h, tree-hash-traits.h): Add includes
(for additions to omp-general.h).

gcc/
* gimplify.cc (gimplify_omp_ctx): Add IMPLICIT_MAPPERS field.
(new_omp_context): Initialise IMPLICIT_MAPPERS hash map.
(delete_omp_context): Delete IMPLICIT_MAPPERS hash map.
(instantiate_mapper_info): New structs.
(remap_mapper_decl_1, omp_mapper_copy_decl, omp_instantiate_mapper,
omp_instantiate_implicit_mappers): New functions.
(gimplify_scan_omp_clauses): Handle MAPPER_BINDING clauses.
(gimplify_adjust_omp_clauses): Instantiate implicit declared 
mappers.
(gimplify_omp_declare_mapper): New fu

[gcc r16-1002] diagnostics: consolidate calls to colorizer::set_named_color

2025-05-30 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:333628a1e2964193c6d93da6332c52ba9e1640b5

commit r16-1002-g333628a1e2964193c6d93da6332c52ba9e1640b5
Author: David Malcolm 
Date:   Fri May 30 07:18:44 2025 -0400

diagnostics: consolidate calls to colorizer::set_named_color

I noticed whilst working on another issue that in diagnostic-show-locus
within the quoted source lines and the annotation underlines that when
we're showing highlight-{a,b} that we emit
  start-colorization-code, character, end-colorization-code
per *character*, rather than just when the colorization changes.

This was due to me failing to implement consolidation of such changes in
colorizer::set_named_color in r15-2015-g7d73c01ce6d1ab.

Fixed thusly, simplifying the output.

I manually inspected all of the changed testcases in a terminal with
color enabled and verified that the output is visually identical to
before.

gcc/ChangeLog:
* diagnostic-show-locus.cc (colorizer::m_current_named_color): New
field.
(colorizer::set_named_color): Use it to consolidate repeated calls
to the same color.

gcc/testsuite/ChangeLog:
* g++.dg/diagnostic/bad-binary-ops-highlight-colors.C: Update
expected multiline output for quoted source and underlines to
reflect emitting color codes when changes happen, rather than
per character.
* g++.dg/diagnostic/long-short-colorization.C: Likewise.
* g++.dg/plugin/show-template-tree-color-labels.C: Likewise.
* gcc.dg/bad-binary-ops-highlight-colors.c: Likewise.
* gcc.dg/format/colors.c: Likewise.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-show-locus.cc  | 5 +
 gcc/testsuite/g++.dg/diagnostic/bad-binary-ops-highlight-colors.C | 4 ++--
 gcc/testsuite/g++.dg/diagnostic/long-short-colorization.C | 8 
 gcc/testsuite/g++.dg/plugin/show-template-tree-color-labels.C | 4 ++--
 gcc/testsuite/gcc.dg/bad-binary-ops-highlight-colors.c| 4 ++--
 gcc/testsuite/gcc.dg/format/colors.c  | 4 ++--
 6 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/gcc/diagnostic-show-locus.cc b/gcc/diagnostic-show-locus.cc
index 397fffbb79e8..c6a0cd80ce8c 100644
--- a/gcc/diagnostic-show-locus.cc
+++ b/gcc/diagnostic-show-locus.cc
@@ -148,6 +148,7 @@ class colorizer
   const char *m_fixit_insert;
   const char *m_fixit_delete;
   const char *m_stop_color;
+  std::string m_current_named_color;
 };
 
 /* In order to handle multibyte sources properly, all of this logic needs to be
@@ -932,9 +933,13 @@ colorizer::~colorizer ()
 void
 colorizer::set_named_color (const char *color)
 {
+  if (m_current_state == STATE_NAMED_COLOR
+  && color == m_current_named_color)
+return;
   finish_state (m_current_state);
   m_current_state = STATE_NAMED_COLOR;
   pp_string (&m_pp, colorize_start (pp_show_color (&m_pp), color));
+  m_current_named_color = color;
 }
 
 /* Update state, printing color codes if necessary if there's a state
diff --git a/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops-highlight-colors.C 
b/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops-highlight-colors.C
index 12603456b484..687af3209809 100644
--- a/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops-highlight-colors.C
+++ b/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops-highlight-colors.C
@@ -23,8 +23,8 @@ int test_4 (void)
  { dg-end-multiline-output "" } */
 
   /* { dg-begin-multiline-output "" }
-   return 
callee_4a
 () + 
callee_4b
 ();
-  
~~~~~~~~~~~~
 ^ 
~~~~~~~~~~~~
+   return callee_4a () + 
callee_4b ();
+   ^ 

 |  |
 S {aka s}  T {aka t}
  { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/g++.dg/diagnostic/long-short-colorization.C 
b/gc

[gcc r14-11819] testsuite: Add testcase for GCC 13 branch s390 bug [PR120480]

2025-05-30 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:f4def864a27c41025bbed0d086fa4628921fec28

commit r14-11819-gf4def864a27c41025bbed0d086fa4628921fec28
Author: Jakub Jelinek 
Date:   Fri May 30 14:35:12 2025 +0200

testsuite: Add testcase for GCC 13 branch s390 bug [PR120480]

This got broken with r13-9727 and fixed with either of
r13-9729 or r13-9728.

2025-05-30  Jakub Jelinek  

PR target/120480
* gcc.dg/pr120480.c: New test.

(cherry picked from commit c13d5b939fee565047394475952878dc5394fb74)

Diff:
---
 gcc/testsuite/gcc.dg/pr120480.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/pr120480.c b/gcc/testsuite/gcc.dg/pr120480.c
new file mode 100644
index ..cf7b47a1151d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120480.c
@@ -0,0 +1,11 @@
+/* PR target/120480 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+struct S { int a, b, c; } s;
+
+void
+foo (void)
+{
+  struct S t = s;
+}


[gcc r16-1007] Add 'libgomp.c++/target-flex-[...].C' test cases

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:28a5bc2d4f7ae345234a15e22fd65cfad851cf04

commit r16-1007-g28a5bc2d4f7ae345234a15e22fd65cfad851cf04
Author: Waffl3x 
Date:   Mon May 26 02:38:27 2025 -0600

Add 'libgomp.c++/target-flex-[...].C' test cases

libgomp/ChangeLog:

* testsuite/libgomp.c++/target-flex-10.C: New test.
* testsuite/libgomp.c++/target-flex-100.C: New test.
* testsuite/libgomp.c++/target-flex-101.C: New test.
* testsuite/libgomp.c++/target-flex-11.C: New test.
* testsuite/libgomp.c++/target-flex-12.C: New test.
* testsuite/libgomp.c++/target-flex-2000.C: New test.
* testsuite/libgomp.c++/target-flex-2001.C: New test.
* testsuite/libgomp.c++/target-flex-2002.C: New test.
* testsuite/libgomp.c++/target-flex-2003.C: New test.
* testsuite/libgomp.c++/target-flex-30.C: New test.
* testsuite/libgomp.c++/target-flex-300.C: New test.
* testsuite/libgomp.c++/target-flex-31.C: New test.
* testsuite/libgomp.c++/target-flex-32.C: New test.
* testsuite/libgomp.c++/target-flex-33.C: New test.
* testsuite/libgomp.c++/target-flex-41.C: New test.
* testsuite/libgomp.c++/target-flex-60.C: New test.
* testsuite/libgomp.c++/target-flex-61.C: New test.
* testsuite/libgomp.c++/target-flex-62.C: New test.
* testsuite/libgomp.c++/target-flex-70.C: New test.
* testsuite/libgomp.c++/target-flex-80.C: New test.
* testsuite/libgomp.c++/target-flex-81.C: New test.
* testsuite/libgomp.c++/target-flex-90.C: New test.
* testsuite/libgomp.c++/target-flex-common.h: New test.

Co-authored-by: Thomas Schwinge 

Diff:
---
 libgomp/testsuite/libgomp.c++/target-flex-10.C | 215 ++
 libgomp/testsuite/libgomp.c++/target-flex-100.C| 210 ++
 libgomp/testsuite/libgomp.c++/target-flex-101.C| 136 
 libgomp/testsuite/libgomp.c++/target-flex-11.C | 444 +
 libgomp/testsuite/libgomp.c++/target-flex-12.C | 736 +
 libgomp/testsuite/libgomp.c++/target-flex-2000.C   |  32 +
 libgomp/testsuite/libgomp.c++/target-flex-2001.C   |  61 ++
 libgomp/testsuite/libgomp.c++/target-flex-2002.C   |  97 +++
 libgomp/testsuite/libgomp.c++/target-flex-2003.C   | 176 +
 libgomp/testsuite/libgomp.c++/target-flex-30.C |  51 ++
 libgomp/testsuite/libgomp.c++/target-flex-300.C|  49 ++
 libgomp/testsuite/libgomp.c++/target-flex-31.C |  80 +++
 libgomp/testsuite/libgomp.c++/target-flex-32.C |  50 ++
 libgomp/testsuite/libgomp.c++/target-flex-33.C |  52 ++
 libgomp/testsuite/libgomp.c++/target-flex-41.C |  94 +++
 libgomp/testsuite/libgomp.c++/target-flex-60.C |  46 ++
 libgomp/testsuite/libgomp.c++/target-flex-61.C |  54 ++
 libgomp/testsuite/libgomp.c++/target-flex-62.C |  50 ++
 libgomp/testsuite/libgomp.c++/target-flex-70.C |  26 +
 libgomp/testsuite/libgomp.c++/target-flex-80.C |  49 ++
 libgomp/testsuite/libgomp.c++/target-flex-81.C |  75 +++
 libgomp/testsuite/libgomp.c++/target-flex-90.C | 107 +++
 libgomp/testsuite/libgomp.c++/target-flex-common.h |  40 ++
 23 files changed, 2930 insertions(+)

diff --git a/libgomp/testsuite/libgomp.c++/target-flex-10.C 
b/libgomp/testsuite/libgomp.c++/target-flex-10.C
new file mode 100644
index ..8fa9af7e4140
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-flex-10.C
@@ -0,0 +1,215 @@
+/* Basic container usage.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#if __cplusplus >= 201103L
+#include 
+#include 
+#include 
+#include 
+#endif
+
+bool vector_test()
+{
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::vector vector;
+  ok = vector.empty();
+}
+  return ok;
+}
+
+bool deque_test()
+{
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::deque deque;
+  ok = deque.empty();
+}
+  return ok;
+}
+
+bool list_test()
+{
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::list list;
+  ok = list.empty();
+}
+  return ok;
+}
+
+bool map_test()
+{
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::map map;
+  ok = map.empty();
+}
+  return ok;
+}
+
+bool set_test()
+{
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::set set;
+  ok = set.empty();
+}
+  return ok;
+}
+
+bool multimap_test()
+{
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::multimap multimap;
+  ok = multimap.empty();
+}
+  return ok;
+}
+
+bool multiset_test()
+{
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::multiset multiset;
+  ok = multiset.empty();
+}
+  return ok;
+}
+
+#if __cplusplus >= 201103L
+
+bool array_test()
+{
+  static constexpr std::size_t array_size = 42;
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::array array{};
+  ok =

[gcc r16-1009] libgomp: Add testcases for concurrent access to standard C++ containers on offload targets

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:a811d1d72261da58196ccec253fd2bdb10e999db

commit r16-1009-ga811d1d72261da58196ccec253fd2bdb10e999db
Author: Kwok Cheung Yeung 
Date:   Thu May 8 20:41:16 2025 +0100

libgomp: Add testcases for concurrent access to standard C++ containers on 
offload targets

libgomp/

* testsuite/libgomp.c++/target-std__array-concurrent.C: New.
* testsuite/libgomp.c++/target-std__bitset-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__deque-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__flat_map-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__flat_multimap-concurrent.C: 
Likewise.
* testsuite/libgomp.c++/target-std__flat_multiset-concurrent.C: 
Likewise.
* testsuite/libgomp.c++/target-std__flat_set-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__forward_list-concurrent.C: 
Likewise.
* testsuite/libgomp.c++/target-std__list-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__map-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__multimap-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__multiset-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__set-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__span-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__unordered_map-concurrent.C: 
Likewise.
* 
testsuite/libgomp.c++/target-std__unordered_multimap-concurrent.C: Likewise.
* 
testsuite/libgomp.c++/target-std__unordered_multiset-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__unordered_set-concurrent.C: 
Likewise.
* testsuite/libgomp.c++/target-std__valarray-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__vector-concurrent.C: Likewise.

Co-authored-by: Thomas Schwinge 

Diff:
---
 .../libgomp.c++/target-std__array-concurrent.C | 60 
 .../libgomp.c++/target-std__bitset-concurrent.C| 67 ++
 .../libgomp.c++/target-std__deque-concurrent.C | 62 +
 .../libgomp.c++/target-std__flat_map-concurrent.C  | 71 +++
 .../target-std__flat_multimap-concurrent.C | 70 +++
 .../target-std__flat_multiset-concurrent.C | 60 
 .../libgomp.c++/target-std__flat_set-concurrent.C  | 67 ++
 .../target-std__forward_list-concurrent.C  | 81 ++
 .../libgomp.c++/target-std__list-concurrent.C  | 81 ++
 .../libgomp.c++/target-std__map-concurrent.C   | 66 ++
 .../libgomp.c++/target-std__multimap-concurrent.C  | 64 +
 .../libgomp.c++/target-std__multiset-concurrent.C  | 60 
 .../libgomp.c++/target-std__set-concurrent.C   | 66 ++
 .../libgomp.c++/target-std__span-concurrent.C  | 62 +
 .../target-std__unordered_map-concurrent.C | 66 ++
 .../target-std__unordered_multimap-concurrent.C| 65 +
 .../target-std__unordered_multiset-concurrent.C| 59 
 .../target-std__unordered_set-concurrent.C | 66 ++
 .../libgomp.c++/target-std__valarray-concurrent.C  | 64 +
 .../libgomp.c++/target-std__vector-concurrent.C| 61 
 20 files changed, 1318 insertions(+)

diff --git a/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C
new file mode 100644
index ..e97bfe60a615
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C
@@ -0,0 +1,60 @@
+// { dg-do run }
+// { dg-additional-options -DMEM_SHARED { target offload_device_shared_as } }
+
+#include 
+#include 
+#include 
+#include 
+
+#define N 5
+
+void init (int data[])
+{
+  for (int i = 0; i < N; ++i)
+data[i] = rand ();
+}
+
+#pragma omp declare target
+bool validate (const std::array &arr, int data[])
+{
+  for (int i = 0; i < N; ++i)
+if (arr[i] != data[i] * data[i])
+  return false;
+  return true;
+}
+#pragma omp end declare target
+
+int main (void)
+{
+  int data[N];
+  bool ok;
+  std::array arr;
+
+  srand (time (NULL));
+  init (data);
+
+  #pragma omp target data map (to: data[:N]) map (alloc: arr)
+{
+  #pragma omp target
+   {
+#ifndef MEM_SHARED
+ new (&arr) std::array ();
+#endif
+ std::copy (data, data + N, arr.begin ());
+   }
+
+  #pragma omp target teams distribute parallel for
+   for (int i = 0; i < N; ++i)
+ arr[i] *= arr[i];
+
+  #pragma omp target map (from: ok)
+   {
+ ok = validate (arr, data);
+#ifndef MEM_SHARED
+ arr.~array ();
+#endif
+   }
+}
+
+  return ok ? 0 : 1;
+}
diff --git a/libgomp/testsuit

[gcc r16-1008] libgomp: Add testcases for the standard C++ math library on offload targets

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:fbcd0ad41f7cc801664da1e583f6bcad1eb02a08

commit r16-1008-gfbcd0ad41f7cc801664da1e583f6bcad1eb02a08
Author: Kwok Cheung Yeung 
Date:   Wed May 21 12:59:58 2025 +0100

libgomp: Add testcases for the standard C++ math library on offload targets

libgomp/

* testsuite/libgomp.c++/target-std__cmath.C: New.
* testsuite/libgomp.c++/target-std__complex.C: Likewise.
* testsuite/libgomp.c++/target-std__numbers.C: Likewise.

Diff:
---
 libgomp/testsuite/libgomp.c++/target-std__cmath.C  | 340 +
 .../testsuite/libgomp.c++/target-std__complex.C| 175 +++
 .../testsuite/libgomp.c++/target-std__numbers.C|  93 ++
 3 files changed, 608 insertions(+)

diff --git a/libgomp/testsuite/libgomp.c++/target-std__cmath.C 
b/libgomp/testsuite/libgomp.c++/target-std__cmath.C
new file mode 100644
index ..aaf715237a40
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-std__cmath.C
@@ -0,0 +1,340 @@
+// { dg-do run }
+// { dg-additional-options "-std=c++20" }
+
+#include 
+#include 
+
+#define FP_EQUAL(x,y) (std::abs ((x) - (y)) < 1E-6)
+
+#pragma omp declare target
+template bool test_basic ()
+{
+  T x = -3.456789;
+  T y = 1.234567;
+  T z = 5.678901;
+
+  if (std::abs (x) != -x)
+return false;
+  if (!FP_EQUAL (std::trunc (x / y) * y + std::fmod (x, y), x))
+return false;
+  if (!FP_EQUAL (x - std::round (x / y) * y, std::remainder (x, y)))
+return false;
+  if (!FP_EQUAL (std::fma (x, y, z), x * y + z))
+return false;
+  if (std::fmax (x, y) != (x > y ? x : y))
+return false;
+  if (std::fmin (x, y) != (x < y ? x : y))
+return false;
+  if (std::fdim (x, y) != std::max(x - y, (T) 0.0))
+return false;
+  if (std::fdim (y, x) != std::max(y - x, (T) 0.0))
+return false;
+  return true;
+}
+
+template bool test_exp ()
+{
+  T x = -4.567890;
+  T y = 2.345678;
+
+  if (!FP_EQUAL (std::exp (x), std::pow (std::numbers::e_v, x)))
+return false;
+  if (!FP_EQUAL (std::exp2 (y), std::pow ((T) 2.0, y)))
+return false;
+  if (!FP_EQUAL (std::expm1 (y), std::exp (y) - (T) 1.0))
+return false;
+  if (!FP_EQUAL (std::log (std::exp (x)), x))
+return false;
+  if (!FP_EQUAL (std::log10 (std::pow ((T) 10.0, y)), y))
+return false;
+  if (!FP_EQUAL (std::log2 (std::exp2 (y)), y))
+return false;
+  if (!FP_EQUAL (std::log1p (std::expm1 (y)), y))
+return false;
+  return true;
+}
+
+template bool test_power ()
+{
+  T x = 7.234251;
+  T y = 0.340128;
+
+  if (!FP_EQUAL (std::log (std::pow (x, y)) / std::log (x), y))
+return false;
+  if (!FP_EQUAL (std::sqrt (x) * std::sqrt (x), x))
+return false;
+  if (!FP_EQUAL (std::cbrt (x) * std::cbrt (x) * std::cbrt (x), x))
+return false;
+  if (!FP_EQUAL (std::hypot (x, y), std::sqrt (x * x + y * y)))
+return false;
+  return true;
+}
+
+template bool test_trig ()
+{
+  T theta = std::numbers::pi / 4;
+  T phi = std::numbers::pi / 6;
+
+  if (!FP_EQUAL (std::sin (theta), std::sqrt ((T) 2) / 2))
+return false;
+  if (!FP_EQUAL (std::sin (phi), 0.5))
+return false;
+  if (!FP_EQUAL (std::cos (theta), std::sqrt ((T) 2) / 2))
+return false;
+  if (!FP_EQUAL (std::cos (phi), std::sqrt ((T) 3) / 2))
+return false;
+  if (!FP_EQUAL (std::tan (theta), 1.0))
+return false;
+  if (!FP_EQUAL (std::tan (phi), std::sqrt ((T) 3) / 3))
+return false;
+
+  T x = 0.33245623;
+
+  if (!FP_EQUAL (std::asin (std::sin (x)), x))
+return false;
+  if (!FP_EQUAL (std::acos (std::cos (x)), x))
+return false;
+  if (!FP_EQUAL (std::atan (std::tan (x)), x))
+return false;
+  if (!FP_EQUAL (std::atan2 (std::sin (x), std::cos (x)), x))
+return false;
+  return true;
+}
+
+template bool test_hyperbolic ()
+{
+  T x = 0.7423532;
+
+  if (!FP_EQUAL (std::sinh (x), (std::exp (x) - std::exp (-x)) / (T) 2.0))
+return false;
+  if (!FP_EQUAL (std::cosh (x), (std::exp (x) + std::exp (-x)) / (T) 2.0))
+return false;
+  if (!FP_EQUAL (std::tanh (x), std::sinh (x) / std::cosh (x)))
+return false;
+  if (!FP_EQUAL (std::asinh (std::sinh (x)), x))
+return false;
+  if (!FP_EQUAL (std::acosh (std::cosh (x)), x))
+return false;
+  if (!FP_EQUAL (std::atanh (std::tanh (x)), x))
+return false;
+  return true;
+}
+
+template bool test_erf ()
+{
+  if (!FP_EQUAL (std::erf ((T) 0), 0))
+return false;
+  if (!FP_EQUAL (std::erf ((T) INFINITY), 1))
+return false;
+  if (!FP_EQUAL (std::erf ((T) -INFINITY), -1))
+return false;
+
+  if (!FP_EQUAL (std::erfc (0), 1))
+return false;
+  if (!FP_EQUAL (std::erfc ((T) INFINITY), 0))
+return false;
+  if (!FP_EQUAL (std::erfc ((T) -INFINITY), 2))
+return false;
+
+  return true;
+}
+
+template bool test_gamma ()
+{
+  if (!FP_EQUAL (std::tgamma ((T) 5), 4*3*2*1))
+return false;
+  if (!FP_EQUAL (std::tgamma ((T) 0.5), std::sqrt (std::numbers::pi_v)))
+return false;
+  if (!FP_EQUAL (std::tgamma ((T) -0.5), (T) -2 * std::

[gcc r16-1011] Add 'libgomp.c++/target-valarray-1.C'

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:2ffada0296c95898a68bdb67ced738fe788df93a

commit r16-1011-g2ffada0296c95898a68bdb67ced738fe788df93a
Author: Thomas Schwinge 
Date:   Wed Apr 30 11:29:08 2025 +0200

Add 'libgomp.c++/target-valarray-1.C'

libgomp/
* testsuite/libgomp.c++/target-std__valarray-1.C: New.
* testsuite/libgomp.c++/target-std__valarray-1.output: Likewise.

Diff:
---
 .../testsuite/libgomp.c++/target-std__valarray-1.C | 179 +
 .../libgomp.c++/target-std__valarray-1.output  |  22 +++
 2 files changed, 201 insertions(+)

diff --git a/libgomp/testsuite/libgomp.c++/target-std__valarray-1.C 
b/libgomp/testsuite/libgomp.c++/target-std__valarray-1.C
new file mode 100644
index ..865cde2e66b1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-std__valarray-1.C
@@ -0,0 +1,179 @@
+// { dg-additional-options -std=c++20 }
+// { dg-output-file target-std__valarray-1.output }
+
+#include 
+#include 
+#include 
+
+
+/*TODO Work around PR118484 "ICE during IPA pass: cp, segfault in 
determine_versionability ipa-cp.cc:467".
+
+We can't:
+
+#pragma omp declare target(std::basic_streambuf>::basic_streambuf)
+
+... because:
+
+error: overloaded function name ‘std::basic_streambuf::__ct ’ in 
clause ‘enter’
+
+Therefore, use dummy classes in '#pragma omp declare target':
+*/
+
+#pragma omp declare target
+
+// For 'std::basic_streambuf >::basic_streambuf':
+
+class dummy_basic_streambuf__char
+  : public std::basic_streambuf
+{
+public:
+  dummy_basic_streambuf__char() {}
+};
+
+// For 'std::basic_ios >::basic_ios()':
+
+class dummy_basic_ios__char
+  : public std::basic_ios
+{
+public:
+  dummy_basic_ios__char() {}
+};
+
+#pragma omp end declare target
+
+
+int main()
+{
+  // Due to PR120021 "Offloading vs. C++ 'std::initializer_list'", we can't 
construct these on the device.
+  std::initializer_list v1_i = {10, 20, 30, 40, 50};
+  const int *v1_i_data = std::data(v1_i);
+  size_t v1_i_size = v1_i.size();
+  std::initializer_list v2_i = {5, 4, 3, 2, 1};
+  const int *v2_i_data = std::data(v2_i);
+  size_t v2_i_size = v2_i.size();
+  std::initializer_list shiftData_i = {1, 2, 3, 4, 5};
+  const int *shiftData_i_data = std::data(shiftData_i);
+  size_t shiftData_i_size = shiftData_i.size();
+#pragma omp target \
+  defaultmap(none) \
+  map(to: v1_i_data[:v1_i_size], v1_i_size, \
+  v2_i_data[:v2_i_size], v2_i_size, \
+  shiftData_i_data[:shiftData_i_size], shiftData_i_size)
+  {
+/* Manually set up a buffer we can stream into, similar to 'cout << 
[...]', and print it at the end of region.  */
+std::stringbuf out_b;
+std::ostream out(&out_b);
+
+std::valarray v1(v1_i_data, v1_i_size);
+out << "\nv1:";
+for (auto val : v1)
+  out << " " << val;
+
+std::valarray v2(v2_i_data, v2_i_size);
+out << "\nv2:";
+for (auto val : v2)
+  out << " " << val;
+
+std::valarray sum = v1 + v2;
+out << "\nv1 + v2:";
+for (auto val : sum)
+  out << " " << val;
+
+std::valarray diff = v1 - v2;
+out << "\nv1 - v2:";
+for (auto val : diff)
+  out << " " << val;
+
+std::valarray product = v1 * v2;
+out << "\nv1 * v2:";
+for (auto val : product)
+  out << " " << val;
+
+std::valarray quotient = v1 / v2;
+out << "\nv1 / v2:";
+for (auto val : quotient)
+  out << " " << val;
+
+std::valarray squares = pow(v1, 2);
+out << "\npow(v1, 2):";
+for (auto val : squares)
+  out << " " << val;
+
+std::valarray sinhs = sinh(v2);
+out << "\nsinh(v2):";
+for (auto val : sinhs)
+  out << " " << val;
+
+std::valarray logs = log(v1 * v2);
+out << "\nlog(v1 * v2):";
+for (auto val : logs)
+  out << " " << val;
+
+std::valarray data(12);
+for (size_t i = 0; i < data.size(); ++i)
+  data[i] = i;
+out << "\nOriginal array:";
+for (auto val : data)
+  out << " " << val;
+
+std::slice slice1(2, 5, 1);
+std::valarray sliced1 = data[slice1];
+out << "\nSlice(2, 5, 1):";
+for (auto val : sliced1)
+  out << " " << val;
+
+std::slice slice2(1, 4, 3);
+std::valarray sliced2 = data[slice2];
+out << "\nSlice(1, 4, 3):";
+for (auto val : sliced2)
+  out << " " << val;
+
+data[slice1] = 99;
+out << "\nArray after slice modification:";
+for (auto val : data)
+  out << " " << val;
+
+std::valarray mask = (v1 > 20);
+out << "\nElements of v1 > 20:";
+for (size_t i = 0; i < v1.size(); ++i)
+  {
+   if (mask[i])
+ out << " " << v1[i];
+  }
+
+std::valarray masked = v1[mask];
+out << "\nMasked array:";
+for (auto val : masked)
+  out << " " << val;
+
+std::valarray shiftData(shiftData_i_data, shiftData_i_size);
+out << "\nOriginal shiftData:";
+for (auto val : shiftData)
+  out << " " << val;
+
+std::valarray shifted = shiftData.shift(2);
+out << "\nshift(2):";
+for (auto val : 

[gcc r16-1010] libgomp: Add testcases for concurrent access to standard C++ containers on offload targets, a number

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:83ca283853f195a08d2f758580a369bc6a076122

commit r16-1010-g83ca283853f195a08d2f758580a369bc6a076122
Author: Thomas Schwinge 
Date:   Fri May 30 11:37:46 2025 +0200

libgomp: Add testcases for concurrent access to standard C++ containers on 
offload targets, a number of USM variants

libgomp/
* testsuite/libgomp.c++/target-std__array-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__array-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__bitset-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__deque-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__deque-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C: 
New.
* testsuite/libgomp.c++/target-std__forward_list-concurrent.C: 
Adjust.
* testsuite/libgomp.c++/target-std__list-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__list-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__map-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__map-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__multimap-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__multiset-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__set-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__set-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__span-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__span-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__valarray-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__vector-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__vector-concurrent.C: Adjust.

Diff:
---
 libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C   | 5 +
 libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C   | 2 ++
 libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C  | 5 +
 libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent.C  | 2 ++
 libgomp/testsuite/libgomp.c++/target-std__deque-concurrent-usm.C   | 5 +
 libgomp/testsuite/libgomp.c++/target-std__deque-concurrent.C   | 2 ++
 .../libgomp.c++/target-std__forward_list-concurrent-usm.C  | 5 +
 .../testsuite/libgomp.c++/target-std__forward_list-concurrent.C| 2 ++
 libgomp/testsuite/libgomp.c++/target-std__list-concurrent-usm.C| 5 +
 libgomp/testsuite/libgomp.c++/target-std__list-concurrent.C| 2 ++
 libgomp/testsuite/libgomp.c++/target-std__map-concurrent-usm.C | 5 +
 libgomp/testsuite/libgomp.c++/target-std__map-concurrent.C | 4 
 .../testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C| 5 +
 libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent.C| 4 
 .../testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C| 5 +
 libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent.C| 2 ++
 libgomp/testsuite/libgomp.c++/target-std__set-concurrent-usm.C | 5 +
 libgomp/testsuite/libgomp.c++/target-std__set-concurrent.C | 2 ++
 libgomp/testsuite/libgomp.c++/target-std__span-concurrent-usm.C| 7 +++
 libgomp/testsuite/libgomp.c++/target-std__span-concurrent.C| 4 
 .../testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C| 5 +
 libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent.C| 2 ++
 libgomp/testsuite/libgomp.c++/target-std__vector-concurrent-usm.C  | 5 +
 libgomp/testsuite/libgomp.c++/target-std__vector-concurrent.C  | 2 ++
 24 files changed, 92 insertions(+)

diff --git a/libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C 
b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C
new file mode 100644
index ..9923783bcb12
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C
@@ -0,0 +1,5 @@
+#pragma omp requires unified_shared_memory self_maps
+
+#define MEM_SHARED
+
+#include "target-std__array-concurrent.C"
diff --git a/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C
index e97bfe60a615..c42105a65ed6 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C
@@ -33,7 +33,9 @@ int main (void)
   srand (time (NULL));
   init (data);
 
+#ifndef MEM_SHARED
   #pragma omp target data map (to: data[:N]) map (alloc: arr)
+#endif
 {
  

[gcc/devel/omp/gcc-15] Add 'libgomp.c++/target-flex-[...].C' test cases

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:38bfd2bc4e34b4447975826dba67fa31bc6b01f4

commit 38bfd2bc4e34b4447975826dba67fa31bc6b01f4
Author: Waffl3x 
Date:   Mon May 26 02:38:27 2025 -0600

Add 'libgomp.c++/target-flex-[...].C' test cases

libgomp/ChangeLog:

* testsuite/libgomp.c++/target-flex-10.C: New test.
* testsuite/libgomp.c++/target-flex-100.C: New test.
* testsuite/libgomp.c++/target-flex-101.C: New test.
* testsuite/libgomp.c++/target-flex-11.C: New test.
* testsuite/libgomp.c++/target-flex-12.C: New test.
* testsuite/libgomp.c++/target-flex-2000.C: New test.
* testsuite/libgomp.c++/target-flex-2001.C: New test.
* testsuite/libgomp.c++/target-flex-2002.C: New test.
* testsuite/libgomp.c++/target-flex-2003.C: New test.
* testsuite/libgomp.c++/target-flex-30.C: New test.
* testsuite/libgomp.c++/target-flex-300.C: New test.
* testsuite/libgomp.c++/target-flex-31.C: New test.
* testsuite/libgomp.c++/target-flex-32.C: New test.
* testsuite/libgomp.c++/target-flex-33.C: New test.
* testsuite/libgomp.c++/target-flex-41.C: New test.
* testsuite/libgomp.c++/target-flex-60.C: New test.
* testsuite/libgomp.c++/target-flex-61.C: New test.
* testsuite/libgomp.c++/target-flex-62.C: New test.
* testsuite/libgomp.c++/target-flex-70.C: New test.
* testsuite/libgomp.c++/target-flex-80.C: New test.
* testsuite/libgomp.c++/target-flex-81.C: New test.
* testsuite/libgomp.c++/target-flex-90.C: New test.
* testsuite/libgomp.c++/target-flex-common.h: New test.

Co-authored-by: Thomas Schwinge 
(cherry picked from commit 28a5bc2d4f7ae345234a15e22fd65cfad851cf04)

Diff:
---
 libgomp/testsuite/libgomp.c++/target-flex-10.C | 215 ++
 libgomp/testsuite/libgomp.c++/target-flex-100.C| 210 ++
 libgomp/testsuite/libgomp.c++/target-flex-101.C| 136 
 libgomp/testsuite/libgomp.c++/target-flex-11.C | 444 +
 libgomp/testsuite/libgomp.c++/target-flex-12.C | 736 +
 libgomp/testsuite/libgomp.c++/target-flex-2000.C   |  32 +
 libgomp/testsuite/libgomp.c++/target-flex-2001.C   |  61 ++
 libgomp/testsuite/libgomp.c++/target-flex-2002.C   |  97 +++
 libgomp/testsuite/libgomp.c++/target-flex-2003.C   | 176 +
 libgomp/testsuite/libgomp.c++/target-flex-30.C |  51 ++
 libgomp/testsuite/libgomp.c++/target-flex-300.C|  49 ++
 libgomp/testsuite/libgomp.c++/target-flex-31.C |  80 +++
 libgomp/testsuite/libgomp.c++/target-flex-32.C |  50 ++
 libgomp/testsuite/libgomp.c++/target-flex-33.C |  52 ++
 libgomp/testsuite/libgomp.c++/target-flex-41.C |  94 +++
 libgomp/testsuite/libgomp.c++/target-flex-60.C |  46 ++
 libgomp/testsuite/libgomp.c++/target-flex-61.C |  54 ++
 libgomp/testsuite/libgomp.c++/target-flex-62.C |  50 ++
 libgomp/testsuite/libgomp.c++/target-flex-70.C |  26 +
 libgomp/testsuite/libgomp.c++/target-flex-80.C |  49 ++
 libgomp/testsuite/libgomp.c++/target-flex-81.C |  75 +++
 libgomp/testsuite/libgomp.c++/target-flex-90.C | 107 +++
 libgomp/testsuite/libgomp.c++/target-flex-common.h |  40 ++
 23 files changed, 2930 insertions(+)

diff --git a/libgomp/testsuite/libgomp.c++/target-flex-10.C 
b/libgomp/testsuite/libgomp.c++/target-flex-10.C
new file mode 100644
index ..8fa9af7e4140
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-flex-10.C
@@ -0,0 +1,215 @@
+/* Basic container usage.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#if __cplusplus >= 201103L
+#include 
+#include 
+#include 
+#include 
+#endif
+
+bool vector_test()
+{
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::vector vector;
+  ok = vector.empty();
+}
+  return ok;
+}
+
+bool deque_test()
+{
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::deque deque;
+  ok = deque.empty();
+}
+  return ok;
+}
+
+bool list_test()
+{
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::list list;
+  ok = list.empty();
+}
+  return ok;
+}
+
+bool map_test()
+{
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::map map;
+  ok = map.empty();
+}
+  return ok;
+}
+
+bool set_test()
+{
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::set set;
+  ok = set.empty();
+}
+  return ok;
+}
+
+bool multimap_test()
+{
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::multimap multimap;
+  ok = multimap.empty();
+}
+  return ok;
+}
+
+bool multiset_test()
+{
+  bool ok;
+  #pragma omp target map(from: ok)
+{
+  std::multiset multiset;
+  ok = multiset.empty();
+}
+  return ok;
+}
+
+#if __cplusplus >= 201103L
+
+bool array_test()
+{
+  static constexpr std::size_t array_size = 42;
+  bool ok;
+  #pragma omp tar

[gcc/devel/omp/gcc-15] libgomp: Add testcases for the standard C++ math library on offload targets

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:a04de7264a6dd23377121e140e7f67de3b347b88

commit a04de7264a6dd23377121e140e7f67de3b347b88
Author: Kwok Cheung Yeung 
Date:   Wed May 21 12:59:58 2025 +0100

libgomp: Add testcases for the standard C++ math library on offload targets

libgomp/

* testsuite/libgomp.c++/target-std__cmath.C: New.
* testsuite/libgomp.c++/target-std__complex.C: Likewise.
* testsuite/libgomp.c++/target-std__numbers.C: Likewise.

(cherry picked from commit fbcd0ad41f7cc801664da1e583f6bcad1eb02a08)

Diff:
---
 libgomp/testsuite/libgomp.c++/target-std__cmath.C  | 340 +
 .../testsuite/libgomp.c++/target-std__complex.C| 175 +++
 .../testsuite/libgomp.c++/target-std__numbers.C|  93 ++
 3 files changed, 608 insertions(+)

diff --git a/libgomp/testsuite/libgomp.c++/target-std__cmath.C 
b/libgomp/testsuite/libgomp.c++/target-std__cmath.C
new file mode 100644
index ..aaf715237a40
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-std__cmath.C
@@ -0,0 +1,340 @@
+// { dg-do run }
+// { dg-additional-options "-std=c++20" }
+
+#include 
+#include 
+
+#define FP_EQUAL(x,y) (std::abs ((x) - (y)) < 1E-6)
+
+#pragma omp declare target
+template bool test_basic ()
+{
+  T x = -3.456789;
+  T y = 1.234567;
+  T z = 5.678901;
+
+  if (std::abs (x) != -x)
+return false;
+  if (!FP_EQUAL (std::trunc (x / y) * y + std::fmod (x, y), x))
+return false;
+  if (!FP_EQUAL (x - std::round (x / y) * y, std::remainder (x, y)))
+return false;
+  if (!FP_EQUAL (std::fma (x, y, z), x * y + z))
+return false;
+  if (std::fmax (x, y) != (x > y ? x : y))
+return false;
+  if (std::fmin (x, y) != (x < y ? x : y))
+return false;
+  if (std::fdim (x, y) != std::max(x - y, (T) 0.0))
+return false;
+  if (std::fdim (y, x) != std::max(y - x, (T) 0.0))
+return false;
+  return true;
+}
+
+template bool test_exp ()
+{
+  T x = -4.567890;
+  T y = 2.345678;
+
+  if (!FP_EQUAL (std::exp (x), std::pow (std::numbers::e_v, x)))
+return false;
+  if (!FP_EQUAL (std::exp2 (y), std::pow ((T) 2.0, y)))
+return false;
+  if (!FP_EQUAL (std::expm1 (y), std::exp (y) - (T) 1.0))
+return false;
+  if (!FP_EQUAL (std::log (std::exp (x)), x))
+return false;
+  if (!FP_EQUAL (std::log10 (std::pow ((T) 10.0, y)), y))
+return false;
+  if (!FP_EQUAL (std::log2 (std::exp2 (y)), y))
+return false;
+  if (!FP_EQUAL (std::log1p (std::expm1 (y)), y))
+return false;
+  return true;
+}
+
+template bool test_power ()
+{
+  T x = 7.234251;
+  T y = 0.340128;
+
+  if (!FP_EQUAL (std::log (std::pow (x, y)) / std::log (x), y))
+return false;
+  if (!FP_EQUAL (std::sqrt (x) * std::sqrt (x), x))
+return false;
+  if (!FP_EQUAL (std::cbrt (x) * std::cbrt (x) * std::cbrt (x), x))
+return false;
+  if (!FP_EQUAL (std::hypot (x, y), std::sqrt (x * x + y * y)))
+return false;
+  return true;
+}
+
+template bool test_trig ()
+{
+  T theta = std::numbers::pi / 4;
+  T phi = std::numbers::pi / 6;
+
+  if (!FP_EQUAL (std::sin (theta), std::sqrt ((T) 2) / 2))
+return false;
+  if (!FP_EQUAL (std::sin (phi), 0.5))
+return false;
+  if (!FP_EQUAL (std::cos (theta), std::sqrt ((T) 2) / 2))
+return false;
+  if (!FP_EQUAL (std::cos (phi), std::sqrt ((T) 3) / 2))
+return false;
+  if (!FP_EQUAL (std::tan (theta), 1.0))
+return false;
+  if (!FP_EQUAL (std::tan (phi), std::sqrt ((T) 3) / 3))
+return false;
+
+  T x = 0.33245623;
+
+  if (!FP_EQUAL (std::asin (std::sin (x)), x))
+return false;
+  if (!FP_EQUAL (std::acos (std::cos (x)), x))
+return false;
+  if (!FP_EQUAL (std::atan (std::tan (x)), x))
+return false;
+  if (!FP_EQUAL (std::atan2 (std::sin (x), std::cos (x)), x))
+return false;
+  return true;
+}
+
+template bool test_hyperbolic ()
+{
+  T x = 0.7423532;
+
+  if (!FP_EQUAL (std::sinh (x), (std::exp (x) - std::exp (-x)) / (T) 2.0))
+return false;
+  if (!FP_EQUAL (std::cosh (x), (std::exp (x) + std::exp (-x)) / (T) 2.0))
+return false;
+  if (!FP_EQUAL (std::tanh (x), std::sinh (x) / std::cosh (x)))
+return false;
+  if (!FP_EQUAL (std::asinh (std::sinh (x)), x))
+return false;
+  if (!FP_EQUAL (std::acosh (std::cosh (x)), x))
+return false;
+  if (!FP_EQUAL (std::atanh (std::tanh (x)), x))
+return false;
+  return true;
+}
+
+template bool test_erf ()
+{
+  if (!FP_EQUAL (std::erf ((T) 0), 0))
+return false;
+  if (!FP_EQUAL (std::erf ((T) INFINITY), 1))
+return false;
+  if (!FP_EQUAL (std::erf ((T) -INFINITY), -1))
+return false;
+
+  if (!FP_EQUAL (std::erfc (0), 1))
+return false;
+  if (!FP_EQUAL (std::erfc ((T) INFINITY), 0))
+return false;
+  if (!FP_EQUAL (std::erfc ((T) -INFINITY), 2))
+return false;
+
+  return true;
+}
+
+template bool test_gamma ()
+{
+  if (!FP_EQUAL (std::tgamma ((T) 5), 4*3*2*1))
+return false;
+  if (!FP_EQUAL (std::tgamma ((T) 0.5), std::sqrt (std::numbers::pi_v)))
+re

[gcc/devel/omp/gcc-15] libgomp: Add testcases for concurrent access to standard C++ containers on offload targets

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:9aa037ff9910605a1b8718b70f7c5fad0e2106d8

commit 9aa037ff9910605a1b8718b70f7c5fad0e2106d8
Author: Kwok Cheung Yeung 
Date:   Thu May 8 20:41:16 2025 +0100

libgomp: Add testcases for concurrent access to standard C++ containers on 
offload targets

libgomp/

* testsuite/libgomp.c++/target-std__array-concurrent.C: New.
* testsuite/libgomp.c++/target-std__bitset-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__deque-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__flat_map-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__flat_multimap-concurrent.C: 
Likewise.
* testsuite/libgomp.c++/target-std__flat_multiset-concurrent.C: 
Likewise.
* testsuite/libgomp.c++/target-std__flat_set-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__forward_list-concurrent.C: 
Likewise.
* testsuite/libgomp.c++/target-std__list-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__map-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__multimap-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__multiset-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__set-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__span-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__unordered_map-concurrent.C: 
Likewise.
* 
testsuite/libgomp.c++/target-std__unordered_multimap-concurrent.C: Likewise.
* 
testsuite/libgomp.c++/target-std__unordered_multiset-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__unordered_set-concurrent.C: 
Likewise.
* testsuite/libgomp.c++/target-std__valarray-concurrent.C: Likewise.
* testsuite/libgomp.c++/target-std__vector-concurrent.C: Likewise.

Co-authored-by: Thomas Schwinge 
(cherry picked from commit a811d1d72261da58196ccec253fd2bdb10e999db)

Diff:
---
 .../libgomp.c++/target-std__array-concurrent.C | 60 
 .../libgomp.c++/target-std__bitset-concurrent.C| 67 ++
 .../libgomp.c++/target-std__deque-concurrent.C | 62 +
 .../libgomp.c++/target-std__flat_map-concurrent.C  | 71 +++
 .../target-std__flat_multimap-concurrent.C | 70 +++
 .../target-std__flat_multiset-concurrent.C | 60 
 .../libgomp.c++/target-std__flat_set-concurrent.C  | 67 ++
 .../target-std__forward_list-concurrent.C  | 81 ++
 .../libgomp.c++/target-std__list-concurrent.C  | 81 ++
 .../libgomp.c++/target-std__map-concurrent.C   | 66 ++
 .../libgomp.c++/target-std__multimap-concurrent.C  | 64 +
 .../libgomp.c++/target-std__multiset-concurrent.C  | 60 
 .../libgomp.c++/target-std__set-concurrent.C   | 66 ++
 .../libgomp.c++/target-std__span-concurrent.C  | 62 +
 .../target-std__unordered_map-concurrent.C | 66 ++
 .../target-std__unordered_multimap-concurrent.C| 65 +
 .../target-std__unordered_multiset-concurrent.C| 59 
 .../target-std__unordered_set-concurrent.C | 66 ++
 .../libgomp.c++/target-std__valarray-concurrent.C  | 64 +
 .../libgomp.c++/target-std__vector-concurrent.C| 61 
 20 files changed, 1318 insertions(+)

diff --git a/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C
new file mode 100644
index ..e97bfe60a615
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C
@@ -0,0 +1,60 @@
+// { dg-do run }
+// { dg-additional-options -DMEM_SHARED { target offload_device_shared_as } }
+
+#include 
+#include 
+#include 
+#include 
+
+#define N 5
+
+void init (int data[])
+{
+  for (int i = 0; i < N; ++i)
+data[i] = rand ();
+}
+
+#pragma omp declare target
+bool validate (const std::array &arr, int data[])
+{
+  for (int i = 0; i < N; ++i)
+if (arr[i] != data[i] * data[i])
+  return false;
+  return true;
+}
+#pragma omp end declare target
+
+int main (void)
+{
+  int data[N];
+  bool ok;
+  std::array arr;
+
+  srand (time (NULL));
+  init (data);
+
+  #pragma omp target data map (to: data[:N]) map (alloc: arr)
+{
+  #pragma omp target
+   {
+#ifndef MEM_SHARED
+ new (&arr) std::array ();
+#endif
+ std::copy (data, data + N, arr.begin ());
+   }
+
+  #pragma omp target teams distribute parallel for
+   for (int i = 0; i < N; ++i)
+ arr[i] *= arr[i];
+
+  #pragma omp target map (from: ok)
+   {
+ ok = validate (arr, data);
+#ifndef MEM_SHARED
+ arr.~array ();
+#endif
+   }

[gcc/devel/omp/gcc-15] Defuse 'RESULT_DECL' check in 'pass_nrv' (for offloading compilation) [PR119835]

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:ad212f7025627e49330094a408845bf09fc367a5

commit ad212f7025627e49330094a408845bf09fc367a5
Author: Thomas Schwinge 
Date:   Wed May 28 18:40:31 2025 +0200

Defuse 'RESULT_DECL' check in 'pass_nrv' (for offloading compilation) 
[PR119835]

... to avoid running into ICEs per PR119835, until that's resolved properly.

PR middle-end/119835
gcc/
* tree-nrv.cc (pass_nrv::execute): Defuse 'RESULT_DECL' check.
libgomp/
* testsuite/libgomp.oacc-c-c++-common/abi-struct-1.c:
'#pragma GCC optimize "-fno-inline"'.
* testsuite/libgomp.c-c++-common/target-abi-struct-1.c: New.
* testsuite/libgomp.c-c++-common/target-abi-struct-1-O0.c: Adjust.

Co-authored-by: Richard Biener 
(cherry picked from commit 543f7e1d59f0b6628e0de6610ad5e1cf7150090b)

Diff:
---
 gcc/tree-nrv.cc   | 19 ---
 .../libgomp.c-c++-common/target-abi-struct-1-O0.c |  2 +-
 .../libgomp.c-c++-common/target-abi-struct-1.c|  1 +
 .../libgomp.oacc-c-c++-common/abi-struct-1.c  |  6 +-
 4 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/gcc/tree-nrv.cc b/gcc/tree-nrv.cc
index 180ce39de4c5..3be97afb319e 100644
--- a/gcc/tree-nrv.cc
+++ b/gcc/tree-nrv.cc
@@ -167,16 +167,21 @@ pass_nrv::execute (function *fun)
   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
  gimple *stmt = gsi_stmt (gsi);
- tree ret_val;
 
  if (greturn *return_stmt = dyn_cast  (stmt))
{
- /* In a function with an aggregate return value, the
-gimplifier has changed all non-empty RETURN_EXPRs to
-return the RESULT_DECL.  */
- ret_val = gimple_return_retval (return_stmt);
- if (ret_val)
-   gcc_assert (ret_val == result);
+ /* We cannot perform NRV optimizations in a function with an
+aggregate return value if there is a return that does not
+return RESULT_DECL.  We used to assert this scenario doesn't
+happen: the gimplifier has changed all non-empty RETURN_EXPRs
+to return the RESULT_DECL.  However, per PR119835 we may run
+into this scenario for offloading compilation, and therefore
+gracefully bail out.  */
+ if (tree ret_val = gimple_return_retval (return_stmt))
+   {
+ if (ret_val != result)
+   return 0;
+   }
}
  else if (gimple_has_lhs (stmt)
   && gimple_get_lhs (stmt) == result)
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-abi-struct-1-O0.c 
b/libgomp/testsuite/libgomp.c-c++-common/target-abi-struct-1-O0.c
index 35ec75d648d3..9bf949a1f066 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/target-abi-struct-1-O0.c
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-abi-struct-1-O0.c
@@ -1,3 +1,3 @@
 /* { dg-additional-options -O0 } */
 
-#include "../libgomp.oacc-c-c++-common/abi-struct-1.c"
+#include "target-abi-struct-1.c"
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-abi-struct-1.c 
b/libgomp/testsuite/libgomp.c-c++-common/target-abi-struct-1.c
new file mode 100644
index ..d9268af55cfe
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-abi-struct-1.c
@@ -0,0 +1 @@
+#include "../libgomp.oacc-c-c++-common/abi-struct-1.c"
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/abi-struct-1.c 
b/libgomp/testsuite/libgomp.oacc-c-c++-common/abi-struct-1.c
index 80786555fe21..4b541711f363 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/abi-struct-1.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/abi-struct-1.c
@@ -1,6 +1,10 @@
 /* Inspired by 'gcc.target/nvptx/abi-struct-arg.c', 
'gcc.target/nvptx/abi-struct-ret.c'.  */
 
-/* See also '../libgomp.c-c++-common/target-abi-struct-1-O0.c'.  */
+/* See also '../libgomp.c-c++-common/target-abi-struct-1.c'.  */
+
+/* To exercise PR119835 (if optimizations enabled): disable inlining, so that
+   GIMPLE passes still see the functions that return aggregate types.  */
+#pragma GCC optimize "-fno-inline"
 
 typedef struct {} empty;  /* See 'gcc/doc/extend.texi', "Empty Structures".  */
 typedef struct {char a;} schar;


[gcc/devel/omp/gcc-15] XFAIL 'libgomp.c++/target-flex-{300, 60, 61, 62, 81}.C'

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:b11c10797108bf14570ca77cf2d68b185eb03f56

commit b11c10797108bf14570ca77cf2d68b185eb03f56
Author: Thomas Schwinge 
Date:   Fri May 30 09:30:36 2025 +0200

XFAIL 'libgomp.c++/target-flex-{300,60,61,62,81}.C'

... which run into:

[...]/libgomp.c++/target-flex-300.C: In function 'bool 
test(std::size_t)':
[...]/libgomp.c++/target-flex-300.C:25:11: sorry, unimplemented: 
unsupported map expression 'test(std::size_t)::()'

... etc., due to other OG15 changes.

libgomp/
* testsuite/libgomp.c++/target-flex-300.C: XFAIL.
* testsuite/libgomp.c++/target-flex-60.C: Likewise.
* testsuite/libgomp.c++/target-flex-61.C: Likewise.
* testsuite/libgomp.c++/target-flex-62.C: Likewise.
* testsuite/libgomp.c++/target-flex-81.C: Likewise.

Diff:
---
 libgomp/testsuite/libgomp.c++/target-flex-300.C | 2 ++
 libgomp/testsuite/libgomp.c++/target-flex-60.C  | 2 ++
 libgomp/testsuite/libgomp.c++/target-flex-61.C  | 2 ++
 libgomp/testsuite/libgomp.c++/target-flex-62.C  | 2 ++
 libgomp/testsuite/libgomp.c++/target-flex-81.C  | 2 ++
 5 files changed, 10 insertions(+)

diff --git a/libgomp/testsuite/libgomp.c++/target-flex-300.C 
b/libgomp/testsuite/libgomp.c++/target-flex-300.C
index ef9e5a9b29bb..329a1897ddc7 100644
--- a/libgomp/testsuite/libgomp.c++/target-flex-300.C
+++ b/libgomp/testsuite/libgomp.c++/target-flex-300.C
@@ -23,6 +23,8 @@ bool test(std::size_t arg)
   int *data = vec.data();
   std::size_t size = vec.size();
   #pragma omp target defaultmap(none) map(from: ok, midpoint_out) map(tofrom: 
data[:size]) map(to: arg, size)
+  /* 
+ { dg-bogus {sorry, unimplemented: unsupported map expression '.*} TODO { xfail *-*-* } .-2 } */
 {
   std::span span = {data, size};
   bool inner_ok = true;
diff --git a/libgomp/testsuite/libgomp.c++/target-flex-60.C 
b/libgomp/testsuite/libgomp.c++/target-flex-60.C
index 014b9f5807a6..393bb3c3458c 100644
--- a/libgomp/testsuite/libgomp.c++/target-flex-60.C
+++ b/libgomp/testsuite/libgomp.c++/target-flex-60.C
@@ -13,6 +13,8 @@ bool test(const T (&arr)[Size])
   T out_shifted_arr[Size];
   #pragma omp target map(from: ok, out_2x_arr[:Size], out_shifted_arr[:Size]) \
 map(to: arr[:Size])
+  /* 
+ { dg-bogus {sorry, unimplemented: unsupported map expression '.*} TODO { xfail *-*-* } .-3 } */
 {
   std::vector vec(Size);
   std::vector mutated(Size);
diff --git a/libgomp/testsuite/libgomp.c++/target-flex-61.C 
b/libgomp/testsuite/libgomp.c++/target-flex-61.C
index 9070c2d34b83..e06133aa390c 100644
--- a/libgomp/testsuite/libgomp.c++/target-flex-61.C
+++ b/libgomp/testsuite/libgomp.c++/target-flex-61.C
@@ -22,6 +22,8 @@ bool test(const T (&arr)[Size])
   #pragma omp target defaultmap(none) \
 map(from: ok, out_2x_arr[:Size], out_shifted_arr[:Size]) \
 map(to: arr[:Size])
+  /* 
+ { dg-bogus {sorry, unimplemented: unsupported map expression '.*} TODO { xfail *-*-* } .-4 } */
 {
   std::vector vec(Size);
   std::vector mutated(Size);
diff --git a/libgomp/testsuite/libgomp.c++/target-flex-62.C 
b/libgomp/testsuite/libgomp.c++/target-flex-62.C
index ef6b942059c1..2e74b200a3b5 100644
--- a/libgomp/testsuite/libgomp.c++/target-flex-62.C
+++ b/libgomp/testsuite/libgomp.c++/target-flex-62.C
@@ -21,6 +21,8 @@ bool f()
 
   bool ok;
   #pragma omp target defaultmap(none) map(from: ok) map(to: arr_fwd[:8], 
arr_rev[:8])
+  /* 
+ { dg-bogus {sorry, unimplemented: unsupported map expression '.*} TODO { xfail *-*-* } .-2 } */
 {
   std::span fwd = {arr_fwd, 8};
   std::span rev = {arr_rev, 8};
diff --git a/libgomp/testsuite/libgomp.c++/target-flex-81.C 
b/libgomp/testsuite/libgomp.c++/target-flex-81.C
index a86fefb8d793..950c122c5f46 100644
--- a/libgomp/testsuite/libgomp.c++/target-flex-81.C
+++ b/libgomp/testsuite/libgomp.c++/target-flex-81.C
@@ -35,6 +35,8 @@ bool test(Rn&& range)
   std::size_t size = vec.size();
   bool ok;
   #pragma omp target map(from: ok) map(tofrom: data[:size]) map(to: size)
+  /* 
+ { dg-bogus {sorry, unimplemented: unsupported map expression '.*} TODO { xfail *-*-* } .-2 } */
 {
   std::vector orig = {data, data + size};
   std::span span = {data, size};


[gcc/devel/omp/gcc-15] Add 'libgomp.c++/target-valarray-1.C'

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:c5e30d27f47f8b93f1a292b0b87e021c7eceab5c

commit c5e30d27f47f8b93f1a292b0b87e021c7eceab5c
Author: Thomas Schwinge 
Date:   Wed Apr 30 11:29:08 2025 +0200

Add 'libgomp.c++/target-valarray-1.C'

libgomp/
* testsuite/libgomp.c++/target-std__valarray-1.C: New.
* testsuite/libgomp.c++/target-std__valarray-1.output: Likewise.

(cherry picked from commit 2ffada0296c95898a68bdb67ced738fe788df93a)

Diff:
---
 .../testsuite/libgomp.c++/target-std__valarray-1.C | 179 +
 .../libgomp.c++/target-std__valarray-1.output  |  22 +++
 2 files changed, 201 insertions(+)

diff --git a/libgomp/testsuite/libgomp.c++/target-std__valarray-1.C 
b/libgomp/testsuite/libgomp.c++/target-std__valarray-1.C
new file mode 100644
index ..865cde2e66b1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-std__valarray-1.C
@@ -0,0 +1,179 @@
+// { dg-additional-options -std=c++20 }
+// { dg-output-file target-std__valarray-1.output }
+
+#include 
+#include 
+#include 
+
+
+/*TODO Work around PR118484 "ICE during IPA pass: cp, segfault in 
determine_versionability ipa-cp.cc:467".
+
+We can't:
+
+#pragma omp declare target(std::basic_streambuf>::basic_streambuf)
+
+... because:
+
+error: overloaded function name ‘std::basic_streambuf::__ct ’ in 
clause ‘enter’
+
+Therefore, use dummy classes in '#pragma omp declare target':
+*/
+
+#pragma omp declare target
+
+// For 'std::basic_streambuf >::basic_streambuf':
+
+class dummy_basic_streambuf__char
+  : public std::basic_streambuf
+{
+public:
+  dummy_basic_streambuf__char() {}
+};
+
+// For 'std::basic_ios >::basic_ios()':
+
+class dummy_basic_ios__char
+  : public std::basic_ios
+{
+public:
+  dummy_basic_ios__char() {}
+};
+
+#pragma omp end declare target
+
+
+int main()
+{
+  // Due to PR120021 "Offloading vs. C++ 'std::initializer_list'", we can't 
construct these on the device.
+  std::initializer_list v1_i = {10, 20, 30, 40, 50};
+  const int *v1_i_data = std::data(v1_i);
+  size_t v1_i_size = v1_i.size();
+  std::initializer_list v2_i = {5, 4, 3, 2, 1};
+  const int *v2_i_data = std::data(v2_i);
+  size_t v2_i_size = v2_i.size();
+  std::initializer_list shiftData_i = {1, 2, 3, 4, 5};
+  const int *shiftData_i_data = std::data(shiftData_i);
+  size_t shiftData_i_size = shiftData_i.size();
+#pragma omp target \
+  defaultmap(none) \
+  map(to: v1_i_data[:v1_i_size], v1_i_size, \
+  v2_i_data[:v2_i_size], v2_i_size, \
+  shiftData_i_data[:shiftData_i_size], shiftData_i_size)
+  {
+/* Manually set up a buffer we can stream into, similar to 'cout << 
[...]', and print it at the end of region.  */
+std::stringbuf out_b;
+std::ostream out(&out_b);
+
+std::valarray v1(v1_i_data, v1_i_size);
+out << "\nv1:";
+for (auto val : v1)
+  out << " " << val;
+
+std::valarray v2(v2_i_data, v2_i_size);
+out << "\nv2:";
+for (auto val : v2)
+  out << " " << val;
+
+std::valarray sum = v1 + v2;
+out << "\nv1 + v2:";
+for (auto val : sum)
+  out << " " << val;
+
+std::valarray diff = v1 - v2;
+out << "\nv1 - v2:";
+for (auto val : diff)
+  out << " " << val;
+
+std::valarray product = v1 * v2;
+out << "\nv1 * v2:";
+for (auto val : product)
+  out << " " << val;
+
+std::valarray quotient = v1 / v2;
+out << "\nv1 / v2:";
+for (auto val : quotient)
+  out << " " << val;
+
+std::valarray squares = pow(v1, 2);
+out << "\npow(v1, 2):";
+for (auto val : squares)
+  out << " " << val;
+
+std::valarray sinhs = sinh(v2);
+out << "\nsinh(v2):";
+for (auto val : sinhs)
+  out << " " << val;
+
+std::valarray logs = log(v1 * v2);
+out << "\nlog(v1 * v2):";
+for (auto val : logs)
+  out << " " << val;
+
+std::valarray data(12);
+for (size_t i = 0; i < data.size(); ++i)
+  data[i] = i;
+out << "\nOriginal array:";
+for (auto val : data)
+  out << " " << val;
+
+std::slice slice1(2, 5, 1);
+std::valarray sliced1 = data[slice1];
+out << "\nSlice(2, 5, 1):";
+for (auto val : sliced1)
+  out << " " << val;
+
+std::slice slice2(1, 4, 3);
+std::valarray sliced2 = data[slice2];
+out << "\nSlice(1, 4, 3):";
+for (auto val : sliced2)
+  out << " " << val;
+
+data[slice1] = 99;
+out << "\nArray after slice modification:";
+for (auto val : data)
+  out << " " << val;
+
+std::valarray mask = (v1 > 20);
+out << "\nElements of v1 > 20:";
+for (size_t i = 0; i < v1.size(); ++i)
+  {
+   if (mask[i])
+ out << " " << v1[i];
+  }
+
+std::valarray masked = v1[mask];
+out << "\nMasked array:";
+for (auto val : masked)
+  out << " " << val;
+
+std::valarray shiftData(shiftData_i_data, shiftData_i_size);
+out << "\nOriginal shiftData:";
+for (auto val : shiftData)
+  out << " " << val;
+
+std::valarray shifted = 

[gcc/devel/omp/gcc-15] libgomp: Add testcases for concurrent access to standard C++ containers on offload targets, a number

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:94334a764b073fe5011db1a53bc5693b30b57fae

commit 94334a764b073fe5011db1a53bc5693b30b57fae
Author: Thomas Schwinge 
Date:   Fri May 30 11:37:46 2025 +0200

libgomp: Add testcases for concurrent access to standard C++ containers on 
offload targets, a number of USM variants

libgomp/
* testsuite/libgomp.c++/target-std__array-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__array-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__bitset-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__deque-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__deque-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C: 
New.
* testsuite/libgomp.c++/target-std__forward_list-concurrent.C: 
Adjust.
* testsuite/libgomp.c++/target-std__list-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__list-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__map-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__map-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__multimap-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__multiset-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__set-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__set-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__span-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__span-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__valarray-concurrent.C: Adjust.
* testsuite/libgomp.c++/target-std__vector-concurrent-usm.C: New.
* testsuite/libgomp.c++/target-std__vector-concurrent.C: Adjust.

(cherry picked from commit 83ca283853f195a08d2f758580a369bc6a076122)

Diff:
---
 libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C   | 5 +
 libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C   | 2 ++
 libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C  | 5 +
 libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent.C  | 2 ++
 libgomp/testsuite/libgomp.c++/target-std__deque-concurrent-usm.C   | 5 +
 libgomp/testsuite/libgomp.c++/target-std__deque-concurrent.C   | 2 ++
 .../libgomp.c++/target-std__forward_list-concurrent-usm.C  | 5 +
 .../testsuite/libgomp.c++/target-std__forward_list-concurrent.C| 2 ++
 libgomp/testsuite/libgomp.c++/target-std__list-concurrent-usm.C| 5 +
 libgomp/testsuite/libgomp.c++/target-std__list-concurrent.C| 2 ++
 libgomp/testsuite/libgomp.c++/target-std__map-concurrent-usm.C | 5 +
 libgomp/testsuite/libgomp.c++/target-std__map-concurrent.C | 4 
 .../testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C| 5 +
 libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent.C| 4 
 .../testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C| 5 +
 libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent.C| 2 ++
 libgomp/testsuite/libgomp.c++/target-std__set-concurrent-usm.C | 5 +
 libgomp/testsuite/libgomp.c++/target-std__set-concurrent.C | 2 ++
 libgomp/testsuite/libgomp.c++/target-std__span-concurrent-usm.C| 7 +++
 libgomp/testsuite/libgomp.c++/target-std__span-concurrent.C| 4 
 .../testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C| 5 +
 libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent.C| 2 ++
 libgomp/testsuite/libgomp.c++/target-std__vector-concurrent-usm.C  | 5 +
 libgomp/testsuite/libgomp.c++/target-std__vector-concurrent.C  | 2 ++
 24 files changed, 92 insertions(+)

diff --git a/libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C 
b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C
new file mode 100644
index ..9923783bcb12
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C
@@ -0,0 +1,5 @@
+#pragma omp requires unified_shared_memory self_maps
+
+#define MEM_SHARED
+
+#include "target-std__array-concurrent.C"
diff --git a/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C
index e97bfe60a615..c42105a65ed6 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C
@@ -33,7 +33,9 @@ int main (void)
   srand (time (NULL));
   init (data);
 
+#ifndef MEM_SHARED
   #pragma o

[gcc/devel/omp/gcc-15] Merge commit 'c153150b8a05878191de2ee16c0cce7d526f3c46' into HEAD

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:fbde111a3466f3870d00a574700fbb87c56d6c42

commit fbde111a3466f3870d00a574700fbb87c56d6c42
Merge: 1e21c26f2f53 c153150b8a05
Author: Thomas Schwinge 
Date:   Fri May 30 15:06:20 2025 +0200

Merge commit 'c153150b8a05878191de2ee16c0cce7d526f3c46' into HEAD

Diff:

 gcc/ChangeLog.omp  |   9 +
 gcc/tree-nrv.cc|  19 +-
 libgomp/ChangeLog.omp  | 126 +++-
 libgomp/testsuite/libgomp.c++/target-flex-10.C | 215 ++
 libgomp/testsuite/libgomp.c++/target-flex-100.C| 210 ++
 libgomp/testsuite/libgomp.c++/target-flex-101.C| 136 
 libgomp/testsuite/libgomp.c++/target-flex-11.C | 444 +
 libgomp/testsuite/libgomp.c++/target-flex-12.C | 736 +
 libgomp/testsuite/libgomp.c++/target-flex-2000.C   |  32 +
 libgomp/testsuite/libgomp.c++/target-flex-2001.C   |  61 ++
 libgomp/testsuite/libgomp.c++/target-flex-2002.C   |  97 +++
 libgomp/testsuite/libgomp.c++/target-flex-2003.C   | 176 +
 libgomp/testsuite/libgomp.c++/target-flex-30.C |  51 ++
 libgomp/testsuite/libgomp.c++/target-flex-300.C|  51 ++
 libgomp/testsuite/libgomp.c++/target-flex-31.C |  80 +++
 libgomp/testsuite/libgomp.c++/target-flex-32.C |  50 ++
 libgomp/testsuite/libgomp.c++/target-flex-33.C |  52 ++
 libgomp/testsuite/libgomp.c++/target-flex-41.C |  94 +++
 libgomp/testsuite/libgomp.c++/target-flex-60.C |  48 ++
 libgomp/testsuite/libgomp.c++/target-flex-61.C |  56 ++
 libgomp/testsuite/libgomp.c++/target-flex-62.C |  52 ++
 libgomp/testsuite/libgomp.c++/target-flex-70.C |  26 +
 libgomp/testsuite/libgomp.c++/target-flex-80.C |  49 ++
 libgomp/testsuite/libgomp.c++/target-flex-81.C |  77 +++
 libgomp/testsuite/libgomp.c++/target-flex-90.C | 107 +++
 libgomp/testsuite/libgomp.c++/target-flex-common.h |  40 ++
 .../libgomp.c++/target-std__array-concurrent-usm.C |   5 +
 .../libgomp.c++/target-std__array-concurrent.C |  62 ++
 .../target-std__bitset-concurrent-usm.C|   5 +
 .../libgomp.c++/target-std__bitset-concurrent.C|  69 ++
 libgomp/testsuite/libgomp.c++/target-std__cmath.C  | 340 ++
 .../testsuite/libgomp.c++/target-std__complex.C| 175 +
 .../libgomp.c++/target-std__deque-concurrent-usm.C |   5 +
 .../libgomp.c++/target-std__deque-concurrent.C |  64 ++
 .../libgomp.c++/target-std__flat_map-concurrent.C  |  71 ++
 .../target-std__flat_multimap-concurrent.C |  70 ++
 .../target-std__flat_multiset-concurrent.C |  60 ++
 .../libgomp.c++/target-std__flat_set-concurrent.C  |  67 ++
 .../target-std__forward_list-concurrent-usm.C  |   5 +
 .../target-std__forward_list-concurrent.C  |  83 +++
 .../libgomp.c++/target-std__list-concurrent-usm.C  |   5 +
 .../libgomp.c++/target-std__list-concurrent.C  |  83 +++
 .../libgomp.c++/target-std__map-concurrent-usm.C   |   5 +
 .../libgomp.c++/target-std__map-concurrent.C   |  70 ++
 .../target-std__multimap-concurrent-usm.C  |   5 +
 .../libgomp.c++/target-std__multimap-concurrent.C  |  68 ++
 .../target-std__multiset-concurrent-usm.C  |   5 +
 .../libgomp.c++/target-std__multiset-concurrent.C  |  62 ++
 .../testsuite/libgomp.c++/target-std__numbers.C|  93 +++
 .../libgomp.c++/target-std__set-concurrent-usm.C   |   5 +
 .../libgomp.c++/target-std__set-concurrent.C   |  68 ++
 .../libgomp.c++/target-std__span-concurrent-usm.C  |   7 +
 .../libgomp.c++/target-std__span-concurrent.C  |  66 ++
 .../target-std__unordered_map-concurrent.C |  66 ++
 .../target-std__unordered_multimap-concurrent.C|  65 ++
 .../target-std__unordered_multiset-concurrent.C|  59 ++
 .../target-std__unordered_set-concurrent.C |  66 ++
 .../testsuite/libgomp.c++/target-std__valarray-1.C | 179 +
 .../libgomp.c++/target-std__valarray-1.output  |  22 +
 .../target-std__valarray-concurrent-usm.C  |   5 +
 .../libgomp.c++/target-std__valarray-concurrent.C  |  66 ++
 .../target-std__vector-concurrent-usm.C|   5 +
 .../libgomp.c++/target-std__vector-concurrent.C|  63 ++
 .../libgomp.c-c++-common/target-abi-struct-1-O0.c  |   2 +-
 .../libgomp.c-c++-common/target-abi-struct-1.c |   1 +
 .../libgomp.oacc-c-c++-common/abi-struct-1.c   |   6 +-
 66 files changed, 5312 insertions(+), 10 deletions(-)

diff --cc libgomp/ChangeLog.omp
index 53d3bc165381,afc818454dea..5ecab6d05e98
--- a/libgomp/ChangeLog.omp
+++ b/libgomp/ChangeLog.omp
@@@ -1,39 -1,127 +1,163 @@@
+ 2025-05-30  Thomas Schwinge  
+ 
+   * testsuite/libgomp.c++/target-flex-300.C: XFAIL.
+   * testsuite/libgomp.c++/target-flex-60.C: Likewise.
+   * testsuite/libgomp.c++/target-flex-61.C: Likewise.
+   * testsuite/libgomp.c++/target-flex-62.C: Likewise.
+   * testsuite/libgomp.c++/target-flex-81.C: Likewise.
+ 
+ 2025-05-30  Thomas Schwinge  
+ 
+   Backported from master:
+   2025-0

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

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:1e21c26f2f53986ad3d5be033ca0098f459bb9e8

commit 1e21c26f2f53986ad3d5be033ca0098f459bb9e8
Author: Thomas Schwinge 
Date:   Fri May 30 15:04:37 2025 +0200

ChangeLog.omp bump

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

diff --git a/gcc/DATESTAMP.omp b/gcc/DATESTAMP.omp
index 7a7061068fcc..ac2743335765 100644
--- a/gcc/DATESTAMP.omp
+++ b/gcc/DATESTAMP.omp
@@ -1 +1 @@
-20250522
+20250530
diff --git a/libgomp/ChangeLog.omp b/libgomp/ChangeLog.omp
index 8ee1287d2be6..53d3bc165381 100644
--- a/libgomp/ChangeLog.omp
+++ b/libgomp/ChangeLog.omp
@@ -1,3 +1,39 @@
+2025-05-30  Tobias Burnus  
+
+   Backported from master:
+   2025-05-29  Tobias Burnus  
+
+   PR libgomp/93226
+   * libgomp-plugin.h (GOMP_OFFLOAD_openacc_async_dev2dev): New
+   prototype.
+   * libgomp.h (struct acc_dispatch_t): Add dev2dev_func.
+   (gomp_copy_dev2dev): New prototype.
+   * libgomp.map (OACC_2.6.1): New; add acc_memcpy_device{,_async}.
+   * libgomp.texi (acc_memcpy_device): New.
+   * oacc-mem.c (memcpy_tofrom_device): Change to take from/to
+   device boolean; use memcpy not memmove; add early return if
+   size == 0 or same device + same ptr.
+   (acc_memcpy_to_device, acc_memcpy_to_device_async,
+   acc_memcpy_from_device, acc_memcpy_from_device_async): Update.
+   (acc_memcpy_device, acc_memcpy_device_async): New.
+   * openacc.f90 (acc_memcpy_device, acc_memcpy_device_async):
+   Add interface.
+   * openacc_lib.h (acc_memcpy_device, acc_memcpy_device_async):
+   Likewise.
+   * openacc.h (acc_memcpy_device, acc_memcpy_device_async): Add
+   prototype.
+   * plugin/plugin-gcn.c (GOMP_OFFLOAD_openacc_async_host2dev):
+   Update comment.
+   (GOMP_OFFLOAD_openacc_async_dev2host): Update call.
+   (GOMP_OFFLOAD_openacc_async_dev2dev): New.
+   * plugin/plugin-nvptx.c (cuda_memcpy_dev_sanity_check): New.
+   (GOMP_OFFLOAD_dev2dev): Call it.
+   (GOMP_OFFLOAD_openacc_async_dev2dev): New.
+   * target.c (gomp_copy_dev2dev): New.
+   (gomp_load_plugin_for_device): Load dev2dev and async_dev2dev.
+   * testsuite/libgomp.oacc-c-c++-common/acc_memcpy_device-1.c: New test.
+   * testsuite/libgomp.oacc-fortran/acc_memcpy_device-1.f90: New test.
+
 2025-05-22  Thomas Schwinge  
 
Backported from master:


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

2025-05-30 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:c153150b8a05878191de2ee16c0cce7d526f3c46

commit c153150b8a05878191de2ee16c0cce7d526f3c46
Author: Thomas Schwinge 
Date:   Fri May 30 15:03:59 2025 +0200

ChangeLog.omp bump

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

diff --git a/gcc/ChangeLog.omp b/gcc/ChangeLog.omp
index eaeb97f7f2ee..b832b2a2d325 100644
--- a/gcc/ChangeLog.omp
+++ b/gcc/ChangeLog.omp
@@ -1,3 +1,12 @@
+2025-05-30  Thomas Schwinge  
+
+   Backported from master:
+   2025-05-30  Thomas Schwinge  
+   Richard Biener  
+
+   PR middle-end/119835
+   * tree-nrv.cc (pass_nrv::execute): Defuse 'RESULT_DECL' check.
+
 2025-05-22  Thomas Schwinge  
 
Backported from master:
diff --git a/gcc/DATESTAMP.omp b/gcc/DATESTAMP.omp
index 7a7061068fcc..ac2743335765 100644
--- a/gcc/DATESTAMP.omp
+++ b/gcc/DATESTAMP.omp
@@ -1 +1 @@
-20250522
+20250530
diff --git a/libgomp/ChangeLog.omp b/libgomp/ChangeLog.omp
index 8ee1287d2be6..afc818454dea 100644
--- a/libgomp/ChangeLog.omp
+++ b/libgomp/ChangeLog.omp
@@ -1,3 +1,127 @@
+2025-05-30  Thomas Schwinge  
+
+   * testsuite/libgomp.c++/target-flex-300.C: XFAIL.
+   * testsuite/libgomp.c++/target-flex-60.C: Likewise.
+   * testsuite/libgomp.c++/target-flex-61.C: Likewise.
+   * testsuite/libgomp.c++/target-flex-62.C: Likewise.
+   * testsuite/libgomp.c++/target-flex-81.C: Likewise.
+
+2025-05-30  Thomas Schwinge  
+
+   Backported from master:
+   2025-05-30  Thomas Schwinge  
+
+   * testsuite/libgomp.c++/target-std__valarray-1.C: New.
+   * testsuite/libgomp.c++/target-std__valarray-1.output: Likewise.
+
+2025-05-30  Thomas Schwinge  
+
+   Backported from master:
+   2025-05-30  Thomas Schwinge  
+
+   * testsuite/libgomp.c++/target-std__array-concurrent-usm.C: New.
+   * testsuite/libgomp.c++/target-std__array-concurrent.C: Adjust.
+   * testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C: New.
+   * testsuite/libgomp.c++/target-std__bitset-concurrent.C: Adjust.
+   * testsuite/libgomp.c++/target-std__deque-concurrent-usm.C: New.
+   * testsuite/libgomp.c++/target-std__deque-concurrent.C: Adjust.
+   * testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C: New.
+   * testsuite/libgomp.c++/target-std__forward_list-concurrent.C: Adjust.
+   * testsuite/libgomp.c++/target-std__list-concurrent-usm.C: New.
+   * testsuite/libgomp.c++/target-std__list-concurrent.C: Adjust.
+   * testsuite/libgomp.c++/target-std__map-concurrent-usm.C: New.
+   * testsuite/libgomp.c++/target-std__map-concurrent.C: Adjust.
+   * testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C: New.
+   * testsuite/libgomp.c++/target-std__multimap-concurrent.C: Adjust.
+   * testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C: New.
+   * testsuite/libgomp.c++/target-std__multiset-concurrent.C: Adjust.
+   * testsuite/libgomp.c++/target-std__set-concurrent-usm.C: New.
+   * testsuite/libgomp.c++/target-std__set-concurrent.C: Adjust.
+   * testsuite/libgomp.c++/target-std__span-concurrent-usm.C: New.
+   * testsuite/libgomp.c++/target-std__span-concurrent.C: Adjust.
+   * testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C: New.
+   * testsuite/libgomp.c++/target-std__valarray-concurrent.C: Adjust.
+   * testsuite/libgomp.c++/target-std__vector-concurrent-usm.C: New.
+   * testsuite/libgomp.c++/target-std__vector-concurrent.C: Adjust.
+
+2025-05-30  Kwok Cheung Yeung  
+
+   Backported from master:
+   2025-05-30  Kwok Cheung Yeung  
+   Thomas Schwinge  
+
+   * testsuite/libgomp.c++/target-std__array-concurrent.C: New.
+   * testsuite/libgomp.c++/target-std__bitset-concurrent.C: Likewise.
+   * testsuite/libgomp.c++/target-std__deque-concurrent.C: Likewise.
+   * testsuite/libgomp.c++/target-std__flat_map-concurrent.C: Likewise.
+   * testsuite/libgomp.c++/target-std__flat_multimap-concurrent.C: 
Likewise.
+   * testsuite/libgomp.c++/target-std__flat_multiset-concurrent.C: 
Likewise.
+   * testsuite/libgomp.c++/target-std__flat_set-concurrent.C: Likewise.
+   * testsuite/libgomp.c++/target-std__forward_list-concurrent.C: Likewise.
+   * testsuite/libgomp.c++/target-std__list-concurrent.C: Likewise.
+   * testsuite/libgomp.c++/target-std__map-concurrent.C: Likewise.
+   * testsuite/libgomp.c++/target-std__multimap-concurrent.C: Likewise.
+   * testsuite/libgomp.c++/target-std__multiset-concurrent.C: Likewise.
+   * testsuite/libgomp.c++/target-std__set-concurrent.C: Likewise.
+   * testsuite/libgomp.c++/target-std__span-concurrent.C: Likewise.
+   * testsuite/libgomp.c++/target-std__unordered_map-concurrent.C: 
Likewise.
+   * testsuite/libgomp.

[gcc r16-1015] RISC-V: Add test cases for avg_ceil vaadd implementation

2025-05-30 Thread Pan Li via Gcc-cvs
https://gcc.gnu.org/g:72972bc3a1b35bcfc83d801a9da45121210bc3c3

commit r16-1015-g72972bc3a1b35bcfc83d801a9da45121210bc3c3
Author: Pan Li 
Date:   Thu May 29 21:33:44 2025 +0800

RISC-V: Add test cases for avg_ceil vaadd implementation

Add asm and run testcase for avg_ceil vaadd implementation.

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

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/autovec/avg.h: Add test helper macros.
* gcc.target/riscv/rvv/autovec/avg_data.h: Add test data for
avg_ceil.
* gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i32.c: New test.
* gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i64.c: New test.
* gcc.target/riscv/rvv/autovec/avg_ceil-1-i32-from-i64.c: New test.
* gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i16.c: New test.
* gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i32.c: New test.
* gcc.target/riscv/rvv/autovec/avg_ceil-1-i8-from-i64.c: New test.
* gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i16-from-i32.c: New 
test.
* gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i16-from-i64.c: New 
test.
* gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i32-from-i64.c: New 
test.
* gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i16.c: New 
test.
* gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i32.c: New 
test.
* gcc.target/riscv/rvv/autovec/avg_ceil-run-1-i8-from-i64.c: New 
test.

Signed-off-by: Pan Li 

Diff:
---
 gcc/testsuite/gcc.target/riscv/rvv/autovec/avg.h   |  17 ++
 .../riscv/rvv/autovec/avg_ceil-1-i16-from-i32.c|  12 ++
 .../riscv/rvv/autovec/avg_ceil-1-i16-from-i64.c|  12 ++
 .../riscv/rvv/autovec/avg_ceil-1-i32-from-i64.c|  12 ++
 .../riscv/rvv/autovec/avg_ceil-1-i8-from-i16.c |  12 ++
 .../riscv/rvv/autovec/avg_ceil-1-i8-from-i32.c |  12 ++
 .../riscv/rvv/autovec/avg_ceil-1-i8-from-i64.c |  12 ++
 .../rvv/autovec/avg_ceil-run-1-i16-from-i32.c  |  16 ++
 .../rvv/autovec/avg_ceil-run-1-i16-from-i64.c  |  16 ++
 .../rvv/autovec/avg_ceil-run-1-i32-from-i64.c  |  16 ++
 .../riscv/rvv/autovec/avg_ceil-run-1-i8-from-i16.c |  16 ++
 .../riscv/rvv/autovec/avg_ceil-run-1-i8-from-i32.c |  16 ++
 .../riscv/rvv/autovec/avg_ceil-run-1-i8-from-i64.c |  16 ++
 .../gcc.target/riscv/rvv/autovec/avg_data.h| 176 +
 14 files changed, 361 insertions(+)

diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg.h 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg.h
index 746c635ae577..4aeb637bba7e 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg.h
@@ -20,4 +20,21 @@ test_##NAME##_##WT##_##NT##_0(NT * restrict a, NT * restrict 
b, \
 #define RUN_AVG_0_WRAP(NT, WT, NAME, a, b, out, n) \
   RUN_AVG_0(NT, WT, NAME, a, b, out, n)
 
+#define DEF_AVG_1(NT, WT, NAME) \
+__attribute__((noinline))   \
+void\
+test_##NAME##_##WT##_##NT##_1(NT * restrict a, NT * restrict b, \
+ NT * restrict out, int n) \
+{   \
+  for (int i = 0; i < n; i++) { \
+out[i] = (NT)(((WT)a[i] + (WT)b[i] + 1) >> 1);  \
+  } \
+}
+#define DEF_AVG_1_WRAP(NT, WT, NAME) DEF_AVG_1(NT, WT, NAME)
+
+#define RUN_AVG_1(NT, WT, NAME, a, b, out, n) \
+  test_##NAME##_##WT##_##NT##_1(a, b, out, n)
+#define RUN_AVG_1_WRAP(NT, WT, NAME, a, b, out, n) \
+  RUN_AVG_1(NT, WT, NAME, a, b, out, n)
+
 #endif
diff --git 
a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i32.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i32.c
new file mode 100644
index ..138124c8c4a0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i32.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d" } */
+
+#include "avg.h"
+
+#define NT int16_t
+#define WT int32_t
+
+DEF_AVG_1(NT, WT, avg_ceil)
+
+/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 1 } } */
+/* { dg-final { scan-assembler-times {vaadd.vv} 1 } } */
diff --git 
a/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i64.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i64.c
new file mode 100644
index ..30438c90abea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/avg_ceil-1-i16-from-i64.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d" } */
+
+#include "avg.h"
+
+#define NT int16_t
+#define WT int64_t
+
+DEF_AVG_1(NT, WT, avg_ceil)
+
+/* { dg-final { scan-ass

[gcc r16-1013] RISC-V: Leverage vaadd.vv for signed standard name avg_ceil

2025-05-30 Thread Pan Li via Gcc-cvs
https://gcc.gnu.org/g:6bcd522438250d014d0fa1e4bcf2aa049934c887

commit r16-1013-g6bcd522438250d014d0fa1e4bcf2aa049934c887
Author: Pan Li 
Date:   Thu May 29 21:19:36 2025 +0800

RISC-V: Leverage vaadd.vv for signed standard name avg_ceil

The avg_ceil has the rounding mode towards +inf, while the
vaadd.vv has the rnu which totally match the sematics.  From
RVV spec, the fixed vaadd.vv with rnu,

roundoff_signed(v, d) = (signed(v) >> d) + r
r = v[d - 1]

For vaadd, d = 1, then we have

roundoff_signed(v, 1) = (signed(v) >> 1) + v[0]

If v[0] is bit 0, nothing need to do as there is no rounding.
If v[0] is bit 1, there will be rounding with 2 cases.

Case 1: v is positive.
  roundoff_signed(v, 1) = (signed(v) >> 1) + 1, aka round towards +inf
  roundoff_signed(2 + 3, 1) = (5 >> 1) + 1 = 3

Case 2: v is negative.
  roundoff_signed(v, 1) = (signed(v) >> 1) + 1, aka round towards +inf
  roundoff_signed(-9 + 2, 1) = (-7 >> 1) + 1 = -4 + 1 = -3

Thus, we can leverage the vaadd with rnu directly for avg_ceil.

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

gcc/ChangeLog:

* config/riscv/autovec.md (avg3_ceil): Add insn
expand to leverage vaadd with rnu directly.

Signed-off-by: Pan Li 

Diff:
---
 gcc/config/riscv/autovec.md | 26 +++---
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index a54f552a80ce..60c881b1d746 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -2510,25 +2510,13 @@
(match_operand: 2 "register_operand")))
   (const_int 1)]
   "TARGET_VECTOR"
-{
-  /* First emit a widening addition.  */
-  rtx tmp1 = gen_reg_rtx (mode);
-  rtx ops1[] = {tmp1, operands[1], operands[2]};
-  insn_code icode = code_for_pred_dual_widen (PLUS, SIGN_EXTEND, mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops1);
-
-  /* Then add 1.  */
-  rtx tmp2 = gen_reg_rtx (mode);
-  rtx ops2[] = {tmp2, tmp1, const1_rtx};
-  icode = code_for_pred_scalar (PLUS, mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops2);
-
-  /* Finally, a narrowing shift.  */
-  rtx ops3[] = {operands[0], tmp2, const1_rtx};
-  icode = code_for_pred_narrow_scalar (ASHIFTRT, mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops3);
-  DONE;
-})
+  {
+insn_code icode = code_for_pred (UNSPEC_VAADD, mode);
+riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RNU,
+  operands);
+DONE;
+  }
+)
 
 ;; csrwi vxrm, 2
 ;; vaaddu.vv vd, vs2, vs1


[gcc r16-1014] RISC-V: Reconcile the existing test for avg_ceil

2025-05-30 Thread Pan Li via Gcc-cvs
https://gcc.gnu.org/g:6d4c38b232e1d58c85de7959411cc1562a7a0bdc

commit r16-1014-g6d4c38b232e1d58c85de7959411cc1562a7a0bdc
Author: Pan Li 
Date:   Thu May 29 21:31:54 2025 +0800

RISC-V: Reconcile the existing test for avg_ceil

Some existing avg_floor test need updated due to change to
leverage vaadd.vv directly.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/autovec/vls/avg-4.c: Update asm check
to vaadd.
* gcc.target/riscv/rvv/autovec/vls/avg-5.c: Ditto.
* gcc.target/riscv/rvv/autovec/vls/avg-6.c: Ditto.
* gcc.target/riscv/rvv/autovec/widen/vec-avg-rv32gcv.c: Ditto.
* gcc.target/riscv/rvv/autovec/widen/vec-avg-rv64gcv.c: Ditto.

Signed-off-by: Pan Li 

Diff:
---
 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-4.c | 6 ++
 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-5.c | 6 ++
 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-6.c | 6 ++
 gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv32gcv.c | 2 +-
 gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv64gcv.c | 2 +-
 5 files changed, 8 insertions(+), 14 deletions(-)

diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-4.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-4.c
index 8d106aaeed09..986a0ff21cfd 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-4.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-4.c
@@ -25,11 +25,9 @@ DEF_AVG_CEIL (uint8_t, uint16_t, 512)
 DEF_AVG_CEIL (uint8_t, uint16_t, 1024)
 DEF_AVG_CEIL (uint8_t, uint16_t, 2048)
 
-/* { dg-final { scan-assembler-times {vwadd\.vv} 10 } } */
-/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 10 } } */
-/* { dg-final { scan-assembler-times {vnsra\.wi} 10 } } */
+/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 20 } } */
+/* { dg-final { scan-assembler-times {vaadd\.vv} 10 } } */
 /* { dg-final { scan-assembler-times {vaaddu\.vv} 10 } } */
-/* { dg-final { scan-assembler-times {vadd\.vi} 10 } } */
 /* { dg-final { scan-assembler-not {csrr} } } */
 /* { dg-final { scan-tree-dump-not "1,1" "optimized" } } */
 /* { dg-final { scan-tree-dump-not "2,2" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-5.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-5.c
index 981abd515888..c450f80291a0 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-5.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-5.c
@@ -23,11 +23,9 @@ DEF_AVG_CEIL (uint16_t, uint32_t, 256)
 DEF_AVG_CEIL (uint16_t, uint32_t, 512)
 DEF_AVG_CEIL (uint16_t, uint32_t, 1024)
 
-/* { dg-final { scan-assembler-times {vwadd\.vv} 9 } } */
-/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 9 } } */
-/* { dg-final { scan-assembler-times {vnsra\.wi} 9 } } */
+/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 18 } } */
 /* { dg-final { scan-assembler-times {vaaddu\.vv} 9 } } */
-/* { dg-final { scan-assembler-times {vadd\.vi} 9 } } */
+/* { dg-final { scan-assembler-times {vaadd\.vv} 9 } } */
 /* { dg-final { scan-assembler-not {csrr} } } */
 /* { dg-final { scan-tree-dump-not "1,1" "optimized" } } */
 /* { dg-final { scan-tree-dump-not "2,2" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-6.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-6.c
index bfe4ba3c4bda..3473e193a5cb 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-6.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/avg-6.c
@@ -21,11 +21,9 @@ DEF_AVG_CEIL (uint16_t, uint32_t, 128)
 DEF_AVG_CEIL (uint16_t, uint32_t, 256)
 DEF_AVG_CEIL (uint16_t, uint32_t, 512)
 
-/* { dg-final { scan-assembler-times {vwadd\.vv} 8 } } */
-/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 8 } } */
-/* { dg-final { scan-assembler-times {vnsra\.wi} 8 } } */
+/* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*0} 16 } } */
 /* { dg-final { scan-assembler-times {vaaddu\.vv} 8 } } */
-/* { dg-final { scan-assembler-times {vadd\.vi} 8 } } */
+/* { dg-final { scan-assembler-times {vaadd\.vv} 8 } } */
 /* { dg-final { scan-assembler-not {csrr} } } */
 /* { dg-final { scan-tree-dump-not "1,1" "optimized" } } */
 /* { dg-final { scan-tree-dump-not "2,2" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv32gcv.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv32gcv.c
index b7246a38dba7..a5224e78d94a 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv32gcv.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv32gcv.c
@@ -5,4 +5,4 @@
 
 /* { dg-final { scan-assembler-times {csrwi\s*vxrm,\s*2} 6 } } */
 /* { dg-final { scan-assembler-times {vaaddu\.vv} 6 } } */
-/* { dg-final { scan-assembler-times {vaadd\.vv} 3 } } */
+/* { dg-final { scan-assembler-times {vaadd\.vv} 6 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/widen/vec-avg-rv64gcv.c 

[gcc r15-9746] OpenMP: Fix ICE and other issues in C/C++ metadirective error recovery.

2025-05-30 Thread Sandra Loosemore via Gcc-cvs
https://gcc.gnu.org/g:d67a38ca08298fbe2e18e938165bab4adfda7293

commit r15-9746-gd67a38ca08298fbe2e18e938165bab4adfda7293
Author: Sandra Loosemore 
Date:   Mon May 26 19:21:48 2025 +

OpenMP: Fix ICE and other issues in C/C++ metadirective error recovery.

The new testcase included in this patch used to ICE in gcc after
diagnosing the first error, and in g++ it only diagnosed the error in
the first metadirective, ignoring the second one.  The solution is to
make error recovery in the C front end more like that in the C++ front
end, and remove the code in both front ends that previously tried to
skip all the way over the following statement (instead of just to the
end of the metadirective pragma) after an error.

gcc/c/ChangeLog
* c-parser.cc (c_parser_skip_to_closing_brace): New, copied from
the equivalent function in the C++ front end.
(c_parser_skip_to_end_of_block_or_statement): Pass false to
the error flag.
(c_parser_omp_context_selector): Immediately return error_mark_node
after giving an error that the integer trait property is invalid,
similarly to C++ front end.
(c_parser_omp_context_selector_specification): Likewise handle
error return from c_parser_omp_context_selector similarly to C++.
(c_parser_omp_metadirective): Do not call
c_parser_skip_to_end_of_block_or_statement after an error.

gcc/cp/ChangeLog
* parser.cc (cp_parser_omp_metadirective): Do not call
cp_parser_skip_to_end_of_block_or_statement after an error.

gcc/testsuite/ChangeLog
* c-c++-common/gomp/declare-variant-2.c: Adjust patterns now that
C and C++ now behave similarly.
* c-c++-common/gomp/metadirective-error-recovery.c: New.

(cherry picked from commit 33b65e4d1c83808b54cd6b3fc97ebacc522b125d)

Diff:
---
 gcc/c/c-parser.cc  | 82 --
 gcc/cp/parser.cc   |  9 +--
 .../c-c++-common/gomp/declare-variant-2.c  | 13 ++--
 .../gomp/metadirective-error-recovery.c| 20 ++
 4 files changed, 89 insertions(+), 35 deletions(-)

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index d825e059a94d..93cc7b043b21 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -1418,6 +1418,51 @@ c_parser_skip_to_end_of_parameter (c_parser *parser)
   parser->error = false;
 }
 
+/* Skip tokens until a non-nested closing curly brace is the next
+   token, or there are no more tokens. Return true in the first case,
+   false otherwise.  */
+
+static bool
+c_parser_skip_to_closing_brace (c_parser *parser)
+{
+  unsigned nesting_depth = 0;
+
+  while (true)
+{
+  c_token *token = c_parser_peek_token (parser);
+
+  switch (token->type)
+   {
+   case CPP_PRAGMA_EOL:
+ if (!parser->in_pragma)
+   break;
+ /* FALLTHRU */
+   case CPP_EOF:
+ /* If we've run out of tokens, stop.  */
+ return false;
+
+   case CPP_CLOSE_BRACE:
+ /* If the next token is a non-nested `}', then we have reached
+the end of the current block.  */
+ if (nesting_depth-- == 0)
+   return true;
+ break;
+
+   case CPP_OPEN_BRACE:
+ /* If it the next token is a `{', then we are entering a new
+block.  Consume the entire block.  */
+ ++nesting_depth;
+ break;
+
+   default:
+ break;
+   }
+
+  /* Consume the token.  */
+  c_parser_consume_token (parser);
+}
+}
+
 /* Expect to be at the end of the pragma directive and consume an
end of line marker.  */
 
@@ -1533,7 +1578,7 @@ c_parser_skip_to_end_of_block_or_statement (c_parser 
*parser,
 here for secondary error recovery, after parser->error has
 been cleared.  */
  c_parser_consume_pragma (parser);
- c_parser_skip_to_pragma_eol (parser);
+ c_parser_skip_to_pragma_eol (parser, false);
  parser->error = save_error;
  continue;
 
@@ -26772,19 +26817,17 @@ c_parser_omp_context_selector (c_parser *parser, enum 
omp_tss_code set,
case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
case OMP_TRAIT_PROPERTY_BOOL_EXPR:
  t = c_parser_expr_no_commas (parser, NULL).value;
- if (t != error_mark_node)
+ if (t == error_mark_node)
+   return error_mark_node;
+ mark_exp_read (t);
+ t = c_fully_fold (t, false, NULL);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
- mark_exp_read (t);
- t = c_fully_fold (t, false, NULL);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
-   error_at (token->location,
- "property must be integer expression");
- else
- 

[gcc r16-1022] Fix typo in comment in execute_all_ipa_transforms.

2025-05-30 Thread Andrew Pinski via Gcc-cvs
https://gcc.gnu.org/g:948bb7ee02ad6b9f9625e684d1505b57c2a11a6e

commit r16-1022-g948bb7ee02ad6b9f9625e684d1505b57c2a11a6e
Author: Andrew Pinski 
Date:   Fri May 30 00:00:31 2025 -0700

Fix typo in comment in execute_all_ipa_transforms.

small typo, missing n at the end of function.

Pushed as obvious after a bootstrap/test.

gcc/ChangeLog:

* passes.cc (execute_all_ipa_transforms): Fix typo in
commenet.

Signed-off-by: Andrew Pinski 

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

diff --git a/gcc/passes.cc b/gcc/passes.cc
index 0482de0b198d..e86aa1f2d1bd 100644
--- a/gcc/passes.cc
+++ b/gcc/passes.cc
@@ -2391,7 +2391,7 @@ execute_all_ipa_transforms (bool do_not_collect)
 
   for (auto p : node->ipa_transforms_to_apply)
 {
-  /* To get consistent statistics, we need to account each functio
+  /* To get consistent statistics, we need to account each function
 to each IPA pass.  */
   if (report)
{


[gcc r15-9745] OpenMP: Fix ICE in metadirective recovery after error [PR120180]

2025-05-30 Thread Sandra Loosemore via Gcc-cvs
https://gcc.gnu.org/g:b368dd5de53fc981b5b20e2fd6d7de9116e82331

commit r15-9745-gb368dd5de53fc981b5b20e2fd6d7de9116e82331
Author: Sandra Loosemore 
Date:   Sat May 24 03:21:18 2025 +

OpenMP: Fix ICE in metadirective recovery after error [PR120180]

It's not clear whether a metadirective in a loop nest is supposed to
be valid, but GCC certainly shouldn't be ICE'ing after diagnosing it
as an error.

gcc/c/ChangeLog
PR c/120180
* c-parser.cc (c_parser_omp_metadirective): Only consume the
token if it is the expected close paren.

gcc/cp/ChangeLog
PR c/120180
* parser.cc (cp_parser_omp_metadirective): Only consume the
token if it is the expected close paren.

gcc/testsuite/ChangeLog
PR c/120180
* c-c++-common/gomp/pr120180.c: New.

(cherry picked from commit 65e0ed2310a1b0d1a3255583bbfb8a8d86c5aea5)

Diff:
---
 gcc/c/c-parser.cc  |  7 ---
 gcc/cp/parser.cc   |  7 ---
 gcc/testsuite/c-c++-common/gomp/pr120180.c | 22 ++
 3 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 22ec0f849b74..d825e059a94d 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -29247,7 +29247,10 @@ c_parser_omp_metadirective (c_parser *parser, bool 
*if_p)
  goto add;
case CPP_CLOSE_PAREN:
  if (nesting_depth-- == 0)
-   break;
+   {
+ c_parser_consume_token (parser);
+ break;
+   }
  goto add;
default:
add:
@@ -29259,8 +29262,6 @@ c_parser_omp_metadirective (c_parser *parser, bool 
*if_p)
  break;
}
 
-  c_parser_consume_token (parser);
-
   if (!skip)
{
  c_token eol_token;
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 3628cfefa07c..93ec030d8566 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -51568,7 +51568,10 @@ cp_parser_omp_metadirective (cp_parser *parser, 
cp_token *pragma_tok,
  goto add;
case CPP_CLOSE_PAREN:
  if (nesting_depth-- == 0)
-   break;
+   {
+ cp_lexer_consume_token (parser->lexer);
+ break;
+   }
  goto add;
default:
add:
@@ -51580,8 +51583,6 @@ cp_parser_omp_metadirective (cp_parser *parser, 
cp_token *pragma_tok,
  break;
}
 
-  cp_lexer_consume_token (parser->lexer);
-
   if (!skip)
{
  cp_token eol_token = {};
diff --git a/gcc/testsuite/c-c++-common/gomp/pr120180.c 
b/gcc/testsuite/c-c++-common/gomp/pr120180.c
new file mode 100644
index ..cb5a0d5a8191
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr120180.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+
+/* This test used to ICE after erroring on the metadirective in the
+   loop nest.  */
+
+int main()
+{
+  int blksize = 15000;
+  double *qq;
+  int i, k, nq;
+
+  #pragma omp metadirective when(user={condition(0)}: target teams distribute 
parallel for collapse(2) map(qq[:0]) private(i)) \
+when(user={condition(0)}: target teams distribute 
parallel for map(qq[:0]) private(i)) \
+when(user={condition(1)}: target teams loop 
collapse(2) map(qq[:0]) private(i))
+  for(k=0; k

[gcc r16-1021] c: Update description of C library facilities provided by GCC for C23

2025-05-30 Thread Joseph Myers via Gcc-cvs
https://gcc.gnu.org/g:dd9b6035a317a70a33112b830ce96b381d323af4

commit r16-1021-gdd9b6035a317a70a33112b830ce96b381d323af4
Author: Joseph Myers 
Date:   Fri May 30 20:15:53 2025 +

c: Update description of C library facilities provided by GCC for C23

The documentation of which standard C library facilities (headers) are
provided by GCC, as being those required of freestanding
implementations, is reasonably accurate for C99 and before (if you
ignore the provision of  for non-GNU targets).  It's less
accurate for C11, since we provide  although that's not
required for freestanding implementations.  And it's very inaccurate
for C23, which specifies that freestanding implementations also
provide most of , memalignment from , and, when
supporting Annex F, also ,  and the strto*
floating-point numeric conversion functions from .

I don't think expanding the scope of the C library facilities GCC
provides to include all those extra facilities specified by C23 for
freestanding implementations is a good idea.  (Indeed, GCC once used
to install assert.h on some platforms, but stopped doing so a long
time ago.)  Rather, it seems better to document that in both the
freestanding and the hosted cases, GCC is intended to provide the
compiler part of a conforming implementation, to be combined with a
corresponding library implementation, rather than providing all the
required library facilities in either case.

The rule about which headers GCC provides is then described in terms
of headers not declaring functions with external linkage, which is
much closer to existing practice, although still not perfect in all
cases (, although mainly providing type-generic
operations, does declare a few non-type-generic functions that we
provide in libatomic).

A paragraph in trouble.texi that talks about freestanding
implementations with -ansi -pedantic is not changed (given that the
description in terms of freestanding implementations is sufficiently
accurate for C90); if the -ansi there were changed to an option for a
more recent standard, a corresponding change to that paragraph might
be needed as well.

Tested with "make info html pdf".

* doc/standards.texi (C Language): Document library facilities
provided in terms of headers not declaring functions with external
linkage, not in terms of headers required of freestanding
implementations.
* doc/sourcebuild.texi (Subdirectories, Headers): Likewise.
* doc/trouble.texi (Standard Libraries): Likewise.

Diff:
---
 gcc/doc/sourcebuild.texi | 15 ---
 gcc/doc/standards.texi   | 38 ++
 gcc/doc/trouble.texi |  8 +---
 3 files changed, 39 insertions(+), 22 deletions(-)

diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 91fadc6ed01d..90430028eb86 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -215,10 +215,10 @@ man pages and support for converting the installation 
manual to
 HTML@.  @xref{Documentation}.
 
 @item ginclude
-System headers installed by GCC, mainly those required by the C
-standard of freestanding implementations.  @xref{Headers, , Headers
-Installed by GCC}, for details of when these and other headers are
-installed.
+System headers installed by GCC, mainly those defined by the C
+standard that do not declare functions with external linkage.
+@xref{Headers, , Headers Installed by GCC}, for details of when these
+and other headers are installed.
 
 @item po
 Message catalogs with translations of messages produced by GCC into
@@ -326,7 +326,8 @@ Headers Installed by GCC}, for more information about the
 In general, GCC expects the system C library to provide most of the
 headers to be used with it.  However, GCC will fix those headers if
 necessary to make them work with GCC, and will install some headers
-required of freestanding implementations.  These headers are installed
+of its own, mainly headers that do not declare functions with external
+linkage.  These headers are installed
 in @file{@var{libsubdir}/include}.  Headers for non-C runtime
 libraries are also installed by GCC; these are not documented here.
 (FIXME: document them somewhere.)
@@ -351,8 +352,8 @@ representation of floating point numbers.
 GCC also installs its own version of @code{}; this is generated
 from @file{glimits.h}, together with @file{limitx.h} and
 @file{limity.h} if the system also has its own version of
-@code{}.  (GCC provides its own header because it is
-required of ISO C freestanding implementations, but needs to include
+@code{}.  (GCC provides its own header because it does not
+declare functions with external linkage, but needs to include
 the system header from its own header as well because other standards
 such as POSIX specify additional values to be defined

[gcc r16-1003] Type mismatch for passed external function

2025-05-30 Thread Thomas Koenig via Gcc-cvs
https://gcc.gnu.org/g:0e77309047a7b479c89f03dcaf2994e050d0f33e

commit r16-1003-g0e77309047a7b479c89f03dcaf2994e050d0f33e
Author: Thomas Koenig 
Date:   Fri May 30 13:31:58 2025 +0200

Type mismatch for passed external function

This obvious and simple patch fixes a 15/16 regression where the
typespec of a global function was in the RESULT clause and not
in the symbol itself.

gcc/fortran/ChangeLog:

PR fortran/120355
* interface.cc (compare_parameter): If the global function has a
result clause, take typespec from there for the comparison against
the dummy argument.

gcc/testsuite/ChangeLog:

PR fortran/120355
* gfortran.dg/interface_62.f90: New test.

Diff:
---
 gcc/fortran/interface.cc   |  9 ++-
 gcc/testsuite/gfortran.dg/interface_62.f90 | 39 ++
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/interface.cc b/gcc/fortran/interface.cc
index 753f589ff677..b8542920ce79 100644
--- a/gcc/fortran/interface.cc
+++ b/gcc/fortran/interface.cc
@@ -2547,7 +2547,14 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
}
  else if (formal->attr.function)
{
- if (!gfc_compare_types (&global_asym->ts,
+ gfc_typespec ts;
+
+ if (global_asym->result)
+   ts = global_asym->result->ts;
+ else
+   ts = global_asym->ts;
+
+ if (!gfc_compare_types (&ts,
  &formal->ts))
{
  gfc_error ("Type mismatch at %L passing global "
diff --git a/gcc/testsuite/gfortran.dg/interface_62.f90 
b/gcc/testsuite/gfortran.dg/interface_62.f90
new file mode 100644
index ..19d4325d552f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/interface_62.f90
@@ -0,0 +1,39 @@
+! { dg-do compile }
+! PR fortran/120355 - this was rejected because the typespec from
+! the RESULT clause was not picked up.
+! Test case jsb...@bnl.gov.
+
+program p
+  implicit none
+  integer :: i,j
+  interface
+ function s(x) result(y)
+   implicit none
+   integer, intent(in) :: x
+   integer :: y
+ end function s
+  end interface
+  i = 0
+  call t(s,i,j)
+contains
+  subroutine t(f,x,y)
+implicit none
+integer, intent(in) :: x
+integer, intent(out) :: y
+interface
+   function f(x) result(y)
+ implicit none
+ integer, intent(in) :: x
+ integer :: y
+   end function f
+end interface
+y = f(x)
+  end subroutine t
+end program p
+
+function s(x) result(y)
+  implicit none
+  integer, intent(in) :: x
+  integer :: y
+  y = 1 - x
+end function s


[gcc r13-9728] Revert "[LRA]: Backporting solutions for PR112918 and PR113354 to solve PR99015"

2025-05-30 Thread Vladimir Makarov via Gcc-cvs
https://gcc.gnu.org/g:3e26dca1bd94ca26b21c661a471e929ab58642fd

commit r13-9728-g3e26dca1bd94ca26b21c661a471e929ab58642fd
Author: Vladimir N. Makarov 
Date:   Fri May 30 08:28:59 2025 -0400

Revert "[LRA]: Backporting solutions for PR112918 and PR113354 to solve 
PR99015"

This reverts commit af73c8bf5168848275bf909ee44fbb8f4973438f.

Diff:
---
 gcc/lra-constraints.cc | 124 +++--
 1 file changed, 49 insertions(+), 75 deletions(-)

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 2d31fcc9b4f2..21f05df0d618 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -233,41 +233,6 @@ get_reg_class (int regno)
   return NO_REGS;
 }
 
-/* Return true if REG_CLASS has enough allocatable hard regs to keep value of
-   REG_MODE.  */
-static bool
-enough_allocatable_hard_regs_p (enum reg_class reg_class,
-   enum machine_mode reg_mode)
-{
-  int i, j, hard_regno, class_size, nregs;
-
-  if (hard_reg_set_subset_p (reg_class_contents[reg_class], lra_no_alloc_regs))
-return false;
-  class_size = ira_class_hard_regs_num[reg_class];
-  for (i = 0; i < class_size; i++)
-{
-  hard_regno = ira_class_hard_regs[reg_class][i];
-  nregs = hard_regno_nregs (hard_regno, reg_mode);
-  if (nregs == 1)
-   return true;
-  for (j = 0; j < nregs; j++)
-   if (TEST_HARD_REG_BIT (lra_no_alloc_regs, hard_regno + j)
-   || ! TEST_HARD_REG_BIT (reg_class_contents[reg_class],
-   hard_regno + j))
- break;
-  if (j >= nregs)
-   return true;
-}
-  return false;
-}
-
-/* True if C is a non-empty register class that has too few registers
-   to be safely used as a reload target class. */
-#define SMALL_REGISTER_CLASS_P(C)  \
-  (ira_class_hard_regs_num [(C)] == 1  \
-   || (ira_class_hard_regs_num [(C)] >= 1  \
-   && targetm.class_likely_spilled_p (C)))
-
 /* Return true if REG satisfies (or will satisfy) reg class constraint
CL.  Use elimination first if REG is a hard register.  If REG is a
reload pseudo created by this constraints pass, assume that it will
@@ -287,6 +252,7 @@ in_class_p (rtx reg, enum reg_class cl, enum reg_class 
*new_class,
   enum reg_class rclass, common_class;
   machine_mode reg_mode;
   rtx src;
+  int class_size, hard_regno, nregs, i, j;
   int regno = REGNO (reg);
 
   if (new_class != NULL)
@@ -325,11 +291,26 @@ in_class_p (rtx reg, enum reg_class cl, enum reg_class 
*new_class,
   common_class = ira_reg_class_subset[rclass][cl];
   if (new_class != NULL)
*new_class = common_class;
-  return (enough_allocatable_hard_regs_p (common_class, reg_mode)
- /* Do not permit reload insn operand matching (new_class == NULL
-case) if the new class is too small.  */
- && (new_class != NULL || common_class == rclass
- || !SMALL_REGISTER_CLASS_P (common_class)));
+  if (hard_reg_set_subset_p (reg_class_contents[common_class],
+lra_no_alloc_regs))
+   return false;
+  /* Check that there are enough allocatable regs.  */
+  class_size = ira_class_hard_regs_num[common_class];
+  for (i = 0; i < class_size; i++)
+   {
+ hard_regno = ira_class_hard_regs[common_class][i];
+ nregs = hard_regno_nregs (hard_regno, reg_mode);
+ if (nregs == 1)
+   return true;
+ for (j = 0; j < nregs; j++)
+   if (TEST_HARD_REG_BIT (lra_no_alloc_regs, hard_regno + j)
+   || ! TEST_HARD_REG_BIT (reg_class_contents[common_class],
+   hard_regno + j))
+ break;
+ if (j >= nregs)
+   return true;
+   }
+  return false;
 }
 }
 
@@ -933,6 +914,13 @@ operands_match_p (rtx x, rtx y, int y_hard_regno)
&& GET_MODE_SIZE (MODE).is_constant ()  \
&& !targetm.cannot_force_const_mem (MODE, X))
 
+/* True if C is a non-empty register class that has too few registers
+   to be safely used as a reload target class. */
+#define SMALL_REGISTER_CLASS_P(C)  \
+  (ira_class_hard_regs_num [(C)] == 1  \
+   || (ira_class_hard_regs_num [(C)] >= 1  \
+   && targetm.class_likely_spilled_p (C)))
+
 /* If REG is a reload pseudo, try to make its class satisfying CL.  */
 static void
 narrow_reload_pseudo_class (rtx reg, enum reg_class cl)
@@ -2070,7 +2058,6 @@ process_alt_operands (int only_alternative)
   int curr_alt_dont_inherit_ops_num;
   /* Numbers of operands whose reload pseudos should not be inherited. */
   int curr_alt_dont_inherit_ops[MAX_RECOG_OPERANDS];
-  bool curr_alt_class_change_p;
   rtx op;
   /* The register when the operand is a subreg of register, otherwise the
  operand itself.  */
@@ -2146,7 +2133,6 @@ process_alt_operands (int only_alternative)
}
   reject += static_reject;
   early_clobbered_regs_num 

[gcc r13-9729] s390: Use match_scratch instead of scratch in define_split [PR119834]

2025-05-30 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:ceb2d19235478213219bb722cf4248a1ac78b73c

commit r13-9729-gceb2d19235478213219bb722cf4248a1ac78b73c
Author: Jakub Jelinek 
Date:   Thu Apr 17 10:57:18 2025 +0200

s390: Use match_scratch instead of scratch in define_split [PR119834]

The following testcase ICEs since r15-1579 (addition of late combiner),
because *clrmem_short can't be split.
The problem is that the define_insn uses
   (use (match_operand 1 "nonmemory_operand" "n,a,a,a"))
   (use (match_operand 2 "immediate_operand" "X,R,X,X"))
   (clobber (match_scratch:P 3 "=X,X,X,&a"))
and define_split assumed that if operands[1] is const_int_operand,
match_scratch will be always scratch, and it will be reg only if
it was the last alternative where operands[1] is a reg.
The pattern doesn't guarantee it though, of course RA will not try to
uselessly assign a reg there if it is not needed, but during RA
on the testcase below we match the last alternative, but then comes
late combiner and propagates const_int 3 into operands[1].  And that
matches fine, match_scratch matches either scratch or reg and the constraint
in that case is X for the first variant, so still just fine.  But we won't
split that because the splitters only expect scratch.

The following patch fixes it by using match_scratch instead of scratch,
so that it accepts either.

2025-04-17  Jakub Jelinek  

PR target/119834
* config/s390/s390.md (define_split after *cpymem_short): Use
(clobber (match_scratch N)) instead of (clobber (scratch)).  Use
(match_dup 4) and operands[4] instead of (match_dup 3) and 
operands[3]
in the last of those.
(define_split after *clrmem_short): Use (clobber (match_scratch N))
instead of (clobber (scratch)).
(define_split after *cmpmem_short): Likewise.

* g++.target/s390/pr119834.C: New test.

(cherry picked from commit 22fe83d6fc9f59311241c981bcad58b61e2056d4)

Diff:
---
 gcc/config/s390/s390.md  | 22 -
 gcc/testsuite/g++.target/s390/pr119834.C | 76 
 2 files changed, 87 insertions(+), 11 deletions(-)

diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 2e1229f5f411..d7664db4d672 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -3381,7 +3381,7 @@
 (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand 2 "const_int_operand" ""))
(use (match_operand 3 "immediate_operand" ""))
-   (clobber (scratch))]
+   (clobber (match_scratch 4))]
   "reload_completed"
   [(parallel
 [(set (match_dup 0) (match_dup 1))
@@ -3393,7 +3393,7 @@
 (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand 2 "register_operand" ""))
(use (match_operand 3 "memory_operand" ""))
-   (clobber (scratch))]
+   (clobber (match_scratch 4))]
   "reload_completed"
   [(parallel
 [(unspec [(match_dup 2) (match_dup 3)
@@ -3407,14 +3407,14 @@
 (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand 2 "register_operand" ""))
(use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
-   (clobber (scratch))]
+   (clobber (match_scratch 3))]
   "TARGET_Z10 && reload_completed"
   [(parallel
 [(unspec [(match_dup 2) (const_int 0)
-  (label_ref (match_dup 3))] UNSPEC_EXECUTE)
+ (label_ref (match_dup 4))] UNSPEC_EXECUTE)
  (set (match_dup 0) (match_dup 1))
  (use (const_int 1))])]
-  "operands[3] = gen_label_rtx ();")
+  "operands[4] = gen_label_rtx ();")
 
 (define_split
   [(set (match_operand:BLK 0 "memory_operand" "")
@@ -3595,7 +3595,7 @@
 (const_int 0))
(use (match_operand 1 "const_int_operand" ""))
(use (match_operand 2 "immediate_operand" ""))
-   (clobber (scratch))
+   (clobber (match_scratch 3))
(clobber (reg:CC CC_REGNUM))]
   "reload_completed"
   [(parallel
@@ -3609,7 +3609,7 @@
 (const_int 0))
(use (match_operand 1 "register_operand" ""))
(use (match_operand 2 "memory_operand" ""))
-   (clobber (scratch))
+   (clobber (match_scratch 3))
(clobber (reg:CC CC_REGNUM))]
   "reload_completed"
   [(parallel
@@ -3625,7 +3625,7 @@
 (const_int 0))
(use (match_operand 1 "register_operand" ""))
(use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
-   (clobber (scratch))
+   (clobber (match_scratch 2))
(clobber (reg:CC CC_REGNUM))]
   "TARGET_Z10 && reload_completed"
   [(parallel
@@ -3790,7 +3790,7 @@
  (match_operand:BLK 1 "memory_operand" "")))
(use (match_operand 2 "const_int_operand" ""))
(use (match_operand 3 "immediate_operand" ""))
-   (clobber (scratch))]
+   (clobber (match_scratch 4))]
   "reload_completed"
   [(parallel
 [(set (reg:CCU CC_REGNUM) (compare:CCU (match_dup 0) (match_dup 1)))
@@ -3803,7 +3803,7 @@
  (match_operand:BLK 1 "memory_op

[gcc r16-1005] testsuite: Add testcase for GCC 13 branch s390 bug [PR120480]

2025-05-30 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:c13d5b939fee565047394475952878dc5394fb74

commit r16-1005-gc13d5b939fee565047394475952878dc5394fb74
Author: Jakub Jelinek 
Date:   Fri May 30 14:35:12 2025 +0200

testsuite: Add testcase for GCC 13 branch s390 bug [PR120480]

This got broken with r13-9727 and fixed with either of
r13-9729 or r13-9728.

2025-05-30  Jakub Jelinek  

PR target/120480
* gcc.dg/pr120480.c: New test.

Diff:
---
 gcc/testsuite/gcc.dg/pr120480.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/pr120480.c b/gcc/testsuite/gcc.dg/pr120480.c
new file mode 100644
index ..cf7b47a1151d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120480.c
@@ -0,0 +1,11 @@
+/* PR target/120480 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+struct S { int a, b, c; } s;
+
+void
+foo (void)
+{
+  struct S t = s;
+}


[gcc r15-9744] testsuite: Add testcase for GCC 13 branch s390 bug [PR120480]

2025-05-30 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:9fa1f93eb7e39ccabf39a45e89f1a35adcf1bf1f

commit r15-9744-g9fa1f93eb7e39ccabf39a45e89f1a35adcf1bf1f
Author: Jakub Jelinek 
Date:   Fri May 30 14:35:12 2025 +0200

testsuite: Add testcase for GCC 13 branch s390 bug [PR120480]

This got broken with r13-9727 and fixed with either of
r13-9729 or r13-9728.

2025-05-30  Jakub Jelinek  

PR target/120480
* gcc.dg/pr120480.c: New test.

(cherry picked from commit c13d5b939fee565047394475952878dc5394fb74)

Diff:
---
 gcc/testsuite/gcc.dg/pr120480.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/pr120480.c b/gcc/testsuite/gcc.dg/pr120480.c
new file mode 100644
index ..cf7b47a1151d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120480.c
@@ -0,0 +1,11 @@
+/* PR target/120480 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+struct S { int a, b, c; } s;
+
+void
+foo (void)
+{
+  struct S t = s;
+}


[gcc r16-1012] tree-optimization/120341 - stores into STRING_CSTs can trap

2025-05-30 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:02c58bc4b0885f5b6f50033da35768ebe6c4a030

commit r16-1012-g02c58bc4b0885f5b6f50033da35768ebe6c4a030
Author: Richard Biener 
Date:   Fri May 30 13:47:55 2025 +0200

tree-optimization/120341 - stores into STRING_CSTs can trap

The following fixes conditional store elimination and store motion
so they consider stores to STRING_CSTs as trapping.

PR tree-optimization/120341
* tree-ssa-loop-im.cc (can_sm_ref_p): STRING_CSTs are readonly.
* tree-ssa-phiopt.cc (cond_store_replacement): Likewise.

* gcc.dg/torture/pr120341-1.c: New testcase.
* gcc.dg/torture/pr120341-2.c: Likewise.

Diff:
---
 gcc/testsuite/gcc.dg/torture/pr120341-1.c | 11 +++
 gcc/testsuite/gcc.dg/torture/pr120341-2.c | 13 +
 gcc/tree-ssa-loop-im.cc   |  3 ++-
 gcc/tree-ssa-phiopt.cc|  5 +++--
 4 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/torture/pr120341-1.c 
b/gcc/testsuite/gcc.dg/torture/pr120341-1.c
new file mode 100644
index ..e23185b62b07
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr120341-1.c
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fallow-store-data-races" } */
+
+char a, *b;
+int main()
+{
+  b = "0";
+  if (a)
+b[0]++;
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr120341-2.c 
b/gcc/testsuite/gcc.dg/torture/pr120341-2.c
new file mode 100644
index ..7bcc96f63ddc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr120341-2.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fallow-store-data-races" } */
+
+char a, *b;
+int main()
+{
+  while (a)
+{
+  b = "0";
+  b[0]++;
+}
+  return 0;
+}
diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc
index 50d2ee9b99d6..aee419aa5b1e 100644
--- a/gcc/tree-ssa-loop-im.cc
+++ b/gcc/tree-ssa-loop-im.cc
@@ -3307,7 +3307,8 @@ can_sm_ref_p (class loop *loop, im_mem_ref *ref)
  explicitly.  */
   base = get_base_address (ref->mem.ref);
   if ((tree_could_trap_p (ref->mem.ref)
-   || (DECL_P (base) && TREE_READONLY (base)))
+   || (DECL_P (base) && TREE_READONLY (base))
+   || TREE_CODE (base) == STRING_CST)
   /* ???  We can at least use false here, allowing loads?  We
 are forcing conditional stores if the ref is not always
 stored to later anyway.  So this would only guard
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 8c5908e5bff9..bf493e129878 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -3525,8 +3525,9 @@ cond_store_replacement (basic_block middle_bb, 
basic_block join_bb,
  /* tree_could_trap_p is a predicate for rvalues, so check
 for readonly memory explicitly.  */
  || ((base = get_base_address (lhs))
- && DECL_P (base)
- && TREE_READONLY (base)))
+ && ((DECL_P (base)
+  && TREE_READONLY (base))
+ || TREE_CODE (base) == STRING_CST)))
return false;
 }


[gcc r14-11818] s390: Use match_scratch instead of scratch in define_split [PR119834]

2025-05-30 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:004523c9530f94ae3d64d4c9967ff90388bc

commit r14-11818-g004523c9530f94ae3d64d4c9967ff90388bc
Author: Jakub Jelinek 
Date:   Thu Apr 17 10:57:18 2025 +0200

s390: Use match_scratch instead of scratch in define_split [PR119834]

The following testcase ICEs since r15-1579 (addition of late combiner),
because *clrmem_short can't be split.
The problem is that the define_insn uses
   (use (match_operand 1 "nonmemory_operand" "n,a,a,a"))
   (use (match_operand 2 "immediate_operand" "X,R,X,X"))
   (clobber (match_scratch:P 3 "=X,X,X,&a"))
and define_split assumed that if operands[1] is const_int_operand,
match_scratch will be always scratch, and it will be reg only if
it was the last alternative where operands[1] is a reg.
The pattern doesn't guarantee it though, of course RA will not try to
uselessly assign a reg there if it is not needed, but during RA
on the testcase below we match the last alternative, but then comes
late combiner and propagates const_int 3 into operands[1].  And that
matches fine, match_scratch matches either scratch or reg and the constraint
in that case is X for the first variant, so still just fine.  But we won't
split that because the splitters only expect scratch.

The following patch fixes it by using match_scratch instead of scratch,
so that it accepts either.

2025-04-17  Jakub Jelinek  

PR target/119834
* config/s390/s390.md (define_split after *cpymem_short): Use
(clobber (match_scratch N)) instead of (clobber (scratch)).  Use
(match_dup 4) and operands[4] instead of (match_dup 3) and 
operands[3]
in the last of those.
(define_split after *clrmem_short): Use (clobber (match_scratch N))
instead of (clobber (scratch)).
(define_split after *cmpmem_short): Likewise.

* g++.target/s390/pr119834.C: New test.

(cherry picked from commit 22fe83d6fc9f59311241c981bcad58b61e2056d4)

Diff:
---
 gcc/config/s390/s390.md  | 22 -
 gcc/testsuite/g++.target/s390/pr119834.C | 76 
 2 files changed, 87 insertions(+), 11 deletions(-)

diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 72e05be9b182..c364880af0ae 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -3392,7 +3392,7 @@
 (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand 2 "const_int_operand" ""))
(use (match_operand 3 "immediate_operand" ""))
-   (clobber (scratch))]
+   (clobber (match_scratch 4))]
   "reload_completed"
   [(parallel
 [(set (match_dup 0) (match_dup 1))
@@ -3404,7 +3404,7 @@
 (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand 2 "register_operand" ""))
(use (match_operand 3 "memory_operand" ""))
-   (clobber (scratch))]
+   (clobber (match_scratch 4))]
   "reload_completed"
   [(parallel
 [(unspec [(match_dup 2) (match_dup 3)
@@ -3418,14 +3418,14 @@
 (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand 2 "register_operand" ""))
(use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
-   (clobber (scratch))]
+   (clobber (match_scratch 3))]
   "TARGET_Z10 && reload_completed"
   [(parallel
 [(unspec [(match_dup 2) (const_int 0)
-  (label_ref (match_dup 3))] UNSPEC_EXECUTE)
+ (label_ref (match_dup 4))] UNSPEC_EXECUTE)
  (set (match_dup 0) (match_dup 1))
  (use (const_int 1))])]
-  "operands[3] = gen_label_rtx ();")
+  "operands[4] = gen_label_rtx ();")
 
 (define_split
   [(set (match_operand:BLK 0 "memory_operand" "")
@@ -3644,7 +3644,7 @@
 (const_int 0))
(use (match_operand 1 "const_int_operand" ""))
(use (match_operand 2 "immediate_operand" ""))
-   (clobber (scratch))
+   (clobber (match_scratch 3))
(clobber (reg:CC CC_REGNUM))]
   "reload_completed"
   [(parallel
@@ -3658,7 +3658,7 @@
 (const_int 0))
(use (match_operand 1 "register_operand" ""))
(use (match_operand 2 "memory_operand" ""))
-   (clobber (scratch))
+   (clobber (match_scratch 3))
(clobber (reg:CC CC_REGNUM))]
   "reload_completed"
   [(parallel
@@ -3674,7 +3674,7 @@
 (const_int 0))
(use (match_operand 1 "register_operand" ""))
(use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
-   (clobber (scratch))
+   (clobber (match_scratch 2))
(clobber (reg:CC CC_REGNUM))]
   "TARGET_Z10 && reload_completed"
   [(parallel
@@ -3839,7 +3839,7 @@
  (match_operand:BLK 1 "memory_operand" "")))
(use (match_operand 2 "const_int_operand" ""))
(use (match_operand 3 "immediate_operand" ""))
-   (clobber (scratch))]
+   (clobber (match_scratch 4))]
   "reload_completed"
   [(parallel
 [(set (reg:CCU CC_REGNUM) (compare:CCU (match_dup 0) (match_dup 1)))
@@ -3852,7 +3852,7 @@
  (match_operand:BLK 1 "memory_o

[gcc r16-1023] c++: another xobj lambda testcase [PR120123]

2025-05-30 Thread Jason Merrill via Gcc-cvs
https://gcc.gnu.org/g:d10e3e0900c92479a6621e375070d4a99ca1fd57

commit r16-1023-gd10e3e0900c92479a6621e375070d4a99ca1fd57
Author: Jason Merrill 
Date:   Fri May 30 18:27:45 2025 -0400

c++: another xobj lambda testcase [PR120123]

Patrick noticed this was fixed by r16-970.

PR c++/120123

gcc/testsuite/ChangeLog:

* g++.dg/cpp23/explicit-obj-lambda18.C: New test.

Diff:
---
 gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C | 13 +
 1 file changed, 13 insertions(+)

diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C 
b/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C
new file mode 100644
index ..21bd2e99e79d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C
@@ -0,0 +1,13 @@
+// PR c++/120123
+// { dg-do compile { target c++23 } }
+
+struct H {
+void member(int) {}
+void call() {
+[this]() {
+[this](const auto& v)
+requires requires { /*this->*/member(v); }
+{ return member(v); }(0);
+};
+}
+};


[gcc r16-1026] PR modula2/120389 Assigning wrong type to an array causes an ICE

2025-05-30 Thread Gaius Mulley via Gcc-cvs
https://gcc.gnu.org/g:e131ba3de5f487f5e957ba1b011c960fce557c7b

commit r16-1026-ge131ba3de5f487f5e957ba1b011c960fce557c7b
Author: Gaius Mulley 
Date:   Sat May 31 01:53:48 2025 +0100

PR modula2/120389 Assigning wrong type to an array causes an ICE

This patch provides follow on fixes for undetected type violations
which can occur then Lvalues are generated during assignment.
For example array accesses and with statements.  The type checker
M2Check.mod has been overhauled and cleaned up.

gcc/ChangeLog:

PR modula2/120389
* doc/gm2.texi (-fm2-strict-type-reason): Document new flag.

gcc/m2/ChangeLog:

PR modula2/120389
* gm2-compiler/M2Check.def (AssignmentTypeCompatible): Add new
parameter enableReason.
* gm2-compiler/M2Check.mod (EquivalenceProcedure): New type.
(falseReason2): New procedure function.
(falseReason1): Ditto.
(falseReason0): Ditto.
(checkTypeEquivalence): Rewrite.
(checkUnboundedArray): Ditto.
(checkUnbounded): Ditto.
(checkArrayTypeEquivalence): Ditto.
(checkCharStringTypeEquivalence): Ditto.
(buildError4): Add false reason.
(buildError2): Ditto.
(IsTyped): Use GetDType.
(IsTypeEquivalence): New procedure function.
(checkVarTypeEquivalence): Ditto.
(checkVarEquivalence ): Rewrite.
(checkConstMeta): Ditto.
(checkEnumField): New procedure function.
(checkEnumFieldEquivalence): Ditto.
(checkSubrangeTypeEquivalence): Rewrite.
(checkSystemEquivalence): Ditto.
(checkTypeKindViolation): Ditto.
(doCheckPair): Ditto.
(InitEquivalenceArray): New procedure.
(addEquivalence): Ditto.
(checkProcType): Rewrite.
(deconstruct): Deallocate reason string.
(AssignmentTypeCompatible): Initialize reason and reasonEnable
fields.
(ParameterTypeCompatible): Ditto.
(doExpressionTypeCompatible): Ditto.
* gm2-compiler/M2GenGCC.mod (CodeIndrX) Rewrite.
(CheckBinaryExpressionTypes): Rewrite and simplify now that the
type checker is more robust.
(CheckElementSetTypes): Ditto.
(CodeXIndr): Add new range assignment type check.
* gm2-compiler/M2MetaError.def: Correct comments.
* gm2-compiler/M2Options.def (SetStrictTypeAssignment): New 
procedure.
(SetStrictTypeReason): Ditto.
* gm2-compiler/M2Options.mod: (SetStrictTypeAssignment): New 
procedure.
(SetStrictTypeReason): Ditto.
(StrictTypeReason): Initialize.
(StrictTypeAssignment): Ditto.
* gm2-compiler/M2Quads.mod (CheckBreak): Delete.
(BreakQuad): New global variable.
(BreakAtQuad): Delete.
(gdbhook): New procedure.
(BreakWhenQuadCreated): Ditto.
(CheckBreak): Ditto.
(Init): Call BreakWhenQuadCreated and gdbhook.
(doBuildAssignment): Add type assignment range check.
(CheckProcTypeAndProcedure): Only check if the procedure
types differ.
(doIndrX): Add type IndrX range check.
(CheckReturnType): Add range return type check.
* gm2-compiler/M2Range.def (InitTypesIndrXCheck): New procedure
function.
(InitTypesReturnTypeCheck): Ditto.
* gm2-compiler/M2Range.mod (InitTypesIndrXCheck): New procedure
function.
(InitTypesReturnTypeCheck): Ditto.
(HandlerExists): Add new clauses.
(FoldAssignment): Pass extra FALSE parameter to
AssignmentTypeCompatible.
(FoldTypeReturnFunc): New procedure.
(FoldTypeAssign): Ditto.
(FoldTypeIndrX): Ditto.
(CodeTypeAssign): Rewrite.
(CodeTypeIndrX): New procedure.
(CodeTypeReturnFunc): Ditto.
(FoldTypeCheck): Add new case clauses.
(CodeTypeCheck): Ditto.
(FoldRangeCheckLower): Ditto.
(IssueWarning): Ditto.
* gm2-gcc/m2options.h (M2Options_SetStrictTypeAssignment): New
function prototype.
(M2Options_SetStrictTypeReason): Ditto.
* gm2-lang.cc (gm2_langhook_handle_option): New case clause
OPT_fm2_strict_type_reason.
* lang.opt (-fm2-strict-type-reason): New option.

gcc/testsuite/ChangeLog:

PR modula2/120389
* gm2/pim/fail/testcharint.mod: New test.
* gm2/pim/fail/testindrx.mod: New test.
* gm2/pim/pass/testxindr.mod: New test.
* gm2/pim/pass/testxindr2.mod: New test.
* gm2/pim/pass/testxindr3.mod: New test.

Signed-off-by: Ga

[gcc r15-9748] Type mismatch for passed external function

2025-05-30 Thread Thomas Koenig via Gcc-cvs
https://gcc.gnu.org/g:d8e7a2dbe736a57e4cec0293387a1c558b5a155e

commit r15-9748-gd8e7a2dbe736a57e4cec0293387a1c558b5a155e
Author: Thomas Koenig 
Date:   Fri May 30 13:31:58 2025 +0200

Type mismatch for passed external function

This obvious and simple patch fixes a 15/16 regression where the
typespec of a global function was in the RESULT clause and not
in the symbol itself.

gcc/fortran/ChangeLog:

PR fortran/120355
* interface.cc (compare_parameter): If the global function has a
result clause, take typespec from there for the comparison against
the dummy argument.

gcc/testsuite/ChangeLog:

PR fortran/120355
* gfortran.dg/interface_62.f90: New test.

(cherry picked from commit 0e77309047a7b479c89f03dcaf2994e050d0f33e)

Diff:
---
 gcc/fortran/interface.cc   |  9 ++-
 gcc/testsuite/gfortran.dg/interface_62.f90 | 39 ++
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/interface.cc b/gcc/fortran/interface.cc
index 753f589ff677..b8542920ce79 100644
--- a/gcc/fortran/interface.cc
+++ b/gcc/fortran/interface.cc
@@ -2547,7 +2547,14 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
}
  else if (formal->attr.function)
{
- if (!gfc_compare_types (&global_asym->ts,
+ gfc_typespec ts;
+
+ if (global_asym->result)
+   ts = global_asym->result->ts;
+ else
+   ts = global_asym->ts;
+
+ if (!gfc_compare_types (&ts,
  &formal->ts))
{
  gfc_error ("Type mismatch at %L passing global "
diff --git a/gcc/testsuite/gfortran.dg/interface_62.f90 
b/gcc/testsuite/gfortran.dg/interface_62.f90
new file mode 100644
index ..19d4325d552f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/interface_62.f90
@@ -0,0 +1,39 @@
+! { dg-do compile }
+! PR fortran/120355 - this was rejected because the typespec from
+! the RESULT clause was not picked up.
+! Test case jsb...@bnl.gov.
+
+program p
+  implicit none
+  integer :: i,j
+  interface
+ function s(x) result(y)
+   implicit none
+   integer, intent(in) :: x
+   integer :: y
+ end function s
+  end interface
+  i = 0
+  call t(s,i,j)
+contains
+  subroutine t(f,x,y)
+implicit none
+integer, intent(in) :: x
+integer, intent(out) :: y
+interface
+   function f(x) result(y)
+ implicit none
+ integer, intent(in) :: x
+ integer :: y
+   end function f
+end interface
+y = f(x)
+  end subroutine t
+end program p
+
+function s(x) result(y)
+  implicit none
+  integer, intent(in) :: x
+  integer :: y
+  y = 1 - x
+end function s


[gcc r16-1024] diagnostics: implement highlight-a vs -b in HTML output [PR116792]

2025-05-30 Thread David Malcolm via Gcc-cvs
https://gcc.gnu.org/g:a746747e2102c965a7736dc22ba56c3bc8e3e61e

commit r16-1024-ga746747e2102c965a7736dc22ba56c3bc8e3e61e
Author: David Malcolm 
Date:   Fri May 30 19:57:46 2025 -0400

diagnostics: implement highlight-a vs -b in HTML output [PR116792]

Update HTML output so that it renders highlight-a vs highlight-b
via  tags in the message itself, in the quoted source line,
in the underlines, and in the labels and their vertical bars.

Example output can be seen at:
  https://dmalcolm.fedorapeople.org/gcc/2025-05-28/diagnostic-ranges.c.html

gcc/ChangeLog:
PR other/116792
* diagnostic-format-html.cc (HTML_STYLE): Add ".highlight-a" and
".highlight-b".
(html_builder::make_element_for_diagnostic): Handle begin_color
and end_color.
* diagnostic-show-locus.cc (to_html::to_html): Add "richloc"
param and use it to initialize m_richloc.
(to_html::colorize_text_for_range_idx): Drop.
(to_html::get_location_range_by_idx): New.
(to_html::get_highlight_color_for_range_idx): New.
(to_html::m_richloc): New field.
(print_html_span_start): Update for new param of to_html ctor.
(line_printer::m_was_in_range_p): New field.
(line_printer::m_last_range_idx): New field.
(layout_printer::print_source_line): Use set_in_range
and set_outside_range rather than colorization calls.
(layout_printer::set_in_range): New.
(layout_printer::set_outside_range): New.
(layout_printer::print_annotation_line): Use set_in_range
and set_outside_range rather than colorization calls.
(layout_printer::begin_label): Convert param from label
to state_idx.  Add "is_label_text" param and use it to guard logic
for turning off colorization within paths.
(layout_printer::begin_label): Likewise.  Push 
for any highlight color.
(layout_printer::end_label): Likewise.
(layout_printer::end_label): Likewise, popping the
.
(layout_printer::print_any_labels): Convert begin/end_label
calls to pass in state_idx rather than label.  Use begin/end_label
rather than colorization calls.
(layout_printer::layout_printer): Likewise.
(layout_printer::layout_printer): Initialize new fields.
(diagnostic_source_print_policy::print_as_html): Update for new
param of to_html ctor.

gcc/testsuite/ChangeLog:
PR other/116792
* gcc.dg/format/diagnostic-ranges-html.py: New test script.
* gcc.dg/format/diagnostic-ranges.c: Add HTML generation to
options, and invoke the new script to check the HTML output.

Signed-off-by: David Malcolm 

Diff:
---
 gcc/diagnostic-format-html.cc  |  13 +-
 gcc/diagnostic-show-locus.cc   | 140 +
 .../gcc.dg/format/diagnostic-ranges-html.py|  99 +++
 gcc/testsuite/gcc.dg/format/diagnostic-ranges.c|   6 +-
 4 files changed, 230 insertions(+), 28 deletions(-)

diff --git a/gcc/diagnostic-format-html.cc b/gcc/diagnostic-format-html.cc
index c430bdac75ae..05d4273c2c61 100644
--- a/gcc/diagnostic-format-html.cc
+++ b/gcc/diagnostic-format-html.cc
@@ -511,6 +511,10 @@ static const char * const HTML_STYLE
  "box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.5); }\n"
  ".frame-funcname { text-align: right;\n"
  "  font-style: italic; } \n"
+ ".highlight-a { color: #703fec;\n" // pf-purple-400
+ "   font-weight: bold; }\n"
+ ".highlight-b { color: #3f9c35;\n" // pf-green-400
+ "   font-weight: bold; }\n"
  "  \n");
 
 /* A little JavaScript for ease of navigation.
@@ -725,8 +729,15 @@ html_builder::make_element_for_diagnostic (const 
diagnostic_info &diagnostic,
break;
 
  case pp_token::kind::begin_color:
+   {
+ pp_token_begin_color *sub = as_a  (iter);
+ gcc_assert (sub->m_value.get ());
+ m_xp.push_tag_with_class ("span", sub->m_value.get ());
+   }
+   break;
+
  case pp_token::kind::end_color:
-   /* These are no-ops.  */
+   m_xp.pop_tag ();
break;
 
  case pp_token::kind::begin_quote:
diff --git a/gcc/diagnostic-show-locus.cc b/gcc/diagnostic-show-locus.cc
index c6a0cd80ce8c..3654102509b9 100644
--- a/gcc/diagnostic-show-locus.cc
+++ b/gcc/diagnostic-show-locus.cc
@@ -539,8 +539,10 @@ struct to_html
   friend class layout_printer;
 
   to_html (xml::printer &xp,
+  const rich_location *richloc,
   html_label_writer *html_label_writer)
   : m_xp (xp),
+m_richloc (richloc),
 m_html_label_writer (html_label_write