diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index ca75a4f1b8ad0462ec833e5a31e61bc6ec32ce97..e82f918198c5d208499461c1c2140658c7d4c7b8 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -4145,6 +4145,13 @@ static IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType()); } +static QualType GetExprType(Expr *E) { + QualType Ty = E->getType(); + if (const AtomicType *AtomicRHS = Ty->getAs<AtomicType>()) + Ty = AtomicRHS->getValueType(); + return Ty; +} + /// Pseudo-evaluate the given integer expression, estimating the /// range of values it might take. /// @@ -4155,7 +4162,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { // Try a full evaluation first. Expr::EvalResult result; if (E->EvaluateAsRValue(result, C)) - return GetValueRange(C, result.Val, E->getType(), MaxWidth); + return GetValueRange(C, result.Val, GetExprType(E), MaxWidth); // I think we only want to look through implicit casts here; if the // user has an explicit widening cast, we should treat the value as @@ -4164,7 +4171,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { if (CE->getCastKind() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue) return GetExprRange(C, CE->getSubExpr(), MaxWidth); - IntRange OutputTypeRange = IntRange::forValueOfType(C, CE->getType()); + IntRange OutputTypeRange = IntRange::forValueOfType(C, GetExprType(CE)); bool isIntegerCast = (CE->getCastKind() == CK_IntegralCast); @@ -4224,7 +4231,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { case BO_XorAssign: case BO_OrAssign: // TODO: bitfields? - return IntRange::forValueOfType(C, E->getType()); + return IntRange::forValueOfType(C, GetExprType(E)); // Simple assignments just pass through the RHS, which will have // been coerced to the LHS type. @@ -4235,7 +4242,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { // Operations with opaque sources are black-listed. case BO_PtrMemD: case BO_PtrMemI: - return IntRange::forValueOfType(C, E->getType()); + return IntRange::forValueOfType(C, GetExprType(E)); // Bitwise-and uses the *infinum* of the two source ranges. case BO_And: @@ -4250,14 +4257,14 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { if (IntegerLiteral *I = dyn_cast<IntegerLiteral>(BO->getLHS()->IgnoreParenCasts())) { if (I->getValue() == 1) { - IntRange R = IntRange::forValueOfType(C, E->getType()); + IntRange R = IntRange::forValueOfType(C, GetExprType(E)); return IntRange(R.Width, /*NonNegative*/ true); } } // fallthrough case BO_ShlAssign: - return IntRange::forValueOfType(C, E->getType()); + return IntRange::forValueOfType(C, GetExprType(E)); // Right shift by a constant can narrow its left argument. case BO_Shr: @@ -4286,14 +4293,14 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { // Black-list pointer subtractions. case BO_Sub: if (BO->getLHS()->getType()->isPointerType()) - return IntRange::forValueOfType(C, E->getType()); + return IntRange::forValueOfType(C, GetExprType(E)); break; // The width of a division result is mostly determined by the size // of the LHS. case BO_Div: { // Don't 'pre-truncate' the operands. - unsigned opWidth = C.getIntWidth(E->getType()); + unsigned opWidth = C.getIntWidth(GetExprType(E)); IntRange L = GetExprRange(C, BO->getLHS(), opWidth); // If the divisor is constant, use that. @@ -4316,7 +4323,7 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { // either side. case BO_Rem: { // Don't 'pre-truncate' the operands. - unsigned opWidth = C.getIntWidth(E->getType()); + unsigned opWidth = C.getIntWidth(GetExprType(E)); IntRange L = GetExprRange(C, BO->getLHS(), opWidth); IntRange R = GetExprRange(C, BO->getRHS(), opWidth); @@ -4349,26 +4356,22 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { // Operations with opaque sources are black-listed. case UO_Deref: case UO_AddrOf: // should be impossible - return IntRange::forValueOfType(C, E->getType()); + return IntRange::forValueOfType(C, GetExprType(E)); default: return GetExprRange(C, UO->getSubExpr(), MaxWidth); } } - - if (dyn_cast<OffsetOfExpr>(E)) { - IntRange::forValueOfType(C, E->getType()); - } if (FieldDecl *BitField = E->getSourceBitField()) return IntRange(BitField->getBitWidthValue(C), BitField->getType()->isUnsignedIntegerOrEnumerationType()); - return IntRange::forValueOfType(C, E->getType()); + return IntRange::forValueOfType(C, GetExprType(E)); } static IntRange GetExprRange(ASTContext &C, Expr *E) { - return GetExprRange(C, E, C.getIntWidth(E->getType())); + return GetExprRange(C, E, C.getIntWidth(GetExprType(E))); } /// Checks whether the given value, which currently has the given diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c35c1b4e6446a5c89dc8cf5a7c98246eb37973c4..b4dbcd2c9ed8081e90879f14f1a29455820dac5e 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5280,11 +5280,8 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, Cond = UsualUnaryConversions(Cond.take()); if (Cond.isInvalid()) return QualType(); - LHS = UsualUnaryConversions(LHS.take()); - if (LHS.isInvalid()) - return QualType(); - RHS = UsualUnaryConversions(RHS.take()); - if (RHS.isInvalid()) + UsualArithmeticConversions(LHS, RHS); + if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); QualType CondTy = Cond.get()->getType(); @@ -5308,12 +5305,8 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // If both operands have arithmetic type, do the usual arithmetic conversions // to find a common type: C99 6.5.15p3,5. - if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) { - UsualArithmeticConversions(LHS, RHS); - if (LHS.isInvalid() || RHS.isInvalid()) - return QualType(); + if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) return LHS.get()->getType(); - } // If both operands are the same structure or union type, the result is that // type. @@ -7401,21 +7394,9 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, } // C99 6.5.8p3 / C99 6.5.9p4 - if (LHS.get()->getType()->isArithmeticType() && - RHS.get()->getType()->isArithmeticType()) { - UsualArithmeticConversions(LHS, RHS); - if (LHS.isInvalid() || RHS.isInvalid()) - return QualType(); - } - else { - LHS = UsualUnaryConversions(LHS.take()); - if (LHS.isInvalid()) - return QualType(); - - RHS = UsualUnaryConversions(RHS.take()); - if (RHS.isInvalid()) - return QualType(); - } + UsualArithmeticConversions(LHS, RHS); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); LHSType = LHS.get()->getType(); RHSType = RHS.get()->getType(); diff --git a/test/Sema/atomic-expr.c b/test/Sema/atomic-expr.c index ecc04c4c68d6827039f3cc6c70218672fbec7546..5602d545cc7f97d89089cdc08d7b133db2784b25 100644 --- a/test/Sema/atomic-expr.c +++ b/test/Sema/atomic-expr.c @@ -45,3 +45,16 @@ void func_09 (int* xp) { void func_10 (int* xp) { *xp <<= data2; } + +int func_11 (int x) { + return data1 == x; +} + +int func_12 () { + return data1 < data2; +} + +int func_13 (int x, unsigned y) { + return x ? data1 : y; +} +