|
| 1 | +// RUN: %clang_cc1 -triple x86_64-apple-darwin -verify -fsyntax-only %s -Wdouble-promotion |
| 2 | + |
| 3 | +using LongDouble = long double; |
| 4 | + |
| 5 | +double ReturnDoubleFromFloatWithExplicitCast(float f) { |
| 6 | + return static_cast<double>(f); |
| 7 | +} |
| 8 | + |
| 9 | +long double ReturnLongDoubleFromFloatWithExplicitCast(float f) { |
| 10 | + return static_cast<long double>(f); |
| 11 | +} |
| 12 | + |
| 13 | +long double ReturnLongDoubleFromDoubleWithExplicitCast(double d) { |
| 14 | + return static_cast<long double>(d); |
| 15 | +} |
| 16 | + |
| 17 | +double ReturnDoubleFromFloatWithExplicitListInitialization(float f) { |
| 18 | + return double{f}; |
| 19 | +} |
| 20 | + |
| 21 | +long double ReturnLongDoubleFromFloatWithExplicitListInitialization(float f) { |
| 22 | + return LongDouble{f}; |
| 23 | +} |
| 24 | + |
| 25 | +long double ReturnLongDoubleFromDoubleWithExplicitListInitialization(double d) { |
| 26 | + return LongDouble{d}; |
| 27 | +} |
| 28 | + |
| 29 | +double ReturnDoubleFromFloatWithFunctionStyleCast(float f) { |
| 30 | + return double(f); |
| 31 | +} |
| 32 | + |
| 33 | +long double ReturnLongDoubleFromFloatWithFunctionStyleCast(float f) { |
| 34 | + return LongDouble(f); |
| 35 | +} |
| 36 | + |
| 37 | +long double ReturnLongDoubleFromDoubleWithFunctionStyleCast(double d) { |
| 38 | + return LongDouble(d); |
| 39 | +} |
| 40 | + |
| 41 | +void InitializationWithParens(float f, double d) { |
| 42 | + { |
| 43 | + double d(f); // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'double'}} |
| 44 | + long double ld0(f); // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'long double'}} |
| 45 | + long double ld1(d); // expected-warning{{implicit conversion increases floating-point precision: 'double' to 'long double'}} |
| 46 | + } |
| 47 | + { |
| 48 | + double d(static_cast<double>(f)); |
| 49 | + long double ld0(static_cast<long double>(f)); |
| 50 | + long double ld1(static_cast<long double>(d)); |
| 51 | + } |
| 52 | + { |
| 53 | + double d(double{f}); |
| 54 | + long double ld0(LongDouble{f}); |
| 55 | + long double ld1(LongDouble{d}); |
| 56 | + } |
| 57 | + { |
| 58 | + double d((double(f))); |
| 59 | + long double ld0((LongDouble(f))); |
| 60 | + long double ld1((LongDouble(d))); |
| 61 | + } |
| 62 | +} |
| 63 | + |
| 64 | +void InitializationWithBraces(float f, double d) { |
| 65 | + { |
| 66 | + double d{f}; // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'double'}} |
| 67 | + long double ld0{f}; // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'long double'}} |
| 68 | + long double ld1{d}; // expected-warning{{implicit conversion increases floating-point precision: 'double' to 'long double'}} |
| 69 | + } |
| 70 | + { |
| 71 | + double d{static_cast<double>(f)}; |
| 72 | + long double ld0{static_cast<long double>(f)}; |
| 73 | + long double ld1{static_cast<long double>(d)}; |
| 74 | + } |
| 75 | + { |
| 76 | + double d{double{f}}; |
| 77 | + long double ld0{LongDouble{f}}; |
| 78 | + long double ld1{LongDouble{d}}; |
| 79 | + } |
| 80 | + { |
| 81 | + double d{double(f)}; |
| 82 | + long double ld0{LongDouble(f)}; |
| 83 | + long double ld1{LongDouble(d)}; |
| 84 | + } |
| 85 | +} |
| 86 | + |
| 87 | +void Assignment(float f, double d, long double ld) { |
| 88 | + d = static_cast<double>(f); |
| 89 | + ld = static_cast<long double>(f); |
| 90 | + ld = static_cast<long double>(d); |
| 91 | + d = double{f}; |
| 92 | + ld = LongDouble{f}; |
| 93 | + ld = LongDouble{d}; |
| 94 | + d = double(f); |
| 95 | + ld = LongDouble(f); |
| 96 | + ld = LongDouble(d); |
| 97 | +} |
| 98 | + |
| 99 | +void AssignmentWithExtraParens(float f, double d, long double ld) { |
| 100 | + d = static_cast<double>((f)); |
| 101 | + ld = static_cast<long double>((f)); |
| 102 | + ld = static_cast<long double>((d)); |
| 103 | + d = double{(f)}; |
| 104 | + ld = LongDouble{(f)}; |
| 105 | + ld = LongDouble{(d)}; |
| 106 | + d = double((f)); |
| 107 | + ld = LongDouble((f)); |
| 108 | + ld = LongDouble((d)); |
| 109 | +} |
| 110 | + |
| 111 | +void AssignmentWithExtraBraces(float f, double d, long double ld) { |
| 112 | + d = double{{f}}; // expected-warning{{too many braces around scalar initializer}} |
| 113 | + ld = LongDouble{{f}}; // expected-warning{{too many braces around scalar initializer}} |
| 114 | + ld = LongDouble{{d}}; // expected-warning{{too many braces around scalar initializer}} |
| 115 | +} |
| 116 | + |
| 117 | +extern void DoubleParameter(double); |
| 118 | +extern void LongDoubleParameter(long double); |
| 119 | + |
| 120 | +void ArgumentPassing(float f, double d) { |
| 121 | + DoubleParameter(static_cast<double>(f)); |
| 122 | + LongDoubleParameter(static_cast<long double>(f)); |
| 123 | + LongDoubleParameter(static_cast<long double>(d)); |
| 124 | + DoubleParameter(double{f}); |
| 125 | + LongDoubleParameter(LongDouble{f}); |
| 126 | + LongDoubleParameter(LongDouble{d}); |
| 127 | + DoubleParameter(double(f)); |
| 128 | + LongDoubleParameter(LongDouble(f)); |
| 129 | + LongDoubleParameter(LongDouble(d)); |
| 130 | +} |
| 131 | + |
| 132 | +void BinaryOperator(float f, double d, long double ld) { |
| 133 | + f = static_cast<double>(f) * d; |
| 134 | + f = d * static_cast<double>(f); |
| 135 | + f = static_cast<long double>(f) * ld; |
| 136 | + f = ld * static_cast<long double>(f); |
| 137 | + d = static_cast<long double>(d) * ld; |
| 138 | + d = ld * static_cast<long double>(d); |
| 139 | + f = double{f} * d; |
| 140 | + f = d * double{f}; |
| 141 | + f = LongDouble{f} * ld; |
| 142 | + f = ld * LongDouble{f}; |
| 143 | + d = LongDouble{d} * ld; |
| 144 | + d = ld * LongDouble{d}; |
| 145 | + f = double(f) * d; |
| 146 | + f = d * double(f); |
| 147 | + f = LongDouble(f) * ld; |
| 148 | + f = ld * LongDouble(f); |
| 149 | + d = LongDouble(d) * ld; |
| 150 | + d = ld * LongDouble(d); |
| 151 | +} |
| 152 | + |
| 153 | +void MultiplicationAssignment(float f, double d, long double ld) { |
| 154 | + d *= static_cast<double>(f); |
| 155 | + ld *= static_cast<long double>(f); |
| 156 | + ld *= static_cast<long double>(d); |
| 157 | + d *= double{f}; |
| 158 | + ld *= LongDouble{f}; |
| 159 | + ld *= LongDouble{d}; |
| 160 | + d *= double(f); |
| 161 | + ld *= LongDouble(f); |
| 162 | + ld *= LongDouble(d); |
| 163 | +} |
| 164 | + |
| 165 | +struct ConstructWithDouble { |
| 166 | + ConstructWithDouble(double); |
| 167 | +}; |
| 168 | + |
| 169 | +struct ConstructWithLongDouble { |
| 170 | + ConstructWithLongDouble(long double); |
| 171 | +}; |
| 172 | + |
| 173 | +void Construct(float f, double d) { |
| 174 | + ConstructWithDouble{f}; // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'double'}} |
| 175 | + ConstructWithLongDouble{f}; // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'long double'}} |
| 176 | + ConstructWithLongDouble{d}; // expected-warning{{implicit conversion increases floating-point precision: 'double' to 'long double'}} |
| 177 | + ConstructWithDouble{static_cast<double>(f)}; |
| 178 | + ConstructWithLongDouble{static_cast<long double>(f)}; |
| 179 | + ConstructWithLongDouble{static_cast<long double>(d)}; |
| 180 | + ConstructWithDouble{double{f}}; |
| 181 | + ConstructWithLongDouble{LongDouble{f}}; |
| 182 | + ConstructWithLongDouble{LongDouble{d}}; |
| 183 | + ConstructWithDouble{double(f)}; |
| 184 | + ConstructWithLongDouble{LongDouble(f)}; |
| 185 | + ConstructWithLongDouble{LongDouble(d)}; |
| 186 | +} |
| 187 | + |
| 188 | +template <class T> T ReturnTFromFloat(float f) { |
| 189 | + return f; // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'double'}} \ |
| 190 | + // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'long double'}} |
| 191 | +} |
| 192 | + |
| 193 | +template <class T> T ReturnTFromDouble(double d) { |
| 194 | + return d; // expected-warning{{implicit conversion increases floating-point precision: 'double' to 'long double'}} |
| 195 | +} |
| 196 | + |
| 197 | +template <class T> T ReturnTFromFloatWithStaticCast(float f) { |
| 198 | + return static_cast<T>(f); |
| 199 | +} |
| 200 | + |
| 201 | +template <class T> T ReturnTFromDoubleWithStaticCast(double d) { |
| 202 | + return static_cast<T>(d); |
| 203 | +} |
| 204 | + |
| 205 | +template <class T> T ReturnTFromFloatWithExplicitListInitialization(float f) { |
| 206 | + return T{f}; |
| 207 | +} |
| 208 | + |
| 209 | +template <class T> T ReturnTFromDoubleWithExplicitListInitialization(double d) { |
| 210 | + return T{d}; |
| 211 | +} |
| 212 | + |
| 213 | +template <class T> T ReturnTFromFloatWithFunctionStyleCast(float f) { |
| 214 | + return T(f); |
| 215 | +} |
| 216 | + |
| 217 | +template <class T> T ReturnTFromDoubleWithFunctionStyleCast(double d) { |
| 218 | + return T(d); |
| 219 | +} |
| 220 | + |
| 221 | +void TestTemplate(float f, double d) { |
| 222 | + ReturnTFromFloat<double>(f); // expected-note{{in instantiation of function template specialization 'ReturnTFromFloat<double>' requested here}} |
| 223 | + ReturnTFromFloat<long double>(f); // expected-note{{in instantiation of function template specialization 'ReturnTFromFloat<long double>' requested here}} |
| 224 | + ReturnTFromDouble<long double>(d); // expected-note{{in instantiation of function template specialization 'ReturnTFromDouble<long double>' requested here}} |
| 225 | + ReturnTFromFloatWithStaticCast<double>(f); |
| 226 | + ReturnTFromFloatWithStaticCast<long double>(f); |
| 227 | + ReturnTFromDoubleWithStaticCast<long double>(d); |
| 228 | + ReturnTFromFloatWithExplicitListInitialization<double>(f); |
| 229 | + ReturnTFromFloatWithExplicitListInitialization<long double>(f); |
| 230 | + ReturnTFromDoubleWithExplicitListInitialization<long double>(d); |
| 231 | + ReturnTFromFloatWithFunctionStyleCast<double>(f); |
| 232 | + ReturnTFromFloatWithFunctionStyleCast<long double>(f); |
| 233 | + ReturnTFromDoubleWithFunctionStyleCast<long double>(d); |
| 234 | +} |
| 235 | + |
| 236 | +struct MemberInitializerListParens { |
| 237 | + double m_d; |
| 238 | + long double m_ld0; |
| 239 | + long double m_ld1; |
| 240 | + MemberInitializerListParens(float f, double d): |
| 241 | + m_d(f), // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'double'}} |
| 242 | + m_ld0(f), // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'long double'}} |
| 243 | + m_ld1(d) // expected-warning{{implicit conversion increases floating-point precision: 'double' to 'long double'}} |
| 244 | + {} |
| 245 | +}; |
| 246 | + |
| 247 | +struct MemberInitializerListBraces { |
| 248 | + double m_d; |
| 249 | + long double m_ld0; |
| 250 | + long double m_ld1; |
| 251 | + MemberInitializerListBraces(float f, double d): |
| 252 | + m_d{f}, // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'double'}} |
| 253 | + m_ld0{f}, // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'long double'}} |
| 254 | + m_ld1{d} // expected-warning{{implicit conversion increases floating-point precision: 'double' to 'long double'}} |
| 255 | + {} |
| 256 | +}; |
0 commit comments