From: Eric Fiselier Date: Wed, 30 Mar 2016 23:39:56 +0000 (+0000) Subject: Fix deduction of __atomic_load's parameter types. X-Git-Tag: llvmorg-3.9.0-rc1~10429 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8d662441a6a50530d7779e815df14c0426deb8e3;p=platform%2Fupstream%2Fllvm.git 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 --- diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 6f9060b..43195bd 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -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()->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: diff --git a/clang/test/Sema/atomic-ops.c b/clang/test/Sema/atomic-ops.c index 9a37ec2..0583621 100644 --- a/clang/test/Sema/atomic-ops.c +++ b/clang/test/Sema/atomic-ops.c @@ -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'}}