diff options
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 69 |
1 files changed, 66 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 66b87120b0d..a5ee8bebae7 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1155,6 +1155,48 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS, /*convertFloat=*/!IsCompAssign); } +/// \brief Diagnose attempts to convert between __float128 and long double if +/// there is no support for such conversion. Helper function of +/// UsualArithmeticConversions(). +static bool unsupportedTypeConversion(const Sema &S, QualType LHSType, + QualType RHSType) { + /* No issue converting if at least one of the types is not a floating point + type or the two types have the same rank. + */ + if (!LHSType->isFloatingType() || !RHSType->isFloatingType() || + S.Context.getFloatingTypeOrder(LHSType, RHSType) == 0) + return false; + + assert(LHSType->isFloatingType() && RHSType->isFloatingType() && + "The remaining types must be floating point types."); + + auto *LHSComplex = LHSType->getAs<ComplexType>(); + auto *RHSComplex = RHSType->getAs<ComplexType>(); + + QualType LHSElemType = LHSComplex ? + LHSComplex->getElementType() : LHSType; + QualType RHSElemType = RHSComplex ? + RHSComplex->getElementType() : RHSType; + + // No issue if the two types have the same representation + if (&S.Context.getFloatTypeSemantics(LHSElemType) == + &S.Context.getFloatTypeSemantics(RHSElemType)) + return false; + + bool Float128AndLongDouble = (LHSElemType == S.Context.Float128Ty && + RHSElemType == S.Context.LongDoubleTy); + Float128AndLongDouble |= (LHSElemType == S.Context.LongDoubleTy && + RHSElemType == S.Context.Float128Ty); + + /* We've handled the situation where __float128 and long double have the same + representation. The only other allowable conversion is if long double is + really just double. + */ + return Float128AndLongDouble && + (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) != + &llvm::APFloat::IEEEdouble); +} + typedef ExprResult PerformCastFn(Sema &S, Expr *operand, QualType toType); namespace { @@ -1318,6 +1360,11 @@ QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS, // At this point, we have two different arithmetic types. + // Diagnose attempts to convert between __float128 and long double where + // such conversions currently can't be handled. + if (unsupportedTypeConversion(*this, LHSType, RHSType)) + return QualType(); + // Handle complex types first (C99 6.3.1.8p1). if (LHSType->isComplexType() || RHSType->isComplexType()) return handleComplexFloatConversion(*this, LHS, RHS, LHSType, RHSType, @@ -3327,10 +3374,12 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { } } else if (Literal.isFloat) Ty = Context.FloatTy; - else if (!Literal.isLong) - Ty = Context.DoubleTy; - else + else if (Literal.isLong) Ty = Context.LongDoubleTy; + else if (Literal.isFloat128) + Ty = Context.Float128Ty; + else + Ty = Context.DoubleTy; Res = BuildFloatingLiteral(*this, Literal, Ty, Tok.getLocation()); @@ -6604,6 +6653,15 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, QualType LHSTy = LHS.get()->getType(); QualType RHSTy = RHS.get()->getType(); + // Diagnose attempts to convert between __float128 and long double where + // such conversions currently can't be handled. + if (unsupportedTypeConversion(*this, LHSTy, RHSTy)) { + Diag(QuestionLoc, + diag::err_typecheck_cond_incompatible_operands) << LHSTy << RHSTy + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); + } + // OpenCL v2.0 s6.12.5 - Blocks cannot be used as expressions of the ternary // selection operator (?:). if (getLangOpts().OpenCL && @@ -7337,6 +7395,11 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, return Incompatible; } + // Diagnose attempts to convert between __float128 and long double where + // such conversions currently can't be handled. + if (unsupportedTypeConversion(*this, LHSType, RHSType)) + return Incompatible; + // Arithmetic conversions. if (LHSType->isArithmeticType() && RHSType->isArithmeticType() && !(getLangOpts().CPlusPlus && LHSType->isEnumeralType())) { |