Don't emit string-comparison or self-comparison warnings in

unevaluated contexts, because they only matter for code that will
actually be evaluated at runtime.

As part of this, I had to extend PartialDiagnostic to support fix-it
hints.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93266 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2010-01-12 23:18:54 +00:00
Родитель 58002f9683
Коммит d1e4d9bfd5
4 изменённых файлов: 59 добавлений и 12 удалений

Просмотреть файл

@ -26,7 +26,8 @@ class DeclarationName;
class PartialDiagnostic {
struct Storage {
Storage() : NumDiagArgs(0), NumDiagRanges(0) { }
Storage() : NumDiagArgs(0), NumDiagRanges(0), NumCodeModificationHints(0) {
}
enum {
/// MaxArguments - The maximum number of arguments we can hold. We
@ -42,6 +43,10 @@ class PartialDiagnostic {
/// NumDiagRanges - This is the number of ranges in the DiagRanges array.
unsigned char NumDiagRanges;
/// \brief The number of code modifications hints in the
/// CodeModificationHints array.
unsigned char NumCodeModificationHints;
/// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
/// values, with one for each argument. This specifies whether the argument
/// is in DiagArgumentsStr or in DiagArguments.
@ -56,6 +61,12 @@ class PartialDiagnostic {
/// DiagRanges - The list of ranges added to this diagnostic. It currently
/// only support 10 ranges, could easily be extended if needed.
SourceRange DiagRanges[10];
enum { MaxCodeModificationHints = 3 };
/// CodeModificationHints - If valid, provides a hint with some code
/// to insert, remove, or modify at a particular position.
CodeModificationHint CodeModificationHints[MaxCodeModificationHints];
};
/// DiagID - The diagnostic ID.
@ -84,6 +95,20 @@ class PartialDiagnostic {
DiagStorage->DiagRanges[DiagStorage->NumDiagRanges++] = R;
}
void AddCodeModificationHint(const CodeModificationHint &Hint) const {
if (Hint.isNull())
return;
if (!DiagStorage)
DiagStorage = new Storage;
assert(DiagStorage->NumCodeModificationHints <
Storage::MaxCodeModificationHints &&
"Too many code modification hints!");
DiagStorage->CodeModificationHints[DiagStorage->NumCodeModificationHints++]
= Hint;
}
public:
PartialDiagnostic(unsigned DiagID)
: DiagID(DiagID), DiagStorage(0) { }
@ -130,6 +155,10 @@ public:
// Add all ranges.
for (unsigned i = 0, e = DiagStorage->NumDiagRanges; i != e; ++i)
DB.AddSourceRange(DiagStorage->DiagRanges[i]);
// Add all code modification hints
for (unsigned i = 0, e = DiagStorage->NumCodeModificationHints; i != e; ++i)
DB.AddCodeModificationHint(DiagStorage->CodeModificationHints[i]);
}
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
@ -165,6 +194,13 @@ public:
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
DeclarationName N);
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
const CodeModificationHint &Hint) {
PD.AddCodeModificationHint(Hint);
return PD;
}
};
inline PartialDiagnostic PDiag(unsigned DiagID = 0) {

Просмотреть файл

@ -5196,7 +5196,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped))
if (DRL->getDecl() == DRR->getDecl() &&
!isa<EnumConstantDecl>(DRL->getDecl()))
Diag(Loc, diag::warn_selfcomparison);
DiagRuntimeBehavior(Loc, PDiag(diag::warn_selfcomparison));
if (isa<CastExpr>(LHSStripped))
LHSStripped = LHSStripped->IgnoreParenCasts();
@ -5231,15 +5231,17 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
case BinaryOperator::NE: resultComparison = ") != 0"; break;
default: assert(false && "Invalid comparison operator");
}
Diag(Loc, diag::warn_stringcompare)
<< isa<ObjCEncodeExpr>(literalStringStripped)
<< literalString->getSourceRange()
<< CodeModificationHint::CreateReplacement(SourceRange(Loc), ", ")
<< CodeModificationHint::CreateInsertion(lex->getLocStart(),
"strcmp(")
<< CodeModificationHint::CreateInsertion(
PP.getLocForEndOfToken(rex->getLocEnd()),
resultComparison);
DiagRuntimeBehavior(Loc,
PDiag(diag::warn_stringcompare)
<< isa<ObjCEncodeExpr>(literalStringStripped)
<< literalString->getSourceRange()
<< CodeModificationHint::CreateReplacement(SourceRange(Loc), ", ")
<< CodeModificationHint::CreateInsertion(lex->getLocStart(),
"strcmp(")
<< CodeModificationHint::CreateInsertion(
PP.getLocForEndOfToken(rex->getLocEnd()),
resultComparison));
}
}
@ -5503,7 +5505,7 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens()))
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens()))
if (DRL->getDecl() == DRR->getDecl())
Diag(Loc, diag::warn_selfcomparison);
DiagRuntimeBehavior(Loc, PDiag(diag::warn_selfcomparison));
}
// Check for comparisons of floating point operands using != and ==.

Просмотреть файл

@ -87,6 +87,10 @@ int test12(const char *X) {
return X == "foo"; // expected-warning {{comparison against a string literal is unspecified}}
}
int test12b(const char *X) {
return sizeof(X == "foo"); // no-warning
}
// rdar://6719156
void test13(
void (^P)()) { // expected-error {{blocks support disabled - compile with -fblocks}}

Просмотреть файл

@ -31,3 +31,8 @@ int compare_enum() {
enum { A };
return A == A; // no-warning
}
// Don't complain in unevaluated contexts.
int compare_sizeof(int x) {
return sizeof(x == x); // no-warning
}