From: David Blaikie Date: Tue, 15 May 2012 16:56:36 +0000 (+0000) Subject: Improve some of the conversion warnings to fire on conversion to bool. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=be0ee875d8a91c031a085cbbd73ad9e8dc1aa8ff;p=clang Improve some of the conversion warnings to fire on conversion to bool. Moves the bool bail-out down a little in SemaChecking - so now -Wnull-conversion and -Wliteral-conversion can fire when the target type is bool. Also improve the wording/details in the -Wliteral-conversion warning to match the -Wconstant-conversion. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156826 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 2a34b53e4d..cd2bd27812 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1781,8 +1781,7 @@ def warn_impcast_bitfield_precision_constant : Warning< "implicit truncation from %2 to bitfield changes value from %0 to %1">, InGroup; def warn_impcast_literal_float_to_integer : Warning< - "implicit conversion turns literal floating-point number into integer: " - "%0 to %1">, + "implicit conversion from %0 to %1 changes value from %2 to %3">, InGroup; def warn_impcast_string_literal_to_bool : Warning< "implicit conversion turns string literal into bool: %0 to %1">, diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index eddb612fc6..9c637b89dd 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -22,6 +22,7 @@ #include "clang/AST/CharUnits.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/EvaluatedExprVisitor.h" @@ -4081,8 +4082,17 @@ void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T, == llvm::APFloat::opOK && isExact) return; + SmallString<16> PrettySourceValue; + Value.toString(PrettySourceValue); + std::string PrettyTargetValue; + if (T->isSpecificBuiltinType(BuiltinType::Bool)) + PrettyTargetValue = IntegerValue == 0 ? "false" : "true"; + else + PrettyTargetValue = IntegerValue.toString(10); + S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) - << FL->getType() << T << FL->getSourceRange() << SourceRange(CContext); + << FL->getType() << T.getUnqualifiedType() << PrettySourceValue + << PrettyTargetValue << FL->getSourceRange() << SourceRange(CContext); } std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { @@ -4149,7 +4159,6 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, } } } - return; // Other casts to bool are not checked. } // Strip vector types. @@ -4213,7 +4222,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, } // If the target is integral, always warn. - if ((TargetBT && TargetBT->isInteger())) { + if (TargetBT && TargetBT->isInteger()) { if (S.SourceMgr.isInSystemMacro(CC)) return; @@ -4247,6 +4256,11 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return; } + // TODO: remove this early return once the false positives for constant->bool + // in templates, macros, etc, are reduced or removed. + if (Target->isSpecificBuiltinType(BuiltinType::Bool)) + return; + IntRange SourceRange = GetExprRange(S.Context, E); IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target); diff --git a/test/Analysis/array-struct-region.c b/test/Analysis/array-struct-region.c index 8be86883a0..18d5b2a375 100644 --- a/test/Analysis/array-struct-region.c +++ b/test/Analysis/array-struct-region.c @@ -25,8 +25,8 @@ int string_literal_init() { } void nested_compound_literals(int rad) { - int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, // expected-warning 6 {{implicit conversion turns literal floating-point number into integer}} - {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // expected-warning 6 {{implicit conversion turns literal floating-point number into integer}} + int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, // expected-warning 6 {{implicit conversion from 'double' to 'int' changes value from}} + {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // expected-warning 6 {{implicit conversion from 'double' to 'int' changes value from}} int a; for (a = 0; a < 6; ++a) { diff --git a/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp b/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp index ac11940c80..2646264273 100644 --- a/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp +++ b/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp @@ -4,7 +4,7 @@ bool b = !0; -bool b2 = !1.2; +bool b2 = !1.2; //expected-warning{{implicit conversion from 'double' to 'bool' changes value from 1.2 to true}} bool b3 = !4; diff --git a/test/CXX/temp/temp.spec/p5.cpp b/test/CXX/temp/temp.spec/p5.cpp index 0e69a26b04..ba92d41e3e 100644 --- a/test/CXX/temp/temp.spec/p5.cpp +++ b/test/CXX/temp/temp.spec/p5.cpp @@ -14,7 +14,7 @@ struct X0 { }; template -T X0::value = 3.14; // expected-warning{{implicit conversion turns literal floating-point number into integer}} +T X0::value = 3.14; // expected-warning{{implicit conversion from 'double' to 'int' changes value from 3.14 to 3}} template struct X0; // expected-note{{previous explicit instantiation}} \ expected-note{{requested here}} diff --git a/test/PCH/exprs.h b/test/PCH/exprs.h index 09a50135e4..d08b1f64ed 100644 --- a/test/PCH/exprs.h +++ b/test/PCH/exprs.h @@ -87,7 +87,7 @@ struct { int x; float y; } designated_inits[3] = { [0].y = 17, - [2].x = 12.3, // expected-warning {{implicit conversion turns literal floating-point number into integer}} + [2].x = 12.3, // expected-warning {{implicit conversion from 'double' to 'int' changes value from 12.3 to 12}} 3.5 }; // TypesCompatibleExpr diff --git a/test/Sema/array-init.c b/test/Sema/array-init.c index 26c0b24182..cfdf8e2bd7 100644 --- a/test/Sema/array-init.c +++ b/test/Sema/array-init.c @@ -50,7 +50,7 @@ void func() { static long x2[3] = { 1.0, "abc", // expected-warning{{incompatible pointer to integer conversion initializing 'long' with an expression of type 'char [4]'}} - 5.8 }; // expected-warning {{implicit conversion turns literal floating-point number into integer}} + 5.8 }; // expected-warning {{implicit conversion from 'double' to 'long' changes value from 5.8 to 5}} } void test() { diff --git a/test/Sema/knr-def-call.c b/test/Sema/knr-def-call.c index f41275d1e6..80ad0d820b 100644 --- a/test/Sema/knr-def-call.c +++ b/test/Sema/knr-def-call.c @@ -36,6 +36,6 @@ void proto(x) } void use_proto() { - proto(42.1); // expected-warning{{implicit conversion turns literal floating-point number into integer}} - (&proto)(42.1); // expected-warning{{implicit conversion turns literal floating-point number into integer}} + proto(42.1); // expected-warning{{implicit conversion from 'double' to 'int' changes value from 42.1 to 42}} + (&proto)(42.1); // expected-warning{{implicit conversion from 'double' to 'int' changes value from 42.1 to 42}} } diff --git a/test/SemaCXX/bool.cpp b/test/SemaCXX/bool.cpp index 2b3ab68848..f027186735 100644 --- a/test/SemaCXX/bool.cpp +++ b/test/SemaCXX/bool.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s // Bool literals can be enum values. enum { diff --git a/test/SemaCXX/conversion.cpp b/test/SemaCXX/conversion.cpp index b019536e1a..4b44bede8d 100644 --- a/test/SemaCXX/conversion.cpp +++ b/test/SemaCXX/conversion.cpp @@ -65,7 +65,7 @@ void test3() { int c = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to 'int'}} int d; d = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to 'int'}} - bool bl = NULL; // FIXME: this should warn but we currently suppress a bunch of conversion-to-bool warnings including this one + bool bl = NULL; // expected-warning {{implicit conversion of NULL constant to 'bool'}} char ch = NULL; // expected-warning {{implicit conversion of NULL constant to 'char'}} unsigned char uch = NULL; // expected-warning {{implicit conversion of NULL constant to 'unsigned char'}} short sh = NULL; // expected-warning {{implicit conversion of NULL constant to 'short'}} @@ -104,3 +104,12 @@ namespace test4 { tmpl2(); } } + +namespace test5 { + template + void func() { + bool b = I; + } + + template void func<3>(); +} diff --git a/test/SemaCXX/expressions.cpp b/test/SemaCXX/expressions.cpp index 355833e693..2635fb8d17 100644 --- a/test/SemaCXX/expressions.cpp +++ b/test/SemaCXX/expressions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s void choice(int); int choice(bool); diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index 09eb71d36d..2b5ebb962b 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -233,7 +233,7 @@ float* intref(const int&); void intref_test() { float* ir1 = intref(5); - float* ir2 = intref(5.5); // expected-warning{{implicit conversion turns literal floating-point number into integer}} + float* ir2 = intref(5.5); // expected-warning{{implicit conversion from 'double' to 'int' changes value from 5.5 to 5}} } void derived5(C&); // expected-note{{candidate function not viable: cannot bind base class object of type 'A' to derived class reference 'C &' for 1st argument}} diff --git a/test/SemaCXX/warn-literal-conversion.cpp b/test/SemaCXX/warn-literal-conversion.cpp index 5fcae5dc80..d7bec4c73e 100644 --- a/test/SemaCXX/warn-literal-conversion.cpp +++ b/test/SemaCXX/warn-literal-conversion.cpp @@ -5,29 +5,29 @@ void foo(int y); // Warn when a literal float or double is assigned or bound to an integer. void test0() { // Float - int y0 = 1.2222F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y1 = (1.2222F); // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y2 = (((1.2222F))); // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y3 = 12E-1F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y4 = 1.23E1F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int y0 = 1.2222F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2222 to 1}} + int y1 = (1.2222F); // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2222 to 1}} + int y2 = (((1.2222F))); // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2222 to 1}} + int y3 = 12E-1F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2 to 1}} + int y4 = 1.23E1F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 12.3 to 12}} // Double - int y5 = 1.2222; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y6 = 12E-1; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y7 = 1.23E1; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y8 = (1.23E1); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int y5 = 1.2222; // expected-warning {{implicit conversion from 'double' to 'int' changes value from 1.2222 to 1}} + int y6 = 12E-1; // expected-warning {{implicit conversion from 'double' to 'int' changes value from 1.2 to 1}} + int y7 = 1.23E1; // expected-warning {{implicit conversion from 'double' to 'int' changes value from 12.3 to 12}} + int y8 = (1.23E1); // expected-warning {{implicit conversion from 'double' to 'int' changes value from 12.3 to 12}} // Test assignment to an existing variable. - y8 = 2.22F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} + y8 = 2.22F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 2.22 to 2}} // Test direct initialization. - int y9(1.23F); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int y9(1.23F); // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.23 to 1}} // Test passing a literal floating-point value to a function that takes an integer. - foo(1.2F); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + foo(1.2F); // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2 to 1}} - int y10 = -1.2F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int y10 = -1.2F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2 to 1}} - // -Wconversion-literal does NOT catch const values. + // -Wliteral-conversion does NOT catch const values. // (-Wconversion DOES catch them.) static const float sales_tax_rate = .095F; int z = sales_tax_rate; diff --git a/test/SemaTemplate/member-template-access-expr.cpp b/test/SemaTemplate/member-template-access-expr.cpp index c95b57d4b4..f105ba8e84 100644 --- a/test/SemaTemplate/member-template-access-expr.cpp +++ b/test/SemaTemplate/member-template-access-expr.cpp @@ -60,7 +60,7 @@ struct X1 { void test_X1(X1 x1) { float *fp1 = x1.f1<>(17); - float *fp2 = x1.f1(3.14); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + float *fp2 = x1.f1(3.14); // expected-warning {{implicit conversion from 'double' to 'int' changes value from 3.14 to 3}} int *ip1 = x1.f1(17); float *ip2 = x1.f1(3.14);