================ @@ -401,6 +401,194 @@ void SemaHLSL::DiagnoseAttrStageMismatch( << (AllowedStages.size() != 1) << join(StageStrings, ", "); } +template <CastKind Kind> +static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz) { + if (const auto *VTy = Ty->getAs<VectorType>()) + Ty = VTy->getElementType(); + Ty = S.getASTContext().getExtVectorType(Ty, Sz); + E = S.ImpCastExprToType(E.get(), Ty, Kind); +} + +template <CastKind Kind> +static QualType castElement(Sema &S, ExprResult &E, QualType Ty) { + E = S.ImpCastExprToType(E.get(), Ty, Kind); + return Ty; +} + +static QualType handleFloatVectorBinOpConversion( + Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, + QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign) { + bool LHSFloat = LElTy->isRealFloatingType(); + bool RHSFloat = RElTy->isRealFloatingType(); + + if (LHSFloat && RHSFloat) { + if (IsCompAssign || + SemaRef.getASTContext().getFloatingTypeOrder(LElTy, RElTy) > 0) + return castElement<CK_FloatingCast>(SemaRef, RHS, LHSType); + + return castElement<CK_FloatingCast>(SemaRef, LHS, RHSType); + } + + if (LHSFloat) + return castElement<CK_IntegralToFloating>(SemaRef, RHS, LHSType); + + assert(RHSFloat); + if (IsCompAssign) + return castElement<clang::CK_FloatingToIntegral>(SemaRef, RHS, LHSType); + + return castElement<CK_IntegralToFloating>(SemaRef, LHS, RHSType); +} + +static QualType handleIntegerVectorBinOpConversion( + Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType, + QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign) { + + int IntOrder = SemaRef.Context.getIntegerTypeOrder(LElTy, RElTy); + bool LHSSigned = LElTy->hasSignedIntegerRepresentation(); + bool RHSSigned = RElTy->hasSignedIntegerRepresentation(); + auto &Ctx = SemaRef.getASTContext(); + + // If both types have the same signedness, use the higher ranked type. + if (LHSSigned == RHSSigned) { + if (IsCompAssign || IntOrder >= 0) + return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType); + + return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType); + } + + // If the unsigned type has greater than or equal rank of the signed type, use + // the unsigned type. + if (IntOrder != (LHSSigned ? 1 : -1)) { + if (IsCompAssign || RHSSigned) + return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType); + return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType); + } + + // At this point the signed type has higher rank than the unsigned type, which + // means it will be the same size or bigger. If the signed type is bigger, it + // can represent all the values of the unsigned type, so select it. + if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) { + if (IsCompAssign || LHSSigned) + return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType); + return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType); + } + + // This is a bit of an odd duck case in HLSL. It shouldn't happen, but can due + // to C/C++ leaking through. The place this happens today is long vs long + // long. When arguments are vector<unsigned long, N> and vector<long long, N>, + // the long long has higher rank than long even though they are the same size. ---------------- bogner wrote:
Should we assert on the types to make sure this is indeed the `long`/`long long` case? If we somehow got here for some other case I'm not convinced what we do below would be correct. https://github.com/llvm/llvm-project/pull/108659 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits