forked from OSchip/llvm-project
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
This commit is contained in:
parent
215284d089
commit
a12bf9106a
|
@ -10405,7 +10405,10 @@ private:
|
|||
const AttrVec *Attrs = nullptr,
|
||||
const FunctionDecl *FD = nullptr);
|
||||
|
||||
void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS);
|
||||
public:
|
||||
void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS);
|
||||
|
||||
private:
|
||||
void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
|
||||
void CheckBoolLikeConversion(Expr *E, SourceLocation CC);
|
||||
void CheckForIntOverflow(Expr *E);
|
||||
|
|
|
@ -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();
|
||||
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);
|
||||
|
||||
LHSType = LHS.get()->getType();
|
||||
RHSType = RHS.get()->getType();
|
||||
|
||||
// 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.
|
||||
|
|
|
@ -12,6 +12,6 @@ void test() {
|
|||
if (cp < fp) {} // expected-warning {{comparison of distinct pointer types ('char *' and 'struct foo *')}}
|
||||
if (fp < bp) {} // expected-warning {{comparison of distinct pointer types ('struct foo *' and 'struct bar *')}}
|
||||
if (ip < 7) {} // expected-warning {{comparison between pointer and integer ('int *' and 'int')}}
|
||||
if (sint < ip) {} // expected-warning {{comparison between pointer and integer ('int' and 'int *')}}
|
||||
if (sint < ip) {} // expected-warning {{comparison between pointer and integer ('short' and 'int *')}}
|
||||
if (ip == cp) {} // expected-warning {{comparison of distinct pointer types ('int *' and 'char *')}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue