aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaCast.cpp5
-rw-r--r--lib/Sema/SemaChecking.cpp8
-rw-r--r--lib/Sema/SemaExpr.cpp49
3 files changed, 57 insertions, 5 deletions
diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp
index 2c7611de6b..fe7667e93b 100644
--- a/lib/Sema/SemaCast.cpp
+++ b/lib/Sema/SemaCast.cpp
@@ -1897,6 +1897,11 @@ void CastOperation::CheckCStyleCast() {
if (SrcExpr.isInvalid())
return;
QualType SrcType = SrcExpr.get()->getType();
+
+ // You can cast an _Atomic(T) to anything you can cast a T to.
+ if (const AtomicType *AtomicSrcType = SrcType->getAs<AtomicType>())
+ SrcType = AtomicSrcType->getValueType();
+
assert(!SrcType->isPlaceholderType());
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 90ad03755b..77c5717d24 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -277,6 +277,8 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Load);
case Builtin::BI__atomic_store:
return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Store);
+ case Builtin::BI__atomic_init:
+ return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Init);
case Builtin::BI__atomic_exchange:
return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::Xchg);
case Builtin::BI__atomic_compare_exchange_strong:
@@ -538,6 +540,8 @@ Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op)
NumVals = 2;
NumOrders = 2;
}
+ if (Op == AtomicExpr::Init)
+ NumOrders = 0;
if (TheCall->getNumArgs() < NumVals+NumOrders+1) {
Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
@@ -600,7 +604,7 @@ Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op)
}
QualType ResultType = ValType;
- if (Op == AtomicExpr::Store)
+ if (Op == AtomicExpr::Store || Op == AtomicExpr::Init)
ResultType = Context.VoidTy;
else if (Op == AtomicExpr::CmpXchgWeak || Op == AtomicExpr::CmpXchgStrong)
ResultType = Context.BoolTy;
@@ -641,6 +645,8 @@ Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op)
SubExprs.push_back(Ptr);
if (Op == AtomicExpr::Load) {
SubExprs.push_back(TheCall->getArg(1)); // Order
+ } else if (Op == AtomicExpr::Init) {
+ SubExprs.push_back(TheCall->getArg(1)); // Val1
} else if (Op != AtomicExpr::CmpXchgWeak && Op != AtomicExpr::CmpXchgStrong) {
SubExprs.push_back(TheCall->getArg(2)); // Order
SubExprs.push_back(TheCall->getArg(1)); // Val1
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 39161ea88d..5baf14342f 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -4066,6 +4066,11 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
// pointers. Everything else should be possible.
QualType SrcTy = Src.get()->getType();
+ if (const AtomicType *SrcAtomicTy = SrcTy->getAs<AtomicType>())
+ SrcTy = SrcAtomicTy->getValueType();
+ if (const AtomicType *DestAtomicTy = DestTy->getAs<AtomicType>())
+ DestTy = DestAtomicTy->getValueType();
+
if (Context.hasSameUnqualifiedType(SrcTy, DestTy))
return CK_NoOp;
@@ -5358,9 +5363,6 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
LHSType = Context.getCanonicalType(LHSType).getUnqualifiedType();
RHSType = Context.getCanonicalType(RHSType).getUnqualifiedType();
- // We can't do assignment from/to atomics yet.
- if (LHSType->isAtomicType())
- return Incompatible;
// Common case: no conversion required.
if (LHSType == RHSType) {
@@ -5368,6 +5370,21 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
return Compatible;
}
+ if (const AtomicType *AtomicTy = dyn_cast<AtomicType>(LHSType)) {
+ if (AtomicTy->getValueType() == RHSType) {
+ Kind = CK_NonAtomicToAtomic;
+ return Compatible;
+ }
+ }
+
+ if (const AtomicType *AtomicTy = dyn_cast<AtomicType>(RHSType)) {
+ if (AtomicTy->getValueType() == LHSType) {
+ Kind = CK_AtomicToNonAtomic;
+ return Compatible;
+ }
+ }
+
+
// If the left-hand side is a reference type, then we are in a
// (rare!) case where we've allowed the use of references in C,
// e.g., as a parameter type in a built-in function. In this case,
@@ -5906,9 +5923,15 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
+
if (!LHS.get()->getType()->isArithmeticType() ||
- !RHS.get()->getType()->isArithmeticType())
+ !RHS.get()->getType()->isArithmeticType()) {
+ if (IsCompAssign &&
+ LHS.get()->getType()->isAtomicType() &&
+ RHS.get()->getType()->isArithmeticType())
+ return compType;
return InvalidOperands(Loc, LHS, RHS);
+ }
// Check for division by zero.
if (IsDiv &&
@@ -6134,6 +6157,12 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6
return compType;
}
+ if (LHS.get()->getType()->isAtomicType() &&
+ RHS.get()->getType()->isArithmeticType()) {
+ *CompLHSTy = LHS.get()->getType();
+ return compType;
+ }
+
// Put any potential pointer into PExp
Expr* PExp = LHS.get(), *IExp = RHS.get();
if (IExp->getType()->isAnyPointerType())
@@ -6194,6 +6223,12 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
return compType;
}
+ if (LHS.get()->getType()->isAtomicType() &&
+ RHS.get()->getType()->isArithmeticType()) {
+ *CompLHSTy = LHS.get()->getType();
+ return compType;
+ }
+
// Either ptr - int or ptr - ptr.
if (LHS.get()->getType()->isAnyPointerType()) {
QualType lpointee = LHS.get()->getType()->getPointeeType();
@@ -7290,6 +7325,12 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
return S.Context.DependentTy;
QualType ResType = Op->getType();
+ // Atomic types can be used for increment / decrement where the non-atomic
+ // versions can, so ignore the _Atomic() specifier for the purpose of
+ // checking.
+ if (const AtomicType *ResAtomicType = ResType->getAs<AtomicType>())
+ ResType = ResAtomicType->getValueType();
+
assert(!ResType.isNull() && "no type for increment/decrement expression");
if (S.getLangOptions().CPlusPlus && ResType->isBooleanType()) {