summaryrefslogtreecommitdiffstats
path: root/test/SemaCXX/warn-float-conversion.cpp
blob: fad1ff147e492d73d152af2d9497f3d72e2c521a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// 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