Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -124,6 +124,8 @@ InGroup; 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">, Index: include/clang/Lex/LiteralSupport.h =================================================================== --- include/clang/Lex/LiteralSupport.h +++ include/clang/Lex/LiteralSupport.h @@ -61,6 +61,7 @@ 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. Index: lib/Lex/LiteralSupport.cpp =================================================================== --- lib/Lex/LiteralSupport.cpp +++ lib/Lex/LiteralSupport.cpp @@ -522,6 +522,7 @@ isLong = false; isUnsigned = false; isLongLong = false; + isHalf = false; isFloat = false; isImaginary = false; MicrosoftInteger = 0; @@ -555,10 +556,18 @@ // 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': @@ -570,7 +579,7 @@ 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]) { @@ -647,6 +656,7 @@ isUnsigned = false; isLongLong = false; isFloat = false; + isHalf = false; isImaginary = false; MicrosoftInteger = 0; Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -3294,7 +3294,14 @@ 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; Index: test/Lexer/opencl-half-literal.cl =================================================================== --- /dev/null +++ test/Lexer/opencl-half-literal.cl @@ -0,0 +1,10 @@ +// 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}} Index: test/SemaOpenCL/half.cl =================================================================== --- test/SemaOpenCL/half.cl +++ test/SemaOpenCL/half.cl @@ -1,6 +1,7 @@ // 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}} @@ -12,6 +13,8 @@ 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; @@ -22,6 +25,7 @@ // 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]; @@ -31,6 +35,8 @@ float c = 1.0f; b = (half) c; + c = (float) 1.0h; + b = 1.0h; half *allowed = &p[1]; half *allowed2 = &*p; @@ -38,3 +44,7 @@ return h; } + +#pragma OPENCL EXTENSION cl_khr_fp16 : disable +constant float b = 1.0h; // expected-error{{half precision constant requires cl_khr_fp16}} +