| // RUN: %clang_cc1 -verify -fsyntax-only -triple x86_64-pc-linux-gnu %s -Wno-literal-conversion -Wfloat-conversion -DFLOAT_CONVERSION -DZERO -DBOOL -DCONSTANT_BOOL -DOVERFLOW | 
 | // RUN: %clang_cc1 -verify -fsyntax-only -triple x86_64-pc-linux-gnu %s -Wno-conversion -Wfloat-overflow-conversion -DOVERFLOW | 
 | // RUN: %clang_cc1 -verify -fsyntax-only -triple x86_64-pc-linux-gnu %s -Wno-conversion -Wfloat-zero-conversion -DZERO | 
 |  | 
 | float ReturnFloat(); | 
 |  | 
 | #ifdef FLOAT_CONVERSION | 
 | bool ReturnBool(float f) { | 
 |   return f;  //expected-warning{{conversion}} | 
 | } | 
 |  | 
 | char ReturnChar(float f) { | 
 |   return f;  //expected-warning{{conversion}} | 
 | } | 
 |  | 
 | int ReturnInt(float f) { | 
 |   return f;  //expected-warning{{conversion}} | 
 | } | 
 |  | 
 | long ReturnLong(float f) { | 
 |   return f;  //expected-warning{{conversion}} | 
 | } | 
 |  | 
 | void Convert(float f, double d, long double ld) { | 
 |   bool b; | 
 |   char c; | 
 |   int i; | 
 |   long l; | 
 |  | 
 |   b = f;  //expected-warning{{conversion}} | 
 |   b = d;  //expected-warning{{conversion}} | 
 |   b = ld;  //expected-warning{{conversion}} | 
 |   c = f;  //expected-warning{{conversion}} | 
 |   c = d;  //expected-warning{{conversion}} | 
 |   c = ld;  //expected-warning{{conversion}} | 
 |   i = f;  //expected-warning{{conversion}} | 
 |   i = d;  //expected-warning{{conversion}} | 
 |   i = ld;  //expected-warning{{conversion}} | 
 |   l = f;  //expected-warning{{conversion}} | 
 |   l = d;  //expected-warning{{conversion}} | 
 |   l = ld;  //expected-warning{{conversion}} | 
 | } | 
 |  | 
 | void CompoundAssignment() { | 
 |   int x = 3; | 
 |  | 
 |   x += 1.234; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} | 
 |   x -= -0.0;  // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} | 
 |   x *= 1.1f;  // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} | 
 |   x /= -2.2f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} | 
 |  | 
 |   int y = x += 1.4f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} | 
 |  | 
 |   float z = 1.1f; | 
 |   double w = -2.2; | 
 |  | 
 |   y += z + w; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} | 
 | } | 
 |  | 
 | # 1 "foo.h" 3 | 
 | //          ^ the following text comes from a system header file. | 
 | #define SYSTEM_MACRO_FLOAT(x) do { (x) += 1.1; } while(0) | 
 | # 1 "warn-float-conversion.cpp" 1 | 
 | //                              ^ start of a new file. | 
 | void SystemMacro() { | 
 |   float x = 0.0f; | 
 |   SYSTEM_MACRO_FLOAT(x); | 
 | } | 
 |  | 
 | void Test() { | 
 |   int a1 = 10.0/2.0;  //expected-warning{{conversion}} | 
 |   int a2 = 1.0/2.0;  //expected-warning{{conversion}} | 
 |   bool a3 = ReturnFloat();  //expected-warning{{conversion}} | 
 |   int a4 = 1e30 + 1;  //expected-warning{{conversion}} | 
 | } | 
 |  | 
 | void TestConstantFloat() { | 
 |   // Don't warn on exact floating literals. | 
 |   int a1 = 5.0; | 
 |   int a2 = 1e3; | 
 |  | 
 |   int a3 = 5.5;  // caught by -Wliteral-conversion | 
 |   int a4 = 500.44;  // caught by -Wliteral-convserion | 
 |  | 
 |   int b1 = 5.0 / 1.0;  //expected-warning{{conversion}} | 
 |   int b2 = 5.0 / 2.0;  //expected-warning{{conversion}} | 
 |  | 
 |   const float five = 5.0; | 
 |  | 
 |   int b3 = five / 1.0;  //expected-warning{{conversion}} | 
 |   int b4 = five / 2.0;  //expected-warning{{conversion}} | 
 |  | 
 |   int f = 2147483646.5 + 1; // expected-warning{{implicit conversion from 'double' to 'int' changes value from 2147483647.5 to 2147483647}} | 
 |   unsigned g = -.5 + .01; // expected-warning{{implicit conversion from 'double' to 'unsigned int' changes non-zero value from -0.49 to 0}} | 
 | } | 
 | #endif  // FLOAT_CONVERSION | 
 |  | 
 | #ifdef ZERO | 
 | void TestZero() { | 
 |   const float half = .5; | 
 |   int a1 = half;  // expected-warning{{implicit conversion from 'const float' to 'int' changes non-zero value from 0.5 to 0}} | 
 |   int a2 = 1.0 / 2.0;  // expected-warning{{implicit conversion from 'double' to 'int' changes non-zero value from 0.5 to 0}} | 
 |   int a3 = 5; | 
 | } | 
 | #endif  // ZERO | 
 |  | 
 | #ifdef OVERFLOW | 
 | void TestOverflow() { | 
 |   char a = 500.0;  // caught by -Wliteral-conversion | 
 |   char b = -500.0;  // caught by -Wliteral-conversion | 
 |  | 
 |   const float LargeNumber = 1024; | 
 |   char c = LargeNumber;  // expected-warning{{implicit conversion of out of range value from 'const float' to 'char' is undefined}} | 
 |   char d = 400.0 + 400.0;  // expected-warning{{implicit conversion of out of range value from 'double' to 'char' is undefined}} | 
 |  | 
 |   char e = 1.0 / 0.0;  // expected-warning{{implicit conversion of out of range value from 'double' to 'char' is undefined}} | 
 | } | 
 |  | 
 |  | 
 | template <typename T> | 
 | class Check { | 
 |  public: | 
 |   static constexpr bool Safe(); | 
 | }; | 
 |  | 
 | template<> | 
 | constexpr bool Check<char>::Safe() { return false; } | 
 |  | 
 | template<> | 
 | constexpr bool Check<float>::Safe() { return true; } | 
 |  | 
 | template <typename T> | 
 | T run1(T t) { | 
 |   const float ret = 800; | 
 |   return ret;  // expected-warning {{implicit conversion of out of range value from 'const float' to 'char' is undefined}} | 
 | } | 
 |  | 
 | template <typename T> | 
 | T run2(T t) { | 
 |   const float ret = 800; | 
 |   if (Check<T>::Safe()) | 
 |     return ret; | 
 |   else | 
 |     return t; | 
 | } | 
 |  | 
 | void test() { | 
 |   float a = run1(a) + run2(a); | 
 |   char b = run1(b) + run2(b);  // expected-note {{in instantiation of function template specialization 'run1<char>' requested here}} | 
 | } | 
 |  | 
 | #endif  // OVERFLOW |