Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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``
Expand Down
15 changes: 15 additions & 0 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 1 addition & 5 deletions clang/lib/AST/StmtPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down
92 changes: 92 additions & 0 deletions clang/test/SemaCXX/ast-print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 *();
Expand Down