diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-01-08 21:12:04 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-01-08 21:12:04 +0000 |
| commit | a12bf9106a70841f96c7105ef663a1af5f45989a (patch) | |
| tree | e4e47a31165b07b5d3d400eb9307d557102eb6d2 /clang/lib/Sema/SemaExpr.cpp | |
| parent | 215284d089dd0956f684daf10f245b1a31c14aed (diff) | |
| download | bcm5719-llvm-a12bf9106a70841f96c7105ef663a1af5f45989a.tar.gz bcm5719-llvm-a12bf9106a70841f96c7105ef663a1af5f45989a.zip | |
Factor out comparison handling for arithmetic types.
This is not quite NFC: we don't perform the usual arithmetic conversions unless
we have an operand of arithmetic or enumeration type any more. This matches the
standard rule, but actually has no effect other than to marginally improve our
diagnostics for the non-arithmetic, non-enumeration cases (by not performing
integral promotions on one operand if the other is a pointer).
llvm-svn: 322024
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 85 |
1 files changed, 50 insertions, 35 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 39b532309d7..a6f3ee2c094 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -9598,7 +9598,6 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc, Expr *RHSStripped = RHS->IgnoreParenImpCasts(); QualType LHSType = LHS->getType(); - QualType RHSType = RHS->getType(); if (LHSType->hasFloatingRepresentation() || (LHSType->isBlockPointerType() && !BinaryOperator::isEqualityOp(Opc)) || LHS->getLocStart().isMacroID() || RHS->getLocStart().isMacroID() || @@ -9636,9 +9635,8 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc, S.PDiag(diag::warn_comparison_always) << 0 /*self-comparison*/ << !Result.empty() << Result); - } else if (DL && DR && LHSType->isArrayType() && RHSType->isArrayType() && - !DL->getType()->isReferenceType() && - !DR->getType()->isReferenceType() && + } else if (DL && DR && + DL->getType()->isArrayType() && DR->getType()->isArrayType() && !DL->isWeak() && !DR->isWeak()) { // What is it always going to evaluate to? StringRef Result; @@ -9689,10 +9687,53 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc, } } +static QualType checkArithmeticOrEnumeralCompare(Sema &S, ExprResult &LHS, + ExprResult &RHS, + SourceLocation Loc, + BinaryOperatorKind Opc) { + // C99 6.5.8p3 / C99 6.5.9p4 + QualType Type = S.UsualArithmeticConversions(LHS, RHS); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + if (Type.isNull()) + return S.InvalidOperands(Loc, LHS, RHS); + assert(Type->isArithmeticType() || Type->isEnumeralType()); + + checkEnumComparison(S, Loc, LHS.get(), RHS.get()); + + enum { StrongEquality, PartialOrdering, StrongOrdering } Ordering; + if (Type->isAnyComplexType()) + Ordering = StrongEquality; + else if (Type->isFloatingType()) + Ordering = PartialOrdering; + else + Ordering = StrongOrdering; + + if (Ordering == StrongEquality && BinaryOperator::isRelationalOp(Opc)) + return S.InvalidOperands(Loc, LHS, RHS); + + // Check for comparisons of floating point operands using != and ==. + if (Type->hasFloatingRepresentation() && BinaryOperator::isEqualityOp(Opc)) + S.CheckFloatComparison(Loc, LHS.get(), RHS.get()); + + // The result of comparisons is 'bool' in C++, 'int' in C. + // FIXME: For BO_Cmp, return the relevant comparison category type. + return S.Context.getLogicalOperationType(); +} + // C99 6.5.8, C++ [expr.rel] QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, BinaryOperatorKind Opc, bool IsRelational) { + // Comparisons expect an rvalue, so convert to rvalue before any + // type-related checks. + LHS = DefaultFunctionArrayLvalueConversion(LHS.get()); + if (LHS.isInvalid()) + return QualType(); + RHS = DefaultFunctionArrayLvalueConversion(RHS.get()); + if (RHS.isInvalid()) + return QualType(); + checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/true); // Handle vector comparisons separately. @@ -9700,36 +9741,17 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, RHS.get()->getType()->isVectorType()) return CheckVectorCompareOperands(LHS, RHS, Loc, Opc); - QualType LHSType = LHS.get()->getType(); - QualType RHSType = RHS.get()->getType(); - - checkEnumComparison(*this, Loc, LHS.get(), RHS.get()); diagnoseLogicalNotOnLHSofCheck(*this, LHS, RHS, Loc, Opc); diagnoseTautologicalComparison(*this, Loc, LHS.get(), RHS.get(), Opc); - // C99 6.5.8p3 / C99 6.5.9p4 - UsualArithmeticConversions(LHS, RHS); - if (LHS.isInvalid() || RHS.isInvalid()) - return QualType(); - - LHSType = LHS.get()->getType(); - RHSType = RHS.get()->getType(); + QualType LHSType = LHS.get()->getType(); + QualType RHSType = RHS.get()->getType(); + if ((LHSType->isArithmeticType() || LHSType->isEnumeralType()) && + (RHSType->isArithmeticType() || RHSType->isEnumeralType())) + return checkArithmeticOrEnumeralCompare(*this, LHS, RHS, Loc, Opc); - // The result of comparisons is 'bool' in C++, 'int' in C. QualType ResultTy = Context.getLogicalOperationType(); - if (IsRelational) { - if (LHSType->isRealType() && RHSType->isRealType()) - return ResultTy; - } else { - // Check for comparisons of floating point operands using != and ==. - if (LHSType->hasFloatingRepresentation()) - CheckFloatComparison(Loc, LHS.get(), RHS.get()); - - if (LHSType->isArithmeticType() && RHSType->isArithmeticType()) - return ResultTy; - } - const Expr::NullPointerConstantKind LHSNullKind = LHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull); const Expr::NullPointerConstantKind RHSNullKind = @@ -9903,13 +9925,6 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, else return ResultTy; } - - // Handle scoped enumeration types specifically, since they don't promote - // to integers. - if (LHS.get()->getType()->isEnumeralType() && - Context.hasSameUnqualifiedType(LHS.get()->getType(), - RHS.get()->getType())) - return ResultTy; } // Handle block pointer types. |

