Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -3733,8 +3733,9 @@ if (ImplicitCastExpr *Cast = dyn_cast(OrigArg)) { Expr *CastArg = Cast->getSubExpr(); if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { - assert(Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) && - "promotion from float to double is the only expected cast here"); + assert((Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) || + Cast->getType()->isSpecificBuiltinType(BuiltinType::Float)) && + "promotion from float to either float or double is the only expected cast here"); Cast->setSubExpr(nullptr); TheCall->setArg(NumArgs-1, CastArg); } Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -705,9 +705,11 @@ if (getLangOpts().ObjCAutoRefCount && E->getType().getObjCLifetime() == Qualifiers::OCL_Weak) Cleanup.setExprNeedsCleanups(true); + + ExprResult Res = E; - ExprResult Res = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E, - nullptr, VK_RValue); + Res = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E, + nullptr, VK_RValue); // C11 6.3.2.1p2: // ... if the lvalue has atomic type, the value has the non-atomic version @@ -817,8 +819,16 @@ // double. const BuiltinType *BTy = Ty->getAs(); if (BTy && (BTy->getKind() == BuiltinType::Half || - BTy->getKind() == BuiltinType::Float)) - E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get(); + BTy->getKind() == BuiltinType::Float)) { + if (getLangOpts().OpenCL && + !(getOpenCLOptions().cl_khr_fp64)) { + if (BTy->getKind() == BuiltinType::Half) { + E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get(); + } + } else { + E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get(); + } + } // C++ performs lvalue-to-rvalue conversion as a default argument // promotion, even on class types, but note: @@ -3397,10 +3407,13 @@ if (Ty == Context.DoubleTy) { if (getLangOpts().SinglePrecisionConstants) { - Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get(); + const BuiltinType *BTy = Ty->getAs(); + if (BTy->getKind() != BuiltinType::Float) { + Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get(); + } } else if (getLangOpts().OpenCL && - !((getLangOpts().OpenCLVersion >= 120) || - getOpenCLOptions().cl_khr_fp64)) { + !(getOpenCLOptions().cl_khr_fp64)) { + // Impose single-precision float type when cl_khr_fp64 is not enabled. Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64); Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get(); } Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -1401,8 +1401,7 @@ Result = Context.DoubleTy; if (S.getLangOpts().OpenCL && - !((S.getLangOpts().OpenCLVersion >= 120) || - S.getOpenCLOptions().cl_khr_fp64)) { + !(S.getOpenCLOptions().cl_khr_fp64)) { S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension) << Result << "cl_khr_fp64"; declarator.setInvalidType(true); Index: test/CodeGenOpenCL/fpmath.cl =================================================================== --- test/CodeGenOpenCL/fpmath.cl +++ test/CodeGenOpenCL/fpmath.cl @@ -1,5 +1,7 @@ // RUN: %clang_cc1 %s -emit-llvm -o - -triple spir-unknown-unknown | FileCheck --check-prefix=CHECK --check-prefix=NODIVOPT %s // RUN: %clang_cc1 %s -emit-llvm -o - -triple spir-unknown-unknown -cl-fp32-correctly-rounded-divide-sqrt | FileCheck --check-prefix=CHECK --check-prefix=DIVOPT %s +// RUN: %clang_cc1 %s -emit-llvm -o - -DNOFP64 -cl-std=CL1.2 -triple r600-unknown-unknown -target-cpu r600 -pedantic | FileCheck --check-prefix=CHECK-FLT %s +// RUN: %clang_cc1 %s -emit-llvm -o - -DFP64 -cl-std=CL1.2 -pedantic | FileCheck --check-prefix=CHECK-DBL %s typedef __attribute__(( ext_vector_type(4) )) float float4; @@ -21,14 +23,26 @@ return a / b; } -#pragma OPENCL EXTENSION cl_khr_fp64 : enable +#if __OPENCL_C_VERSION__ >=120 +void printf(constant char* fmt, ...); + +void testdbllit(long *val) { + // CHECK-FLT: float 2.000000e+01 + // CHECK-DBL: double 2.000000e+01 + printf("%f", 20.0); +} +#endif + +#ifndef NOFP64 +#pragma OPENCL EXTENSION cl_khr_fp64 : enable double dpscalardiv(double a, double b) { // CHECK: @dpscalardiv // CHECK: #[[ATTR]] // CHECK-NOT: !fpmath return a / b; } +#endif // CHECK: attributes #[[ATTR]] = { // NODIVOPT: "correctly-rounded-divide-sqrt-fp-math"="false" Index: test/SemaOpenCL/extensions.cl =================================================================== --- test/SemaOpenCL/extensions.cl +++ test/SemaOpenCL/extensions.cl @@ -1,13 +1,20 @@ // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL1.1 +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL1.2 -DFP64 // Test with a target not supporting fp64. // RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -DNOFP64 +#ifdef FP64 +// expected-no-diagnostics +#endif + +#if __OPENCL_C_VERSION__ < 120 void f1(double da) { // expected-error {{type 'double' requires cl_khr_fp64 extension}} double d; // expected-error {{type 'double' requires cl_khr_fp64 extension}} (void) 1.0; // expected-warning {{double precision constant requires cl_khr_fp64}} } +#endif #pragma OPENCL EXTENSION cl_khr_fp64 : enable #ifdef NOFP64 @@ -21,8 +28,9 @@ #endif (void) 1.0; + #ifdef NOFP64 -// expected-warning@-2{{double precision constant requires cl_khr_fp64, casting to single precision}} +// expected-warning@-3{{double precision constant requires cl_khr_fp64, casting to single precision}} #endif } @@ -31,6 +39,8 @@ // expected-warning@-2{{unsupported OpenCL extension 'cl_khr_fp64' - ignoring}} #endif +#if __OPENCL_C_VERSION__ < 120 void f3(void) { double d; // expected-error {{type 'double' requires cl_khr_fp64 extension}} } +#endif