OpenCL Extension v1.2 s9.5 allows half precision floating point
type literals with suffices h or H when cl_khr_fp16 is enabled.
Example: half x = 1.0h;
Patch by Liu Yaxun (Sam)!
Differential Revision: http://reviews.llvm.org/D16865
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@261084
91177308-0d34-0410-b5e6-
96231b3b80d8
InGroup<LiteralRange>;
def warn_double_const_requires_fp64 : Warning<
"double precision constant requires cl_khr_fp64, casting to single precision">;
+def err_half_const_requires_fp16 : Error<
+ "half precision constant requires cl_khr_fp16">;
// C99 variable-length arrays
def ext_vla : Extension<"variable length arrays are a C99 feature">,
bool isUnsigned : 1;
bool isLong : 1; // This is *not* set for long long.
bool isLongLong : 1;
+ bool isHalf : 1; // 1.0h
bool isFloat : 1; // 1.0f
bool isImaginary : 1; // 1.0i
uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64.
isLong = false;
isUnsigned = false;
isLongLong = false;
+ isHalf = false;
isFloat = false;
isImaginary = false;
MicrosoftInteger = 0;
// we break out of the loop.
for (; s != ThisTokEnd; ++s) {
switch (*s) {
+ case 'h': // FP Suffix for "half".
+ case 'H':
+ // OpenCL Extension v1.2 s9.5 - h or H suffix for half type.
+ if (!PP.getLangOpts().Half) break;
+ if (!isFPConstant) break; // Error for integer constant.
+ if (isHalf || isFloat || isLong) break; // HH, FH, LH invalid.
+ isHalf = true;
+ continue; // Success.
case 'f': // FP Suffix for "float"
case 'F':
if (!isFPConstant) break; // Error for integer constant.
- if (isFloat || isLong) break; // FF, LF invalid.
+ if (isHalf || isFloat || isLong) break; // HF, FF, LF invalid.
isFloat = true;
continue; // Success.
case 'u':
case 'l':
case 'L':
if (isLong || isLongLong) break; // Cannot be repeated.
- if (isFloat) break; // LF invalid.
+ if (isHalf || isFloat) break; // LH, LF invalid.
// Check for long long. The L's need to be adjacent and the same case.
if (s[1] == s[0]) {
isUnsigned = false;
isLongLong = false;
isFloat = false;
+ isHalf = false;
isImaginary = false;
MicrosoftInteger = 0;
if (Literal.isFloatingLiteral()) {
QualType Ty;
- if (Literal.isFloat)
+ if (Literal.isHalf){
+ if (getOpenCLOptions().cl_khr_fp16)
+ Ty = Context.HalfTy;
+ else {
+ Diag(Tok.getLocation(), diag::err_half_const_requires_fp16);
+ return ExprError();
+ }
+ } else if (Literal.isFloat)
Ty = Context.FloatTy;
else if (!Literal.isLong)
Ty = Context.DoubleTy;
--- /dev/null
+// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s
+float a = 1.0h; // expected-error{{invalid suffix 'h' on floating constant}}
+float b = 1.0H; // expected-error{{invalid suffix 'H' on floating constant}}
--- /dev/null
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+
+constant half a = 1.0h;
+constant half aa = 1.0H;
+constant half b = 1.0hh; // expected-error{{invalid suffix 'hh' on floating constant}}
+constant half c = 1.0fh; // expected-error{{invalid suffix 'fh' on floating constant}}
+constant half d = 1.0lh; // expected-error{{invalid suffix 'lh' on floating constant}}
+constant half e = 1.0hf; // expected-error{{invalid suffix 'hf' on floating constant}}
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -Wno-unused-value
#pragma OPENCL EXTENSION cl_khr_fp16 : disable
+constant float f = 1.0h; // expected-error{{half precision constant requires cl_khr_fp16}}
half half_disabled(half *p, // expected-error{{declaring function return value of type 'half' is not allowed}}
half h) // expected-error{{declaring function parameter of type 'half' is not allowed}}
float c = 1.0f;
b = (half) c; // expected-error{{casting to type 'half' is not allowed}}
+ c = (float) 1.0h; // expected-error{{half precision constant requires cl_khr_fp16}}
+ b = 1.0h; // expected-error{{half precision constant requires cl_khr_fp16}}
half *allowed = &p[1];
half *allowed2 = &*p;
// Exactly the same as above but with the cl_khr_fp16 extension enabled.
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+constant half a = 1.0h;
half half_enabled(half *p, half h)
{
half a[2];
float c = 1.0f;
b = (half) c;
+ c = (float) 1.0h;
+ b = 1.0h;
half *allowed = &p[1];
half *allowed2 = &*p;