xbolva00 updated this revision to Diff 174505.
xbolva00 added a comment.

Addressed comments, fixed tests


https://reviews.llvm.org/D52835

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaChecking.cpp
  test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp
  test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-cxx11-nowarn.cpp
  test/Sema/ext_vector_casts.c
  test/Sema/impcast-integer-float.c

Index: test/Sema/impcast-integer-float.c
===================================================================
--- test/Sema/impcast-integer-float.c
+++ test/Sema/impcast-integer-float.c
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 %s -verify -Wfloat-precision -triple x86_64-linux -fsyntax-only
+
+#define shift_plus_one(x) ((1ULL << x) + 1)
+
+void test(void) {
+    float a1 = (1ULL << 31) + 1; // expected-warning {{implicit conversion from 'unsigned long long' to 'float' changes value from 2147483649 to 2.1474836E+9}}
+    float a2 = 1ULL << 31;
+    float a3 = shift_plus_one(31); // expected-warning {{implicit conversion from 'unsigned long long' to 'float' changes value from 2147483649 to 2.1474836E+9}}
+    float a4 = (1ULL << 31) - 1; // expected-warning {{implicit conversion from 'unsigned long long' to 'float' changes value from 2147483647 to 2.1474836E+9}}
+
+    double b1 = (1ULL << 63) + 1; // expected-warning {{implicit conversion from 'unsigned long long' to 'double' changes value from 9223372036854775809 to 9.223372036854775E+18}}
+    double b2 = 1ULL << 63;
+    double b3 = shift_plus_one(63); // expected-warning {{implicit conversion from 'unsigned long long' to 'double' changes value from 9223372036854775809 to 9.223372036854775E+18}}
+    double b4 = (1ULL << 63) - 1; // expected-warning {{implicit conversion from 'unsigned long long' to 'double' changes value from 9223372036854775807 to 9.223372036854775E+18}} 
+    
+    long double c1 = ((__int128)1 << 127) + 1; // expected-warning {{implicit conversion from '__int128' to 'long double' changes value from -170141183460469231731687303715884105727 to -1.7014118346046923173E+38}}
+    long double c2 = (__int128)1 << 127;
+
+    float d = (__uint128_t)-1; // expected-warning {{implicit conversion from '__uint128_t' (aka 'unsigned __int128') to 'float' changes value from 340282366920938463463374607431768211455 to +Inf}}
+}
Index: test/Sema/ext_vector_casts.c
===================================================================
--- test/Sema/ext_vector_casts.c
+++ test/Sema/ext_vector_casts.c
@@ -118,7 +118,7 @@
   vf = l + vf;
   vf = 2.0 + vf;
   vf = d + vf; // expected-warning {{implicit conversion loses floating-point precision}}
-  vf = vf + 0xffffffff;
+  vf = vf + 0xffffffff; // expected-warning {{implicit conversion from 'unsigned int' to 'float2' (vector of 2 'float' values) changes value from 4294967295 to 4.2949673E+9}}
   vf = vf + 2.1; // expected-warning {{implicit conversion loses floating-point precision}}
   
   vd = l + vd;
Index: test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-cxx11-nowarn.cpp
===================================================================
--- test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-cxx11-nowarn.cpp
+++ test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-cxx11-nowarn.cpp
@@ -121,8 +121,10 @@
 
   // Constants.
   Agg<float> f4 = {12345678};  // OK (exactly fits in a float)
+  // expected-warning@+1 {{implicit conversion from 'int' to 'float' changes value from 123456789 to 1.2345679E+8}}
   Agg<float> f5 = {123456789};  // expected-warning {{ cannot be narrowed }} expected-note {{silence}}
 
+  // expected-warning@+1 {{implicit conversion from 'int' to 'float' changes value from 123456789 to 1.2345679E+8}}
   Agg<float> ce1 = { Convert<int>(123456789) }; // expected-warning {{constant expression evaluates to 123456789 which cannot be narrowed to type 'float'}} expected-note {{silence}}
   Agg<double> ce2 = { ConvertVar<long long>() }; // expected-warning {{non-constant-expression cannot be narrowed from type 'long long' to 'double'}} expected-note {{silence}}
 }
Index: test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp
===================================================================
--- test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp
+++ test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp
@@ -133,8 +133,10 @@
   // Constants.
   Agg<float> f7 = {12345678};  // OK (exactly fits in a float)
   Agg<float> f8 = {EnumVal};  // OK
+  // expected-warning@+1 {{implicit conversion from 'int' to 'float' changes value from 123456789 to 1.2345679E+8}}
   Agg<float> f9 = {123456789};  // expected-error {{ cannot be narrowed }} expected-note {{silence}}
-
+  
+  // expected-warning@+1 {{implicit conversion from 'int' to 'float' changes value from 123456789 to 1.2345679E+8}}
   Agg<float> ce1 = { Convert<int>(123456789) }; // expected-error {{constant expression evaluates to 123456789 which cannot be narrowed to type 'float'}} expected-note {{silence}}
   Agg<double> ce2 = { ConvertVar<long long>() }; // expected-error {{non-constant-expression cannot be narrowed from type 'long long' to 'double'}} expected-note {{silence}}
 }
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -105,6 +105,19 @@
                                Context.getTargetInfo());
 }
 
+// FIXME: Force the precision of the source value down so we don't print
+// digits which are usually useless (we don't really care here if we
+// truncate a digit by accident in edge cases).  Ideally, APFloat::toString
+// would automatically print the shortest representation, but it's a bit
+// tricky to implement.
+static void PrettyPrintFloat(const llvm::APFloat &FloatValue,
+                             const llvm::fltSemantics &FloatSem,
+                             SmallVectorImpl<char> &PrettyFloatValue) {
+  unsigned Precision = llvm::APFloat::semanticsPrecision(FloatSem);
+  Precision = llvm::divideCeil(Precision * 59, 196);
+  FloatValue.toString(PrettyFloatValue, Precision);
+}
+
 /// Checks that a call expression's argument count is the desired number.
 /// This is useful when doing custom type-checking.  Returns true on error.
 static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) {
@@ -10473,15 +10486,8 @@
     DiagID = diag::warn_impcast_float_to_integer;
   }
 
-  // FIXME: Force the precision of the source value down so we don't print
-  // digits which are usually useless (we don't really care here if we
-  // truncate a digit by accident in edge cases).  Ideally, APFloat::toString
-  // would automatically print the shortest representation, but it's a bit
-  // tricky to implement.
   SmallString<16> PrettySourceValue;
-  unsigned precision = llvm::APFloat::semanticsPrecision(Value.getSemantics());
-  precision = (precision * 59 + 195) / 196;
-  Value.toString(PrettySourceValue, precision);
+  PrettyPrintFloat(Value, Value.getSemantics(), PrettySourceValue);
 
   SmallString<16> PrettyTargetValue;
   if (IsBool)
@@ -10914,6 +10920,29 @@
     return;
   }
 
+  if (Source->isIntegerType() && TargetBT && TargetBT->isFloatingType()) {
+    llvm::APSInt IntValue;
+    if (E->EvaluateAsInt(IntValue, S.Context, Expr::SE_AllowSideEffects)) {
+      const llvm::fltSemantics &FloatSemantics =
+          S.Context.getFloatTypeSemantics(QualType(TargetBT, 0));
+      llvm::APFloat FloatValue(FloatSemantics);
+      if (FloatValue.convertFromAPInt(IntValue, Source->isSignedIntegerType(),
+                                      llvm::APFloat::rmNearestTiesToEven) !=
+          llvm::APFloat::opOK) {
+        SmallString<16> PrettyTargetValue;
+        SmallString<16> PrettySourceValue;
+        PrettyPrintFloat(FloatValue, FloatSemantics, PrettyTargetValue);
+        IntValue.toString(PrettySourceValue);
+
+        S.DiagRuntimeBehavior(
+            E->getExprLoc(), E,
+            S.PDiag(diag::warn_impcast_precision_float_to_integer)
+                << E->getType() << T << PrettySourceValue << PrettyTargetValue
+                << E->getSourceRange() << clang::SourceRange(CC));
+      }
+    }
+  }
+
   DiagnoseNullConversion(S, E, T, CC);
 
   S.DiscardMisalignedMemberAddress(Target, E);
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -3229,6 +3229,10 @@
   "implicit conversion turns floating-point number into integer: %0 to %1">,
   InGroup<FloatConversion>, DefaultIgnore;
 
+def warn_impcast_precision_float_to_integer : Warning<
+  "implicit conversion from %0 to %1 changes value from %2 to %3">,
+  InGroup<DiagGroup<"float-precision">>;
+
 def warn_impcast_float_to_integer : Warning<
   "implicit conversion from %0 to %1 changes value from %2 to %3">,
   InGroup<FloatOverflowConversion>, DefaultIgnore;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to