Index: include/clang-c/Index.h =================================================================== --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -3115,8 +3115,9 @@ CXType_ObjCSel = 29, CXType_Float128 = 30, CXType_Half = 31, + CXType_Float16 = 32, CXType_FirstBuiltin = CXType_Void, - CXType_LastBuiltin = CXType_Half, + CXType_LastBuiltin = CXType_Float16, CXType_Complex = 100, CXType_Pointer = 101, Index: include/clang/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h +++ include/clang/AST/ASTContext.h @@ -973,6 +973,7 @@ CanQualType UnsignedLongLongTy, UnsignedInt128Ty; CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty; CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON + CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3 CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; CanQualType Float128ComplexTy; CanQualType VoidPtrTy, NullPtrTy; Index: include/clang/AST/BuiltinTypes.def =================================================================== --- include/clang/AST/BuiltinTypes.def +++ include/clang/AST/BuiltinTypes.def @@ -133,6 +133,9 @@ // 'long double' FLOATING_TYPE(LongDouble, LongDoubleTy) +// '_Float16' +FLOATING_TYPE(Float16, HalfTy) + // '__float128' FLOATING_TYPE(Float128, Float128Ty) Index: include/clang/Basic/Specifiers.h =================================================================== --- include/clang/Basic/Specifiers.h +++ include/clang/Basic/Specifiers.h @@ -52,6 +52,7 @@ TST_int, TST_int128, TST_half, // OpenCL half, ARM NEON __fp16 + TST_Float16, // C11 extension ISO/IEC TS 18661-3 TST_float, TST_double, TST_float128, Index: include/clang/Basic/TokenKinds.def =================================================================== --- include/clang/Basic/TokenKinds.def +++ include/clang/Basic/TokenKinds.def @@ -379,6 +379,9 @@ MODULES_KEYWORD(module) MODULES_KEYWORD(import) +// C11 Extension +KEYWORD(_Float16 , KEYALL) + // GNU Extensions (in impl-reserved namespace) KEYWORD(_Decimal32 , KEYALL) KEYWORD(_Decimal64 , KEYALL) Index: include/clang/Lex/LiteralSupport.h =================================================================== --- include/clang/Lex/LiteralSupport.h +++ include/clang/Lex/LiteralSupport.h @@ -65,6 +65,7 @@ bool isHalf : 1; // 1.0h bool isFloat : 1; // 1.0f bool isImaginary : 1; // 1.0i + bool isFloat16 : 1; // 1.0f16 bool isFloat128 : 1; // 1.0q uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64. Index: include/clang/Sema/DeclSpec.h =================================================================== --- include/clang/Sema/DeclSpec.h +++ include/clang/Sema/DeclSpec.h @@ -280,6 +280,7 @@ static const TST TST_half = clang::TST_half; static const TST TST_float = clang::TST_float; static const TST TST_double = clang::TST_double; + static const TST TST_float16 = clang::TST_Float16; static const TST TST_float128 = clang::TST_float128; static const TST TST_bool = clang::TST_bool; static const TST TST_decimal32 = clang::TST_decimal32; Index: include/clang/Serialization/ASTBitCodes.h =================================================================== --- include/clang/Serialization/ASTBitCodes.h +++ include/clang/Serialization/ASTBitCodes.h @@ -826,6 +826,8 @@ PREDEF_TYPE_OMP_ARRAY_SECTION = 42, /// \brief The '__float128' type PREDEF_TYPE_FLOAT128_ID = 43, + /// \brief The '_Float16' type + PREDEF_TYPE_FLOAT16_ID = 44, /// \brief OpenCL image types with auto numeration #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ PREDEF_TYPE_##Id##_ID, Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -57,7 +57,7 @@ unsigned ASTContext::NumImplicitDestructorsDeclared; enum FloatingRank { - HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank + Float16Rank, HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank }; RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { @@ -1093,6 +1093,9 @@ // GNU extension, __float128 for IEEE quadruple precision InitBuiltinType(Float128Ty, BuiltinType::Float128); + // C11 extension ISO/IEC TS 18661-3 + InitBuiltinType(Float16Ty, BuiltinType::Float16); + // GNU extension, 128-bit integers. InitBuiltinType(Int128Ty, BuiltinType::Int128); InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128); @@ -1420,7 +1423,9 @@ assert(BT && "Not a floating point type!"); switch (BT->getKind()) { default: llvm_unreachable("Not a floating point type!"); - case BuiltinType::Half: return Target->getHalfFormat(); + case BuiltinType::Float16: + case BuiltinType::Half: + return Target->getHalfFormat(); case BuiltinType::Float: return Target->getFloatFormat(); case BuiltinType::Double: return Target->getDoubleFormat(); case BuiltinType::LongDouble: return Target->getLongDoubleFormat(); @@ -1748,6 +1753,7 @@ Width = 128; Align = 128; // int128_t is 128-bit aligned on all targets. break; + case BuiltinType::Float16: case BuiltinType::Half: Width = Target->getHalfWidth(); Align = Target->getHalfAlign(); @@ -5047,6 +5053,7 @@ assert(T->getAs() && "getFloatingRank(): not a floating type"); switch (T->getAs()->getKind()) { default: llvm_unreachable("getFloatingRank(): not a floating type"); + case BuiltinType::Float16: return Float16Rank; case BuiltinType::Half: return HalfRank; case BuiltinType::Float: return FloatRank; case BuiltinType::Double: return DoubleRank; @@ -5064,6 +5071,7 @@ FloatingRank EltRank = getFloatingRank(Size); if (Domain->isComplexType()) { switch (EltRank) { + case Float16Rank: case HalfRank: llvm_unreachable("Complex half is not supported"); case FloatRank: return FloatComplexTy; case DoubleRank: return DoubleComplexTy; @@ -5074,6 +5082,7 @@ assert(Domain->isRealFloatingType() && "Unknown domain!"); switch (EltRank) { + case Float16Rank: return HalfTy; case HalfRank: return HalfTy; case FloatRank: return FloatTy; case DoubleRank: return DoubleTy; @@ -5931,6 +5940,7 @@ case BuiltinType::LongDouble: return 'D'; case BuiltinType::NullPtr: return '*'; // like char* + case BuiltinType::Float16: case BuiltinType::Float128: case BuiltinType::Half: // FIXME: potentially need @encodes for these! Index: lib/AST/ItaniumMangle.cpp =================================================================== --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -2392,6 +2392,7 @@ // UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits) // UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits) // ::= Dh # IEEE 754r half-precision floating point (16 bits) + // ::= DF _ # ISO/IEC TS 18661 binary floating point type _FloatN (N bits); // ::= Di # char32_t // ::= Ds # char16_t // ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) @@ -2454,6 +2455,9 @@ case BuiltinType::Int128: Out << 'n'; break; + case BuiltinType::Float16: + Out << "DF16_"; + break; case BuiltinType::Half: Out << "Dh"; break; Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -1866,6 +1866,7 @@ Out << "$$T"; break; + case BuiltinType::Float16: case BuiltinType::Float128: case BuiltinType::Half: { DiagnosticsEngine &Diags = Context.getDiags(); Index: lib/AST/NSAPI.cpp =================================================================== --- lib/AST/NSAPI.cpp +++ lib/AST/NSAPI.cpp @@ -441,6 +441,7 @@ case BuiltinType::Int128: case BuiltinType::LongDouble: case BuiltinType::UInt128: + case BuiltinType::Float16: case BuiltinType::Float128: case BuiltinType::NullPtr: case BuiltinType::ObjCClass: Index: lib/AST/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -1500,6 +1500,7 @@ default: llvm_unreachable("Unexpected type for float literal!"); case BuiltinType::Half: break; // FIXME: suffix? case BuiltinType::Double: break; // no suffix. + case BuiltinType::Float16: OS << "F16"; break; case BuiltinType::Float: OS << 'F'; break; case BuiltinType::LongDouble: OS << 'L'; break; case BuiltinType::Float128: OS << 'Q'; break; Index: lib/AST/Type.cpp =================================================================== --- lib/AST/Type.cpp +++ lib/AST/Type.cpp @@ -2564,6 +2564,8 @@ return "double"; case LongDouble: return "long double"; + case Float16: + return "_Float16"; case Float128: return "__float128"; case WChar_S: Index: lib/AST/TypeLoc.cpp =================================================================== --- lib/AST/TypeLoc.cpp +++ lib/AST/TypeLoc.cpp @@ -319,6 +319,7 @@ case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: + case BuiltinType::Float16: case BuiltinType::Float128: llvm_unreachable("Builtin type needs extra local data!"); // Fall through, if the impossible happens. Index: lib/Analysis/PrintfFormatString.cpp =================================================================== --- lib/Analysis/PrintfFormatString.cpp +++ lib/Analysis/PrintfFormatString.cpp @@ -654,6 +654,7 @@ case BuiltinType::UInt128: case BuiltinType::Int128: case BuiltinType::Half: + case BuiltinType::Float16: case BuiltinType::Float128: // Various types which are non-trivial to correct. return false; Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -667,6 +667,7 @@ case BuiltinType::Half: case BuiltinType::Float: case BuiltinType::LongDouble: + case BuiltinType::Float16: case BuiltinType::Float128: case BuiltinType::Double: // FIXME: For targets where long double and __float128 have the same size, Index: lib/CodeGen/CGExprScalar.cpp =================================================================== --- lib/CodeGen/CGExprScalar.cpp +++ lib/CodeGen/CGExprScalar.cpp @@ -1778,7 +1778,7 @@ } case CK_IntToOCLSampler: - return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF); + return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF); } // end of switch Index: lib/CodeGen/CodeGenTypes.cpp =================================================================== --- lib/CodeGen/CodeGenTypes.cpp +++ lib/CodeGen/CodeGenTypes.cpp @@ -439,6 +439,12 @@ static_cast(Context.getTypeSize(T))); break; + case BuiltinType::Float16: + ResultType = + getTypeForFormat(getLLVMContext(), Context.getFloatTypeSemantics(T), + /* UseNativeHalf = */ true); + break; + case BuiltinType::Half: // Half FP can either be storage-only (lowered to i16) or native. ResultType = Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -2654,6 +2654,7 @@ case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: + case BuiltinType::Float16: case BuiltinType::Float128: case BuiltinType::Char16: case BuiltinType::Char32: Index: lib/Format/FormatToken.cpp =================================================================== --- lib/Format/FormatToken.cpp +++ lib/Format/FormatToken.cpp @@ -52,6 +52,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Float16: case tok::kw___float128: case tok::kw_wchar_t: case tok::kw_bool: Index: lib/Index/USRGeneration.cpp =================================================================== --- lib/Index/USRGeneration.cpp +++ lib/Index/USRGeneration.cpp @@ -680,6 +680,7 @@ c = 'K'; break; case BuiltinType::Int128: c = 'J'; break; + case BuiltinType::Float16: case BuiltinType::Half: c = 'h'; break; case BuiltinType::Float: Index: lib/Lex/LiteralSupport.cpp =================================================================== --- lib/Lex/LiteralSupport.cpp +++ lib/Lex/LiteralSupport.cpp @@ -544,6 +544,7 @@ isHalf = false; isFloat = false; isImaginary = false; + isFloat16 = false; isFloat128 = false; MicrosoftInteger = 0; hadError = false; @@ -588,6 +589,13 @@ if (!isFPConstant) break; // Error for integer constant. if (isHalf || isFloat || isLong || isFloat128) break; // HF, FF, LF, QF invalid. + + if (s + 2 < ThisTokEnd && s[1] == '1' && s[2] == '6') { + s += 2; // success, eat up 2 characters. + isFloat16 = true; + continue; + } + isFloat = true; continue; // Success. case 'q': // FP Suffix for "__float128" @@ -681,6 +689,7 @@ isUnsigned = false; isLongLong = false; isFloat = false; + isFloat16 = false; isHalf = false; isImaginary = false; MicrosoftInteger = 0; Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -3510,6 +3510,10 @@ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw__Float16: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float16, Loc, PrevSpec, + DiagID, Policy); + break; case tok::kw___float128: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, DiagID, Policy); @@ -4513,6 +4517,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: case tok::kw__Bool: @@ -4588,6 +4593,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: case tok::kw__Bool: @@ -4744,6 +4750,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: case tok::kw__Bool: Index: lib/Parse/ParseExpr.cpp =================================================================== --- lib/Parse/ParseExpr.cpp +++ lib/Parse/ParseExpr.cpp @@ -1229,6 +1229,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Float16: case tok::kw___float128: case tok::kw_void: case tok::kw_typename: Index: lib/Parse/ParseExprCXX.cpp =================================================================== --- lib/Parse/ParseExprCXX.cpp +++ lib/Parse/ParseExprCXX.cpp @@ -1928,6 +1928,9 @@ case tok::kw_double: DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw__Float16: + DS.SetTypeSpecType(DeclSpec::TST_float16, Loc, PrevSpec, DiagID, Policy); + break; case tok::kw___float128: DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, DiagID, Policy); break; Index: lib/Parse/ParseTentative.cpp =================================================================== --- lib/Parse/ParseTentative.cpp +++ lib/Parse/ParseTentative.cpp @@ -1026,6 +1026,7 @@ case tok::kw_char: case tok::kw_const: case tok::kw_double: + case tok::kw__Float16: case tok::kw___float128: case tok::kw_enum: case tok::kw_half: @@ -1510,6 +1511,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Float16: case tok::kw___float128: case tok::kw_void: case tok::annot_decltype: @@ -1600,6 +1602,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Float16: case tok::kw___float128: case tok::kw_void: case tok::kw___unknown_anytype: Index: lib/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -336,6 +336,7 @@ case TST_decimal32: case TST_decimal64: case TST_double: + case TST_Float16: case TST_float128: case TST_enum: case TST_error: @@ -505,6 +506,7 @@ case DeclSpec::TST_half: return "half"; case DeclSpec::TST_float: return "float"; case DeclSpec::TST_double: return "double"; + case DeclSpec::TST_float16: return "_Float16"; case DeclSpec::TST_float128: return "__float128"; case DeclSpec::TST_bool: return Policy.Bool ? "bool" : "_Bool"; case DeclSpec::TST_decimal32: return "_Decimal32"; Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -132,6 +132,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Float16: case tok::kw___float128: case tok::kw_wchar_t: case tok::kw_bool: Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -722,8 +722,10 @@ return ExprError(); E = Res.get(); - // If this is a 'float' or '__fp16' (CVR qualified or typedef) promote to - // double. + // If this is a 'float' or '__fp16' (CVR qualified or typedef) + // promote to double. + // Note that there is default argument promotion for '_Float16'; this + // applies to the standard floating types only. const BuiltinType *BTy = Ty->getAs(); if (BTy && (BTy->getKind() == BuiltinType::Half || BTy->getKind() == BuiltinType::Float)) { @@ -3329,6 +3331,8 @@ Ty = Context.FloatTy; else if (Literal.isLong) Ty = Context.LongDoubleTy; + else if (Literal.isFloat16) + Ty = Context.Float16Ty; else if (Literal.isFloat128) Ty = Context.Float128Ty; else Index: lib/Sema/SemaTemplateVariadic.cpp =================================================================== --- lib/Sema/SemaTemplateVariadic.cpp +++ lib/Sema/SemaTemplateVariadic.cpp @@ -819,6 +819,7 @@ case TST_half: case TST_float: case TST_double: + case TST_Float16: case TST_float128: case TST_bool: case TST_decimal32: Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -1392,8 +1392,9 @@ else Result = Context.Int128Ty; break; - case DeclSpec::TST_half: Result = Context.HalfTy; break; - case DeclSpec::TST_float: Result = Context.FloatTy; break; + case DeclSpec::TST_float16: Result = Context.Float16Ty; break; + case DeclSpec::TST_half: Result = Context.HalfTy; break; + case DeclSpec::TST_float: Result = Context.FloatTy; break; case DeclSpec::TST_double: if (DS.getTypeSpecWidth() == DeclSpec::TSW_long) Result = Context.LongDoubleTy; Index: lib/Serialization/ASTCommon.cpp =================================================================== --- lib/Serialization/ASTCommon.cpp +++ lib/Serialization/ASTCommon.cpp @@ -91,6 +91,9 @@ case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break; + case BuiltinType::Float16: + ID = PREDEF_TYPE_FLOAT16_ID; + break; case BuiltinType::Float128: ID = PREDEF_TYPE_FLOAT128_ID; break; Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -6661,6 +6661,9 @@ case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break; + case PREDEF_TYPE_FLOAT16_ID: + T = Context.Float16Ty; + break; case PREDEF_TYPE_FLOAT128_ID: T = Context.Float128Ty; break; Index: test/CodeGenCXX/float16-declarations.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/float16-declarations.cpp @@ -0,0 +1,156 @@ +// RUN: %clang -std=c++11 --target=aarch64-arm--eabi -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH64 +// RUN: %clang -std=c++11 --target=x86_64 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X86 + +/* Various contexts where type _Float16 can appear. */ + + +/* Namespace */ + +namespace { + _Float16 f1n; +// CHECK-DAG: @_ZN12_GLOBAL__N_13f1nE = internal global half 0xH0000, align 2 + + _Float16 f2n = 33.f16; +// CHECK-AARCH64-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global half 0xH5020, align 2 +// CHECK-X86-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global i16 20512, align 2 + + _Float16 arr1n[10]; +// CHECK-AARCH64-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x half] zeroinitializer, align 2 +// CHECK-X86-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x half] zeroinitializer, align 16 + + _Float16 arr2n[] = { 1.2, 3.0, 3.e4 }; +// CHECK-AARCH64-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x half] [half 0xH3CCD, half 0xH4200, half 0xH7753], align 2 +// CHECK-X86-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x i16] [i16 15565, i16 16896, i16 30547], align 2 + + const volatile _Float16 func1n(const _Float16 &arg) { + return arg + f2n + arr1n[4] - arr2n[1]; + } +} + + +/* File */ + +_Float16 f1f; +// CHECK-AARCH64-DAG: @f1f = global half 0xH0000, align 2 +// CHECK-X86-DAG: @f1f = global half 0xH0000, align 2 + +_Float16 f2f = 32.4; +// CHECK-AARCH64-DAG: @f2f = global half 0xH500D, align 2 +// CHECK-X86-DAG: @f2f = global i16 20493, align 2 + +_Float16 arr1f[10]; +// CHECK-AARCH64-DAG: @arr1f = global [10 x half] zeroinitializer, align 2 +// CHECK-X86-DAG: @arr1f = global [10 x half] zeroinitializer, align 16 + +_Float16 arr2f[] = { -1.2, -3.0, -3.e4 }; +// CHECK-AARCH64-DAG: @arr2f = global [3 x half] [half 0xHBCCD, half 0xHC200, half 0xHF753], align 2 +// CHECK-X86-DAG: @arr2f = global [3 x i16] [i16 -17203, i16 -15872, i16 -2221], align 2 + +_Float16 func1f(_Float16 arg); + + +/* Class */ + +class C1 { + _Float16 f1c; + + static const _Float16 f2c; +// CHECK-DAG: @_ZN2C13f2cE = external constant half, align 2 + + volatile _Float16 f3c; + +public: + C1(_Float16 arg) : f1c(arg), f3c(arg) { } +// Check that we mangle _Float16 to DF16_ +// CHECK-DAG: define linkonce_odr void @_ZN2C1C2EDF16_(%class.C1* %this, half %arg) + + _Float16 func1c(_Float16 arg ) { + return f1c + arg; + } +// CHECK-DAG: define linkonce_odr half @_ZN2C16func1cEDF16_(%class.C1* %this, half %arg) + + static _Float16 func2c(_Float16 arg) { + return arg * C1::f2c; + } +// CHECK-DAG: define linkonce_odr half @_ZN2C16func2cEDF16_(half %arg) +}; + +/* Template */ + +template C func1t(C arg) { + return arg * 2.f16; +} +// CHECK-DAG: define linkonce_odr half @_Z6func1tIDF16_ET_S0_(half %arg) + +template struct S1 { + C mem1; +}; + +template <> struct S1<_Float16> { + _Float16 mem2; +}; + + +/* Local */ + +extern int printf (const char *__restrict __format, ...); + +int main(void) { + _Float16 f1l = 1e3f16; +// CHECK-DAG: store half 0xH63D0, half* %f1l, align 2 + + _Float16 f2l = -0.f16; +// CHECK-DAG: store half 0xH8000, half* %f2l, align 2 + + _Float16 f3l = 1.000976562; +// CHECK-DAG: store half 0xH3C01, half* %f3l, align 2 + + C1 c1(f1l); +// CHECK-DAG: [[F1L:%[a-z0-9]+]] = load half, half* %f1l, align 2 +// CHECK-DAG: call void @_ZN2C1C2EDF16_(%class.C1* %c1, half [[F1L]]) + + S1<_Float16> s1 = { 132.f16 }; +// CHECK-AARCH64-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { half 0xH5820 }, align 2 +// CHECK-X86-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant { i16 } { i16 22560 }, align 2 +// CHECK-DAG: [[S1:%[0-9]+]] = bitcast %struct.S1* %s1 to i8* +// CHECK-AARCH64-DAG: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[S1]], i8* bitcast (%struct.S1* @_ZZ4mainE2s1 to i8*), i64 2, i32 2, i1 false) +// CHECK-X86-DAG: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* bitcast ({ i16 }* @_ZZ4mainE2s1 to i8*), i64 2, i32 2, i1 false) + + _Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) + + func1t(f1l) + s1.mem2 - f1n + f2n; + + auto f5l = -1.f16, *f6l = &f2l, f7l = func1t(f3l); +// CHECK-DAG: store half 0xHBC00, half* %f5l, align 2 +// CHECK-DAG: store half* %f2l, half** %f6l, align 8 + + _Float16 f8l = f4l++; +// CHECK-DAG: [[F4L:%[a-z0-9]+]] = load half, half* %f4l, align 2 +// CHECK-DAG: [[INC:%inc[0-9]*]] = fadd half [[F4L]], 0xH3C00 +// CHECK-DAG: store half [[INC]], half* %f4l, align 2 + + _Float16 arr1l[] = { -1.f16, -0.f16, -11.f16 }; +// CHECK-AARCH64-DAG: @_ZZ4mainE5arr1l = private unnamed_addr constant [3 x half] [half 0xHBC00, half 0xH8000, half 0xHC980], align 2 +// CHECK-X86-DAG: @_ZZ4mainE5arr1l = private unnamed_addr constant [3 x i16] [i16 -17408, i16 -32768, i16 -13952], align 2 + + float cvtf = f2n; +//CHECK-DAG: [[H2F:%conv[0-9]*]] = fpext half {{%[0-9]+}} to float +//CHECK-DAG: store float [[H2F]], float* %cvtf, align 4 + + double cvtd = f2n; +//CHECK-DAG: [[H2D:%conv[0-9]*]] = fpext half {{%[0-9]+}} to double +//CHECK-DAG: store double [[H2D]], double* %cvtd, align 8 + + + long double cvtld = f2n; +//CHECK-AARCh64-DAG: [[H2LD:%conv[0-9]*]] = fpext half {{%[0-9]+}} to fp128 +//CHECK-AARCh64-DAG: store fp128 [[H2LD]], fp128* %cvtld, align 16 +//CHECK-X86-DAG: [[H2LD:%conv[0-9]+]] = fpext half {{%[0-9]+}} to x86_fp80 +//CHECK-X86-DAG: store x86_fp80 [[H2LD]], x86_fp80* %cvtld, align 16 + + _Float16 f2h = 42.0f; +//CHECK-DAG: store half 0xH5140, half* %f2h, align 2 + _Float16 d2h = 42.0; +//CHECK-DAG: store half 0xH5140, half* %d2h, align 2 + _Float16 ld2h = 42.0l; +//CHECK-DAG:store half 0xH5140, half* %ld2h, align 2 +} Index: test/Frontend/float16.cpp =================================================================== --- /dev/null +++ test/Frontend/float16.cpp @@ -0,0 +1,326 @@ +// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -ast-dump -fnative-half-type %s | FileCheck %s --check-prefix=CHECK-NATIVE + +/* Various contexts where type _Float16 can appear. */ + +/* Namespace */ +namespace { + _Float16 f1n; + _Float16 f2n = 33.f16; + _Float16 arr1n[10]; + _Float16 arr2n[] = { 1.2, 3.0, 3.e4 }; + const volatile _Float16 func1n(const _Float16 &arg) { + return arg + f2n + arr1n[4] - arr2n[1]; + } +} + +//CHECK: |-NamespaceDecl +//CHECK: | |-VarDecl {{.*}} f1n '_Float16' +//CHECK: | |-VarDecl {{.*}} f2n '_Float16' cinit +//CHECK: | | `-FloatingLiteral {{.*}} '_Float16' 3.300000e+01 +//CHECK: | |-VarDecl {{.*}} arr1n '_Float16 [10]' +//CHECK: | |-VarDecl {{.*}} arr2n '_Float16 [3]' cinit +//CHECK: | | `-InitListExpr {{.*}} '_Float16 [3]' +//CHECK: | | |-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00 +//CHECK: | | |-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00 +//CHECK: | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+04 +//CHECK: | `-FunctionDecl {{.*}} func1n 'const volatile _Float16 (const _Float16 &)' + +/* File */ +_Float16 f1f; +_Float16 f2f = 32.4; +_Float16 arr1f[10]; +_Float16 arr2f[] = { -1.2, -3.0, -3.e4 }; +_Float16 func1f(_Float16 arg); + +//CHECK: |-VarDecl {{.*}} f1f '_Float16' +//CHECK: |-VarDecl {{.*}} f2f '_Float16' cinit +//CHECK: | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | `-FloatingLiteral {{.*}} 'double' 3.240000e+01 +//CHECK: |-VarDecl {{.*}} arr1f '_Float16 [10]' +//CHECK: |-VarDecl {{.*}} arr2f '_Float16 [3]' cinit +//CHECK: | `-InitListExpr {{.*}} '_Float16 [3]' +//CHECK: | |-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | `-UnaryOperator {{.*}} 'double' prefix '-' +//CHECK: | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00 +//CHECK: | |-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | `-UnaryOperator {{.*}} 'double' prefix '-' +//CHECK: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00 +//CHECK: | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | `-UnaryOperator {{.*}} 'double' prefix '-' +//CHECK: | `-FloatingLiteral {{.*}} 'double' 3.000000e+04 +//CHECK: |-FunctionDecl {{.*}} func1f '_Float16 (_Float16)' +//CHECK: | `-ParmVarDecl {{.*}} arg '_Float16' + + +// Mixing __fp16 and Float16 types: +// The _Float16 type is first converted to __fp16 type and then the operation +// is completed as if both operands were of __fp16 type. + +__fp16 B = -0.1; +auto C = -1.0f16 + B; + +// When we do *not* have native half types, we expect __fp16 to be promoted to +// float, and consequently also _Float16 promotions to float: + +//CHECK: -VarDecl {{.*}} used B '__fp16' cinit +//CHECK: | `-ImplicitCastExpr {{.*}} '__fp16' +//CHECK: | `-UnaryOperator {{.*}} 'double' prefix '-' +//CHECK: | `-FloatingLiteral {{.*}} 'double' 1.000000e-01 +//CHECK: |-VarDecl {{.*}} C 'float':'float' cinit +//CHECK: | `-BinaryOperator {{.*}} 'float' '+' +//CHECK: | |-ImplicitCastExpr {{.*}} 'float' +//CHECK: | | `-UnaryOperator {{.*}} '_Float16' prefix '-' +//CHECK: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00 +//CHECK: | `-ImplicitCastExpr {{.*}} 'float' +//CHECK: | `-ImplicitCastExpr {{.*}} '__fp16' +//CHECK: | `-DeclRefExpr {{.*}} '__fp16' lvalue Var 0x{{.*}} 'B' '__fp16' + +// When do have native half types, we expect to see promotions to fp16: + +//CHECK-NATIVE: |-VarDecl {{.*}} used B '__fp16' cinit +//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' +//CHECK-NATIVE: | `-UnaryOperator {{.*}} 'double' prefix '-' +//CHECK-NATIVE: | `-FloatingLiteral {{.*}} 'double' 1.000000e-01 +//CHECK-NATIVE: |-VarDecl {{.*}} C '__fp16':'__fp16' cinit +//CHECK-NATIVE: | `-BinaryOperator {{.*}} '__fp16' '+' +//CHECK-NATIVE: | |-ImplicitCastExpr {{.*}} '__fp16' +//CHECK-NATIVE: | | `-UnaryOperator {{.*}} '_Float16' prefix '-' +//CHECK-NATIVE: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00 +//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' +//CHECK-NATIVE: | `-DeclRefExpr {{.*}} '__fp16' lvalue Var 0x{{.*}} 'B' '__fp16' + + +/* Class */ + +class C1 { + _Float16 f1c; + static const _Float16 f2c; + volatile _Float16 f3c; +public: + C1(_Float16 arg) : f1c(arg), f3c(arg) { } + _Float16 func1c(_Float16 arg ) { + return f1c + arg; + } + static _Float16 func2c(_Float16 arg) { + return arg * C1::f2c; + } +}; + +//CHECK: |-CXXRecordDecl {{.*}} referenced class C1 definition +//CHECK: | |-CXXRecordDecl {{.*}} implicit referenced class C1 +//CHECK: | |-FieldDecl {{.*}} referenced f1c '_Float16' +//CHECK: | |-VarDecl {{.*}} used f2c 'const _Float16' static +//CHECK: | |-FieldDecl {{.*}} f3c 'volatile _Float16' +//CHECK: | |-AccessSpecDecl +//CHECK: | |-CXXConstructorDecl {{.*}} used C1 'void (_Float16)' +//CHECK: | | |-ParmVarDecl {{.*}} used arg '_Float16' +//CHECK: | | |-CXXCtorInitializer Field {{.*}} 'f1c' '_Float16' +//CHECK: | | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16' +//CHECK: | | |-CXXCtorInitializer Field {{.*}} 'f3c' 'volatile _Float16' +//CHECK: | | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16' +//CHECK: | | `-CompoundStmt +//CHECK: | |-CXXMethodDecl {{.*}} used func1c '_Float16 (_Float16)' +//CHECK: | | |-ParmVarDecl {{.*}} used arg '_Float16' +//CHECK: | | `-CompoundStmt +//CHECK: | | `-ReturnStmt +//CHECK: | | `-BinaryOperator {{.*}} '_Float16' '+' +//CHECK: | | |-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | | `-MemberExpr {{.*}} '_Float16' lvalue ->f1c 0x{{.*}} +//CHECK: | | | `-CXXThisExpr {{.*}} 'class C1 *' this +//CHECK: | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16' +//CHECK: | |-CXXMethodDecl {{.*}} used func2c '_Float16 (_Float16)' static +//CHECK: | | |-ParmVarDecl {{.*}} used arg '_Float16' +//CHECK: | | `-CompoundStmt +//CHECK: | | `-ReturnStmt +//CHECK: | | `-BinaryOperator {{.*}} '_Float16' '*' +//CHECK: | | |-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16' +//CHECK: | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | `-DeclRefExpr {{.*}} 'const _Float16' lvalue Var 0x{{.*}} 'f2c' 'const _Float16' + + +/* Template */ + +template C func1t(C arg) { + return arg * 2.f16; +} + +//CHECK: |-FunctionTemplateDecl {{.*}} func1t +//CHECK: | |-TemplateTypeParmDecl {{.*}} C +//CHECK: | |-FunctionDecl {{.*}} func1t 'C (C)' +//CHECK: | | |-ParmVarDecl {{.*}} referenced arg 'C' +//CHECK: | | `-CompoundStmt +//CHECK: | | `-ReturnStmt +//CHECK: | | `-BinaryOperator {{.*}} '' '*' +//CHECK: | | |-DeclRefExpr {{.*}} 'C' lvalue ParmVar {{.*}} 'arg' 'C' +//CHECK: | | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00 +//CHECK: | `-FunctionDecl {{.*}} used func1t '_Float16 (_Float16)' +//CHECK: | |-TemplateArgument type '_Float16' +//CHECK: | |-ParmVarDecl {{.*}} used arg '_Float16':'_Float16' +//CHECK: | `-CompoundStmt +//CHECK: | `-ReturnStmt +//CHECK: | `-BinaryOperator {{.*}} '_Float16' '*' +//CHECK: | |-ImplicitCastExpr {{.*}} '_Float16':'_Float16' +//CHECK: | | `-DeclRefExpr {{.*}} '_Float16':'_Float16' lvalue ParmVar {{.*}} 'arg' '_Float16':'_Float16' +//CHECK: | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00 + + +template struct S1 { + C mem1; +}; + +//CHECK: |-ClassTemplateDecl {{.*}} S1 +//CHECK: | |-TemplateTypeParmDecl {{.*}} referenced class depth 0 index 0 C +//CHECK: | |-CXXRecordDecl {{.*}} struct S1 definition +//CHECK: | | |-CXXRecordDecl {{.*}} implicit struct S1 +//CHECK: | | `-FieldDecl {{.*}} mem1 'C' +//CHECK: | `-ClassTemplateSpecialization {{.*}} 'S1' + +template <> struct S1<_Float16> { + _Float16 mem2; +}; + + +/* Local */ + +extern int printf (const char *__restrict __format, ...); + +int main(void) { + _Float16 f1l = 1e3f16; +//CHECK: | `-VarDecl {{.*}} used f1l '_Float16' cinit +//CHECK-NEXT:| `-FloatingLiteral {{.*}} '_Float16' 1.000000e+03 + + _Float16 f2l = -0.f16; +//CHECK: | `-VarDecl {{.*}} used f2l '_Float16' cinit +//CHECK: | `-UnaryOperator {{.*}} '_Float16' prefix '-' +//CHECK: | `-FloatingLiteral {{.*}} '_Float16' 0.000000e+00 + + _Float16 f3l = 1.000976562; +//CHECK: | `-VarDecl {{.*}} used f3l '_Float16' cinit +//CHECK: | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | `-FloatingLiteral {{.*}} 'double' 1.000977e+00 + + C1 c1(f1l); +//CHECK: | `-VarDecl{{.*}} used c1 'class C1' callinit +//CHECK: | `-CXXConstructExpr {{.*}} 'class C1' 'void (_Float16)' +//CHECK: | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var 0x{{.*}} 'f1l' '_Float16' + + S1<_Float16> s1 = { 132.f16 }; +//CHECK: | `-VarDecl {{.*}} used s1 'S1<_Float16>':'struct S1<_Float16>' cinit +//CHECK: | `-InitListExpr {{.*}} 'S1<_Float16>':'struct S1<_Float16>' +//CHECK: | `-FloatingLiteral {{.*}} '_Float16' 1.320000e+02 + + _Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) + + func1t(f1l) + s1.mem2 - f1n + f2n; +//CHECK: | `-VarDecl {{.*}} used f4l '_Float16' cinit +//CHECK: | `-BinaryOperator {{.*}} '_Float16' '+' +//CHECK: | |-BinaryOperator {{.*}} '_Float16' '-' +//CHECK: | | |-BinaryOperator {{.*}} '_Float16' '+' +//CHECK: | | | |-BinaryOperator {{.*}} '_Float16' '+' +//CHECK: | | | | |-BinaryOperator {{.*}} '_Float16' '+' +//CHECK: | | | | | |-BinaryOperator {{.*}} '_Float16' '+' +//CHECK: | | | | | | |-BinaryOperator {{.*}} '_Float16' '+' +//CHECK: | | | | | | | |-CallExpr {{.*}} '_Float16' +//CHECK: | | | | | | | | |-ImplicitCastExpr {{.*}} 'const volatile _Float16 (*)(const _Float16 &)' +//CHECK: | | | | | | | | | `-DeclRefExpr {{.*}} 'const volatile _Float16 (const _Float16 &)' lvalue Function {{.*}} 'func1n' 'const volatile _Float16 (const _Float16 &)' +//CHECK: | | | | | | | | `-ImplicitCastExpr {{.*}} 'const _Float16' lvalue +//CHECK: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16' +//CHECK: | | | | | | | `-CallExpr {{.*}} '_Float16' +//CHECK: | | | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' +//CHECK: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1f' '_Float16 (_Float16)' +//CHECK: | | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16' +//CHECK: | | | | | | `-CXXMemberCallExpr {{.*}} '_Float16' +//CHECK: | | | | | | |-MemberExpr {{.*}} '' .func1c {{.*}} +//CHECK: | | | | | | | `-DeclRefExpr {{.*}} 'class C1' lvalue Var {{.*}} 'c1' 'class C1' +//CHECK: | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16' +//CHECK: | | | | | `-CallExpr {{.*}} '_Float16' +//CHECK: | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' +//CHECK: | | | | | | `-MemberExpr {{.*}} '_Float16 (_Float16)' lvalue .func2c {{.*}} +//CHECK: | | | | | | `-DeclRefExpr {{.*}} 'class C1' lvalue Var {{.*}} 'c1' 'class C1' +//CHECK: | | | | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16' +//CHECK: | | | | `-CallExpr {{.*}} '_Float16':'_Float16' +//CHECK: | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' +//CHECK: | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t') +//CHECK: | | | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16' +//CHECK: | | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | | `-MemberExpr {{.*}} '_Float16' lvalue .mem2 {{.*}} +//CHECK: | | | `-DeclRefExpr {{.*}} 'S1<_Float16>':'struct S1<_Float16>' lvalue Var {{.*}} 's1' 'S1<_Float16>':'struct S1<_Float16>' +//CHECK: | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1n' '_Float16' +//CHECK: | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16' + + auto f5l = -1.f16, *f6l = &f2l, f7l = func1t(f3l); +//CHECK: | |-VarDecl {{.*}} f5l '_Float16':'_Float16' cinit +//CHECK: | | `-UnaryOperator {{.*}} '_Float16' prefix '-' +//CHECK: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00 +//CHECK: | |-VarDecl {{.*}} f6l '_Float16 *' cinit +//CHECK: | | `-UnaryOperator {{.*}} '_Float16 *' prefix '&' +//CHECK: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16' +//CHECK: | `-VarDecl {{.*}} f7l '_Float16':'_Float16' cinit +//CHECK: | `-CallExpr {{.*}} '_Float16':'_Float16' +//CHECK: | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' +//CHECK: | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t') +//CHECK: | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16' + + _Float16 f8l = f4l++; +//CHECK: | `-VarDecl {{.*}} f8l '_Float16' cinit +//CHECK: | `-UnaryOperator {{.*}} '_Float16' postfix '++' +//CHECK: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f4l' '_Float16' + + _Float16 arr1l[] = { -1.f16, -0.f16, -11.f16 }; +//CHECK: `-VarDecl {{.*}} arr1l '_Float16 [3]' cinit +//CHECK: `-InitListExpr {{.*}} '_Float16 [3]' +//CHECK: |-UnaryOperator {{.*}} '_Float16' prefix '-' +//CHECK: | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00 +//CHECK: |-UnaryOperator {{.*}} '_Float16' prefix '-' +//CHECK: | `-FloatingLiteral {{.*}} '_Float16' 0.000000e+00 +//CHECK: `-UnaryOperator {{.*}} '_Float16' prefix '-' +//CHECK: `-FloatingLiteral {{.*}} '_Float16' 1.100000e+01 + + float cvtf = f2n; +//CHECK: `-VarDecl {{.*}} cvtf 'float' cinit +//CHECK: `-ImplicitCastExpr {{.*}} 'float' +//CHECK: `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16' + + double cvtd = f2n; +//CHECK: `-VarDecl {{.*}} cvtd 'double' cinit +//CHECK: `-ImplicitCastExpr {{.*}} 'double' +//CHECK: `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16' + + long double cvtld = f2n; +//CHECK: `-VarDecl {{.*}} cvtld 'long double' cinit +//CHECK: `-ImplicitCastExpr {{.*}} 'long double' +//CHECK: `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16' + + _Float16 f2h = 42.0f; +//CHECK: `-VarDecl {{.*}} f2h '_Float16' cinit +//CHECK: `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: `-FloatingLiteral {{.*}} 'float' 4.200000e+01 + + _Float16 d2h = 42.0; +//CHECK: `-VarDecl {{.*}} d2h '_Float16' cinit +//CHECK: `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: `-FloatingLiteral {{.*}} 'double' 4.200000e+01 + + _Float16 ld2h = 42.0l; +//CHECK: `-VarDecl {{.*}} ld2h '_Float16' cinit +//CHECK: `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK: `-FloatingLiteral {{.*}} 'long double' 4.200000e+01 +} Index: test/Lexer/half-literal.cpp =================================================================== --- test/Lexer/half-literal.cpp +++ test/Lexer/half-literal.cpp @@ -1,3 +1,6 @@ // 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}} + +_Float16 c = 1.f166; // expected-error{{invalid suffix 'f166' on floating constant}} +_Float16 d = 1.f1; // expected-error{{invalid suffix 'f1' on floating constant}} Index: tools/libclang/CXType.cpp =================================================================== --- tools/libclang/CXType.cpp +++ tools/libclang/CXType.cpp @@ -53,6 +53,7 @@ BTCASE(Float); BTCASE(Double); BTCASE(LongDouble); + BTCASE(Float16); BTCASE(Float128); BTCASE(NullPtr); BTCASE(Overload); @@ -520,7 +521,7 @@ TKIND(Char_U); TKIND(UChar); TKIND(Char16); - TKIND(Char32); + TKIND(Char32); TKIND(UShort); TKIND(UInt); TKIND(ULong); @@ -538,6 +539,7 @@ TKIND(Float); TKIND(Double); TKIND(LongDouble); + TKIND(Float16); TKIND(Float128); TKIND(NullPtr); TKIND(Overload);