Skip to content

Commit

Permalink
__c11_atomic_load's _Atomic can be const
Browse files Browse the repository at this point in the history
Summary:
C++11 onwards specs the non-member functions atomic_load and atomic_load_explicit as taking the atomic<T> by const (potentially volatile) pointer. C11, in its infinite wisdom, decided to drop the const, and C17 will fix this with DR459 (the current draft forgot to fix B.16, but that’s not the normative part).

clang’s lib/Headers/stdatomic.h implements these as #define to the __c11_* equivalent, which are builtins with custom typecheck. Fix the typecheck.

D47613 takes care of the libc++ side.

Discussion: http://lists.llvm.org/pipermail/cfe-dev/2018-May/058129.html

<rdar://problem/27426936>

Reviewers: rsmith

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D47618

llvm-svn: 338743
  • Loading branch information
jfbastien committed Aug 2, 2018
1 parent ae67218 commit b4b1f59
Show file tree
Hide file tree
Showing 3 changed files with 6 additions and 5 deletions.
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaChecking.cpp
Expand Up @@ -4347,7 +4347,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
<< Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
if (AtomTy.isConstQualified() ||
if ((Form != Load && Form != LoadCopy && AtomTy.isConstQualified()) ||
AtomTy.getAddressSpace() == LangAS::opencl_constant) {
Diag(DRE->getLocStart(), diag::err_atomic_op_needs_non_const_atomic)
<< (AtomTy.isConstQualified() ? 0 : 1) << Ptr->getType()
Expand Down
4 changes: 2 additions & 2 deletions clang/test/Sema/atomic-ops.c
Expand Up @@ -115,7 +115,7 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,
__c11_atomic_load(i, memory_order_seq_cst);
__c11_atomic_load(p, memory_order_seq_cst);
__c11_atomic_load(d, memory_order_seq_cst);
__c11_atomic_load(ci, memory_order_seq_cst); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const _Atomic(int) *' invalid)}}
__c11_atomic_load(ci, memory_order_seq_cst);

int load_n_1 = __atomic_load_n(I, memory_order_relaxed);
int *load_n_2 = __atomic_load_n(P, memory_order_relaxed);
Expand Down Expand Up @@ -222,7 +222,7 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,

__c11_atomic_init(ci, 0); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const _Atomic(int) *' invalid)}}
__c11_atomic_store(ci, 0, memory_order_release); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const _Atomic(int) *' invalid)}}
__c11_atomic_load(ci, memory_order_acquire); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const _Atomic(int) *' invalid)}}
__c11_atomic_load(ci, memory_order_acquire);

// Ensure the <stdatomic.h> macros behave appropriately.
atomic_int n = ATOMIC_VAR_INIT(123);
Expand Down
5 changes: 3 additions & 2 deletions clang/test/SemaOpenCL/atomic-ops.cl
Expand Up @@ -58,7 +58,8 @@ void f(atomic_int *i, const atomic_int *ci,
__opencl_atomic_load(i, memory_order_seq_cst, memory_scope_work_group);
__opencl_atomic_load(p, memory_order_seq_cst, memory_scope_work_group);
__opencl_atomic_load(d, memory_order_seq_cst, memory_scope_work_group);
__opencl_atomic_load(ci, memory_order_seq_cst, memory_scope_work_group); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const __generic atomic_int *' (aka 'const __generic _Atomic(int) *') invalid)}}
__opencl_atomic_load(ci, memory_order_seq_cst, memory_scope_work_group);
__opencl_atomic_load(i_c, memory_order_seq_cst, memory_scope_work_group); // expected-error {{address argument to atomic operation must be a pointer to non-constant _Atomic type ('__constant atomic_int *' (aka '__constant _Atomic(int) *') invalid)}}

__opencl_atomic_store(i, 1, memory_order_seq_cst, memory_scope_work_group);
__opencl_atomic_store(p, 1, memory_order_seq_cst, memory_scope_work_group);
Expand Down Expand Up @@ -94,7 +95,7 @@ void f(atomic_int *i, const atomic_int *ci,

__opencl_atomic_init(ci, 0); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const __generic atomic_int *' (aka 'const __generic _Atomic(int) *') invalid)}}
__opencl_atomic_store(ci, 0, memory_order_release, memory_scope_work_group); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const __generic atomic_int *' (aka 'const __generic _Atomic(int) *') invalid)}}
__opencl_atomic_load(ci, memory_order_acquire, memory_scope_work_group); // expected-error {{address argument to atomic operation must be a pointer to non-const _Atomic type ('const __generic atomic_int *' (aka 'const __generic _Atomic(int) *') invalid)}}
__opencl_atomic_load(ci, memory_order_acquire, memory_scope_work_group);

__opencl_atomic_init(&gn, 456);
__opencl_atomic_init(&gn, (void*)0); // expected-warning{{incompatible pointer to integer conversion passing '__generic void *' to parameter of type 'int'}}
Expand Down

0 comments on commit b4b1f59

Please sign in to comment.