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

- better warning


https://reviews.llvm.org/D52835

Files:
  lib/Sema/SemaChecking.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,15 @@
+// RUN: %clang_cc1 %s -verify -Wconversion -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.147484E+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.147484E+9}}
+    float a4 = (1ULL << 31) - 1; // expected-warning {{implicit conversion from 'unsigned long long' to 'float' changes value from 2147483647 to 2.147483E+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}}    
+}
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.294967E+9}}
   vf = vf + 2.1; // expected-warning {{implicit conversion loses floating-point precision}}
   
   vd = l + vd;
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -105,6 +105,12 @@
                                Context.getTargetInfo());
 }
 
+/// Force the precision of the source value down so we don't print digits which
+/// are usually useless
+static unsigned AdjustPrecision(unsigned precision) {
+  return (precision * 59 + 195) / 196;
+}
+
 /// 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) {
@@ -10418,7 +10424,7 @@
   // tricky to implement.
   SmallString<16> PrettySourceValue;
   unsigned precision = llvm::APFloat::semanticsPrecision(Value.getSemantics());
-  precision = (precision * 59 + 195) / 196;
+  precision = AdjustPrecision(precision);
   Value.toString(PrettySourceValue, precision);
 
   SmallString<16> PrettyTargetValue;
@@ -10852,6 +10858,42 @@
     return;
   }
 
+  if (Source->isIntegerType() && Target->isFloatingType()) {
+    const llvm::fltSemantics *FloatSem = nullptr;
+    if (Target->isSpecificBuiltinType(BuiltinType::Float)) {
+      FloatSem = &llvm::APFloat::IEEEsingle();
+    } else if (Target->isSpecificBuiltinType(BuiltinType::Double)) {
+      FloatSem = &llvm::APFloat::IEEEdouble();
+    }
+
+    if (FloatSem) {
+      llvm::APFloat FloatValue(*FloatSem);
+      llvm::APSInt IntValue;
+      if (E->EvaluateAsInt(IntValue, S.Context, Expr::SE_AllowSideEffects)) {
+        if (S.SourceMgr.isInSystemMacro(CC))
+          return;
+
+        if (FloatValue.convertFromAPInt(IntValue, Source->isSignedIntegerType(),
+                                        llvm::APFloat::rmTowardZero) !=
+            llvm::APFloat::opOK) {
+          SmallString<16> PrettyTargetValue;
+          SmallString<16> PrettySourceValue;
+          unsigned precision = llvm::APFloat::semanticsPrecision(*FloatSem);
+          precision = AdjustPrecision(precision);
+          FloatValue.toString(PrettyTargetValue, precision);
+          IntValue.toString(PrettySourceValue);
+
+          S.DiagRuntimeBehavior(
+              E->getExprLoc(), E,
+              S.PDiag(diag::warn_impcast_literal_float_to_integer)
+                  << E->getType() << T << PrettySourceValue << PrettyTargetValue
+                  << E->getSourceRange() << clang::SourceRange(CC));
+          return;
+        }
+      }
+    }
+  }
+
   DiagnoseNullConversion(S, E, T, CC);
 
   S.DiscardMisalignedMemberAddress(Target, E);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to