// 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(f); } long double ReturnLongDoubleFromFloatWithExplicitCast(float f) { return static_cast(f); } long double ReturnLongDoubleFromDoubleWithExplicitCast(double d) { return static_cast(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(f)); long double ld0(static_cast(f)); long double ld1(static_cast(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(f)}; long double ld0{static_cast(f)}; long double ld1{static_cast(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(f); ld = static_cast(f); ld = static_cast(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((f)); ld = static_cast((f)); ld = static_cast((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(f)); LongDoubleParameter(static_cast(f)); LongDoubleParameter(static_cast(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(f) * d; f = d * static_cast(f); f = static_cast(f) * ld; f = ld * static_cast(f); d = static_cast(d) * ld; d = ld * static_cast(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(f); ld *= static_cast(f); ld *= static_cast(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(f)}; ConstructWithLongDouble{static_cast(f)}; ConstructWithLongDouble{static_cast(d)}; ConstructWithDouble{double{f}}; ConstructWithLongDouble{LongDouble{f}}; ConstructWithLongDouble{LongDouble{d}}; ConstructWithDouble{double(f)}; ConstructWithLongDouble{LongDouble(f)}; ConstructWithLongDouble{LongDouble(d)}; } template 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 T ReturnTFromDouble(double d) { return d; // expected-warning{{implicit conversion increases floating-point precision: 'double' to 'long double'}} } template T ReturnTFromFloatWithStaticCast(float f) { return static_cast(f); } template T ReturnTFromDoubleWithStaticCast(double d) { return static_cast(d); } template T ReturnTFromFloatWithExplicitListInitialization(float f) { return T{f}; } template T ReturnTFromDoubleWithExplicitListInitialization(double d) { return T{d}; } template T ReturnTFromFloatWithFunctionStyleCast(float f) { return T(f); } template T ReturnTFromDoubleWithFunctionStyleCast(double d) { return T(d); } void TestTemplate(float f, double d) { ReturnTFromFloat(f); // expected-note{{in instantiation of function template specialization 'ReturnTFromFloat' requested here}} ReturnTFromFloat(f); // expected-note{{in instantiation of function template specialization 'ReturnTFromFloat' requested here}} ReturnTFromDouble(d); // expected-note{{in instantiation of function template specialization 'ReturnTFromDouble' requested here}} ReturnTFromFloatWithStaticCast(f); ReturnTFromFloatWithStaticCast(f); ReturnTFromDoubleWithStaticCast(d); ReturnTFromFloatWithExplicitListInitialization(f); ReturnTFromFloatWithExplicitListInitialization(f); ReturnTFromDoubleWithExplicitListInitialization(d); ReturnTFromFloatWithFunctionStyleCast(f); ReturnTFromFloatWithFunctionStyleCast(f); ReturnTFromDoubleWithFunctionStyleCast(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'}} {} };