]> granicus.if.org Git - clang/commitdiff
Don't emit string-comparison or self-comparison warnings in
authorDouglas Gregor <dgregor@apple.com>
Tue, 12 Jan 2010 23:18:54 +0000 (23:18 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 12 Jan 2010 23:18:54 +0000 (23:18 +0000)
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

include/clang/Basic/PartialDiagnostic.h
lib/Sema/SemaExpr.cpp
test/Sema/exprs.c
test/Sema/self-comparison.c

index ae11a755cce4dc3ae2de8468d0092f241aa5550f..0d970123f745842a3dcc1940a523496b77fb6590 100644 (file)
@@ -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) {
index 26c2e176cf01de2684a4e672ab7c1de8f0eaaf8a..c71fd98aa04074955a4539f3193d4fbfdaae45ff 100644 (file)
@@ -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 ==.
index 9059cac22e508111e10a1d937798a331599b2be2..9acc63fa41a5e5725597b91dd2022630031bb73b 100644 (file)
@@ -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}}
index b2b06c209a61341a697b11e8de46398e6e632252..1baba2755f43f902d8cf174208f6f6db17fb5de0 100644 (file)
@@ -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
+}