Author: Joshua Batista
Date: 2026-08-17T10:12:09-07:00
New Revision: cf7e84e3f48a58f97af0abce7fd24fdb4b1f5797

URL: 
https://github.com/llvm/llvm-project/commit/cf7e84e3f48a58f97af0abce7fd24fdb4b1f5797
DIFF: 
https://github.com/llvm/llvm-project/commit/cf7e84e3f48a58f97af0abce7fd24fdb4b1f5797.diff

LOG: Test locally scoped resources (#190037)

This PR adds tests to clang to document local resource behavior.
Tests that emit any diagnostics in Sema go to Semahlsl. Test
organization is described here: https://github.com/llvm/wg-hlsl/pull/414

Fixes: https://github.com/llvm/llvm-project/issues/214537
Context: https://github.com/llvm/wg-hlsl/pull/414

Assisted by: Github Copilot

Added: 
    clang/test/CodeGenHLSL/resources/Local-Resources/array.hlsl
    
clang/test/CodeGenHLSL/resources/Local-Resources/consolidated_assignments.hlsl
    
clang/test/CodeGenHLSL/resources/Local-Resources/init_from_global_array_dynamic_index.hlsl
    clang/test/CodeGenHLSL/resources/Local-Resources/static_local.hlsl
    
clang/test/CodeGenHLSL/resources/Local-Resources/ternary_lvalue_unambiguous.hlsl
    
clang/test/SemaHLSL/Resources/Local-Resources/array_partial_init_dynamic.hlsl
    clang/test/SemaHLSL/Resources/Local-Resources/assign_wrong_type.hlsl
    clang/test/SemaHLSL/Resources/Local-Resources/bindings.hlsl
    clang/test/SemaHLSL/Resources/Local-Resources/bindings_errs.hlsl
    
clang/test/SemaHLSL/Resources/Local-Resources/branched_reassign_ambiguous.hlsl
    clang/test/SemaHLSL/Resources/Local-Resources/const_local_store.hlsl
    clang/test/SemaHLSL/Resources/Local-Resources/explicit_register.hlsl
    clang/test/SemaHLSL/Resources/Local-Resources/static_const.hlsl

Modified: 
    clang/test/SemaHLSL/Language/Volatile.hlsl

Removed: 
    clang/test/SemaHLSL/local_resource_bindings.hlsl
    clang/test/SemaHLSL/local_resource_bindings_errs.hlsl


################################################################################
diff  --git a/clang/test/CodeGenHLSL/resources/Local-Resources/array.hlsl 
b/clang/test/CodeGenHLSL/resources/Local-Resources/array.hlsl
new file mode 100644
index 0000000000000..d139c989203e4
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Local-Resources/array.hlsl
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -triple 
dxil-pc-shadermodel6.6-compute %s -emit-llvm -O1 -o - | FileCheck %s
+
+RWByteAddressBuffer Out : register(u0);
+RWByteAddressBuffer Aux : register(u1);
+
+[numthreads(1,1,1)]
+void main() {
+    RWByteAddressBuffer Arr[2];
+    RWByteAddressBuffer Arr2[1];
+    Arr[0] = Out;
+    Arr2[0] = Aux;
+    Arr[0].Store(0, 42);
+    Arr2[0].Store(4, 99);
+}
+
+// CHECK-LABEL: define {{.*}}@main(
+// Out's handle (u0, space0) flows into Store 42 at offset 0; Aux's (u1, 
space0) into Store 99 at offset 4.
+// CHECK: %[[H0:[^ ]+]] = tail call {{.*}}handlefrombinding{{.*}}(i32 0, i32 0,
+// CHECK: %[[H1:[^ ]+]] = tail call {{.*}}handlefrombinding{{.*}}(i32 0, i32 1,
+// CHECK: %[[P0:[^ ]+]] = call ptr {{.*}}getpointer{{.*}}(target({{.*}}) 
%[[H0]], i32 0)
+// CHECK: store i32 42, ptr %[[P0]]
+// CHECK: %[[P1:[^ ]+]] = call ptr {{.*}}getpointer{{.*}}(target({{.*}}) 
%[[H1]], i32 4)
+// CHECK: store i32 99, ptr %[[P1]]

diff  --git 
a/clang/test/CodeGenHLSL/resources/Local-Resources/consolidated_assignments.hlsl
 
b/clang/test/CodeGenHLSL/resources/Local-Resources/consolidated_assignments.hlsl
new file mode 100644
index 0000000000000..f25d8f781249e
--- /dev/null
+++ 
b/clang/test/CodeGenHLSL/resources/Local-Resources/consolidated_assignments.hlsl
@@ -0,0 +1,108 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -triple 
dxil-pc-shadermodel6.6-compute %s -emit-llvm -O1 -Wno-unused-value -o - | 
FileCheck %s
+
+// Consolidated coverage for local-resource assignment/initialization patterns
+// that must fold to a single unique global binding.
+//
+// Using two distinct globals (u0/u1) lets us prove that only GBuf0's binding
+// materializes — all other reassignments fold away.
+//
+// Arrays of resources are covered separately by array.hlsl.
+
+RWByteAddressBuffer GBuf0 : register(u0);
+RWByteAddressBuffer GBuf1 : register(u1);
+
+/// Mixed payload: a resource member alongside a non-resource one, so we also
+/// cover a resource field being tracked independently of surrounding data.
+struct ResHolder {
+    RWByteAddressBuffer Buf;
+    uint Value;
+};
+
+// Function returning a resource by way of a local — exercised as an
+// aggregate-init element and as a chained-call receiver 
(`GetBuf().Store(...)`).
+RWByteAddressBuffer GetBuf() {
+    RWByteAddressBuffer Local = GBuf0;
+    return Local;
+}
+
+// `inout` parameter: the callee both reads and could write back the handle.
+void DoStore(inout RWByteAddressBuffer Buf, uint Idx) {
+    Buf.Store(Idx, 42);
+}
+void ForwardStore(RWByteAddressBuffer Buf, uint Idx) {
+    DoStore(Buf, Idx);
+}
+
+// `out` parameter: the callee assigns a global into the caller's local.
+void WriteThrough(out RWByteAddressBuffer Buf) {
+    Buf = GBuf0;
+}
+
+[numthreads(1,1,1)]
+void main(uint GI : SV_GroupIndex) {
+  // CHECK-LABEL: define {{.*}}@main(
+
+  /// Only GBuf0 (register u0, space 0) materializes; every other
+  /// init/reassignment resolves back to it or is folded away.
+  // CHECK: %[[H:[^ ]+]] = tail call {{.*}}handlefrombinding{{.*}}(i32 0, i32 
0,
+
+  /// GBuf1 (u1) never materializes — all reassignments through it are folded
+  /// away. Resources are materialized at the top of the entry point, so this
+  /// must be checked here rather than at the end of the file.
+  // CHECK-NOT: handlefrombinding{{.*}}(i32 0, i32 1,
+
+  /// Aggregate init: brace-init a struct with a function-returned resource.
+  ResHolder H = {GetBuf(), 0};
+  /// Expression init: ternary in the initializer folds to H.Buf (= GBuf0).
+  RWByteAddressBuffer Buf = (true ? H.Buf : GBuf1);
+  /// Dead reassignment on the `false` path — folded away.
+  if (false)
+    Buf = GBuf1;
+  /// Self-assign: `Buf = Buf` is a no-op.
+  if (true)
+    Buf = Buf;
+  /// Alias chain: Buf → Alias preserves GBuf0's identity.
+  RWByteAddressBuffer Alias = Buf;
+  /// Comma initializer: right operand (= Alias = GBuf0) wins.
+  RWByteAddressBuffer Comma = (GBuf1, Alias);
+
+  /// Forwarding through a call chain: ForwardStore → DoStore (`inout`) stores
+  /// 42 at offset 0.
+  // CHECK: %[[P0:[^ ]+]] = call ptr {{.*}}getpointer{{.*}}(target({{.*}}) 
%[[H]], i32 0)
+  // CHECK: store i32 42, ptr %[[P0]]
+  ForwardStore(Comma, 0);
+
+  /// Chained call: method invoked directly on a function return; stores at
+  /// offset 4.
+  // CHECK: %[[P1:[^ ]+]] = call ptr {{.*}}getpointer{{.*}}(target({{.*}}) 
%[[H]], i32 4)
+  // CHECK: store i32 42, ptr %[[P1]]
+  GetBuf().Store(4, 42);
+
+  /// Init directly from a function return.
+  // CHECK: %[[P2:[^ ]+]] = call ptr {{.*}}getpointer{{.*}}(target({{.*}}) 
%[[H]], i32 8)
+  // CHECK: store i32 42, ptr %[[P2]]
+  RWByteAddressBuffer FromRet = GetBuf();
+  FromRet.Store(8, 42);
+
+  /// Ternary whose arms are the same global — folds even under a runtime
+  /// condition.
+  // CHECK: %[[P3:[^ ]+]] = call ptr {{.*}}getpointer{{.*}}(target({{.*}}) 
%[[H]], i32 12)
+  // CHECK: store i32 42, ptr %[[P3]]
+  RWByteAddressBuffer BothSame = (GI != 0) ? GBuf0 : GBuf0;
+  BothSame.Store(12, 42);
+
+  /// `out` param: the callee initializes an otherwise-uninitialized local.
+  // CHECK: %[[P4:[^ ]+]] = call ptr {{.*}}getpointer{{.*}}(target({{.*}}) 
%[[H]], i32 16)
+  // CHECK: store i32 42, ptr %[[P4]]
+  RWByteAddressBuffer FromOut;
+  WriteThrough(FromOut);
+  FromOut.Store(16, 42);
+
+  /// Struct member assignment with a non-resource field alongside it.
+  // CHECK: %[[P5:[^ ]+]] = call ptr {{.*}}getpointer{{.*}}(target({{.*}}) 
%[[H]], i32 20)
+  // CHECK: store i32 42, ptr %[[P5]]
+  ResHolder Mixed;
+  Mixed.Buf = GBuf0;
+  Mixed.Value = 42;
+  Mixed.Buf.Store(20, Mixed.Value);
+}

diff  --git 
a/clang/test/CodeGenHLSL/resources/Local-Resources/init_from_global_array_dynamic_index.hlsl
 
b/clang/test/CodeGenHLSL/resources/Local-Resources/init_from_global_array_dynamic_index.hlsl
new file mode 100644
index 0000000000000..ac752cc73eeeb
--- /dev/null
+++ 
b/clang/test/CodeGenHLSL/resources/Local-Resources/init_from_global_array_dynamic_index.hlsl
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -triple 
dxil-pc-shadermodel6.6-compute %s -emit-llvm -O1 -o - | FileCheck %s
+
+RWByteAddressBuffer GBufArray[4] : register(u0);
+
+// CHECK-LABEL: define {{.*}}@main(
+[numthreads(1,1,1)]
+void main(uint3 Tid : SV_DispatchThreadID) {
+// The index is not statically known, so it must survive as a runtime value and
+// be threaded into the index operand of the binding rather than folded away.
+// The binding covers the whole array: register u0, space 0, range 4.
+// CHECK: %[[TID:.*]] = tail call i32 @llvm.dx.thread.id(i32 0)
+// CHECK: %[[AND:.*]] = and i32 %[[TID]], 3
+// CHECK: call target("dx.RawBuffer", i8, 1, 0) 
@llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_1_0t(i32 0, i32 0, i32 4, 
i32 %[[AND]],
+    RWByteAddressBuffer Buf = GBufArray[Tid.x & 3];
+    Buf.Store(0, 42);
+}

diff  --git 
a/clang/test/CodeGenHLSL/resources/Local-Resources/static_local.hlsl 
b/clang/test/CodeGenHLSL/resources/Local-Resources/static_local.hlsl
new file mode 100644
index 0000000000000..57a37836c71cb
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/Local-Resources/static_local.hlsl
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -triple 
dxil-pc-shadermodel6.6-compute %s -emit-llvm -disable-llvm-passes -o - | 
FileCheck %s
+
+RWByteAddressBuffer GBuf0 : register(u0);
+
+void Pass_StaticLocal(uint Idx) {
+    static RWByteAddressBuffer Buf = GBuf0;
+    Buf.Store(Idx * 4, 1);
+}
+
+[numthreads(1,1,1)]
+void main(uint3 Tid : SV_DispatchThreadID) {
+    Pass_StaticLocal(Tid.x);
+}
+
+// Binding wrapper for GBuf0 (register(u0, space0)) is emitted.
+// The static local Buf is copy-constructed from GBuf0; its Store call writes 
through the static.
+// CHECK-DAG: call {{.*}}__createFromBinding{{.*}}@_ZL5GBuf0,
+// CHECK-LABEL: define {{.*}}@_Z16Pass_StaticLocal
+// CHECK: call void @{{.*}}RWByteAddressBufferC1{{.*}}(ptr {{.*}} 
@_ZZ16Pass_StaticLocaljE3Buf, ptr {{.*}} @_ZL5GBuf0
+// CHECK: call void @{{.*}}RWByteAddressBuffer5Store{{.*}}(ptr {{.*}} 
@_ZZ16Pass_StaticLocaljE3Buf,

diff  --git 
a/clang/test/CodeGenHLSL/resources/Local-Resources/ternary_lvalue_unambiguous.hlsl
 
b/clang/test/CodeGenHLSL/resources/Local-Resources/ternary_lvalue_unambiguous.hlsl
new file mode 100644
index 0000000000000..ac257a94025f2
--- /dev/null
+++ 
b/clang/test/CodeGenHLSL/resources/Local-Resources/ternary_lvalue_unambiguous.hlsl
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -triple 
dxil-pc-shadermodel6.6-compute %s -emit-llvm -O1 -o - | FileCheck %s
+
+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) = GBuf0;
+    A.Store(Tid.x * 4, 1);
+    B.Store(Tid.x * 4, 2);
+}
+
+// CHECK-LABEL: define {{.*}}@main(
+// After (true ? A : B) = GBuf0, A stays bound to GBuf0 (u0) and B stays bound 
to GBuf1 (u1).
+// CHECK: %[[H0:[^ ]+]] = tail call {{.*}}handlefrombinding{{.*}}(i32 0, i32 0,
+// CHECK: %[[H1:[^ ]+]] = tail call {{.*}}handlefrombinding{{.*}}(i32 0, i32 1,
+// A.Store(Tid.x*4, 1) writes through GBuf0.
+// CHECK: %[[PA:[^ ]+]] = call ptr {{.*}}getpointer{{.*}}(target({{.*}}) 
%[[H0]], i32 %{{[^,)]+}})
+// CHECK: store i32 1, ptr %[[PA]]
+// B.Store(Tid.x*4, 2) writes through GBuf1.
+// CHECK: %[[PB:[^ ]+]] = call ptr {{.*}}getpointer{{.*}}(target({{.*}}) 
%[[H1]], i32 %{{[^,)]+}})
+// CHECK: store i32 2, ptr %[[PB]]

diff  --git a/clang/test/SemaHLSL/Language/Volatile.hlsl 
b/clang/test/SemaHLSL/Language/Volatile.hlsl
index 5750c2b2f10ae..4b0f1e63baf34 100644
--- a/clang/test/SemaHLSL/Language/Volatile.hlsl
+++ b/clang/test/SemaHLSL/Language/Volatile.hlsl
@@ -5,6 +5,6 @@ RWByteAddressBuffer gBuf : register(u0);
 [numthreads(1,1,1)]
 void main() {
     // expected-error@+1 {{unknown type name 'volatile'}}
-    volatile RWByteAddressBuffer buf = gBuf; // expected-error {{expected ';' 
at end of declaration}}
-    buf.Store(0, 42); // expected-error {{use of undeclared identifier 'buf'}}
+    volatile int x = 3;
+    gBuf.Store(0, x);
 }

diff  --git 
a/clang/test/SemaHLSL/Resources/Local-Resources/array_partial_init_dynamic.hlsl 
b/clang/test/SemaHLSL/Resources/Local-Resources/array_partial_init_dynamic.hlsl
new file mode 100644
index 0000000000000..e21ad79a1af62
--- /dev/null
+++ 
b/clang/test/SemaHLSL/Resources/Local-Resources/array_partial_init_dynamic.hlsl
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -triple 
dxil-pc-shadermodel6.6-compute %s -emit-llvm -o - -verify
+
+// A *local* resource array indexed by a runtime value. Every element the index
+// can select holds the same global, so there is one unique binding and nothing
+// to warn about. `& 1` keeps the index off the unassigned elements 2 and 3.
+// Sema-only: the backend can't lower this yet (llvm/llvm-project#192538).
+
+// expected-no-diagnostics
+RWByteAddressBuffer Out : register(u0);
+
+[numthreads(1,1,1)]
+void main(uint3 Tid : SV_DispatchThreadID) {
+    RWByteAddressBuffer Arr[4];
+    Arr[0] = Out;
+    Arr[1] = Out;
+    Arr[Tid.x & 1].Store(0, 42);
+}

diff  --git 
a/clang/test/SemaHLSL/Resources/Local-Resources/assign_wrong_type.hlsl 
b/clang/test/SemaHLSL/Resources/Local-Resources/assign_wrong_type.hlsl
new file mode 100644
index 0000000000000..666d1097d0bf9
--- /dev/null
+++ b/clang/test/SemaHLSL/Resources/Local-Resources/assign_wrong_type.hlsl
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -triple 
dxil-pc-shadermodel6.6-compute %s -emit-llvm -o - -verify
+
+// expected-note@*:* {{candidate function not viable: no known conversion from 
'RWStructuredBuffer<uint>' (aka 'RWStructuredBuffer<unsigned int>') to 'const 
hlsl::RWByteAddressBuffer' for 1st argument}}
+RWByteAddressBuffer GBuf0 : register(u0);
+RWStructuredBuffer<uint> GSB : register(u1);
+
+[numthreads(1,1,1)]
+void main(uint3 Tid : SV_DispatchThreadID) {
+    RWByteAddressBuffer Buf = GBuf0;
+    RWStructuredBuffer<uint> Sb = GSB;
+// expected-error@+1 {{no viable overloaded '='}}
+    Buf = Sb;
+}

diff  --git a/clang/test/SemaHLSL/local_resource_bindings.hlsl 
b/clang/test/SemaHLSL/Resources/Local-Resources/bindings.hlsl
similarity index 72%
rename from clang/test/SemaHLSL/local_resource_bindings.hlsl
rename to clang/test/SemaHLSL/Resources/Local-Resources/bindings.hlsl
index 58e7bf47d2d0d..c64818029b40d 100644
--- a/clang/test/SemaHLSL/local_resource_bindings.hlsl
+++ b/clang/test/SemaHLSL/Resources/Local-Resources/bindings.hlsl
@@ -11,19 +11,12 @@ cbuffer c {
     bool cond;
 };
 
-void no_initial_assignment(uint idx) {
-    RWStructuredBuffer<uint> Out;
-    if (cond) {
-        Out = Out1;
-    }
-    Out[idx] = In[idx];
-}
-
-void assignment_to_uninitialized(uint idx) {
-    RWStructuredBuffer<uint> Out;
-    Out = Out;
-    Out[idx] = In[idx];
-}
+// The uninitialized-use cases that were here (`no_initial_assignment` and
+// `assignment_to_uninitialized`) were removed rather than pinned with
+// expected-no-diagnostics: we ought to diagnose them, so asserting silence
+// would entrench a bug. Tracked by
+// https://github.com/llvm/llvm-project/issues/216193, which carries both
+// repros and should restore coverage here once we diagnose.
 
 void same_assignment(uint idx) {
     RWStructuredBuffer<uint> Out = Out1;

diff  --git a/clang/test/SemaHLSL/local_resource_bindings_errs.hlsl 
b/clang/test/SemaHLSL/Resources/Local-Resources/bindings_errs.hlsl
similarity index 81%
rename from clang/test/SemaHLSL/local_resource_bindings_errs.hlsl
rename to clang/test/SemaHLSL/Resources/Local-Resources/bindings_errs.hlsl
index 7404e444390b1..1a4b33ec86653 100644
--- a/clang/test/SemaHLSL/local_resource_bindings_errs.hlsl
+++ b/clang/test/SemaHLSL/Resources/Local-Resources/bindings_errs.hlsl
@@ -15,14 +15,8 @@ void conditional_initialization(uint idx) {
     Out[idx] = In[idx];
 }
 
-void branched_assignment(uint idx) {
-    RWStructuredBuffer<uint> Out = Out0; // expected-note {{variable 'Out' is 
declared here}}
-    if (cond) {
-        // expected-warning@+1 {{assignment of 'Out1' to local resource 'Out' 
is not to the same unique global resource}}
-        Out = Out1;
-    }
-    Out[idx] = In[idx];
-}
+// The plain `if (cond) { Out = Out1; }` reassignment is covered by the
+// dedicated branched_reassign_ambiguous.hlsl.
 
 void branched_assignment_with_array(uint idx) {
     RWStructuredBuffer<uint> Out = Out0; // expected-note {{variable 'Out' is 
declared here}}

diff  --git 
a/clang/test/SemaHLSL/Resources/Local-Resources/branched_reassign_ambiguous.hlsl
 
b/clang/test/SemaHLSL/Resources/Local-Resources/branched_reassign_ambiguous.hlsl
new file mode 100644
index 0000000000000..b2c4b005178dd
--- /dev/null
+++ 
b/clang/test/SemaHLSL/Resources/Local-Resources/branched_reassign_ambiguous.hlsl
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -triple 
dxil-pc-shadermodel6.6-compute %s -emit-llvm -o - -verify
+
+RWByteAddressBuffer GBuf1 : register(u1);
+RWByteAddressBuffer GBuf2 : register(u2);
+
+void Pass_BranchedReassign(uint Cond, uint Idx) {
+// expected-note@+1 {{variable 'Buf' is declared here}}
+    RWByteAddressBuffer Buf = GBuf1;
+    if (Cond) {
+// expected-warning@+1 {{assignment of 'GBuf2' to local resource 'Buf' is not 
to the same unique global resource}}
+        Buf = GBuf2;
+    }
+    Buf.Store(Idx * 4, 32);
+}
+
+[numthreads(8,8,1)]
+void main(uint3 Tid : SV_DispatchThreadID) {
+    uint Idx = Tid.x + Tid.y * 8;
+    Pass_BranchedReassign(Tid.x & 1, Idx);
+}

diff  --git 
a/clang/test/SemaHLSL/Resources/Local-Resources/const_local_store.hlsl 
b/clang/test/SemaHLSL/Resources/Local-Resources/const_local_store.hlsl
new file mode 100644
index 0000000000000..2b35107bea304
--- /dev/null
+++ b/clang/test/SemaHLSL/Resources/Local-Resources/const_local_store.hlsl
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -triple 
dxil-pc-shadermodel6.6-compute %s -emit-llvm -o - -verify
+
+// A const local resource rejects mutating methods. Reading is still allowed,
+// so LoadConst shows the restriction is on mutation rather than on const
+// resources generally.
+
+// expected-note@*:* {{candidate function template not viable: 'this' argument 
has type 'const RWByteAddressBuffer', but method is not marked const}}
+// expected-note@*:* {{candidate function not viable: 'this' argument has type 
'const RWByteAddressBuffer', but method is not marked const}}
+RWByteAddressBuffer GBuf : register(u0);
+
+uint LoadConst(const RWByteAddressBuffer Buf) {
+    return Buf.Load(0);
+}
+
+[numthreads(1,1,1)]
+void main() {
+    const RWByteAddressBuffer Local = GBuf;
+    uint Val = LoadConst(Local);
+// expected-error@+1 {{no matching member function for call to 'Store'}}
+    Local.Store(0, Val);
+}

diff  --git 
a/clang/test/SemaHLSL/Resources/Local-Resources/explicit_register.hlsl 
b/clang/test/SemaHLSL/Resources/Local-Resources/explicit_register.hlsl
new file mode 100644
index 0000000000000..33ab268ab5c5d
--- /dev/null
+++ b/clang/test/SemaHLSL/Resources/Local-Resources/explicit_register.hlsl
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -triple 
dxil-pc-shadermodel6.6-compute %s -emit-llvm -o - -verify
+
+RWByteAddressBuffer G0 : register(u0);
+
+[numthreads(1,1,1)]
+void main(uint3 Tid : SV_DispatchThreadID)
+{
+// expected-error@+1 {{'register' attribute only applies to cbuffer/tbuffer 
and external global variables}}
+    RWByteAddressBuffer Buf : register(u5) = G0;
+    Buf.Store(Tid.x * 4, 42);
+}

diff  --git a/clang/test/SemaHLSL/Resources/Local-Resources/static_const.hlsl 
b/clang/test/SemaHLSL/Resources/Local-Resources/static_const.hlsl
new file mode 100644
index 0000000000000..5ad3e237e8e3e
--- /dev/null
+++ b/clang/test/SemaHLSL/Resources/Local-Resources/static_const.hlsl
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -triple 
dxil-pc-shadermodel6.6-compute %s -emit-llvm -o - -verify
+
+// expected-no-diagnostics
+RWByteAddressBuffer GBuf0 : register(u0);
+
+void Fail_StaticConst(uint Idx) {
+    static const RWByteAddressBuffer Buf = GBuf0;
+    Buf.Load(Idx * 4);
+}
+
+[numthreads(1,1,1)]
+void main(uint3 Tid : SV_DispatchThreadID) {
+    Fail_StaticConst(Tid.x);
+}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to