| // RUN: %clang_cc1 -triple x86_64-apple-darwin -verify -fsyntax-only %s -Wdouble-promotion |
| |
| using LongDouble = long double; |
| |
| double ReturnDoubleFromFloatWithExplicitCast(float f) { |
| return static_cast<double>(f); |
| } |
| |
| long double ReturnLongDoubleFromFloatWithExplicitCast(float f) { |
| return static_cast<long double>(f); |
| } |
| |
| long double ReturnLongDoubleFromDoubleWithExplicitCast(double d) { |
| return static_cast<long double>(d); |
| } |
| |
| double ReturnDoubleFromFloatWithExplicitListInitialization(float f) { |
| return double{f}; |
| } |
| |
| long double ReturnLongDoubleFromFloatWithExplicitListInitialization(float f) { |
| return LongDouble{f}; |
| } |
| |
| long double ReturnLongDoubleFromDoubleWithExplicitListInitialization(double d) { |
| return LongDouble{d}; |
| } |
| |
| double ReturnDoubleFromFloatWithFunctionStyleCast(float f) { |
| return double(f); |
| } |
| |
| long double ReturnLongDoubleFromFloatWithFunctionStyleCast(float f) { |
| return LongDouble(f); |
| } |
| |
| long double ReturnLongDoubleFromDoubleWithFunctionStyleCast(double d) { |
| return LongDouble(d); |
| } |
| |
| void InitializationWithParens(float f, double d) { |
| { |
| double d(f); // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'double'}} |
| long double ld0(f); // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'long double'}} |
| long double ld1(d); // expected-warning{{implicit conversion increases floating-point precision: 'double' to 'long double'}} |
| } |
| { |
| double d(static_cast<double>(f)); |
| long double ld0(static_cast<long double>(f)); |
| long double ld1(static_cast<long double>(d)); |
| } |
| { |
| double d(double{f}); |
| long double ld0(LongDouble{f}); |
| long double ld1(LongDouble{d}); |
| } |
| { |
| double d((double(f))); |
| long double ld0((LongDouble(f))); |
| long double ld1((LongDouble(d))); |
| } |
| } |
| |
| void InitializationWithBraces(float f, double d) { |
| { |
| double d{f}; // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'double'}} |
| long double ld0{f}; // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'long double'}} |
| long double ld1{d}; // expected-warning{{implicit conversion increases floating-point precision: 'double' to 'long double'}} |
| } |
| { |
| double d{static_cast<double>(f)}; |
| long double ld0{static_cast<long double>(f)}; |
| long double ld1{static_cast<long double>(d)}; |
| } |
| { |
| double d{double{f}}; |
| long double ld0{LongDouble{f}}; |
| long double ld1{LongDouble{d}}; |
| } |
| { |
| double d{double(f)}; |
| long double ld0{LongDouble(f)}; |
| long double ld1{LongDouble(d)}; |
| } |
| } |
| |
| void Assignment(float f, double d, long double ld) { |
| d = static_cast<double>(f); |
| ld = static_cast<long double>(f); |
| ld = static_cast<long double>(d); |
| d = double{f}; |
| ld = LongDouble{f}; |
| ld = LongDouble{d}; |
| d = double(f); |
| ld = LongDouble(f); |
| ld = LongDouble(d); |
| } |
| |
| void AssignmentWithExtraParens(float f, double d, long double ld) { |
| d = static_cast<double>((f)); |
| ld = static_cast<long double>((f)); |
| ld = static_cast<long double>((d)); |
| d = double{(f)}; |
| ld = LongDouble{(f)}; |
| ld = LongDouble{(d)}; |
| d = double((f)); |
| ld = LongDouble((f)); |
| ld = LongDouble((d)); |
| } |
| |
| void AssignmentWithExtraBraces(float f, double d, long double ld) { |
| d = double{{f}}; // expected-warning{{too many braces around scalar initializer}} |
| ld = LongDouble{{f}}; // expected-warning{{too many braces around scalar initializer}} |
| ld = LongDouble{{d}}; // expected-warning{{too many braces around scalar initializer}} |
| } |
| |
| extern void DoubleParameter(double); |
| extern void LongDoubleParameter(long double); |
| |
| void ArgumentPassing(float f, double d) { |
| DoubleParameter(static_cast<double>(f)); |
| LongDoubleParameter(static_cast<long double>(f)); |
| LongDoubleParameter(static_cast<long double>(d)); |
| DoubleParameter(double{f}); |
| LongDoubleParameter(LongDouble{f}); |
| LongDoubleParameter(LongDouble{d}); |
| DoubleParameter(double(f)); |
| LongDoubleParameter(LongDouble(f)); |
| LongDoubleParameter(LongDouble(d)); |
| } |
| |
| void BinaryOperator(float f, double d, long double ld) { |
| f = static_cast<double>(f) * d; |
| f = d * static_cast<double>(f); |
| f = static_cast<long double>(f) * ld; |
| f = ld * static_cast<long double>(f); |
| d = static_cast<long double>(d) * ld; |
| d = ld * static_cast<long double>(d); |
| f = double{f} * d; |
| f = d * double{f}; |
| f = LongDouble{f} * ld; |
| f = ld * LongDouble{f}; |
| d = LongDouble{d} * ld; |
| d = ld * LongDouble{d}; |
| f = double(f) * d; |
| f = d * double(f); |
| f = LongDouble(f) * ld; |
| f = ld * LongDouble(f); |
| d = LongDouble(d) * ld; |
| d = ld * LongDouble(d); |
| } |
| |
| void MultiplicationAssignment(float f, double d, long double ld) { |
| d *= static_cast<double>(f); |
| ld *= static_cast<long double>(f); |
| ld *= static_cast<long double>(d); |
| d *= double{f}; |
| ld *= LongDouble{f}; |
| ld *= LongDouble{d}; |
| d *= double(f); |
| ld *= LongDouble(f); |
| ld *= LongDouble(d); |
| } |
| |
| struct ConstructWithDouble { |
| ConstructWithDouble(double); |
| }; |
| |
| struct ConstructWithLongDouble { |
| ConstructWithLongDouble(long double); |
| }; |
| |
| void Construct(float f, double d) { |
| ConstructWithDouble{f}; // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'double'}} |
| ConstructWithLongDouble{f}; // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'long double'}} |
| ConstructWithLongDouble{d}; // expected-warning{{implicit conversion increases floating-point precision: 'double' to 'long double'}} |
| ConstructWithDouble{static_cast<double>(f)}; |
| ConstructWithLongDouble{static_cast<long double>(f)}; |
| ConstructWithLongDouble{static_cast<long double>(d)}; |
| ConstructWithDouble{double{f}}; |
| ConstructWithLongDouble{LongDouble{f}}; |
| ConstructWithLongDouble{LongDouble{d}}; |
| ConstructWithDouble{double(f)}; |
| ConstructWithLongDouble{LongDouble(f)}; |
| ConstructWithLongDouble{LongDouble(d)}; |
| } |
| |
| template <class T> T ReturnTFromFloat(float f) { |
| return f; // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'double'}} \ |
| // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'long double'}} |
| } |
| |
| template <class T> T ReturnTFromDouble(double d) { |
| return d; // expected-warning{{implicit conversion increases floating-point precision: 'double' to 'long double'}} |
| } |
| |
| template <class T> T ReturnTFromFloatWithStaticCast(float f) { |
| return static_cast<T>(f); |
| } |
| |
| template <class T> T ReturnTFromDoubleWithStaticCast(double d) { |
| return static_cast<T>(d); |
| } |
| |
| template <class T> T ReturnTFromFloatWithExplicitListInitialization(float f) { |
| return T{f}; |
| } |
| |
| template <class T> T ReturnTFromDoubleWithExplicitListInitialization(double d) { |
| return T{d}; |
| } |
| |
| template <class T> T ReturnTFromFloatWithFunctionStyleCast(float f) { |
| return T(f); |
| } |
| |
| template <class T> T ReturnTFromDoubleWithFunctionStyleCast(double d) { |
| return T(d); |
| } |
| |
| void TestTemplate(float f, double d) { |
| ReturnTFromFloat<double>(f); // expected-note{{in instantiation of function template specialization 'ReturnTFromFloat<double>' requested here}} |
| ReturnTFromFloat<long double>(f); // expected-note{{in instantiation of function template specialization 'ReturnTFromFloat<long double>' requested here}} |
| ReturnTFromDouble<long double>(d); // expected-note{{in instantiation of function template specialization 'ReturnTFromDouble<long double>' requested here}} |
| ReturnTFromFloatWithStaticCast<double>(f); |
| ReturnTFromFloatWithStaticCast<long double>(f); |
| ReturnTFromDoubleWithStaticCast<long double>(d); |
| ReturnTFromFloatWithExplicitListInitialization<double>(f); |
| ReturnTFromFloatWithExplicitListInitialization<long double>(f); |
| ReturnTFromDoubleWithExplicitListInitialization<long double>(d); |
| ReturnTFromFloatWithFunctionStyleCast<double>(f); |
| ReturnTFromFloatWithFunctionStyleCast<long double>(f); |
| ReturnTFromDoubleWithFunctionStyleCast<long double>(d); |
| } |
| |
| struct MemberInitializerListParens { |
| double m_d; |
| long double m_ld0; |
| long double m_ld1; |
| MemberInitializerListParens(float f, double d): |
| m_d(f), // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'double'}} |
| m_ld0(f), // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'long double'}} |
| m_ld1(d) // expected-warning{{implicit conversion increases floating-point precision: 'double' to 'long double'}} |
| {} |
| }; |
| |
| struct MemberInitializerListBraces { |
| double m_d; |
| long double m_ld0; |
| long double m_ld1; |
| MemberInitializerListBraces(float f, double d): |
| m_d{f}, // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'double'}} |
| m_ld0{f}, // expected-warning{{implicit conversion increases floating-point precision: 'float' to 'long double'}} |
| m_ld1{d} // expected-warning{{implicit conversion increases floating-point precision: 'double' to 'long double'}} |
| {} |
| }; |