From: Chris Lattner Date: Sun, 8 Mar 2009 19:39:53 +0000 (+0000) Subject: implement PR3753, warning about comparisons with a string literal. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=55660a74897bf42111a8ae61c1f617645e5a9274;p=clang implement PR3753, warning about comparisons with a string literal. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66387 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def index eda47d6dbb..d5d6175b0c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.def +++ b/include/clang/Basic/DiagnosticSemaKinds.def @@ -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 diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 6c4176720a..4fb03b3d6b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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(lex->IgnoreParens())) - if (DeclRefExpr* DRR = dyn_cast(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(LHSStripped)) + if (DeclRefExpr* DRR = dyn_cast(RHSStripped)) if (DRL->getDecl() == DRR->getDecl()) Diag(Loc, diag::warn_selfcomparison); + + if (isa(LHSStripped)) + LHSStripped = LHSStripped->IgnoreParenCasts(); + if (isa(RHSStripped)) + RHSStripped = RHSStripped->IgnoreParenCasts(); + + // Warn about comparisons against a string constant (unless the other + // operand is null), the user probably wants strcmp. + if ((isa(LHSStripped) || isa(LHSStripped)) && + !RHSStripped->isNullPointerConstant(Context)) + Diag(Loc, diag::warn_stringcompare) << lex->getSourceRange(); + else if ((isa(RHSStripped) || + isa(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); } diff --git a/test/Sema/exprs.c b/test/Sema/exprs.c index 45e146286a..e307eb7758 100644 --- a/test/Sema/exprs.c +++ b/test/Sema/exprs.c @@ -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}} +} +