summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2018-01-08 21:12:04 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2018-01-08 21:12:04 +0000
commita12bf9106a70841f96c7105ef663a1af5f45989a (patch)
treee4e47a31165b07b5d3d400eb9307d557102eb6d2 /clang/lib/Sema
parent215284d089dd0956f684daf10f245b1a31c14aed (diff)
downloadbcm5719-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')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp85
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.
OpenPOWER on IntegriCloud