[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 11:56:01 PDT 2024
https://github.com/bob80905 created https://github.com/llvm/llvm-project/pull/112600
This PR is step one on the journey to implement resource element type validation via C++20 concepts. The PR sets up the infrastructure for injecting implicit concept decls / concept specialization expressions into the AST, which will then be evaluated after template arguments are instantiated. This is not meant to be a complete implementation of the desired validation for HLSL,
there are a couple of missing elements:
1. We need the __builtin_hlsl_is_line_vector_layout_compatible builtin to be implemented.
2. We need other constraints, like is_intangible, and verifying that the template type is not a bool or enum
3. We need to put the first 2 points together, and construct a finalized constraint expression, which should differ between typed and raw buffers
This is just an initial PR that puts some of the core infrastructure in place.
>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/7] 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/7] 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/7] 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/7] 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/7] 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/7] 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/7] 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();
More information about the cfe-commits
mailing list