[clang] [HLSL] Make load methods take const attribute (PR #193858)
Joshua Batista via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 27 15:53:30 PDT 2026
https://github.com/bob80905 updated https://github.com/llvm/llvm-project/pull/193858
>From 9878e10c24e1e83edb27346a8b9ddab3cab27c57 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Thu, 23 Apr 2026 16:17:40 -0700
Subject: [PATCH 1/5] first attempt
---
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 8 ++---
.../SemaHLSL/BuiltIns/Buffers-Load-const.hlsl | 35 +++++++++++++++++++
2 files changed, 39 insertions(+), 4 deletions(-)
create mode 100644 clang/test/SemaHLSL/BuiltIns/Buffers-Load-const.hlsl
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 4c8b0283b0f1e..0cdc2538a1bc1 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -1408,9 +1408,9 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addLoadMethods() {
IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
DeclarationName Load(&II);
// TODO: We also need versions with status for CheckAccessFullyMapped.
- addHandleAccessFunction(Load, /*IsConst=*/false, /*IsRef=*/false,
+ addHandleAccessFunction(Load, /*IsConst=*/true, /*IsRef=*/false,
AST.UnsignedIntTy);
- addLoadWithStatusFunction(Load, /*IsConst=*/false);
+ addLoadWithStatusFunction(Load, /*IsConst=*/true);
return *this;
}
@@ -1562,9 +1562,9 @@ BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
DeclarationName Load(&II);
- addHandleAccessFunction(Load, /*IsConst=*/false, /*IsRef=*/false,
+ addHandleAccessFunction(Load, /*IsConst=*/true, /*IsRef=*/false,
AST.UnsignedIntTy, ReturnType);
- addLoadWithStatusFunction(Load, /*IsConst=*/false, ReturnType);
+ addLoadWithStatusFunction(Load, /*IsConst=*/true, ReturnType);
};
AddLoads("Load", AST.UnsignedIntTy);
diff --git a/clang/test/SemaHLSL/BuiltIns/Buffers-Load-const.hlsl b/clang/test/SemaHLSL/BuiltIns/Buffers-Load-const.hlsl
new file mode 100644
index 0000000000000..3f408f7d8c2dd
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/Buffers-Load-const.hlsl
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.0-compute -x hlsl -fsyntax-only -verify \
+// RUN: -DRESOURCE="RWByteAddressBuffer" -DREGISTER=u1 %s
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.0-compute -x hlsl -fsyntax-only -verify \
+// RUN: -DRESOURCE="ByteAddressBuffer" -DREGISTER=t0 %s
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.0-compute -x hlsl -fsyntax-only -verify \
+// RUN: "-DRESOURCE=StructuredBuffer<uint>" -DREGISTER=t0 %s
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.0-compute -x hlsl -fsyntax-only -verify \
+// RUN: "-DRESOURCE=RWStructuredBuffer<uint>" -DREGISTER=u1 %s
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.0-compute -x hlsl -fsyntax-only -verify \
+// RUN: "-DRESOURCE=Buffer<uint>" -DREGISTER=t0 %s
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.0-compute -x hlsl -fsyntax-only -verify \
+// RUN: "-DRESOURCE=RWBuffer<uint>" -DREGISTER=u1 %s
+
+// expected-no-diagnostics
+
+// Regression test for https://github.com/llvm/llvm-project/issues/192557
+// Load on a const resource (e.g. const RWByteAddressBuffer) should be callable
+// because Load does not modify the buffer. DXC accepts this pattern.
+
+RESOURCE gBuf : register(REGISTER);
+RWByteAddressBuffer gOut : register(u0);
+
+void UseConst(const RESOURCE buf, out uint val) {
+ val = buf.Load(0);
+}
+
+[numthreads(1,1,1)]
+void main() {
+ const RESOURCE local = gBuf;
+ uint val;
+ UseConst(local, val);
+ // Write the loaded value to a separate buffer so it isn't dead-code
+ // eliminated.
+ gOut.Store(0, val);
+}
>From 6e5351017728a1dd4ea103a162396d000632c9b4 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Thu, 23 Apr 2026 17:05:00 -0700
Subject: [PATCH 2/5] add test updates
---
.../test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 36 +++++++++----------
.../test/AST/HLSL/StructuredBuffers-AST.hlsl | 8 ++---
clang/test/AST/HLSL/TypedBuffers-AST.hlsl | 8 ++---
.../resources/ByteAddressBuffers-methods.hlsl | 32 ++++++++---------
.../StructuredBuffers-methods-lib.hlsl | 16 ++++-----
.../StructuredBuffers-methods-ps.hlsl | 16 ++++-----
.../resources/TypedBuffers-methods.hlsl | 16 ++++-----
.../SemaHLSL/BuiltIns/Buffers-Load-const.hlsl | 11 +++++-
8 files changed, 76 insertions(+), 67 deletions(-)
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 16ce8ab0e7400..21c81dd895502 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -154,7 +154,7 @@ RESOURCE Buffer;
// Load methods
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'unsigned int (unsigned int)'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'const unsigned int (unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: CompoundStmt
// CHECK-LOAD-NEXT: ReturnStmt
@@ -164,7 +164,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer_typed' 'void (...) noexcept'
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t {{.*}}' <LValueToRValue>
// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
-// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' <LValueToRValue>
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'unsigned int *'
@@ -181,7 +181,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_with_status_typed' 'void (...) noexcept'
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t {{.*}}' <LValueToRValue>
// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
-// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' <LValueToRValue>
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' <LValueToRValue>
@@ -189,7 +189,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'unsigned int *'
// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load2 'vector<unsigned int, 2> (unsigned int)'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load2 'vector<unsigned int, 2> const (unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: CompoundStmt
// CHECK-LOAD-NEXT: ReturnStmt
@@ -199,13 +199,13 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer_typed' 'void (...) noexcept'
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t {{.*}}' <LValueToRValue>
// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
-// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' <LValueToRValue>
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'vector<unsigned int, 2> *'
// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load2 'vector<unsigned int, 2> (unsigned int, out unsigned int)'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load2 'vector<unsigned int, 2> (unsigned int, out unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'
// CHECK-LOAD-NEXT: HLSLParamModifierAttr {{.*}} out
@@ -216,7 +216,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_with_status_typed' 'void (...) noexcept'
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t {{.*}}' <LValueToRValue>
// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
-// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' <LValueToRValue>
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' <LValueToRValue>
@@ -224,7 +224,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'vector<unsigned int, 2> *'
// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load3 'vector<unsigned int, 3> (unsigned int)'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load3 'vector<unsigned int, 3> const (unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: CompoundStmt
// CHECK-LOAD-NEXT: ReturnStmt
@@ -234,13 +234,13 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer_typed' 'void (...) noexcept'
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t {{.*}}' <LValueToRValue>
// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
-// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' <LValueToRValue>
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'vector<unsigned int, 3> *'
// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load3 'vector<unsigned int, 3> (unsigned int, out unsigned int)'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load3 'vector<unsigned int, 3> (unsigned int, out unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'
// CHECK-LOAD-NEXT: HLSLParamModifierAttr {{.*}} out
@@ -251,7 +251,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_with_status_typed' 'void (...) noexcept'
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t {{.*}}' <LValueToRValue>
// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
-// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' <LValueToRValue>
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' <LValueToRValue>
@@ -259,7 +259,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'vector<unsigned int, 3> *'
// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load4 'vector<unsigned int, 4> (unsigned int)'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load4 'vector<unsigned int, 4> const (unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: CompoundStmt
// CHECK-LOAD-NEXT: ReturnStmt
@@ -269,13 +269,13 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer_typed' 'void (...) noexcept'
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t {{.*}}' <LValueToRValue>
// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
-// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' <LValueToRValue>
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'vector<unsigned int, 4> *'
// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load4 'vector<unsigned int, 4> (unsigned int, out unsigned int)'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load4 'vector<unsigned int, 4> (unsigned int, out unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'
// CHECK-LOAD-NEXT: HLSLParamModifierAttr {{.*}} out
@@ -286,7 +286,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_with_status_typed' 'void (...) noexcept'
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} '__hlsl_resource_t {{.*}}' <LValueToRValue>
// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
-// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' <LValueToRValue>
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-LOAD-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' <LValueToRValue>
@@ -294,7 +294,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'vector<unsigned int, 4> *'
// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'element_type (unsigned int)'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'const element_type (unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: CompoundStmt
// CHECK-LOAD-NEXT: ReturnStmt
@@ -303,7 +303,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: CallExpr {{.*}} '<dependent type>'
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getpointer_typed' 'void (...) noexcept'
// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
-// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'element_type *'
// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
@@ -318,7 +318,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: CallExpr {{.*}} '<dependent type>'
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_with_status_typed' 'void (...) noexcept'
// CHECK-LOAD-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
-// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Status' 'unsigned int &__restrict'
// CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'element_type *'
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index 3cc33dbdb32af..bfd99814aa22a 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -310,7 +310,7 @@ RESOURCE<float> Buffer;
// Load method
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'element_type (unsigned int)'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'const element_type (unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: CompoundStmt
// CHECK-LOAD-NEXT: ReturnStmt
@@ -322,13 +322,13 @@ RESOURCE<float> Buffer;
// CHECK-LOAD-SAME{LITERAL}: [[hlsl::resource_class(
// CHECK-LOAD-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
// CHECK-LOAD-SAME: ' lvalue .__handle {{.*}}
-// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
// Load with status method
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'element_type (unsigned int, out unsigned int)'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'element_type (unsigned int, out unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'
// CHECK-LOAD-NEXT: HLSLParamModifierAttr {{.*}} out
@@ -341,7 +341,7 @@ RESOURCE<float> Buffer;
// CHECK-LOAD-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
// CHECK-LOAD-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
// CHECK-LOAD-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
-// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Status' 'unsigned int &__restrict'
// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index b6f9f79e0722e..ac564f61c11f7 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -197,7 +197,7 @@ RESOURCE<float> Buffer;
// Load method
-// CHECK: CXXMethodDecl {{.*}} Load 'element_type (unsigned int)'
+// CHECK: CXXMethodDecl {{.*}} Load 'const element_type (unsigned int) const'
// CHECK-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: ReturnStmt
@@ -210,12 +210,12 @@ RESOURCE<float> Buffer;
// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
// CHECK-SAME: ' lvalue .__handle {{.*}}
-// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
// Load with status method
-// CHECK: CXXMethodDecl {{.*}} Load 'element_type (unsigned int, out unsigned int)'
+// CHECK: CXXMethodDecl {{.*}} Load 'element_type (unsigned int, out unsigned int) const'
// CHECK-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-NEXT: ParmVarDecl {{.*}} Status 'unsigned int &__restrict'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
@@ -228,7 +228,7 @@ RESOURCE<float> Buffer;
// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
-// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'Status' 'unsigned int &__restrict'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
index fa04d82d54fb0..b91052bd4fa62 100644
--- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
+++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
@@ -17,14 +17,14 @@ export float TestLoad() {
}
// CHECK: define {{.*}} float @TestLoad()()
-// CHECK: call {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int)(ptr {{.*}} @Buf, i32 noundef 0)
-// CHECK: call {{.*}} <4 x i32> @hlsl::RWByteAddressBuffer::Load4(unsigned int)(ptr {{.*}} @RWBuf, i32 noundef 4)
-// CHECK: call {{.*}} float @float hlsl::ByteAddressBuffer::Load<float>(unsigned int)(ptr {{.*}} @Buf, i32 noundef 20)
-// CHECK: call {{.*}} <4 x float> @float vector[4] hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int)(ptr {{.*}} @RWBuf, i32 noundef 24)
+// CHECK: call {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int) const(ptr {{.*}} @Buf, i32 noundef 0)
+// CHECK: call {{.*}} <4 x i32> @hlsl::RWByteAddressBuffer::Load4(unsigned int) const(ptr {{.*}} @RWBuf, i32 noundef 4)
+// CHECK: call {{.*}} float @float const hlsl::ByteAddressBuffer::Load<float>(unsigned int) const(ptr {{.*}} @Buf, i32 noundef 20)
+// CHECK: call {{.*}} <4 x float> @float vector[4] const hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int) const(ptr {{.*}} @RWBuf, i32 noundef 24)
// CHECK: add
// CHECK: ret float
-// CHECK: define {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int)(ptr {{.*}} %this, i32 noundef %Index)
+// CHECK: define {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int) const(ptr {{.*}} %this, i32 noundef %Index)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -32,7 +32,7 @@ export float TestLoad() {
// CHECK-NEXT: %[[VAL:.*]] = load i32, ptr %[[PTR]]
// CHECK-NEXT: ret i32 %[[VAL]]
-// CHECK: define {{.*}} <4 x i32> @hlsl::RWByteAddressBuffer::Load4(unsigned int)(ptr {{.*}} %this, i32 noundef %Index)
+// CHECK: define {{.*}} <4 x i32> @hlsl::RWByteAddressBuffer::Load4(unsigned int) const(ptr {{.*}} %this, i32 noundef %Index)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -40,7 +40,7 @@ export float TestLoad() {
// CHECK-NEXT: %[[VEC:.*]] = load <4 x i32>, ptr %[[PTR]]
// CHECK-NEXT: ret <4 x i32> %[[VEC]]
-// CHECK: define {{.*}} float @float hlsl::ByteAddressBuffer::Load<float>(unsigned int)(ptr {{.*}} %this, i32 noundef %Index)
+// CHECK: define {{.*}} float @float const hlsl::ByteAddressBuffer::Load<float>(unsigned int) const(ptr {{.*}} %this, i32 noundef %Index)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -48,7 +48,7 @@ export float TestLoad() {
// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[PTR]]
// CHECK-NEXT: ret float %[[VAL]]
-// CHECK: define {{.*}} <4 x float> @float vector[4] hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int)(ptr {{.*}} %this, i32 noundef %Index)
+// CHECK: define {{.*}} <4 x float> @float vector[4] const hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int) const(ptr {{.*}} %this, i32 noundef %Index)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -64,14 +64,14 @@ export float TestLoadWithStatus() {
}
// CHECK: define {{.*}} float @TestLoadWithStatus()()
-// CHECK: call {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int, unsigned int&)(ptr {{.*}} @Buf, i32 noundef 0, ptr {{.*}} %tmp)
-// CHECK: call {{.*}} <4 x i32> @hlsl::RWByteAddressBuffer::Load4(unsigned int, unsigned int&)(ptr {{.*}} @RWBuf, i32 noundef 4, ptr {{.*}} %tmp1)
-// CHECK: call {{.*}} float @float hlsl::ByteAddressBuffer::Load<float>(unsigned int, unsigned int&)(ptr {{.*}} @Buf, i32 noundef 20, ptr {{.*}} %tmp4)
-// CHECK: call {{.*}} <4 x float> @float vector[4] hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int, unsigned int&)(ptr {{.*}} @RWBuf, i32 noundef 24, ptr {{.*}} %tmp7)
+// CHECK: call {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int, unsigned int&) const(ptr {{.*}} @Buf, i32 noundef 0, ptr {{.*}} %tmp)
+// CHECK: call {{.*}} <4 x i32> @hlsl::RWByteAddressBuffer::Load4(unsigned int, unsigned int&) const(ptr {{.*}} @RWBuf, i32 noundef 4, ptr {{.*}} %tmp1)
+// CHECK: call {{.*}} float @float hlsl::ByteAddressBuffer::Load<float>(unsigned int, unsigned int&) const(ptr {{.*}} @Buf, i32 noundef 20, ptr {{.*}} %tmp4)
+// CHECK: call {{.*}} <4 x float> @float vector[4] hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int, unsigned int&) const(ptr {{.*}} @RWBuf, i32 noundef 24, ptr {{.*}} %tmp7)
// CHECK: add
// CHECK: ret float
-// CHECK: define {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: define {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int, unsigned int&) const(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -83,7 +83,7 @@ export float TestLoadWithStatus() {
// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
// CHECK-NEXT: ret i32 %[[VALUE]]
-// CHECK: define {{.*}} <4 x i32> @hlsl::RWByteAddressBuffer::Load4(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: define {{.*}} <4 x i32> @hlsl::RWByteAddressBuffer::Load4(unsigned int, unsigned int&) const(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -95,7 +95,7 @@ export float TestLoadWithStatus() {
// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
// CHECK-NEXT: ret <4 x i32> %[[VALUE]]
-// CHECK: define {{.*}} float @float hlsl::ByteAddressBuffer::Load<float>(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: define {{.*}} float @float hlsl::ByteAddressBuffer::Load<float>(unsigned int, unsigned int&) const(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -107,7 +107,7 @@ export float TestLoadWithStatus() {
// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
// CHECK-NEXT: ret float %[[VALUE]]
-// CHECK: define {{.*}} <4 x float> @float vector[4] hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: define {{.*}} <4 x float> @float vector[4] hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int, unsigned int&) const(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
index 12a644b4d4355..35f838a48c422 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
@@ -83,12 +83,12 @@ export float TestLoad() {
}
// CHECK: define noundef nofpclass(nan inf) float @TestLoad()()
-// CHECK: call {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} @RWSB1, i32 noundef 1)
-// CHECK: call {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} @SB1, i32 noundef 2)
+// CHECK: call {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int) const(ptr {{.*}} @RWSB1, i32 noundef 1)
+// CHECK: call {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int) const(ptr {{.*}} @SB1, i32 noundef 2)
// CHECK: add
// CHECK: ret float
-// CHECK: define {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} %this, i32 noundef %Index)
+// CHECK: define {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int) const(ptr {{.*}} %this, i32 noundef %Index)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -96,7 +96,7 @@ export float TestLoad() {
// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[PTR]]
// CHECK-NEXT: ret float %[[VAL]]
-// CHECK: define {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} %this, i32 noundef %Index)
+// CHECK: define {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int) const(ptr {{.*}} %this, i32 noundef %Index)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 0, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -113,12 +113,12 @@ export float TestLoadWithStatus() {
}
// CHECK: define noundef nofpclass(nan inf) float @TestLoadWithStatus()()
-// CHECK: call {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} @RWSB1, i32 noundef 1, ptr {{.*}} %tmp)
-// CHECK: call {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} @SB1, i32 noundef 2, ptr {{.*}} %tmp1)
+// CHECK: call {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int, unsigned int&) const(ptr {{.*}} @RWSB1, i32 noundef 1, ptr {{.*}} %tmp)
+// CHECK: call {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int, unsigned int&) const(ptr {{.*}} @SB1, i32 noundef 2, ptr {{.*}} %tmp1)
// CHECK: add
// CHECK: ret float
-// CHECK: define {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: define {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int, unsigned int&) const(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -130,7 +130,7 @@ export float TestLoadWithStatus() {
// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
// CHECK-NEXT: ret float %[[VALUE]]
-// CHECK: define {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: define {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int, unsigned int&) const(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 0, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
index 85ca449bc6ea3..a38b627f997b6 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
@@ -45,11 +45,11 @@ export float TestLoad() {
}
// CHECK: define {{.*}} float @TestLoad()()
-// CHECK: call {{.*}} float @hlsl::RasterizerOrderedStructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} @ROSB1, i32 noundef 10)
-// CHECK: call {{.*}} <2 x i32> @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::Load(unsigned int)(ptr {{.*}} @ROSB2, i32 noundef 20)
+// CHECK: call {{.*}} float @hlsl::RasterizerOrderedStructuredBuffer<float>::Load(unsigned int) const(ptr {{.*}} @ROSB1, i32 noundef 10)
+// CHECK: call {{.*}} <2 x i32> @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::Load(unsigned int) const(ptr {{.*}} @ROSB2, i32 noundef 20)
// CHECK: ret
-// CHECK: define {{.*}} float @hlsl::RasterizerOrderedStructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} %Index)
+// CHECK: define {{.*}} float @hlsl::RasterizerOrderedStructuredBuffer<float>::Load(unsigned int) const(ptr {{.*}} %Index)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer", ptr {{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 1), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -57,7 +57,7 @@ export float TestLoad() {
// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[BUFPTR]]
// CHECK-NEXT: ret float %[[VAL]]
-// CHECK: define {{.*}} <2 x i32> @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::Load(unsigned int)(ptr {{.*}} %Index)
+// CHECK: define {{.*}} <2 x i32> @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::Load(unsigned int) const(ptr {{.*}} %Index)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer.0", ptr {{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <2 x i32>, 1, 1), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -73,11 +73,11 @@ export float TestLoadWithStatus() {
}
// CHECK: define {{.*}} float @TestLoadWithStatus()()
-// CHECK: call {{.*}} float @hlsl::RasterizerOrderedStructuredBuffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} @ROSB1, i32 noundef 10, ptr {{.*}} %tmp)
-// CHECK: call {{.*}} <2 x i32> @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::Load(unsigned int, unsigned int&)(ptr {{.*}} @ROSB2, i32 noundef 20, ptr {{.*}} %tmp2)
+// CHECK: call {{.*}} float @hlsl::RasterizerOrderedStructuredBuffer<float>::Load(unsigned int, unsigned int&) const(ptr {{.*}} @ROSB1, i32 noundef 10, ptr {{.*}} %tmp)
+// CHECK: call {{.*}} <2 x i32> @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::Load(unsigned int, unsigned int&) const(ptr {{.*}} @ROSB2, i32 noundef 20, ptr {{.*}} %tmp2)
// CHECK: ret
-// CHECK: define {{.*}} float @hlsl::RasterizerOrderedStructuredBuffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: define {{.*}} float @hlsl::RasterizerOrderedStructuredBuffer<float>::Load(unsigned int, unsigned int&) const(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer", ptr {{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 1), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -89,7 +89,7 @@ export float TestLoadWithStatus() {
// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
// CHECK-NEXT: ret float %[[VALUE]]
-// CHECK: define {{.*}} <2 x i32> @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::Load(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: define {{.*}} <2 x i32> @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::Load(unsigned int, unsigned int&) const(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer.0", ptr {{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <2 x i32>, 1, 1), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
diff --git a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
index bdf7f4d7fd388..dc74b966dfe13 100644
--- a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
+++ b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
@@ -17,12 +17,12 @@ export float TestLoad() {
}
// CHECK: define noundef nofpclass(nan inf) float @TestLoad()()
-// CHECK: call {{.*}} float @hlsl::Buffer<float>::Load(unsigned int)(ptr {{.*}} @Buf, i32 noundef 1)
-// CHECK: call {{.*}} <4 x i32> @hlsl::RWBuffer<unsigned int vector[4]>::Load(unsigned int)(ptr {{.*}} @RWBuf, i32 noundef 2)
+// CHECK: call {{.*}} float @hlsl::Buffer<float>::Load(unsigned int) const(ptr {{.*}} @Buf, i32 noundef 1)
+// CHECK: call {{.*}} <4 x i32> @hlsl::RWBuffer<unsigned int vector[4]>::Load(unsigned int) const(ptr {{.*}} @RWBuf, i32 noundef 2)
// CHECK: add
// CHECK: ret float
-// CHECK: define {{.*}} float @hlsl::Buffer<float>::Load(unsigned int)(ptr {{.*}} %this, i32 noundef %Index)
+// CHECK: define {{.*}} float @hlsl::Buffer<float>::Load(unsigned int) const(ptr {{.*}} %this, i32 noundef %Index)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::Buffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", float, 0, 0, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -30,7 +30,7 @@ export float TestLoad() {
// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[PTR]]
// CHECK-NEXT: ret float %[[VAL]]
-// CHECK: define {{.*}} <4 x i32> @hlsl::RWBuffer<unsigned int vector[4]>::Load(unsigned int)(ptr {{.*}} %this, i32 noundef %Index)
+// CHECK: define {{.*}} <4 x i32> @hlsl::RWBuffer<unsigned int vector[4]>::Load(unsigned int) const(ptr {{.*}} %this, i32 noundef %Index)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -47,12 +47,12 @@ export float TestLoadWithStatus() {
}
// CHECK: define noundef nofpclass(nan inf) float @TestLoadWithStatus()()
-// CHECK: call {{.*}} float @hlsl::Buffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} @Buf, i32 noundef 1, ptr {{.*}} %tmp)
-// CHECK: call {{.*}} <4 x i32> @hlsl::RWBuffer<unsigned int vector[4]>::Load(unsigned int, unsigned int&)(ptr {{.*}} @RWBuf, i32 noundef 2, ptr {{.*}} %tmp1)
+// CHECK: call {{.*}} float @hlsl::Buffer<float>::Load(unsigned int, unsigned int&) const(ptr {{.*}} @Buf, i32 noundef 1, ptr {{.*}} %tmp)
+// CHECK: call {{.*}} <4 x i32> @hlsl::RWBuffer<unsigned int vector[4]>::Load(unsigned int, unsigned int&) const(ptr {{.*}} @RWBuf, i32 noundef 2, ptr {{.*}} %tmp1)
// CHECK: add
// CHECK: ret float
-// CHECK: define {{.*}} float @hlsl::Buffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: define {{.*}} float @hlsl::Buffer<float>::Load(unsigned int, unsigned int&) const(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::Buffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", float, 0, 0, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -64,7 +64,7 @@ export float TestLoadWithStatus() {
// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
// CHECK-NEXT: ret float %[[VALUE]]
-// CHECK: define {{.*}} <4 x i32> @hlsl::RWBuffer<unsigned int vector[4]>::Load(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: define {{.*}} <4 x i32> @hlsl::RWBuffer<unsigned int vector[4]>::Load(unsigned int, unsigned int&) const(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
diff --git a/clang/test/SemaHLSL/BuiltIns/Buffers-Load-const.hlsl b/clang/test/SemaHLSL/BuiltIns/Buffers-Load-const.hlsl
index 3f408f7d8c2dd..3b2fa7c05440e 100644
--- a/clang/test/SemaHLSL/BuiltIns/Buffers-Load-const.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/Buffers-Load-const.hlsl
@@ -24,12 +24,21 @@ void UseConst(const RESOURCE buf, out uint val) {
val = buf.Load(0);
}
+void UseConstWithStatus(const RESOURCE buf, out uint val) {
+ uint status;
+ val = buf.Load(0, status);
+ val += status;
+}
+
[numthreads(1,1,1)]
void main() {
const RESOURCE local = gBuf;
uint val;
UseConst(local, val);
- // Write the loaded value to a separate buffer so it isn't dead-code
+ uint val2;
+ UseConstWithStatus(local, val2);
+ // Write the loaded values to a separate buffer so they aren't dead-code
// eliminated.
gOut.Store(0, val);
+ gOut.Store(4, val2);
}
>From b5df1572b11aa68fda22a0009120f8e969b2e492 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 24 Apr 2026 11:23:46 -0700
Subject: [PATCH 3/5] remove const return type, just const methods
---
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 23 +++++++++++--------
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h | 5 ++--
.../test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 10 ++++----
.../test/AST/HLSL/StructuredBuffers-AST.hlsl | 2 +-
clang/test/AST/HLSL/TypedBuffers-AST.hlsl | 2 +-
.../resources/ByteAddressBuffers-methods.hlsl | 8 +++----
6 files changed, 27 insertions(+), 23 deletions(-)
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 0cdc2538a1bc1..aecf09d4d0bce 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -1393,10 +1393,11 @@ BuiltinTypeDeclBuilder::addArraySubscriptOperators(ResourceDimension Dim) {
DeclarationName Subscript =
AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
- addHandleAccessFunction(Subscript, /*IsConst=*/true, /*IsRef=*/true, IndexTy);
+ addHandleAccessFunction(Subscript, /*IsConstMethod=*/true,
+ /*IsConstReturn=*/true, /*IsRef=*/true, IndexTy);
if (getResourceAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV)
- addHandleAccessFunction(Subscript, /*IsConst=*/false, /*IsRef=*/true,
- IndexTy);
+ addHandleAccessFunction(Subscript, /*IsConstMethod=*/false,
+ /*IsConstReturn=*/false, /*IsRef=*/true, IndexTy);
return *this;
}
@@ -1408,7 +1409,8 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addLoadMethods() {
IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
DeclarationName Load(&II);
// TODO: We also need versions with status for CheckAccessFullyMapped.
- addHandleAccessFunction(Load, /*IsConst=*/true, /*IsRef=*/false,
+ addHandleAccessFunction(Load, /*IsConstMethod=*/true,
+ /*IsConstReturn=*/false, /*IsRef=*/false,
AST.UnsignedIntTy);
addLoadWithStatusFunction(Load, /*IsConst=*/true);
@@ -1562,7 +1564,8 @@ BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
DeclarationName Load(&II);
- addHandleAccessFunction(Load, /*IsConst=*/true, /*IsRef=*/false,
+ addHandleAccessFunction(Load, /*IsConstMethod=*/true,
+ /*IsConstReturn=*/false, /*IsRef=*/false,
AST.UnsignedIntTy, ReturnType);
addLoadWithStatusFunction(Load, /*IsConst=*/true, ReturnType);
};
@@ -2232,15 +2235,15 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addLoadWithStatusFunction(
}
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleAccessFunction(
- DeclarationName &Name, bool IsConst, bool IsRef, QualType IndexTy,
- QualType ElemTy) {
+ DeclarationName &Name, bool IsConstMethod, bool IsConstReturn, bool IsRef,
+ QualType IndexTy, QualType ElemTy) {
assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = SemaRef.getASTContext();
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
bool NeedsTypedBuiltin = !ElemTy.isNull();
// The empty QualType is a placeholder. The actual return type is set below.
- BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), IsConst);
+ BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), IsConstMethod);
if (!NeedsTypedBuiltin)
ElemTy = getHandleElementType();
@@ -2253,12 +2256,12 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleAccessFunction(
if (IsRef) {
ReturnTy = AddrSpaceElemTy;
- if (IsConst)
+ if (IsConstReturn)
ReturnTy.addConst();
ReturnTy = AST.getLValueReferenceType(ReturnTy);
} else {
ReturnTy = ElemTy;
- if (IsConst)
+ if (IsConstReturn)
ReturnTy.addConst();
}
MMB.ReturnTy = ReturnTy;
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index 1ffe5d9a624ef..ed23123016278 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -114,8 +114,9 @@ class BuiltinTypeDeclBuilder {
BuiltinTypeDeclBuilder &addIncrementCounterMethod();
BuiltinTypeDeclBuilder &addDecrementCounterMethod();
BuiltinTypeDeclBuilder &addHandleAccessFunction(DeclarationName &Name,
- bool IsConst, bool IsRef,
- QualType IndexTy,
+ bool IsConstMethod,
+ bool IsConstReturn,
+ bool IsRef, QualType IndexTy,
QualType ElemTy = QualType());
BuiltinTypeDeclBuilder &
addLoadWithStatusFunction(DeclarationName &Name, bool IsConst,
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 21c81dd895502..61585d7770d7c 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -154,7 +154,7 @@ RESOURCE Buffer;
// Load methods
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'const unsigned int (unsigned int) const'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'unsigned int (unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: CompoundStmt
// CHECK-LOAD-NEXT: ReturnStmt
@@ -189,7 +189,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'unsigned int *'
// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load2 'vector<unsigned int, 2> const (unsigned int) const'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load2 'vector<unsigned int, 2> (unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: CompoundStmt
// CHECK-LOAD-NEXT: ReturnStmt
@@ -224,7 +224,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'vector<unsigned int, 2> *'
// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load3 'vector<unsigned int, 3> const (unsigned int) const'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load3 'vector<unsigned int, 3> (unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: CompoundStmt
// CHECK-LOAD-NEXT: ReturnStmt
@@ -259,7 +259,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'vector<unsigned int, 3> *'
// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load4 'vector<unsigned int, 4> const (unsigned int) const'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load4 'vector<unsigned int, 4> (unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: CompoundStmt
// CHECK-LOAD-NEXT: ReturnStmt
@@ -294,7 +294,7 @@ RESOURCE Buffer;
// CHECK-LOAD-NEXT: CXXScalarValueInitExpr {{.*}} 'vector<unsigned int, 4> *'
// CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'const element_type (unsigned int) const'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'element_type (unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: CompoundStmt
// CHECK-LOAD-NEXT: ReturnStmt
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index bfd99814aa22a..fa1180fc69983 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -310,7 +310,7 @@ RESOURCE<float> Buffer;
// Load method
-// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'const element_type (unsigned int) const'
+// CHECK-LOAD: CXXMethodDecl {{.*}} Load 'element_type (unsigned int) const'
// CHECK-LOAD-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-LOAD-NEXT: CompoundStmt
// CHECK-LOAD-NEXT: ReturnStmt
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index ac564f61c11f7..c27b7360ee81c 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -197,7 +197,7 @@ RESOURCE<float> Buffer;
// Load method
-// CHECK: CXXMethodDecl {{.*}} Load 'const element_type (unsigned int) const'
+// CHECK: CXXMethodDecl {{.*}} Load 'element_type (unsigned int) const'
// CHECK-NEXT: ParmVarDecl {{.*}} Index 'unsigned int'
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: ReturnStmt
diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
index b91052bd4fa62..caa1fd18fc8e6 100644
--- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
+++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
@@ -19,8 +19,8 @@ export float TestLoad() {
// CHECK: define {{.*}} float @TestLoad()()
// CHECK: call {{.*}} i32 @hlsl::ByteAddressBuffer::Load(unsigned int) const(ptr {{.*}} @Buf, i32 noundef 0)
// CHECK: call {{.*}} <4 x i32> @hlsl::RWByteAddressBuffer::Load4(unsigned int) const(ptr {{.*}} @RWBuf, i32 noundef 4)
-// CHECK: call {{.*}} float @float const hlsl::ByteAddressBuffer::Load<float>(unsigned int) const(ptr {{.*}} @Buf, i32 noundef 20)
-// CHECK: call {{.*}} <4 x float> @float vector[4] const hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int) const(ptr {{.*}} @RWBuf, i32 noundef 24)
+// CHECK: call {{.*}} float @float hlsl::ByteAddressBuffer::Load<float>(unsigned int) const(ptr {{.*}} @Buf, i32 noundef 20)
+// CHECK: call {{.*}} <4 x float> @float vector[4] hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int) const(ptr {{.*}} @RWBuf, i32 noundef 24)
// CHECK: add
// CHECK: ret float
@@ -40,7 +40,7 @@ export float TestLoad() {
// CHECK-NEXT: %[[VEC:.*]] = load <4 x i32>, ptr %[[PTR]]
// CHECK-NEXT: ret <4 x i32> %[[VEC]]
-// CHECK: define {{.*}} float @float const hlsl::ByteAddressBuffer::Load<float>(unsigned int) const(ptr {{.*}} %this, i32 noundef %Index)
+// CHECK: define {{.*}} float @float hlsl::ByteAddressBuffer::Load<float>(unsigned int) const(ptr {{.*}} %this, i32 noundef %Index)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
@@ -48,7 +48,7 @@ export float TestLoad() {
// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[PTR]]
// CHECK-NEXT: ret float %[[VAL]]
-// CHECK: define {{.*}} <4 x float> @float vector[4] const hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int) const(ptr {{.*}} %this, i32 noundef %Index)
+// CHECK: define {{.*}} <4 x float> @float vector[4] hlsl::RWByteAddressBuffer::Load<float vector[4]>(unsigned int) const(ptr {{.*}} %this, i32 noundef %Index)
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %__handle
// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
>From ca24da5f2603ed6273aeeacb65cad8529b1bb4b5 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 24 Apr 2026 15:39:24 -0700
Subject: [PATCH 4/5] rename for consistency!
---
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 8 ++++----
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index aecf09d4d0bce..a9c99654bf9eb 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -1412,7 +1412,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addLoadMethods() {
addHandleAccessFunction(Load, /*IsConstMethod=*/true,
/*IsConstReturn=*/false, /*IsRef=*/false,
AST.UnsignedIntTy);
- addLoadWithStatusFunction(Load, /*IsConst=*/true);
+ addLoadWithStatusFunction(Load, /*IsConstMethod=*/true);
return *this;
}
@@ -1567,7 +1567,7 @@ BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
addHandleAccessFunction(Load, /*IsConstMethod=*/true,
/*IsConstReturn=*/false, /*IsRef=*/false,
AST.UnsignedIntTy, ReturnType);
- addLoadWithStatusFunction(Load, /*IsConst=*/true, ReturnType);
+ addLoadWithStatusFunction(Load, /*IsConstMethod=*/true, ReturnType);
};
AddLoads("Load", AST.UnsignedIntTy);
@@ -2205,14 +2205,14 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDecrementCounterMethod() {
}
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addLoadWithStatusFunction(
- DeclarationName &Name, bool IsConst, QualType ReturnTy) {
+ DeclarationName &Name, bool IsConstMethod, QualType ReturnTy) {
assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = SemaRef.getASTContext();
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
bool NeedsTypedBuiltin = !ReturnTy.isNull();
// The empty QualType is a placeholder. The actual return type is set below.
- BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), IsConst);
+ BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), IsConstMethod);
if (!NeedsTypedBuiltin)
ReturnTy = getHandleElementType();
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index ed23123016278..cd47f01e9193e 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -119,7 +119,7 @@ class BuiltinTypeDeclBuilder {
bool IsRef, QualType IndexTy,
QualType ElemTy = QualType());
BuiltinTypeDeclBuilder &
- addLoadWithStatusFunction(DeclarationName &Name, bool IsConst,
+ addLoadWithStatusFunction(DeclarationName &Name, bool IsConstMethod,
QualType ReturnTy = QualType());
BuiltinTypeDeclBuilder &addStoreFunction(DeclarationName &Name, bool IsConst,
QualType ValueType);
>From 4b24c23ed33bc6755ddc1c39bb0a69c4bd79dfbb Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Mon, 27 Apr 2026 15:53:09 -0700
Subject: [PATCH 5/5] remove param for load functions for const method, assume
it is always true
---
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 29 ++++++++++---------
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h | 6 ++--
2 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index a9c99654bf9eb..2522637f5417c 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -1393,11 +1393,12 @@ BuiltinTypeDeclBuilder::addArraySubscriptOperators(ResourceDimension Dim) {
DeclarationName Subscript =
AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
- addHandleAccessFunction(Subscript, /*IsConstMethod=*/true,
+ addHandleAccessFunction(Subscript,
/*IsConstReturn=*/true, /*IsRef=*/true, IndexTy);
if (getResourceAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV)
- addHandleAccessFunction(Subscript, /*IsConstMethod=*/false,
- /*IsConstReturn=*/false, /*IsRef=*/true, IndexTy);
+ addHandleAccessFunction(Subscript,
+ /*IsConstReturn=*/false, /*IsRef=*/true, IndexTy,
+ /*ElemTy=*/QualType(), /*IsConstMethod=*/false);
return *this;
}
@@ -1408,11 +1409,11 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addLoadMethods() {
ASTContext &AST = Record->getASTContext();
IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
DeclarationName Load(&II);
- // TODO: We also need versions with status for CheckAccessFullyMapped.
- addHandleAccessFunction(Load, /*IsConstMethod=*/true,
+
+ addHandleAccessFunction(Load,
/*IsConstReturn=*/false, /*IsRef=*/false,
AST.UnsignedIntTy);
- addLoadWithStatusFunction(Load, /*IsConstMethod=*/true);
+ addLoadWithStatusFunction(Load);
return *this;
}
@@ -1564,10 +1565,10 @@ BuiltinTypeDeclBuilder::addByteAddressBufferLoadMethods() {
IdentifierInfo &II = AST.Idents.get(MethodName, tok::TokenKind::identifier);
DeclarationName Load(&II);
- addHandleAccessFunction(Load, /*IsConstMethod=*/true,
+ addHandleAccessFunction(Load,
/*IsConstReturn=*/false, /*IsRef=*/false,
AST.UnsignedIntTy, ReturnType);
- addLoadWithStatusFunction(Load, /*IsConstMethod=*/true, ReturnType);
+ addLoadWithStatusFunction(Load, ReturnType);
};
AddLoads("Load", AST.UnsignedIntTy);
@@ -2204,15 +2205,17 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDecrementCounterMethod() {
.finalize();
}
-BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addLoadWithStatusFunction(
- DeclarationName &Name, bool IsConstMethod, QualType ReturnTy) {
+BuiltinTypeDeclBuilder &
+BuiltinTypeDeclBuilder::addLoadWithStatusFunction(DeclarationName &Name,
+ QualType ReturnTy) {
assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = SemaRef.getASTContext();
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
bool NeedsTypedBuiltin = !ReturnTy.isNull();
// The empty QualType is a placeholder. The actual return type is set below.
- BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), IsConstMethod);
+ // All load methods will be const.
+ BuiltinTypeMethodBuilder MMB(*this, Name, QualType(), true);
if (!NeedsTypedBuiltin)
ReturnTy = getHandleElementType();
@@ -2235,8 +2238,8 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addLoadWithStatusFunction(
}
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleAccessFunction(
- DeclarationName &Name, bool IsConstMethod, bool IsConstReturn, bool IsRef,
- QualType IndexTy, QualType ElemTy) {
+ DeclarationName &Name, bool IsConstReturn, bool IsRef, QualType IndexTy,
+ QualType ElemTy, bool IsConstMethod) {
assert(!Record->isCompleteDefinition() && "record is already complete");
ASTContext &AST = SemaRef.getASTContext();
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index cd47f01e9193e..34e51f5d03794 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -114,12 +114,12 @@ class BuiltinTypeDeclBuilder {
BuiltinTypeDeclBuilder &addIncrementCounterMethod();
BuiltinTypeDeclBuilder &addDecrementCounterMethod();
BuiltinTypeDeclBuilder &addHandleAccessFunction(DeclarationName &Name,
- bool IsConstMethod,
bool IsConstReturn,
bool IsRef, QualType IndexTy,
- QualType ElemTy = QualType());
+ QualType ElemTy = QualType(),
+ bool IsConstMethod = true);
BuiltinTypeDeclBuilder &
- addLoadWithStatusFunction(DeclarationName &Name, bool IsConstMethod,
+ addLoadWithStatusFunction(DeclarationName &Name,
QualType ReturnTy = QualType());
BuiltinTypeDeclBuilder &addStoreFunction(DeclarationName &Name, bool IsConst,
QualType ValueType);
More information about the cfe-commits
mailing list