forked from OSchip/llvm-project
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:
parent
a7fa1b247c
commit
5a0f164a52
|
@ -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;
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue