[clang] [SemaHLSL] Verify assignment of local resources (PR #176793)
Finn Plummer via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 20 09:30:05 PST 2026
https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/176793
>From 007a060105b094abd17802246cd16835934d391b Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Mon, 19 Jan 2026 09:31:01 -0800
Subject: [PATCH 1/6] [SemaHLSL] Verify assignment of local resources
---
.../clang/Basic/DiagnosticSemaKinds.td | 3 +
clang/include/clang/Sema/SemaHLSL.h | 15 ++++
clang/lib/Sema/SemaHLSL.cpp | 76 +++++++++++++++++--
.../test/SemaHLSL/local_resource_binding.hlsl | 56 ++++++++++++++
.../SemaHLSL/local_resource_binding_errs.hlsl | 41 ++++++++++
5 files changed, 185 insertions(+), 6 deletions(-)
create mode 100644 clang/test/SemaHLSL/local_resource_binding.hlsl
create mode 100644 clang/test/SemaHLSL/local_resource_binding_errs.hlsl
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index eb7a608f798b8..87673e944fc0d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13431,6 +13431,9 @@ def err_hlsl_incomplete_resource_array_in_function_param: Error<
"incomplete resource array in a function parameter">;
def err_hlsl_assign_to_global_resource: Error<
"assignment to global resource variable %0 is not allowed">;
+def err_hlsl_assigning_local_resource_is_not_unique
+ : Error<"assignment to local resource %0 is not to same unique global "
+ "resource">;
def err_hlsl_push_constant_unique
: Error<"cannot have more than one push constant block">;
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 99d8ed137b0c2..48daebbf61c90 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -132,6 +132,14 @@ class SemaHLSL : public SemaBase {
bool ActOnUninitializedVarDecl(VarDecl *D);
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU);
void CheckEntryPoint(FunctionDecl *FD);
+
+ // Return an info if the expr has common global binding info; returns
+ // std::nullopt if the expr refers to non-unique global bindings, returns
+ // nullptr if it isn't refer to any global binding, otherwise it returns
+ // a reference to the global binding info.
+ std::optional<const DeclBindingInfo *> GetGlobalBinding(Expr *E);
+
+ // Return true if everything is ok; returns false if there was an error.
bool CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr,
SourceLocation Loc);
@@ -230,6 +238,13 @@ class SemaHLSL : public SemaBase {
// List of all resource bindings
ResourceBindings Bindings;
+ // Map of local resource variables to their used global resource.
+ //
+ // The Binding can be a nullptr, in which case, the variable has not be
+ // initialized or assigned to yet.
+ llvm::DenseMap<const VarDecl *, const DeclBindingInfo *>
+ LocalResourceBindings;
+
// Global declaration collected for the $Globals default constant
// buffer which will be created at the end of the translation unit.
llvm::SmallVector<Decl *> DefaultCBufferDecls;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index f15b274a65a53..cd00167ceb72f 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -4398,7 +4398,35 @@ bool SemaHLSL::ActOnUninitializedVarDecl(VarDecl *VD) {
return false;
}
-// Return true if everything is ok; returns false if there was an error.
+std::optional<const DeclBindingInfo *> SemaHLSL::GetGlobalBinding(Expr *E) {
+ if (auto *Ternary = dyn_cast<ConditionalOperator>(E)) {
+ auto TrueInfo = GetGlobalBinding(Ternary->getTrueExpr());
+ auto FalseInfo = GetGlobalBinding(Ternary->getFalseExpr());
+ if (!TrueInfo || !FalseInfo)
+ return std::nullopt;
+ if (*TrueInfo != *FalseInfo)
+ return std::nullopt;
+ return TrueInfo;
+ }
+
+ if (auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
+ E = ASE->getBase()->IgnoreParenImpCasts();
+
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens()))
+ if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+ const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();
+ if (Ty->isArrayType())
+ Ty = Ty->getArrayElementTypeNoTypeQual();
+ if (const auto *AttrResType =
+ HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {
+ ResourceClass RC = AttrResType->getAttrs().ResourceClass;
+ return Bindings.getDeclBindingInfo(VD, RC);
+ }
+ }
+
+ return nullptr;
+}
+
bool SemaHLSL::CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr,
Expr *RHSExpr, SourceLocation Loc) {
assert((LHSExpr->getType()->isHLSLResourceRecord() ||
@@ -4412,14 +4440,37 @@ bool SemaHLSL::CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr,
while (auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
E = ASE->getBase()->IgnoreParenImpCasts();
+ auto RHSBinding = GetGlobalBinding(RHSExpr);
+ if (!RHSBinding) {
+ SemaRef.Diag(Loc, diag::err_hlsl_assigning_local_resource_is_not_unique)
+ << RHSExpr;
+ return false;
+ }
+
// Report error if LHS is a non-static resource declared at a global scope.
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
- if (VD->hasGlobalStorage() && VD->getStorageClass() != SC_Static) {
- // assignment to global resource is not allowed
- SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
- SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
- return false;
+ if (VD->getStorageClass() != SC_Static) {
+ if (VD->hasGlobalStorage()) {
+ // assignment to global resource is not allowed
+ SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
+ SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
+ return false;
+ }
+
+ // Ensure assignment to a non-static local resource does not conflict
+ // with previous assignments to global resources
+ const DeclBindingInfo *LHSBinding = LocalResourceBindings[VD];
+ if (!LHSBinding) {
+ // occurs when local resource was instantiated without an expression
+ LocalResourceBindings[VD] = *RHSBinding;
+ } else if (LHSBinding != *RHSBinding) {
+ SemaRef.Diag(Loc,
+ diag::err_hlsl_assigning_local_resource_is_not_unique)
+ << RHSExpr;
+ SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
+ return false;
+ }
}
}
}
@@ -4797,6 +4848,19 @@ bool SemaHLSL::transformInitList(const InitializedEntity &Entity,
}
bool SemaHLSL::handleInitialization(VarDecl *VDecl, Expr *&Init) {
+ // If initializing a local resource, register the binding it is using
+ if (VDecl->getType()->isHLSLResourceRecord() && !VDecl->hasGlobalStorage())
+ if (auto *InitExpr = Init) {
+ if (auto Binding = GetGlobalBinding(InitExpr)) {
+ LocalResourceBindings.insert({VDecl, *Binding});
+ } else {
+ SemaRef.Diag(Init->getBeginLoc(),
+ diag::err_hlsl_assigning_local_resource_is_not_unique)
+ << Init;
+ return false;
+ }
+ }
+
const HLSLVkConstantIdAttr *ConstIdAttr =
VDecl->getAttr<HLSLVkConstantIdAttr>();
if (!ConstIdAttr)
diff --git a/clang/test/SemaHLSL/local_resource_binding.hlsl b/clang/test/SemaHLSL/local_resource_binding.hlsl
new file mode 100644
index 0000000000000..3059452b49ef0
--- /dev/null
+++ b/clang/test/SemaHLSL/local_resource_binding.hlsl
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -verify %s
+
+// expected-no-diagnostics
+
+RWBuffer<int> In : register(u0);
+RWStructuredBuffer<int> Out0 : register(u1);
+RWStructuredBuffer<int> Out1 : register(u2);
+RWStructuredBuffer<int> OutArr[];
+
+cbuffer c {
+ bool cond;
+};
+
+void no_initial_assignment(int idx) {
+ RWStructuredBuffer<int> Out;
+ if (cond) {
+ Out = Out1;
+ }
+ Out[idx] = In[idx];
+}
+
+void same_assignment(int idx) {
+ RWStructuredBuffer<int> Out = Out1;
+ if (cond) {
+ Out = Out1;
+ }
+ Out[idx] = In[idx];
+}
+
+void conditional_initialization_with_index(int idx) {
+ RWStructuredBuffer<int> Out = cond ? OutArr[0] : OutArr[1];
+ Out[idx] = In[idx];
+}
+
+void conditional_assignment_with_index(int idx) {
+ RWStructuredBuffer<int> Out;
+ if (cond) {
+ Out = OutArr[0];
+ } else {
+ Out = OutArr[1];
+ }
+ Out[idx] = In[idx];
+}
+
+void reassignment(int idx) {
+ RWStructuredBuffer<int> Out = Out0;
+ if (cond) {
+ Out = Out0;
+ }
+ Out[idx] = In[idx];
+}
+
+void conditional_result_in_same(int idx) {
+ RWStructuredBuffer<int> Out = cond ? Out0 : Out0;
+ Out[idx] = In[idx];
+}
diff --git a/clang/test/SemaHLSL/local_resource_binding_errs.hlsl b/clang/test/SemaHLSL/local_resource_binding_errs.hlsl
new file mode 100644
index 0000000000000..163d3c4493ca2
--- /dev/null
+++ b/clang/test/SemaHLSL/local_resource_binding_errs.hlsl
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -verify %s
+
+RWBuffer<int> In : register(u0);
+RWStructuredBuffer<int> Out0 : register(u1);
+RWStructuredBuffer<int> Out1 : register(u2);
+RWStructuredBuffer<int> OutArr[];
+
+cbuffer c {
+ bool cond;
+};
+
+void conditional_initialization(int idx) {
+ // expected-error at +1 {{assignment to local resource 'cond ? Out0 : Out1' is not to same unique global resource}}
+ RWStructuredBuffer<int> Out = cond ? Out0 : Out1;
+ Out[idx] = In[idx];
+}
+
+void branched_assignment(int idx) {
+ RWStructuredBuffer<int> Out = Out0; // expected-note {{variable 'Out' is declared here}}
+ if (cond) {
+ // expected-error at +1 {{assignment to local resource 'Out1' is not to same unique global resource}}
+ Out = Out1;
+ }
+ Out[idx] = In[idx];
+}
+
+void branched_assignment_with_array(int idx) {
+ RWStructuredBuffer<int> Out = Out0; // expected-note {{variable 'Out' is declared here}}
+ if (cond) {
+ // expected-error at +1 {{assignment to local resource 'OutArr[0]' is not to same unique global resource}}
+ Out = OutArr[0];
+ }
+ Out[idx] = In[idx];
+}
+
+void conditional_assignment(int idx) {
+ RWStructuredBuffer<int> Out;
+ // expected-error at +1 {{assignment to local resource 'cond ? Out0 : Out1' is not to same unique global resource}}
+ Out = cond ? Out0 : Out1;
+ Out[idx] = In[idx];
+}
>From 4c4fcf9936aa61a1766dd6bab147c7137baf8292 Mon Sep 17 00:00:00 2001
From: Finn Plummer <finn.c.plum at gmail.com>
Date: Mon, 19 Jan 2026 11:24:18 -0800
Subject: [PATCH 2/6] review: fix-up comments
Co-authored-by: Deric C. <cheung.deric at gmail.com>
---
clang/include/clang/Sema/SemaHLSL.h | 4 ++--
clang/lib/Sema/SemaHLSL.cpp | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 48daebbf61c90..d12dcc596989e 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -240,8 +240,8 @@ class SemaHLSL : public SemaBase {
// Map of local resource variables to their used global resource.
//
- // The Binding can be a nullptr, in which case, the variable has not be
- // initialized or assigned to yet.
+ // The binding can be a nullptr, in which case, the variable has yet to be
+ // initialized or assigned to.
llvm::DenseMap<const VarDecl *, const DeclBindingInfo *>
LocalResourceBindings;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index cd00167ceb72f..c41e48128cef9 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -4452,7 +4452,7 @@ bool SemaHLSL::CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr,
if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
if (VD->getStorageClass() != SC_Static) {
if (VD->hasGlobalStorage()) {
- // assignment to global resource is not allowed
+ // Assignment to a global resource is not allowed.
SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;
SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
return false;
@@ -4462,7 +4462,7 @@ bool SemaHLSL::CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr,
// with previous assignments to global resources
const DeclBindingInfo *LHSBinding = LocalResourceBindings[VD];
if (!LHSBinding) {
- // occurs when local resource was instantiated without an expression
+ // LHSBinding is a nullptr when the local resource is instantiated without an expression.
LocalResourceBindings[VD] = *RHSBinding;
} else if (LHSBinding != *RHSBinding) {
SemaRef.Diag(Loc,
@@ -4848,7 +4848,7 @@ bool SemaHLSL::transformInitList(const InitializedEntity &Entity,
}
bool SemaHLSL::handleInitialization(VarDecl *VDecl, Expr *&Init) {
- // If initializing a local resource, register the binding it is using
+ // If initializing a local resource, register the binding it is using.
if (VDecl->getType()->isHLSLResourceRecord() && !VDecl->hasGlobalStorage())
if (auto *InitExpr = Init) {
if (auto Binding = GetGlobalBinding(InitExpr)) {
>From 5eca470288d496b2d0f64e4db6b061aed862f0e4 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Mon, 19 Jan 2026 11:26:32 -0800
Subject: [PATCH 3/6] review: fix-up diagnostic message
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
clang/test/SemaHLSL/local_resource_binding_errs.hlsl | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 87673e944fc0d..5e206d84ab7c0 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13432,7 +13432,7 @@ def err_hlsl_incomplete_resource_array_in_function_param: Error<
def err_hlsl_assign_to_global_resource: Error<
"assignment to global resource variable %0 is not allowed">;
def err_hlsl_assigning_local_resource_is_not_unique
- : Error<"assignment to local resource %0 is not to same unique global "
+ : Error<"assignment to local resource %0 is not to the same unique global "
"resource">;
def err_hlsl_push_constant_unique
diff --git a/clang/test/SemaHLSL/local_resource_binding_errs.hlsl b/clang/test/SemaHLSL/local_resource_binding_errs.hlsl
index 163d3c4493ca2..807886d77bc7a 100644
--- a/clang/test/SemaHLSL/local_resource_binding_errs.hlsl
+++ b/clang/test/SemaHLSL/local_resource_binding_errs.hlsl
@@ -10,7 +10,7 @@ cbuffer c {
};
void conditional_initialization(int idx) {
- // expected-error at +1 {{assignment to local resource 'cond ? Out0 : Out1' is not to same unique global resource}}
+ // expected-error at +1 {{assignment to local resource 'cond ? Out0 : Out1' is not to the same unique global resource}}
RWStructuredBuffer<int> Out = cond ? Out0 : Out1;
Out[idx] = In[idx];
}
@@ -18,7 +18,7 @@ void conditional_initialization(int idx) {
void branched_assignment(int idx) {
RWStructuredBuffer<int> Out = Out0; // expected-note {{variable 'Out' is declared here}}
if (cond) {
- // expected-error at +1 {{assignment to local resource 'Out1' is not to same unique global resource}}
+ // expected-error at +1 {{assignment to local resource 'Out1' is not to same the unique global resource}}
Out = Out1;
}
Out[idx] = In[idx];
@@ -27,7 +27,7 @@ void branched_assignment(int idx) {
void branched_assignment_with_array(int idx) {
RWStructuredBuffer<int> Out = Out0; // expected-note {{variable 'Out' is declared here}}
if (cond) {
- // expected-error at +1 {{assignment to local resource 'OutArr[0]' is not to same unique global resource}}
+ // expected-error at +1 {{assignment to local resource 'OutArr[0]' is not to the same unique global resource}}
Out = OutArr[0];
}
Out[idx] = In[idx];
@@ -35,7 +35,7 @@ void branched_assignment_with_array(int idx) {
void conditional_assignment(int idx) {
RWStructuredBuffer<int> Out;
- // expected-error at +1 {{assignment to local resource 'cond ? Out0 : Out1' is not to same unique global resource}}
+ // expected-error at +1 {{assignment to local resource 'cond ? Out0 : Out1' is not to the same unique global resource}}
Out = cond ? Out0 : Out1;
Out[idx] = In[idx];
}
>From 8d0f91924d97fcddf72c76781b5f3af137294533 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Mon, 19 Jan 2026 11:26:47 -0800
Subject: [PATCH 4/6] clang-format
---
clang/lib/Sema/SemaHLSL.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index c41e48128cef9..021745ba26430 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -4462,7 +4462,8 @@ bool SemaHLSL::CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr,
// with previous assignments to global resources
const DeclBindingInfo *LHSBinding = LocalResourceBindings[VD];
if (!LHSBinding) {
- // LHSBinding is a nullptr when the local resource is instantiated without an expression.
+ // LHSBinding is a nullptr when the local resource is instantiated
+ // without an expression.
LocalResourceBindings[VD] = *RHSBinding;
} else if (LHSBinding != *RHSBinding) {
SemaRef.Diag(Loc,
>From 5c7f60d6c75f0954459a118991f73203ab430e06 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Mon, 19 Jan 2026 11:54:03 -0800
Subject: [PATCH 5/6] fix typo, whoops
---
clang/test/SemaHLSL/local_resource_binding_errs.hlsl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/SemaHLSL/local_resource_binding_errs.hlsl b/clang/test/SemaHLSL/local_resource_binding_errs.hlsl
index 807886d77bc7a..ad9a46b865965 100644
--- a/clang/test/SemaHLSL/local_resource_binding_errs.hlsl
+++ b/clang/test/SemaHLSL/local_resource_binding_errs.hlsl
@@ -18,7 +18,7 @@ void conditional_initialization(int idx) {
void branched_assignment(int idx) {
RWStructuredBuffer<int> Out = Out0; // expected-note {{variable 'Out' is declared here}}
if (cond) {
- // expected-error at +1 {{assignment to local resource 'Out1' is not to same the unique global resource}}
+ // expected-error at +1 {{assignment to local resource 'Out1' is not to the same unique global resource}}
Out = Out1;
}
Out[idx] = In[idx];
>From 1850989f2ca6fcaa5c93af1c5d2b4004dc0c156b Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 20 Jan 2026 09:29:30 -0800
Subject: [PATCH 6/6] review: clarify diag message
---
.../clang/Basic/DiagnosticSemaKinds.td | 3 ++-
clang/lib/Sema/SemaHLSL.cpp | 19 ++++++++++---------
.../SemaHLSL/local_resource_binding_errs.hlsl | 8 ++++----
3 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5e206d84ab7c0..9a5d38af5a207 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13432,7 +13432,8 @@ def err_hlsl_incomplete_resource_array_in_function_param: Error<
def err_hlsl_assign_to_global_resource: Error<
"assignment to global resource variable %0 is not allowed">;
def err_hlsl_assigning_local_resource_is_not_unique
- : Error<"assignment to local resource %0 is not to the same unique global "
+ : Error<"assignment of %0 to local resource %1 is not to the same unique "
+ "global "
"resource">;
def err_hlsl_push_constant_unique
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 021745ba26430..c5fe38eaf57aa 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -4440,13 +4440,6 @@ bool SemaHLSL::CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr,
while (auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
E = ASE->getBase()->IgnoreParenImpCasts();
- auto RHSBinding = GetGlobalBinding(RHSExpr);
- if (!RHSBinding) {
- SemaRef.Diag(Loc, diag::err_hlsl_assigning_local_resource_is_not_unique)
- << RHSExpr;
- return false;
- }
-
// Report error if LHS is a non-static resource declared at a global scope.
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
@@ -4458,6 +4451,14 @@ bool SemaHLSL::CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr,
return false;
}
+ auto RHSBinding = GetGlobalBinding(RHSExpr);
+ if (!RHSBinding) {
+ SemaRef.Diag(Loc,
+ diag::err_hlsl_assigning_local_resource_is_not_unique)
+ << RHSExpr << VD;
+ return false;
+ }
+
// Ensure assignment to a non-static local resource does not conflict
// with previous assignments to global resources
const DeclBindingInfo *LHSBinding = LocalResourceBindings[VD];
@@ -4468,7 +4469,7 @@ bool SemaHLSL::CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr,
} else if (LHSBinding != *RHSBinding) {
SemaRef.Diag(Loc,
diag::err_hlsl_assigning_local_resource_is_not_unique)
- << RHSExpr;
+ << RHSExpr << VD;
SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;
return false;
}
@@ -4857,7 +4858,7 @@ bool SemaHLSL::handleInitialization(VarDecl *VDecl, Expr *&Init) {
} else {
SemaRef.Diag(Init->getBeginLoc(),
diag::err_hlsl_assigning_local_resource_is_not_unique)
- << Init;
+ << Init << VDecl;
return false;
}
}
diff --git a/clang/test/SemaHLSL/local_resource_binding_errs.hlsl b/clang/test/SemaHLSL/local_resource_binding_errs.hlsl
index ad9a46b865965..95951a636b881 100644
--- a/clang/test/SemaHLSL/local_resource_binding_errs.hlsl
+++ b/clang/test/SemaHLSL/local_resource_binding_errs.hlsl
@@ -10,7 +10,7 @@ cbuffer c {
};
void conditional_initialization(int idx) {
- // expected-error at +1 {{assignment to local resource 'cond ? Out0 : Out1' is not to the same unique global resource}}
+ // expected-error at +1 {{assignment of 'cond ? Out0 : Out1' to local resource 'Out' is not to the same unique global resource}}
RWStructuredBuffer<int> Out = cond ? Out0 : Out1;
Out[idx] = In[idx];
}
@@ -18,7 +18,7 @@ void conditional_initialization(int idx) {
void branched_assignment(int idx) {
RWStructuredBuffer<int> Out = Out0; // expected-note {{variable 'Out' is declared here}}
if (cond) {
- // expected-error at +1 {{assignment to local resource 'Out1' is not to the same unique global resource}}
+ // expected-error at +1 {{assignment of 'Out1' to local resource 'Out' is not to the same unique global resource}}
Out = Out1;
}
Out[idx] = In[idx];
@@ -27,7 +27,7 @@ void branched_assignment(int idx) {
void branched_assignment_with_array(int idx) {
RWStructuredBuffer<int> Out = Out0; // expected-note {{variable 'Out' is declared here}}
if (cond) {
- // expected-error at +1 {{assignment to local resource 'OutArr[0]' is not to the same unique global resource}}
+ // expected-error at +1 {{assignment of 'OutArr[0]' to local resource 'Out' is not to the same unique global resource}}
Out = OutArr[0];
}
Out[idx] = In[idx];
@@ -35,7 +35,7 @@ void branched_assignment_with_array(int idx) {
void conditional_assignment(int idx) {
RWStructuredBuffer<int> Out;
- // expected-error at +1 {{assignment to local resource 'cond ? Out0 : Out1' is not to the same unique global resource}}
+ // expected-error at +1 {{assignment of 'cond ? Out0 : Out1' to local resource 'Out' is not to the same unique global resource}}
Out = cond ? Out0 : Out1;
Out[idx] = In[idx];
}
More information about the cfe-commits
mailing list