// Load/convert the LHS.
LValue LHSLV = EmitCheckedLValue(E->getLHS());
OpInfo.LHS = EmitLoadOfLValue(LHSLV);
- OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy,
- E->getComputationLHSType());
llvm::PHINode *atomicPHI = 0;
- if (const AtomicType *atomicTy = OpInfo.Ty->getAs<AtomicType>()) {
+ if (LHSTy->isAtomicType()) {
// FIXME: For floating point types, we should be saving and restoring the
// floating point environment in the loop.
llvm::BasicBlock *startBB = Builder.GetInsertBlock();
Builder.SetInsertPoint(opBB);
atomicPHI = Builder.CreatePHI(OpInfo.LHS->getType(), 2);
atomicPHI->addIncoming(OpInfo.LHS, startBB);
- OpInfo.Ty = atomicTy->getValueType();
OpInfo.LHS = atomicPHI;
}
-
+
+ OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy,
+ E->getComputationLHSType());
+
// Expand the binary operator.
Result = (this->*Func)(OpInfo);
QualType RHSType =
Context.getCanonicalType(RHS.get()->getType()).getUnqualifiedType();
+ // For conversion purposes, we ignore any atomic qualifier on the LHS.
+ if (const AtomicType *AtomicLHS = LHSType->getAs<AtomicType>())
+ LHSType = AtomicLHS->getValueType();
+
// If both types are identical, no conversion is needed.
if (LHSType == RHSType)
return LHSType;
// If either side is a non-arithmetic type (e.g. a pointer), we are done.
// The caller can deal with this (e.g. pointer + int).
if (!LHSType->isArithmeticType() || !RHSType->isArithmeticType())
- return LHSType;
+ return QualType();
// Apply unary and bitfield promotions to the LHS's type.
QualType LHSUnpromotedType = LHSType;
// 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;
return Compatible;
}
+ // If we have an atomic type, try a non-atomic assignment, then just add an
+ // atomic qualification step.
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;
- }
+ Sema::AssignConvertType result =
+ CheckAssignmentConstraints(AtomicTy->getValueType(), RHS, Kind);
+ if (result != Compatible)
+ return result;
+ if (Kind != CK_NoOp)
+ RHS = ImpCastExprToType(RHS.take(), AtomicTy->getValueType(), Kind);
+ Kind = CK_NonAtomicToAtomic;
+ 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,
return QualType();
- if (!LHS.get()->getType()->isArithmeticType() ||
- !RHS.get()->getType()->isArithmeticType()) {
- if (IsCompAssign &&
- LHS.get()->getType()->isAtomicType() &&
- RHS.get()->getType()->isArithmeticType())
- return compType;
+ if (compType.isNull() || !compType->isArithmeticType())
return InvalidOperands(Loc, LHS, RHS);
- }
// Check for division by zero.
if (IsDiv &&
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
- if (!LHS.get()->getType()->isIntegerType() ||
- !RHS.get()->getType()->isIntegerType())
+ if (compType.isNull() || !compType->isIntegerType())
return InvalidOperands(Loc, LHS, RHS);
// Check for remainder by zero.
diagnoseStringPlusInt(*this, Loc, LHS.get(), RHS.get());
// handle the common case first (both operands are arithmetic).
- if (LHS.get()->getType()->isArithmeticType() &&
- RHS.get()->getType()->isArithmeticType()) {
+ if (!compType.isNull() && compType->isArithmeticType()) {
if (CompLHSTy) *CompLHSTy = compType;
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())
// Enforce type constraints: C99 6.5.6p3.
// Handle the common case first (both operands are arithmetic).
- if (LHS.get()->getType()->isArithmeticType() &&
- RHS.get()->getType()->isArithmeticType()) {
+ if (!compType.isNull() && compType->isArithmeticType()) {
if (CompLHSTy) *CompLHSTy = compType;
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();
LHS = LHSResult.take();
RHS = RHSResult.take();
- if (LHS.get()->getType()->isIntegralOrUnscopedEnumerationType() &&
- RHS.get()->getType()->isIntegralOrUnscopedEnumerationType())
+ if (!compType.isNull() && compType->isIntegralOrUnscopedEnumerationType())
return compType;
return InvalidOperands(Loc, LHS, RHS);
}