]> granicus.if.org Git - clang/commitdiff
implement PR3753, warning about comparisons with a string literal.
authorChris Lattner <sabre@nondot.org>
Sun, 8 Mar 2009 19:39:53 +0000 (19:39 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 8 Mar 2009 19:39:53 +0000 (19:39 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66387 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.def
lib/Sema/SemaExpr.cpp
test/Sema/exprs.c

index eda47d6dbb7645cb03ab61eca60563fc422d773b..d5d6175b0cc9aa73153411ab041bdffbdac17ffe 100644 (file)
@@ -1344,10 +1344,12 @@ DIAG(warn_ret_stack_ref, WARNING,
   "reference to stack memory associated with local variable %0 returned")
 
 
-// CHECK: for non-floating point, expressions of the form x == x or x != x
+// for non-floating point, expressions of the form x == x or x != x
 // should result in a warning, since these always evaluate to a constant.
-DIAG(warn_selfcomparison,WARNING,
-     "self-comparison always results in a constant value.")
+DIAG(warn_selfcomparison, WARNING,
+     "self-comparison always results in a constant value")
+DIAG(warn_stringcompare, WARNING,
+     "comparison against a string literal is undefined (use strcmp?)")
 
 
 // Blocks
index 6c4176720af9955cd304cb6cc625984f594a61f0..4fb03b3d6bc575449277996176bb2d10d6aa56be 100644 (file)
@@ -3155,18 +3155,35 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
   QualType lType = lex->getType();
   QualType rType = rex->getType();
 
-  // For non-floating point types, check for self-comparisons of the form
-  // x == x, x != x, x < x, etc.  These always evaluate to a constant, and
-  // often indicate logic errors in the program.
   if (!lType->isFloatingType()) {
-    if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens()))
-      if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens()))
+    // For non-floating point types, check for self-comparisons of the form
+    // x == x, x != x, x < x, etc.  These always evaluate to a constant, and
+    // often indicate logic errors in the program.
+    Expr *LHSStripped = lex->IgnoreParens();
+    Expr *RHSStripped = rex->IgnoreParens();
+    if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped))
+      if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped))
         if (DRL->getDecl() == DRR->getDecl())
           Diag(Loc, diag::warn_selfcomparison);
+    
+    if (isa<CastExpr>(LHSStripped))
+      LHSStripped = LHSStripped->IgnoreParenCasts();
+    if (isa<CastExpr>(RHSStripped))
+      RHSStripped = RHSStripped->IgnoreParenCasts();
+    
+    // Warn about comparisons against a string constant (unless the other
+    // operand is null), the user probably wants strcmp.
+    if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) &&
+        !RHSStripped->isNullPointerConstant(Context))
+      Diag(Loc, diag::warn_stringcompare) << lex->getSourceRange();
+    else if ((isa<StringLiteral>(RHSStripped) ||
+              isa<ObjCEncodeExpr>(RHSStripped)) &&
+             !LHSStripped->isNullPointerConstant(Context))
+      Diag(Loc, diag::warn_stringcompare) << rex->getSourceRange();
   }
 
   // The result of comparisons is 'bool' in C++, 'int' in C.
-  QualType ResultTy = getLangOptions().CPlusPlus? Context.BoolTy : Context.IntTy;
+  QualType ResultTy = getLangOptions().CPlusPlus? Context.BoolTy :Context.IntTy;
 
   if (isRelational) {
     if (lType->isRealType() && rType->isRealType())
@@ -3174,7 +3191,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
   } else {
     // Check for comparisons of floating point operands using != and ==.
     if (lType->isFloatingType()) {
-      assert (rType->isFloatingType());
+      assert(rType->isFloatingType());
       CheckFloatComparison(Loc,lex,rex);
     }
 
index 45e146286a3451c30fd2e86de389ef3ccecc6c92..e307eb775848b82f39d2b71acffef6ae64ed0dc5 100644 (file)
@@ -72,7 +72,12 @@ void test10(int n,...) {
 #define MYMAX(A,B)    __extension__ ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; })
 
 struct mystruct {int A; };
-void foo(struct mystruct P, float F) {
+void test11(struct mystruct P, float F) {
   MYMAX(P, F);  // expected-error {{invalid operands to binary expression ('typeof(P)' (aka 'struct mystruct') and 'typeof(F)' (aka 'float'))}}
 }
 
+// PR3753
+int test12(const char *X) {
+  return X == "foo";  // expected-warning {{comparison against a string literal is undefined}}
+}
+