From 09bddcf8c0ce4cc2f2a18e050e971539e8a396f8 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Mon, 8 Jul 2013 20:20:06 +0000 Subject: [PATCH] Fix Sema for compares with _Atomic vars. Use UsualArithmeticConversions unconditionally in analysis of comparisons and conditional operators: the method performs the usual arithmetic conversions if both sides are arithmetic, and usual unary conversions if they are not. This is just a cleanup for conditional operators; for comparisons, it fixes the issue that we would try to check isArithmetic() on an atomic type. Also, fix GetExprRange() in SemaChecking.cpp so it deals with variables of atomic type correctly. Fixes PR15537. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@185857 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaChecking.cpp | 35 +++++++++++++++++++---------------- lib/Sema/SemaExpr.cpp | 31 ++++++------------------------- test/Sema/atomic-expr.c | 13 +++++++++++++ 3 files changed, 38 insertions(+), 41 deletions(-) diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index ca75a4f1b8..e82f918198 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()) + 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(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(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 c35c1b4e64..b4dbcd2c9e 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 ecc04c4c68..5602d545cc 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; +} + -- 2.40.0