@@ -104,6 +104,7 @@ namespace {
104104 void CheckStaticCast ();
105105 void CheckDynamicCast ();
106106 void CheckCXXCStyleCast (bool FunctionalCast, bool ListInitialization);
107+ bool CheckHLSLCStyleCast (CheckedConversionKind CCK);
107108 void CheckCStyleCast ();
108109 void CheckBuiltinBitCast ();
109110 void CheckAddrspaceCast ();
@@ -2776,39 +2777,9 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
27762777 CheckedConversionKind CCK = FunctionalStyle
27772778 ? CheckedConversionKind::FunctionalCast
27782779 : CheckedConversionKind::CStyleCast;
2779-
2780- QualType SrcTy = SrcExpr.get ()->getType ();
2781- // This case should not trigger on regular vector cast, vector truncation
2782- if (Self.getLangOpts ().HLSL &&
2783- Self.HLSL ().CanPerformElementwiseCast (SrcExpr.get (), DestType)) {
2784- if (SrcTy->isConstantArrayType ())
2785- SrcExpr = Self.ImpCastExprToType (
2786- SrcExpr.get (), Self.Context .getArrayParameterType (SrcTy),
2787- CK_HLSLArrayRValue, VK_PRValue, nullptr , CCK);
2788- Kind = CK_HLSLElementwiseCast;
2789- return ;
2790- }
2791-
2792- // This case should not trigger on regular vector splat
2793- // If the relative order of this and the HLSLElementWise cast checks
2794- // are changed, it might change which cast handles what in a few cases
2795- if (Self.getLangOpts ().HLSL &&
2796- Self.HLSL ().CanPerformAggregateSplatCast (SrcExpr.get (), DestType)) {
2797- const VectorType *VT = SrcTy->getAs <VectorType>();
2798- // change splat from vec1 case to splat from scalar
2799- if (VT && VT->getNumElements () == 1 )
2800- SrcExpr = Self.ImpCastExprToType (
2801- SrcExpr.get (), VT->getElementType (), CK_HLSLVectorTruncation,
2802- SrcExpr.get ()->getValueKind (), nullptr , CCK);
2803- // Inserting a scalar cast here allows for a simplified codegen in
2804- // the case the destTy is a vector
2805- if (const VectorType *DVT = DestType->getAs <VectorType>())
2806- SrcExpr = Self.ImpCastExprToType (
2807- SrcExpr.get (), DVT->getElementType (),
2808- Self.PrepareScalarCast (SrcExpr, DVT->getElementType ()),
2809- SrcExpr.get ()->getValueKind (), nullptr , CCK);
2810- Kind = CK_HLSLAggregateSplatCast;
2811- return ;
2780+ if (Self.getLangOpts ().HLSL ) {
2781+ if (CheckHLSLCStyleCast (CCK))
2782+ return ;
28122783 }
28132784
28142785 if (ValueKind == VK_PRValue && !DestType->isRecordType () &&
@@ -2927,6 +2898,56 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
29272898 }
29282899}
29292900
2901+ // CheckHLSLCStyleCast - Returns `true` ihe cast is handled or errored as an
2902+ // HLSL-specific cast. Returns false if the cast should be checked as a CXX
2903+ // C-Style cast.
2904+ bool CastOperation::CheckHLSLCStyleCast (CheckedConversionKind CCK) {
2905+ assert (Self.getLangOpts ().HLSL && " Must be HLSL!" );
2906+ QualType SrcTy = SrcExpr.get ()->getType ();
2907+ // HLSL has several unique forms of C-style casts which support aggregate to
2908+ // aggregate casting.
2909+ // This case should not trigger on regular vector cast, vector truncation
2910+ if (Self.HLSL ().CanPerformElementwiseCast (SrcExpr.get (), DestType)) {
2911+ if (SrcTy->isConstantArrayType ())
2912+ SrcExpr = Self.ImpCastExprToType (
2913+ SrcExpr.get (), Self.Context .getArrayParameterType (SrcTy),
2914+ CK_HLSLArrayRValue, VK_PRValue, nullptr , CCK);
2915+ Kind = CK_HLSLElementwiseCast;
2916+ return true ;
2917+ }
2918+
2919+ // This case should not trigger on regular vector splat
2920+ // If the relative order of this and the HLSLElementWise cast checks
2921+ // are changed, it might change which cast handles what in a few cases
2922+ if (Self.HLSL ().CanPerformAggregateSplatCast (SrcExpr.get (), DestType)) {
2923+ const VectorType *VT = SrcTy->getAs <VectorType>();
2924+ // change splat from vec1 case to splat from scalar
2925+ if (VT && VT->getNumElements () == 1 )
2926+ SrcExpr = Self.ImpCastExprToType (
2927+ SrcExpr.get (), VT->getElementType (), CK_HLSLVectorTruncation,
2928+ SrcExpr.get ()->getValueKind (), nullptr , CCK);
2929+ // Inserting a scalar cast here allows for a simplified codegen in
2930+ // the case the destTy is a vector
2931+ if (const VectorType *DVT = DestType->getAs <VectorType>())
2932+ SrcExpr = Self.ImpCastExprToType (
2933+ SrcExpr.get (), DVT->getElementType (),
2934+ Self.PrepareScalarCast (SrcExpr, DVT->getElementType ()),
2935+ SrcExpr.get ()->getValueKind (), nullptr , CCK);
2936+ Kind = CK_HLSLAggregateSplatCast;
2937+ return true ;
2938+ }
2939+
2940+ // If the destination is an array, we've exhausted the valid HLSL casts, so we
2941+ // should emit a dignostic and stop processing.
2942+ if (DestType->isArrayType ()) {
2943+ Self.Diag (OpRange.getBegin (), diag::err_bad_cxx_cast_generic)
2944+ << 4 << SrcTy << DestType;
2945+ SrcExpr = ExprError ();
2946+ return true ;
2947+ }
2948+ return false ;
2949+ }
2950+
29302951// / DiagnoseBadFunctionCast - Warn whenever a function call is cast to a
29312952// / non-matching type. Such as enum function call to int, int call to
29322953// / pointer; etc. Cast to 'void' is an exception.
0 commit comments