Broaden -Wstring-conversion to catch string literals in logical or expressions.

Previously, string literals were ignored in all logical expressions.  This
reduces it to only ignore in logical and expressions.

assert(0 && "error"); // No warning
assert(0 || "error"); // Warn

Fixes PR17565

llvm-svn: 200056
This commit is contained in:
Richard Trieu 2014-01-25 01:10:35 +00:00
parent 6bd95b8aac
commit 955231ddf6
2 changed files with 13 additions and 6 deletions

View File

@ -5346,8 +5346,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
if (Target->isSpecificBuiltinType(BuiltinType::Bool)) { if (Target->isSpecificBuiltinType(BuiltinType::Bool)) {
if (isa<StringLiteral>(E)) if (isa<StringLiteral>(E))
// Warn on string literal to bool. Checks for string literals in logical // Warn on string literal to bool. Checks for string literals in logical
// expressions, for instances, assert(0 && "error here"), are prevented // and expressions, for instance, assert(0 && "error here"), are
// by a check in AnalyzeImplicitConversions(). // prevented by a check in AnalyzeImplicitConversions().
return DiagnoseImpCast(S, E, T, CC, return DiagnoseImpCast(S, E, T, CC,
diag::warn_impcast_string_literal_to_bool); diag::warn_impcast_string_literal_to_bool);
if (Source->isFunctionType()) { if (Source->isFunctionType()) {
@ -5698,15 +5698,16 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
// Now just recurse over the expression's children. // Now just recurse over the expression's children.
CC = E->getExprLoc(); CC = E->getExprLoc();
BinaryOperator *BO = dyn_cast<BinaryOperator>(E); BinaryOperator *BO = dyn_cast<BinaryOperator>(E);
bool IsLogicalOperator = BO && BO->isLogicalOp(); bool IsLogicalAndOperator = BO && BO->getOpcode() == BO_LAnd;
for (Stmt::child_range I = E->children(); I; ++I) { for (Stmt::child_range I = E->children(); I; ++I) {
Expr *ChildExpr = dyn_cast_or_null<Expr>(*I); Expr *ChildExpr = dyn_cast_or_null<Expr>(*I);
if (!ChildExpr) if (!ChildExpr)
continue; continue;
if (IsLogicalOperator && if (IsLogicalAndOperator &&
isa<StringLiteral>(ChildExpr->IgnoreParenImpCasts())) isa<StringLiteral>(ChildExpr->IgnoreParenImpCasts()))
// Ignore checking string literals that are in logical operators. // Ignore checking string literals that are in logical and operators.
// This is a common pattern for asserts.
continue; continue;
AnalyzeImplicitConversions(S, ChildExpr, CC); AnalyzeImplicitConversions(S, ChildExpr, CC);
} }

View File

@ -1,14 +1,20 @@
// RUN: %clang_cc1 -fsyntax-only -Wstring-conversion -verify %s // RUN: %clang_cc1 -fsyntax-only -Wstring-conversion -verify %s
// Warn on cases where a string literal is converted into a bool. // Warn on cases where a string literal is converted into a bool.
// An exception is made for this in logical operators. // An exception is made for this in logical and operators.
void assert(bool condition); void assert(bool condition);
void test0() { void test0() {
bool b0 = "hi"; // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} 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 = ""; // expected-warning{{implicit conversion turns string literal into bool: 'const char [1]' to 'bool'}}
b0 = 0 || ""; // expected-warning{{implicit conversion turns string literal into bool: 'const char [1]' to 'bool'}}
b0 = "" || 0; // expected-warning{{implicit conversion turns string literal into bool: 'const char [1]' to 'bool'}}
b0 = 0 && ""; b0 = 0 && "";
b0 = "" && 0;
assert("error"); // expected-warning{{implicit conversion turns string literal into bool: 'const char [6]' to 'bool'}} assert("error"); // expected-warning{{implicit conversion turns string literal into bool: 'const char [6]' to 'bool'}}
assert(0 || "error"); // expected-warning{{implicit conversion turns string literal into bool: 'const char [6]' to 'bool'}}
assert("error" || 0); // expected-warning{{implicit conversion turns string literal into bool: 'const char [6]' to 'bool'}}
assert(0 && "error"); assert(0 && "error");
assert("error" && 0);
while("hi") {} // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} 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'}} do {} while("hi"); // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}}