From: Chandler Carruth Date: Sun, 10 Apr 2011 08:36:24 +0000 (+0000) Subject: Enhance the diagnostic for literal float -> int conversions to suggest X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f65076ebf5e8bc5ae7b77fe3c3a65dc5db8d763f;p=clang Enhance the diagnostic for literal float -> int conversions to suggest rewriting the literal when the value is integral. It is not uncommon to see code written as: const int kBigNumber = 42e5; Without any real awareness that this is no longer an ICE. The note helps automate and ease the process of fixing code that violates the warning. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129243 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index edcf4ef14f..4ec3d735af 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1194,6 +1194,8 @@ def warn_impcast_literal_float_to_integer : Warning< "implicit conversion turns literal floating-point number into integer: " "%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< "implicit conversion from enumeration type %0 to different enumeration type " "%1">, InGroup>; diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index e1adfd4839..9372a16bf1 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2763,6 +2763,38 @@ void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext, DiagnoseImpCast(S, E, E->getType(), T, CContext, diag); } +/// Diagnose an implicit cast from a literal expression. Also attemps to supply +/// fixit hints when the cast wouldn't lose information to simply write the +/// expression with the expected type. +void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T, + SourceLocation CContext) { + // Emit the primary warning first, then try to emit a fixit hint note if + // reasonable. + S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) + << FL->getType() << T << FL->getSourceRange() << SourceRange(CContext); + + const llvm::APFloat &Value = FL->getValue(); + + // Don't attempt to fix PPC double double literals. + if (&Value.getSemantics() == &llvm::APFloat::PPCDoubleDouble) + return; + + // Try to convert this exactly to an 64-bit integer. FIXME: It would be + // nice to support arbitrarily large integers here. + bool isExact = false; + uint64_t IntegerPart; + if (Value.convertToInteger(&IntegerPart, 64, /*isSigned=*/true, + llvm::APFloat::rmTowardZero, &isExact) + != llvm::APFloat::opOK || !isExact) + return; + + llvm::APInt IntegerValue(64, IntegerPart, /*isSigned=*/true); + + std::string LiteralValue = IntegerValue.toString(10, /*isSigned=*/true); + S.Diag(FL->getExprLoc(), diag::note_fix_integral_float_as_integer) + << FixItHint::CreateReplacement(FL->getSourceRange(), LiteralValue); +} + std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { if (!Range.Width) return "0"; @@ -2776,7 +2808,7 @@ static bool isFromSystemMacro(Sema &S, SourceLocation loc) { SourceManager &smgr = S.Context.getSourceManager(); return loc.isMacroID() && smgr.isInSystemHeader(smgr.getSpellingLoc(loc)); } - + void CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, bool *ICContext = 0) { if (E->isTypeDependent() || E->isValueDependent()) return; @@ -2859,9 +2891,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return; Expr *InnerE = E->IgnoreParenImpCasts(); - if (FloatingLiteral *LiteralExpr = dyn_cast(InnerE)) { - DiagnoseImpCast(S, LiteralExpr, T, CC, - diag::warn_impcast_literal_float_to_integer); + if (FloatingLiteral *FL = dyn_cast(InnerE)) { + DiagnoseFloatingLiteralImpCast(S, FL, T, CC); } else { DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_integer); } diff --git a/test/Sema/knr-def-call.c b/test/Sema/knr-def-call.c index d054a04765..6243af6193 100644 --- a/test/Sema/knr-def-call.c +++ b/test/Sema/knr-def-call.c @@ -36,6 +36,8 @@ void proto(x) } void use_proto() { - proto(42.0); // expected-warning{{implicit conversion turns literal floating-point number into integer}} - (&proto)(42.0); // expected-warning{{implicit conversion turns literal floating-point number into integer}} + proto(42.0); // expected-warning{{implicit conversion turns literal floating-point number into integer}} \ + // expected-note {{this can be rewritten as an integer literal with the exact same value}} + (&proto)(42.0); // expected-warning{{implicit conversion turns literal floating-point number into integer}} \ + // expected-note {{this can be rewritten as an integer literal with the exact same value}} } diff --git a/test/SemaCXX/warn-literal-conversion.cpp b/test/SemaCXX/warn-literal-conversion.cpp index dab5c01bf6..b9c952873b 100644 --- a/test/SemaCXX/warn-literal-conversion.cpp +++ b/test/SemaCXX/warn-literal-conversion.cpp @@ -8,13 +8,18 @@ void test0() { 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 = 12E1F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y4 = 1.2E1F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int y3 = 12E1F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} \ + // expected-note {{this can be rewritten as an integer literal with the exact same value}} + int y4 = 1.2E1F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} \ + // expected-note {{this can be rewritten as an integer literal with the exact same value}} // Double int y5 = 1.2222; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y6 = 12E1; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y7 = 1.2E1; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y8 = (1.2E1); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int y6 = 12E1; // expected-warning {{implicit conversion turns literal floating-point number into integer}} \ + // expected-note {{this can be rewritten as an integer literal with the exact same value}} + int y7 = 1.2E1; // expected-warning {{implicit conversion turns literal floating-point number into integer}} \ + // expected-note {{this can be rewritten as an integer literal with the exact same value}} + int y8 = (1.2E1); // expected-warning {{implicit conversion turns literal floating-point number into integer}} \ + // expected-note {{this can be rewritten as an integer literal with the exact same value}} // Test assignment to an existing variable. y8 = 2.22F; // expected-warning {{implicit conversion turns literal floating-point number into integer}}