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

Joshua Batista via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 16 12:49:47 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 1/8] 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 2/8] 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 3/8] 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 4/8] 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 5/8] 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 6/8] 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 7/8] 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 8/8] 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();
 }



More information about the cfe-commits mailing list