Move the warning for different enum comparisons and the warning for using NULL as a non-pointer in a binary operation into separate functions.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138995 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Trieu 2011-09-02 03:48:46 +00:00
Родитель 7be1be0d5e
Коммит e648ac33e5
1 изменённых файлов: 88 добавлений и 61 удалений

Просмотреть файл

@ -6167,6 +6167,35 @@ static bool IsWithinTemplateSpecialization(Decl *D) {
return false;
}
/// If two different enums are compared, raise a warning.
static void checkEnumComparison(Sema &S, SourceLocation Loc, ExprResult &lex,
ExprResult &rex) {
QualType lType = lex.get()->getType();
QualType rType = rex.get()->getType();
QualType LHSStrippedType = lex.get()->IgnoreParenImpCasts()->getType();
QualType RHSStrippedType = rex.get()->IgnoreParenImpCasts()->getType();
const EnumType *LHSEnumType = LHSStrippedType->getAs<EnumType>();
if (!LHSEnumType)
return;
const EnumType *RHSEnumType = RHSStrippedType->getAs<EnumType>();
if (!RHSEnumType)
return;
// Ignore anonymous enums.
if (!LHSEnumType->getDecl()->getIdentifier())
return;
if (!RHSEnumType->getDecl()->getIdentifier())
return;
if (S.Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType))
return;
S.Diag(Loc, diag::warn_comparison_of_mixed_enum_types)
<< LHSStrippedType << RHSStrippedType
<< lex.get()->getSourceRange() << rex.get()->getSourceRange();
}
/// \brief Diagnose bad pointer comparisons.
static void diagnoseDistinctPointerComparison(Sema &S, SourceLocation Loc,
ExprResult &lex, ExprResult &rex,
@ -6254,20 +6283,7 @@ QualType Sema::CheckCompareOperands(ExprResult &lex, ExprResult &rex,
QualType LHSStrippedType = LHSStripped->getType();
QualType RHSStrippedType = RHSStripped->getType();
// Two different enums will raise a warning when compared.
if (const EnumType *LHSEnumType = LHSStrippedType->getAs<EnumType>()) {
if (const EnumType *RHSEnumType = RHSStrippedType->getAs<EnumType>()) {
if (LHSEnumType->getDecl()->getIdentifier() &&
RHSEnumType->getDecl()->getIdentifier() &&
!Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType)) {
Diag(Loc, diag::warn_comparison_of_mixed_enum_types)
<< LHSStrippedType << RHSStrippedType
<< lex.get()->getSourceRange() << rex.get()->getSourceRange();
}
}
}
checkEnumComparison(*this, Loc, lex, rex);
if (!lType->hasFloatingRepresentation() &&
!(lType->isBlockPointerType() && isRelational) &&
@ -7576,6 +7592,54 @@ static void DiagnoseSelfAssignment(Sema &S, Expr *lhs, Expr *rhs,
<< lhs->getSourceRange() << rhs->getSourceRange();
}
// checkArithmeticNull - Detect when a NULL constant is used improperly in an
// expression. These are mainly cases where the null pointer is used as an
// integer instead of a pointer.
static void checkArithmeticNull(Sema &S, ExprResult &lex, ExprResult &rex,
SourceLocation Loc, bool isCompare) {
// The canonical way to check for a GNU null is with isNullPointerConstant,
// but we use a bit of a hack here for speed; this is a relatively
// hot path, and isNullPointerConstant is slow.
bool LeftNull = isa<GNUNullExpr>(lex.get()->IgnoreParenImpCasts());
bool RightNull = isa<GNUNullExpr>(rex.get()->IgnoreParenImpCasts());
// Detect when a NULL constant is used improperly in an expression. These
// are mainly cases where the null pointer is used as an integer instead
// of a pointer.
if (!LeftNull && !RightNull)
return;
QualType LeftType = lex.get()->getType();
QualType RightType = rex.get()->getType();
// Avoid analyzing cases where the result will either be invalid (and
// diagnosed as such) or entirely valid and not something to warn about.
if (LeftType->isBlockPointerType() || LeftType->isMemberPointerType() ||
LeftType->isFunctionType() || RightType->isBlockPointerType() ||
RightType->isMemberPointerType() || RightType->isFunctionType())
return;
// Comparison operations would not make sense with a null pointer no matter
// what the other expression is.
if (!isCompare) {
S.Diag(Loc, diag::warn_null_in_arithmetic_operation)
<< (LeftNull ? lex.get()->getSourceRange() : SourceRange())
<< (RightNull ? rex.get()->getSourceRange() : SourceRange());
return;
}
// The rest of the operations only make sense with a null pointer
// if the other expression is a pointer.
if (LeftNull == RightNull || LeftType->isAnyPointerType() ||
LeftType->canDecayToPointerType() || RightType->isAnyPointerType() ||
RightType->canDecayToPointerType())
return;
S.Diag(Loc, diag::warn_null_in_comparison_operation)
<< LeftNull /* LHS is NULL */
<< (LeftNull ? rex.get()->getType() : lex.get()->getType())
<< lex.get()->getSourceRange() << rex.get()->getSourceRange();
}
/// CreateBuiltinBinOp - Creates a new built-in binary operation with
/// operator @p Opc at location @c TokLoc. This routine only supports
/// built-in operations; ActOnBinOp handles overloaded operators.
@ -7607,53 +7671,16 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
rhs = move(resolvedRHS);
}
// The canonical way to check for a GNU null is with isNullPointerConstant,
// but we use a bit of a hack here for speed; this is a relatively
// hot path, and isNullPointerConstant is slow.
bool LeftNull = isa<GNUNullExpr>(lhs.get()->IgnoreParenImpCasts());
bool RightNull = isa<GNUNullExpr>(rhs.get()->IgnoreParenImpCasts());
// Detect when a NULL constant is used improperly in an expression. These
// are mainly cases where the null pointer is used as an integer instead
// of a pointer.
if (LeftNull || RightNull) {
// Avoid analyzing cases where the result will either be invalid (and
// diagnosed as such) or entirely valid and not something to warn about.
QualType LeftType = lhs.get()->getType();
QualType RightType = rhs.get()->getType();
if (!LeftType->isBlockPointerType() && !LeftType->isMemberPointerType() &&
!LeftType->isFunctionType() &&
!RightType->isBlockPointerType() &&
!RightType->isMemberPointerType() &&
!RightType->isFunctionType()) {
if (Opc == BO_Mul || Opc == BO_Div || Opc == BO_Rem || Opc == BO_Add ||
Opc == BO_Sub || Opc == BO_Shl || Opc == BO_Shr || Opc == BO_And ||
Opc == BO_Xor || Opc == BO_Or || Opc == BO_MulAssign ||
Opc == BO_DivAssign || Opc == BO_AddAssign || Opc == BO_SubAssign ||
Opc == BO_RemAssign || Opc == BO_ShlAssign || Opc == BO_ShrAssign ||
Opc == BO_AndAssign || Opc == BO_OrAssign || Opc == BO_XorAssign) {
// These are the operations that would not make sense with a null pointer
// pointer no matter what the other expression is.
Diag(OpLoc, diag::warn_null_in_arithmetic_operation)
<< (LeftNull ? lhs.get()->getSourceRange() : SourceRange())
<< (RightNull ? rhs.get()->getSourceRange() : SourceRange());
} else if (Opc == BO_LE || Opc == BO_LT || Opc == BO_GE || Opc == BO_GT ||
Opc == BO_EQ || Opc == BO_NE) {
// These are the operations that would not make sense with a null pointer
// if the other expression the other expression is not a pointer.
if (LeftNull != RightNull &&
!LeftType->isAnyPointerType() &&
!LeftType->canDecayToPointerType() &&
!RightType->isAnyPointerType() &&
!RightType->canDecayToPointerType()) {
Diag(OpLoc, diag::warn_null_in_comparison_operation)
<< LeftNull /* LHS is NULL */
<< (LeftNull ? rhs.get()->getType() : lhs.get()->getType())
<< lhs.get()->getSourceRange() << rhs.get()->getSourceRange();
}
}
}
}
Opc == BO_AndAssign || Opc == BO_OrAssign || Opc == BO_XorAssign)
checkArithmeticNull(*this, lhs, rhs, OpLoc, /*isCompare=*/false);
else if (Opc == BO_LE || Opc == BO_LT || Opc == BO_GE || Opc == BO_GT ||
Opc == BO_EQ || Opc == BO_NE)
checkArithmeticNull(*this, lhs, rhs, OpLoc, /*isCompare=*/true);
switch (Opc) {
case BO_Assign: