forked from OSchip/llvm-project
Fix deduction of __atomic_load's parameter types.
Summary: __atomic_load's allows it's first argument to be a pointer to a const type. However the second argument is an output parameter and must be a pointer to non-const. This patch fixes the signature of __atomic_load generated by clang so that it respects the above requirements. Reviewers: rsmith, majnemer Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D13420 llvm-svn: 264967
This commit is contained in:
parent
6596977130
commit
8d662441a6
|
@ -1829,6 +1829,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
|
|||
// C __c11_atomic_load(A *, int)
|
||||
Load,
|
||||
// void __atomic_load(A *, CP, int)
|
||||
LoadCopy,
|
||||
// void __atomic_store(A *, CP, int)
|
||||
Copy,
|
||||
// C __c11_atomic_add(A *, M, int)
|
||||
Arithmetic,
|
||||
|
@ -1841,8 +1843,8 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
|
|||
// bool __atomic_compare_exchange(A *, C *, CP, bool, int, int)
|
||||
GNUCmpXchg
|
||||
} Form = Init;
|
||||
const unsigned NumArgs[] = { 2, 2, 3, 3, 3, 4, 5, 6 };
|
||||
const unsigned NumVals[] = { 1, 0, 1, 1, 1, 2, 2, 3 };
|
||||
const unsigned NumArgs[] = { 2, 2, 3, 3, 3, 3, 4, 5, 6 };
|
||||
const unsigned NumVals[] = { 1, 0, 1, 1, 1, 1, 2, 2, 3 };
|
||||
// where:
|
||||
// C is an appropriate type,
|
||||
// A is volatile _Atomic(C) for __c11 builtins and is C for GNU builtins,
|
||||
|
@ -1872,8 +1874,11 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
|
|||
Form = Load;
|
||||
break;
|
||||
|
||||
case AtomicExpr::AO__c11_atomic_store:
|
||||
case AtomicExpr::AO__atomic_load:
|
||||
Form = LoadCopy;
|
||||
break;
|
||||
|
||||
case AtomicExpr::AO__c11_atomic_store:
|
||||
case AtomicExpr::AO__atomic_store:
|
||||
case AtomicExpr::AO__atomic_store_n:
|
||||
Form = Copy;
|
||||
|
@ -1960,7 +1965,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
|
|||
return ExprError();
|
||||
}
|
||||
ValType = AtomTy->getAs<AtomicType>()->getValueType();
|
||||
} else if (Form != Load && Op != AtomicExpr::AO__atomic_load) {
|
||||
} else if (Form != Load && Form != LoadCopy) {
|
||||
if (ValType.isConstQualified()) {
|
||||
Diag(DRE->getLocStart(), diag::err_atomic_op_needs_non_const_pointer)
|
||||
<< Ptr->getType() << Ptr->getSourceRange();
|
||||
|
@ -2021,10 +2026,11 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
|
|||
|
||||
// atomic_fetch_or takes a pointer to a volatile 'A'. We shouldn't let the
|
||||
// volatile-ness of the pointee-type inject itself into the result or the
|
||||
// other operands.
|
||||
// other operands. Similarly atomic_load can take a pointer to a const 'A'.
|
||||
ValType.removeLocalVolatile();
|
||||
ValType.removeLocalConst();
|
||||
QualType ResultType = ValType;
|
||||
if (Form == Copy || Form == GNUXchg || Form == Init)
|
||||
if (Form == Copy || Form == LoadCopy || Form == GNUXchg || Form == Init)
|
||||
ResultType = Context.VoidTy;
|
||||
else if (Form == C11CmpXchg || Form == GNUCmpXchg)
|
||||
ResultType = Context.BoolTy;
|
||||
|
@ -2035,10 +2041,6 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
|
|||
if (!IsC11 && !IsN)
|
||||
ByValType = Ptr->getType();
|
||||
|
||||
// FIXME: __atomic_load allows the first argument to be a a pointer to const
|
||||
// but not the second argument. We need to manually remove possible const
|
||||
// qualifiers.
|
||||
|
||||
// The first argument --- the pointer --- has a fixed type; we
|
||||
// deduce the types of the rest of the arguments accordingly. Walk
|
||||
// the remaining arguments, converting them to the deduced value type.
|
||||
|
@ -2105,6 +2107,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
|
|||
case Load:
|
||||
SubExprs.push_back(TheCall->getArg(1)); // Order
|
||||
break;
|
||||
case LoadCopy:
|
||||
case Copy:
|
||||
case Arithmetic:
|
||||
case Xchg:
|
||||
|
|
|
@ -121,7 +121,10 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,
|
|||
__atomic_load(I, *P, memory_order_relaxed, 42); // expected-error {{too many arguments}}
|
||||
(int)__atomic_load(I, I, memory_order_seq_cst); // expected-error {{operand of type 'void'}}
|
||||
__atomic_load(s1, s2, memory_order_acquire);
|
||||
(void)__atomic_load(I, CI, memory_order_relaxed); // expected-warning {{passing 'const int *' to parameter of type 'int *' discards qualifiers}}
|
||||
__atomic_load(CI, I, memory_order_relaxed);
|
||||
__atomic_load(I, CI, memory_order_relaxed); // expected-warning {{passing 'const int *' to parameter of type 'int *' discards qualifiers}}
|
||||
__atomic_load(CI, CI, memory_order_relaxed); // expected-warning {{passing 'const int *' to parameter of type 'int *' discards qualifiers}}
|
||||
|
||||
__c11_atomic_store(i, 1, memory_order_seq_cst);
|
||||
__c11_atomic_store(p, 1, memory_order_seq_cst); // expected-warning {{incompatible integer to pointer conversion}}
|
||||
(int)__c11_atomic_store(d, 1, memory_order_seq_cst); // expected-error {{operand of type 'void'}}
|
||||
|
|
Loading…
Reference in New Issue