[clang] [HLSL] Allow arrays to copy-initialize (PR #127557)
Chris B via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 17 18:46:36 PST 2025
https://github.com/llvm-beanz created https://github.com/llvm/llvm-project/pull/127557
This change allows array variables to copy-initialize from other arrays. It also corrects a small error in HLSL C-Style casting that did not error on casting to arrays if elementwise and splat conversions fail.
Fixes #127551
>From 54ba5ffea82a9613fd343750ec36242e1494f5e4 Mon Sep 17 00:00:00 2001
From: Chris Bieneman <chris.bieneman at me.com>
Date: Mon, 17 Feb 2025 20:41:18 -0600
Subject: [PATCH] [HLSL] Allow arrays to copy-initialize
This change allows array variables to copy-initialize from other
arrays. It also corrects a small error in HLSL C-Style casting that did
not error on casting to arrays if elementwise and splat conversions
fail.
Fixes #127551
---
clang/lib/Sema/SemaCast.cpp | 70 +++++++++++--------
clang/lib/Sema/SemaInit.cpp | 12 ++++
clang/test/SemaHLSL/Language/AssignArray.hlsl | 34 +++++++++
.../Language/ElementwiseCast-errors.hlsl | 2 +-
4 files changed, 86 insertions(+), 32 deletions(-)
create mode 100644 clang/test/SemaHLSL/Language/AssignArray.hlsl
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 8972957ded9f5..3ab8598e513c6 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -2778,37 +2778,45 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
: CheckedConversionKind::CStyleCast;
QualType SrcTy = SrcExpr.get()->getType();
- // This case should not trigger on regular vector cast, vector truncation
- if (Self.getLangOpts().HLSL &&
- Self.HLSL().CanPerformElementwiseCast(SrcExpr.get(), DestType)) {
- if (SrcTy->isConstantArrayType())
- SrcExpr = Self.ImpCastExprToType(
- SrcExpr.get(), Self.Context.getArrayParameterType(SrcTy),
- CK_HLSLArrayRValue, VK_PRValue, nullptr, CCK);
- Kind = CK_HLSLElementwiseCast;
- return;
- }
-
- // This case should not trigger on regular vector splat
- // If the relative order of this and the HLSLElementWise cast checks
- // are changed, it might change which cast handles what in a few cases
- if (Self.getLangOpts().HLSL &&
- Self.HLSL().CanPerformAggregateSplatCast(SrcExpr.get(), DestType)) {
- const VectorType *VT = SrcTy->getAs<VectorType>();
- // change splat from vec1 case to splat from scalar
- if (VT && VT->getNumElements() == 1)
- SrcExpr = Self.ImpCastExprToType(
- SrcExpr.get(), VT->getElementType(), CK_HLSLVectorTruncation,
- SrcExpr.get()->getValueKind(), nullptr, CCK);
- // Inserting a scalar cast here allows for a simplified codegen in
- // the case the destTy is a vector
- if (const VectorType *DVT = DestType->getAs<VectorType>())
- SrcExpr = Self.ImpCastExprToType(
- SrcExpr.get(), DVT->getElementType(),
- Self.PrepareScalarCast(SrcExpr, DVT->getElementType()),
- SrcExpr.get()->getValueKind(), nullptr, CCK);
- Kind = CK_HLSLAggregateSplatCast;
- return;
+ // HLSL has several unique forms of C-style casts which support aggregate to
+ // aggregate casting.
+ if (Self.getLangOpts().HLSL) {
+ // This case should not trigger on regular vector cast, vector truncation
+ if (Self.HLSL().CanPerformElementwiseCast(SrcExpr.get(), DestType)) {
+ if (SrcTy->isConstantArrayType())
+ SrcExpr = Self.ImpCastExprToType(
+ SrcExpr.get(), Self.Context.getArrayParameterType(SrcTy),
+ CK_HLSLArrayRValue, VK_PRValue, nullptr, CCK);
+ Kind = CK_HLSLElementwiseCast;
+ return;
+ }
+
+ // This case should not trigger on regular vector splat
+ // If the relative order of this and the HLSLElementWise cast checks
+ // are changed, it might change which cast handles what in a few cases
+ if (Self.HLSL().CanPerformAggregateSplatCast(SrcExpr.get(), DestType)) {
+ const VectorType *VT = SrcTy->getAs<VectorType>();
+ // change splat from vec1 case to splat from scalar
+ if (VT && VT->getNumElements() == 1)
+ SrcExpr = Self.ImpCastExprToType(
+ SrcExpr.get(), VT->getElementType(), CK_HLSLVectorTruncation,
+ SrcExpr.get()->getValueKind(), nullptr, CCK);
+ // Inserting a scalar cast here allows for a simplified codegen in
+ // the case the destTy is a vector
+ if (const VectorType *DVT = DestType->getAs<VectorType>())
+ SrcExpr = Self.ImpCastExprToType(
+ SrcExpr.get(), DVT->getElementType(),
+ Self.PrepareScalarCast(SrcExpr, DVT->getElementType()),
+ SrcExpr.get()->getValueKind(), nullptr, CCK);
+ Kind = CK_HLSLAggregateSplatCast;
+ return;
+ }
+ if (DestType->isArrayType()) {
+ Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic)
+ << 4 << SrcTy << DestType;
+ SrcExpr = ExprError();
+ return;
+ }
}
if (ValueKind == VK_PRValue && !DestType->isRecordType() &&
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 6a76e6d74a4b0..a34005bf376aa 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -6585,6 +6585,18 @@ void InitializationSequence::InitializeFrom(Sema &S,
}
}
+ if (S.getLangOpts().HLSL && Initializer && isa<ConstantArrayType>(DestAT)) {
+ QualType SrcType = Entity.getType();
+ if (SrcType->isArrayParameterType())
+ SrcType =
+ cast<ArrayParameterType>(SrcType)->getConstantArrayType(Context);
+ if (S.Context.hasSameUnqualifiedType(DestType, SrcType)) {
+ TryArrayCopy(S, Kind, Entity, Initializer, DestType, *this,
+ TreatUnavailableAsInvalid);
+ return;
+ }
+ }
+
// Some kinds of initialization permit an array to be initialized from
// another array of the same type, and perform elementwise initialization.
if (Initializer && isa<ConstantArrayType>(DestAT) &&
diff --git a/clang/test/SemaHLSL/Language/AssignArray.hlsl b/clang/test/SemaHLSL/Language/AssignArray.hlsl
new file mode 100644
index 0000000000000..1f813e7a350b1
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/AssignArray.hlsl
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library %s -ast-dump | FileCheck %s
+
+typedef vector<int,4> int8[2];
+
+export void fn(int8 A) {
+ int8 a = {A};
+// CHECK-LABEL: VarDecl {{.*}} b 'int8':'vector<int, 4>[2]' cinit
+// CHECK-NEXT: ArrayInitLoopExpr {{.*}} 'int8':'vector<int, 4>[2]'
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'int8':'vector<int, 4>[2]' lvalue
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int8':'vector<int, 4>[2]' lvalue Var {{.*}} 'a' 'int8':'vector<int, 4>[2]'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 4>' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'vector<int, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 4> *' <ArrayToPointerDecay>
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'int8':'vector<int, 4>[2]' lvalue
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int8':'vector<int, 4>[2]' lvalue Var {{.*}} 'a' 'int8':'vector<int, 4>[2]'
+// CHECK-NEXT: ArrayInitIndexExpr {{.*}} 'unsigned long'
+ int8 b = a;
+
+// CHECK-LABEL: VarDecl {{.*}} c 'int8':'vector<int, 4>[2]' cinit
+// CHECK-NEXT: ArrayInitLoopExpr {{.*}} 'int8':'vector<int, 4>[2]'
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'vector<int, 4>[2]' lvalue
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 4>[2]' lvalue ParmVar {{.*}} 'A' 'vector<int, 4>[2]'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 4>' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'vector<int, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 4> *' <ArrayToPointerDecay>
+// CHECK-NEXT: OpaqueValueExpr {{.*}} 'vector<int, 4>[2]' lvalue
+// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 4>[2]' lvalue ParmVar {{.*}} 'A' 'vector<int, 4>[2]'
+// CHECK-NEXT: ArrayInitIndexExpr {{.*}} 'unsigned long'
+ int8 c = A;
+}
+
+
+
+
diff --git a/clang/test/SemaHLSL/Language/ElementwiseCast-errors.hlsl b/clang/test/SemaHLSL/Language/ElementwiseCast-errors.hlsl
index 9417249383469..30591507b3260 100644
--- a/clang/test/SemaHLSL/Language/ElementwiseCast-errors.hlsl
+++ b/clang/test/SemaHLSL/Language/ElementwiseCast-errors.hlsl
@@ -4,7 +4,7 @@ export void cantCast() {
int A[3] = {1,2,3};
int B[4] = {1,2,3,4};
B = (int[4])A;
- // expected-error at -1 {{C-style cast from 'int *' to 'int[4]' is not allowed}}
+ // expected-error at -1 {{C-style cast from 'int[3]' to 'int[4]' is not allowed}}
}
struct S {
More information about the cfe-commits
mailing list