Track overflow of shift amounts, allowing diagnostics like:

t.c:6:7: warning: integer overflow in preprocessor expression
#if 1 << 63
      ^
t.c:8:7: warning: integer overflow in preprocessor expression
#if 4 << 62
      ^
t.c:10:7: warning: integer overflow in preprocessor expression
#if 4 << 66
      ^

but no diagnostic on:
#if 1U << 63

llvm-svn: 39400
This commit is contained in:
Chris Lattner 2007-04-10 06:54:33 +00:00
parent a7fa1b247c
commit 5a0f164a52
2 changed files with 28 additions and 8 deletions

View File

@ -421,6 +421,7 @@ static bool EvaluateDirectiveSubExpr(APSInt &LHS, unsigned MinPrec,
}
// FIXME: All of these should detect and report overflow??
bool Overflow = false;
switch (Operator) {
default: assert(0 && "Unknown operator token!");
case tok::percent:
@ -440,16 +441,29 @@ static bool EvaluateDirectiveSubExpr(APSInt &LHS, unsigned MinPrec,
case tok::star:
LHS *= RHS;
break;
case tok::lessless:
// FIXME: shift amt overflow?
// FIXME: Don't use getZExtValue.
LHS <<= RHS.getZExtValue();
case tok::lessless: {
// Determine whether overflow is about to happen.
unsigned ShAmt = RHS.getLimitedValue();
if (ShAmt >= LHS.getBitWidth())
Overflow = true, ShAmt = LHS.getBitWidth()-1;
else if (LHS.isUnsigned())
Overflow = ShAmt > LHS.countLeadingZeros();
else if (LHS.isPositive())
Overflow = ShAmt >= LHS.countLeadingZeros(); // Don't allow sign change.
else
Overflow = ShAmt >= LHS.countLeadingOnes();
LHS <<= ShAmt;
break;
case tok::greatergreater:
// FIXME: signed vs unsigned
// FIXME: Don't use getZExtValue.
LHS >>= RHS.getZExtValue();
}
case tok::greatergreater: {
// Determine whether overflow is about to happen.
unsigned ShAmt = RHS.getLimitedValue();
if (ShAmt >= LHS.getBitWidth())
Overflow = true, ShAmt = LHS.getBitWidth()-1;
LHS >>= ShAmt;
break;
}
case tok::plus:
LHS += RHS;
break;
@ -532,6 +546,10 @@ static bool EvaluateDirectiveSubExpr(APSInt &LHS, unsigned MinPrec,
PP.Diag(OpToken, diag::err_pp_colon_without_question);
return true;
}
// If this operator is live and overflowed, report the issue.
if (Overflow && ValueLive)
PP.Diag(OpToken, diag::warn_pp_expr_overflow);
}
return false;

View File

@ -114,6 +114,8 @@ DIAG(pp_macro_not_used, WARNING, // -Wunused-macros
"macro is not used")
DIAG(pp_invalid_string_literal, WARNING,
"invalid string literal, ignoring final '\\'")
DIAG(warn_pp_expr_overflow, WARNING,
"integer overflow in preprocessor expression")
DIAG(ext_pp_import_directive, EXTENSION,
"#import is a language extension")