diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/CodeGen/CGAtomic.cpp | 30 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 38 | 
2 files changed, 47 insertions, 21 deletions
diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index b5a494e2879..dcb3ff10335 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -24,16 +24,6 @@  using namespace clang;  using namespace CodeGen; -// The ABI values for various atomic memory orderings. -enum AtomicOrderingKind { -  AO_ABI_memory_order_relaxed = 0, -  AO_ABI_memory_order_consume = 1, -  AO_ABI_memory_order_acquire = 2, -  AO_ABI_memory_order_release = 3, -  AO_ABI_memory_order_acq_rel = 4, -  AO_ABI_memory_order_seq_cst = 5 -}; -  namespace {    class AtomicInfo {      CodeGenFunction &CGF; @@ -642,30 +632,30 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {    if (isa<llvm::ConstantInt>(Order)) {      int ord = cast<llvm::ConstantInt>(Order)->getZExtValue();      switch (ord) { -    case AO_ABI_memory_order_relaxed: +    case AtomicExpr::AO_ABI_memory_order_relaxed:        EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, Size, Align,                     llvm::Monotonic);        break; -    case AO_ABI_memory_order_consume: -    case AO_ABI_memory_order_acquire: +    case AtomicExpr::AO_ABI_memory_order_consume: +    case AtomicExpr::AO_ABI_memory_order_acquire:        if (IsStore)          break; // Avoid crashing on code with undefined behavior        EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, Size, Align,                     llvm::Acquire);        break; -    case AO_ABI_memory_order_release: +    case AtomicExpr::AO_ABI_memory_order_release:        if (IsLoad)          break; // Avoid crashing on code with undefined behavior        EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, Size, Align,                     llvm::Release);        break; -    case AO_ABI_memory_order_acq_rel: +    case AtomicExpr::AO_ABI_memory_order_acq_rel:        if (IsLoad || IsStore)          break; // Avoid crashing on code with undefined behavior        EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, Size, Align,                     llvm::AcquireRelease);        break; -    case AO_ABI_memory_order_seq_cst: +    case AtomicExpr::AO_ABI_memory_order_seq_cst:        EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, Size, Align,                     llvm::SequentiallyConsistent);        break; @@ -788,8 +778,8 @@ RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc,               getContext().VoidPtrTy);      args.add(RValue::get(EmitCastToVoidPtr(tempAddr)),               getContext().VoidPtrTy); -    args.add(RValue::get(llvm::ConstantInt::get(IntTy, -                                                AO_ABI_memory_order_seq_cst)), +    args.add(RValue::get(llvm::ConstantInt::get( +                 IntTy, AtomicExpr::AO_ABI_memory_order_seq_cst)),               getContext().IntTy);      emitAtomicLibcall(*this, "__atomic_load", getContext().VoidTy, args); @@ -938,8 +928,8 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, bool isInit) {               getContext().VoidPtrTy);      args.add(RValue::get(EmitCastToVoidPtr(srcAddr)),               getContext().VoidPtrTy); -    args.add(RValue::get(llvm::ConstantInt::get(IntTy, -                                                AO_ABI_memory_order_seq_cst)), +    args.add(RValue::get(llvm::ConstantInt::get( +                 IntTy, AtomicExpr::AO_ABI_memory_order_seq_cst)),               getContext().IntTy);      emitAtomicLibcall(*this, "__atomic_store", getContext().VoidTy, args);      return; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 512916e9a8e..19e61b2e819 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -911,6 +911,33 @@ bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) {    return false;  } +static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) { +  if (Ordering < AtomicExpr::AO_ABI_memory_order_relaxed || +      Ordering > AtomicExpr::AO_ABI_memory_order_seq_cst) +    return false; + +  switch (Op) { +  case AtomicExpr::AO__c11_atomic_init: +    llvm_unreachable("There is no ordering argument for an init"); + +  case AtomicExpr::AO__c11_atomic_load: +  case AtomicExpr::AO__atomic_load_n: +  case AtomicExpr::AO__atomic_load: +    return Ordering != AtomicExpr::AO_ABI_memory_order_release && +           Ordering != AtomicExpr::AO_ABI_memory_order_acq_rel; + +  case AtomicExpr::AO__c11_atomic_store: +  case AtomicExpr::AO__atomic_store: +  case AtomicExpr::AO__atomic_store_n: +    return Ordering != AtomicExpr::AO_ABI_memory_order_consume && +           Ordering != AtomicExpr::AO_ABI_memory_order_acquire && +           Ordering != AtomicExpr::AO_ABI_memory_order_acq_rel; + +  default: +    return true; +  } +} +  ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,                                           AtomicExpr::AtomicOp Op) {    CallExpr *TheCall = cast<CallExpr>(TheCallResult.get()); @@ -1199,7 +1226,16 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,      SubExprs.push_back(TheCall->getArg(3)); // Weak      break;    } -   + +  if (SubExprs.size() >= 2 && Form != Init) { +    llvm::APSInt Result(32); +    if (SubExprs[1]->isIntegerConstantExpr(Result, Context) && +        !isValidOrderingForOp(Result.getSExtValue(), Op)) +      return ExprError(Diag(SubExprs[1]->getLocStart(), +                            diag::err_atomic_op_has_invalid_memory_order) +                       << SubExprs[1]->getSourceRange()); +  } +    AtomicExpr *AE = new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(),                                              SubExprs, ResultType, Op,                                              TheCall->getRParenLoc());  | 

