https://github.com/hekota updated 
https://github.com/llvm/llvm-project/pull/155866

>From 7a0d3ca684a2d95e0528d5f4ee77bc1306ddfe1d Mon Sep 17 00:00:00 2001
From: Helena Kotas <heko...@microsoft.com>
Date: Thu, 28 Aug 2025 08:17:31 -0700
Subject: [PATCH 1/4] [HLSL] Reorder the arguments of handle initialization
 builtins

Reorder the arguments of handle initialization builtins to match the order of 
the
llvm intrinsics, and also to match the arguments on the static create methods 
for
resources (coming soon).
---
 clang/lib/CodeGen/CGHLSLBuiltins.cpp            | 8 ++++----
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp   | 2 +-
 clang/lib/Sema/SemaHLSL.cpp                     | 4 ++--
 clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 2 +-
 clang/test/AST/HLSL/StructuredBuffers-AST.hlsl  | 2 +-
 clang/test/AST/HLSL/TypedBuffers-AST.hlsl       | 2 +-
 6 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp 
b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 58165185b6711..483920f2392cd 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -348,10 +348,10 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
   }
   case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
     llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType());
-    Value *SpaceOp = EmitScalarExpr(E->getArg(1));
-    Value *RangeOp = EmitScalarExpr(E->getArg(2));
-    Value *IndexOp = EmitScalarExpr(E->getArg(3));
-    Value *OrderID = EmitScalarExpr(E->getArg(4));
+    Value *OrderID = EmitScalarExpr(E->getArg(1));
+    Value *SpaceOp = EmitScalarExpr(E->getArg(2));
+    Value *RangeOp = EmitScalarExpr(E->getArg(3));
+    Value *IndexOp = EmitScalarExpr(E->getArg(4));
     Value *Name = EmitScalarExpr(E->getArg(5));
     // FIXME: NonUniformResourceIndex bit is not yet implemented
     // (llvm/llvm-project#135452)
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp 
b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 806800cb7b213..7830cdd18c6cd 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -670,7 +670,7 @@ 
BuiltinTypeDeclBuilder::addHandleConstructorFromImplicitBinding() {
       .addParam("orderId", AST.UnsignedIntTy)
       .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
       .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
-                   HandleType, PH::Handle, PH::_0, PH::_1, PH::_2, PH::_3,
+                   HandleType, PH::Handle, PH::_3, PH::_0, PH::_1, PH::_2,
                    PH::_4)
       .assign(PH::Handle, PH::LastStmt)
       .finalize();
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 6a68fa2ed7a8b..c12b35308e127 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2853,8 +2853,8 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned 
BuiltinID, CallExpr *TheCall) {
     if (SemaRef.checkArgCount(TheCall, 6) ||
         CheckResourceHandle(&SemaRef, TheCall, 0) ||
         CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
-        CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.IntTy) ||
-        CheckArgTypeMatches(&SemaRef, TheCall->getArg(3), AST.UnsignedIntTy) ||
+        CheckArgTypeMatches(&SemaRef, TheCall->getArg(2), AST.UnsignedIntTy) ||
+        CheckArgTypeMatches(&SemaRef, TheCall->getArg(3), AST.IntTy) ||
         CheckArgTypeMatches(&SemaRef, TheCall->getArg(4), AST.UnsignedIntTy) ||
         CheckArgTypeMatches(&SemaRef, TheCall->getArg(5),
                             AST.getPointerType(AST.CharTy.withConst())))
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl 
b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index f85194496942b..90794eb69ef46 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -97,10 +97,10 @@ RESOURCE Buffer;
 // CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefromimplicitbinding'
 // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
 // CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
-// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
 // CHECK-NEXT: AlwaysInlineAttr
 
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl 
b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index 6ee7145c7e538..e028936e397ac 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -144,10 +144,10 @@ RESOURCE<float> Buffer;
 // CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefromimplicitbinding'
 // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
 // CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
-// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
 // CHECK-NEXT: AlwaysInlineAttr
 
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl 
b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index e7f000e9c1b70..02c8cf86c8c8b 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -119,10 +119,10 @@ RESOURCE<float> Buffer;
 // CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefromimplicitbinding'
 // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
 // CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
-// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
 // CHECK-NEXT: AlwaysInlineAttr
 

>From dcbbda45ce7d3341ad74025a02b3f8c9b0391dc0 Mon Sep 17 00:00:00 2001
From: Helena Kotas <heko...@microsoft.com>
Date: Thu, 28 Aug 2025 08:22:41 -0700
Subject: [PATCH 2/4] [HLSL] Add static methods for resource initialization and
 a constructor from handle

Adds static methods `__createFromBinding` and `__createFromImplicitBinding`
to resource classes. These methods will be used for resource initialization
instead of the resource constructors that take binding information.

Also adds a private resource constructor that takes an initialized resource 
handle.
This constructor will be called from the static create methods.
---
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 169 ++++++++++++++++--
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h   |   9 +-
 clang/lib/Sema/HLSLExternalSemaSource.cpp     |   5 +-
 .../test/AST/HLSL/ByteAddressBuffers-AST.hlsl |  67 ++++++-
 .../test/AST/HLSL/StructuredBuffers-AST.hlsl  |  63 +++++++
 clang/test/AST/HLSL/TypedBuffers-AST.hlsl     |  63 +++++++
 clang/test/SemaHLSL/Language/InitLists.hlsl   |   1 +
 7 files changed, 354 insertions(+), 23 deletions(-)

diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp 
b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 7830cdd18c6cd..4eac9043dab86 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -19,6 +19,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 #include "clang/Sema/SemaHLSL.h"
@@ -110,8 +111,11 @@ struct BuiltinTypeMethodBuilder {
   CXXMethodDecl *Method;
   bool IsConst;
   bool IsCtor;
+  AccessSpecifier Access;
+  StorageClass SC;
   llvm::SmallVector<Param> Params;
   llvm::SmallVector<Stmt *> StmtsList;
+  llvm::SmallVector<VarDecl *> LocalVars;
 
   // Argument placeholders, inspired by std::placeholder. These are the indices
   // of arguments to forward to `callBuiltin` and other method builder methods.
@@ -120,7 +124,16 @@ struct BuiltinTypeMethodBuilder {
   //   LastStmt - refers to the last statement in the method body; referencing
   //              LastStmt will remove the statement from the method body since
   //              it will be linked from the new expression being constructed.
-  enum class PlaceHolder { _0, _1, _2, _3, _4, Handle = 128, LastStmt };
+  enum class PlaceHolder {
+    _0,
+    _1,
+    _2,
+    _3,
+    _4,
+    LocalVar_0 = 64,
+    Handle = 128,
+    LastStmt
+  };
 
   Expr *convertPlaceholder(PlaceHolder PH);
   Expr *convertPlaceholder(Expr *E) { return E; }
@@ -130,13 +143,17 @@ struct BuiltinTypeMethodBuilder {
 
   BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB, DeclarationName &Name,
                            QualType ReturnTy, bool IsConst = false,
-                           bool IsCtor = false)
+                           bool IsCtor = false,
+                           AccessSpecifier Access = AS_public,
+                           StorageClass SC = SC_None)
       : DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr),
-        IsConst(IsConst), IsCtor(IsCtor) {}
+        IsConst(IsConst), IsCtor(IsCtor), Access(Access), SC(SC) {}
 
   BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB, StringRef NameStr,
                            QualType ReturnTy, bool IsConst = false,
-                           bool IsCtor = false);
+                           bool IsCtor = false,
+                           AccessSpecifier Access = AS_public,
+                           StorageClass SC = SC_None);
   BuiltinTypeMethodBuilder(const BuiltinTypeMethodBuilder &Other) = delete;
 
   ~BuiltinTypeMethodBuilder() { finalize(); }
@@ -147,13 +164,15 @@ struct BuiltinTypeMethodBuilder {
   BuiltinTypeMethodBuilder &addParam(StringRef Name, QualType Ty,
                                      HLSLParamModifierAttr::Spelling Modifier =
                                          HLSLParamModifierAttr::Keyword_in);
+  BuiltinTypeMethodBuilder &createLocalVar(StringRef Name, QualType Ty);
   template <typename... Ts>
   BuiltinTypeMethodBuilder &callBuiltin(StringRef BuiltinName,
                                         QualType ReturnType, Ts... ArgSpecs);
+  template <typename T> BuiltinTypeMethodBuilder &callHandleCtor(T HandleExpr);
   template <typename TLHS, typename TRHS>
   BuiltinTypeMethodBuilder &assign(TLHS LHS, TRHS RHS);
   template <typename T> BuiltinTypeMethodBuilder &dereference(T Ptr);
-  BuiltinTypeDeclBuilder &finalize();
+  BuiltinTypeDeclBuilder &finalize(CXXMethodDecl **OutMethod = nullptr);
   Expr *getResourceHandleExpr();
 
 private:
@@ -328,6 +347,17 @@ Expr 
*BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
   }
 
   ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+  if (PH >= PlaceHolder::LocalVar_0) {
+    unsigned Index = static_cast<unsigned>(PH) -
+                     static_cast<unsigned>(PlaceHolder::LocalVar_0);
+    assert(Index < LocalVars.size() && "local var index out of range");
+    VarDecl *VD = LocalVars[Index];
+    return DeclRefExpr::Create(
+        AST, NestedNameSpecifierLoc(), SourceLocation(), VD, false,
+        DeclarationNameInfo(VD->getDeclName(), SourceLocation()), 
VD->getType(),
+        VK_LValue);
+  }
+
   ParmVarDecl *ParamDecl = Method->getParamDecl(static_cast<unsigned>(PH));
   return DeclRefExpr::Create(
       AST, NestedNameSpecifierLoc(), SourceLocation(), ParamDecl, false,
@@ -335,12 +365,11 @@ Expr 
*BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
       ParamDecl->getType(), VK_PRValue);
 }
 
-BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB,
-                                                   StringRef NameStr,
-                                                   QualType ReturnTy,
-                                                   bool IsConst, bool IsCtor)
+BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder(
+    BuiltinTypeDeclBuilder &DB, StringRef NameStr, QualType ReturnTy,
+    bool IsConst, bool IsCtor, AccessSpecifier Access, StorageClass SC)
     : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr), IsConst(IsConst),
-      IsCtor(IsCtor) {
+      IsCtor(IsCtor), Access(Access), SC(SC) {
 
   assert((!NameStr.empty() || IsCtor) && "method needs a name");
   assert(((IsCtor && !IsConst) || !IsCtor) && "constructor cannot be const");
@@ -390,10 +419,9 @@ void BuiltinTypeMethodBuilder::createDecl() {
         ExplicitSpecifier(), false, true, false,
         ConstexprSpecKind::Unspecified);
   else
-    Method =
-        CXXMethodDecl::Create(AST, DeclBuilder.Record, SourceLocation(),
-                              NameInfo, FuncTy, TSInfo, SC_None, false, false,
-                              ConstexprSpecKind::Unspecified, 
SourceLocation());
+    Method = CXXMethodDecl::Create(
+        AST, DeclBuilder.Record, SourceLocation(), NameInfo, FuncTy, TSInfo, 
SC,
+        false, false, ConstexprSpecKind::Unspecified, SourceLocation());
 
   // create params & set them to the function prototype
   SmallVector<ParmVarDecl *> ParmDecls;
@@ -431,15 +459,31 @@ Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr() {
                                     OK_Ordinary);
 }
 
+BuiltinTypeMethodBuilder &
+BuiltinTypeMethodBuilder::createLocalVar(StringRef Name, QualType Ty) {
+  ensureCompleteDecl();
+
+  ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+  VarDecl *VD =
+      VarDecl::Create(AST, Method, SourceLocation(), SourceLocation(),
+                      &AST.Idents.get(Name, tok::TokenKind::identifier), Ty,
+                      AST.getTrivialTypeSourceInfo(Ty), SC_None);
+  LocalVars.push_back(VD);
+  DeclStmt *DS = new (AST)
+      clang::DeclStmt(DeclGroupRef(VD), SourceLocation(), SourceLocation());
+  StmtsList.push_back(DS);
+  return *this;
+}
+
 template <typename... Ts>
 BuiltinTypeMethodBuilder &
 BuiltinTypeMethodBuilder::callBuiltin(StringRef BuiltinName,
                                       QualType ReturnType, Ts... ArgSpecs) {
+  ensureCompleteDecl();
+
   std::array<Expr *, sizeof...(ArgSpecs)> Args{
       convertPlaceholder(std::forward<Ts>(ArgSpecs))...};
 
-  ensureCompleteDecl();
-
   ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
   FunctionDecl *FD = lookupBuiltinFunction(DeclBuilder.SemaRef, BuiltinName);
   DeclRefExpr *DRE = DeclRefExpr::Create(
@@ -459,6 +503,25 @@ BuiltinTypeMethodBuilder::callBuiltin(StringRef 
BuiltinName,
   return *this;
 }
 
+template <typename T>
+BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::callHandleCtor(T Handle) {
+  ensureCompleteDecl();
+
+  Expr *HandleExpr = convertPlaceholder(Handle);
+
+  ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+  QualType RecordType = 
AST.getTypeDeclType(cast<TypeDecl>(DeclBuilder.Record));
+  CXXConstructorDecl *Ctor = DeclBuilder.HandleCtor;
+  assert(Ctor && "Handle constructor not created");
+
+  CXXConstructExpr *CtorExpr = CXXConstructExpr::Create(
+      AST, RecordType, SourceLocation(), Ctor, false, {HandleExpr}, false,
+      false, false, false, CXXConstructionKind::Complete, SourceRange());
+
+  StmtsList.push_back(CtorExpr);
+  return *this;
+}
+
 template <typename TLHS, typename TRHS>
 BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::assign(TLHS LHS, TRHS RHS) 
{
   Expr *LHSExpr = convertPlaceholder(LHS);
@@ -483,7 +546,8 @@ BuiltinTypeMethodBuilder 
&BuiltinTypeMethodBuilder::dereference(T Ptr) {
   return *this;
 }
 
-BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalize() {
+BuiltinTypeDeclBuilder &
+BuiltinTypeMethodBuilder::finalize(CXXMethodDecl **OutMethod) {
   assert(!DeclBuilder.Record->isCompleteDefinition() &&
          "record is already complete");
 
@@ -510,11 +574,13 @@ BuiltinTypeDeclBuilder 
&BuiltinTypeMethodBuilder::finalize() {
     Method->setBody(CompoundStmt::Create(AST, StmtsList, FPOptionsOverride(),
                                          SourceLocation(), SourceLocation()));
     Method->setLexicalDeclContext(DeclBuilder.Record);
-    Method->setAccess(AccessSpecifier::AS_public);
+    Method->setAccess(Access);
     Method->addAttr(AlwaysInlineAttr::CreateImplicit(
         AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
     DeclBuilder.Record->addDecl(Method);
   }
+  if (OutMethod)
+    *OutMethod = Method;
   return DeclBuilder;
 }
 
@@ -619,7 +685,7 @@ BuiltinTypeDeclBuilder 
&BuiltinTypeDeclBuilder::addHandleMember(
 
 // Adds default constructor to the resource class:
 // Resource::Resource()
-BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultConstructor() {
   if (Record->isCompleteDefinition())
     return *this;
 
@@ -633,6 +699,23 @@ BuiltinTypeDeclBuilder 
&BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
       .finalize();
 }
 
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleConstructor() {
+  if (Record->isCompleteDefinition())
+    return *this;
+
+  using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+  ASTContext &AST = SemaRef.getASTContext();
+  QualType HandleType = getResourceHandleField()->getType();
+  CXXMethodDecl *OutMethod = nullptr;
+
+  BuiltinTypeMethodBuilder(*this, "", AST.VoidTy, false, true, AS_public)
+      .addParam("handle", HandleType)
+      .assign(PH::Handle, PH::_0)
+      .finalize(&OutMethod);
+  HandleCtor = cast<CXXConstructorDecl>(OutMethod);
+  return *this;
+}
+
 BuiltinTypeDeclBuilder &
 BuiltinTypeDeclBuilder::addHandleConstructorFromBinding() {
   if (Record->isCompleteDefinition())
@@ -676,6 +759,54 @@ 
BuiltinTypeDeclBuilder::addHandleConstructorFromImplicitBinding() {
       .finalize();
 }
 
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromBinding() {
+  if (Record->isCompleteDefinition())
+    return *this;
+
+  using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+  ASTContext &AST = SemaRef.getASTContext();
+  QualType HandleType = getResourceHandleField()->getType();
+  QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
+
+  return BuiltinTypeMethodBuilder(*this, "__createFromBinding", RecordType,
+                                  false, false, AS_public, SC_Static)
+      .addParam("registerNo", AST.UnsignedIntTy)
+      .addParam("spaceNo", AST.UnsignedIntTy)
+      .addParam("range", AST.IntTy)
+      .addParam("index", AST.UnsignedIntTy)
+      .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
+      .createLocalVar("tmp", HandleType)
+      .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
+                   PH::LocalVar_0, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
+      .callHandleCtor(PH::LastStmt)
+      .finalize();
+}
+
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCreateFromImplicitBinding() 
{
+  if (Record->isCompleteDefinition())
+    return *this;
+
+  using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+  ASTContext &AST = SemaRef.getASTContext();
+  QualType HandleType = getResourceHandleField()->getType();
+  QualType RecordType = AST.getTypeDeclType(cast<TypeDecl>(Record));
+
+  return BuiltinTypeMethodBuilder(*this, "__createFromImplicitBinding",
+                                  RecordType, false, false, AS_public,
+                                  SC_Static)
+      .addParam("orderId", AST.UnsignedIntTy)
+      .addParam("spaceNo", AST.UnsignedIntTy)
+      .addParam("range", AST.IntTy)
+      .addParam("index", AST.UnsignedIntTy)
+      .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
+      .createLocalVar("tmp", HandleType)
+      .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
+                   HandleType, PH::LocalVar_0, PH::_0, PH::_1, PH::_2, PH::_3,
+                   PH::_4)
+      .callHandleCtor(PH::LastStmt)
+      .finalize();
+}
+
 BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators() {
   ASTContext &AST = Record->getASTContext();
   DeclarationName Subscript =
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h 
b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index 098b72692bd3a..be67e150775e2 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -25,6 +25,7 @@ namespace clang {
 class ClassTemplateDecl;
 class NamespaceDecl;
 class CXXRecordDecl;
+class CXXConstructorDecl;
 class FieldDecl;
 
 namespace hlsl {
@@ -52,6 +53,7 @@ class BuiltinTypeDeclBuilder {
   ClassTemplateDecl *PrevTemplate = nullptr;
   NamespaceDecl *HLSLNamespace = nullptr;
   llvm::StringMap<FieldDecl *> Fields;
+  CXXConstructorDecl *HandleCtor = nullptr;
 
 public:
   friend struct TemplateParameterListBuilder;
@@ -77,10 +79,15 @@ class BuiltinTypeDeclBuilder {
   BuiltinTypeDeclBuilder &addArraySubscriptOperators();
 
   // Builtin types constructors
-  BuiltinTypeDeclBuilder &addDefaultHandleConstructor();
+  BuiltinTypeDeclBuilder &addDefaultConstructor();
+  BuiltinTypeDeclBuilder &addHandleConstructor();
   BuiltinTypeDeclBuilder &addHandleConstructorFromBinding();
   BuiltinTypeDeclBuilder &addHandleConstructorFromImplicitBinding();
 
+  // Static create methods
+  BuiltinTypeDeclBuilder &addCreateFromBinding();
+  BuiltinTypeDeclBuilder &addCreateFromImplicitBinding();
+
   // Builtin types methods
   BuiltinTypeDeclBuilder &addLoadMethods();
   BuiltinTypeDeclBuilder &addIncrementCounterMethod();
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp 
b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 726581d131623..17843c4e6c751 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -131,7 +131,10 @@ static BuiltinTypeDeclBuilder 
setupBufferType(CXXRecordDecl *Decl, Sema &S,
                                               bool RawBuffer) {
   return BuiltinTypeDeclBuilder(S, Decl)
       .addHandleMember(RC, IsROV, RawBuffer)
-      .addDefaultHandleConstructor()
+      .addDefaultConstructor()
+      .addHandleConstructor()
+      .addCreateFromBinding()
+      .addCreateFromImplicitBinding()
       .addHandleConstructorFromBinding()
       .addHandleConstructorFromImplicitBinding();
 }
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl 
b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 90794eb69ef46..8336bf00ed4cb 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -56,6 +56,69 @@ RESOURCE Buffer;
 // CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-NEXT: AlwaysInlineAttr
 
+// Constructor from handle
+
+// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void (__hlsl_resource_t
+// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(char8_t)]]
+// CHECK-SAME: )' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} handle '__hlsl_resource_t
+// CHECK-NEXT: CompoundStmt {{.*}}
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}} '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' ParmVar {{.*}} 
'handle' '__hlsl_resource_t {{.*}}
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// Static __createFromBinding method
+
+// CHECK: CXXMethodDecl {{.*}} __createFromBinding 'hlsl::[[RESOURCE]] 
(unsigned int, unsigned int, int, unsigned int, const char *)' static
+// CHECK-NEXT: ParmVarDecl {{.*}} registerNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
+// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ReturnStmt {{.*}}
+// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]' 'void 
(__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' 
<BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 
'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// Static __createFromImplicitBinding method
+
+// CHECK: CXXMethodDecl {{.*}} __createFromImplicitBinding 'hlsl::[[RESOURCE]] 
(unsigned int, unsigned int, int, unsigned int, const char *)' static
+// CHECK-NEXT: ParmVarDecl {{.*}} orderId 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
+// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
+// CHECK-NEXT: CompoundStmt {{.*}}
+// CHECK-NEXT: DeclStmt {{.*}}
+// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ReturnStmt {{.*}}
+// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]' 'void 
(__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' 
<BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 
'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
 // Constructor from binding
 
 // CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void (unsigned int, unsigned 
int, int, unsigned int, const char *)' inline
@@ -104,5 +167,5 @@ RESOURCE Buffer;
 // CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
 // CHECK-NEXT: AlwaysInlineAttr
 
-// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'const element_type 
&(unsigned int) const'
-// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'element_type 
&(unsigned int)'
+// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'const char8_t 
&(unsigned int) const'
+// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'char8_t &(unsigned 
int)'
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl 
b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index e028936e397ac..ad481ca68b248 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -103,6 +103,69 @@ RESOURCE<float> Buffer;
 // CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
implicit this
 // CHECK-NEXT: AlwaysInlineAttr
 
+// Constructor from handle
+// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void 
(__hlsl_resource_t
+// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME: )' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} handle '__hlsl_resource_t
+// CHECK-NEXT: CompoundStmt {{.*}}
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}} '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' ParmVar {{.*}} 
'handle' '__hlsl_resource_t {{.*}}
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// Static __createFromBinding method
+
+// CHECK: CXXMethodDecl {{.*}} __createFromBinding 
'hlsl::[[RESOURCE]]<element_type> (unsigned int, unsigned int, int, unsigned 
int, const char *)' static
+// CHECK-NEXT: ParmVarDecl {{.*}} registerNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
+// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ReturnStmt {{.*}}
+// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 
'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' 
<BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 
'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// Static __createFromImplicitBinding method
+
+// CHECK: CXXMethodDecl {{.*}} __createFromImplicitBinding 
'hlsl::[[RESOURCE]]<element_type> (unsigned int, unsigned int, int, unsigned 
int, const char *)' static
+// CHECK-NEXT: ParmVarDecl {{.*}} orderId 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
+// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
+// CHECK-NEXT: CompoundStmt {{.*}}
+// CHECK-NEXT: DeclStmt {{.*}}
+// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ReturnStmt {{.*}}
+// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 
'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' 
<BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 
'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
 // Constructor from binding
 
 // CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void (unsigned 
int, unsigned int, int, unsigned int, const char *)' inline
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl 
b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index 02c8cf86c8c8b..3484d088eb17a 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -78,6 +78,69 @@ RESOURCE<float> Buffer;
 // CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
implicit this
 // CHECK-NEXT: AlwaysInlineAttr
 
+// Constructor from handle
+
+// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void 
(__hlsl_resource_t
+// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
+// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
+// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
+// CHECK-SAME: )' inline
+// CHECK-NEXT: ParmVarDecl {{.*}} handle '__hlsl_resource_t
+// CHECK-NEXT: CompoundStmt {{.*}}
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}} '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}} lvalue .__handle
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' ParmVar {{.*}} 
'handle' '__hlsl_resource_t {{.*}}
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// Static __createFromBinding method
+
+// CHECK: CXXMethodDecl {{.*}} __createFromBinding 
'hlsl::[[RESOURCE]]<element_type> (unsigned int, unsigned int, int, unsigned 
int, const char *)' static
+// CHECK-NEXT: ParmVarDecl {{.*}} registerNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
+// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: DeclStmt
+// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ReturnStmt {{.*}}
+// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 
'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' 
<BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 
'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
+// Static __createFromImplicitBinding method
+
+// CHECK: CXXMethodDecl {{.*}} __createFromImplicitBinding 
'hlsl::[[RESOURCE]]<element_type> (unsigned int, unsigned int, int, unsigned 
int, const char *)' static
+// CHECK-NEXT: ParmVarDecl {{.*}} orderId 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} range 'int'
+// CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int'
+// CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
+// CHECK-NEXT: CompoundStmt {{.*}}
+// CHECK-NEXT: DeclStmt {{.*}}
+// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ReturnStmt {{.*}}
+// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 
'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' 
<BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 
'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
 // Constructor from binding
 
 // CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void (unsigned 
int, unsigned int, int, unsigned int, const char *)' inline
diff --git a/clang/test/SemaHLSL/Language/InitLists.hlsl 
b/clang/test/SemaHLSL/Language/InitLists.hlsl
index 3607dfd8aedbc..524f6ac220092 100644
--- a/clang/test/SemaHLSL/Language/InitLists.hlsl
+++ b/clang/test/SemaHLSL/Language/InitLists.hlsl
@@ -124,3 +124,4 @@ void Err2(RWBuffer<float4> B) {
 // These notes refer to the RWBuffer constructors that do not have source 
locations
 // expected-note@*{{candidate constructor (the implicit copy constructor) not 
viable}}
 // expected-note@*{{candidate constructor (the implicit move constructor) not 
viable}}
+// expected-note@*{{candidate constructor not viable}}

>From dfc07bd4df196ac59cb2ec1a0620fc7840534a77 Mon Sep 17 00:00:00 2001
From: Helena Kotas <heko...@microsoft.com>
Date: Wed, 3 Sep 2025 17:55:11 -0700
Subject: [PATCH 3/4] Remove handle constructor, update create methods body and
 expected AST structure

---
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 102 ++++++++++--------
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h   |   1 -
 clang/lib/Sema/HLSLExternalSemaSource.cpp     |   1 -
 .../test/AST/HLSL/ByteAddressBuffers-AST.hlsl |  39 +++----
 .../test/AST/HLSL/StructuredBuffers-AST.hlsl  |  39 +++----
 clang/test/AST/HLSL/TypedBuffers-AST.hlsl     |  39 +++----
 clang/test/SemaHLSL/Language/InitLists.hlsl   |   1 -
 7 files changed, 107 insertions(+), 115 deletions(-)

diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp 
b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 4eac9043dab86..d635664b449c2 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -168,10 +168,13 @@ struct BuiltinTypeMethodBuilder {
   template <typename... Ts>
   BuiltinTypeMethodBuilder &callBuiltin(StringRef BuiltinName,
                                         QualType ReturnType, Ts... ArgSpecs);
-  template <typename T> BuiltinTypeMethodBuilder &callHandleCtor(T HandleExpr);
   template <typename TLHS, typename TRHS>
   BuiltinTypeMethodBuilder &assign(TLHS LHS, TRHS RHS);
   template <typename T> BuiltinTypeMethodBuilder &dereference(T Ptr);
+  template <typename T> BuiltinTypeMethodBuilder &getResourceHandle(T 
ResourceRecord);
+  template <typename TResource, typename TValue>
+  BuiltinTypeMethodBuilder &setHandleFieldOnResource(TResource ResourceRecord, 
TValue HandleValue);
+  template <typename T> BuiltinTypeMethodBuilder &returnValue(T ReturnValue);
   BuiltinTypeDeclBuilder &finalize(CXXMethodDecl **OutMethod = nullptr);
   Expr *getResourceHandleExpr();
 
@@ -503,25 +506,6 @@ BuiltinTypeMethodBuilder::callBuiltin(StringRef 
BuiltinName,
   return *this;
 }
 
-template <typename T>
-BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::callHandleCtor(T Handle) {
-  ensureCompleteDecl();
-
-  Expr *HandleExpr = convertPlaceholder(Handle);
-
-  ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
-  QualType RecordType = 
AST.getTypeDeclType(cast<TypeDecl>(DeclBuilder.Record));
-  CXXConstructorDecl *Ctor = DeclBuilder.HandleCtor;
-  assert(Ctor && "Handle constructor not created");
-
-  CXXConstructExpr *CtorExpr = CXXConstructExpr::Create(
-      AST, RecordType, SourceLocation(), Ctor, false, {HandleExpr}, false,
-      false, false, false, CXXConstructionKind::Complete, SourceRange());
-
-  StmtsList.push_back(CtorExpr);
-  return *this;
-}
-
 template <typename TLHS, typename TRHS>
 BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::assign(TLHS LHS, TRHS RHS) 
{
   Expr *LHSExpr = convertPlaceholder(LHS);
@@ -546,6 +530,51 @@ BuiltinTypeMethodBuilder 
&BuiltinTypeMethodBuilder::dereference(T Ptr) {
   return *this;
 }
 
+template <typename T>
+BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::getResourceHandle(T 
ResourceRecord) {
+  ensureCompleteDecl();
+
+  Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
+
+  ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+  FieldDecl *HandleField = DeclBuilder.getResourceHandleField();
+  MemberExpr *HandleExpr = MemberExpr::CreateImplicit(
+      AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
+      OK_Ordinary);
+  StmtsList.push_back(HandleExpr);
+  return *this;
+}
+
+template <typename TResource, typename TValue>
+BuiltinTypeMethodBuilder 
&BuiltinTypeMethodBuilder::setHandleFieldOnResource(TResource ResourceRecord, 
TValue HandleValue) {
+  ensureCompleteDecl();
+
+  Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
+  Expr *HandleValueExpr = convertPlaceholder(HandleValue);
+
+  ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+  FieldDecl *HandleField = DeclBuilder.getResourceHandleField();
+  MemberExpr *HandleMemberExpr = MemberExpr::CreateImplicit(
+      AST, ResourceExpr, false, HandleField, HandleField->getType(), VK_LValue,
+      OK_Ordinary);
+  Stmt *AssignStmt = BinaryOperator::Create(
+      DeclBuilder.SemaRef.getASTContext(), HandleMemberExpr, HandleValueExpr, 
BO_Assign,
+      HandleMemberExpr->getType(), ExprValueKind::VK_PRValue,
+      ExprObjectKind::OK_Ordinary, SourceLocation(), FPOptionsOverride());
+  StmtsList.push_back(AssignStmt);
+  return *this;
+}
+
+template <typename T>
+BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::returnValue(T ReturnValue) 
{
+  ensureCompleteDecl();
+
+  Expr *ReturnValueExpr = convertPlaceholder(ReturnValue);
+  ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
+  StmtsList.push_back(ReturnStmt::Create(AST, SourceLocation(), 
ReturnValueExpr, nullptr));
+  return *this;
+}
+
 BuiltinTypeDeclBuilder &
 BuiltinTypeMethodBuilder::finalize(CXXMethodDecl **OutMethod) {
   assert(!DeclBuilder.Record->isCompleteDefinition() &&
@@ -699,23 +728,6 @@ BuiltinTypeDeclBuilder 
&BuiltinTypeDeclBuilder::addDefaultConstructor() {
       .finalize();
 }
 
-BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleConstructor() {
-  if (Record->isCompleteDefinition())
-    return *this;
-
-  using PH = BuiltinTypeMethodBuilder::PlaceHolder;
-  ASTContext &AST = SemaRef.getASTContext();
-  QualType HandleType = getResourceHandleField()->getType();
-  CXXMethodDecl *OutMethod = nullptr;
-
-  BuiltinTypeMethodBuilder(*this, "", AST.VoidTy, false, true, AS_public)
-      .addParam("handle", HandleType)
-      .assign(PH::Handle, PH::_0)
-      .finalize(&OutMethod);
-  HandleCtor = cast<CXXConstructorDecl>(OutMethod);
-  return *this;
-}
-
 BuiltinTypeDeclBuilder &
 BuiltinTypeDeclBuilder::addHandleConstructorFromBinding() {
   if (Record->isCompleteDefinition())
@@ -775,10 +787,12 @@ BuiltinTypeDeclBuilder 
&BuiltinTypeDeclBuilder::addCreateFromBinding() {
       .addParam("range", AST.IntTy)
       .addParam("index", AST.UnsignedIntTy)
       .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
-      .createLocalVar("tmp", HandleType)
+      .createLocalVar("tmp", RecordType)
+      .getResourceHandle(PH::LocalVar_0)
       .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
-                   PH::LocalVar_0, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
-      .callHandleCtor(PH::LastStmt)
+                   PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
+      .setHandleFieldOnResource(PH::LocalVar_0, PH::LastStmt)
+      .returnValue(PH::LocalVar_0)
       .finalize();
 }
 
@@ -799,11 +813,13 @@ BuiltinTypeDeclBuilder 
&BuiltinTypeDeclBuilder::addCreateFromImplicitBinding() {
       .addParam("range", AST.IntTy)
       .addParam("index", AST.UnsignedIntTy)
       .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
-      .createLocalVar("tmp", HandleType)
+      .createLocalVar("tmp", RecordType)
+      .getResourceHandle(PH::LocalVar_0)
       .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
-                   HandleType, PH::LocalVar_0, PH::_0, PH::_1, PH::_2, PH::_3,
+                   HandleType, PH::LastStmt, PH::_0, PH::_1, PH::_2, PH::_3,
                    PH::_4)
-      .callHandleCtor(PH::LastStmt)
+      .setHandleFieldOnResource(PH::LocalVar_0, PH::LastStmt)
+      .returnValue(PH::LocalVar_0)
       .finalize();
 }
 
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h 
b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index be67e150775e2..f38bbd63b2ac1 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -80,7 +80,6 @@ class BuiltinTypeDeclBuilder {
 
   // Builtin types constructors
   BuiltinTypeDeclBuilder &addDefaultConstructor();
-  BuiltinTypeDeclBuilder &addHandleConstructor();
   BuiltinTypeDeclBuilder &addHandleConstructorFromBinding();
   BuiltinTypeDeclBuilder &addHandleConstructorFromImplicitBinding();
 
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp 
b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 17843c4e6c751..cfc222af45f8c 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -132,7 +132,6 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl 
*Decl, Sema &S,
   return BuiltinTypeDeclBuilder(S, Decl)
       .addHandleMember(RC, IsROV, RawBuffer)
       .addDefaultConstructor()
-      .addHandleConstructor()
       .addCreateFromBinding()
       .addCreateFromImplicitBinding()
       .addHandleConstructorFromBinding()
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl 
b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 8336bf00ed4cb..1fef4901d7404 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -56,21 +56,6 @@ RESOURCE Buffer;
 // CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
 // CHECK-NEXT: AlwaysInlineAttr
 
-// Constructor from handle
-
-// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void (__hlsl_resource_t
-// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
-// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
-// CHECK-SAME{LITERAL}: [[hlsl::contained_type(char8_t)]]
-// CHECK-SAME: )' inline
-// CHECK-NEXT: ParmVarDecl {{.*}} handle '__hlsl_resource_t
-// CHECK-NEXT: CompoundStmt {{.*}}
-// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}} '='
-// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}} lvalue .__handle
-// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' ParmVar {{.*}} 
'handle' '__hlsl_resource_t {{.*}}
-// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-
 // Static __createFromBinding method
 
 // CHECK: CXXMethodDecl {{.*}} __createFromBinding 'hlsl::[[RESOURCE]] 
(unsigned int, unsigned int, int, unsigned int, const char *)' static
@@ -81,18 +66,22 @@ RESOURCE Buffer;
 // CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
 // CHECK-NEXT: CompoundStmt
 // CHECK-NEXT: DeclStmt
-// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ReturnStmt {{.*}}
-// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]' 'void 
(__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: VarDecl {{.*}} tmp 'hlsl::[[RESOURCE]]'
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}}]]' '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 
'hlsl::[[RESOURCE]]'
 // CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' 
<BuiltinFnToFnPtr>
 // CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 
'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 
'hlsl::[[RESOURCE]]'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 
'hlsl::[[RESOURCE]]'
 // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // Static __createFromImplicitBinding method
@@ -105,18 +94,22 @@ RESOURCE Buffer;
 // CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
 // CHECK-NEXT: CompoundStmt {{.*}}
 // CHECK-NEXT: DeclStmt {{.*}}
-// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ReturnStmt {{.*}}
-// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]' 'void 
(__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: VarDecl {{.*}} tmp 'hlsl::[[RESOURCE]]'
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}}]]' '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 
'hlsl::[[RESOURCE]]'
 // CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' 
<BuiltinFnToFnPtr>
 // CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 
'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 
'hlsl::[[RESOURCE]]'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 
'hlsl::[[RESOURCE]]'
 // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // Constructor from binding
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl 
b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index ad481ca68b248..798af6232b124 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -103,21 +103,6 @@ RESOURCE<float> Buffer;
 // CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
implicit this
 // CHECK-NEXT: AlwaysInlineAttr
 
-// Constructor from handle
-// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void 
(__hlsl_resource_t
-// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
-// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
-// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
-// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
-// CHECK-SAME: )' inline
-// CHECK-NEXT: ParmVarDecl {{.*}} handle '__hlsl_resource_t
-// CHECK-NEXT: CompoundStmt {{.*}}
-// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}} '='
-// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}} lvalue .__handle
-// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
implicit this
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' ParmVar {{.*}} 
'handle' '__hlsl_resource_t {{.*}}
-// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-
 // Static __createFromBinding method
 
 // CHECK: CXXMethodDecl {{.*}} __createFromBinding 
'hlsl::[[RESOURCE]]<element_type> (unsigned int, unsigned int, int, unsigned 
int, const char *)' static
@@ -128,18 +113,22 @@ RESOURCE<float> Buffer;
 // CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
 // CHECK-NEXT: CompoundStmt
 // CHECK-NEXT: DeclStmt
-// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ReturnStmt {{.*}}
-// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 
'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: VarDecl {{.*}} tmp 'hlsl::[[RESOURCE]]<element_type>'
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}}]]' '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
 // CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' 
<BuiltinFnToFnPtr>
 // CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 
'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
 // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // Static __createFromImplicitBinding method
@@ -152,18 +141,22 @@ RESOURCE<float> Buffer;
 // CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
 // CHECK-NEXT: CompoundStmt {{.*}}
 // CHECK-NEXT: DeclStmt {{.*}}
-// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ReturnStmt {{.*}}
-// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 
'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: VarDecl {{.*}} tmp 'hlsl::[[RESOURCE]]<element_type>'
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}}]]' '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
 // CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' 
<BuiltinFnToFnPtr>
 // CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 
'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
 // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // Constructor from binding
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl 
b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index 3484d088eb17a..cc3d9cc399499 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -78,21 +78,6 @@ RESOURCE<float> Buffer;
 // CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
implicit this
 // CHECK-NEXT: AlwaysInlineAttr
 
-// Constructor from handle
-
-// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void 
(__hlsl_resource_t
-// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
-// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
-// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
-// CHECK-SAME: )' inline
-// CHECK-NEXT: ParmVarDecl {{.*}} handle '__hlsl_resource_t
-// CHECK-NEXT: CompoundStmt {{.*}}
-// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}} '='
-// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}} lvalue .__handle
-// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
implicit this
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' ParmVar {{.*}} 
'handle' '__hlsl_resource_t {{.*}}
-// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
-
 // Static __createFromBinding method
 
 // CHECK: CXXMethodDecl {{.*}} __createFromBinding 
'hlsl::[[RESOURCE]]<element_type> (unsigned int, unsigned int, int, unsigned 
int, const char *)' static
@@ -103,18 +88,22 @@ RESOURCE<float> Buffer;
 // CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
 // CHECK-NEXT: CompoundStmt
 // CHECK-NEXT: DeclStmt
-// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ReturnStmt {{.*}}
-// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 
'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: VarDecl {{.*}} tmp 'hlsl::[[RESOURCE]]<element_type>'
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}}]]' '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
 // CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' 
<BuiltinFnToFnPtr>
 // CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefrombinding' 'void (...) noexcept'
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 
'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
 // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // Static __createFromImplicitBinding method
@@ -127,18 +116,22 @@ RESOURCE<float> Buffer;
 // CHECK-NEXT: ParmVarDecl {{.*}} name 'const char *'
 // CHECK-NEXT: CompoundStmt {{.*}}
 // CHECK-NEXT: DeclStmt {{.*}}
-// CHECK-NEXT: VarDecl {{.*}} tmp '__hlsl_resource_t {{.*}}'
-// CHECK-NEXT: ReturnStmt {{.*}}
-// CHECK-NEXT: CXXConstructExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' 
'void (__hlsl_resource_t {{.*}})'
+// CHECK-NEXT: VarDecl {{.*}} tmp 'hlsl::[[RESOURCE]]<element_type>'
+// CHECK-NEXT: BinaryOperator {{.*}} '__hlsl_resource_t {{.*}}]]' '='
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
 // CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t {{.*}}'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' 
<BuiltinFnToFnPtr>
 // CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} 
'__builtin_hlsl_resource_handlefromimplicitbinding' 'void (...) noexcept'
-// CHECK-NEXT: DeclRefExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue Var {{.*}} 
'tmp' '__hlsl_resource_t {{.*}}'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'orderId' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 
'unsigned int'
 // CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const 
char *'
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue 
Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]<element_type>'
 // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
 
 // Constructor from binding
diff --git a/clang/test/SemaHLSL/Language/InitLists.hlsl 
b/clang/test/SemaHLSL/Language/InitLists.hlsl
index 524f6ac220092..3607dfd8aedbc 100644
--- a/clang/test/SemaHLSL/Language/InitLists.hlsl
+++ b/clang/test/SemaHLSL/Language/InitLists.hlsl
@@ -124,4 +124,3 @@ void Err2(RWBuffer<float4> B) {
 // These notes refer to the RWBuffer constructors that do not have source 
locations
 // expected-note@*{{candidate constructor (the implicit copy constructor) not 
viable}}
 // expected-note@*{{candidate constructor (the implicit move constructor) not 
viable}}
-// expected-note@*{{candidate constructor not viable}}

>From e7641e13fb3f85e8978a7f4c25847e0fd817ace9 Mon Sep 17 00:00:00 2001
From: Helena Kotas <heko...@microsoft.com>
Date: Wed, 3 Sep 2025 18:56:32 -0700
Subject: [PATCH 4/4] cleanup

---
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 8 +++-----
 clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h   | 4 +---
 clang/lib/Sema/HLSLExternalSemaSource.cpp     | 2 +-
 3 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp 
b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index d635664b449c2..3ccda084f3813 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -175,7 +175,7 @@ struct BuiltinTypeMethodBuilder {
   template <typename TResource, typename TValue>
   BuiltinTypeMethodBuilder &setHandleFieldOnResource(TResource ResourceRecord, 
TValue HandleValue);
   template <typename T> BuiltinTypeMethodBuilder &returnValue(T ReturnValue);
-  BuiltinTypeDeclBuilder &finalize(CXXMethodDecl **OutMethod = nullptr);
+  BuiltinTypeDeclBuilder &finalize();
   Expr *getResourceHandleExpr();
 
 private:
@@ -576,7 +576,7 @@ BuiltinTypeMethodBuilder 
&BuiltinTypeMethodBuilder::returnValue(T ReturnValue) {
 }
 
 BuiltinTypeDeclBuilder &
-BuiltinTypeMethodBuilder::finalize(CXXMethodDecl **OutMethod) {
+BuiltinTypeMethodBuilder::finalize() {
   assert(!DeclBuilder.Record->isCompleteDefinition() &&
          "record is already complete");
 
@@ -608,8 +608,6 @@ BuiltinTypeMethodBuilder::finalize(CXXMethodDecl 
**OutMethod) {
         AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
     DeclBuilder.Record->addDecl(Method);
   }
-  if (OutMethod)
-    *OutMethod = Method;
   return DeclBuilder;
 }
 
@@ -714,7 +712,7 @@ BuiltinTypeDeclBuilder 
&BuiltinTypeDeclBuilder::addHandleMember(
 
 // Adds default constructor to the resource class:
 // Resource::Resource()
-BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultConstructor() {
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor() {
   if (Record->isCompleteDefinition())
     return *this;
 
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h 
b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index f38bbd63b2ac1..ba860a9080cea 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -25,7 +25,6 @@ namespace clang {
 class ClassTemplateDecl;
 class NamespaceDecl;
 class CXXRecordDecl;
-class CXXConstructorDecl;
 class FieldDecl;
 
 namespace hlsl {
@@ -53,7 +52,6 @@ class BuiltinTypeDeclBuilder {
   ClassTemplateDecl *PrevTemplate = nullptr;
   NamespaceDecl *HLSLNamespace = nullptr;
   llvm::StringMap<FieldDecl *> Fields;
-  CXXConstructorDecl *HandleCtor = nullptr;
 
 public:
   friend struct TemplateParameterListBuilder;
@@ -79,7 +77,7 @@ class BuiltinTypeDeclBuilder {
   BuiltinTypeDeclBuilder &addArraySubscriptOperators();
 
   // Builtin types constructors
-  BuiltinTypeDeclBuilder &addDefaultConstructor();
+  BuiltinTypeDeclBuilder &addDefaultHandleConstructor();
   BuiltinTypeDeclBuilder &addHandleConstructorFromBinding();
   BuiltinTypeDeclBuilder &addHandleConstructorFromImplicitBinding();
 
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp 
b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index cfc222af45f8c..a5d51ca7d35be 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -131,7 +131,7 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl 
*Decl, Sema &S,
                                               bool RawBuffer) {
   return BuiltinTypeDeclBuilder(S, Decl)
       .addHandleMember(RC, IsROV, RawBuffer)
-      .addDefaultConstructor()
+      .addDefaultHandleConstructor()
       .addCreateFromBinding()
       .addCreateFromImplicitBinding()
       .addHandleConstructorFromBinding()

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to