Replace magic numbers in CheckICE with an enum.

llvm-svn: 171192
This commit is contained in:
Richard Smith 2012-12-28 13:25:52 +00:00
parent 74fc72143a
commit 9e575dafad
1 changed files with 66 additions and 70 deletions

View File

@ -6375,54 +6375,55 @@ APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const {
/// FIXME: Pass up a reason why! Invalid operation in i-c-e, division by zero,
/// comma, etc
///
/// FIXME: Handle offsetof. Two things to do: Handle GCC's __builtin_offsetof
/// to support gcc 4.0+ and handle the idiom GCC recognizes with a null pointer
/// cast+dereference.
// CheckICE - This function does the fundamental ICE checking: the returned
// ICEDiag contains a Val of 0, 1, or 2, and a possibly null SourceLocation.
// ICEDiag contains an ICEKind indicating whether the expression is an ICE,
// and a (possibly null) SourceLocation indicating the location of the problem.
//
// Note that to reduce code duplication, this helper does no evaluation
// itself; the caller checks whether the expression is evaluatable, and
// in the rare cases where CheckICE actually cares about the evaluated
// value, it calls into Evalute.
//
// Meanings of Val:
// 0: This expression is an ICE.
// 1: This expression is not an ICE, but if it isn't evaluated, it's
// a legal subexpression for an ICE. This return value is used to handle
// the comma operator in C99 mode.
// 2: This expression is not an ICE, and is not a legal subexpression for one.
namespace {
enum ICEKind {
/// This expression is an ICE.
IK_ICE,
/// This expression is not an ICE, but if it isn't evaluated, it's
/// a legal subexpression for an ICE. This return value is used to handle
/// the comma operator in C99 mode, and non-constant subexpressions.
IK_ICEIfUnevaluated,
/// This expression is not an ICE, and is not a legal subexpression for one.
IK_NotICE
};
struct ICEDiag {
unsigned Val;
ICEKind Kind;
SourceLocation Loc;
public:
ICEDiag(unsigned v, SourceLocation l) : Val(v), Loc(l) {}
ICEDiag() : Val(0) {}
ICEDiag(ICEKind IK, SourceLocation l) : Kind(IK), Loc(l) {}
};
}
static ICEDiag NoDiag() { return ICEDiag(); }
static ICEDiag NoDiag() { return ICEDiag(IK_ICE, SourceLocation()); }
static ICEDiag Worst(ICEDiag A, ICEDiag B) { return A.Kind >= B.Kind ? A : B; }
static ICEDiag CheckEvalInICE(const Expr* E, ASTContext &Ctx) {
Expr::EvalResult EVResult;
if (!E->EvaluateAsRValue(EVResult, Ctx) || EVResult.HasSideEffects ||
!EVResult.Val.isInt()) {
return ICEDiag(2, E->getLocStart());
}
!EVResult.Val.isInt())
return ICEDiag(IK_NotICE, E->getLocStart());
return NoDiag();
}
static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
assert(!E->isValueDependent() && "Should not see value dependent exprs!");
if (!E->getType()->isIntegralOrEnumerationType()) {
return ICEDiag(2, E->getLocStart());
}
if (!E->getType()->isIntegralOrEnumerationType())
return ICEDiag(IK_NotICE, E->getLocStart());
switch (E->getStmtClass()) {
#define ABSTRACT_STMT(Node)
@ -6491,7 +6492,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::AtomicExprClass:
case Expr::InitListExprClass:
case Expr::LambdaExprClass:
return ICEDiag(2, E->getLocStart());
return ICEDiag(IK_NotICE, E->getLocStart());
case Expr::SizeOfPackExprClass:
case Expr::GNUNullExprClass:
@ -6526,7 +6527,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
const CallExpr *CE = cast<CallExpr>(E);
if (CE->isBuiltinCall())
return CheckEvalInICE(E, Ctx);
return ICEDiag(2, E->getLocStart());
return ICEDiag(IK_NotICE, E->getLocStart());
}
case Expr::DeclRefExprClass: {
if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl()))
@ -6538,14 +6539,14 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
// getAnyInitializer() can find a default argument, which leads
// to chaos.
if (isa<ParmVarDecl>(D))
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation());
// C++ 7.1.5.1p2
// A variable of non-volatile const-qualified integral or enumeration
// type initialized by an ICE can be used in ICEs.
if (const VarDecl *Dcl = dyn_cast<VarDecl>(D)) {
if (!Dcl->getType()->isIntegralOrEnumerationType())
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation());
const VarDecl *VD;
// Look for a declaration of this variable that has an initializer, and
@ -6553,10 +6554,10 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
if (Dcl->getAnyInitializer(VD) && VD->checkInitIsICE())
return NoDiag();
else
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation());
}
}
return ICEDiag(2, E->getLocStart());
return ICEDiag(IK_NotICE, E->getLocStart());
}
case Expr::UnaryOperatorClass: {
const UnaryOperator *Exp = cast<UnaryOperator>(E);
@ -6570,7 +6571,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
// C99 6.6/3 allows increment and decrement within unevaluated
// subexpressions of constant expressions, but they can never be ICEs
// because an ICE cannot contain an lvalue operand.
return ICEDiag(2, E->getLocStart());
return ICEDiag(IK_NotICE, E->getLocStart());
case UO_Extension:
case UO_LNot:
case UO_Plus:
@ -6580,23 +6581,23 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case UO_Imag:
return CheckICE(Exp->getSubExpr(), Ctx);
}
// OffsetOf falls through here.
}
case Expr::OffsetOfExprClass: {
// Note that per C99, offsetof must be an ICE. And AFAIK, using
// EvaluateAsRValue matches the proposed gcc behavior for cases like
// "offsetof(struct s{int x[4];}, x[1.0])". This doesn't affect
// compliance: we should warn earlier for offsetof expressions with
// array subscripts that aren't ICEs, and if the array subscripts
// are ICEs, the value of the offsetof must be an integer constant.
return CheckEvalInICE(E, Ctx);
// Note that per C99, offsetof must be an ICE. And AFAIK, using
// EvaluateAsRValue matches the proposed gcc behavior for cases like
// "offsetof(struct s{int x[4];}, x[1.0])". This doesn't affect
// compliance: we should warn earlier for offsetof expressions with
// array subscripts that aren't ICEs, and if the array subscripts
// are ICEs, the value of the offsetof must be an integer constant.
return CheckEvalInICE(E, Ctx);
}
case Expr::UnaryExprOrTypeTraitExprClass: {
const UnaryExprOrTypeTraitExpr *Exp = cast<UnaryExprOrTypeTraitExpr>(E);
if ((Exp->getKind() == UETT_SizeOf) &&
Exp->getTypeOfArgument()->isVariableArrayType())
return ICEDiag(2, E->getLocStart());
return ICEDiag(IK_NotICE, E->getLocStart());
return NoDiag();
}
case Expr::BinaryOperatorClass: {
@ -6618,7 +6619,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
// C99 6.6/3 allows assignments within unevaluated subexpressions of
// constant expressions, but they can never be ICEs because an ICE cannot
// contain an lvalue operand.
return ICEDiag(2, E->getLocStart());
return ICEDiag(IK_NotICE, E->getLocStart());
case BO_Mul:
case BO_Div:
@ -6643,14 +6644,14 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
Exp->getOpcode() == BO_Rem) {
// EvaluateAsRValue gives an error for undefined Div/Rem, so make sure
// we don't evaluate one.
if (LHSResult.Val == 0 && RHSResult.Val == 0) {
if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) {
llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx);
if (REval == 0)
return ICEDiag(1, E->getLocStart());
return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart());
if (REval.isSigned() && REval.isAllOnesValue()) {
llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx);
if (LEval.isMinSignedValue())
return ICEDiag(1, E->getLocStart());
return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart());
}
}
}
@ -6658,22 +6659,20 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
if (Ctx.getLangOpts().C99) {
// C99 6.6p3 introduces a strange edge case: comma can be in an ICE
// if it isn't evaluated.
if (LHSResult.Val == 0 && RHSResult.Val == 0)
return ICEDiag(1, E->getLocStart());
if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE)
return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart());
} else {
// In both C89 and C++, commas in ICEs are illegal.
return ICEDiag(2, E->getLocStart());
return ICEDiag(IK_NotICE, E->getLocStart());
}
}
if (LHSResult.Val >= RHSResult.Val)
return LHSResult;
return RHSResult;
return Worst(LHSResult, RHSResult);
}
case BO_LAnd:
case BO_LOr: {
ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
if (LHSResult.Val == 0 && RHSResult.Val == 1) {
if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICEIfUnevaluated) {
// Rare case where the RHS has a comma "side-effect"; we need
// to actually check the condition to see whether the side
// with the comma is evaluated.
@ -6683,9 +6682,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
return NoDiag();
}
if (LHSResult.Val >= RHSResult.Val)
return LHSResult;
return RHSResult;
return Worst(LHSResult, RHSResult);
}
}
}
@ -6710,7 +6707,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
if (FL->getValue().convertToInteger(IgnoredVal,
llvm::APFloat::rmTowardZero,
&Ignored) & APFloat::opInvalidOp)
return ICEDiag(2, E->getLocStart());
return ICEDiag(IK_NotICE, E->getLocStart());
return NoDiag();
}
}
@ -6723,17 +6720,17 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case CK_IntegralCast:
return CheckICE(SubExpr, Ctx);
default:
return ICEDiag(2, E->getLocStart());
return ICEDiag(IK_NotICE, E->getLocStart());
}
}
case Expr::BinaryConditionalOperatorClass: {
const BinaryConditionalOperator *Exp = cast<BinaryConditionalOperator>(E);
ICEDiag CommonResult = CheckICE(Exp->getCommon(), Ctx);
if (CommonResult.Val == 2) return CommonResult;
if (CommonResult.Kind == IK_NotICE) return CommonResult;
ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx);
if (FalseResult.Val == 2) return FalseResult;
if (CommonResult.Val == 1) return CommonResult;
if (FalseResult.Val == 1 &&
if (FalseResult.Kind == IK_NotICE) return FalseResult;
if (CommonResult.Kind == IK_ICEIfUnevaluated) return CommonResult;
if (FalseResult.Kind == IK_ICEIfUnevaluated &&
Exp->getCommon()->EvaluateKnownConstInt(Ctx) != 0) return NoDiag();
return FalseResult;
}
@ -6748,26 +6745,25 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p)
return CheckEvalInICE(E, Ctx);
ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx);
if (CondResult.Val == 2)
if (CondResult.Kind == IK_NotICE)
return CondResult;
ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx);
ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx);
if (TrueResult.Val == 2)
if (TrueResult.Kind == IK_NotICE)
return TrueResult;
if (FalseResult.Val == 2)
if (FalseResult.Kind == IK_NotICE)
return FalseResult;
if (CondResult.Val == 1)
if (CondResult.Kind == IK_ICEIfUnevaluated)
return CondResult;
if (TrueResult.Val == 0 && FalseResult.Val == 0)
if (TrueResult.Kind == IK_ICE && FalseResult.Kind == IK_ICE)
return NoDiag();
// Rare case where the diagnostics depend on which side is evaluated
// Note that if we get here, CondResult is 0, and at least one of
// TrueResult and FalseResult is non-zero.
if (Exp->getCond()->EvaluateKnownConstInt(Ctx) == 0) {
if (Exp->getCond()->EvaluateKnownConstInt(Ctx) == 0)
return FalseResult;
}
return TrueResult;
}
case Expr::CXXDefaultArgExprClass:
@ -6803,9 +6799,9 @@ bool Expr::isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
if (Ctx.getLangOpts().CPlusPlus0x)
return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, 0, Loc);
ICEDiag d = CheckICE(this, Ctx);
if (d.Val != 0) {
if (Loc) *Loc = d.Loc;
ICEDiag D = CheckICE(this, Ctx);
if (D.Kind != IK_ICE) {
if (Loc) *Loc = D.Loc;
return false;
}
return true;
@ -6824,7 +6820,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, ASTContext &Ctx,
}
bool Expr::isCXX98IntegralConstantExpr(ASTContext &Ctx) const {
return CheckICE(this, Ctx).Val == 0;
return CheckICE(this, Ctx).Kind == IK_ICE;
}
bool Expr::isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result,