summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-01-12 23:18:54 +0000
committerDouglas Gregor <dgregor@apple.com>2010-01-12 23:18:54 +0000
commit49862b8285b62d7222bd91e57f7ea953751d4c93 (patch)
treeee84083b229af94ca44f6f6772550b01d50befe2
parent4b0e352061e10a50928154beccfc043ded9e6b84 (diff)
downloadbcm5719-llvm-49862b8285b62d7222bd91e57f7ea953751d4c93.tar.gz
bcm5719-llvm-49862b8285b62d7222bd91e57f7ea953751d4c93.zip
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. llvm-svn: 93266
-rw-r--r--clang/include/clang/Basic/PartialDiagnostic.h38
-rw-r--r--clang/lib/Sema/SemaExpr.cpp24
-rw-r--r--clang/test/Sema/exprs.c4
-rw-r--r--clang/test/Sema/self-comparison.c5
4 files changed, 59 insertions, 12 deletions
diff --git a/clang/include/clang/Basic/PartialDiagnostic.h b/clang/include/clang/Basic/PartialDiagnostic.h
index ae11a755cce..0d970123f74 100644
--- a/clang/include/clang/Basic/PartialDiagnostic.h
+++ b/clang/include/clang/Basic/PartialDiagnostic.h
@@ -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) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 26c2e176cf0..c71fd98aa04 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -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 ==.
diff --git a/clang/test/Sema/exprs.c b/clang/test/Sema/exprs.c
index 9059cac22e5..9acc63fa41a 100644
--- a/clang/test/Sema/exprs.c
+++ b/clang/test/Sema/exprs.c
@@ -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}}
diff --git a/clang/test/Sema/self-comparison.c b/clang/test/Sema/self-comparison.c
index b2b06c209a6..1baba2755f4 100644
--- a/clang/test/Sema/self-comparison.c
+++ b/clang/test/Sema/self-comparison.c
@@ -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
+}
OpenPOWER on IntegriCloud