diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 28 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateVariadic.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 32 |
7 files changed, 71 insertions, 12 deletions
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 3564f2657b0..f0a763e4ecf 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -257,6 +257,7 @@ bool Declarator::isDeclarationOfFunction() const { case TST_enum: case TST_error: case TST_float: + case TST_half: case TST_int: case TST_struct: case TST_union: @@ -373,6 +374,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { case DeclSpec::TST_char16: return "char16_t"; case DeclSpec::TST_char32: return "char32_t"; case DeclSpec::TST_int: return "int"; + case DeclSpec::TST_half: return "half"; case DeclSpec::TST_float: return "float"; case DeclSpec::TST_double: return "double"; case DeclSpec::TST_bool: return "_Bool"; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 71b3c526a16..8d993ef6103 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4729,7 +4729,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, diag::err_object_cannot_be_passed_returned_by_value) << 0 << R->getAs<FunctionType>()->getResultType() << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*"); - + QualType T = R->getAs<FunctionType>()->getResultType(); T = Context.getObjCObjectPointerType(T); if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(R)) { @@ -4740,7 +4740,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, else if (isa<FunctionNoProtoType>(R)) R = Context.getFunctionNoProtoType(T); } - + bool isFriend = false; FunctionTemplateDecl *FunctionTemplate = 0; bool isExplicitSpecialization = false; @@ -5065,6 +5065,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, assert(R->isFunctionNoProtoType() && NewFD->getNumParams() == 0 && "Should not need args for typedef of non-prototype fn"); } + // Finally, we know we have the right number of parameters, install them. NewFD->setParams(Params); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 41fcf7299db..170097cc59a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -396,12 +396,14 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // C99 6.3.2.1p2: // If the lvalue has qualified type, the value has the unqualified // version of the type of the lvalue; otherwise, the value has the - // type of the lvalue. + // type of the lvalue. if (T.hasQualifiers()) T = T.getUnqualifiedType(); - - return Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, - E, 0, VK_RValue)); + + ExprResult Res = Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, + E, 0, VK_RValue)); + + return Res; } ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E) { @@ -426,10 +428,15 @@ ExprResult Sema::UsualUnaryConversions(Expr *E) { if (Res.isInvalid()) return Owned(E); E = Res.take(); - + QualType Ty = E->getType(); assert(!Ty.isNull() && "UsualUnaryConversions - missing type"); - + + // Half FP is a bit different: it's a storage-only type, meaning that any + // "use" of it should be promoted to float. + if (Ty->isHalfType()) + return ImpCastExprToType(Res.take(), Context.FloatTy, CK_FloatingCast); + // Try to perform integral promotions if the object has a theoretically // promotable type. if (Ty->isIntegralOrUnscopedEnumerationType()) { @@ -446,7 +453,7 @@ ExprResult Sema::UsualUnaryConversions(Expr *E) { // value is converted to an int; otherwise, it is converted to an // unsigned int. These are called the integer promotions. All // other types are unchanged by the integer promotions. - + QualType PTy = Context.isPromotableBitField(E); if (!PTy.isNull()) { E = ImpCastExprToType(E, PTy, CK_IntegralCast).take(); @@ -8103,6 +8110,13 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, Input = DefaultFunctionArrayLvalueConversion(Input.take()); if (Input.isInvalid()) return ExprError(); resultType = Input.get()->getType(); + + // Though we still have to promote half FP to float... + if (resultType->isHalfType()) { + Input = ImpCastExprToType(Input.take(), Context.FloatTy, CK_FloatingCast).take(); + resultType = Context.FloatTy; + } + if (resultType->isDependentType()) break; if (resultType->isScalarType()) { diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index d3c4da8816c..3300444a1c1 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -2416,6 +2416,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, } case ICK_Boolean_Conversion: + // Perform half-to-boolean conversion via float. + if (From->getType()->isHalfType()) { + From = ImpCastExprToType(From, Context.FloatTy, CK_FloatingCast).take(); + FromType = Context.FloatTy; + } + From = ImpCastExprToType(From, Context.BoolTy, ScalarTypeToBooleanCastKind(FromType), VK_RValue, /*BasePath=*/0, CCK).take(); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 6112e0d4181..b0dd5e280eb 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1469,10 +1469,10 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { /// FromType to ToType is a floating point promotion (C++ 4.6). If so, /// returns true and sets PromotedType to the promoted type. bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) { - /// An rvalue of type float can be converted to an rvalue of type - /// double. (C++ 4.6p1). if (const BuiltinType *FromBuiltin = FromType->getAs<BuiltinType>()) if (const BuiltinType *ToBuiltin = ToType->getAs<BuiltinType>()) { + /// An rvalue of type float can be converted to an rvalue of type + /// double. (C++ 4.6p1). if (FromBuiltin->getKind() == BuiltinType::Float && ToBuiltin->getKind() == BuiltinType::Double) return true; @@ -1485,6 +1485,11 @@ bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) { FromBuiltin->getKind() == BuiltinType::Double) && (ToBuiltin->getKind() == BuiltinType::LongDouble)) return true; + + // Half can be promoted to float. + if (FromBuiltin->getKind() == BuiltinType::Half && + ToBuiltin->getKind() == BuiltinType::Float) + return true; } return false; diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index a2aa1b30264..e383db93506 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -641,6 +641,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_char16: case TST_char32: case TST_int: + case TST_half: case TST_float: case TST_double: case TST_bool: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index dc08320cad7..2b563a50a99 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -711,6 +711,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } 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) @@ -1434,13 +1435,26 @@ QualType Sema::BuildFunctionType(QualType T, << T->isFunctionType() << T; return QualType(); } - + + // Functions cannot return half FP. + if (T->isHalfType()) { + Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 << + FixItHint::CreateInsertion(Loc, "*"); + return QualType(); + } + bool Invalid = false; for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) { + // FIXME: Loc is too inprecise here, should use proper locations for args. QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]); if (ParamType->isVoidType()) { Diag(Loc, diag::err_param_with_void_type); Invalid = true; + } else if (ParamType->isHalfType()) { + // Disallow half FP arguments. + Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 0 << + FixItHint::CreateInsertion(Loc, "*"); + Invalid = true; } ParamTypes[Idx] = ParamType; @@ -2062,6 +2076,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, D.setInvalidType(true); } + // Do not allow returning half FP value. + // FIXME: This really should be in BuildFunctionType. + if (T->isHalfType()) { + S.Diag(D.getIdentifierLoc(), + diag::err_parameters_retval_cannot_have_fp16_type) << 1 + << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*"); + D.setInvalidType(true); + } + // cv-qualifiers on return types are pointless except when the type is a // class type in C++. if (isa<PointerType>(T) && T.getLocalCVRQualifiers() && @@ -2185,6 +2208,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Do not add 'void' to the ArgTys list. break; } + } else if (ArgTy->isHalfType()) { + // Disallow half FP arguments. + // FIXME: This really should be in BuildFunctionType. + S.Diag(Param->getLocation(), + diag::err_parameters_retval_cannot_have_fp16_type) << 0 + << FixItHint::CreateInsertion(Param->getLocation(), "*"); + D.setInvalidType(); } else if (!FTI.hasPrototype) { if (ArgTy->isPromotableIntegerType()) { ArgTy = Context.getPromotedIntegerType(ArgTy); |