From: Richard Trieu Date: Fri, 23 Sep 2011 20:10:00 +0000 (+0000) Subject: Add a new warning to -Wliteral-conversion to catch cases where a string literal X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f1f8b1a404d9ce6f0eb78e97b598a220d8ca9090;p=clang Add a new warning to -Wliteral-conversion to catch cases where a string literal is cast to a boolean. An exception has been made for string literals in logical expressions to allow the common case of use in assert statements. bool x; x = "hi"; // Warn here void foo(bool x); foo("hi"); // Warn here assert(0 && "error"); assert("error); // Warn here git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140405 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 57e4285d0e..b0f6c938f8 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1474,6 +1474,9 @@ def warn_impcast_literal_float_to_integer : Warning< "implicit conversion turns literal floating-point number into integer: " "%0 to %1">, InGroup>, DefaultIgnore; +def warn_impcast_string_literal_to_bool : Warning< + "implicit conversion turns string literal into bool: %0 to %1">, + InGroup>, DefaultIgnore; def note_fix_integral_float_as_integer : Note< "this can be rewritten as an integer literal with the exact same value">; def warn_impcast_different_enum_types : Warning< diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 052ef3bef2..5de43bb619 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -3237,9 +3237,17 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (CC.isInvalid()) return; - // Never diagnose implicit casts to bool. - if (Target->isSpecificBuiltinType(BuiltinType::Bool)) - return; + // Diagnose implicit casts to bool. + if (Target->isSpecificBuiltinType(BuiltinType::Bool)) { + if (isa(E)) + // Warn on string literal to bool. Checks for string literals in logical + // expressions, for instances, assert(0 && "error here"), is prevented + // by a check in AnalyzeImplicitConversions(). + return DiagnoseImpCast(S, E, T, CC, + diag::warn_impcast_string_literal_to_bool); + else // Other casts to bool are not checked. + return; + } // Strip vector types. if (isa(Source)) { @@ -3508,8 +3516,16 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { // Now just recurse over the expression's children. CC = E->getExprLoc(); - for (Stmt::child_range I = E->children(); I; ++I) - AnalyzeImplicitConversions(S, cast(*I), CC); + BinaryOperator *BO = dyn_cast(E); + bool IsLogicalOperator = BO && BO->isLogicalOp(); + for (Stmt::child_range I = E->children(); I; ++I) { + Expr *ChildExpr = cast(*I); + if (IsLogicalOperator && + isa(ChildExpr->IgnoreParenImpCasts())) + // Ignore checking string literals that are in logical operators. + continue; + AnalyzeImplicitConversions(S, ChildExpr, CC); + } } } // end anonymous namespace diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 3beb51c865..3fb8df6682 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -4643,7 +4643,7 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE) { if (FullExpr.isInvalid()) return ExprError(); - CheckImplicitConversions(FullExpr.get()); + CheckImplicitConversions(FullExpr.get(), FullExpr.get()->getExprLoc()); return MaybeCreateExprWithCleanups(FullExpr); } diff --git a/test/SemaCXX/warn-literal-conversion.cpp b/test/SemaCXX/warn-literal-conversion.cpp index 3fc8a6fec7..c225aa4bf0 100644 --- a/test/SemaCXX/warn-literal-conversion.cpp +++ b/test/SemaCXX/warn-literal-conversion.cpp @@ -43,3 +43,19 @@ void test0() { int y = (24*60*60) * 0.25; int pennies = 123.45 * 100; } + +// Warn on cases where a string literal is converted into a bool. +// An exception is made for this in logical operators. +void assert(bool condition); +void test1() { + bool b0 = "hi"; // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} + b0 = ""; // expected-warning{{implicit conversion turns string literal into bool: 'const char [1]' to 'bool'}} + b0 = 0 && ""; + assert("error"); // expected-warning{{implicit conversion turns string literal into bool: 'const char [6]' to 'bool'}} + assert(0 && "error"); + + while("hi") {} // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} + do {} while("hi"); // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} + for (;"hi";); // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} + if("hi") {} // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} +}