diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md index 4da2a4f644..429dc56831 100644 --- a/docs/ReleaseNotes.md +++ b/docs/ReleaseNotes.md @@ -67,6 +67,10 @@ line upon naming the release. Refer to previous for appropriate section names. - Fixed an optimizer crash when scalarizing an out-of-bounds vector access [#8940](https://github.com/microsoft/DirectXShaderCompiler/issues/8940). +- Assigning to a conditional operator on objects, such as `(c ? a : b) = buf` + with resources, is now an "expression is not assignable" error like for + other types, instead of asserting or being silently dropped + [#8579](https://github.com/microsoft/DirectXShaderCompiler/issues/8579). ### Upcoming Preview Release diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 5d480a99ee..bf68852696 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -11159,8 +11159,14 @@ HLSLExternalSource::CheckVectorConditional(ExprResult &Cond, ExprResult &LHS, rightObjectKind == AR_TOBJ_MATRIX; if (!leftIsSimple || !rightIsSimple) { - if (leftObjectKind == AR_TOBJ_OBJECT && leftObjectKind == AR_TOBJ_OBJECT) { + if (leftObjectKind == AR_TOBJ_OBJECT && rightObjectKind == AR_TOBJ_OBJECT) { if (leftType == rightType) { + // As for the other types, the result is not an lvalue, so it can't be + // assigned to. + if (LHS.get()->isLValue()) + LHS.set(CreateLValueToRValueCast(LHS.get())); + if (RHS.get()->isLValue()) + RHS.set(CreateLValueToRValueCast(RHS.get())); return leftType; } } diff --git a/tools/clang/test/SemaHLSL/conditional-object-not-assignable.hlsl b/tools/clang/test/SemaHLSL/conditional-object-not-assignable.hlsl new file mode 100644 index 0000000000..9b72ce7fcf --- /dev/null +++ b/tools/clang/test/SemaHLSL/conditional-object-not-assignable.hlsl @@ -0,0 +1,22 @@ +// RUN: %dxc -Tcs_6_0 -verify %s + +// Like for scalars, vectors and matrices, a conditional operator on objects +// yields an rvalue, so it can't be assigned to. + +RWByteAddressBuffer gBuf0 : register(u0); +RWByteAddressBuffer gBuf1 : register(u1); + +[numthreads(1, 1, 1)] +void main(uint3 tid : SV_DispatchThreadID) { + RWByteAddressBuffer a = gBuf0; + RWByteAddressBuffer b = gBuf1; + (true ? a : b) = gBuf1; /* expected-error {{expression is not assignable}} */ + + uint x = 1, y = 2; + (true ? x : y) = 5; /* expected-error {{expression is not assignable}} */ + + // Using the result as an rvalue is still fine. + RWByteAddressBuffer c = true ? a : b; + c.Store(0, 1); + (false ? a : b).Store(4, 2); +}