[clang] [HLSL] Add implicit resource element type concepts to AST (PR #112600)

Joshua Batista via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 18 14:06:00 PDT 2024


https://github.com/bob80905 updated https://github.com/llvm/llvm-project/pull/112600

>From 0739f6da81d7c1edd9578ae4ff9dd699e5c828c6 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Thu, 10 Oct 2024 14:31:25 -0700
Subject: [PATCH 01/16] ConceptSpecializationExpr shows up in AST!!!

---
 .../clang/Sema/HLSLExternalSemaSource.h       |   2 +
 clang/lib/AST/DeclTemplate.cpp                |   6 +-
 clang/lib/Sema/HLSLExternalSemaSource.cpp     | 154 +++++++++++++++++-
 3 files changed, 158 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Sema/HLSLExternalSemaSource.h b/clang/include/clang/Sema/HLSLExternalSemaSource.h
index 3c7495e66055dc..0266bc0f8b336e 100644
--- a/clang/include/clang/Sema/HLSLExternalSemaSource.h
+++ b/clang/include/clang/Sema/HLSLExternalSemaSource.h
@@ -47,6 +47,8 @@ class HLSLExternalSemaSource : public ExternalSemaSource {
   using ExternalASTSource::CompleteType;
   /// Complete an incomplete HLSL builtin type
   void CompleteType(TagDecl *Tag) override;
+
+  ConceptDecl *getTypedBufferConceptDecl(Sema &S, CXXRecordDecl *Decl);
 };
 
 } // namespace clang
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 6fe817c5ef1c6b..2eae6d14718b86 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -1080,10 +1080,10 @@ ConceptDecl *ConceptDecl::Create(ASTContext &C, DeclContext *DC,
                                  TemplateParameterList *Params,
                                  Expr *ConstraintExpr) {
   bool Invalid = AdoptTemplateParameterList(Params, DC);
-  auto *TD = new (C, DC) ConceptDecl(DC, L, Name, Params, ConstraintExpr);
+  auto *CD = new (C, DC) ConceptDecl(DC, L, Name, Params, ConstraintExpr);
   if (Invalid)
-    TD->setInvalidDecl();
-  return TD;
+    CD->setInvalidDecl();
+  return CD;
 }
 
 ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 2913d16fca4823..8104513857027c 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -304,6 +304,7 @@ struct BuiltinTypeDeclBuilder {
   TemplateParameterListBuilder addTemplateArgumentList(Sema &S);
   BuiltinTypeDeclBuilder &addSimpleTemplateParams(Sema &S,
                                                   ArrayRef<StringRef> Names);
+  BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S);
 };
 
 struct TemplateParameterListBuilder {
@@ -326,7 +327,8 @@ struct TemplateParameterListBuilder {
         SourceLocation(), /* TemplateDepth */ 0, Position,
         &S.Context.Idents.get(Name, tok::TokenKind::identifier),
         /* Typename */ false,
-        /* ParameterPack */ false);
+        /* ParameterPack */ false,
+        /* HasTypeConstraint*/ true);
     if (!DefaultValue.isNull())
       Decl->setDefaultArgument(
           S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(),
@@ -336,6 +338,152 @@ struct TemplateParameterListBuilder {
     return *this;
   }
 
+  Expr *getTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
+                                     TemplateTypeParmDecl *T) {
+    clang::ASTContext &context = S.getASTContext();
+    // Obtain the QualType for 'unsigned long'
+    clang::QualType unsignedLongType = context.UnsignedLongTy;
+
+    // Create a QualType that points to this TemplateTypeParmDecl
+    clang::QualType TType = context.getTypeDeclType(T);
+
+    // Create a TypeSourceInfo for the template type parameter 'T'
+    clang::TypeSourceInfo *TTypeSourceInfo =
+        context.getTrivialTypeSourceInfo(TType, NameLoc);
+
+    clang::UnaryExprOrTypeTraitExpr *sizeofExpr = new (S.getASTContext())
+        clang::UnaryExprOrTypeTraitExpr(clang::UETT_SizeOf, TTypeSourceInfo,
+                                        unsignedLongType, NameLoc, NameLoc);
+
+    // Create an IntegerLiteral for the value '16'
+    llvm::APInt intValue(context.getIntWidth(context.IntTy), 4);
+    clang::IntegerLiteral *intLiteral = new (context)
+        clang::IntegerLiteral(context, intValue, context.IntTy, NameLoc);
+
+    // Create an ImplicitCastExpr to cast 'int' to 'unsigned long'
+    FPOptionsOverride fpoo = FPOptionsOverride();
+    clang::ImplicitCastExpr *implicitCastExpr = clang::ImplicitCastExpr::Create(
+        context,
+        unsignedLongType, // The type we are casting to (QualType for 'unsigned
+                          // long')
+        clang::CK_IntegralCast, // CastKind (e.g., Integral cast)
+        intLiteral,             // Sub-expression being cast
+        nullptr,                // Base path, usually null for implicit casts
+        clang::VK_XValue,
+        fpoo // Value kind, typically VK_RValue for implicit casts
+    );
+
+    clang::QualType BoolTy = context.BoolTy;
+
+    clang::BinaryOperator *binaryOperator = clang::BinaryOperator::Create(
+        context, sizeofExpr, // Left-hand side expression
+        implicitCastExpr,    // Right-hand side expression
+        clang::BO_LE,        // Binary operator kind (<=)
+        BoolTy,              // Result type (bool)
+        clang::VK_XValue,    // Value kind
+        clang::OK_Ordinary,  // Object kind
+        NameLoc,             // Source location of operator
+        fpoo);
+
+    return binaryOperator;
+  }
+
+  ConceptDecl *getTypedBufferConceptDecl(Sema &S, CXXRecordDecl *Decl) {
+    DeclContext *DC = S.CurContext;
+    clang::ASTContext &context = S.getASTContext();
+    SourceLocation NameLoc = Decl->getBeginLoc();
+    IdentifierInfo *Name = Decl->getIdentifier();
+
+    clang::TemplateTypeParmDecl *T = clang::TemplateTypeParmDecl::Create(
+        context,                          // AST context
+        context.getTranslationUnitDecl(), // DeclContext
+        NameLoc,                          // SourceLocation of 'T'
+        NameLoc,                          // SourceLocation of 'T' again
+        /*depth=*/0,            // Depth in the template parameter list
+        /*position=*/0,         // Position in the template parameter list
+        /*id=*/Name,            // Identifier for 'T'
+        /*Typename=*/true,      // Indicates this is a 'typename' or 'class'
+        /*ParameterPack=*/false // Not a parameter pack
+    );
+
+    T->setDeclContext(DC);
+    T->setReferenced();
+
+    // Create and Attach Template Parameter List to ConceptDecl
+
+    llvm::ArrayRef<NamedDecl *> TemplateParamArrayRef = {T};
+    clang::TemplateParameterList *Params = clang::TemplateParameterList::Create(
+        context,
+        NameLoc, // Source location of the template parameter list start
+        NameLoc, // Source location of the template parameter list end
+        TemplateParamArrayRef, // Template parameter (list as an ArrayRef)
+        NameLoc, // Source location of the template parameter list within
+                 // concept
+        nullptr  // Source location of the template parameter list end within
+                 // concept
+    );
+
+    Expr *ConstraintExpr = getTypedBufferConstraintExpr(S, NameLoc, T);
+
+    DeclarationName DeclName = DeclarationName(Name);
+    // Create a ConceptDecl
+    clang::ConceptDecl *conceptDecl = clang::ConceptDecl::Create(
+        context,
+        context.getTranslationUnitDecl(), // DeclContext
+        NameLoc,                          // Source location of start of concept
+        DeclName,                         // Source location of end of concept
+        Params,                           // Template type parameter
+        ConstraintExpr                    // Expression defining the concept
+    );
+
+    // Attach the template parameter list to the ConceptDecl
+    conceptDecl->setTemplateParameters(Params);
+
+    // Add the concept declaration to the Translation Unit Decl
+    context.getTranslationUnitDecl()->addDecl(conceptDecl);
+
+    return conceptDecl;
+  }
+
+  BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S) {
+    ASTContext &context = S.getASTContext();
+    SourceLocation loc = Builder.Record->getBeginLoc();
+    ConceptDecl *CD = getTypedBufferConceptDecl(S, Builder.Record);
+    DeclarationNameInfo DNI(Builder.Record->getDeclName(), loc);
+    NestedNameSpecifierLoc NNS;
+    ClassTemplateDecl *TD = Builder.Template;
+
+    TemplateArgumentListInfo TALI(loc, loc);
+    const ASTTemplateArgumentListInfo *ATALI =
+        ASTTemplateArgumentListInfo::Create(context, TALI);
+
+    ConceptReference *CR = ConceptReference::Create(
+        S.getASTContext(), NNS, loc, DNI, Builder.Record, CD, ATALI);
+
+    TemplateTypeParmDecl *T = dyn_cast<TemplateTypeParmDecl>(
+        TD->getTemplateParameters()->getParam(0));
+
+    clang::QualType TType = context.getTypeDeclType(T);
+
+    ArrayRef<TemplateArgument> ConvertedArgs = {TemplateArgument(TType)};
+
+    ImplicitConceptSpecializationDecl *IDecl =
+        ImplicitConceptSpecializationDecl::Create(
+            context, Builder.Record->getDeclContext(), loc, ConvertedArgs);
+    const ConstraintSatisfaction CS(CD, ConvertedArgs);
+
+    TemplateParameterList *templateParams = TD->getTemplateParameters();
+    ConceptSpecializationExpr *CSE =
+        ConceptSpecializationExpr::Create(context, CR, IDecl, &CS);
+
+    TD->setTemplateParameters(templateParams);
+    T->setTypeConstraint(CR, CSE);
+
+    Builder.Record->getDeclContext()->addDecl(IDecl);
+
+    return Builder;
+  }
+
   BuiltinTypeDeclBuilder &finalizeTemplateArgs() {
     if (Params.empty())
       return Builder;
@@ -346,9 +494,12 @@ struct TemplateParameterListBuilder {
         S.Context, Builder.Record->getDeclContext(), SourceLocation(),
         DeclarationName(Builder.Record->getIdentifier()), ParamList,
         Builder.Record);
+    addConceptSpecializationExpr(S);
+
     Builder.Record->setDescribedClassTemplate(Builder.Template);
     Builder.Template->setImplicit(true);
     Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());
+
     // NOTE: setPreviousDecl before addDecl so new decl replace old decl when
     // make visible.
     Builder.Template->setPreviousDecl(Builder.PrevTemplate);
@@ -374,6 +525,7 @@ BuiltinTypeDeclBuilder::addSimpleTemplateParams(Sema &S,
   TemplateParameterListBuilder Builder = this->addTemplateArgumentList(S);
   for (StringRef Name : Names)
     Builder.addTypeParameter(Name);
+
   return Builder.finalizeTemplateArgs();
 }
 

>From d1cb98e4cd2a9ffed967cb673760d44799fb20dd Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Thu, 10 Oct 2024 15:51:23 -0700
Subject: [PATCH 02/16] CSE is in the right spot in the AST

---
 clang/lib/Sema/HLSLExternalSemaSource.cpp | 37 ++++++++++++++---------
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 8104513857027c..885ed312d8ed51 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -445,14 +445,13 @@ struct TemplateParameterListBuilder {
     return conceptDecl;
   }
 
-  BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S) {
+  ConceptSpecializationExpr *getConceptSpecializationExpr(Sema &S) {
     ASTContext &context = S.getASTContext();
     SourceLocation loc = Builder.Record->getBeginLoc();
     ConceptDecl *CD = getTypedBufferConceptDecl(S, Builder.Record);
     DeclarationNameInfo DNI(Builder.Record->getDeclName(), loc);
     NestedNameSpecifierLoc NNS;
-    ClassTemplateDecl *TD = Builder.Template;
-
+    DeclContext *DC = Builder.Record->getDeclContext();
     TemplateArgumentListInfo TALI(loc, loc);
     const ASTTemplateArgumentListInfo *ATALI =
         ASTTemplateArgumentListInfo::Create(context, TALI);
@@ -460,8 +459,22 @@ struct TemplateParameterListBuilder {
     ConceptReference *CR = ConceptReference::Create(
         S.getASTContext(), NNS, loc, DNI, Builder.Record, CD, ATALI);
 
-    TemplateTypeParmDecl *T = dyn_cast<TemplateTypeParmDecl>(
-        TD->getTemplateParameters()->getParam(0));
+    clang::TemplateTypeParmDecl *T =
+        clang::TemplateTypeParmDecl::Create(
+            context,                          // AST context
+            context.getTranslationUnitDecl(), // DeclContext
+            loc,                              // SourceLocation of 'T'
+            loc,                              // SourceLocation of 'T' again
+            /*depth=*/0,            // Depth in the template parameter list
+            /*position=*/0,         // Position in the template parameter list
+            /*id=*/Builder.Record->getIdentifier(), // Identifier for 'T'
+            /*Typename=*/true,      // Indicates this is a 'typename' or 'class'
+            /*ParameterPack=*/false,// Not a parameter pack
+            /*HasTypeConstraint=*/true // Not a parameter pack
+        );
+
+    T->setDeclContext(DC);
+    T->setReferenced();
 
     clang::QualType TType = context.getTypeDeclType(T);
 
@@ -472,29 +485,25 @@ struct TemplateParameterListBuilder {
             context, Builder.Record->getDeclContext(), loc, ConvertedArgs);
     const ConstraintSatisfaction CS(CD, ConvertedArgs);
 
-    TemplateParameterList *templateParams = TD->getTemplateParameters();
     ConceptSpecializationExpr *CSE =
         ConceptSpecializationExpr::Create(context, CR, IDecl, &CS);
-
-    TD->setTemplateParameters(templateParams);
     T->setTypeConstraint(CR, CSE);
-
-    Builder.Record->getDeclContext()->addDecl(IDecl);
-
-    return Builder;
+    
+    return CSE;
   }
 
   BuiltinTypeDeclBuilder &finalizeTemplateArgs() {
     if (Params.empty())
       return Builder;
+    ConceptSpecializationExpr *CSE = getConceptSpecializationExpr(S);
+
     auto *ParamList = TemplateParameterList::Create(S.Context, SourceLocation(),
                                                     SourceLocation(), Params,
-                                                    SourceLocation(), nullptr);
+                                                    SourceLocation(), CSE);
     Builder.Template = ClassTemplateDecl::Create(
         S.Context, Builder.Record->getDeclContext(), SourceLocation(),
         DeclarationName(Builder.Record->getIdentifier()), ParamList,
         Builder.Record);
-    addConceptSpecializationExpr(S);
 
     Builder.Record->setDescribedClassTemplate(Builder.Template);
     Builder.Template->setImplicit(true);

>From ff195ae2a67a3354f64e037e0af2cf8d48b87d32 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Thu, 10 Oct 2024 17:55:46 -0700
Subject: [PATCH 03/16] templateArg is aligned correctly on the AST

---
 clang/lib/Sema/HLSLExternalSemaSource.cpp | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 885ed312d8ed51..eed793256399ff 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -449,15 +449,15 @@ struct TemplateParameterListBuilder {
     ASTContext &context = S.getASTContext();
     SourceLocation loc = Builder.Record->getBeginLoc();
     ConceptDecl *CD = getTypedBufferConceptDecl(S, Builder.Record);
-    DeclarationNameInfo DNI(Builder.Record->getDeclName(), loc);
+    DeclarationNameInfo DNI(CD->getDeclName(), loc);
     NestedNameSpecifierLoc NNS;
     DeclContext *DC = Builder.Record->getDeclContext();
     TemplateArgumentListInfo TALI(loc, loc);
     const ASTTemplateArgumentListInfo *ATALI =
         ASTTemplateArgumentListInfo::Create(context, TALI);
 
-    ConceptReference *CR = ConceptReference::Create(
-        S.getASTContext(), NNS, loc, DNI, Builder.Record, CD, ATALI);
+    ConceptReference *CR = ConceptReference::Create(S.getASTContext(), NNS, loc,
+                                                    DNI, CD, CD, ATALI);
 
     clang::TemplateTypeParmDecl *T =
         clang::TemplateTypeParmDecl::Create(
@@ -478,17 +478,18 @@ struct TemplateParameterListBuilder {
 
     clang::QualType TType = context.getTypeDeclType(T);
 
-    ArrayRef<TemplateArgument> ConvertedArgs = {TemplateArgument(TType)};
+    ArrayRef<TemplateArgument> ConvertedArgs = {TemplateArgument(TType),
+                                                TemplateArgument(TType)};
 
     ImplicitConceptSpecializationDecl *IDecl =
         ImplicitConceptSpecializationDecl::Create(
             context, Builder.Record->getDeclContext(), loc, ConvertedArgs);
+
     const ConstraintSatisfaction CS(CD, ConvertedArgs);
 
     ConceptSpecializationExpr *CSE =
         ConceptSpecializationExpr::Create(context, CR, IDecl, &CS);
     T->setTypeConstraint(CR, CSE);
-    
     return CSE;
   }
 

>From 73f932f4179575660135bfb02166e1251a917fa7 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Tue, 15 Oct 2024 11:42:26 -0700
Subject: [PATCH 04/16] template arguments are in the right spot!

---
 clang/lib/Sema/HLSLExternalSemaSource.cpp | 106 ++++++++++++++--------
 1 file changed, 67 insertions(+), 39 deletions(-)

diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index eed793256399ff..0135ff096b946d 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -338,6 +338,27 @@ struct TemplateParameterListBuilder {
     return *this;
   }
 
+  TemplateParameterListBuilder &
+  addTypenameTypeParameter(StringRef Name, QualType DefaultValue = QualType()) {
+    if (Builder.Record->isCompleteDefinition())
+      return *this;
+    unsigned Position = static_cast<unsigned>(Params.size());
+    auto *Decl = TemplateTypeParmDecl::Create(
+        S.Context, Builder.Record->getDeclContext(), SourceLocation(),
+        SourceLocation(), /* TemplateDepth */ 0, Position,
+        &S.Context.Idents.get(Name, tok::TokenKind::identifier),
+        /* Typename */ true,
+        /* ParameterPack */ false,
+        /* HasTypeConstraint*/ false);
+    if (!DefaultValue.isNull())
+      Decl->setDefaultArgument(
+          S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(),
+                                                     SourceLocation()));
+    Decl->setReferenced();
+    Params.emplace_back(Decl);
+    return *this;
+  }
+
   Expr *getTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
                                      TemplateTypeParmDecl *T) {
     clang::ASTContext &context = S.getASTContext();
@@ -369,7 +390,7 @@ struct TemplateParameterListBuilder {
         clang::CK_IntegralCast, // CastKind (e.g., Integral cast)
         intLiteral,             // Sub-expression being cast
         nullptr,                // Base path, usually null for implicit casts
-        clang::VK_XValue,
+        clang::VK_LValue,
         fpoo // Value kind, typically VK_RValue for implicit casts
     );
 
@@ -380,7 +401,7 @@ struct TemplateParameterListBuilder {
         implicitCastExpr,    // Right-hand side expression
         clang::BO_LE,        // Binary operator kind (<=)
         BoolTy,              // Result type (bool)
-        clang::VK_XValue,    // Value kind
+        clang::VK_LValue,    // Value kind
         clang::OK_Ordinary,  // Object kind
         NameLoc,             // Source location of operator
         fpoo);
@@ -392,7 +413,10 @@ struct TemplateParameterListBuilder {
     DeclContext *DC = S.CurContext;
     clang::ASTContext &context = S.getASTContext();
     SourceLocation NameLoc = Decl->getBeginLoc();
-    IdentifierInfo *Name = Decl->getIdentifier();
+
+    IdentifierInfo &IsValidLineVectorII =
+        context.Idents.get("is_valid_line_vector");
+    IdentifierInfo &TII = context.Idents.get("T");
 
     clang::TemplateTypeParmDecl *T = clang::TemplateTypeParmDecl::Create(
         context,                          // AST context
@@ -401,7 +425,7 @@ struct TemplateParameterListBuilder {
         NameLoc,                          // SourceLocation of 'T' again
         /*depth=*/0,            // Depth in the template parameter list
         /*position=*/0,         // Position in the template parameter list
-        /*id=*/Name,            // Identifier for 'T'
+        /*id=*/&TII,            // Identifier for 'T'
         /*Typename=*/true,      // Indicates this is a 'typename' or 'class'
         /*ParameterPack=*/false // Not a parameter pack
     );
@@ -412,32 +436,33 @@ struct TemplateParameterListBuilder {
     // Create and Attach Template Parameter List to ConceptDecl
 
     llvm::ArrayRef<NamedDecl *> TemplateParamArrayRef = {T};
-    clang::TemplateParameterList *Params = clang::TemplateParameterList::Create(
-        context,
-        NameLoc, // Source location of the template parameter list start
-        NameLoc, // Source location of the template parameter list end
-        TemplateParamArrayRef, // Template parameter (list as an ArrayRef)
-        NameLoc, // Source location of the template parameter list within
-                 // concept
-        nullptr  // Source location of the template parameter list end within
-                 // concept
-    );
+    clang::TemplateParameterList *ConceptParams =
+        clang::TemplateParameterList::Create(
+            context,
+            NameLoc, // Source location of the template parameter list start
+            NameLoc, // Source location of the template parameter list end
+            TemplateParamArrayRef, // Template parameter (list as an ArrayRef)
+            NameLoc, // Source location of the template parameter list within
+                     // concept
+            nullptr // Source location of the template parameter list end within
+                    // concept
+        );
 
     Expr *ConstraintExpr = getTypedBufferConstraintExpr(S, NameLoc, T);
 
-    DeclarationName DeclName = DeclarationName(Name);
+    DeclarationName DeclName = DeclarationName(&IsValidLineVectorII);
     // Create a ConceptDecl
     clang::ConceptDecl *conceptDecl = clang::ConceptDecl::Create(
         context,
         context.getTranslationUnitDecl(), // DeclContext
         NameLoc,                          // Source location of start of concept
         DeclName,                         // Source location of end of concept
-        Params,                           // Template type parameter
+        ConceptParams,                    // Template type parameter
         ConstraintExpr                    // Expression defining the concept
     );
 
     // Attach the template parameter list to the ConceptDecl
-    conceptDecl->setTemplateParameters(Params);
+    conceptDecl->setTemplateParameters(ConceptParams);
 
     // Add the concept declaration to the Translation Unit Decl
     context.getTranslationUnitDecl()->addDecl(conceptDecl);
@@ -453,43 +478,43 @@ struct TemplateParameterListBuilder {
     NestedNameSpecifierLoc NNS;
     DeclContext *DC = Builder.Record->getDeclContext();
     TemplateArgumentListInfo TALI(loc, loc);
-    const ASTTemplateArgumentListInfo *ATALI =
-        ASTTemplateArgumentListInfo::Create(context, TALI);
-
-    ConceptReference *CR = ConceptReference::Create(S.getASTContext(), NNS, loc,
-                                                    DNI, CD, CD, ATALI);
 
-    clang::TemplateTypeParmDecl *T =
-        clang::TemplateTypeParmDecl::Create(
-            context,                          // AST context
-            context.getTranslationUnitDecl(), // DeclContext
-            loc,                              // SourceLocation of 'T'
-            loc,                              // SourceLocation of 'T' again
-            /*depth=*/0,            // Depth in the template parameter list
-            /*position=*/0,         // Position in the template parameter list
-            /*id=*/Builder.Record->getIdentifier(), // Identifier for 'T'
-            /*Typename=*/true,      // Indicates this is a 'typename' or 'class'
-            /*ParameterPack=*/false,// Not a parameter pack
-            /*HasTypeConstraint=*/true // Not a parameter pack
-        );
+    clang::TemplateTypeParmDecl *T = clang::TemplateTypeParmDecl::Create(
+        context,                          // AST context
+        context.getTranslationUnitDecl(), // DeclContext
+        SourceLocation(), SourceLocation(),
+        /*depth=*/0,                // Depth in the template parameter list
+        /*position=*/0,             // Position in the template parameter list
+        /*id=*/nullptr,             // Identifier for 'T'
+        /*Typename=*/true,          // Indicates this is a 'typename' or 'class'
+        /*ParameterPack=*/false,    // Not a parameter pack
+        /*HasTypeConstraint=*/false // Not a parameter pack
+    );
 
     T->setDeclContext(DC);
     T->setReferenced();
 
     clang::QualType TType = context.getTypeDeclType(T);
 
-    ArrayRef<TemplateArgument> ConvertedArgs = {TemplateArgument(TType),
-                                                TemplateArgument(TType)};
+    ArrayRef<TemplateArgument> ConvertedArgs = {TemplateArgument(TType)};
 
     ImplicitConceptSpecializationDecl *IDecl =
         ImplicitConceptSpecializationDecl::Create(
             context, Builder.Record->getDeclContext(), loc, ConvertedArgs);
 
     const ConstraintSatisfaction CS(CD, ConvertedArgs);
+    TemplateArgumentLoc tal = S.getTrivialTemplateArgumentLoc(
+        TemplateArgument(TType), QualType(), SourceLocation());
+
+    TALI.addArgument(tal);
+    const ASTTemplateArgumentListInfo *ATALI =
+        ASTTemplateArgumentListInfo::Create(context, TALI);
+    ConceptReference *CR = ConceptReference::Create(S.getASTContext(), NNS, loc,
+                                                    DNI, CD, CD, ATALI);
 
     ConceptSpecializationExpr *CSE =
         ConceptSpecializationExpr::Create(context, CR, IDecl, &CS);
-    T->setTypeConstraint(CR, CSE);
+
     return CSE;
   }
 
@@ -519,6 +544,9 @@ struct TemplateParameterListBuilder {
     QualType T = Builder.Template->getInjectedClassNameSpecialization();
     T = S.Context.getInjectedClassNameType(Builder.Record, T);
 
+    ArrayRef<TemplateArgument> TempArgs =
+        Builder.Template->getInjectedTemplateArgs();
+
     return Builder;
   }
 };
@@ -534,7 +562,7 @@ BuiltinTypeDeclBuilder::addSimpleTemplateParams(Sema &S,
                                                 ArrayRef<StringRef> Names) {
   TemplateParameterListBuilder Builder = this->addTemplateArgumentList(S);
   for (StringRef Name : Names)
-    Builder.addTypeParameter(Name);
+    Builder.addTypenameTypeParameter(Name);
 
   return Builder.finalizeTemplateArgs();
 }

>From b1718c68a6025ea066e4badf8019b162dcfad68c Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Tue, 15 Oct 2024 14:04:46 -0700
Subject: [PATCH 05/16] template arguments are almost done

---
 clang/lib/Sema/HLSLExternalSemaSource.cpp | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 0135ff096b946d..bcfa3c591be91f 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -479,6 +479,9 @@ struct TemplateParameterListBuilder {
     DeclContext *DC = Builder.Record->getDeclContext();
     TemplateArgumentListInfo TALI(loc, loc);
 
+    TemplateTypeParmDecl *ConceptTTPD = dyn_cast<TemplateTypeParmDecl>(
+        CD->getTemplateParameters()->getParam(0));
+
     clang::TemplateTypeParmDecl *T = clang::TemplateTypeParmDecl::Create(
         context,                          // AST context
         context.getTranslationUnitDecl(), // DeclContext
@@ -494,21 +497,31 @@ struct TemplateParameterListBuilder {
     T->setDeclContext(DC);
     T->setReferenced();
 
-    clang::QualType TType = context.getTypeDeclType(T);
+    clang::QualType TType = context.getTypeDeclType(ConceptTTPD);
+
+    TemplateArgument TA = TemplateArgument(TType);
+
+    ArrayRef<TemplateArgument> ConvertedArgs = {TA};
 
-    ArrayRef<TemplateArgument> ConvertedArgs = {TemplateArgument(TType)};
+    clang::QualType CSETType = context.getTypeDeclType(T);
+
+    TemplateArgument CSETA = TemplateArgument(CSETType);
+
+    ArrayRef<TemplateArgument> CSEConvertedArgs = {CSETA};
 
     ImplicitConceptSpecializationDecl *IDecl =
         ImplicitConceptSpecializationDecl::Create(
-            context, Builder.Record->getDeclContext(), loc, ConvertedArgs);
+            context, Builder.Record->getDeclContext(), loc, CSEConvertedArgs);
 
     const ConstraintSatisfaction CS(CD, ConvertedArgs);
-    TemplateArgumentLoc tal = S.getTrivialTemplateArgumentLoc(
-        TemplateArgument(TType), QualType(), SourceLocation());
+    TemplateArgumentLoc tal =
+        S.getTrivialTemplateArgumentLoc(TA, QualType(), SourceLocation());
 
     TALI.addArgument(tal);
     const ASTTemplateArgumentListInfo *ATALI =
         ASTTemplateArgumentListInfo::Create(context, TALI);
+
+    // In CR, ATALI is what adds the extra TemplateArgument node underneath CSE
     ConceptReference *CR = ConceptReference::Create(S.getASTContext(), NNS, loc,
                                                     DNI, CD, CD, ATALI);
 

>From 63358a1d90d6e086b22c257e8d61501ae6f07343 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Tue, 15 Oct 2024 14:26:24 -0700
Subject: [PATCH 06/16] IT WORKS! updated template arg name, just need to
 remove extraneous templatetypeparmdecl

---
 clang/lib/Sema/HLSLExternalSemaSource.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index bcfa3c591be91f..6c490fe08b670f 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -423,9 +423,9 @@ struct TemplateParameterListBuilder {
         context.getTranslationUnitDecl(), // DeclContext
         NameLoc,                          // SourceLocation of 'T'
         NameLoc,                          // SourceLocation of 'T' again
-        /*depth=*/0,            // Depth in the template parameter list
-        /*position=*/0,         // Position in the template parameter list
-        /*id=*/&TII,            // Identifier for 'T'
+        /*depth=*/0,    // Depth in the template parameter list
+        /*position=*/0, // Position in the template parameter list
+        /*id=*/Params[0]->getIdentifier(), // Identifier for 'T'
         /*Typename=*/true,      // Indicates this is a 'typename' or 'class'
         /*ParameterPack=*/false // Not a parameter pack
     );

>From efaf1254baad2807f9a415418a4cd7988dc71abc Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 16 Oct 2024 11:44:01 -0700
Subject: [PATCH 07/16] break down constraint expression into simpler function

---
 clang/lib/Sema/HLSLExternalSemaSource.cpp | 41 ++++++++++++-----------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 6c490fe08b670f..e2db32eeddc7df 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -359,9 +359,9 @@ struct TemplateParameterListBuilder {
     return *this;
   }
 
-  Expr *getTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
+  BinaryOperator *getSizeOfLEQ16Expr(clang::ASTContext &context,
+                                     SourceLocation NameLoc,
                                      TemplateTypeParmDecl *T) {
-    clang::ASTContext &context = S.getASTContext();
     // Obtain the QualType for 'unsigned long'
     clang::QualType unsignedLongType = context.UnsignedLongTy;
 
@@ -376,29 +376,18 @@ struct TemplateParameterListBuilder {
         clang::UnaryExprOrTypeTraitExpr(clang::UETT_SizeOf, TTypeSourceInfo,
                                         unsignedLongType, NameLoc, NameLoc);
 
-    // Create an IntegerLiteral for the value '16'
-    llvm::APInt intValue(context.getIntWidth(context.IntTy), 4);
-    clang::IntegerLiteral *intLiteral = new (context)
-        clang::IntegerLiteral(context, intValue, context.IntTy, NameLoc);
-
-    // Create an ImplicitCastExpr to cast 'int' to 'unsigned long'
-    FPOptionsOverride fpoo = FPOptionsOverride();
-    clang::ImplicitCastExpr *implicitCastExpr = clang::ImplicitCastExpr::Create(
-        context,
-        unsignedLongType, // The type we are casting to (QualType for 'unsigned
-                          // long')
-        clang::CK_IntegralCast, // CastKind (e.g., Integral cast)
-        intLiteral,             // Sub-expression being cast
-        nullptr,                // Base path, usually null for implicit casts
-        clang::VK_LValue,
-        fpoo // Value kind, typically VK_RValue for implicit casts
-    );
+    // Create an IntegerLiteral for the value '16' with size type
+    clang::QualType sizeType = context.getSizeType();
+    llvm::APInt sizeValue = llvm::APInt(context.getTypeSize(sizeType), 16);
+    clang::IntegerLiteral *sizeLiteral = new (context)
+        clang::IntegerLiteral(context, sizeValue, sizeType, NameLoc);
 
     clang::QualType BoolTy = context.BoolTy;
+    FPOptionsOverride fpoo = FPOptionsOverride();
 
     clang::BinaryOperator *binaryOperator = clang::BinaryOperator::Create(
         context, sizeofExpr, // Left-hand side expression
-        implicitCastExpr,    // Right-hand side expression
+        sizeLiteral,         // Right-hand side expression
         clang::BO_LE,        // Binary operator kind (<=)
         BoolTy,              // Result type (bool)
         clang::VK_LValue,    // Value kind
@@ -409,6 +398,18 @@ struct TemplateParameterListBuilder {
     return binaryOperator;
   }
 
+  Expr *getTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
+                                     TemplateTypeParmDecl *T) {
+    clang::ASTContext &context = S.getASTContext();
+
+    // first get the "sizeof(T) <= 16" expression, as a binary operator
+    // TODO: add the '__builtin_hlsl_is_line_vector_layout_compatible' builtin
+    // and return a binary operator that evaluates the builtin on the given
+    // template type parameter 'T'
+    BinaryOperator *sizeOfLEQ16 = getSizeOfLEQ16Expr(context, NameLoc, T);
+    return sizeOfLEQ16;
+  }
+
   ConceptDecl *getTypedBufferConceptDecl(Sema &S, CXXRecordDecl *Decl) {
     DeclContext *DC = S.CurContext;
     clang::ASTContext &context = S.getASTContext();

>From 01ef90694786125414c044935e9d9afc5f5cdddc Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 16 Oct 2024 12:48:09 -0700
Subject: [PATCH 08/16] remove useless function

---
 .../clang/Sema/HLSLExternalSemaSource.h       |  2 --
 clang/lib/Sema/HLSLExternalSemaSource.cpp     | 23 +------------------
 2 files changed, 1 insertion(+), 24 deletions(-)

diff --git a/clang/include/clang/Sema/HLSLExternalSemaSource.h b/clang/include/clang/Sema/HLSLExternalSemaSource.h
index 0266bc0f8b336e..3c7495e66055dc 100644
--- a/clang/include/clang/Sema/HLSLExternalSemaSource.h
+++ b/clang/include/clang/Sema/HLSLExternalSemaSource.h
@@ -47,8 +47,6 @@ class HLSLExternalSemaSource : public ExternalSemaSource {
   using ExternalASTSource::CompleteType;
   /// Complete an incomplete HLSL builtin type
   void CompleteType(TagDecl *Tag) override;
-
-  ConceptDecl *getTypedBufferConceptDecl(Sema &S, CXXRecordDecl *Decl);
 };
 
 } // namespace clang
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index a502f1743aa917..4fc1472a722ce6 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -317,27 +317,6 @@ struct TemplateParameterListBuilder {
 
   TemplateParameterListBuilder &
   addTypeParameter(StringRef Name, QualType DefaultValue = QualType()) {
-    if (Builder.Record->isCompleteDefinition())
-      return *this;
-    unsigned Position = static_cast<unsigned>(Params.size());
-    auto *Decl = TemplateTypeParmDecl::Create(
-        S.Context, Builder.Record->getDeclContext(), SourceLocation(),
-        SourceLocation(), /* TemplateDepth */ 0, Position,
-        &S.Context.Idents.get(Name, tok::TokenKind::identifier),
-        /* Typename */ false,
-        /* ParameterPack */ false,
-        /* HasTypeConstraint*/ true);
-    if (!DefaultValue.isNull())
-      Decl->setDefaultArgument(
-          S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(),
-                                                     SourceLocation()));
-
-    Params.emplace_back(Decl);
-    return *this;
-  }
-
-  TemplateParameterListBuilder &
-  addTypenameTypeParameter(StringRef Name, QualType DefaultValue = QualType()) {
     if (Builder.Record->isCompleteDefinition())
       return *this;
     unsigned Position = static_cast<unsigned>(Params.size());
@@ -574,7 +553,7 @@ BuiltinTypeDeclBuilder::addSimpleTemplateParams(Sema &S,
                                                 ArrayRef<StringRef> Names) {
   TemplateParameterListBuilder Builder = this->addTemplateArgumentList(S);
   for (StringRef Name : Names)
-    Builder.addTypenameTypeParameter(Name);
+    Builder.addTypeParameter(Name);
 
   return Builder.finalizeTemplateArgs();
 }

>From ee5dbc599fae7127bcee999c4e58405474f4403b Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 16 Oct 2024 13:40:15 -0700
Subject: [PATCH 09/16] some variable renaming, function rearranging

---
 clang/lib/Sema/HLSLExternalSemaSource.cpp | 232 ++++++++++------------
 1 file changed, 110 insertions(+), 122 deletions(-)

diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 4fc1472a722ce6..a5f41e23cb7abe 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -301,7 +301,7 @@ struct BuiltinTypeDeclBuilder {
 
   TemplateParameterListBuilder addTemplateArgumentList(Sema &S);
   BuiltinTypeDeclBuilder &addSimpleTemplateParams(Sema &S,
-                                                  ArrayRef<StringRef> Names);
+                                                  ArrayRef<StringRef> Names, ConceptDecl *CD);
   BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S);
 };
 
@@ -309,11 +309,12 @@ struct TemplateParameterListBuilder {
   BuiltinTypeDeclBuilder &Builder;
   Sema &S;
   llvm::SmallVector<NamedDecl *> Params;
+  
 
   TemplateParameterListBuilder(Sema &S, BuiltinTypeDeclBuilder &RB)
       : Builder(RB), S(S) {}
 
-  ~TemplateParameterListBuilder() { finalizeTemplateArgs(); }
+  ~TemplateParameterListBuilder() { finalizeTemplateArgs(nullptr); }
 
   TemplateParameterListBuilder &
   addTypeParameter(StringRef Name, QualType DefaultValue = QualType()) {
@@ -334,124 +335,11 @@ struct TemplateParameterListBuilder {
     Decl->setReferenced();
     Params.emplace_back(Decl);
     return *this;
-  }
-
-  BinaryOperator *getSizeOfLEQ16Expr(clang::ASTContext &context,
-                                     SourceLocation NameLoc,
-                                     TemplateTypeParmDecl *T) {
-    // Obtain the QualType for 'unsigned long'
-    clang::QualType unsignedLongType = context.UnsignedLongTy;
-
-    // Create a QualType that points to this TemplateTypeParmDecl
-    clang::QualType TType = context.getTypeDeclType(T);
-
-    // Create a TypeSourceInfo for the template type parameter 'T'
-    clang::TypeSourceInfo *TTypeSourceInfo =
-        context.getTrivialTypeSourceInfo(TType, NameLoc);
-
-    clang::UnaryExprOrTypeTraitExpr *sizeofExpr = new (S.getASTContext())
-        clang::UnaryExprOrTypeTraitExpr(clang::UETT_SizeOf, TTypeSourceInfo,
-                                        unsignedLongType, NameLoc, NameLoc);
-
-    // Create an IntegerLiteral for the value '16' with size type
-    clang::QualType sizeType = context.getSizeType();
-    llvm::APInt sizeValue = llvm::APInt(context.getTypeSize(sizeType), 16);
-    clang::IntegerLiteral *sizeLiteral = new (context)
-        clang::IntegerLiteral(context, sizeValue, sizeType, NameLoc);
-
-    clang::QualType BoolTy = context.BoolTy;
-    FPOptionsOverride fpoo = FPOptionsOverride();
-
-    clang::BinaryOperator *binaryOperator = clang::BinaryOperator::Create(
-        context, sizeofExpr, // Left-hand side expression
-        sizeLiteral,         // Right-hand side expression
-        clang::BO_LE,        // Binary operator kind (<=)
-        BoolTy,              // Result type (bool)
-        clang::VK_LValue,    // Value kind
-        clang::OK_Ordinary,  // Object kind
-        NameLoc,             // Source location of operator
-        fpoo);
-
-    return binaryOperator;
-  }
-
-  Expr *getTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
-                                     TemplateTypeParmDecl *T) {
-    clang::ASTContext &context = S.getASTContext();
-
-    // first get the "sizeof(T) <= 16" expression, as a binary operator
-    // TODO: add the '__builtin_hlsl_is_line_vector_layout_compatible' builtin
-    // and return a binary operator that evaluates the builtin on the given
-    // template type parameter 'T'
-    BinaryOperator *sizeOfLEQ16 = getSizeOfLEQ16Expr(context, NameLoc, T);
-    return sizeOfLEQ16;
-  }
-
-  ConceptDecl *getTypedBufferConceptDecl(Sema &S, CXXRecordDecl *Decl) {
-    DeclContext *DC = S.CurContext;
-    clang::ASTContext &context = S.getASTContext();
-    SourceLocation NameLoc = Decl->getBeginLoc();
-
-    IdentifierInfo &IsValidLineVectorII =
-        context.Idents.get("is_valid_line_vector");
-    IdentifierInfo &TII = context.Idents.get("T");
-
-    clang::TemplateTypeParmDecl *T = clang::TemplateTypeParmDecl::Create(
-        context,                          // AST context
-        context.getTranslationUnitDecl(), // DeclContext
-        NameLoc,                          // SourceLocation of 'T'
-        NameLoc,                          // SourceLocation of 'T' again
-        /*depth=*/0,    // Depth in the template parameter list
-        /*position=*/0, // Position in the template parameter list
-        /*id=*/Params[0]->getIdentifier(), // Identifier for 'T'
-        /*Typename=*/true,      // Indicates this is a 'typename' or 'class'
-        /*ParameterPack=*/false // Not a parameter pack
-    );
-
-    T->setDeclContext(DC);
-    T->setReferenced();
+  }  
 
-    // Create and Attach Template Parameter List to ConceptDecl
-
-    llvm::ArrayRef<NamedDecl *> TemplateParamArrayRef = {T};
-    clang::TemplateParameterList *ConceptParams =
-        clang::TemplateParameterList::Create(
-            context,
-            NameLoc, // Source location of the template parameter list start
-            NameLoc, // Source location of the template parameter list end
-            TemplateParamArrayRef, // Template parameter (list as an ArrayRef)
-            NameLoc, // Source location of the template parameter list within
-                     // concept
-            nullptr // Source location of the template parameter list end within
-                    // concept
-        );
-
-    Expr *ConstraintExpr = getTypedBufferConstraintExpr(S, NameLoc, T);
-
-    DeclarationName DeclName = DeclarationName(&IsValidLineVectorII);
-    // Create a ConceptDecl
-    clang::ConceptDecl *conceptDecl = clang::ConceptDecl::Create(
-        context,
-        context.getTranslationUnitDecl(), // DeclContext
-        NameLoc,                          // Source location of start of concept
-        DeclName,                         // Source location of end of concept
-        ConceptParams,                    // Template type parameter
-        ConstraintExpr                    // Expression defining the concept
-    );
-
-    // Attach the template parameter list to the ConceptDecl
-    conceptDecl->setTemplateParameters(ConceptParams);
-
-    // Add the concept declaration to the Translation Unit Decl
-    context.getTranslationUnitDecl()->addDecl(conceptDecl);
-
-    return conceptDecl;
-  }
-
-  ConceptSpecializationExpr *getConceptSpecializationExpr(Sema &S) {
+  ConceptSpecializationExpr *getConceptSpecializationExpr(Sema &S, ConceptDecl *CD) {
     ASTContext &context = S.getASTContext();
     SourceLocation loc = Builder.Record->getBeginLoc();
-    ConceptDecl *CD = getTypedBufferConceptDecl(S, Builder.Record);
     DeclarationNameInfo DNI(CD->getDeclName(), loc);
     NestedNameSpecifierLoc NNS;
     DeclContext *DC = Builder.Record->getDeclContext();
@@ -509,10 +397,10 @@ struct TemplateParameterListBuilder {
     return CSE;
   }
 
-  BuiltinTypeDeclBuilder &finalizeTemplateArgs() {
+  BuiltinTypeDeclBuilder &finalizeTemplateArgs(ConceptDecl *CD) {
     if (Params.empty())
       return Builder;
-    ConceptSpecializationExpr *CSE = getConceptSpecializationExpr(S);
+    ConceptSpecializationExpr *CSE = CD ? getConceptSpecializationExpr(S, CD) : nullptr;
 
     auto *ParamList = TemplateParameterList::Create(S.Context, SourceLocation(),
                                                     SourceLocation(), Params,
@@ -550,12 +438,12 @@ BuiltinTypeDeclBuilder::addTemplateArgumentList(Sema &S) {
 
 BuiltinTypeDeclBuilder &
 BuiltinTypeDeclBuilder::addSimpleTemplateParams(Sema &S,
-                                                ArrayRef<StringRef> Names) {
+                                                ArrayRef<StringRef> Names, ConceptDecl *CD = nullptr) {
   TemplateParameterListBuilder Builder = this->addTemplateArgumentList(S);
   for (StringRef Name : Names)
     Builder.addTypeParameter(Name);
 
-  return Builder.finalizeTemplateArgs();
+  return Builder.finalizeTemplateArgs(CD);
 }
 
 HLSLExternalSemaSource::~HLSLExternalSemaSource() {}
@@ -666,10 +554,110 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
       .addDefaultHandleConstructor(S, RC);
 }
 
+BinaryOperator *getSizeOfLEQ16Expr(clang::ASTContext &context,
+                                   SourceLocation NameLoc,
+                                   TemplateTypeParmDecl *T) {
+  // Obtain the QualType for 'unsigned long'
+  clang::QualType unsignedLongType = context.UnsignedLongTy;
+
+  // Create a QualType that points to this TemplateTypeParmDecl
+  clang::QualType TType = context.getTypeDeclType(T);
+
+  // Create a TypeSourceInfo for the template type parameter 'T'
+  clang::TypeSourceInfo *TTypeSourceInfo =
+      context.getTrivialTypeSourceInfo(TType, NameLoc);
+
+  clang::UnaryExprOrTypeTraitExpr *sizeOfExpr = new (context)
+      clang::UnaryExprOrTypeTraitExpr(clang::UETT_SizeOf, TTypeSourceInfo,
+                                      unsignedLongType, NameLoc, NameLoc);
+
+  // Create an IntegerLiteral for the value '16' with size type
+  clang::QualType sizeType = context.getSizeType();
+  llvm::APInt sizeValue = llvm::APInt(context.getTypeSize(sizeType), 16);
+  clang::IntegerLiteral *sizeLiteral = new (context)
+      clang::IntegerLiteral(context, sizeValue, sizeType, NameLoc);
+
+  clang::QualType BoolTy = context.BoolTy;
+
+  clang::BinaryOperator *binaryOperator = clang::BinaryOperator::Create(
+      context, sizeOfExpr, // Left-hand side expression
+      sizeLiteral,         // Right-hand side expression
+      clang::BO_LE,        // Binary operator kind (<=)
+      BoolTy,              // Result type (bool)
+      clang::VK_LValue,    // Value kind
+      clang::OK_Ordinary,  // Object kind
+      NameLoc,             // Source location of operator
+      FPOptionsOverride());
+
+  return binaryOperator;
+}
+
+Expr *getTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
+                                   TemplateTypeParmDecl *T) {
+  clang::ASTContext &context = S.getASTContext();
+
+  // first get the "sizeof(T) <= 16" expression, as a binary operator
+  BinaryOperator *sizeOfLEQ16 = getSizeOfLEQ16Expr(context, NameLoc, T);
+  // TODO: add the '__builtin_hlsl_is_line_vector_layout_compatible' builtin
+  // and return a binary operator that evaluates the builtin on the given
+  // template type parameter 'T'
+  return sizeOfLEQ16;
+}
+
+ConceptDecl *getTypedBufferConceptDecl(Sema &S) {
+  DeclContext *DC = S.CurContext;
+  clang::ASTContext &context = S.getASTContext();
+  SourceLocation DeclLoc = SourceLocation();
+
+  IdentifierInfo &IsValidLineVectorII =
+      context.Idents.get("is_valid_line_vector");
+  IdentifierInfo &ElementTypeII =
+      context.Idents.get("element_type");
+  clang::TemplateTypeParmDecl *T = clang::TemplateTypeParmDecl::Create(
+      context, context.getTranslationUnitDecl(), DeclLoc, DeclLoc,
+      /*depth=*/0,
+      /*position=*/0,
+      /*id=*/&ElementTypeII,
+      /*Typename=*/true,
+      /*ParameterPack=*/false);
+
+  T->setDeclContext(DC);
+  T->setReferenced();
+
+  // Create and Attach Template Parameter List to ConceptDecl
+  llvm::ArrayRef<NamedDecl *> TemplateParams = {T};
+  clang::TemplateParameterList *ConceptParams =
+      clang::TemplateParameterList::Create(context, DeclLoc, DeclLoc,
+                                           TemplateParams, DeclLoc, nullptr);
+
+  DeclarationName DeclName = DeclarationName(&IsValidLineVectorII);
+  Expr *ConstraintExpr = getTypedBufferConstraintExpr(S, DeclLoc, T);
+
+  // Create a ConceptDecl
+  clang::ConceptDecl *conceptDecl = clang::ConceptDecl::Create(
+      context,
+      context.getTranslationUnitDecl(), // DeclContext
+      DeclLoc,                          // Source location of start of concept
+      DeclName,                         // Source location of end of concept
+      ConceptParams,                    // Template type parameter
+      ConstraintExpr                    // Expression defining the concept
+  );
+
+  // Attach the template parameter list to the ConceptDecl
+  conceptDecl->setTemplateParameters(ConceptParams);
+
+  // Add the concept declaration to the Translation Unit Decl
+  context.getTranslationUnitDecl()->addDecl(conceptDecl);
+
+  return conceptDecl;
+}
+
 void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
   CXXRecordDecl *Decl;
+  ConceptDecl *CD = getTypedBufferConceptDecl(*SemaPtr);
+
   Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer")
-             .addSimpleTemplateParams(*SemaPtr, {"element_type"})
+             .addSimpleTemplateParams(*SemaPtr, {"element_type"}, CD)
              .Record;
 
   onCompletion(Decl, [this](CXXRecordDecl *Decl) {

>From f6ec52c31be98dbc4f6121d6f921cf27af5010fa Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 16 Oct 2024 13:42:13 -0700
Subject: [PATCH 10/16] clang format

---
 clang/lib/Sema/HLSLExternalSemaSource.cpp | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index a5f41e23cb7abe..5863c8df955479 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -300,8 +300,8 @@ struct BuiltinTypeDeclBuilder {
   }
 
   TemplateParameterListBuilder addTemplateArgumentList(Sema &S);
-  BuiltinTypeDeclBuilder &addSimpleTemplateParams(Sema &S,
-                                                  ArrayRef<StringRef> Names, ConceptDecl *CD);
+  BuiltinTypeDeclBuilder &
+  addSimpleTemplateParams(Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD);
   BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S);
 };
 
@@ -309,7 +309,6 @@ struct TemplateParameterListBuilder {
   BuiltinTypeDeclBuilder &Builder;
   Sema &S;
   llvm::SmallVector<NamedDecl *> Params;
-  
 
   TemplateParameterListBuilder(Sema &S, BuiltinTypeDeclBuilder &RB)
       : Builder(RB), S(S) {}
@@ -335,9 +334,10 @@ struct TemplateParameterListBuilder {
     Decl->setReferenced();
     Params.emplace_back(Decl);
     return *this;
-  }  
+  }
 
-  ConceptSpecializationExpr *getConceptSpecializationExpr(Sema &S, ConceptDecl *CD) {
+  ConceptSpecializationExpr *getConceptSpecializationExpr(Sema &S,
+                                                          ConceptDecl *CD) {
     ASTContext &context = S.getASTContext();
     SourceLocation loc = Builder.Record->getBeginLoc();
     DeclarationNameInfo DNI(CD->getDeclName(), loc);
@@ -400,7 +400,8 @@ struct TemplateParameterListBuilder {
   BuiltinTypeDeclBuilder &finalizeTemplateArgs(ConceptDecl *CD) {
     if (Params.empty())
       return Builder;
-    ConceptSpecializationExpr *CSE = CD ? getConceptSpecializationExpr(S, CD) : nullptr;
+    ConceptSpecializationExpr *CSE =
+        CD ? getConceptSpecializationExpr(S, CD) : nullptr;
 
     auto *ParamList = TemplateParameterList::Create(S.Context, SourceLocation(),
                                                     SourceLocation(), Params,
@@ -436,9 +437,8 @@ BuiltinTypeDeclBuilder::addTemplateArgumentList(Sema &S) {
   return TemplateParameterListBuilder(S, *this);
 }
 
-BuiltinTypeDeclBuilder &
-BuiltinTypeDeclBuilder::addSimpleTemplateParams(Sema &S,
-                                                ArrayRef<StringRef> Names, ConceptDecl *CD = nullptr) {
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addSimpleTemplateParams(
+    Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD = nullptr) {
   TemplateParameterListBuilder Builder = this->addTemplateArgumentList(S);
   for (StringRef Name : Names)
     Builder.addTypeParameter(Name);
@@ -611,8 +611,7 @@ ConceptDecl *getTypedBufferConceptDecl(Sema &S) {
 
   IdentifierInfo &IsValidLineVectorII =
       context.Idents.get("is_valid_line_vector");
-  IdentifierInfo &ElementTypeII =
-      context.Idents.get("element_type");
+  IdentifierInfo &ElementTypeII = context.Idents.get("element_type");
   clang::TemplateTypeParmDecl *T = clang::TemplateTypeParmDecl::Create(
       context, context.getTranslationUnitDecl(), DeclLoc, DeclLoc,
       /*depth=*/0,

>From ed2bd244fee8bfffeaa9f67c716a6df8c0b78adb Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 16 Oct 2024 14:52:44 -0700
Subject: [PATCH 11/16] fix / add test cases

---
 clang/lib/Sema/HLSLExternalSemaSource.cpp     | 28 ++++++++++---------
 clang/test/AST/HLSL/RWBuffer-AST.hlsl         | 20 +++++++++++--
 clang/test/AST/HLSL/StructuredBuffer-AST.hlsl |  4 +--
 clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl   | 15 ++++++++--
 .../SemaHLSL/BuiltIns/StructuredBuffers.hlsl  |  4 +--
 5 files changed, 50 insertions(+), 21 deletions(-)

diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 5863c8df955479..b2d5413f7971a9 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -341,10 +341,11 @@ struct TemplateParameterListBuilder {
     ASTContext &context = S.getASTContext();
     SourceLocation loc = Builder.Record->getBeginLoc();
     DeclarationNameInfo DNI(CD->getDeclName(), loc);
-    NestedNameSpecifierLoc NNS;
+    NestedNameSpecifierLoc NNSLoc;
     DeclContext *DC = Builder.Record->getDeclContext();
     TemplateArgumentListInfo TALI(loc, loc);
 
+    // assume that the concept decl has just one template parameter
     TemplateTypeParmDecl *ConceptTTPD = dyn_cast<TemplateTypeParmDecl>(
         CD->getTemplateParameters()->getParam(0));
 
@@ -363,11 +364,11 @@ struct TemplateParameterListBuilder {
     T->setDeclContext(DC);
     T->setReferenced();
 
-    clang::QualType TType = context.getTypeDeclType(ConceptTTPD);
+    clang::QualType ConceptTType = context.getTypeDeclType(ConceptTTPD);
 
-    TemplateArgument TA = TemplateArgument(TType);
+    TemplateArgument ConceptTA = TemplateArgument(ConceptTType);
 
-    ArrayRef<TemplateArgument> ConvertedArgs = {TA};
+    ArrayRef<TemplateArgument> ConceptConvertedArgs = {ConceptTA};
 
     clang::QualType CSETType = context.getTypeDeclType(T);
 
@@ -375,24 +376,25 @@ struct TemplateParameterListBuilder {
 
     ArrayRef<TemplateArgument> CSEConvertedArgs = {CSETA};
 
-    ImplicitConceptSpecializationDecl *IDecl =
+    ImplicitConceptSpecializationDecl *ImplicitCSEDecl =
         ImplicitConceptSpecializationDecl::Create(
             context, Builder.Record->getDeclContext(), loc, CSEConvertedArgs);
 
-    const ConstraintSatisfaction CS(CD, ConvertedArgs);
-    TemplateArgumentLoc tal =
-        S.getTrivialTemplateArgumentLoc(TA, QualType(), SourceLocation());
+    const ConstraintSatisfaction CS(CD, ConceptConvertedArgs);
+    TemplateArgumentLoc TAL = S.getTrivialTemplateArgumentLoc(
+        ConceptTA, QualType(), SourceLocation());
 
-    TALI.addArgument(tal);
+    TALI.addArgument(TAL);
     const ASTTemplateArgumentListInfo *ATALI =
         ASTTemplateArgumentListInfo::Create(context, TALI);
 
-    // In CR, ATALI is what adds the extra TemplateArgument node underneath CSE
-    ConceptReference *CR = ConceptReference::Create(S.getASTContext(), NNS, loc,
-                                                    DNI, CD, CD, ATALI);
+    // In the concept reference, ATALI is what adds the extra
+    // TemplateArgument node underneath CSE
+    ConceptReference *CR = ConceptReference::Create(S.getASTContext(), NNSLoc,
+                                                    loc, DNI, CD, CD, ATALI);
 
     ConceptSpecializationExpr *CSE =
-        ConceptSpecializationExpr::Create(context, CR, IDecl, &CS);
+        ConceptSpecializationExpr::Create(context, CR, ImplicitCSEDecl, &CS);
 
     return CSE;
   }
diff --git a/clang/test/AST/HLSL/RWBuffer-AST.hlsl b/clang/test/AST/HLSL/RWBuffer-AST.hlsl
index e6ce73dbd962f7..b60519e803bb79 100644
--- a/clang/test/AST/HLSL/RWBuffer-AST.hlsl
+++ b/clang/test/AST/HLSL/RWBuffer-AST.hlsl
@@ -11,7 +11,15 @@
 // instantiated specialization.
 
 // EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit RWBuffer
-// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
+// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> referenced typename depth 0 index 0 element_type
+// EMPTY-NEXT: ConceptSpecializationExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'bool' Concept 0x{{[0-9A-Fa-f]+}} 'is_valid_line_vector'
+// EMPTY-NEXT: ImplicitConceptSpecializationDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc>
+// EMPTY-NEXT: TemplateArgument type 'type-parameter-0-0'
+// EMPTY-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-0' dependent depth 0 index 0
+// EMPTY-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
+// EMPTY-NEXT: TemplateArgument type 'element_type':'type-parameter-0-0'
+// EMPTY-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'element_type' dependent depth 0 index 0
+// EMPTY-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'element_type'
 // EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit <undeserialized declarations> class RWBuffer
 // EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
 
@@ -25,7 +33,15 @@ RWBuffer<float> Buffer;
 #endif
 
 // CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit RWBuffer
-// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> referenced typename depth 0 index 0 element_type
+// CHECK-NEXT: ConceptSpecializationExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'bool' Concept 0x{{[0-9A-Fa-f]+}} 'is_valid_line_vector'
+// CHECK-NEXT: ImplicitConceptSpecializationDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc>
+// CHECK-NEXT: TemplateArgument type 'type-parameter-0-0'
+// CHECK-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-0' dependent depth 0 index 0
+// CHECK-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
+// CHECK-NEXT: TemplateArgument type 'element_type':'type-parameter-0-0'
+// CHECK-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'element_type' dependent depth 0 index 0
+// CHECK-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'element_type'
 // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit class RWBuffer definition
 
 // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
diff --git a/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl
index 030fcfc31691dc..14784b5abb60b7 100644
--- a/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl
@@ -12,7 +12,7 @@
 // instantiated specialization.
 
 // EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit StructuredBuffer
-// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
+// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> referenced typename depth 0 index 0 element_type
 // EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit <undeserialized declarations> class StructuredBuffer
 // EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
 
@@ -26,7 +26,7 @@ StructuredBuffer<float> Buffer;
 #endif
 
 // CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit StructuredBuffer
-// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> referenced typename depth 0 index 0 element_type
 // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit class StructuredBuffer definition
 
 // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
diff --git a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl
index 76b5d01b8036eb..9880b643852a20 100644
--- a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl
@@ -5,13 +5,24 @@ typedef vector<float, 3> float3;
 RWBuffer<float3> Buffer;
 
 // expected-error at +2 {{class template 'RWBuffer' requires template arguments}}
-// expected-note@*:* {{template declaration from hidden source: template <class element_type> class RWBuffer}}
+// expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires is_valid_line_vector<element_type> class RWBuffer {}}}
 RWBuffer BufferErr1;
 
 // expected-error at +2 {{too few template arguments for class template 'RWBuffer'}}
-// expected-note@*:* {{template declaration from hidden source: template <class element_type> class RWBuffer}}
+// expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires is_valid_line_vector<element_type> class RWBuffer {}}}
 RWBuffer<> BufferErr2;
 
+struct threeDoubles {
+  double a;
+  double b;
+  double c;
+};
+
+// expected-error at +3 {{constraints not satisfied for class template 'RWBuffer'}}
+// expected-note@*:* {{because 'threeDoubles' does not satisfy 'is_valid_line_vector'}}
+// expected-note@*:* {{because 'sizeof(threeDoubles) <= 16UL' (24 <= 16) evaluated to false}}
+RWBuffer<threeDoubles> BufferErr3;
+
 [numthreads(1,1,1)]
 void main() {
   (void)Buffer.h; // expected-error {{'h' is a private member of 'hlsl::RWBuffer<vector<float, 3>>'}}
diff --git a/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl
index a472d5519dc51f..552624f13ee5f8 100644
--- a/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl
@@ -5,11 +5,11 @@ typedef vector<float, 3> float3;
 StructuredBuffer<float3> Buffer;
 
 // expected-error at +2 {{class template 'StructuredBuffer' requires template arguments}}
-// expected-note@*:* {{template declaration from hidden source: template <class element_type> class StructuredBuffer}}
+// expected-note@*:* {{template declaration from hidden source: template <typename element_type> class StructuredBuffer {}}}
 StructuredBuffer BufferErr1;
 
 // expected-error at +2 {{too few template arguments for class template 'StructuredBuffer'}}
-// expected-note@*:* {{template declaration from hidden source: template <class element_type> class StructuredBuffer}}
+// expected-note@*:* {{template declaration from hidden source: template <typename element_type> class StructuredBuffer {}}}
 StructuredBuffer<> BufferErr2;
 
 [numthreads(1,1,1)]

>From 64e565aa51e3853f719c5de0607d8742bd3283c3 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Thu, 17 Oct 2024 11:03:52 -0700
Subject: [PATCH 12/16] add default nullptr, remove comments

---
 clang/lib/Sema/HLSLExternalSemaSource.cpp | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index b2d5413f7971a9..3fa764808bcefc 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -313,7 +313,7 @@ struct TemplateParameterListBuilder {
   TemplateParameterListBuilder(Sema &S, BuiltinTypeDeclBuilder &RB)
       : Builder(RB), S(S) {}
 
-  ~TemplateParameterListBuilder() { finalizeTemplateArgs(nullptr); }
+  ~TemplateParameterListBuilder() { finalizeTemplateArgs(); }
 
   TemplateParameterListBuilder &
   addTypeParameter(StringRef Name, QualType DefaultValue = QualType()) {
@@ -399,7 +399,7 @@ struct TemplateParameterListBuilder {
     return CSE;
   }
 
-  BuiltinTypeDeclBuilder &finalizeTemplateArgs(ConceptDecl *CD) {
+  BuiltinTypeDeclBuilder &finalizeTemplateArgs(ConceptDecl *CD = nullptr) {
     if (Params.empty())
       return Builder;
     ConceptSpecializationExpr *CSE =
@@ -636,13 +636,8 @@ ConceptDecl *getTypedBufferConceptDecl(Sema &S) {
 
   // Create a ConceptDecl
   clang::ConceptDecl *conceptDecl = clang::ConceptDecl::Create(
-      context,
-      context.getTranslationUnitDecl(), // DeclContext
-      DeclLoc,                          // Source location of start of concept
-      DeclName,                         // Source location of end of concept
-      ConceptParams,                    // Template type parameter
-      ConstraintExpr                    // Expression defining the concept
-  );
+      context, context.getTranslationUnitDecl(), DeclLoc, DeclName,
+      ConceptParams, ConstraintExpr);
 
   // Attach the template parameter list to the ConceptDecl
   conceptDecl->setTemplateParameters(ConceptParams);

>From 83cd7f9277b29ceac90c6be2f3196b6a5896c46f Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Thu, 17 Oct 2024 16:18:52 -0700
Subject: [PATCH 13/16] remove unused var, use vector to extend memory
 lifetime, may need to extend further

---
 clang/lib/Sema/HLSLExternalSemaSource.cpp | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 3fa764808bcefc..895db454c3cf46 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -368,13 +368,15 @@ struct TemplateParameterListBuilder {
 
     TemplateArgument ConceptTA = TemplateArgument(ConceptTType);
 
-    ArrayRef<TemplateArgument> ConceptConvertedArgs = {ConceptTA};
+    std::vector<TemplateArgument> ConceptConvertedArgsVec = {ConceptTA};
+    ArrayRef<TemplateArgument> ConceptConvertedArgs = ConceptConvertedArgsVec;
 
     clang::QualType CSETType = context.getTypeDeclType(T);
 
     TemplateArgument CSETA = TemplateArgument(CSETType);
 
-    ArrayRef<TemplateArgument> CSEConvertedArgs = {CSETA};
+    std::vector<TemplateArgument> CSEConvertedArgsVec = {CSETA};
+    ArrayRef<TemplateArgument> CSEConvertedArgs = CSEConvertedArgsVec;
 
     ImplicitConceptSpecializationDecl *ImplicitCSEDecl =
         ImplicitConceptSpecializationDecl::Create(
@@ -426,9 +428,6 @@ struct TemplateParameterListBuilder {
     QualType T = Builder.Template->getInjectedClassNameSpecialization();
     T = S.Context.getInjectedClassNameType(Builder.Record, T);
 
-    ArrayRef<TemplateArgument> TempArgs =
-        Builder.Template->getInjectedTemplateArgs();
-
     return Builder;
   }
 };
@@ -626,7 +625,9 @@ ConceptDecl *getTypedBufferConceptDecl(Sema &S) {
   T->setReferenced();
 
   // Create and Attach Template Parameter List to ConceptDecl
-  llvm::ArrayRef<NamedDecl *> TemplateParams = {T};
+  std::vector<NamedDecl *> TemplateParamsVec = {T};
+  llvm::ArrayRef<NamedDecl *> TemplateParams(TemplateParamsVec);
+
   clang::TemplateParameterList *ConceptParams =
       clang::TemplateParameterList::Create(context, DeclLoc, DeclLoc,
                                            TemplateParams, DeclLoc, nullptr);

>From 12e72b462f2fa516ba19870950791092c86a3b1e Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 18 Oct 2024 00:33:43 -0700
Subject: [PATCH 14/16] address everything

---
 clang/lib/AST/DeclTemplate.cpp            |  6 +-
 clang/lib/Sema/HLSLExternalSemaSource.cpp | 67 ++++++++++++++---------
 2 files changed, 44 insertions(+), 29 deletions(-)

diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 515abb3f68b244..d2d8907b884ec8 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -1078,10 +1078,10 @@ ConceptDecl *ConceptDecl::Create(ASTContext &C, DeclContext *DC,
                                  TemplateParameterList *Params,
                                  Expr *ConstraintExpr) {
   bool Invalid = AdoptTemplateParameterList(Params, DC);
-  auto *CD = new (C, DC) ConceptDecl(DC, L, Name, Params, ConstraintExpr);
+  auto *TD = new (C, DC) ConceptDecl(DC, L, Name, Params, ConstraintExpr);
   if (Invalid)
-    CD->setInvalidDecl();
-  return CD;
+    TD->setInvalidDecl();
+  return TD;
 }
 
 ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 895db454c3cf46..5126657ab0c29d 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -336,22 +336,41 @@ struct TemplateParameterListBuilder {
     return *this;
   }
 
+  /*
+  The desired result AST after this function constructs the concept
+  specialization Expression is as follows:
+
+  |-ConceptSpecializationExpr 0xdd5d408 <col:42, col:75> 'bool' Concept
+  0xdd5d1c0 'is_valid_line_vector' | |-ImplicitConceptSpecializationDecl
+  0xdd5d350 <line:5:9> col:9 | | `-TemplateArgument type 'type-parameter-0-0' |
+  |   `-TemplateTypeParmType 0xdb90ba0 'type-parameter-0-0' dependent depth 0
+  index 0 | `-TemplateArgument <line:8:63> type
+  'element_type':'type-parameter-0-0' |   `-TemplateTypeParmType 0xdd5d2f0
+  'element_type' dependent depth 0 index 0 |     `-TemplateTypeParm 0xdd5d298
+  'element_type'
+  */
   ConceptSpecializationExpr *getConceptSpecializationExpr(Sema &S,
                                                           ConceptDecl *CD) {
-    ASTContext &context = S.getASTContext();
-    SourceLocation loc = Builder.Record->getBeginLoc();
-    DeclarationNameInfo DNI(CD->getDeclName(), loc);
+    ASTContext &Context = S.getASTContext();
+    SourceLocation Loc = Builder.Record->getBeginLoc();
+    DeclarationNameInfo DNI(CD->getDeclName(), Loc);
     NestedNameSpecifierLoc NNSLoc;
     DeclContext *DC = Builder.Record->getDeclContext();
-    TemplateArgumentListInfo TALI(loc, loc);
+    TemplateArgumentListInfo TALI(Loc, Loc);
 
-    // assume that the concept decl has just one template parameter
+    // Assume that the concept decl has just one template parameter
+    // This parameter should have been added when CD was constructed
+    // in getTypedBufferConceptDecl
+    assert(CD->getTemplateParameters()->size() == 1 &&
+           "unexpected concept decl parameter count");
     TemplateTypeParmDecl *ConceptTTPD = dyn_cast<TemplateTypeParmDecl>(
         CD->getTemplateParameters()->getParam(0));
 
+    // this fake TemplateTypeParmDecl is used to construct a template argument
+    // that will be used to construct the ImplicitConceptSpecializationDecl
     clang::TemplateTypeParmDecl *T = clang::TemplateTypeParmDecl::Create(
-        context,                          // AST context
-        context.getTranslationUnitDecl(), // DeclContext
+        Context,                          // AST context
+        Context.getTranslationUnitDecl(), // DeclContext
         SourceLocation(), SourceLocation(),
         /*depth=*/0,                // Depth in the template parameter list
         /*position=*/0,             // Position in the template parameter list
@@ -364,39 +383,38 @@ struct TemplateParameterListBuilder {
     T->setDeclContext(DC);
     T->setReferenced();
 
-    clang::QualType ConceptTType = context.getTypeDeclType(ConceptTTPD);
+    clang::QualType ConceptTType = Context.getTypeDeclType(ConceptTTPD);
 
+    // this is the 2nd template argument node in the AST above
     TemplateArgument ConceptTA = TemplateArgument(ConceptTType);
 
-    std::vector<TemplateArgument> ConceptConvertedArgsVec = {ConceptTA};
-    ArrayRef<TemplateArgument> ConceptConvertedArgs = ConceptConvertedArgsVec;
-
-    clang::QualType CSETType = context.getTypeDeclType(T);
+    clang::QualType CSETType = Context.getTypeDeclType(T);
 
+    // this is the 1st template argument node in the AST above
     TemplateArgument CSETA = TemplateArgument(CSETType);
 
-    std::vector<TemplateArgument> CSEConvertedArgsVec = {CSETA};
-    ArrayRef<TemplateArgument> CSEConvertedArgs = CSEConvertedArgsVec;
-
     ImplicitConceptSpecializationDecl *ImplicitCSEDecl =
         ImplicitConceptSpecializationDecl::Create(
-            context, Builder.Record->getDeclContext(), loc, CSEConvertedArgs);
+            Context, Builder.Record->getDeclContext(), Loc, {CSETA});
 
-    const ConstraintSatisfaction CS(CD, ConceptConvertedArgs);
+    // Constraint satisfaction is used to construct the
+    // ConceptSpecailizationExpr, and represents the 2nd Template Argument,
+    // located at the bottom of the sample AST above.
+    const ConstraintSatisfaction CS(CD, {ConceptTA});
     TemplateArgumentLoc TAL = S.getTrivialTemplateArgumentLoc(
         ConceptTA, QualType(), SourceLocation());
 
     TALI.addArgument(TAL);
     const ASTTemplateArgumentListInfo *ATALI =
-        ASTTemplateArgumentListInfo::Create(context, TALI);
+        ASTTemplateArgumentListInfo::Create(Context, TALI);
 
     // In the concept reference, ATALI is what adds the extra
     // TemplateArgument node underneath CSE
-    ConceptReference *CR = ConceptReference::Create(S.getASTContext(), NNSLoc,
-                                                    loc, DNI, CD, CD, ATALI);
+    ConceptReference *CR =
+        ConceptReference::Create(Context, NNSLoc, Loc, DNI, CD, CD, ATALI);
 
     ConceptSpecializationExpr *CSE =
-        ConceptSpecializationExpr::Create(context, CR, ImplicitCSEDecl, &CS);
+        ConceptSpecializationExpr::Create(Context, CR, ImplicitCSEDecl, &CS);
 
     return CSE;
   }
@@ -625,12 +643,9 @@ ConceptDecl *getTypedBufferConceptDecl(Sema &S) {
   T->setReferenced();
 
   // Create and Attach Template Parameter List to ConceptDecl
-  std::vector<NamedDecl *> TemplateParamsVec = {T};
-  llvm::ArrayRef<NamedDecl *> TemplateParams(TemplateParamsVec);
-
   clang::TemplateParameterList *ConceptParams =
-      clang::TemplateParameterList::Create(context, DeclLoc, DeclLoc,
-                                           TemplateParams, DeclLoc, nullptr);
+      clang::TemplateParameterList::Create(context, DeclLoc, DeclLoc, {T},
+                                           DeclLoc, nullptr);
 
   DeclarationName DeclName = DeclarationName(&IsValidLineVectorII);
   Expr *ConstraintExpr = getTypedBufferConstraintExpr(S, DeclLoc, T);

>From e4c87549a662586ccce667e52687e48514810010 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 18 Oct 2024 13:55:17 -0700
Subject: [PATCH 15/16] remove clang::, add c++ ast generation code, fix var
 names

---
 clang/lib/Sema/HLSLExternalSemaSource.cpp | 1457 +++++++++++----------
 1 file changed, 731 insertions(+), 726 deletions(-)

diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 5126657ab0c29d..addfe38cd64583 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -1,726 +1,731 @@
-//===--- HLSLExternalSemaSource.cpp - HLSL Sema Source --------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Sema/HLSLExternalSemaSource.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/Type.h"
-#include "clang/Basic/AttrKinds.h"
-#include "clang/Basic/HLSLRuntime.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/Sema.h"
-#include "clang/Sema/SemaHLSL.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Frontend/HLSL/HLSLResource.h"
-
-#include <functional>
-
-using namespace clang;
-using namespace llvm::hlsl;
-
-namespace {
-
-struct TemplateParameterListBuilder;
-
-struct BuiltinTypeDeclBuilder {
-  CXXRecordDecl *Record = nullptr;
-  ClassTemplateDecl *Template = nullptr;
-  ClassTemplateDecl *PrevTemplate = nullptr;
-  NamespaceDecl *HLSLNamespace = nullptr;
-  llvm::StringMap<FieldDecl *> Fields;
-
-  BuiltinTypeDeclBuilder(CXXRecordDecl *R) : Record(R) {
-    Record->startDefinition();
-    Template = Record->getDescribedClassTemplate();
-  }
-
-  BuiltinTypeDeclBuilder(Sema &S, NamespaceDecl *Namespace, StringRef Name)
-      : HLSLNamespace(Namespace) {
-    ASTContext &AST = S.getASTContext();
-    IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
-
-    LookupResult Result(S, &II, SourceLocation(), Sema::LookupTagName);
-    CXXRecordDecl *PrevDecl = nullptr;
-    if (S.LookupQualifiedName(Result, HLSLNamespace)) {
-      NamedDecl *Found = Result.getFoundDecl();
-      if (auto *TD = dyn_cast<ClassTemplateDecl>(Found)) {
-        PrevDecl = TD->getTemplatedDecl();
-        PrevTemplate = TD;
-      } else
-        PrevDecl = dyn_cast<CXXRecordDecl>(Found);
-      assert(PrevDecl && "Unexpected lookup result type.");
-    }
-
-    if (PrevDecl && PrevDecl->isCompleteDefinition()) {
-      Record = PrevDecl;
-      return;
-    }
-
-    Record = CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, HLSLNamespace,
-                                   SourceLocation(), SourceLocation(), &II,
-                                   PrevDecl, true);
-    Record->setImplicit(true);
-    Record->setLexicalDeclContext(HLSLNamespace);
-    Record->setHasExternalLexicalStorage();
-
-    // Don't let anyone derive from built-in types.
-    Record->addAttr(FinalAttr::CreateImplicit(AST, SourceRange(),
-                                              FinalAttr::Keyword_final));
-  }
-
-  ~BuiltinTypeDeclBuilder() {
-    if (HLSLNamespace && !Template && Record->getDeclContext() == HLSLNamespace)
-      HLSLNamespace->addDecl(Record);
-  }
-
-  BuiltinTypeDeclBuilder &
-  addMemberVariable(StringRef Name, QualType Type, llvm::ArrayRef<Attr *> Attrs,
-                    AccessSpecifier Access = AccessSpecifier::AS_private) {
-    if (Record->isCompleteDefinition())
-      return *this;
-    assert(Record->isBeingDefined() &&
-           "Definition must be started before adding members!");
-    ASTContext &AST = Record->getASTContext();
-
-    IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
-    TypeSourceInfo *MemTySource =
-        AST.getTrivialTypeSourceInfo(Type, SourceLocation());
-    auto *Field = FieldDecl::Create(
-        AST, Record, SourceLocation(), SourceLocation(), &II, Type, MemTySource,
-        nullptr, false, InClassInitStyle::ICIS_NoInit);
-    Field->setAccess(Access);
-    Field->setImplicit(true);
-    for (Attr *A : Attrs) {
-      if (A)
-        Field->addAttr(A);
-    }
-
-    Record->addDecl(Field);
-    Fields[Name] = Field;
-    return *this;
-  }
-
-  BuiltinTypeDeclBuilder &
-  addHandleMember(Sema &S, ResourceClass RC, ResourceKind RK, bool IsROV,
-                  bool RawBuffer,
-                  AccessSpecifier Access = AccessSpecifier::AS_private) {
-    if (Record->isCompleteDefinition())
-      return *this;
-
-    ASTContext &Ctx = S.getASTContext();
-    TypeSourceInfo *ElementTypeInfo = nullptr;
-
-    QualType ElemTy = Ctx.Char8Ty;
-    if (Template) {
-      if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
-              Template->getTemplateParameters()->getParam(0))) {
-        ElemTy = QualType(TTD->getTypeForDecl(), 0);
-      }
-    }
-    ElementTypeInfo = Ctx.getTrivialTypeSourceInfo(ElemTy, SourceLocation());
-
-    // add handle member with resource type attributes
-    QualType AttributedResTy = QualType();
-    SmallVector<const Attr *> Attrs = {
-        HLSLResourceClassAttr::CreateImplicit(Ctx, RC),
-        IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr,
-        RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr,
-        ElementTypeInfo
-            ? HLSLContainedTypeAttr::CreateImplicit(Ctx, ElementTypeInfo)
-            : nullptr};
-    Attr *ResourceAttr = HLSLResourceAttr::CreateImplicit(Ctx, RK);
-    if (CreateHLSLAttributedResourceType(S, Ctx.HLSLResourceTy, Attrs,
-                                         AttributedResTy))
-      addMemberVariable("h", AttributedResTy, {ResourceAttr}, Access);
-    return *this;
-  }
-
-  static DeclRefExpr *lookupBuiltinFunction(ASTContext &AST, Sema &S,
-                                            StringRef Name) {
-    IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
-    DeclarationNameInfo NameInfo =
-        DeclarationNameInfo(DeclarationName(&II), SourceLocation());
-    LookupResult R(S, NameInfo, Sema::LookupOrdinaryName);
-    // AllowBuiltinCreation is false but LookupDirect will create
-    // the builtin when searching the global scope anyways...
-    S.LookupName(R, S.getCurScope());
-    // FIXME: If the builtin function was user-declared in global scope,
-    // this assert *will* fail. Should this call LookupBuiltin instead?
-    assert(R.isSingleResult() &&
-           "Since this is a builtin it should always resolve!");
-    auto *VD = cast<ValueDecl>(R.getFoundDecl());
-    QualType Ty = VD->getType();
-    return DeclRefExpr::Create(AST, NestedNameSpecifierLoc(), SourceLocation(),
-                               VD, false, NameInfo, Ty, VK_PRValue);
-  }
-
-  static Expr *emitResourceClassExpr(ASTContext &AST, ResourceClass RC) {
-    return IntegerLiteral::Create(
-        AST,
-        llvm::APInt(AST.getIntWidth(AST.UnsignedCharTy),
-                    static_cast<uint8_t>(RC)),
-        AST.UnsignedCharTy, SourceLocation());
-  }
-
-  BuiltinTypeDeclBuilder &addDefaultHandleConstructor(Sema &S,
-                                                      ResourceClass RC) {
-    if (Record->isCompleteDefinition())
-      return *this;
-    ASTContext &AST = Record->getASTContext();
-
-    QualType ConstructorType =
-        AST.getFunctionType(AST.VoidTy, {}, FunctionProtoType::ExtProtoInfo());
-
-    CanQualType CanTy = Record->getTypeForDecl()->getCanonicalTypeUnqualified();
-    DeclarationName Name = AST.DeclarationNames.getCXXConstructorName(CanTy);
-    CXXConstructorDecl *Constructor = CXXConstructorDecl::Create(
-        AST, Record, SourceLocation(),
-        DeclarationNameInfo(Name, SourceLocation()), ConstructorType,
-        AST.getTrivialTypeSourceInfo(ConstructorType, SourceLocation()),
-        ExplicitSpecifier(), false, true, false,
-        ConstexprSpecKind::Unspecified);
-
-    Constructor->setBody(CompoundStmt::Create(
-        AST, {}, FPOptionsOverride(), SourceLocation(), SourceLocation()));
-    Constructor->setAccess(AccessSpecifier::AS_public);
-    Record->addDecl(Constructor);
-    return *this;
-  }
-
-  BuiltinTypeDeclBuilder &addArraySubscriptOperators() {
-    if (Record->isCompleteDefinition())
-      return *this;
-    addArraySubscriptOperator(true);
-    addArraySubscriptOperator(false);
-    return *this;
-  }
-
-  BuiltinTypeDeclBuilder &addArraySubscriptOperator(bool IsConst) {
-    if (Record->isCompleteDefinition())
-      return *this;
-
-    ASTContext &AST = Record->getASTContext();
-    QualType ElemTy = AST.Char8Ty;
-    if (Template) {
-      if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
-              Template->getTemplateParameters()->getParam(0))) {
-        ElemTy = QualType(TTD->getTypeForDecl(), 0);
-      }
-    }
-    QualType ReturnTy = ElemTy;
-
-    FunctionProtoType::ExtProtoInfo ExtInfo;
-
-    // Subscript operators return references to elements, const makes the
-    // reference and method const so that the underlying data is not mutable.
-    ReturnTy = AST.getLValueReferenceType(ReturnTy);
-    if (IsConst) {
-      ExtInfo.TypeQuals.addConst();
-      ReturnTy.addConst();
-    }
-
-    QualType MethodTy =
-        AST.getFunctionType(ReturnTy, {AST.UnsignedIntTy}, ExtInfo);
-    auto *TSInfo = AST.getTrivialTypeSourceInfo(MethodTy, SourceLocation());
-    auto *MethodDecl = CXXMethodDecl::Create(
-        AST, Record, SourceLocation(),
-        DeclarationNameInfo(
-            AST.DeclarationNames.getCXXOperatorName(OO_Subscript),
-            SourceLocation()),
-        MethodTy, TSInfo, SC_None, false, false, ConstexprSpecKind::Unspecified,
-        SourceLocation());
-
-    IdentifierInfo &II = AST.Idents.get("Idx", tok::TokenKind::identifier);
-    auto *IdxParam = ParmVarDecl::Create(
-        AST, MethodDecl->getDeclContext(), SourceLocation(), SourceLocation(),
-        &II, AST.UnsignedIntTy,
-        AST.getTrivialTypeSourceInfo(AST.UnsignedIntTy, SourceLocation()),
-        SC_None, nullptr);
-    MethodDecl->setParams({IdxParam});
-
-    // Also add the parameter to the function prototype.
-    auto FnProtoLoc = TSInfo->getTypeLoc().getAs<FunctionProtoTypeLoc>();
-    FnProtoLoc.setParam(0, IdxParam);
-
-    // FIXME: Placeholder to make sure we return the correct type - create
-    // field of element_type and return reference to it. This field will go
-    // away once indexing into resources is properly implemented in
-    // llvm/llvm-project#95956.
-    if (Fields.count("e") == 0) {
-      addMemberVariable("e", ElemTy, {});
-    }
-    FieldDecl *ElemFieldDecl = Fields["e"];
-
-    auto *This =
-        CXXThisExpr::Create(AST, SourceLocation(),
-                            MethodDecl->getFunctionObjectParameterType(), true);
-    Expr *ElemField = MemberExpr::CreateImplicit(
-        AST, This, false, ElemFieldDecl, ElemFieldDecl->getType(), VK_LValue,
-        OK_Ordinary);
-    auto *Return =
-        ReturnStmt::Create(AST, SourceLocation(), ElemField, nullptr);
-
-    MethodDecl->setBody(CompoundStmt::Create(AST, {Return}, FPOptionsOverride(),
-                                             SourceLocation(),
-                                             SourceLocation()));
-    MethodDecl->setLexicalDeclContext(Record);
-    MethodDecl->setAccess(AccessSpecifier::AS_public);
-    MethodDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
-        AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
-    Record->addDecl(MethodDecl);
-
-    return *this;
-  }
-
-  BuiltinTypeDeclBuilder &startDefinition() {
-    if (Record->isCompleteDefinition())
-      return *this;
-    Record->startDefinition();
-    return *this;
-  }
-
-  BuiltinTypeDeclBuilder &completeDefinition() {
-    if (Record->isCompleteDefinition())
-      return *this;
-    assert(Record->isBeingDefined() &&
-           "Definition must be started before completing it.");
-
-    Record->completeDefinition();
-    return *this;
-  }
-
-  TemplateParameterListBuilder addTemplateArgumentList(Sema &S);
-  BuiltinTypeDeclBuilder &
-  addSimpleTemplateParams(Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD);
-  BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S);
-};
-
-struct TemplateParameterListBuilder {
-  BuiltinTypeDeclBuilder &Builder;
-  Sema &S;
-  llvm::SmallVector<NamedDecl *> Params;
-
-  TemplateParameterListBuilder(Sema &S, BuiltinTypeDeclBuilder &RB)
-      : Builder(RB), S(S) {}
-
-  ~TemplateParameterListBuilder() { finalizeTemplateArgs(); }
-
-  TemplateParameterListBuilder &
-  addTypeParameter(StringRef Name, QualType DefaultValue = QualType()) {
-    if (Builder.Record->isCompleteDefinition())
-      return *this;
-    unsigned Position = static_cast<unsigned>(Params.size());
-    auto *Decl = TemplateTypeParmDecl::Create(
-        S.Context, Builder.Record->getDeclContext(), SourceLocation(),
-        SourceLocation(), /* TemplateDepth */ 0, Position,
-        &S.Context.Idents.get(Name, tok::TokenKind::identifier),
-        /* Typename */ true,
-        /* ParameterPack */ false,
-        /* HasTypeConstraint*/ false);
-    if (!DefaultValue.isNull())
-      Decl->setDefaultArgument(
-          S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(),
-                                                     SourceLocation()));
-    Decl->setReferenced();
-    Params.emplace_back(Decl);
-    return *this;
-  }
-
-  /*
-  The desired result AST after this function constructs the concept
-  specialization Expression is as follows:
-
-  |-ConceptSpecializationExpr 0xdd5d408 <col:42, col:75> 'bool' Concept
-  0xdd5d1c0 'is_valid_line_vector' | |-ImplicitConceptSpecializationDecl
-  0xdd5d350 <line:5:9> col:9 | | `-TemplateArgument type 'type-parameter-0-0' |
-  |   `-TemplateTypeParmType 0xdb90ba0 'type-parameter-0-0' dependent depth 0
-  index 0 | `-TemplateArgument <line:8:63> type
-  'element_type':'type-parameter-0-0' |   `-TemplateTypeParmType 0xdd5d2f0
-  'element_type' dependent depth 0 index 0 |     `-TemplateTypeParm 0xdd5d298
-  'element_type'
-  */
-  ConceptSpecializationExpr *getConceptSpecializationExpr(Sema &S,
-                                                          ConceptDecl *CD) {
-    ASTContext &Context = S.getASTContext();
-    SourceLocation Loc = Builder.Record->getBeginLoc();
-    DeclarationNameInfo DNI(CD->getDeclName(), Loc);
-    NestedNameSpecifierLoc NNSLoc;
-    DeclContext *DC = Builder.Record->getDeclContext();
-    TemplateArgumentListInfo TALI(Loc, Loc);
-
-    // Assume that the concept decl has just one template parameter
-    // This parameter should have been added when CD was constructed
-    // in getTypedBufferConceptDecl
-    assert(CD->getTemplateParameters()->size() == 1 &&
-           "unexpected concept decl parameter count");
-    TemplateTypeParmDecl *ConceptTTPD = dyn_cast<TemplateTypeParmDecl>(
-        CD->getTemplateParameters()->getParam(0));
-
-    // this fake TemplateTypeParmDecl is used to construct a template argument
-    // that will be used to construct the ImplicitConceptSpecializationDecl
-    clang::TemplateTypeParmDecl *T = clang::TemplateTypeParmDecl::Create(
-        Context,                          // AST context
-        Context.getTranslationUnitDecl(), // DeclContext
-        SourceLocation(), SourceLocation(),
-        /*depth=*/0,                // Depth in the template parameter list
-        /*position=*/0,             // Position in the template parameter list
-        /*id=*/nullptr,             // Identifier for 'T'
-        /*Typename=*/true,          // Indicates this is a 'typename' or 'class'
-        /*ParameterPack=*/false,    // Not a parameter pack
-        /*HasTypeConstraint=*/false // Not a parameter pack
-    );
-
-    T->setDeclContext(DC);
-    T->setReferenced();
-
-    clang::QualType ConceptTType = Context.getTypeDeclType(ConceptTTPD);
-
-    // this is the 2nd template argument node in the AST above
-    TemplateArgument ConceptTA = TemplateArgument(ConceptTType);
-
-    clang::QualType CSETType = Context.getTypeDeclType(T);
-
-    // this is the 1st template argument node in the AST above
-    TemplateArgument CSETA = TemplateArgument(CSETType);
-
-    ImplicitConceptSpecializationDecl *ImplicitCSEDecl =
-        ImplicitConceptSpecializationDecl::Create(
-            Context, Builder.Record->getDeclContext(), Loc, {CSETA});
-
-    // Constraint satisfaction is used to construct the
-    // ConceptSpecailizationExpr, and represents the 2nd Template Argument,
-    // located at the bottom of the sample AST above.
-    const ConstraintSatisfaction CS(CD, {ConceptTA});
-    TemplateArgumentLoc TAL = S.getTrivialTemplateArgumentLoc(
-        ConceptTA, QualType(), SourceLocation());
-
-    TALI.addArgument(TAL);
-    const ASTTemplateArgumentListInfo *ATALI =
-        ASTTemplateArgumentListInfo::Create(Context, TALI);
-
-    // In the concept reference, ATALI is what adds the extra
-    // TemplateArgument node underneath CSE
-    ConceptReference *CR =
-        ConceptReference::Create(Context, NNSLoc, Loc, DNI, CD, CD, ATALI);
-
-    ConceptSpecializationExpr *CSE =
-        ConceptSpecializationExpr::Create(Context, CR, ImplicitCSEDecl, &CS);
-
-    return CSE;
-  }
-
-  BuiltinTypeDeclBuilder &finalizeTemplateArgs(ConceptDecl *CD = nullptr) {
-    if (Params.empty())
-      return Builder;
-    ConceptSpecializationExpr *CSE =
-        CD ? getConceptSpecializationExpr(S, CD) : nullptr;
-
-    auto *ParamList = TemplateParameterList::Create(S.Context, SourceLocation(),
-                                                    SourceLocation(), Params,
-                                                    SourceLocation(), CSE);
-    Builder.Template = ClassTemplateDecl::Create(
-        S.Context, Builder.Record->getDeclContext(), SourceLocation(),
-        DeclarationName(Builder.Record->getIdentifier()), ParamList,
-        Builder.Record);
-
-    Builder.Record->setDescribedClassTemplate(Builder.Template);
-    Builder.Template->setImplicit(true);
-    Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());
-
-    // NOTE: setPreviousDecl before addDecl so new decl replace old decl when
-    // make visible.
-    Builder.Template->setPreviousDecl(Builder.PrevTemplate);
-    Builder.Record->getDeclContext()->addDecl(Builder.Template);
-    Params.clear();
-
-    QualType T = Builder.Template->getInjectedClassNameSpecialization();
-    T = S.Context.getInjectedClassNameType(Builder.Record, T);
-
-    return Builder;
-  }
-};
-} // namespace
-
-TemplateParameterListBuilder
-BuiltinTypeDeclBuilder::addTemplateArgumentList(Sema &S) {
-  return TemplateParameterListBuilder(S, *this);
-}
-
-BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addSimpleTemplateParams(
-    Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD = nullptr) {
-  TemplateParameterListBuilder Builder = this->addTemplateArgumentList(S);
-  for (StringRef Name : Names)
-    Builder.addTypeParameter(Name);
-
-  return Builder.finalizeTemplateArgs(CD);
-}
-
-HLSLExternalSemaSource::~HLSLExternalSemaSource() {}
-
-void HLSLExternalSemaSource::InitializeSema(Sema &S) {
-  SemaPtr = &S;
-  ASTContext &AST = SemaPtr->getASTContext();
-  // If the translation unit has external storage force external decls to load.
-  if (AST.getTranslationUnitDecl()->hasExternalLexicalStorage())
-    (void)AST.getTranslationUnitDecl()->decls_begin();
-
-  IdentifierInfo &HLSL = AST.Idents.get("hlsl", tok::TokenKind::identifier);
-  LookupResult Result(S, &HLSL, SourceLocation(), Sema::LookupNamespaceName);
-  NamespaceDecl *PrevDecl = nullptr;
-  if (S.LookupQualifiedName(Result, AST.getTranslationUnitDecl()))
-    PrevDecl = Result.getAsSingle<NamespaceDecl>();
-  HLSLNamespace = NamespaceDecl::Create(
-      AST, AST.getTranslationUnitDecl(), /*Inline=*/false, SourceLocation(),
-      SourceLocation(), &HLSL, PrevDecl, /*Nested=*/false);
-  HLSLNamespace->setImplicit(true);
-  HLSLNamespace->setHasExternalLexicalStorage();
-  AST.getTranslationUnitDecl()->addDecl(HLSLNamespace);
-
-  // Force external decls in the HLSL namespace to load from the PCH.
-  (void)HLSLNamespace->getCanonicalDecl()->decls_begin();
-  defineTrivialHLSLTypes();
-  defineHLSLTypesWithForwardDeclarations();
-
-  // This adds a `using namespace hlsl` directive. In DXC, we don't put HLSL's
-  // built in types inside a namespace, but we are planning to change that in
-  // the near future. In order to be source compatible older versions of HLSL
-  // will need to implicitly use the hlsl namespace. For now in clang everything
-  // will get added to the namespace, and we can remove the using directive for
-  // future language versions to match HLSL's evolution.
-  auto *UsingDecl = UsingDirectiveDecl::Create(
-      AST, AST.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
-      NestedNameSpecifierLoc(), SourceLocation(), HLSLNamespace,
-      AST.getTranslationUnitDecl());
-
-  AST.getTranslationUnitDecl()->addDecl(UsingDecl);
-}
-
-void HLSLExternalSemaSource::defineHLSLVectorAlias() {
-  ASTContext &AST = SemaPtr->getASTContext();
-
-  llvm::SmallVector<NamedDecl *> TemplateParams;
-
-  auto *TypeParam = TemplateTypeParmDecl::Create(
-      AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 0,
-      &AST.Idents.get("element", tok::TokenKind::identifier), false, false);
-  TypeParam->setDefaultArgument(
-      AST, SemaPtr->getTrivialTemplateArgumentLoc(
-               TemplateArgument(AST.FloatTy), QualType(), SourceLocation()));
-
-  TemplateParams.emplace_back(TypeParam);
-
-  auto *SizeParam = NonTypeTemplateParmDecl::Create(
-      AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 1,
-      &AST.Idents.get("element_count", tok::TokenKind::identifier), AST.IntTy,
-      false, AST.getTrivialTypeSourceInfo(AST.IntTy));
-  llvm::APInt Val(AST.getIntWidth(AST.IntTy), 4);
-  TemplateArgument Default(AST, llvm::APSInt(std::move(Val)), AST.IntTy,
-                           /*IsDefaulted=*/true);
-  SizeParam->setDefaultArgument(
-      AST, SemaPtr->getTrivialTemplateArgumentLoc(Default, AST.IntTy,
-                                                  SourceLocation(), SizeParam));
-  TemplateParams.emplace_back(SizeParam);
-
-  auto *ParamList =
-      TemplateParameterList::Create(AST, SourceLocation(), SourceLocation(),
-                                    TemplateParams, SourceLocation(), nullptr);
-
-  IdentifierInfo &II = AST.Idents.get("vector", tok::TokenKind::identifier);
-
-  QualType AliasType = AST.getDependentSizedExtVectorType(
-      AST.getTemplateTypeParmType(0, 0, false, TypeParam),
-      DeclRefExpr::Create(
-          AST, NestedNameSpecifierLoc(), SourceLocation(), SizeParam, false,
-          DeclarationNameInfo(SizeParam->getDeclName(), SourceLocation()),
-          AST.IntTy, VK_LValue),
-      SourceLocation());
-
-  auto *Record = TypeAliasDecl::Create(AST, HLSLNamespace, SourceLocation(),
-                                       SourceLocation(), &II,
-                                       AST.getTrivialTypeSourceInfo(AliasType));
-  Record->setImplicit(true);
-
-  auto *Template =
-      TypeAliasTemplateDecl::Create(AST, HLSLNamespace, SourceLocation(),
-                                    Record->getIdentifier(), ParamList, Record);
-
-  Record->setDescribedAliasTemplate(Template);
-  Template->setImplicit(true);
-  Template->setLexicalDeclContext(Record->getDeclContext());
-  HLSLNamespace->addDecl(Template);
-}
-
-void HLSLExternalSemaSource::defineTrivialHLSLTypes() {
-  defineHLSLVectorAlias();
-}
-
-/// Set up common members and attributes for buffer types
-static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
-                                              ResourceClass RC, ResourceKind RK,
-                                              bool IsROV, bool RawBuffer) {
-  return BuiltinTypeDeclBuilder(Decl)
-      .addHandleMember(S, RC, RK, IsROV, RawBuffer)
-      .addDefaultHandleConstructor(S, RC);
-}
-
-BinaryOperator *getSizeOfLEQ16Expr(clang::ASTContext &context,
-                                   SourceLocation NameLoc,
-                                   TemplateTypeParmDecl *T) {
-  // Obtain the QualType for 'unsigned long'
-  clang::QualType unsignedLongType = context.UnsignedLongTy;
-
-  // Create a QualType that points to this TemplateTypeParmDecl
-  clang::QualType TType = context.getTypeDeclType(T);
-
-  // Create a TypeSourceInfo for the template type parameter 'T'
-  clang::TypeSourceInfo *TTypeSourceInfo =
-      context.getTrivialTypeSourceInfo(TType, NameLoc);
-
-  clang::UnaryExprOrTypeTraitExpr *sizeOfExpr = new (context)
-      clang::UnaryExprOrTypeTraitExpr(clang::UETT_SizeOf, TTypeSourceInfo,
-                                      unsignedLongType, NameLoc, NameLoc);
-
-  // Create an IntegerLiteral for the value '16' with size type
-  clang::QualType sizeType = context.getSizeType();
-  llvm::APInt sizeValue = llvm::APInt(context.getTypeSize(sizeType), 16);
-  clang::IntegerLiteral *sizeLiteral = new (context)
-      clang::IntegerLiteral(context, sizeValue, sizeType, NameLoc);
-
-  clang::QualType BoolTy = context.BoolTy;
-
-  clang::BinaryOperator *binaryOperator = clang::BinaryOperator::Create(
-      context, sizeOfExpr, // Left-hand side expression
-      sizeLiteral,         // Right-hand side expression
-      clang::BO_LE,        // Binary operator kind (<=)
-      BoolTy,              // Result type (bool)
-      clang::VK_LValue,    // Value kind
-      clang::OK_Ordinary,  // Object kind
-      NameLoc,             // Source location of operator
-      FPOptionsOverride());
-
-  return binaryOperator;
-}
-
-Expr *getTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
-                                   TemplateTypeParmDecl *T) {
-  clang::ASTContext &context = S.getASTContext();
-
-  // first get the "sizeof(T) <= 16" expression, as a binary operator
-  BinaryOperator *sizeOfLEQ16 = getSizeOfLEQ16Expr(context, NameLoc, T);
-  // TODO: add the '__builtin_hlsl_is_line_vector_layout_compatible' builtin
-  // and return a binary operator that evaluates the builtin on the given
-  // template type parameter 'T'
-  return sizeOfLEQ16;
-}
-
-ConceptDecl *getTypedBufferConceptDecl(Sema &S) {
-  DeclContext *DC = S.CurContext;
-  clang::ASTContext &context = S.getASTContext();
-  SourceLocation DeclLoc = SourceLocation();
-
-  IdentifierInfo &IsValidLineVectorII =
-      context.Idents.get("is_valid_line_vector");
-  IdentifierInfo &ElementTypeII = context.Idents.get("element_type");
-  clang::TemplateTypeParmDecl *T = clang::TemplateTypeParmDecl::Create(
-      context, context.getTranslationUnitDecl(), DeclLoc, DeclLoc,
-      /*depth=*/0,
-      /*position=*/0,
-      /*id=*/&ElementTypeII,
-      /*Typename=*/true,
-      /*ParameterPack=*/false);
-
-  T->setDeclContext(DC);
-  T->setReferenced();
-
-  // Create and Attach Template Parameter List to ConceptDecl
-  clang::TemplateParameterList *ConceptParams =
-      clang::TemplateParameterList::Create(context, DeclLoc, DeclLoc, {T},
-                                           DeclLoc, nullptr);
-
-  DeclarationName DeclName = DeclarationName(&IsValidLineVectorII);
-  Expr *ConstraintExpr = getTypedBufferConstraintExpr(S, DeclLoc, T);
-
-  // Create a ConceptDecl
-  clang::ConceptDecl *conceptDecl = clang::ConceptDecl::Create(
-      context, context.getTranslationUnitDecl(), DeclLoc, DeclName,
-      ConceptParams, ConstraintExpr);
-
-  // Attach the template parameter list to the ConceptDecl
-  conceptDecl->setTemplateParameters(ConceptParams);
-
-  // Add the concept declaration to the Translation Unit Decl
-  context.getTranslationUnitDecl()->addDecl(conceptDecl);
-
-  return conceptDecl;
-}
-
-void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
-  CXXRecordDecl *Decl;
-  ConceptDecl *CD = getTypedBufferConceptDecl(*SemaPtr);
-
-  Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer")
-             .addSimpleTemplateParams(*SemaPtr, {"element_type"}, CD)
-             .Record;
-
-  onCompletion(Decl, [this](CXXRecordDecl *Decl) {
-    setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
-                    ResourceKind::TypedBuffer,
-                    /*IsROV=*/false, /*RawBuffer=*/false)
-        .addArraySubscriptOperators()
-        .completeDefinition();
-  });
-
-  Decl =
-      BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedBuffer")
-          .addSimpleTemplateParams(*SemaPtr, {"element_type"})
-          .Record;
-  onCompletion(Decl, [this](CXXRecordDecl *Decl) {
-    setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
-                    ResourceKind::TypedBuffer, /*IsROV=*/true,
-                    /*RawBuffer=*/false)
-        .addArraySubscriptOperators()
-        .completeDefinition();
-  });
-
-  Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "StructuredBuffer")
-             .addSimpleTemplateParams(*SemaPtr, {"element_type"})
-             .Record;
-  onCompletion(Decl, [this](CXXRecordDecl *Decl) {
-    setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
-                    ResourceKind::TypedBuffer, /*IsROV=*/false,
-                    /*RawBuffer=*/true)
-        .addArraySubscriptOperators()
-        .completeDefinition();
-  });
-}
-
-void HLSLExternalSemaSource::onCompletion(CXXRecordDecl *Record,
-                                          CompletionFunction Fn) {
-  Completions.insert(std::make_pair(Record->getCanonicalDecl(), Fn));
-}
-
-void HLSLExternalSemaSource::CompleteType(TagDecl *Tag) {
-  if (!isa<CXXRecordDecl>(Tag))
-    return;
-  auto Record = cast<CXXRecordDecl>(Tag);
-
-  // If this is a specialization, we need to get the underlying templated
-  // declaration and complete that.
-  if (auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(Record))
-    Record = TDecl->getSpecializedTemplate()->getTemplatedDecl();
-  Record = Record->getCanonicalDecl();
-  auto It = Completions.find(Record);
-  if (It == Completions.end())
-    return;
-  It->second(Record);
-}
+//===--- HLSLExternalSemaSource.cpp - HLSL Sema Source --------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/HLSLExternalSemaSource.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/AttrKinds.h"
+#include "clang/Basic/HLSLRuntime.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaHLSL.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Frontend/HLSL/HLSLResource.h"
+
+#include <functional>
+
+using namespace clang;
+using namespace llvm::hlsl;
+
+namespace {
+
+struct TemplateParameterListBuilder;
+
+struct BuiltinTypeDeclBuilder {
+  CXXRecordDecl *Record = nullptr;
+  ClassTemplateDecl *Template = nullptr;
+  ClassTemplateDecl *PrevTemplate = nullptr;
+  NamespaceDecl *HLSLNamespace = nullptr;
+  llvm::StringMap<FieldDecl *> Fields;
+
+  BuiltinTypeDeclBuilder(CXXRecordDecl *R) : Record(R) {
+    Record->startDefinition();
+    Template = Record->getDescribedClassTemplate();
+  }
+
+  BuiltinTypeDeclBuilder(Sema &S, NamespaceDecl *Namespace, StringRef Name)
+      : HLSLNamespace(Namespace) {
+    ASTContext &AST = S.getASTContext();
+    IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
+
+    LookupResult Result(S, &II, SourceLocation(), Sema::LookupTagName);
+    CXXRecordDecl *PrevDecl = nullptr;
+    if (S.LookupQualifiedName(Result, HLSLNamespace)) {
+      NamedDecl *Found = Result.getFoundDecl();
+      if (auto *TD = dyn_cast<ClassTemplateDecl>(Found)) {
+        PrevDecl = TD->getTemplatedDecl();
+        PrevTemplate = TD;
+      } else
+        PrevDecl = dyn_cast<CXXRecordDecl>(Found);
+      assert(PrevDecl && "Unexpected lookup result type.");
+    }
+
+    if (PrevDecl && PrevDecl->isCompleteDefinition()) {
+      Record = PrevDecl;
+      return;
+    }
+
+    Record = CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, HLSLNamespace,
+                                   SourceLocation(), SourceLocation(), &II,
+                                   PrevDecl, true);
+    Record->setImplicit(true);
+    Record->setLexicalDeclContext(HLSLNamespace);
+    Record->setHasExternalLexicalStorage();
+
+    // Don't let anyone derive from built-in types.
+    Record->addAttr(FinalAttr::CreateImplicit(AST, SourceRange(),
+                                              FinalAttr::Keyword_final));
+  }
+
+  ~BuiltinTypeDeclBuilder() {
+    if (HLSLNamespace && !Template && Record->getDeclContext() == HLSLNamespace)
+      HLSLNamespace->addDecl(Record);
+  }
+
+  BuiltinTypeDeclBuilder &
+  addMemberVariable(StringRef Name, QualType Type, llvm::ArrayRef<Attr *> Attrs,
+                    AccessSpecifier Access = AccessSpecifier::AS_private) {
+    if (Record->isCompleteDefinition())
+      return *this;
+    assert(Record->isBeingDefined() &&
+           "Definition must be started before adding members!");
+    ASTContext &AST = Record->getASTContext();
+
+    IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
+    TypeSourceInfo *MemTySource =
+        AST.getTrivialTypeSourceInfo(Type, SourceLocation());
+    auto *Field = FieldDecl::Create(
+        AST, Record, SourceLocation(), SourceLocation(), &II, Type, MemTySource,
+        nullptr, false, InClassInitStyle::ICIS_NoInit);
+    Field->setAccess(Access);
+    Field->setImplicit(true);
+    for (Attr *A : Attrs) {
+      if (A)
+        Field->addAttr(A);
+    }
+
+    Record->addDecl(Field);
+    Fields[Name] = Field;
+    return *this;
+  }
+
+  BuiltinTypeDeclBuilder &
+  addHandleMember(Sema &S, ResourceClass RC, ResourceKind RK, bool IsROV,
+                  bool RawBuffer,
+                  AccessSpecifier Access = AccessSpecifier::AS_private) {
+    if (Record->isCompleteDefinition())
+      return *this;
+
+    ASTContext &Ctx = S.getASTContext();
+    TypeSourceInfo *ElementTypeInfo = nullptr;
+
+    QualType ElemTy = Ctx.Char8Ty;
+    if (Template) {
+      if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
+              Template->getTemplateParameters()->getParam(0))) {
+        ElemTy = QualType(TTD->getTypeForDecl(), 0);
+      }
+    }
+    ElementTypeInfo = Ctx.getTrivialTypeSourceInfo(ElemTy, SourceLocation());
+
+    // add handle member with resource type attributes
+    QualType AttributedResTy = QualType();
+    SmallVector<const Attr *> Attrs = {
+        HLSLResourceClassAttr::CreateImplicit(Ctx, RC),
+        IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr,
+        RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr,
+        ElementTypeInfo
+            ? HLSLContainedTypeAttr::CreateImplicit(Ctx, ElementTypeInfo)
+            : nullptr};
+    Attr *ResourceAttr = HLSLResourceAttr::CreateImplicit(Ctx, RK);
+    if (CreateHLSLAttributedResourceType(S, Ctx.HLSLResourceTy, Attrs,
+                                         AttributedResTy))
+      addMemberVariable("h", AttributedResTy, {ResourceAttr}, Access);
+    return *this;
+  }
+
+  static DeclRefExpr *lookupBuiltinFunction(ASTContext &AST, Sema &S,
+                                            StringRef Name) {
+    IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
+    DeclarationNameInfo NameInfo =
+        DeclarationNameInfo(DeclarationName(&II), SourceLocation());
+    LookupResult R(S, NameInfo, Sema::LookupOrdinaryName);
+    // AllowBuiltinCreation is false but LookupDirect will create
+    // the builtin when searching the global scope anyways...
+    S.LookupName(R, S.getCurScope());
+    // FIXME: If the builtin function was user-declared in global scope,
+    // this assert *will* fail. Should this call LookupBuiltin instead?
+    assert(R.isSingleResult() &&
+           "Since this is a builtin it should always resolve!");
+    auto *VD = cast<ValueDecl>(R.getFoundDecl());
+    QualType Ty = VD->getType();
+    return DeclRefExpr::Create(AST, NestedNameSpecifierLoc(), SourceLocation(),
+                               VD, false, NameInfo, Ty, VK_PRValue);
+  }
+
+  static Expr *emitResourceClassExpr(ASTContext &AST, ResourceClass RC) {
+    return IntegerLiteral::Create(
+        AST,
+        llvm::APInt(AST.getIntWidth(AST.UnsignedCharTy),
+                    static_cast<uint8_t>(RC)),
+        AST.UnsignedCharTy, SourceLocation());
+  }
+
+  BuiltinTypeDeclBuilder &addDefaultHandleConstructor(Sema &S,
+                                                      ResourceClass RC) {
+    if (Record->isCompleteDefinition())
+      return *this;
+    ASTContext &AST = Record->getASTContext();
+
+    QualType ConstructorType =
+        AST.getFunctionType(AST.VoidTy, {}, FunctionProtoType::ExtProtoInfo());
+
+    CanQualType CanTy = Record->getTypeForDecl()->getCanonicalTypeUnqualified();
+    DeclarationName Name = AST.DeclarationNames.getCXXConstructorName(CanTy);
+    CXXConstructorDecl *Constructor = CXXConstructorDecl::Create(
+        AST, Record, SourceLocation(),
+        DeclarationNameInfo(Name, SourceLocation()), ConstructorType,
+        AST.getTrivialTypeSourceInfo(ConstructorType, SourceLocation()),
+        ExplicitSpecifier(), false, true, false,
+        ConstexprSpecKind::Unspecified);
+
+    Constructor->setBody(CompoundStmt::Create(
+        AST, {}, FPOptionsOverride(), SourceLocation(), SourceLocation()));
+    Constructor->setAccess(AccessSpecifier::AS_public);
+    Record->addDecl(Constructor);
+    return *this;
+  }
+
+  BuiltinTypeDeclBuilder &addArraySubscriptOperators() {
+    if (Record->isCompleteDefinition())
+      return *this;
+    addArraySubscriptOperator(true);
+    addArraySubscriptOperator(false);
+    return *this;
+  }
+
+  BuiltinTypeDeclBuilder &addArraySubscriptOperator(bool IsConst) {
+    if (Record->isCompleteDefinition())
+      return *this;
+
+    ASTContext &AST = Record->getASTContext();
+    QualType ElemTy = AST.Char8Ty;
+    if (Template) {
+      if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
+              Template->getTemplateParameters()->getParam(0))) {
+        ElemTy = QualType(TTD->getTypeForDecl(), 0);
+      }
+    }
+    QualType ReturnTy = ElemTy;
+
+    FunctionProtoType::ExtProtoInfo ExtInfo;
+
+    // Subscript operators return references to elements, const makes the
+    // reference and method const so that the underlying data is not mutable.
+    ReturnTy = AST.getLValueReferenceType(ReturnTy);
+    if (IsConst) {
+      ExtInfo.TypeQuals.addConst();
+      ReturnTy.addConst();
+    }
+
+    QualType MethodTy =
+        AST.getFunctionType(ReturnTy, {AST.UnsignedIntTy}, ExtInfo);
+    auto *TSInfo = AST.getTrivialTypeSourceInfo(MethodTy, SourceLocation());
+    auto *MethodDecl = CXXMethodDecl::Create(
+        AST, Record, SourceLocation(),
+        DeclarationNameInfo(
+            AST.DeclarationNames.getCXXOperatorName(OO_Subscript),
+            SourceLocation()),
+        MethodTy, TSInfo, SC_None, false, false, ConstexprSpecKind::Unspecified,
+        SourceLocation());
+
+    IdentifierInfo &II = AST.Idents.get("Idx", tok::TokenKind::identifier);
+    auto *IdxParam = ParmVarDecl::Create(
+        AST, MethodDecl->getDeclContext(), SourceLocation(), SourceLocation(),
+        &II, AST.UnsignedIntTy,
+        AST.getTrivialTypeSourceInfo(AST.UnsignedIntTy, SourceLocation()),
+        SC_None, nullptr);
+    MethodDecl->setParams({IdxParam});
+
+    // Also add the parameter to the function prototype.
+    auto FnProtoLoc = TSInfo->getTypeLoc().getAs<FunctionProtoTypeLoc>();
+    FnProtoLoc.setParam(0, IdxParam);
+
+    // FIXME: Placeholder to make sure we return the correct type - create
+    // field of element_type and return reference to it. This field will go
+    // away once indexing into resources is properly implemented in
+    // llvm/llvm-project#95956.
+    if (Fields.count("e") == 0) {
+      addMemberVariable("e", ElemTy, {});
+    }
+    FieldDecl *ElemFieldDecl = Fields["e"];
+
+    auto *This =
+        CXXThisExpr::Create(AST, SourceLocation(),
+                            MethodDecl->getFunctionObjectParameterType(), true);
+    Expr *ElemField = MemberExpr::CreateImplicit(
+        AST, This, false, ElemFieldDecl, ElemFieldDecl->getType(), VK_LValue,
+        OK_Ordinary);
+    auto *Return =
+        ReturnStmt::Create(AST, SourceLocation(), ElemField, nullptr);
+
+    MethodDecl->setBody(CompoundStmt::Create(AST, {Return}, FPOptionsOverride(),
+                                             SourceLocation(),
+                                             SourceLocation()));
+    MethodDecl->setLexicalDeclContext(Record);
+    MethodDecl->setAccess(AccessSpecifier::AS_public);
+    MethodDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
+        AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
+    Record->addDecl(MethodDecl);
+
+    return *this;
+  }
+
+  BuiltinTypeDeclBuilder &startDefinition() {
+    if (Record->isCompleteDefinition())
+      return *this;
+    Record->startDefinition();
+    return *this;
+  }
+
+  BuiltinTypeDeclBuilder &completeDefinition() {
+    if (Record->isCompleteDefinition())
+      return *this;
+    assert(Record->isBeingDefined() &&
+           "Definition must be started before completing it.");
+
+    Record->completeDefinition();
+    return *this;
+  }
+
+  TemplateParameterListBuilder addTemplateArgumentList(Sema &S);
+  BuiltinTypeDeclBuilder &
+  addSimpleTemplateParams(Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD);
+  BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S);
+};
+
+struct TemplateParameterListBuilder {
+  BuiltinTypeDeclBuilder &Builder;
+  Sema &S;
+  llvm::SmallVector<NamedDecl *> Params;
+
+  TemplateParameterListBuilder(Sema &S, BuiltinTypeDeclBuilder &RB)
+      : Builder(RB), S(S) {}
+
+  ~TemplateParameterListBuilder() { finalizeTemplateArgs(); }
+
+  TemplateParameterListBuilder &
+  addTypeParameter(StringRef Name, QualType DefaultValue = QualType()) {
+    if (Builder.Record->isCompleteDefinition())
+      return *this;
+    unsigned Position = static_cast<unsigned>(Params.size());
+    auto *Decl = TemplateTypeParmDecl::Create(
+        S.Context, Builder.Record->getDeclContext(), SourceLocation(),
+        SourceLocation(), /* TemplateDepth */ 0, Position,
+        &S.Context.Idents.get(Name, tok::TokenKind::identifier),
+        /* Typename */ true,
+        /* ParameterPack */ false,
+        /* HasTypeConstraint*/ false);
+    if (!DefaultValue.isNull())
+      Decl->setDefaultArgument(
+          S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(),
+                                                     SourceLocation()));
+    Decl->setReferenced();
+    Params.emplace_back(Decl);
+    return *this;
+  }
+
+  /*
+  The concept specialization expression (CSE) constructed below is constructed
+  so that it matches the CSE that is constructed when parsing
+  the below C++ code:
+
+  template<typename T>
+  concept is_valid_line_vector =sizeof(T) <= 16;
+
+  template<typename element_type> requires is_valid_line_vector<element_type>
+  struct RWBuffer {
+      element_type Val;
+  };
+
+  int fn() {
+      RWBuffer<int> Buf;
+  }
+
+  When dumping the AST and filtering for "RWBuffer", the resulting AST
+  structure is what we're trying to construct below, specifically the
+  CSE portion.
+  */
+  ConceptSpecializationExpr *getConceptSpecializationExpr(Sema &S,
+                                                          ConceptDecl *CD) {
+    ASTContext &Context = S.getASTContext();
+    SourceLocation Loc = Builder.Record->getBeginLoc();
+    DeclarationNameInfo DNI(CD->getDeclName(), Loc);
+    NestedNameSpecifierLoc NNSLoc;
+    DeclContext *DC = Builder.Record->getDeclContext();
+    TemplateArgumentListInfo TALI(Loc, Loc);
+
+    // Assume that the concept decl has just one template parameter
+    // This parameter should have been added when CD was constructed
+    // in getTypedBufferConceptDecl
+    assert(CD->getTemplateParameters()->size() == 1 &&
+           "unexpected concept decl parameter count");
+    TemplateTypeParmDecl *ConceptTTPD = dyn_cast<TemplateTypeParmDecl>(
+        CD->getTemplateParameters()->getParam(0));
+
+    // this fake TemplateTypeParmDecl is used to construct a template argument
+    // that will be used to construct the ImplicitConceptSpecializationDecl
+    TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create(
+        Context,                          // AST context
+        Context.getTranslationUnitDecl(), // DeclContext
+        SourceLocation(), SourceLocation(),
+        /*depth=*/0,                // Depth in the template parameter list
+        /*position=*/0,             // Position in the template parameter list
+        /*id=*/nullptr,             // Identifier for 'T'
+        /*Typename=*/true,          // Indicates this is a 'typename' or 'class'
+        /*ParameterPack=*/false,    // Not a parameter pack
+        /*HasTypeConstraint=*/false // Not a parameter pack
+    );
+
+    T->setDeclContext(DC);
+    T->setReferenced();
+
+    QualType ConceptTType = Context.getTypeDeclType(ConceptTTPD);
+
+    // this is the 2nd template argument node in the AST above
+    TemplateArgument ConceptTA = TemplateArgument(ConceptTType);
+
+    QualType CSETType = Context.getTypeDeclType(T);
+
+    // this is the 1st template argument node in the AST above
+    TemplateArgument CSETA = TemplateArgument(CSETType);
+
+    ImplicitConceptSpecializationDecl *ImplicitCSEDecl =
+        ImplicitConceptSpecializationDecl::Create(
+            Context, Builder.Record->getDeclContext(), Loc, {CSETA});
+
+    // Constraint satisfaction is used to construct the
+    // ConceptSpecailizationExpr, and represents the 2nd Template Argument,
+    // located at the bottom of the sample AST above.
+    const ConstraintSatisfaction CS(CD, {ConceptTA});
+    TemplateArgumentLoc TAL = S.getTrivialTemplateArgumentLoc(
+        ConceptTA, QualType(), SourceLocation());
+
+    TALI.addArgument(TAL);
+    const ASTTemplateArgumentListInfo *ATALI =
+        ASTTemplateArgumentListInfo::Create(Context, TALI);
+
+    // In the concept reference, ATALI is what adds the extra
+    // TemplateArgument node underneath CSE
+    ConceptReference *CR =
+        ConceptReference::Create(Context, NNSLoc, Loc, DNI, CD, CD, ATALI);
+
+    ConceptSpecializationExpr *CSE =
+        ConceptSpecializationExpr::Create(Context, CR, ImplicitCSEDecl, &CS);
+
+    return CSE;
+  }
+
+  BuiltinTypeDeclBuilder &finalizeTemplateArgs(ConceptDecl *CD = nullptr) {
+    if (Params.empty())
+      return Builder;
+    ConceptSpecializationExpr *CSE =
+        CD ? getConceptSpecializationExpr(S, CD) : nullptr;
+
+    auto *ParamList = TemplateParameterList::Create(S.Context, SourceLocation(),
+                                                    SourceLocation(), Params,
+                                                    SourceLocation(), CSE);
+    Builder.Template = ClassTemplateDecl::Create(
+        S.Context, Builder.Record->getDeclContext(), SourceLocation(),
+        DeclarationName(Builder.Record->getIdentifier()), ParamList,
+        Builder.Record);
+
+    Builder.Record->setDescribedClassTemplate(Builder.Template);
+    Builder.Template->setImplicit(true);
+    Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());
+
+    // NOTE: setPreviousDecl before addDecl so new decl replace old decl when
+    // make visible.
+    Builder.Template->setPreviousDecl(Builder.PrevTemplate);
+    Builder.Record->getDeclContext()->addDecl(Builder.Template);
+    Params.clear();
+
+    QualType T = Builder.Template->getInjectedClassNameSpecialization();
+    T = S.Context.getInjectedClassNameType(Builder.Record, T);
+
+    return Builder;
+  }
+};
+} // namespace
+
+TemplateParameterListBuilder
+BuiltinTypeDeclBuilder::addTemplateArgumentList(Sema &S) {
+  return TemplateParameterListBuilder(S, *this);
+}
+
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addSimpleTemplateParams(
+    Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD = nullptr) {
+  TemplateParameterListBuilder Builder = this->addTemplateArgumentList(S);
+  for (StringRef Name : Names)
+    Builder.addTypeParameter(Name);
+
+  return Builder.finalizeTemplateArgs(CD);
+}
+
+HLSLExternalSemaSource::~HLSLExternalSemaSource() {}
+
+void HLSLExternalSemaSource::InitializeSema(Sema &S) {
+  SemaPtr = &S;
+  ASTContext &AST = SemaPtr->getASTContext();
+  // If the translation unit has external storage force external decls to load.
+  if (AST.getTranslationUnitDecl()->hasExternalLexicalStorage())
+    (void)AST.getTranslationUnitDecl()->decls_begin();
+
+  IdentifierInfo &HLSL = AST.Idents.get("hlsl", tok::TokenKind::identifier);
+  LookupResult Result(S, &HLSL, SourceLocation(), Sema::LookupNamespaceName);
+  NamespaceDecl *PrevDecl = nullptr;
+  if (S.LookupQualifiedName(Result, AST.getTranslationUnitDecl()))
+    PrevDecl = Result.getAsSingle<NamespaceDecl>();
+  HLSLNamespace = NamespaceDecl::Create(
+      AST, AST.getTranslationUnitDecl(), /*Inline=*/false, SourceLocation(),
+      SourceLocation(), &HLSL, PrevDecl, /*Nested=*/false);
+  HLSLNamespace->setImplicit(true);
+  HLSLNamespace->setHasExternalLexicalStorage();
+  AST.getTranslationUnitDecl()->addDecl(HLSLNamespace);
+
+  // Force external decls in the HLSL namespace to load from the PCH.
+  (void)HLSLNamespace->getCanonicalDecl()->decls_begin();
+  defineTrivialHLSLTypes();
+  defineHLSLTypesWithForwardDeclarations();
+
+  // This adds a `using namespace hlsl` directive. In DXC, we don't put HLSL's
+  // built in types inside a namespace, but we are planning to change that in
+  // the near future. In order to be source compatible older versions of HLSL
+  // will need to implicitly use the hlsl namespace. For now in clang everything
+  // will get added to the namespace, and we can remove the using directive for
+  // future language versions to match HLSL's evolution.
+  auto *UsingDecl = UsingDirectiveDecl::Create(
+      AST, AST.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
+      NestedNameSpecifierLoc(), SourceLocation(), HLSLNamespace,
+      AST.getTranslationUnitDecl());
+
+  AST.getTranslationUnitDecl()->addDecl(UsingDecl);
+}
+
+void HLSLExternalSemaSource::defineHLSLVectorAlias() {
+  ASTContext &AST = SemaPtr->getASTContext();
+
+  llvm::SmallVector<NamedDecl *> TemplateParams;
+
+  auto *TypeParam = TemplateTypeParmDecl::Create(
+      AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 0,
+      &AST.Idents.get("element", tok::TokenKind::identifier), false, false);
+  TypeParam->setDefaultArgument(
+      AST, SemaPtr->getTrivialTemplateArgumentLoc(
+               TemplateArgument(AST.FloatTy), QualType(), SourceLocation()));
+
+  TemplateParams.emplace_back(TypeParam);
+
+  auto *SizeParam = NonTypeTemplateParmDecl::Create(
+      AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 1,
+      &AST.Idents.get("element_count", tok::TokenKind::identifier), AST.IntTy,
+      false, AST.getTrivialTypeSourceInfo(AST.IntTy));
+  llvm::APInt Val(AST.getIntWidth(AST.IntTy), 4);
+  TemplateArgument Default(AST, llvm::APSInt(std::move(Val)), AST.IntTy,
+                           /*IsDefaulted=*/true);
+  SizeParam->setDefaultArgument(
+      AST, SemaPtr->getTrivialTemplateArgumentLoc(Default, AST.IntTy,
+                                                  SourceLocation(), SizeParam));
+  TemplateParams.emplace_back(SizeParam);
+
+  auto *ParamList =
+      TemplateParameterList::Create(AST, SourceLocation(), SourceLocation(),
+                                    TemplateParams, SourceLocation(), nullptr);
+
+  IdentifierInfo &II = AST.Idents.get("vector", tok::TokenKind::identifier);
+
+  QualType AliasType = AST.getDependentSizedExtVectorType(
+      AST.getTemplateTypeParmType(0, 0, false, TypeParam),
+      DeclRefExpr::Create(
+          AST, NestedNameSpecifierLoc(), SourceLocation(), SizeParam, false,
+          DeclarationNameInfo(SizeParam->getDeclName(), SourceLocation()),
+          AST.IntTy, VK_LValue),
+      SourceLocation());
+
+  auto *Record = TypeAliasDecl::Create(AST, HLSLNamespace, SourceLocation(),
+                                       SourceLocation(), &II,
+                                       AST.getTrivialTypeSourceInfo(AliasType));
+  Record->setImplicit(true);
+
+  auto *Template =
+      TypeAliasTemplateDecl::Create(AST, HLSLNamespace, SourceLocation(),
+                                    Record->getIdentifier(), ParamList, Record);
+
+  Record->setDescribedAliasTemplate(Template);
+  Template->setImplicit(true);
+  Template->setLexicalDeclContext(Record->getDeclContext());
+  HLSLNamespace->addDecl(Template);
+}
+
+void HLSLExternalSemaSource::defineTrivialHLSLTypes() {
+  defineHLSLVectorAlias();
+}
+
+/// Set up common members and attributes for buffer types
+static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
+                                              ResourceClass RC, ResourceKind RK,
+                                              bool IsROV, bool RawBuffer) {
+  return BuiltinTypeDeclBuilder(Decl)
+      .addHandleMember(S, RC, RK, IsROV, RawBuffer)
+      .addDefaultHandleConstructor(S, RC);
+}
+
+BinaryOperator *getSizeOfLEQ16Expr(ASTContext &Context, SourceLocation NameLoc,
+                                   TemplateTypeParmDecl *T) {
+  // Obtain the QualType for 'unsigned long'
+  QualType unsignedLongType = Context.UnsignedLongTy;
+
+  // Create a QualType that points to this TemplateTypeParmDecl
+  QualType TType = Context.getTypeDeclType(T);
+
+  // Create a TypeSourceInfo for the template type parameter 'T'
+  TypeSourceInfo *TTypeSourceInfo =
+      Context.getTrivialTypeSourceInfo(TType, NameLoc);
+
+  UnaryExprOrTypeTraitExpr *SizeOfExpr = new (Context) UnaryExprOrTypeTraitExpr(
+      UETT_SizeOf, TTypeSourceInfo, unsignedLongType, NameLoc, NameLoc);
+
+  // Create an IntegerLiteral for the value '16' with size type
+  QualType SizeType = Context.getSizeType();
+  llvm::APInt SizeValue = llvm::APInt(Context.getTypeSize(SizeType), 16);
+  IntegerLiteral *sizeLiteral =
+      new (Context) IntegerLiteral(Context, SizeValue, SizeType, NameLoc);
+
+  QualType BoolTy = Context.BoolTy;
+
+  BinaryOperator *binaryOperator =
+      BinaryOperator::Create(Context, SizeOfExpr, // Left-hand side expression
+                             sizeLiteral,         // Right-hand side expression
+                             BO_LE,               // Binary operator kind (<=)
+                             BoolTy,              // Result type (bool)
+                             VK_LValue,           // Value kind
+                             OK_Ordinary,         // Object kind
+                             NameLoc,             // Source location of operator
+                             FPOptionsOverride());
+
+  return binaryOperator;
+}
+
+Expr *getTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
+                                   TemplateTypeParmDecl *T) {
+  ASTContext &Context = S.getASTContext();
+
+  // first get the "sizeof(T) <= 16" expression, as a binary operator
+  BinaryOperator *SizeOfLEQ16 = getSizeOfLEQ16Expr(Context, NameLoc, T);
+  // TODO: add the '__builtin_hlsl_is_line_vector_layout_compatible' builtin
+  // and return a binary operator that evaluates the builtin on the given
+  // template type parameter 'T'
+  return SizeOfLEQ16;
+}
+
+ConceptDecl *getTypedBufferConceptDecl(Sema &S) {
+  DeclContext *DC = S.CurContext;
+  ASTContext &Context = S.getASTContext();
+  SourceLocation DeclLoc = SourceLocation();
+
+  IdentifierInfo &IsValidLineVectorII =
+      Context.Idents.get("is_valid_line_vector");
+  IdentifierInfo &ElementTypeII = Context.Idents.get("element_type");
+  TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create(
+      Context, Context.getTranslationUnitDecl(), DeclLoc, DeclLoc,
+      /*depth=*/0,
+      /*position=*/0,
+      /*id=*/&ElementTypeII,
+      /*Typename=*/true,
+      /*ParameterPack=*/false);
+
+  T->setDeclContext(DC);
+  T->setReferenced();
+
+  // Create and Attach Template Parameter List to ConceptDecl
+  TemplateParameterList *ConceptParams = TemplateParameterList::Create(
+      Context, DeclLoc, DeclLoc, {T}, DeclLoc, nullptr);
+
+  DeclarationName DeclName = DeclarationName(&IsValidLineVectorII);
+  Expr *ConstraintExpr = getTypedBufferConstraintExpr(S, DeclLoc, T);
+
+  // Create a ConceptDecl
+  ConceptDecl *CD =
+      ConceptDecl::Create(Context, Context.getTranslationUnitDecl(), DeclLoc,
+                          DeclName, ConceptParams, ConstraintExpr);
+
+  // Attach the template parameter list to the ConceptDecl
+  CD->setTemplateParameters(ConceptParams);
+
+  // Add the concept declaration to the Translation Unit Decl
+  Context.getTranslationUnitDecl()->addDecl(CD);
+
+  return CD;
+}
+
+void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
+  CXXRecordDecl *Decl;
+  ConceptDecl *CD = getTypedBufferConceptDecl(*SemaPtr);
+
+  Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer")
+             .addSimpleTemplateParams(*SemaPtr, {"element_type"}, CD)
+             .Record;
+
+  onCompletion(Decl, [this](CXXRecordDecl *Decl) {
+    setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
+                    ResourceKind::TypedBuffer,
+                    /*IsROV=*/false, /*RawBuffer=*/false)
+        .addArraySubscriptOperators()
+        .completeDefinition();
+  });
+
+  Decl =
+      BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedBuffer")
+          .addSimpleTemplateParams(*SemaPtr, {"element_type"})
+          .Record;
+  onCompletion(Decl, [this](CXXRecordDecl *Decl) {
+    setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
+                    ResourceKind::TypedBuffer, /*IsROV=*/true,
+                    /*RawBuffer=*/false)
+        .addArraySubscriptOperators()
+        .completeDefinition();
+  });
+
+  Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "StructuredBuffer")
+             .addSimpleTemplateParams(*SemaPtr, {"element_type"})
+             .Record;
+  onCompletion(Decl, [this](CXXRecordDecl *Decl) {
+    setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
+                    ResourceKind::TypedBuffer, /*IsROV=*/false,
+                    /*RawBuffer=*/true)
+        .addArraySubscriptOperators()
+        .completeDefinition();
+  });
+}
+
+void HLSLExternalSemaSource::onCompletion(CXXRecordDecl *Record,
+                                          CompletionFunction Fn) {
+  Completions.insert(std::make_pair(Record->getCanonicalDecl(), Fn));
+}
+
+void HLSLExternalSemaSource::CompleteType(TagDecl *Tag) {
+  if (!isa<CXXRecordDecl>(Tag))
+    return;
+  auto Record = cast<CXXRecordDecl>(Tag);
+
+  // If this is a specialization, we need to get the underlying templated
+  // declaration and complete that.
+  if (auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(Record))
+    Record = TDecl->getSpecializedTemplate()->getTemplatedDecl();
+  Record = Record->getCanonicalDecl();
+  auto It = Completions.find(Record);
+  if (It == Completions.end())
+    return;
+  It->second(Record);
+}

>From a7429295546de30675b9c5d566376361dbc9d25e Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 18 Oct 2024 14:05:40 -0700
Subject: [PATCH 16/16] undo formatting problem

---
 clang/lib/Sema/HLSLExternalSemaSource.cpp | 1463 +++++++++++----------
 1 file changed, 732 insertions(+), 731 deletions(-)

diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index addfe38cd64583..82c446c341dd34 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -1,731 +1,732 @@
-//===--- HLSLExternalSemaSource.cpp - HLSL Sema Source --------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Sema/HLSLExternalSemaSource.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/Type.h"
-#include "clang/Basic/AttrKinds.h"
-#include "clang/Basic/HLSLRuntime.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/Sema.h"
-#include "clang/Sema/SemaHLSL.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Frontend/HLSL/HLSLResource.h"
-
-#include <functional>
-
-using namespace clang;
-using namespace llvm::hlsl;
-
-namespace {
-
-struct TemplateParameterListBuilder;
-
-struct BuiltinTypeDeclBuilder {
-  CXXRecordDecl *Record = nullptr;
-  ClassTemplateDecl *Template = nullptr;
-  ClassTemplateDecl *PrevTemplate = nullptr;
-  NamespaceDecl *HLSLNamespace = nullptr;
-  llvm::StringMap<FieldDecl *> Fields;
-
-  BuiltinTypeDeclBuilder(CXXRecordDecl *R) : Record(R) {
-    Record->startDefinition();
-    Template = Record->getDescribedClassTemplate();
-  }
-
-  BuiltinTypeDeclBuilder(Sema &S, NamespaceDecl *Namespace, StringRef Name)
-      : HLSLNamespace(Namespace) {
-    ASTContext &AST = S.getASTContext();
-    IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
-
-    LookupResult Result(S, &II, SourceLocation(), Sema::LookupTagName);
-    CXXRecordDecl *PrevDecl = nullptr;
-    if (S.LookupQualifiedName(Result, HLSLNamespace)) {
-      NamedDecl *Found = Result.getFoundDecl();
-      if (auto *TD = dyn_cast<ClassTemplateDecl>(Found)) {
-        PrevDecl = TD->getTemplatedDecl();
-        PrevTemplate = TD;
-      } else
-        PrevDecl = dyn_cast<CXXRecordDecl>(Found);
-      assert(PrevDecl && "Unexpected lookup result type.");
-    }
-
-    if (PrevDecl && PrevDecl->isCompleteDefinition()) {
-      Record = PrevDecl;
-      return;
-    }
-
-    Record = CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, HLSLNamespace,
-                                   SourceLocation(), SourceLocation(), &II,
-                                   PrevDecl, true);
-    Record->setImplicit(true);
-    Record->setLexicalDeclContext(HLSLNamespace);
-    Record->setHasExternalLexicalStorage();
-
-    // Don't let anyone derive from built-in types.
-    Record->addAttr(FinalAttr::CreateImplicit(AST, SourceRange(),
-                                              FinalAttr::Keyword_final));
-  }
-
-  ~BuiltinTypeDeclBuilder() {
-    if (HLSLNamespace && !Template && Record->getDeclContext() == HLSLNamespace)
-      HLSLNamespace->addDecl(Record);
-  }
-
-  BuiltinTypeDeclBuilder &
-  addMemberVariable(StringRef Name, QualType Type, llvm::ArrayRef<Attr *> Attrs,
-                    AccessSpecifier Access = AccessSpecifier::AS_private) {
-    if (Record->isCompleteDefinition())
-      return *this;
-    assert(Record->isBeingDefined() &&
-           "Definition must be started before adding members!");
-    ASTContext &AST = Record->getASTContext();
-
-    IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
-    TypeSourceInfo *MemTySource =
-        AST.getTrivialTypeSourceInfo(Type, SourceLocation());
-    auto *Field = FieldDecl::Create(
-        AST, Record, SourceLocation(), SourceLocation(), &II, Type, MemTySource,
-        nullptr, false, InClassInitStyle::ICIS_NoInit);
-    Field->setAccess(Access);
-    Field->setImplicit(true);
-    for (Attr *A : Attrs) {
-      if (A)
-        Field->addAttr(A);
-    }
-
-    Record->addDecl(Field);
-    Fields[Name] = Field;
-    return *this;
-  }
-
-  BuiltinTypeDeclBuilder &
-  addHandleMember(Sema &S, ResourceClass RC, ResourceKind RK, bool IsROV,
-                  bool RawBuffer,
-                  AccessSpecifier Access = AccessSpecifier::AS_private) {
-    if (Record->isCompleteDefinition())
-      return *this;
-
-    ASTContext &Ctx = S.getASTContext();
-    TypeSourceInfo *ElementTypeInfo = nullptr;
-
-    QualType ElemTy = Ctx.Char8Ty;
-    if (Template) {
-      if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
-              Template->getTemplateParameters()->getParam(0))) {
-        ElemTy = QualType(TTD->getTypeForDecl(), 0);
-      }
-    }
-    ElementTypeInfo = Ctx.getTrivialTypeSourceInfo(ElemTy, SourceLocation());
-
-    // add handle member with resource type attributes
-    QualType AttributedResTy = QualType();
-    SmallVector<const Attr *> Attrs = {
-        HLSLResourceClassAttr::CreateImplicit(Ctx, RC),
-        IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr,
-        RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr,
-        ElementTypeInfo
-            ? HLSLContainedTypeAttr::CreateImplicit(Ctx, ElementTypeInfo)
-            : nullptr};
-    Attr *ResourceAttr = HLSLResourceAttr::CreateImplicit(Ctx, RK);
-    if (CreateHLSLAttributedResourceType(S, Ctx.HLSLResourceTy, Attrs,
-                                         AttributedResTy))
-      addMemberVariable("h", AttributedResTy, {ResourceAttr}, Access);
-    return *this;
-  }
-
-  static DeclRefExpr *lookupBuiltinFunction(ASTContext &AST, Sema &S,
-                                            StringRef Name) {
-    IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
-    DeclarationNameInfo NameInfo =
-        DeclarationNameInfo(DeclarationName(&II), SourceLocation());
-    LookupResult R(S, NameInfo, Sema::LookupOrdinaryName);
-    // AllowBuiltinCreation is false but LookupDirect will create
-    // the builtin when searching the global scope anyways...
-    S.LookupName(R, S.getCurScope());
-    // FIXME: If the builtin function was user-declared in global scope,
-    // this assert *will* fail. Should this call LookupBuiltin instead?
-    assert(R.isSingleResult() &&
-           "Since this is a builtin it should always resolve!");
-    auto *VD = cast<ValueDecl>(R.getFoundDecl());
-    QualType Ty = VD->getType();
-    return DeclRefExpr::Create(AST, NestedNameSpecifierLoc(), SourceLocation(),
-                               VD, false, NameInfo, Ty, VK_PRValue);
-  }
-
-  static Expr *emitResourceClassExpr(ASTContext &AST, ResourceClass RC) {
-    return IntegerLiteral::Create(
-        AST,
-        llvm::APInt(AST.getIntWidth(AST.UnsignedCharTy),
-                    static_cast<uint8_t>(RC)),
-        AST.UnsignedCharTy, SourceLocation());
-  }
-
-  BuiltinTypeDeclBuilder &addDefaultHandleConstructor(Sema &S,
-                                                      ResourceClass RC) {
-    if (Record->isCompleteDefinition())
-      return *this;
-    ASTContext &AST = Record->getASTContext();
-
-    QualType ConstructorType =
-        AST.getFunctionType(AST.VoidTy, {}, FunctionProtoType::ExtProtoInfo());
-
-    CanQualType CanTy = Record->getTypeForDecl()->getCanonicalTypeUnqualified();
-    DeclarationName Name = AST.DeclarationNames.getCXXConstructorName(CanTy);
-    CXXConstructorDecl *Constructor = CXXConstructorDecl::Create(
-        AST, Record, SourceLocation(),
-        DeclarationNameInfo(Name, SourceLocation()), ConstructorType,
-        AST.getTrivialTypeSourceInfo(ConstructorType, SourceLocation()),
-        ExplicitSpecifier(), false, true, false,
-        ConstexprSpecKind::Unspecified);
-
-    Constructor->setBody(CompoundStmt::Create(
-        AST, {}, FPOptionsOverride(), SourceLocation(), SourceLocation()));
-    Constructor->setAccess(AccessSpecifier::AS_public);
-    Record->addDecl(Constructor);
-    return *this;
-  }
-
-  BuiltinTypeDeclBuilder &addArraySubscriptOperators() {
-    if (Record->isCompleteDefinition())
-      return *this;
-    addArraySubscriptOperator(true);
-    addArraySubscriptOperator(false);
-    return *this;
-  }
-
-  BuiltinTypeDeclBuilder &addArraySubscriptOperator(bool IsConst) {
-    if (Record->isCompleteDefinition())
-      return *this;
-
-    ASTContext &AST = Record->getASTContext();
-    QualType ElemTy = AST.Char8Ty;
-    if (Template) {
-      if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
-              Template->getTemplateParameters()->getParam(0))) {
-        ElemTy = QualType(TTD->getTypeForDecl(), 0);
-      }
-    }
-    QualType ReturnTy = ElemTy;
-
-    FunctionProtoType::ExtProtoInfo ExtInfo;
-
-    // Subscript operators return references to elements, const makes the
-    // reference and method const so that the underlying data is not mutable.
-    ReturnTy = AST.getLValueReferenceType(ReturnTy);
-    if (IsConst) {
-      ExtInfo.TypeQuals.addConst();
-      ReturnTy.addConst();
-    }
-
-    QualType MethodTy =
-        AST.getFunctionType(ReturnTy, {AST.UnsignedIntTy}, ExtInfo);
-    auto *TSInfo = AST.getTrivialTypeSourceInfo(MethodTy, SourceLocation());
-    auto *MethodDecl = CXXMethodDecl::Create(
-        AST, Record, SourceLocation(),
-        DeclarationNameInfo(
-            AST.DeclarationNames.getCXXOperatorName(OO_Subscript),
-            SourceLocation()),
-        MethodTy, TSInfo, SC_None, false, false, ConstexprSpecKind::Unspecified,
-        SourceLocation());
-
-    IdentifierInfo &II = AST.Idents.get("Idx", tok::TokenKind::identifier);
-    auto *IdxParam = ParmVarDecl::Create(
-        AST, MethodDecl->getDeclContext(), SourceLocation(), SourceLocation(),
-        &II, AST.UnsignedIntTy,
-        AST.getTrivialTypeSourceInfo(AST.UnsignedIntTy, SourceLocation()),
-        SC_None, nullptr);
-    MethodDecl->setParams({IdxParam});
-
-    // Also add the parameter to the function prototype.
-    auto FnProtoLoc = TSInfo->getTypeLoc().getAs<FunctionProtoTypeLoc>();
-    FnProtoLoc.setParam(0, IdxParam);
-
-    // FIXME: Placeholder to make sure we return the correct type - create
-    // field of element_type and return reference to it. This field will go
-    // away once indexing into resources is properly implemented in
-    // llvm/llvm-project#95956.
-    if (Fields.count("e") == 0) {
-      addMemberVariable("e", ElemTy, {});
-    }
-    FieldDecl *ElemFieldDecl = Fields["e"];
-
-    auto *This =
-        CXXThisExpr::Create(AST, SourceLocation(),
-                            MethodDecl->getFunctionObjectParameterType(), true);
-    Expr *ElemField = MemberExpr::CreateImplicit(
-        AST, This, false, ElemFieldDecl, ElemFieldDecl->getType(), VK_LValue,
-        OK_Ordinary);
-    auto *Return =
-        ReturnStmt::Create(AST, SourceLocation(), ElemField, nullptr);
-
-    MethodDecl->setBody(CompoundStmt::Create(AST, {Return}, FPOptionsOverride(),
-                                             SourceLocation(),
-                                             SourceLocation()));
-    MethodDecl->setLexicalDeclContext(Record);
-    MethodDecl->setAccess(AccessSpecifier::AS_public);
-    MethodDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
-        AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
-    Record->addDecl(MethodDecl);
-
-    return *this;
-  }
-
-  BuiltinTypeDeclBuilder &startDefinition() {
-    if (Record->isCompleteDefinition())
-      return *this;
-    Record->startDefinition();
-    return *this;
-  }
-
-  BuiltinTypeDeclBuilder &completeDefinition() {
-    if (Record->isCompleteDefinition())
-      return *this;
-    assert(Record->isBeingDefined() &&
-           "Definition must be started before completing it.");
-
-    Record->completeDefinition();
-    return *this;
-  }
-
-  TemplateParameterListBuilder addTemplateArgumentList(Sema &S);
-  BuiltinTypeDeclBuilder &
-  addSimpleTemplateParams(Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD);
-  BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S);
-};
-
-struct TemplateParameterListBuilder {
-  BuiltinTypeDeclBuilder &Builder;
-  Sema &S;
-  llvm::SmallVector<NamedDecl *> Params;
-
-  TemplateParameterListBuilder(Sema &S, BuiltinTypeDeclBuilder &RB)
-      : Builder(RB), S(S) {}
-
-  ~TemplateParameterListBuilder() { finalizeTemplateArgs(); }
-
-  TemplateParameterListBuilder &
-  addTypeParameter(StringRef Name, QualType DefaultValue = QualType()) {
-    if (Builder.Record->isCompleteDefinition())
-      return *this;
-    unsigned Position = static_cast<unsigned>(Params.size());
-    auto *Decl = TemplateTypeParmDecl::Create(
-        S.Context, Builder.Record->getDeclContext(), SourceLocation(),
-        SourceLocation(), /* TemplateDepth */ 0, Position,
-        &S.Context.Idents.get(Name, tok::TokenKind::identifier),
-        /* Typename */ true,
-        /* ParameterPack */ false,
-        /* HasTypeConstraint*/ false);
-    if (!DefaultValue.isNull())
-      Decl->setDefaultArgument(
-          S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(),
-                                                     SourceLocation()));
-    Decl->setReferenced();
-    Params.emplace_back(Decl);
-    return *this;
-  }
-
-  /*
-  The concept specialization expression (CSE) constructed below is constructed
-  so that it matches the CSE that is constructed when parsing
-  the below C++ code:
-
-  template<typename T>
-  concept is_valid_line_vector =sizeof(T) <= 16;
-
-  template<typename element_type> requires is_valid_line_vector<element_type>
-  struct RWBuffer {
-      element_type Val;
-  };
-
-  int fn() {
-      RWBuffer<int> Buf;
-  }
-
-  When dumping the AST and filtering for "RWBuffer", the resulting AST
-  structure is what we're trying to construct below, specifically the
-  CSE portion.
-  */
-  ConceptSpecializationExpr *getConceptSpecializationExpr(Sema &S,
-                                                          ConceptDecl *CD) {
-    ASTContext &Context = S.getASTContext();
-    SourceLocation Loc = Builder.Record->getBeginLoc();
-    DeclarationNameInfo DNI(CD->getDeclName(), Loc);
-    NestedNameSpecifierLoc NNSLoc;
-    DeclContext *DC = Builder.Record->getDeclContext();
-    TemplateArgumentListInfo TALI(Loc, Loc);
-
-    // Assume that the concept decl has just one template parameter
-    // This parameter should have been added when CD was constructed
-    // in getTypedBufferConceptDecl
-    assert(CD->getTemplateParameters()->size() == 1 &&
-           "unexpected concept decl parameter count");
-    TemplateTypeParmDecl *ConceptTTPD = dyn_cast<TemplateTypeParmDecl>(
-        CD->getTemplateParameters()->getParam(0));
-
-    // this fake TemplateTypeParmDecl is used to construct a template argument
-    // that will be used to construct the ImplicitConceptSpecializationDecl
-    TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create(
-        Context,                          // AST context
-        Context.getTranslationUnitDecl(), // DeclContext
-        SourceLocation(), SourceLocation(),
-        /*depth=*/0,                // Depth in the template parameter list
-        /*position=*/0,             // Position in the template parameter list
-        /*id=*/nullptr,             // Identifier for 'T'
-        /*Typename=*/true,          // Indicates this is a 'typename' or 'class'
-        /*ParameterPack=*/false,    // Not a parameter pack
-        /*HasTypeConstraint=*/false // Not a parameter pack
-    );
-
-    T->setDeclContext(DC);
-    T->setReferenced();
-
-    QualType ConceptTType = Context.getTypeDeclType(ConceptTTPD);
-
-    // this is the 2nd template argument node in the AST above
-    TemplateArgument ConceptTA = TemplateArgument(ConceptTType);
-
-    QualType CSETType = Context.getTypeDeclType(T);
-
-    // this is the 1st template argument node in the AST above
-    TemplateArgument CSETA = TemplateArgument(CSETType);
-
-    ImplicitConceptSpecializationDecl *ImplicitCSEDecl =
-        ImplicitConceptSpecializationDecl::Create(
-            Context, Builder.Record->getDeclContext(), Loc, {CSETA});
-
-    // Constraint satisfaction is used to construct the
-    // ConceptSpecailizationExpr, and represents the 2nd Template Argument,
-    // located at the bottom of the sample AST above.
-    const ConstraintSatisfaction CS(CD, {ConceptTA});
-    TemplateArgumentLoc TAL = S.getTrivialTemplateArgumentLoc(
-        ConceptTA, QualType(), SourceLocation());
-
-    TALI.addArgument(TAL);
-    const ASTTemplateArgumentListInfo *ATALI =
-        ASTTemplateArgumentListInfo::Create(Context, TALI);
-
-    // In the concept reference, ATALI is what adds the extra
-    // TemplateArgument node underneath CSE
-    ConceptReference *CR =
-        ConceptReference::Create(Context, NNSLoc, Loc, DNI, CD, CD, ATALI);
-
-    ConceptSpecializationExpr *CSE =
-        ConceptSpecializationExpr::Create(Context, CR, ImplicitCSEDecl, &CS);
-
-    return CSE;
-  }
-
-  BuiltinTypeDeclBuilder &finalizeTemplateArgs(ConceptDecl *CD = nullptr) {
-    if (Params.empty())
-      return Builder;
-    ConceptSpecializationExpr *CSE =
-        CD ? getConceptSpecializationExpr(S, CD) : nullptr;
-
-    auto *ParamList = TemplateParameterList::Create(S.Context, SourceLocation(),
-                                                    SourceLocation(), Params,
-                                                    SourceLocation(), CSE);
-    Builder.Template = ClassTemplateDecl::Create(
-        S.Context, Builder.Record->getDeclContext(), SourceLocation(),
-        DeclarationName(Builder.Record->getIdentifier()), ParamList,
-        Builder.Record);
-
-    Builder.Record->setDescribedClassTemplate(Builder.Template);
-    Builder.Template->setImplicit(true);
-    Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());
-
-    // NOTE: setPreviousDecl before addDecl so new decl replace old decl when
-    // make visible.
-    Builder.Template->setPreviousDecl(Builder.PrevTemplate);
-    Builder.Record->getDeclContext()->addDecl(Builder.Template);
-    Params.clear();
-
-    QualType T = Builder.Template->getInjectedClassNameSpecialization();
-    T = S.Context.getInjectedClassNameType(Builder.Record, T);
-
-    return Builder;
-  }
-};
-} // namespace
-
-TemplateParameterListBuilder
-BuiltinTypeDeclBuilder::addTemplateArgumentList(Sema &S) {
-  return TemplateParameterListBuilder(S, *this);
-}
-
-BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addSimpleTemplateParams(
-    Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD = nullptr) {
-  TemplateParameterListBuilder Builder = this->addTemplateArgumentList(S);
-  for (StringRef Name : Names)
-    Builder.addTypeParameter(Name);
-
-  return Builder.finalizeTemplateArgs(CD);
-}
-
-HLSLExternalSemaSource::~HLSLExternalSemaSource() {}
-
-void HLSLExternalSemaSource::InitializeSema(Sema &S) {
-  SemaPtr = &S;
-  ASTContext &AST = SemaPtr->getASTContext();
-  // If the translation unit has external storage force external decls to load.
-  if (AST.getTranslationUnitDecl()->hasExternalLexicalStorage())
-    (void)AST.getTranslationUnitDecl()->decls_begin();
-
-  IdentifierInfo &HLSL = AST.Idents.get("hlsl", tok::TokenKind::identifier);
-  LookupResult Result(S, &HLSL, SourceLocation(), Sema::LookupNamespaceName);
-  NamespaceDecl *PrevDecl = nullptr;
-  if (S.LookupQualifiedName(Result, AST.getTranslationUnitDecl()))
-    PrevDecl = Result.getAsSingle<NamespaceDecl>();
-  HLSLNamespace = NamespaceDecl::Create(
-      AST, AST.getTranslationUnitDecl(), /*Inline=*/false, SourceLocation(),
-      SourceLocation(), &HLSL, PrevDecl, /*Nested=*/false);
-  HLSLNamespace->setImplicit(true);
-  HLSLNamespace->setHasExternalLexicalStorage();
-  AST.getTranslationUnitDecl()->addDecl(HLSLNamespace);
-
-  // Force external decls in the HLSL namespace to load from the PCH.
-  (void)HLSLNamespace->getCanonicalDecl()->decls_begin();
-  defineTrivialHLSLTypes();
-  defineHLSLTypesWithForwardDeclarations();
-
-  // This adds a `using namespace hlsl` directive. In DXC, we don't put HLSL's
-  // built in types inside a namespace, but we are planning to change that in
-  // the near future. In order to be source compatible older versions of HLSL
-  // will need to implicitly use the hlsl namespace. For now in clang everything
-  // will get added to the namespace, and we can remove the using directive for
-  // future language versions to match HLSL's evolution.
-  auto *UsingDecl = UsingDirectiveDecl::Create(
-      AST, AST.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
-      NestedNameSpecifierLoc(), SourceLocation(), HLSLNamespace,
-      AST.getTranslationUnitDecl());
-
-  AST.getTranslationUnitDecl()->addDecl(UsingDecl);
-}
-
-void HLSLExternalSemaSource::defineHLSLVectorAlias() {
-  ASTContext &AST = SemaPtr->getASTContext();
-
-  llvm::SmallVector<NamedDecl *> TemplateParams;
-
-  auto *TypeParam = TemplateTypeParmDecl::Create(
-      AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 0,
-      &AST.Idents.get("element", tok::TokenKind::identifier), false, false);
-  TypeParam->setDefaultArgument(
-      AST, SemaPtr->getTrivialTemplateArgumentLoc(
-               TemplateArgument(AST.FloatTy), QualType(), SourceLocation()));
-
-  TemplateParams.emplace_back(TypeParam);
-
-  auto *SizeParam = NonTypeTemplateParmDecl::Create(
-      AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 1,
-      &AST.Idents.get("element_count", tok::TokenKind::identifier), AST.IntTy,
-      false, AST.getTrivialTypeSourceInfo(AST.IntTy));
-  llvm::APInt Val(AST.getIntWidth(AST.IntTy), 4);
-  TemplateArgument Default(AST, llvm::APSInt(std::move(Val)), AST.IntTy,
-                           /*IsDefaulted=*/true);
-  SizeParam->setDefaultArgument(
-      AST, SemaPtr->getTrivialTemplateArgumentLoc(Default, AST.IntTy,
-                                                  SourceLocation(), SizeParam));
-  TemplateParams.emplace_back(SizeParam);
-
-  auto *ParamList =
-      TemplateParameterList::Create(AST, SourceLocation(), SourceLocation(),
-                                    TemplateParams, SourceLocation(), nullptr);
-
-  IdentifierInfo &II = AST.Idents.get("vector", tok::TokenKind::identifier);
-
-  QualType AliasType = AST.getDependentSizedExtVectorType(
-      AST.getTemplateTypeParmType(0, 0, false, TypeParam),
-      DeclRefExpr::Create(
-          AST, NestedNameSpecifierLoc(), SourceLocation(), SizeParam, false,
-          DeclarationNameInfo(SizeParam->getDeclName(), SourceLocation()),
-          AST.IntTy, VK_LValue),
-      SourceLocation());
-
-  auto *Record = TypeAliasDecl::Create(AST, HLSLNamespace, SourceLocation(),
-                                       SourceLocation(), &II,
-                                       AST.getTrivialTypeSourceInfo(AliasType));
-  Record->setImplicit(true);
-
-  auto *Template =
-      TypeAliasTemplateDecl::Create(AST, HLSLNamespace, SourceLocation(),
-                                    Record->getIdentifier(), ParamList, Record);
-
-  Record->setDescribedAliasTemplate(Template);
-  Template->setImplicit(true);
-  Template->setLexicalDeclContext(Record->getDeclContext());
-  HLSLNamespace->addDecl(Template);
-}
-
-void HLSLExternalSemaSource::defineTrivialHLSLTypes() {
-  defineHLSLVectorAlias();
-}
-
-/// Set up common members and attributes for buffer types
-static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
-                                              ResourceClass RC, ResourceKind RK,
-                                              bool IsROV, bool RawBuffer) {
-  return BuiltinTypeDeclBuilder(Decl)
-      .addHandleMember(S, RC, RK, IsROV, RawBuffer)
-      .addDefaultHandleConstructor(S, RC);
-}
-
-BinaryOperator *getSizeOfLEQ16Expr(ASTContext &Context, SourceLocation NameLoc,
-                                   TemplateTypeParmDecl *T) {
-  // Obtain the QualType for 'unsigned long'
-  QualType unsignedLongType = Context.UnsignedLongTy;
-
-  // Create a QualType that points to this TemplateTypeParmDecl
-  QualType TType = Context.getTypeDeclType(T);
-
-  // Create a TypeSourceInfo for the template type parameter 'T'
-  TypeSourceInfo *TTypeSourceInfo =
-      Context.getTrivialTypeSourceInfo(TType, NameLoc);
-
-  UnaryExprOrTypeTraitExpr *SizeOfExpr = new (Context) UnaryExprOrTypeTraitExpr(
-      UETT_SizeOf, TTypeSourceInfo, unsignedLongType, NameLoc, NameLoc);
-
-  // Create an IntegerLiteral for the value '16' with size type
-  QualType SizeType = Context.getSizeType();
-  llvm::APInt SizeValue = llvm::APInt(Context.getTypeSize(SizeType), 16);
-  IntegerLiteral *sizeLiteral =
-      new (Context) IntegerLiteral(Context, SizeValue, SizeType, NameLoc);
-
-  QualType BoolTy = Context.BoolTy;
-
-  BinaryOperator *binaryOperator =
-      BinaryOperator::Create(Context, SizeOfExpr, // Left-hand side expression
-                             sizeLiteral,         // Right-hand side expression
-                             BO_LE,               // Binary operator kind (<=)
-                             BoolTy,              // Result type (bool)
-                             VK_LValue,           // Value kind
-                             OK_Ordinary,         // Object kind
-                             NameLoc,             // Source location of operator
-                             FPOptionsOverride());
-
-  return binaryOperator;
-}
-
-Expr *getTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
-                                   TemplateTypeParmDecl *T) {
-  ASTContext &Context = S.getASTContext();
-
-  // first get the "sizeof(T) <= 16" expression, as a binary operator
-  BinaryOperator *SizeOfLEQ16 = getSizeOfLEQ16Expr(Context, NameLoc, T);
-  // TODO: add the '__builtin_hlsl_is_line_vector_layout_compatible' builtin
-  // and return a binary operator that evaluates the builtin on the given
-  // template type parameter 'T'
-  return SizeOfLEQ16;
-}
-
-ConceptDecl *getTypedBufferConceptDecl(Sema &S) {
-  DeclContext *DC = S.CurContext;
-  ASTContext &Context = S.getASTContext();
-  SourceLocation DeclLoc = SourceLocation();
-
-  IdentifierInfo &IsValidLineVectorII =
-      Context.Idents.get("is_valid_line_vector");
-  IdentifierInfo &ElementTypeII = Context.Idents.get("element_type");
-  TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create(
-      Context, Context.getTranslationUnitDecl(), DeclLoc, DeclLoc,
-      /*depth=*/0,
-      /*position=*/0,
-      /*id=*/&ElementTypeII,
-      /*Typename=*/true,
-      /*ParameterPack=*/false);
-
-  T->setDeclContext(DC);
-  T->setReferenced();
-
-  // Create and Attach Template Parameter List to ConceptDecl
-  TemplateParameterList *ConceptParams = TemplateParameterList::Create(
-      Context, DeclLoc, DeclLoc, {T}, DeclLoc, nullptr);
-
-  DeclarationName DeclName = DeclarationName(&IsValidLineVectorII);
-  Expr *ConstraintExpr = getTypedBufferConstraintExpr(S, DeclLoc, T);
-
-  // Create a ConceptDecl
-  ConceptDecl *CD =
-      ConceptDecl::Create(Context, Context.getTranslationUnitDecl(), DeclLoc,
-                          DeclName, ConceptParams, ConstraintExpr);
-
-  // Attach the template parameter list to the ConceptDecl
-  CD->setTemplateParameters(ConceptParams);
-
-  // Add the concept declaration to the Translation Unit Decl
-  Context.getTranslationUnitDecl()->addDecl(CD);
-
-  return CD;
-}
-
-void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
-  CXXRecordDecl *Decl;
-  ConceptDecl *CD = getTypedBufferConceptDecl(*SemaPtr);
-
-  Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer")
-             .addSimpleTemplateParams(*SemaPtr, {"element_type"}, CD)
-             .Record;
-
-  onCompletion(Decl, [this](CXXRecordDecl *Decl) {
-    setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
-                    ResourceKind::TypedBuffer,
-                    /*IsROV=*/false, /*RawBuffer=*/false)
-        .addArraySubscriptOperators()
-        .completeDefinition();
-  });
-
-  Decl =
-      BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedBuffer")
-          .addSimpleTemplateParams(*SemaPtr, {"element_type"})
-          .Record;
-  onCompletion(Decl, [this](CXXRecordDecl *Decl) {
-    setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
-                    ResourceKind::TypedBuffer, /*IsROV=*/true,
-                    /*RawBuffer=*/false)
-        .addArraySubscriptOperators()
-        .completeDefinition();
-  });
-
-  Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "StructuredBuffer")
-             .addSimpleTemplateParams(*SemaPtr, {"element_type"})
-             .Record;
-  onCompletion(Decl, [this](CXXRecordDecl *Decl) {
-    setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
-                    ResourceKind::TypedBuffer, /*IsROV=*/false,
-                    /*RawBuffer=*/true)
-        .addArraySubscriptOperators()
-        .completeDefinition();
-  });
-}
-
-void HLSLExternalSemaSource::onCompletion(CXXRecordDecl *Record,
-                                          CompletionFunction Fn) {
-  Completions.insert(std::make_pair(Record->getCanonicalDecl(), Fn));
-}
-
-void HLSLExternalSemaSource::CompleteType(TagDecl *Tag) {
-  if (!isa<CXXRecordDecl>(Tag))
-    return;
-  auto Record = cast<CXXRecordDecl>(Tag);
-
-  // If this is a specialization, we need to get the underlying templated
-  // declaration and complete that.
-  if (auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(Record))
-    Record = TDecl->getSpecializedTemplate()->getTemplatedDecl();
-  Record = Record->getCanonicalDecl();
-  auto It = Completions.find(Record);
-  if (It == Completions.end())
-    return;
-  It->second(Record);
-}
+//===--- HLSLExternalSemaSource.cpp - HLSL Sema Source --------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/HLSLExternalSemaSource.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/AttrKinds.h"
+#include "clang/Basic/HLSLRuntime.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaHLSL.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Frontend/HLSL/HLSLResource.h"
+
+#include <functional>
+
+using namespace clang;
+using namespace llvm::hlsl;
+
+namespace {
+
+struct TemplateParameterListBuilder;
+
+struct BuiltinTypeDeclBuilder {
+  CXXRecordDecl *Record = nullptr;
+  ClassTemplateDecl *Template = nullptr;
+  ClassTemplateDecl *PrevTemplate = nullptr;
+  NamespaceDecl *HLSLNamespace = nullptr;
+  llvm::StringMap<FieldDecl *> Fields;
+
+  BuiltinTypeDeclBuilder(CXXRecordDecl *R) : Record(R) {
+    Record->startDefinition();
+    Template = Record->getDescribedClassTemplate();
+  }
+
+  BuiltinTypeDeclBuilder(Sema &S, NamespaceDecl *Namespace, StringRef Name)
+      : HLSLNamespace(Namespace) {
+    ASTContext &AST = S.getASTContext();
+    IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
+
+    LookupResult Result(S, &II, SourceLocation(), Sema::LookupTagName);
+    CXXRecordDecl *PrevDecl = nullptr;
+    if (S.LookupQualifiedName(Result, HLSLNamespace)) {
+      NamedDecl *Found = Result.getFoundDecl();
+      if (auto *TD = dyn_cast<ClassTemplateDecl>(Found)) {
+        PrevDecl = TD->getTemplatedDecl();
+        PrevTemplate = TD;
+      } else
+        PrevDecl = dyn_cast<CXXRecordDecl>(Found);
+      assert(PrevDecl && "Unexpected lookup result type.");
+    }
+
+    if (PrevDecl && PrevDecl->isCompleteDefinition()) {
+      Record = PrevDecl;
+      return;
+    }
+
+    Record = CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, HLSLNamespace,
+                                   SourceLocation(), SourceLocation(), &II,
+                                   PrevDecl, true);
+    Record->setImplicit(true);
+    Record->setLexicalDeclContext(HLSLNamespace);
+    Record->setHasExternalLexicalStorage();
+
+    // Don't let anyone derive from built-in types.
+    Record->addAttr(FinalAttr::CreateImplicit(AST, SourceRange(),
+                                              FinalAttr::Keyword_final));
+  }
+
+  ~BuiltinTypeDeclBuilder() {
+    if (HLSLNamespace && !Template && Record->getDeclContext() == HLSLNamespace)
+      HLSLNamespace->addDecl(Record);
+  }
+
+  BuiltinTypeDeclBuilder &
+  addMemberVariable(StringRef Name, QualType Type, llvm::ArrayRef<Attr *> Attrs,
+                    AccessSpecifier Access = AccessSpecifier::AS_private) {
+    if (Record->isCompleteDefinition())
+      return *this;
+    assert(Record->isBeingDefined() &&
+           "Definition must be started before adding members!");
+    ASTContext &AST = Record->getASTContext();
+
+    IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
+    TypeSourceInfo *MemTySource =
+        AST.getTrivialTypeSourceInfo(Type, SourceLocation());
+    auto *Field = FieldDecl::Create(
+        AST, Record, SourceLocation(), SourceLocation(), &II, Type, MemTySource,
+        nullptr, false, InClassInitStyle::ICIS_NoInit);
+    Field->setAccess(Access);
+    Field->setImplicit(true);
+    for (Attr *A : Attrs) {
+      if (A)
+        Field->addAttr(A);
+    }
+
+    Record->addDecl(Field);
+    Fields[Name] = Field;
+    return *this;
+  }
+
+  BuiltinTypeDeclBuilder &
+  addHandleMember(Sema &S, ResourceClass RC, ResourceKind RK, bool IsROV,
+                  bool RawBuffer,
+                  AccessSpecifier Access = AccessSpecifier::AS_private) {
+    if (Record->isCompleteDefinition())
+      return *this;
+
+    ASTContext &Ctx = S.getASTContext();
+    TypeSourceInfo *ElementTypeInfo = nullptr;
+
+    QualType ElemTy = Ctx.Char8Ty;
+    if (Template) {
+      if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
+              Template->getTemplateParameters()->getParam(0))) {
+        ElemTy = QualType(TTD->getTypeForDecl(), 0);
+      }
+    }
+    ElementTypeInfo = Ctx.getTrivialTypeSourceInfo(ElemTy, SourceLocation());
+
+    // add handle member with resource type attributes
+    QualType AttributedResTy = QualType();
+    SmallVector<const Attr *> Attrs = {
+        HLSLResourceClassAttr::CreateImplicit(Ctx, RC),
+        IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr,
+        RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr,
+        ElementTypeInfo
+            ? HLSLContainedTypeAttr::CreateImplicit(Ctx, ElementTypeInfo)
+            : nullptr};
+    Attr *ResourceAttr = HLSLResourceAttr::CreateImplicit(Ctx, RK);
+    if (CreateHLSLAttributedResourceType(S, Ctx.HLSLResourceTy, Attrs,
+                                         AttributedResTy))
+      addMemberVariable("h", AttributedResTy, {ResourceAttr}, Access);
+    return *this;
+  }
+
+  static DeclRefExpr *lookupBuiltinFunction(ASTContext &AST, Sema &S,
+                                            StringRef Name) {
+    IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
+    DeclarationNameInfo NameInfo =
+        DeclarationNameInfo(DeclarationName(&II), SourceLocation());
+    LookupResult R(S, NameInfo, Sema::LookupOrdinaryName);
+    // AllowBuiltinCreation is false but LookupDirect will create
+    // the builtin when searching the global scope anyways...
+    S.LookupName(R, S.getCurScope());
+    // FIXME: If the builtin function was user-declared in global scope,
+    // this assert *will* fail. Should this call LookupBuiltin instead?
+    assert(R.isSingleResult() &&
+           "Since this is a builtin it should always resolve!");
+    auto *VD = cast<ValueDecl>(R.getFoundDecl());
+    QualType Ty = VD->getType();
+    return DeclRefExpr::Create(AST, NestedNameSpecifierLoc(), SourceLocation(),
+                               VD, false, NameInfo, Ty, VK_PRValue);
+  }
+
+  static Expr *emitResourceClassExpr(ASTContext &AST, ResourceClass RC) {
+    return IntegerLiteral::Create(
+        AST,
+        llvm::APInt(AST.getIntWidth(AST.UnsignedCharTy),
+                    static_cast<uint8_t>(RC)),
+        AST.UnsignedCharTy, SourceLocation());
+  }
+
+  BuiltinTypeDeclBuilder &addDefaultHandleConstructor(Sema &S,
+                                                      ResourceClass RC) {
+    if (Record->isCompleteDefinition())
+      return *this;
+    ASTContext &AST = Record->getASTContext();
+
+    QualType ConstructorType =
+        AST.getFunctionType(AST.VoidTy, {}, FunctionProtoType::ExtProtoInfo());
+
+    CanQualType CanTy = Record->getTypeForDecl()->getCanonicalTypeUnqualified();
+    DeclarationName Name = AST.DeclarationNames.getCXXConstructorName(CanTy);
+    CXXConstructorDecl *Constructor = CXXConstructorDecl::Create(
+        AST, Record, SourceLocation(),
+        DeclarationNameInfo(Name, SourceLocation()), ConstructorType,
+        AST.getTrivialTypeSourceInfo(ConstructorType, SourceLocation()),
+        ExplicitSpecifier(), false, true, false,
+        ConstexprSpecKind::Unspecified);
+
+    Constructor->setBody(CompoundStmt::Create(
+        AST, {}, FPOptionsOverride(), SourceLocation(), SourceLocation()));
+    Constructor->setAccess(AccessSpecifier::AS_public);
+    Record->addDecl(Constructor);
+    return *this;
+  }
+
+  BuiltinTypeDeclBuilder &addArraySubscriptOperators() {
+    if (Record->isCompleteDefinition())
+      return *this;
+    addArraySubscriptOperator(true);
+    addArraySubscriptOperator(false);
+    return *this;
+  }
+
+  BuiltinTypeDeclBuilder &addArraySubscriptOperator(bool IsConst) {
+    if (Record->isCompleteDefinition())
+      return *this;
+
+    ASTContext &AST = Record->getASTContext();
+    QualType ElemTy = AST.Char8Ty;
+    if (Template) {
+      if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
+              Template->getTemplateParameters()->getParam(0))) {
+        ElemTy = QualType(TTD->getTypeForDecl(), 0);
+      }
+    }
+    QualType ReturnTy = ElemTy;
+
+    FunctionProtoType::ExtProtoInfo ExtInfo;
+
+    // Subscript operators return references to elements, const makes the
+    // reference and method const so that the underlying data is not mutable.
+    ReturnTy = AST.getLValueReferenceType(ReturnTy);
+    if (IsConst) {
+      ExtInfo.TypeQuals.addConst();
+      ReturnTy.addConst();
+    }
+
+    QualType MethodTy =
+        AST.getFunctionType(ReturnTy, {AST.UnsignedIntTy}, ExtInfo);
+    auto *TSInfo = AST.getTrivialTypeSourceInfo(MethodTy, SourceLocation());
+    auto *MethodDecl = CXXMethodDecl::Create(
+        AST, Record, SourceLocation(),
+        DeclarationNameInfo(
+            AST.DeclarationNames.getCXXOperatorName(OO_Subscript),
+            SourceLocation()),
+        MethodTy, TSInfo, SC_None, false, false, ConstexprSpecKind::Unspecified,
+        SourceLocation());
+
+    IdentifierInfo &II = AST.Idents.get("Idx", tok::TokenKind::identifier);
+    auto *IdxParam = ParmVarDecl::Create(
+        AST, MethodDecl->getDeclContext(), SourceLocation(), SourceLocation(),
+        &II, AST.UnsignedIntTy,
+        AST.getTrivialTypeSourceInfo(AST.UnsignedIntTy, SourceLocation()),
+        SC_None, nullptr);
+    MethodDecl->setParams({IdxParam});
+
+    // Also add the parameter to the function prototype.
+    auto FnProtoLoc = TSInfo->getTypeLoc().getAs<FunctionProtoTypeLoc>();
+    FnProtoLoc.setParam(0, IdxParam);
+
+    // FIXME: Placeholder to make sure we return the correct type - create
+    // field of element_type and return reference to it. This field will go
+    // away once indexing into resources is properly implemented in
+    // llvm/llvm-project#95956.
+    if (Fields.count("e") == 0) {
+      addMemberVariable("e", ElemTy, {});
+    }
+    FieldDecl *ElemFieldDecl = Fields["e"];
+
+    auto *This =
+        CXXThisExpr::Create(AST, SourceLocation(),
+                            MethodDecl->getFunctionObjectParameterType(), true);
+    Expr *ElemField = MemberExpr::CreateImplicit(
+        AST, This, false, ElemFieldDecl, ElemFieldDecl->getType(), VK_LValue,
+        OK_Ordinary);
+    auto *Return =
+        ReturnStmt::Create(AST, SourceLocation(), ElemField, nullptr);
+
+    MethodDecl->setBody(CompoundStmt::Create(AST, {Return}, FPOptionsOverride(),
+                                             SourceLocation(),
+                                             SourceLocation()));
+    MethodDecl->setLexicalDeclContext(Record);
+    MethodDecl->setAccess(AccessSpecifier::AS_public);
+    MethodDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
+        AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
+    Record->addDecl(MethodDecl);
+
+    return *this;
+  }
+
+  BuiltinTypeDeclBuilder &startDefinition() {
+    if (Record->isCompleteDefinition())
+      return *this;
+    Record->startDefinition();
+    return *this;
+  }
+
+  BuiltinTypeDeclBuilder &completeDefinition() {
+    if (Record->isCompleteDefinition())
+      return *this;
+    assert(Record->isBeingDefined() &&
+           "Definition must be started before completing it.");
+
+    Record->completeDefinition();
+    return *this;
+  }
+
+  TemplateParameterListBuilder addTemplateArgumentList(Sema &S);
+  BuiltinTypeDeclBuilder &
+  addSimpleTemplateParams(Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD);
+  BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S);
+};
+
+struct TemplateParameterListBuilder {
+  BuiltinTypeDeclBuilder &Builder;
+  Sema &S;
+  llvm::SmallVector<NamedDecl *> Params;
+
+  TemplateParameterListBuilder(Sema &S, BuiltinTypeDeclBuilder &RB)
+      : Builder(RB), S(S) {}
+
+  ~TemplateParameterListBuilder() { finalizeTemplateArgs(); }
+
+  TemplateParameterListBuilder &
+  addTypeParameter(StringRef Name, QualType DefaultValue = QualType()) {
+    if (Builder.Record->isCompleteDefinition())
+      return *this;
+    unsigned Position = static_cast<unsigned>(Params.size());
+    auto *Decl = TemplateTypeParmDecl::Create(
+        S.Context, Builder.Record->getDeclContext(), SourceLocation(),
+        SourceLocation(), /* TemplateDepth */ 0, Position,
+        &S.Context.Idents.get(Name, tok::TokenKind::identifier),
+        /* Typename */ true,
+        /* ParameterPack */ false,
+        /* HasTypeConstraint*/ false);
+    if (!DefaultValue.isNull())
+      Decl->setDefaultArgument(
+          S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(),
+                                                     SourceLocation()));
+    Decl->setReferenced();
+    Params.emplace_back(Decl);
+    return *this;
+  }
+
+  /*
+  The concept specialization expression (CSE) constructed below is constructed
+  so that it matches the CSE that is constructed when parsing
+  the below C++ code:
+
+  template<typename T>
+  concept is_valid_line_vector =sizeof(T) <= 16;
+
+  template<typename element_type> requires is_valid_line_vector<element_type>
+
+  struct RWBuffer {
+      element_type Val;
+  };
+
+  int fn() {
+      RWBuffer<int> Buf;
+  }
+
+  When dumping the AST and filtering for "RWBuffer", the resulting AST
+  structure is what we're trying to construct below, specifically the
+  CSE portion.
+  */
+  ConceptSpecializationExpr *getConceptSpecializationExpr(Sema &S,
+                                                          ConceptDecl *CD) {
+    ASTContext &Context = S.getASTContext();
+    SourceLocation Loc = Builder.Record->getBeginLoc();
+    DeclarationNameInfo DNI(CD->getDeclName(), Loc);
+    NestedNameSpecifierLoc NNSLoc;
+    DeclContext *DC = Builder.Record->getDeclContext();
+    TemplateArgumentListInfo TALI(Loc, Loc);
+
+    // Assume that the concept decl has just one template parameter
+    // This parameter should have been added when CD was constructed
+    // in getTypedBufferConceptDecl
+    assert(CD->getTemplateParameters()->size() == 1 &&
+           "unexpected concept decl parameter count");
+    TemplateTypeParmDecl *ConceptTTPD = dyn_cast<TemplateTypeParmDecl>(
+        CD->getTemplateParameters()->getParam(0));
+
+    // this fake TemplateTypeParmDecl is used to construct a template argument
+    // that will be used to construct the ImplicitConceptSpecializationDecl
+    TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create(
+        Context,                          // AST context
+        Context.getTranslationUnitDecl(), // DeclContext
+        SourceLocation(), SourceLocation(),
+        /*depth=*/0,                // Depth in the template parameter list
+        /*position=*/0,             // Position in the template parameter list
+        /*id=*/nullptr,             // Identifier for 'T'
+        /*Typename=*/true,          // Indicates this is a 'typename' or 'class'
+        /*ParameterPack=*/false,    // Not a parameter pack
+        /*HasTypeConstraint=*/false // Has no type constraint
+    );
+
+    T->setDeclContext(DC);
+    T->setReferenced();
+
+    QualType ConceptTType = Context.getTypeDeclType(ConceptTTPD);
+
+    // this is the 2nd template argument node in the AST above
+    TemplateArgument ConceptTA = TemplateArgument(ConceptTType);
+
+    QualType CSETType = Context.getTypeDeclType(T);
+
+    // this is the 1st template argument node in the AST above
+    TemplateArgument CSETA = TemplateArgument(CSETType);
+
+    ImplicitConceptSpecializationDecl *ImplicitCSEDecl =
+        ImplicitConceptSpecializationDecl::Create(
+            Context, Builder.Record->getDeclContext(), Loc, {CSETA});
+
+    // Constraint satisfaction is used to construct the
+    // ConceptSpecailizationExpr, and represents the 2nd Template Argument,
+    // located at the bottom of the sample AST above.
+    const ConstraintSatisfaction CS(CD, {ConceptTA});
+    TemplateArgumentLoc TAL = S.getTrivialTemplateArgumentLoc(
+        ConceptTA, QualType(), SourceLocation());
+
+    TALI.addArgument(TAL);
+    const ASTTemplateArgumentListInfo *ATALI =
+        ASTTemplateArgumentListInfo::Create(Context, TALI);
+
+    // In the concept reference, ATALI is what adds the extra
+    // TemplateArgument node underneath CSE
+    ConceptReference *CR =
+        ConceptReference::Create(Context, NNSLoc, Loc, DNI, CD, CD, ATALI);
+
+    ConceptSpecializationExpr *CSE =
+        ConceptSpecializationExpr::Create(Context, CR, ImplicitCSEDecl, &CS);
+
+    return CSE;
+  }
+
+  BuiltinTypeDeclBuilder &finalizeTemplateArgs(ConceptDecl *CD = nullptr) {
+    if (Params.empty())
+      return Builder;
+    ConceptSpecializationExpr *CSE =
+        CD ? getConceptSpecializationExpr(S, CD) : nullptr;
+
+    auto *ParamList = TemplateParameterList::Create(S.Context, SourceLocation(),
+                                                    SourceLocation(), Params,
+                                                    SourceLocation(), CSE);
+    Builder.Template = ClassTemplateDecl::Create(
+        S.Context, Builder.Record->getDeclContext(), SourceLocation(),
+        DeclarationName(Builder.Record->getIdentifier()), ParamList,
+        Builder.Record);
+
+    Builder.Record->setDescribedClassTemplate(Builder.Template);
+    Builder.Template->setImplicit(true);
+    Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());
+
+    // NOTE: setPreviousDecl before addDecl so new decl replace old decl when
+    // make visible.
+    Builder.Template->setPreviousDecl(Builder.PrevTemplate);
+    Builder.Record->getDeclContext()->addDecl(Builder.Template);
+    Params.clear();
+
+    QualType T = Builder.Template->getInjectedClassNameSpecialization();
+    T = S.Context.getInjectedClassNameType(Builder.Record, T);
+
+    return Builder;
+  }
+};
+} // namespace
+
+TemplateParameterListBuilder
+BuiltinTypeDeclBuilder::addTemplateArgumentList(Sema &S) {
+  return TemplateParameterListBuilder(S, *this);
+}
+
+BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addSimpleTemplateParams(
+    Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD = nullptr) {
+  TemplateParameterListBuilder Builder = this->addTemplateArgumentList(S);
+  for (StringRef Name : Names)
+    Builder.addTypeParameter(Name);
+
+  return Builder.finalizeTemplateArgs(CD);
+}
+
+HLSLExternalSemaSource::~HLSLExternalSemaSource() {}
+
+void HLSLExternalSemaSource::InitializeSema(Sema &S) {
+  SemaPtr = &S;
+  ASTContext &AST = SemaPtr->getASTContext();
+  // If the translation unit has external storage force external decls to load.
+  if (AST.getTranslationUnitDecl()->hasExternalLexicalStorage())
+    (void)AST.getTranslationUnitDecl()->decls_begin();
+
+  IdentifierInfo &HLSL = AST.Idents.get("hlsl", tok::TokenKind::identifier);
+  LookupResult Result(S, &HLSL, SourceLocation(), Sema::LookupNamespaceName);
+  NamespaceDecl *PrevDecl = nullptr;
+  if (S.LookupQualifiedName(Result, AST.getTranslationUnitDecl()))
+    PrevDecl = Result.getAsSingle<NamespaceDecl>();
+  HLSLNamespace = NamespaceDecl::Create(
+      AST, AST.getTranslationUnitDecl(), /*Inline=*/false, SourceLocation(),
+      SourceLocation(), &HLSL, PrevDecl, /*Nested=*/false);
+  HLSLNamespace->setImplicit(true);
+  HLSLNamespace->setHasExternalLexicalStorage();
+  AST.getTranslationUnitDecl()->addDecl(HLSLNamespace);
+
+  // Force external decls in the HLSL namespace to load from the PCH.
+  (void)HLSLNamespace->getCanonicalDecl()->decls_begin();
+  defineTrivialHLSLTypes();
+  defineHLSLTypesWithForwardDeclarations();
+
+  // This adds a `using namespace hlsl` directive. In DXC, we don't put HLSL's
+  // built in types inside a namespace, but we are planning to change that in
+  // the near future. In order to be source compatible older versions of HLSL
+  // will need to implicitly use the hlsl namespace. For now in clang everything
+  // will get added to the namespace, and we can remove the using directive for
+  // future language versions to match HLSL's evolution.
+  auto *UsingDecl = UsingDirectiveDecl::Create(
+      AST, AST.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
+      NestedNameSpecifierLoc(), SourceLocation(), HLSLNamespace,
+      AST.getTranslationUnitDecl());
+
+  AST.getTranslationUnitDecl()->addDecl(UsingDecl);
+}
+
+void HLSLExternalSemaSource::defineHLSLVectorAlias() {
+  ASTContext &AST = SemaPtr->getASTContext();
+
+  llvm::SmallVector<NamedDecl *> TemplateParams;
+
+  auto *TypeParam = TemplateTypeParmDecl::Create(
+      AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 0,
+      &AST.Idents.get("element", tok::TokenKind::identifier), false, false);
+  TypeParam->setDefaultArgument(
+      AST, SemaPtr->getTrivialTemplateArgumentLoc(
+               TemplateArgument(AST.FloatTy), QualType(), SourceLocation()));
+
+  TemplateParams.emplace_back(TypeParam);
+
+  auto *SizeParam = NonTypeTemplateParmDecl::Create(
+      AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 1,
+      &AST.Idents.get("element_count", tok::TokenKind::identifier), AST.IntTy,
+      false, AST.getTrivialTypeSourceInfo(AST.IntTy));
+  llvm::APInt Val(AST.getIntWidth(AST.IntTy), 4);
+  TemplateArgument Default(AST, llvm::APSInt(std::move(Val)), AST.IntTy,
+                           /*IsDefaulted=*/true);
+  SizeParam->setDefaultArgument(
+      AST, SemaPtr->getTrivialTemplateArgumentLoc(Default, AST.IntTy,
+                                                  SourceLocation(), SizeParam));
+  TemplateParams.emplace_back(SizeParam);
+
+  auto *ParamList =
+      TemplateParameterList::Create(AST, SourceLocation(), SourceLocation(),
+                                    TemplateParams, SourceLocation(), nullptr);
+
+  IdentifierInfo &II = AST.Idents.get("vector", tok::TokenKind::identifier);
+
+  QualType AliasType = AST.getDependentSizedExtVectorType(
+      AST.getTemplateTypeParmType(0, 0, false, TypeParam),
+      DeclRefExpr::Create(
+          AST, NestedNameSpecifierLoc(), SourceLocation(), SizeParam, false,
+          DeclarationNameInfo(SizeParam->getDeclName(), SourceLocation()),
+          AST.IntTy, VK_LValue),
+      SourceLocation());
+
+  auto *Record = TypeAliasDecl::Create(AST, HLSLNamespace, SourceLocation(),
+                                       SourceLocation(), &II,
+                                       AST.getTrivialTypeSourceInfo(AliasType));
+  Record->setImplicit(true);
+
+  auto *Template =
+      TypeAliasTemplateDecl::Create(AST, HLSLNamespace, SourceLocation(),
+                                    Record->getIdentifier(), ParamList, Record);
+
+  Record->setDescribedAliasTemplate(Template);
+  Template->setImplicit(true);
+  Template->setLexicalDeclContext(Record->getDeclContext());
+  HLSLNamespace->addDecl(Template);
+}
+
+void HLSLExternalSemaSource::defineTrivialHLSLTypes() {
+  defineHLSLVectorAlias();
+}
+
+/// Set up common members and attributes for buffer types
+static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
+                                              ResourceClass RC, ResourceKind RK,
+                                              bool IsROV, bool RawBuffer) {
+  return BuiltinTypeDeclBuilder(Decl)
+      .addHandleMember(S, RC, RK, IsROV, RawBuffer)
+      .addDefaultHandleConstructor(S, RC);
+}
+
+BinaryOperator *getSizeOfLEQ16Expr(ASTContext &Context, SourceLocation NameLoc,
+                                   TemplateTypeParmDecl *T) {
+  // Obtain the QualType for 'unsigned long'
+  QualType UnsignedLongType = Context.UnsignedLongTy;
+
+  // Create a QualType that points to this TemplateTypeParmDecl
+  QualType TType = Context.getTypeDeclType(T);
+
+  // Create a TypeSourceInfo for the template type parameter 'T'
+  TypeSourceInfo *TTypeSourceInfo =
+      Context.getTrivialTypeSourceInfo(TType, NameLoc);
+
+  UnaryExprOrTypeTraitExpr *sizeOfExpr = new (Context) UnaryExprOrTypeTraitExpr(
+      clang::UETT_SizeOf, TTypeSourceInfo, UnsignedLongType, NameLoc, NameLoc);
+
+  // Create an IntegerLiteral for the value '16' with size type
+  QualType SizeType = Context.getSizeType();
+  llvm::APInt SizeValue = llvm::APInt(Context.getTypeSize(SizeType), 16);
+  IntegerLiteral *SizeLiteral =
+      new (Context) IntegerLiteral(Context, SizeValue, SizeType, NameLoc);
+
+  QualType BoolTy = Context.BoolTy;
+
+  BinaryOperator *binaryOperator =
+      BinaryOperator::Create(Context, sizeOfExpr, // Left-hand side expression
+                             SizeLiteral,         // Right-hand side expression
+                             clang::BO_LE,        // Binary operator kind (<=)
+                             BoolTy,              // Result type (bool)
+                             clang::VK_LValue,    // Value kind
+                             clang::OK_Ordinary,  // Object kind
+                             NameLoc,             // Source location of operator
+                             FPOptionsOverride());
+
+  return binaryOperator;
+}
+
+Expr *getTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
+                                   TemplateTypeParmDecl *T) {
+  ASTContext &Context = S.getASTContext();
+
+  // first get the "sizeof(T) <= 16" expression, as a binary operator
+  BinaryOperator *SizeOfLEQ16 = getSizeOfLEQ16Expr(Context, NameLoc, T);
+  // TODO: add the '__builtin_hlsl_is_line_vector_layout_compatible' builtin
+  // and return a binary operator that evaluates the builtin on the given
+  // template type parameter 'T'
+  return SizeOfLEQ16;
+}
+
+ConceptDecl *getTypedBufferConceptDecl(Sema &S) {
+  DeclContext *DC = S.CurContext;
+  ASTContext &Context = S.getASTContext();
+  SourceLocation DeclLoc = SourceLocation();
+
+  IdentifierInfo &IsValidLineVectorII =
+      Context.Idents.get("is_valid_line_vector");
+  IdentifierInfo &ElementTypeII = Context.Idents.get("element_type");
+  TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create(
+      Context, Context.getTranslationUnitDecl(), DeclLoc, DeclLoc,
+      /*depth=*/0,
+      /*position=*/0,
+      /*id=*/&ElementTypeII,
+      /*Typename=*/true,
+      /*ParameterPack=*/false);
+
+  T->setDeclContext(DC);
+  T->setReferenced();
+
+  // Create and Attach Template Parameter List to ConceptDecl
+  TemplateParameterList *ConceptParams = TemplateParameterList::Create(
+      Context, DeclLoc, DeclLoc, {T}, DeclLoc, nullptr);
+
+  DeclarationName DeclName = DeclarationName(&IsValidLineVectorII);
+  Expr *ConstraintExpr = getTypedBufferConstraintExpr(S, DeclLoc, T);
+
+  // Create a ConceptDecl
+  ConceptDecl *CD =
+      ConceptDecl::Create(Context, Context.getTranslationUnitDecl(), DeclLoc,
+                          DeclName, ConceptParams, ConstraintExpr);
+
+  // Attach the template parameter list to the ConceptDecl
+  CD->setTemplateParameters(ConceptParams);
+
+  // Add the concept declaration to the Translation Unit Decl
+  Context.getTranslationUnitDecl()->addDecl(CD);
+
+  return CD;
+}
+
+void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
+  CXXRecordDecl *Decl;
+  ConceptDecl *CD = getTypedBufferConceptDecl(*SemaPtr);
+
+  Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer")
+             .addSimpleTemplateParams(*SemaPtr, {"element_type"}, CD)
+             .Record;
+
+  onCompletion(Decl, [this](CXXRecordDecl *Decl) {
+    setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
+                    ResourceKind::TypedBuffer,
+                    /*IsROV=*/false, /*RawBuffer=*/false)
+        .addArraySubscriptOperators()
+        .completeDefinition();
+  });
+
+  Decl =
+      BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedBuffer")
+          .addSimpleTemplateParams(*SemaPtr, {"element_type"})
+          .Record;
+  onCompletion(Decl, [this](CXXRecordDecl *Decl) {
+    setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
+                    ResourceKind::TypedBuffer, /*IsROV=*/true,
+                    /*RawBuffer=*/false)
+        .addArraySubscriptOperators()
+        .completeDefinition();
+  });
+
+  Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "StructuredBuffer")
+             .addSimpleTemplateParams(*SemaPtr, {"element_type"})
+             .Record;
+  onCompletion(Decl, [this](CXXRecordDecl *Decl) {
+    setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
+                    ResourceKind::TypedBuffer, /*IsROV=*/false,
+                    /*RawBuffer=*/true)
+        .addArraySubscriptOperators()
+        .completeDefinition();
+  });
+}
+
+void HLSLExternalSemaSource::onCompletion(CXXRecordDecl *Record,
+                                          CompletionFunction Fn) {
+  Completions.insert(std::make_pair(Record->getCanonicalDecl(), Fn));
+}
+
+void HLSLExternalSemaSource::CompleteType(TagDecl *Tag) {
+  if (!isa<CXXRecordDecl>(Tag))
+    return;
+  auto Record = cast<CXXRecordDecl>(Tag);
+
+  // If this is a specialization, we need to get the underlying templated
+  // declaration and complete that.
+  if (auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(Record))
+    Record = TDecl->getSpecializedTemplate()->getTemplatedDecl();
+  Record = Record->getCanonicalDecl();
+  auto It = Completions.find(Record);
+  if (It == Completions.end())
+    return;
+  It->second(Record);
+}



More information about the cfe-commits mailing list