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??
|
// FIXME: All of these should detect and report overflow??
|
||||||
|
bool Overflow = false;
|
||||||
switch (Operator) {
|
switch (Operator) {
|
||||||
default: assert(0 && "Unknown operator token!");
|
default: assert(0 && "Unknown operator token!");
|
||||||
case tok::percent:
|
case tok::percent:
|
||||||
|
@ -440,16 +441,29 @@ static bool EvaluateDirectiveSubExpr(APSInt &LHS, unsigned MinPrec,
|
||||||
case tok::star:
|
case tok::star:
|
||||||
LHS *= RHS;
|
LHS *= RHS;
|
||||||
break;
|
break;
|
||||||
case tok::lessless:
|
case tok::lessless: {
|
||||||
// FIXME: shift amt overflow?
|
// Determine whether overflow is about to happen.
|
||||||
// FIXME: Don't use getZExtValue.
|
unsigned ShAmt = RHS.getLimitedValue();
|
||||||
LHS <<= RHS.getZExtValue();
|
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;
|
break;
|
||||||
case tok::greatergreater:
|
}
|
||||||
// FIXME: signed vs unsigned
|
case tok::greatergreater: {
|
||||||
// FIXME: Don't use getZExtValue.
|
// Determine whether overflow is about to happen.
|
||||||
LHS >>= RHS.getZExtValue();
|
unsigned ShAmt = RHS.getLimitedValue();
|
||||||
|
if (ShAmt >= LHS.getBitWidth())
|
||||||
|
Overflow = true, ShAmt = LHS.getBitWidth()-1;
|
||||||
|
LHS >>= ShAmt;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case tok::plus:
|
case tok::plus:
|
||||||
LHS += RHS;
|
LHS += RHS;
|
||||||
break;
|
break;
|
||||||
|
@ -532,6 +546,10 @@ static bool EvaluateDirectiveSubExpr(APSInt &LHS, unsigned MinPrec,
|
||||||
PP.Diag(OpToken, diag::err_pp_colon_without_question);
|
PP.Diag(OpToken, diag::err_pp_colon_without_question);
|
||||||
return true;
|
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;
|
return false;
|
||||||
|
|
|
@ -114,6 +114,8 @@ DIAG(pp_macro_not_used, WARNING, // -Wunused-macros
|
||||||
"macro is not used")
|
"macro is not used")
|
||||||
DIAG(pp_invalid_string_literal, WARNING,
|
DIAG(pp_invalid_string_literal, WARNING,
|
||||||
"invalid string literal, ignoring final '\\'")
|
"invalid string literal, ignoring final '\\'")
|
||||||
|
DIAG(warn_pp_expr_overflow, WARNING,
|
||||||
|
"integer overflow in preprocessor expression")
|
||||||
|
|
||||||
DIAG(ext_pp_import_directive, EXTENSION,
|
DIAG(ext_pp_import_directive, EXTENSION,
|
||||||
"#import is a language extension")
|
"#import is a language extension")
|
||||||
|
|
Loading…
Reference in New Issue