summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r--lib/Sema/SemaChecking.cpp58
1 files changed, 47 insertions, 11 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 30a6ab4..3fac79d 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -59,9 +59,12 @@ SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL,
// Re-lex the token to get its length and original spelling.
std::pair<FileID, unsigned> LocInfo =
SourceMgr.getDecomposedLoc(StrTokSpellingLoc);
- std::pair<const char *,const char *> Buffer =
- SourceMgr.getBufferData(LocInfo.first);
- const char *StrData = Buffer.first+LocInfo.second;
+ bool Invalid = false;
+ llvm::StringRef Buffer = SourceMgr.getBufferData(LocInfo.first, &Invalid);
+ if (Invalid)
+ return StrTokSpellingLoc;
+
+ const char *StrData = Buffer.data()+LocInfo.second;
// Create a langops struct and enable trigraphs. This is sufficient for
// relexing tokens.
@@ -69,8 +72,8 @@ SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL,
LangOpts.Trigraphs = true;
// Create a lexer starting at the beginning of this token.
- Lexer TheLexer(StrTokSpellingLoc, LangOpts, Buffer.first, StrData,
- Buffer.second);
+ Lexer TheLexer(StrTokSpellingLoc, LangOpts, Buffer.begin(), StrData,
+ Buffer.end());
Token TheTok;
TheLexer.LexFromRawLexer(TheTok);
@@ -2011,10 +2014,9 @@ bool IsSameFloatAfterCast(const APValue &value,
/// \param lex the left-hand expression
/// \param rex the right-hand expression
/// \param OpLoc the location of the joining operator
-/// \param Equality whether this is an "equality-like" join, which
-/// suppresses the warning in some cases
+/// \param BinOpc binary opcode or 0
void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
- const PartialDiagnostic &PD, bool Equality) {
+ const BinaryOperator::Opcode* BinOpc) {
// Don't warn if we're in an unevaluated context.
if (ExprEvalContexts.back().Context == Unevaluated)
return;
@@ -2075,17 +2077,51 @@ void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
// If the signed operand is non-negative, then the signed->unsigned
// conversion won't change it.
- if (signedRange.NonNegative)
+ if (signedRange.NonNegative) {
+ // Emit warnings for comparisons of unsigned to integer constant 0.
+ // always false: x < 0 (or 0 > x)
+ // always true: x >= 0 (or 0 <= x)
+ llvm::APSInt X;
+ if (BinOpc && signedOperand->isIntegerConstantExpr(X, Context) && X == 0) {
+ if (signedOperand != lex) {
+ if (*BinOpc == BinaryOperator::LT) {
+ Diag(OpLoc, diag::warn_lunsigned_always_true_comparison)
+ << "< 0" << "false"
+ << lex->getSourceRange() << rex->getSourceRange();
+ }
+ else if (*BinOpc == BinaryOperator::GE) {
+ Diag(OpLoc, diag::warn_lunsigned_always_true_comparison)
+ << ">= 0" << "true"
+ << lex->getSourceRange() << rex->getSourceRange();
+ }
+ }
+ else {
+ if (*BinOpc == BinaryOperator::GT) {
+ Diag(OpLoc, diag::warn_runsigned_always_true_comparison)
+ << "0 >" << "false"
+ << lex->getSourceRange() << rex->getSourceRange();
+ }
+ else if (*BinOpc == BinaryOperator::LE) {
+ Diag(OpLoc, diag::warn_runsigned_always_true_comparison)
+ << "0 <=" << "true"
+ << lex->getSourceRange() << rex->getSourceRange();
+ }
+ }
+ }
return;
+ }
// For (in)equality comparisons, if the unsigned operand is a
// constant which cannot collide with a overflowed signed operand,
// then reinterpreting the signed operand as unsigned will not
// change the result of the comparison.
- if (Equality && unsignedRange.Width < unsignedWidth)
+ if (BinOpc &&
+ (*BinOpc == BinaryOperator::EQ || *BinOpc == BinaryOperator::NE) &&
+ unsignedRange.Width < unsignedWidth)
return;
- Diag(OpLoc, PD)
+ Diag(OpLoc, BinOpc ? diag::warn_mixed_sign_comparison
+ : diag::warn_mixed_sign_conditional)
<< lt << rt << lex->getSourceRange() << rex->getSourceRange();
}
OpenPOWER on IntegriCloud