diff options
author | Chris B <chris.bieneman@me.com> | 2024-02-15 14:58:06 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-15 14:58:06 -0600 |
commit | 5c57fd717d5d6a285efeb8402c6fe0c8f70592f3 (patch) | |
tree | cd4b71c05decd37f40090f06456570ad485e044e /clang/lib | |
parent | edfc859af89e44207bf499b5d702aa26a7357da4 (diff) | |
download | llvm-5c57fd717d5d6a285efeb8402c6fe0c8f70592f3.zip llvm-5c57fd717d5d6a285efeb8402c6fe0c8f70592f3.tar.gz llvm-5c57fd717d5d6a285efeb8402c6fe0c8f70592f3.tar.bz2 |
[HLSL] Vector standard conversions (#71098)
HLSL supports vector truncation and element conversions as part of
standard conversion sequences. The vector truncation conversion is a C++
second conversion in the conversion sequence. If a vector truncation is
in a conversion sequence an element conversion may occur after it before
the standard C++ third conversion.
Vector element conversions can be boolean conversions, floating point or
integral conversions or promotions.
[HLSL Draft
Specification](https://microsoft.github.io/hlsl-specs/specs/hlsl.pdf)
---------
Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 1 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprComplex.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 64 | ||||
-rw-r--r-- | clang/lib/Edit/RewriteObjCFoundationAPI.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 86 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 153 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 3 |
13 files changed, 289 insertions, 42 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 8b10e28..cc04071 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1897,6 +1897,7 @@ bool CastExpr::CastConsistency() const { case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: case CK_MatrixCast: + case CK_HLSLVectorTruncation: assert(!getType()->isBooleanType() && "unheralded conversion to bool"); goto CheckNoBasePath; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 0100101..fcf8f65 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -13980,6 +13980,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_FixedPointCast: case CK_IntegralToFixedPoint: case CK_MatrixCast: + case CK_HLSLVectorTruncation: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -14818,6 +14819,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: case CK_MatrixCast: + case CK_HLSLVectorTruncation: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 4a2f3ca..59a7fe8 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -5180,6 +5180,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: case CK_MatrixCast: + case CK_HLSLVectorTruncation: return EmitUnsupportedLValue(E, "unexpected cast lvalue"); case CK_Dependent: diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 22f55fe..d0d6202 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -933,6 +933,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLOpaqueType: case CK_MatrixCast: + case CK_HLSLVectorTruncation: case CK_IntToOCLSampler: case CK_FloatingToFixedPoint: @@ -1457,6 +1458,7 @@ static bool castPreservesZero(const CastExpr *CE) { case CK_MatrixCast: case CK_NonAtomicToAtomic: case CK_AtomicToNonAtomic: + case CK_HLSLVectorTruncation: return true; case CK_BaseToDerivedMemberPointer: diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 9ddf0e7..176a7e0 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -564,6 +564,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op, case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: case CK_MatrixCast: + case CK_HLSLVectorTruncation: llvm_unreachable("invalid cast kind for complex value"); case CK_FloatingRealToComplex: diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index a054f38..75286dc 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1225,6 +1225,7 @@ public: case CK_IntegralToFixedPoint: case CK_ZeroToOCLOpaqueType: case CK_MatrixCast: + case CK_HLSLVectorTruncation: return nullptr; } llvm_unreachable("Invalid CastKind"); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index aa805f29..13526de 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2408,6 +2408,12 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { CE->getExprLoc()); case CK_IntegralCast: { + if (E->getType()->isExtVectorType() && DestTy->isExtVectorType()) { + QualType SrcElTy = E->getType()->castAs<VectorType>()->getElementType(); + return Builder.CreateIntCast(Visit(E), ConvertType(DestTy), + SrcElTy->isSignedIntegerOrEnumerationType(), + "conv"); + } ScalarConversionOpts Opts; if (auto *ICE = dyn_cast<ImplicitCastExpr>(CE)) { if (!ICE->isPartOfExplicitCast()) @@ -2416,9 +2422,50 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { return EmitScalarConversion(Visit(E), E->getType(), DestTy, CE->getExprLoc(), Opts); } - case CK_IntegralToFloating: - case CK_FloatingToIntegral: - case CK_FloatingCast: + case CK_IntegralToFloating: { + if (E->getType()->isVectorType() && DestTy->isVectorType()) { + // TODO: Support constrained FP intrinsics. + assert(!Builder.getIsFPConstrained() && + "FP Constrained vector casts not supported yet."); + QualType SrcElTy = E->getType()->castAs<VectorType>()->getElementType(); + if (SrcElTy->isSignedIntegerOrEnumerationType()) + return Builder.CreateSIToFP(Visit(E), ConvertType(DestTy), "conv"); + return Builder.CreateUIToFP(Visit(E), ConvertType(DestTy), "conv"); + } + CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, CE); + return EmitScalarConversion(Visit(E), E->getType(), DestTy, + CE->getExprLoc()); + } + case CK_FloatingToIntegral: { + if (E->getType()->isVectorType() && DestTy->isVectorType()) { + // TODO: Support constrained FP intrinsics. + assert(!Builder.getIsFPConstrained() && + "FP Constrained vector casts not supported yet."); + QualType DstElTy = DestTy->castAs<VectorType>()->getElementType(); + if (DstElTy->isSignedIntegerOrEnumerationType()) + return Builder.CreateFPToSI(Visit(E), ConvertType(DestTy), "conv"); + return Builder.CreateFPToUI(Visit(E), ConvertType(DestTy), "conv"); + } + CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, CE); + return EmitScalarConversion(Visit(E), E->getType(), DestTy, + CE->getExprLoc()); + } + case CK_FloatingCast: { + if (E->getType()->isVectorType() && DestTy->isVectorType()) { + // TODO: Support constrained FP intrinsics. + assert(!Builder.getIsFPConstrained() && + "FP Constrained vector casts not supported yet."); + QualType SrcElTy = E->getType()->castAs<VectorType>()->getElementType(); + QualType DstElTy = DestTy->castAs<VectorType>()->getElementType(); + if (DstElTy->castAs<BuiltinType>()->getKind() < + SrcElTy->castAs<BuiltinType>()->getKind()) + return Builder.CreateFPTrunc(Visit(E), ConvertType(DestTy), "conv"); + return Builder.CreateFPExt(Visit(E), ConvertType(DestTy), "conv"); + } + CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, CE); + return EmitScalarConversion(Visit(E), E->getType(), DestTy, + CE->getExprLoc()); + } case CK_FixedPointToFloating: case CK_FloatingToFixedPoint: { CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, CE); @@ -2468,6 +2515,17 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { case CK_IntToOCLSampler: return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF); + case CK_HLSLVectorTruncation: { + assert(DestTy->isVectorType() && "Expected dest type to be vector type"); + Value *Vec = Visit(const_cast<Expr *>(E)); + SmallVector<int, 16> Mask; + unsigned NumElts = DestTy->castAs<VectorType>()->getNumElements(); + for (unsigned I = 0; I != NumElts; ++I) + Mask.push_back(I); + + return Builder.CreateShuffleVector(Vec, Mask, "trunc"); + } + } // end of switch llvm_unreachable("unknown scalar cast"); diff --git a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp index 2e123e8..22f2c47e 100644 --- a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -1083,6 +1083,10 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, case CK_BooleanToSignedIntegral: llvm_unreachable("OpenCL-specific cast in Objective-C?"); + case CK_HLSLVectorTruncation: + llvm_unreachable("HLSL-specific cast in Objective-C?"); + break; + case CK_FloatingToFixedPoint: case CK_FixedPointToFloating: case CK_FixedPointCast: diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index afe2673..8e76338 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -15676,11 +15676,18 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (S.SourceMgr.isInSystemMacro(CC)) return; return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar); + } else if (S.getLangOpts().HLSL && + Target->castAs<VectorType>()->getNumElements() < + Source->castAs<VectorType>()->getNumElements()) { + // Diagnose vector truncation but don't return. We may also want to + // diagnose an element conversion. + DiagnoseImpCast(S, E, T, CC, diag::warn_hlsl_impcast_vector_truncation); } // If the vector cast is cast between two vectors of the same size, it is - // a bitcast, not a conversion. - if (S.Context.getTypeSize(Source) == S.Context.getTypeSize(Target)) + // a bitcast, not a conversion, except under HLSL where it is a conversion. + if (!S.getLangOpts().HLSL && + S.Context.getTypeSize(Source) == S.Context.getTypeSize(Target)) return; Source = cast<VectorType>(Source)->getElementType().getTypePtr(); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f2b8913..801ce7b 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4762,6 +4762,22 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, CK_ZeroToOCLOpaqueType, From->getValueKind()).get(); break; + case ICK_HLSL_Vector_Truncation: { + // Note: HLSL built-in vectors are ExtVectors. Since this truncates a vector + // to a smaller vector, this can only operate on arguments where the source + // and destination types are ExtVectors. + assert(From->getType()->isExtVectorType() && ToType->isExtVectorType() && + "HLSL vector truncation should only apply to ExtVectors"); + auto *FromVec = From->getType()->castAs<VectorType>(); + auto *ToVec = ToType->castAs<VectorType>(); + QualType ElType = FromVec->getElementType(); + QualType TruncTy = + Context.getExtVectorType(ElType, ToVec->getNumElements()); + From = ImpCastExprToType(From, TruncTy, CK_HLSLVectorTruncation, + From->getValueKind()) + .get(); + break; + } case ICK_Lvalue_To_Rvalue: case ICK_Array_To_Pointer: @@ -4774,6 +4790,76 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, llvm_unreachable("Improper second standard conversion"); } + if (SCS.Element != ICK_Identity) { + // If SCS.Element is not ICK_Identity the To and From types must be HLSL + // vectors or matrices. + + // TODO: Support HLSL matrices. + assert((!From->getType()->isMatrixType() && !ToType->isMatrixType()) && + "Element conversion for matrix types is not implemented yet."); + assert(From->getType()->isVectorType() && ToType->isVectorType() && + "Element conversion is only supported for vector types."); + assert(From->getType()->getAs<VectorType>()->getNumElements() == + ToType->getAs<VectorType>()->getNumElements() && + "Element conversion is only supported for vectors with the same " + "element counts."); + QualType FromElTy = From->getType()->getAs<VectorType>()->getElementType(); + unsigned NumElts = ToType->getAs<VectorType>()->getNumElements(); + switch (SCS.Element) { + case ICK_Boolean_Conversion: + // Perform half-to-boolean conversion via float. + if (FromElTy->isHalfType()) { + QualType FPExtType = Context.getExtVectorType(FromElTy, NumElts); + From = ImpCastExprToType(From, FPExtType, CK_FloatingCast).get(); + FromType = FPExtType; + } + + From = + ImpCastExprToType(From, ToType, ScalarTypeToBooleanCastKind(FromElTy), + VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + break; + case ICK_Integral_Promotion: + case ICK_Integral_Conversion: + if (ToType->isBooleanType()) { + assert(FromType->castAs<EnumType>()->getDecl()->isFixed() && + SCS.Second == ICK_Integral_Promotion && + "only enums with fixed underlying type can promote to bool"); + From = ImpCastExprToType(From, ToType, CK_IntegralToBoolean, VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + } else { + From = ImpCastExprToType(From, ToType, CK_IntegralCast, VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + } + break; + + case ICK_Floating_Promotion: + case ICK_Floating_Conversion: + From = ImpCastExprToType(From, ToType, CK_FloatingCast, VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + break; + case ICK_Floating_Integral: + if (ToType->isRealFloatingType()) + From = + ImpCastExprToType(From, ToType, CK_IntegralToFloating, VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + else + From = + ImpCastExprToType(From, ToType, CK_FloatingToIntegral, VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + break; + case ICK_Identity: + default: + llvm_unreachable("Improper element standard conversion"); + } + } + switch (SCS.Third) { case ICK_Identity: // Nothing to do. diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index b6de064..0fd4588 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -6432,7 +6432,7 @@ void InitializationSequence::InitializeFrom(Sema &S, // For HLSL ext vector types we allow list initialization behavior for C++ // constructor syntax. This is accomplished by converting initialization // arguments an InitListExpr late. - if (S.getLangOpts().HLSL && DestType->isExtVectorType() && + if (S.getLangOpts().HLSL && Args.size() > 1 && DestType->isExtVectorType() && (SourceType.isNull() || !Context.hasSameUnqualifiedType(SourceType, DestType))) { diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 5c6d463..f764542 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -159,6 +159,7 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) { ICR_C_Conversion, ICR_C_Conversion_Extension, ICR_Conversion, + ICR_Conversion, }; static_assert(std::size(Rank) == (int)ICK_Num_Conversion_Kinds); return Rank[(int)Kind]; @@ -199,6 +200,7 @@ static const char *GetImplicitConversionName(ImplicitConversionKind Kind) { "C specific type conversion", "Incompatible pointer conversion", "Fixed point conversion", + "HLSL vector truncation", }; static_assert(std::size(Name) == (int)ICK_Num_Conversion_Kinds); return Name[Kind]; @@ -209,6 +211,7 @@ static const char *GetImplicitConversionName(ImplicitConversionKind Kind) { void StandardConversionSequence::setAsIdentityConversion() { First = ICK_Identity; Second = ICK_Identity; + Element = ICK_Identity; Third = ICK_Identity; DeprecatedStringLiteralToCharPtr = false; QualificationIncludesObjCLifetime = false; @@ -227,11 +230,13 @@ void StandardConversionSequence::setAsIdentityConversion() { /// implicit conversions. ImplicitConversionRank StandardConversionSequence::getRank() const { ImplicitConversionRank Rank = ICR_Exact_Match; - if (GetConversionRank(First) > Rank) + if (GetConversionRank(First) > Rank) Rank = GetConversionRank(First); - if (GetConversionRank(Second) > Rank) + if (GetConversionRank(Second) > Rank) Rank = GetConversionRank(Second); - if (GetConversionRank(Third) > Rank) + if (GetConversionRank(Element) > Rank) + Rank = GetConversionRank(Element); + if (GetConversionRank(Third) > Rank) Rank = GetConversionRank(Third); return Rank; } @@ -1829,12 +1834,85 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType, } /// Determine whether the conversion from FromType to ToType is a valid +/// floating point conversion. +/// +static bool IsFloatingPointConversion(Sema &S, QualType FromType, + QualType ToType) { + if (!FromType->isRealFloatingType() || !ToType->isRealFloatingType()) + return false; + // FIXME: disable conversions between long double, __ibm128 and __float128 + // if their representation is different until there is back end support + // We of course allow this conversion if long double is really double. + + // Conversions between bfloat16 and float16 are currently not supported. + if ((FromType->isBFloat16Type() && + (ToType->isFloat16Type() || ToType->isHalfType())) || + (ToType->isBFloat16Type() && + (FromType->isFloat16Type() || FromType->isHalfType()))) + return false; + + // Conversions between IEEE-quad and IBM-extended semantics are not + // permitted. + const llvm::fltSemantics &FromSem = S.Context.getFloatTypeSemantics(FromType); + const llvm::fltSemantics &ToSem = S.Context.getFloatTypeSemantics(ToType); + if ((&FromSem == &llvm::APFloat::PPCDoubleDouble() && + &ToSem == &llvm::APFloat::IEEEquad()) || + (&FromSem == &llvm::APFloat::IEEEquad() && + &ToSem == &llvm::APFloat::PPCDoubleDouble())) + return false; + return true; +} + +static bool IsVectorElementConversion(Sema &S, QualType FromType, + QualType ToType, + ImplicitConversionKind &ICK, Expr *From) { + if (S.Context.hasSameUnqualifiedType(FromType, ToType)) + return true; + + if (S.IsFloatingPointPromotion(FromType, ToType)) { + ICK = ICK_Floating_Promotion; + return true; + } + + if (IsFloatingPointConversion(S, FromType, ToType)) { + ICK = ICK_Floating_Conversion; + return true; + } + + if (ToType->isBooleanType() && FromType->isArithmeticType()) { + ICK = ICK_Boolean_Conversion; + return true; + } + + if (S.IsIntegralPromotion(From, FromType, ToType)) { + ICK = ICK_Integral_Promotion; + return true; + } + + if (FromType->isIntegralOrUnscopedEnumerationType() && + ToType->isIntegralType(S.Context)) { + ICK = ICK_Integral_Conversion; + return true; + } + + if ((FromType->isRealFloatingType() && ToType->isIntegralType(S.Context)) || + (FromType->isIntegralOrUnscopedEnumerationType() && + ToType->isRealFloatingType())) { + ICK = ICK_Floating_Integral; + return true; + } + + return false; +} + +/// Determine whether the conversion from FromType to ToType is a valid /// vector conversion. /// /// \param ICK Will be set to the vector conversion kind, if this is a vector /// conversion. static bool IsVectorConversion(Sema &S, QualType FromType, QualType ToType, - ImplicitConversionKind &ICK, Expr *From, + ImplicitConversionKind &ICK, + ImplicitConversionKind &ElConv, Expr *From, bool InOverloadResolution, bool CStyle) { // We need at least one of these types to be a vector type to have a vector // conversion. @@ -1847,10 +1925,28 @@ static bool IsVectorConversion(Sema &S, QualType FromType, QualType ToType, // There are no conversions between extended vector types, only identity. if (ToType->isExtVectorType()) { - // There are no conversions between extended vector types other than the - // identity conversion. - if (FromType->isExtVectorType()) + if (FromType->isExtVectorType()) { + // HLSL allows implicit truncation of vector types. + if (S.getLangOpts().HLSL) { + unsigned FromElts = FromType->getAs<VectorType>()->getNumElements(); + unsigned ToElts = ToType->getAs<VectorType>()->getNumElements(); + if (FromElts < ToElts) + return false; + if (FromElts == ToElts) + ICK = ICK_Identity; + else + ICK = ICK_HLSL_Vector_Truncation; + + QualType FromElTy = FromType->getAs<VectorType>()->getElementType(); + QualType ToElTy = ToType->getAs<VectorType>()->getElementType(); + if (S.Context.hasSameUnqualifiedType(FromElTy, ToElTy)) + return true; + return IsVectorElementConversion(S, FromElTy, ToElTy, ElConv, From); + } + // There are no conversions between extended vector types other than the + // identity conversion. return false; + } // Vector splat from any arithmetic type to a vector. if (FromType->isArithmeticType()) { @@ -2056,6 +2152,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // conversion. bool IncompatibleObjC = false; ImplicitConversionKind SecondICK = ICK_Identity; + ImplicitConversionKind ElementICK = ICK_Identity; if (S.Context.hasSameUnqualifiedType(FromType, ToType)) { // The unqualified versions of the types are the same: there's no // conversion to do. @@ -2094,29 +2191,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // Complex-real conversions (C99 6.3.1.7) SCS.Second = ICK_Complex_Real; FromType = ToType.getUnqualifiedType(); - } else if (FromType->isRealFloatingType() && ToType->isRealFloatingType()) { - // FIXME: disable conversions between long double, __ibm128 and __float128 - // if their representation is different until there is back end support - // We of course allow this conversion if long double is really double. - - // Conversions between bfloat16 and float16 are currently not supported. - if ((FromType->isBFloat16Type() && - (ToType->isFloat16Type() || ToType->isHalfType())) || - (ToType->isBFloat16Type() && - (FromType->isFloat16Type() || FromType->isHalfType()))) - return false; - - // Conversions between IEEE-quad and IBM-extended semantics are not - // permitted. - const llvm::fltSemantics &FromSem = - S.Context.getFloatTypeSemantics(FromType); - const llvm::fltSemantics &ToSem = S.Context.getFloatTypeSemantics(ToType); - if ((&FromSem == &llvm::APFloat::PPCDoubleDouble() && - &ToSem == &llvm::APFloat::IEEEquad()) || - (&FromSem == &llvm::APFloat::IEEEquad() && - &ToSem == &llvm::APFloat::PPCDoubleDouble())) - return false; - + } else if (IsFloatingPointConversion(S, FromType, ToType)) { // Floating point conversions (C++ 4.8). SCS.Second = ICK_Floating_Conversion; FromType = ToType.getUnqualifiedType(); @@ -2143,18 +2218,18 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, InOverloadResolution, FromType)) { // Pointer to member conversions (4.11). SCS.Second = ICK_Pointer_Member; - } else if (IsVectorConversion(S, FromType, ToType, SecondICK, From, - InOverloadResolution, CStyle)) { + } else if (IsVectorConversion(S, FromType, ToType, SecondICK, ElementICK, + From, InOverloadResolution, CStyle)) { SCS.Second = SecondICK; + SCS.Element = ElementICK; FromType = ToType.getUnqualifiedType(); } else if (!S.getLangOpts().CPlusPlus && S.Context.typesAreCompatible(ToType, FromType)) { // Compatible conversions (Clang extension for C function overloading) SCS.Second = ICK_Compatible_Conversion; FromType = ToType.getUnqualifiedType(); - } else if (IsTransparentUnionStandardConversion(S, From, ToType, - InOverloadResolution, - SCS, CStyle)) { + } else if (IsTransparentUnionStandardConversion( + S, From, ToType, InOverloadResolution, SCS, CStyle)) { SCS.Second = ICK_TransparentUnionConversion; FromType = ToType; } else if (tryAtomicConversion(S, From, ToType, InOverloadResolution, SCS, @@ -2449,6 +2524,11 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { return true; } + // In HLSL an rvalue of integral type can be promoted to an rvalue of a larger + // integral type. + if (Context.getLangOpts().HLSL) + return Context.getTypeSize(FromType) < Context.getTypeSize(ToType); + return false; } @@ -5042,6 +5122,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, : (RefConv & Sema::ReferenceConversions::ObjC) ? ICK_Compatible_Conversion : ICK_Identity; + ICS.Standard.Element = ICK_Identity; // FIXME: As a speculative fix to a defect introduced by CWG2352, we rank // a reference binding that performs a non-top-level qualification // conversion as a qualification conversion, not as an identity conversion. @@ -5968,6 +6049,7 @@ static bool CheckConvertedConstantConversions(Sema &S, case ICK_C_Only_Conversion: case ICK_Incompatible_Pointer_Conversion: case ICK_Fixed_Point_Conversion: + case ICK_HLSL_Vector_Truncation: return false; case ICK_Lvalue_To_Rvalue: @@ -6245,6 +6327,7 @@ Sema::EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value, static void dropPointerConversion(StandardConversionSequence &SCS) { if (SCS.Second == ICK_Pointer_Conversion) { SCS.Second = ICK_Identity; + SCS.Element = ICK_Identity; SCS.Third = ICK_Identity; SCS.ToTypePtrs[2] = SCS.ToTypePtrs[1] = SCS.ToTypePtrs[0]; } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 7e431f7..c3fc56a 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -520,7 +520,8 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, // Various C++ casts that are not handled yet. case CK_ToUnion: case CK_MatrixCast: - case CK_VectorSplat: { + case CK_VectorSplat: + case CK_HLSLVectorTruncation: { QualType resultType = CastE->getType(); if (CastE->isGLValue()) resultType = getContext().getPointerType(resultType); |