зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
58002f9683
Коммит
d1e4d9bfd5
|
@ -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
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче