[clang] ba49062 - [Clang][AST] Fix printing for `atomic_test_and_set` and `atomic_clear` (#159712)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 19 06:17:49 PDT 2025
Author: Devajith
Date: 2025-09-19T15:17:45+02:00
New Revision: ba49062914f01f68cf3c4e067139a24b29a0e45b
URL: https://github.com/llvm/llvm-project/commit/ba49062914f01f68cf3c4e067139a24b29a0e45b
DIFF: https://github.com/llvm/llvm-project/commit/ba49062914f01f68cf3c4e067139a24b29a0e45b.diff
LOG: [Clang][AST] Fix printing for `atomic_test_and_set` and `atomic_clear` (#159712)
https://github.com/llvm/llvm-project/pull/121943 rewrote
`__atomic_test_and_set` and `__atomic_clear` to be lowered through
AtomicExpr
StmtPrinter::VisitAtomicExpr still treated them like other atomic
builtins with a Val1 operand. This led to incorrect pretty-printing when
dumping the AST.
Skip Val1 for these two builtins like atomic loads.
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/Expr.h
clang/lib/AST/StmtPrinter.cpp
clang/test/SemaCXX/ast-print.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c898784b3f93e..ed668ca6f207c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -114,6 +114,15 @@ AST Dumping Potentially Breaking Changes
----------------------------------------
- How nested name specifiers are dumped and printed changes, keeping track of clang AST changes.
+- Pretty-printing of atomic builtins ``__atomic_test_and_set`` and ``__atomic_clear`` in ``-ast-print`` output.
+ These previously displayed an extra ``<null expr>`` argument, e.g.:
+
+ ``__atomic_test_and_set(p, <null expr>, 0)``
+
+ Now they are printed as:
+
+ ``__atomic_test_and_set(p, 0)``
+
Clang Frontend Potentially Breaking Changes
-------------------------------------------
- Members of anonymous unions/structs are now injected as ``IndirectFieldDecl``
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 9eb1a86931b11..e1a4005d1a890 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -6908,6 +6908,21 @@ class AtomicExpr : public Expr {
getOp() == AO__scoped_atomic_compare_exchange_n;
}
+ bool hasVal1Operand() const {
+ switch (getOp()) {
+ case AO__atomic_load_n:
+ case AO__scoped_atomic_load_n:
+ case AO__c11_atomic_load:
+ case AO__opencl_atomic_load:
+ case AO__hip_atomic_load:
+ case AO__atomic_test_and_set:
+ case AO__atomic_clear:
+ return false;
+ default:
+ return true;
+ }
+ }
+
bool isOpenCL() const {
return getOp() >= AO__opencl_atomic_compare_exchange_strong &&
getOp() <= AO__opencl_atomic_store;
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 0030300521128..2c9c3581a2962 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -2024,11 +2024,7 @@ void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) {
// AtomicExpr stores its subexpressions in a permuted order.
PrintExpr(Node->getPtr());
- if (Node->getOp() != AtomicExpr::AO__c11_atomic_load &&
- Node->getOp() != AtomicExpr::AO__atomic_load_n &&
- Node->getOp() != AtomicExpr::AO__scoped_atomic_load_n &&
- Node->getOp() != AtomicExpr::AO__opencl_atomic_load &&
- Node->getOp() != AtomicExpr::AO__hip_atomic_load) {
+ if (Node->hasVal1Operand()) {
OS << ", ";
PrintExpr(Node->getVal1());
}
diff --git a/clang/test/SemaCXX/ast-print.cpp b/clang/test/SemaCXX/ast-print.cpp
index 2cb1ec440b6bb..616fcac64c6f4 100644
--- a/clang/test/SemaCXX/ast-print.cpp
+++ b/clang/test/SemaCXX/ast-print.cpp
@@ -176,6 +176,98 @@ float test15() {
return __builtin_asinf(1.0F);
}
+// CHECK: void test_atomic_loads(int *ptr, int *ret, int memorder) {
+// CHECK: __atomic_load_n(ptr, memorder);
+// CHECK: __atomic_load(ptr, ret, memorder);
+// CHECK: }
+void test_atomic_loads(int *ptr, int *ret, int memorder) {
+ __atomic_load_n(ptr, memorder);
+ __atomic_load(ptr, ret, memorder);
+}
+
+// CHECK: void test_atomic_stores(int *ptr, int val, int memorder) {
+// CHECK: __atomic_store_n(ptr, val, memorder);
+// CHECK: __atomic_store(ptr, &val, memorder);
+// CHECK: }
+void test_atomic_stores(int *ptr, int val, int memorder) {
+ __atomic_store_n(ptr, val, memorder);
+ __atomic_store(ptr, &val, memorder);
+}
+
+// CHECK: void test_atomic_exchanges(int *ptr, int val, int *ret, int memorder) {
+// CHECK: __atomic_exchange_n(ptr, val, memorder);
+// CHECK: __atomic_exchange(ptr, &val, ret, memorder);
+// CHECK: }
+void test_atomic_exchanges(int *ptr, int val, int *ret, int memorder) {
+ __atomic_exchange_n(ptr, val, memorder);
+ __atomic_exchange(ptr, &val, ret, memorder);
+}
+
+// CHECK: void test_atomic_cmpxchgs(int *ptr, int *expected, int desired, bool weak, int success_memorder, int failure_memorder) {
+// CHECK: __atomic_compare_exchange_n(ptr, expected, desired, weak, success_memorder, failure_memorder);
+// CHECK: __atomic_compare_exchange(ptr, expected, &desired, weak, success_memorder, failure_memorder);
+// CHECK: }
+void test_atomic_cmpxchgs(int *ptr, int *expected, int desired, bool weak, int success_memorder, int failure_memorder) {
+ __atomic_compare_exchange_n(ptr, expected, desired, weak, success_memorder, failure_memorder);
+ __atomic_compare_exchange(ptr, expected, &desired, weak, success_memorder, failure_memorder);
+}
+
+// CHECK: void test_atomic_fetch_ops(int *ptr, int val, int memorder) {
+// CHECK: __atomic_add_fetch(ptr, val, memorder);
+// CHECK: __atomic_sub_fetch(ptr, val, memorder);
+// CHECK: __atomic_and_fetch(ptr, val, memorder);
+// CHECK: __atomic_xor_fetch(ptr, val, memorder);
+// CHECK: __atomic_or_fetch(ptr, val, memorder);
+// CHECK: __atomic_nand_fetch(ptr, val, memorder);
+// CHECK: __atomic_fetch_add(ptr, val, memorder);
+// CHECK: __atomic_fetch_sub(ptr, val, memorder);
+// CHECK: __atomic_fetch_and(ptr, val, memorder);
+// CHECK: __atomic_fetch_xor(ptr, val, memorder);
+// CHECK: __atomic_fetch_or(ptr, val, memorder);
+// CHECK: __atomic_fetch_nand(ptr, val, memorder);
+// CHECK: }
+void test_atomic_fetch_ops(int *ptr, int val, int memorder) {
+ __atomic_add_fetch(ptr, val, memorder);
+ __atomic_sub_fetch(ptr, val, memorder);
+ __atomic_and_fetch(ptr, val, memorder);
+ __atomic_xor_fetch(ptr, val, memorder);
+ __atomic_or_fetch(ptr, val, memorder);
+ __atomic_nand_fetch(ptr, val, memorder);
+ __atomic_fetch_add(ptr, val, memorder);
+ __atomic_fetch_sub(ptr, val, memorder);
+ __atomic_fetch_and(ptr, val, memorder);
+ __atomic_fetch_xor(ptr, val, memorder);
+ __atomic_fetch_or(ptr, val, memorder);
+ __atomic_fetch_nand(ptr, val, memorder);
+}
+
+// CHECK: void test_atomic_setclear(void *ptr, int memorder) {
+// CHECK: __atomic_test_and_set(ptr, memorder);
+// CHECK: __atomic_clear(ptr, memorder);
+// CHECK: }
+void test_atomic_setclear(void *ptr, int memorder) {
+ __atomic_test_and_set(ptr, memorder);
+ __atomic_clear(ptr, memorder);
+}
+
+// CHECK: void test_atomic_fences(int memorder) {
+// CHECK: __atomic_thread_fence(memorder);
+// CHECK: __atomic_signal_fence(memorder);
+// CHECK: }
+void test_atomic_fences(int memorder) {
+ __atomic_thread_fence(memorder);
+ __atomic_signal_fence(memorder);
+}
+
+// CHECK: void test_atomic_lockfree(unsigned long size, void *ptr) {
+// CHECK: __atomic_always_lock_free(size, ptr);
+// CHECK: __atomic_is_lock_free(size, ptr);
+// CHECK: }
+void test_atomic_lockfree(unsigned long size, void *ptr) {
+ __atomic_always_lock_free(size, ptr);
+ __atomic_is_lock_free(size, ptr);
+}
+
namespace PR18776 {
struct A {
operator void *();
More information about the cfe-commits
mailing list