Clang Project

clang_source_code/test/SemaCXX/warn-float-conversion.cpp
1// 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
2// RUN: %clang_cc1 -verify -fsyntax-only -triple x86_64-pc-linux-gnu %s -Wno-conversion -Wfloat-overflow-conversion -DOVERFLOW
3// RUN: %clang_cc1 -verify -fsyntax-only -triple x86_64-pc-linux-gnu %s -Wno-conversion -Wfloat-zero-conversion -DZERO
4
5float ReturnFloat();
6
7#ifdef FLOAT_CONVERSION
8bool ReturnBool(float f) {
9  return f;  //expected-warning{{conversion}}
10}
11
12char ReturnChar(float f) {
13  return f;  //expected-warning{{conversion}}
14}
15
16int ReturnInt(float f) {
17  return f;  //expected-warning{{conversion}}
18}
19
20long ReturnLong(float f) {
21  return f;  //expected-warning{{conversion}}
22}
23
24void Convert(float f, double d, long double ld) {
25  bool b;
26  char c;
27  int i;
28  long l;
29
30  b = f;  //expected-warning{{conversion}}
31  b = d;  //expected-warning{{conversion}}
32  b = ld;  //expected-warning{{conversion}}
33  c = f;  //expected-warning{{conversion}}
34  c = d;  //expected-warning{{conversion}}
35  c = ld;  //expected-warning{{conversion}}
36  i = f;  //expected-warning{{conversion}}
37  i = d;  //expected-warning{{conversion}}
38  i = ld;  //expected-warning{{conversion}}
39  l = f;  //expected-warning{{conversion}}
40  l = d;  //expected-warning{{conversion}}
41  l = ld;  //expected-warning{{conversion}}
42}
43
44void CompoundAssignment() {
45  int x = 3;
46
47  x += 1.234; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}}
48  x -= -0.0;  // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}}
49  x *= 1.1f;  // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}}
50  x /= -2.2f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}}
51
52  int y = x += 1.4f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}}
53
54  float z = 1.1f;
55  double w = -2.2;
56
57  y += z + w; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}}
58}
59
60# 1 "foo.h" 3
61//          ^ the following text comes from a system header file.
62#define SYSTEM_MACRO_FLOAT(x) do { (x) += 1.1; } while(0)
63# 1 "warn-float-conversion.cpp" 1
64//                              ^ start of a new file.
65void SystemMacro() {
66  float x = 0.0f;
67  SYSTEM_MACRO_FLOAT(x);
68}
69
70void Test() {
71  int a1 = 10.0/2.0;  //expected-warning{{conversion}}
72  int a2 = 1.0/2.0;  //expected-warning{{conversion}}
73  bool a3 = ReturnFloat();  //expected-warning{{conversion}}
74  int a4 = 1e30 + 1;  //expected-warning{{conversion}}
75}
76
77void TestConstantFloat() {
78  // Don't warn on exact floating literals.
79  int a1 = 5.0;
80  int a2 = 1e3;
81
82  int a3 = 5.5;  // caught by -Wliteral-conversion
83  int a4 = 500.44;  // caught by -Wliteral-convserion
84
85  int b1 = 5.0 / 1.0;  //expected-warning{{conversion}}
86  int b2 = 5.0 / 2.0;  //expected-warning{{conversion}}
87
88  const float five = 5.0;
89
90  int b3 = five / 1.0;  //expected-warning{{conversion}}
91  int b4 = five / 2.0;  //expected-warning{{conversion}}
92
93  int f = 2147483646.5 + 1; // expected-warning{{implicit conversion from 'double' to 'int' changes value from 2147483647.5 to 2147483647}}
94  unsigned g = -.5 + .01; // expected-warning{{implicit conversion from 'double' to 'unsigned int' changes non-zero value from -0.49 to 0}}
95}
96#endif  // FLOAT_CONVERSION
97
98#ifdef ZERO
99void TestZero() {
100  const float half = .5;
101  int a1 = half;  // expected-warning{{implicit conversion from 'const float' to 'int' changes non-zero value from 0.5 to 0}}
102  int a2 = 1.0 / 2.0;  // expected-warning{{implicit conversion from 'double' to 'int' changes non-zero value from 0.5 to 0}}
103  int a3 = 5;
104}
105#endif  // ZERO
106
107#ifdef OVERFLOW
108void TestOverflow() {
109  char a = 500.0;  // caught by -Wliteral-conversion
110  char b = -500.0;  // caught by -Wliteral-conversion
111
112  const float LargeNumber = 1024;
113  char c = LargeNumber;  // expected-warning{{implicit conversion of out of range value from 'const float' to 'char' is undefined}}
114  char d = 400.0 + 400.0;  // expected-warning{{implicit conversion of out of range value from 'double' to 'char' is undefined}}
115
116  char e = 1.0 / 0.0;  // expected-warning{{implicit conversion of out of range value from 'double' to 'char' is undefined}}
117}
118
119
120template <typename T>
121class Check {
122 public:
123  static constexpr bool Safe();
124};
125
126template<>
127constexpr bool Check<char>::Safe() { return false; }
128
129template<>
130constexpr bool Check<float>::Safe() { return true; }
131
132template <typename T>
133T run1(T t) {
134  const float ret = 800;
135  return ret;  // expected-warning {{implicit conversion of out of range value from 'const float' to 'char' is undefined}}
136}
137
138template <typename T>
139T run2(T t) {
140  const float ret = 800;
141  if (Check<T>::Safe())
142    return ret;
143  else
144    return t;
145}
146
147void test() {
148  float a = run1(a) + run2(a);
149  char b = run1(b) + run2(b);  // expected-note {{in instantiation of function template specialization 'run1<char>' requested here}}
150}
151
152#endif  // OVERFLOW
153