2024-02-20 Jakub Jelinek <ja...@redhat.com>
gcc/c-family/
* c-common.cc (resolve_overloaded_atomic_exchange): Instead of setting
p1 to VIEW_CONVERT_EXPR<I_type> (*p1), set it to MEM_REF with p1 and
(typeof (p1)) 0 operands and I_type type.
(resolve_overloaded_atomic_compare_exchange): Similarly for p2.
gcc/cp/
* pt.cc (tsubst_expr): Handle MEM_REF.
gcc/testsuite/
* g++.dg/ext/atomic-5.C: New test.
--- gcc/c-family/c-common.cc.jj 2024-02-17 16:40:42.831571693 +0100
+++ gcc/c-family/c-common.cc 2024-02-20 10:58:56.599865656 +0100
@@ -7793,9 +7793,14 @@ resolve_overloaded_atomic_exchange (loca
/* Convert object pointer to required type. */
p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
(*params)[0] = p0;
- /* Convert new value to required type, and dereference it. */
- p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
- p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
+ /* Convert new value to required type, and dereference it.
+ If *p1 type can have padding or may involve floating point which
+ could e.g. be promoted to wider precision and demoted afterwards,
+ state of padding bits might not be preserved. */
+ build_indirect_ref (loc, p1, RO_UNARY_STAR);
+ p1 = build2_loc (loc, MEM_REF, I_type,
+ build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1),
+ build_zero_cst (TREE_TYPE (p1)));
(*params)[1] = p1;
/* Move memory model to the 3rd position, and end param list. */
@@ -7873,9 +7878,14 @@ resolve_overloaded_atomic_compare_exchan
p1 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1);
(*params)[1] = p1;
- /* Convert desired value to required type, and dereference it. */
- p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR);
- p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2);
+ /* Convert desired value to required type, and dereference it.
+ If *p2 type can have padding or may involve floating point which
+ could e.g. be promoted to wider precision and demoted afterwards,
+ state of padding bits might not be preserved. */
+ build_indirect_ref (loc, p2, RO_UNARY_STAR);
+ p2 = build2_loc (loc, MEM_REF, I_type,
+ build1 (VIEW_CONVERT_EXPR, I_type_ptr, p2),
+ build_zero_cst (TREE_TYPE (p2)));
(*params)[2] = p2;
/* The rest of the parameters are fine. NULL means no special return value
--- gcc/cp/pt.cc.jj 2024-02-17 16:40:42.868571182 +0100
+++ gcc/cp/pt.cc 2024-02-20 10:57:36.646973603 +0100
@@ -20088,6 +20088,14 @@ tsubst_expr (tree t, tree args, tsubst_f
RETURN (r);
}
+ case MEM_REF:
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ tree op1 = RECUR (TREE_OPERAND (t, 0));
+ tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ RETURN (build2_loc (EXPR_LOCATION (t), MEM_REF, new_type, op0, op1));
+ }
+
case NOP_EXPR:
{
tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
--- gcc/testsuite/g++.dg/ext/atomic-5.C.jj 2024-02-20 10:57:36.647973589
+0100
+++ gcc/testsuite/g++.dg/ext/atomic-5.C 2024-02-20 10:57:36.647973589 +0100
@@ -0,0 +1,42 @@
+// { dg-do compile { target c++14 } }
+
+template <int N>
+void
+foo (long double *ptr, long double *val, long double *ret)
+{
+ __atomic_exchange (ptr, val, ret, __ATOMIC_RELAXED);
+}
+
+template <int N>
+bool
+bar (long double *ptr, long double *exp, long double *des)
+{
+ return __atomic_compare_exchange (ptr, exp, des, false,
+ __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
+
+bool
+baz (long double *p, long double *q, long double *r)
+{
+ foo<0> (p, q, r);
+ foo<1> (p + 1, q + 1, r + 1);
+ return bar<0> (p + 2, q + 2, r + 2) || bar<1> (p + 3, q + 3, r + 3);
+}
+
+constexpr int
+qux (long double *ptr, long double *val, long double *ret)
+{
+ __atomic_exchange (ptr, val, ret, __ATOMIC_RELAXED);
+ return 0;
+}
+
+constexpr bool
+corge (long double *ptr, long double *exp, long double *des)
+{
+ return __atomic_compare_exchange (ptr, exp, des, false,
+ __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
+
+long double a[6];
+const int b = qux (a, a + 1, a + 2);
+const bool c = corge (a + 3, a + 4, a + 5);
Jakub