[clang] [HLSL] Add implicit resource element type concepts to AST (PR #116413)
https://github.com/llvm-beanz commented: I think the way that you're staging these changes is awkward and results in more review time than we strictly need. We're also going to need to re-review a bunch of this code in a wider context in the near future, so I'm not sure I'm comfortable with this approach. In a future change, you're going to introduce a new builtin (`__builtin_hlsl_is_typed_resource_element_compatible`), and a bunch of the code here will go away, and a bunch of the tests will be extended and updated to use that builtin. At that time we'll need to re-review this work. Why not introduce the new builtin first so that this code can be merged in its completed state rather than in an intermediate state? https://github.com/llvm/llvm-project/pull/116413 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Add implicit resource element type concepts to AST (PR #116413)
@@ -323,19 +325,114 @@ struct TemplateParameterListBuilder { return *this; } - BuiltinTypeDeclBuilder &finalizeTemplateArgs() { + // The concept specialization expression (CSE) constructed in + // constructConceptSpecializationExpr is constructed so that it + // matches the CSE that is constructed when parsing the below C++ code: + // + // template + // concept is_typed_resource_element_compatible = sizeof(T) <= 16; bob80905 wrote: The purpose of this change is to just verify concept validation works. A very simple constraint expression is used, size <= 16 bytes. This is tested by inspecting the AST, and seeing the CSE in the AST. It's also verified by running simple tests that fail when size > 16, and pass when <= 16. I wanted to keep things separate because I want the PR to be kept as atomic as possible. This PR accomplishes the single purpose of introducing concept infrastructure and testing concept validation. I intend the next and final PR to finalize the constraint expression, which will involve adding a bunch of tests that test each corner case of the constraint expression. This will also be a sizeable PR, which I figured would be best kept separate. https://github.com/llvm/llvm-project/pull/116413 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Add implicit resource element type concepts to AST (PR #116413)
@@ -323,19 +325,114 @@ struct TemplateParameterListBuilder { return *this; } - BuiltinTypeDeclBuilder &finalizeTemplateArgs() { + // The concept specialization expression (CSE) constructed in + // constructConceptSpecializationExpr is constructed so that it + // matches the CSE that is constructed when parsing the below C++ code: + // + // template + // concept is_typed_resource_element_compatible = sizeof(T) <= 16; llvm-beanz wrote: Sure, it needs to be a vector or a scalar (https://github.com/llvm/wg-hlsl/blob/main/proposals/0011-resource-element-type-validation.md?plain=1#L31). I guess I maybe don't understand why we're breaking this into so many separate changes where the intermediate steps aren't fully testable. https://github.com/llvm/llvm-project/pull/116413 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Add implicit resource element type concepts to AST (PR #116413)
@@ -323,19 +325,114 @@ struct TemplateParameterListBuilder { return *this; } - BuiltinTypeDeclBuilder &finalizeTemplateArgs() { + // The concept specialization expression (CSE) constructed in + // constructConceptSpecializationExpr is constructed so that it + // matches the CSE that is constructed when parsing the below C++ code: + // + // template + // concept is_typed_resource_element_compatible = sizeof(T) <= 16; bob80905 wrote: I don't believe that's absolutely required. For example, one can have `RWBuffer`, where the element type, `float`, is not a vector. If we require vectors, then I would think `RWBuffer` would be invalid, and only things like `RWBuffer` would be accepted. Additionally, this comment block will be changed when the finalized constraint expression is added, since the concept is more complex than just comparing the size to 16 bytes. https://github.com/llvm/llvm-project/pull/116413 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Add implicit resource element type concepts to AST (PR #116413)
@@ -323,19 +325,114 @@ struct TemplateParameterListBuilder { return *this; } - BuiltinTypeDeclBuilder &finalizeTemplateArgs() { + // The concept specialization expression (CSE) constructed in + // constructConceptSpecializationExpr is constructed so that it + // matches the CSE that is constructed when parsing the below C++ code: + // + // template + // concept is_typed_resource_element_compatible = sizeof(T) <= 16; llvm-beanz wrote: Shouldn't this also require that `T` is a vector type? https://github.com/llvm/llvm-project/pull/116413 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Add implicit resource element type concepts to AST (PR #116413)
https://github.com/bob80905 updated https://github.com/llvm/llvm-project/pull/116413 >From 92ccbe72ca95ad2df5a81b76244a8a8d7cedef40 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 15 Nov 2024 09:00:15 -0800 Subject: [PATCH 1/3] update new tests --- clang/lib/Sema/HLSLExternalSemaSource.cpp | 210 +- .../AST/HLSL/AppendStructuredBuffer-AST.hlsl | 4 +- .../AST/HLSL/ConsumeStructuredBuffer-AST.hlsl | 4 +- clang/test/AST/HLSL/RWBuffer-AST.hlsl | 22 +- .../test/AST/HLSL/RWStructuredBuffer-AST.hlsl | 4 +- ...RasterizerOrderedStructuredBuffer-AST.hlsl | 4 +- clang/test/AST/HLSL/StructuredBuffer-AST.hlsl | 4 +- ...d_resource_element_compatible_concept.hlsl | 10 + clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl | 16 +- .../SemaHLSL/BuiltIns/StructuredBuffers.hlsl | 4 +- 10 files changed, 253 insertions(+), 29 deletions(-) create mode 100644 clang/test/AST/HLSL/is_typed_resource_element_compatible_concept.hlsl diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index cac15b974a276e..400d3334f6f0de 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -289,8 +289,9 @@ struct BuiltinTypeDeclBuilder { } TemplateParameterListBuilder addTemplateArgumentList(Sema &S); - BuiltinTypeDeclBuilder &addSimpleTemplateParams(Sema &S, - ArrayRef Names); + BuiltinTypeDeclBuilder & + addSimpleTemplateParams(Sema &S, ArrayRef Names, ConceptDecl *CD); + BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S); }; struct TemplateParameterListBuilder { @@ -312,8 +313,9 @@ struct TemplateParameterListBuilder { S.Context, Builder.Record->getDeclContext(), SourceLocation(), SourceLocation(), /* TemplateDepth */ 0, Position, &S.Context.Idents.get(Name, tok::TokenKind::identifier), -/* Typename */ false, -/* ParameterPack */ false); +/* Typename */ true, +/* ParameterPack */ false, +/* HasTypeConstraint*/ false); if (!DefaultValue.isNull()) Decl->setDefaultArgument( S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(), @@ -323,19 +325,114 @@ struct TemplateParameterListBuilder { return *this; } - BuiltinTypeDeclBuilder &finalizeTemplateArgs() { + /* +The concept specialization expression (CSE) constructed in +constructConceptSpecializationExpr is constructed so that it +matches the CSE that is constructed when parsing the below C++ code: +template +concept is_typed_resource_element_compatible = sizeof(T) <= 16; +template requires +is_typed_resource_element_compatible +struct RWBuffer { +element_type Val; +}; +int fn() { +RWBuffer 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 * + constructConceptSpecializationExpr(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( +CD->getTemplateParameters()->getParam(0)); + +// this TemplateTypeParmDecl is the template for the resource, and is +// used to construct a template argumentthat will be used +// to construct the ImplicitConceptSpecializationDecl +TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create( +Context, // AST context +Builder.Record->getDeclContext(), // 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); + +QualType ConceptTType = Context.getTypeDeclType(ConceptTTPD); + +// this is the 2nd template argument node, on which +// the concept constraint is actually being applied: 'element_type' +TemplateArgument ConceptTA = TemplateArgument(ConceptTType); + +QualType CSETType = Context.getTypeDeclType(T); + +// this is the 1st template argume
[clang] [HLSL] Add implicit resource element type concepts to AST (PR #116413)
@@ -323,19 +325,114 @@ struct TemplateParameterListBuilder { return *this; } - BuiltinTypeDeclBuilder &finalizeTemplateArgs() { + /* +The concept specialization expression (CSE) constructed in llvm-beanz wrote: nit: generally LLVM does per-line comment tokens for blocks (`//` rather than `/* ... */`) https://github.com/llvm/llvm-project/pull/116413 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Add implicit resource element type concepts to AST (PR #116413)
damyanp wrote: @bob80905 - can you associate this with an issue please? https://github.com/llvm/llvm-project/pull/116413 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Add implicit resource element type concepts to AST (PR #116413)
https://github.com/bob80905 edited https://github.com/llvm/llvm-project/pull/116413 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Add implicit resource element type concepts to AST (PR #116413)
https://github.com/damyanp approved this pull request. https://github.com/llvm/llvm-project/pull/116413 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Add implicit resource element type concepts to AST (PR #116413)
llvmbot wrote: @llvm/pr-subscribers-hlsl Author: Joshua Batista (bob80905) Changes 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: We need the __builtin_hlsl_is_typed_resource_element_compatible builtin to be implemented. We need other constraints, like is_intangible 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. This PR is an edit of #112600, so that new tests that were put into main don't fail --- Patch is 25.49 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/116413.diff 10 Files Affected: - (modified) clang/lib/Sema/HLSLExternalSemaSource.cpp (+199-11) - (modified) clang/test/AST/HLSL/AppendStructuredBuffer-AST.hlsl (+2-2) - (modified) clang/test/AST/HLSL/ConsumeStructuredBuffer-AST.hlsl (+2-2) - (modified) clang/test/AST/HLSL/RWBuffer-AST.hlsl (+18-2) - (modified) clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl (+2-2) - (modified) clang/test/AST/HLSL/RasterizerOrderedStructuredBuffer-AST.hlsl (+2-2) - (modified) clang/test/AST/HLSL/StructuredBuffer-AST.hlsl (+2-2) - (added) clang/test/AST/HLSL/is_typed_resource_element_compatible_concept.hlsl (+10) - (modified) clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl (+14-2) - (modified) clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl (+2-2) ``diff diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index cac15b974a276e..400d3334f6f0de 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -289,8 +289,9 @@ struct BuiltinTypeDeclBuilder { } TemplateParameterListBuilder addTemplateArgumentList(Sema &S); - BuiltinTypeDeclBuilder &addSimpleTemplateParams(Sema &S, - ArrayRef Names); + BuiltinTypeDeclBuilder & + addSimpleTemplateParams(Sema &S, ArrayRef Names, ConceptDecl *CD); + BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S); }; struct TemplateParameterListBuilder { @@ -312,8 +313,9 @@ struct TemplateParameterListBuilder { S.Context, Builder.Record->getDeclContext(), SourceLocation(), SourceLocation(), /* TemplateDepth */ 0, Position, &S.Context.Idents.get(Name, tok::TokenKind::identifier), -/* Typename */ false, -/* ParameterPack */ false); +/* Typename */ true, +/* ParameterPack */ false, +/* HasTypeConstraint*/ false); if (!DefaultValue.isNull()) Decl->setDefaultArgument( S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(), @@ -323,19 +325,114 @@ struct TemplateParameterListBuilder { return *this; } - BuiltinTypeDeclBuilder &finalizeTemplateArgs() { + /* +The concept specialization expression (CSE) constructed in +constructConceptSpecializationExpr is constructed so that it +matches the CSE that is constructed when parsing the below C++ code: +template +concept is_typed_resource_element_compatible = sizeof(T) <= 16; +template requires +is_typed_resource_element_compatible +struct RWBuffer { +element_type Val; +}; +int fn() { +RWBuffer 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 * + constructConceptSpecializationExpr(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( +CD->getTemplateParameters()->getParam(0)); + +// this TemplateTypeParmDecl is the template for the resource, and is +// used to construct a template argumentthat will be used +// to construct the ImplicitConceptSpecializationDecl +TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create( +Context, // AST context +Builder.Record->getDeclContext(), // DeclContext +
[clang] [HLSL] Add implicit resource element type concepts to AST (PR #116413)
https://github.com/bob80905 updated https://github.com/llvm/llvm-project/pull/116413 >From 92ccbe72ca95ad2df5a81b76244a8a8d7cedef40 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 15 Nov 2024 09:00:15 -0800 Subject: [PATCH 1/2] update new tests --- clang/lib/Sema/HLSLExternalSemaSource.cpp | 210 +- .../AST/HLSL/AppendStructuredBuffer-AST.hlsl | 4 +- .../AST/HLSL/ConsumeStructuredBuffer-AST.hlsl | 4 +- clang/test/AST/HLSL/RWBuffer-AST.hlsl | 22 +- .../test/AST/HLSL/RWStructuredBuffer-AST.hlsl | 4 +- ...RasterizerOrderedStructuredBuffer-AST.hlsl | 4 +- clang/test/AST/HLSL/StructuredBuffer-AST.hlsl | 4 +- ...d_resource_element_compatible_concept.hlsl | 10 + clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl | 16 +- .../SemaHLSL/BuiltIns/StructuredBuffers.hlsl | 4 +- 10 files changed, 253 insertions(+), 29 deletions(-) create mode 100644 clang/test/AST/HLSL/is_typed_resource_element_compatible_concept.hlsl diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index cac15b974a276e..400d3334f6f0de 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -289,8 +289,9 @@ struct BuiltinTypeDeclBuilder { } TemplateParameterListBuilder addTemplateArgumentList(Sema &S); - BuiltinTypeDeclBuilder &addSimpleTemplateParams(Sema &S, - ArrayRef Names); + BuiltinTypeDeclBuilder & + addSimpleTemplateParams(Sema &S, ArrayRef Names, ConceptDecl *CD); + BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S); }; struct TemplateParameterListBuilder { @@ -312,8 +313,9 @@ struct TemplateParameterListBuilder { S.Context, Builder.Record->getDeclContext(), SourceLocation(), SourceLocation(), /* TemplateDepth */ 0, Position, &S.Context.Idents.get(Name, tok::TokenKind::identifier), -/* Typename */ false, -/* ParameterPack */ false); +/* Typename */ true, +/* ParameterPack */ false, +/* HasTypeConstraint*/ false); if (!DefaultValue.isNull()) Decl->setDefaultArgument( S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(), @@ -323,19 +325,114 @@ struct TemplateParameterListBuilder { return *this; } - BuiltinTypeDeclBuilder &finalizeTemplateArgs() { + /* +The concept specialization expression (CSE) constructed in +constructConceptSpecializationExpr is constructed so that it +matches the CSE that is constructed when parsing the below C++ code: +template +concept is_typed_resource_element_compatible = sizeof(T) <= 16; +template requires +is_typed_resource_element_compatible +struct RWBuffer { +element_type Val; +}; +int fn() { +RWBuffer 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 * + constructConceptSpecializationExpr(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( +CD->getTemplateParameters()->getParam(0)); + +// this TemplateTypeParmDecl is the template for the resource, and is +// used to construct a template argumentthat will be used +// to construct the ImplicitConceptSpecializationDecl +TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create( +Context, // AST context +Builder.Record->getDeclContext(), // 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); + +QualType ConceptTType = Context.getTypeDeclType(ConceptTTPD); + +// this is the 2nd template argument node, on which +// the concept constraint is actually being applied: 'element_type' +TemplateArgument ConceptTA = TemplateArgument(ConceptTType); + +QualType CSETType = Context.getTypeDeclType(T); + +// this is the 1st template argume
[clang] [HLSL] Add implicit resource element type concepts to AST (PR #116413)
https://github.com/bob80905 created https://github.com/llvm/llvm-project/pull/116413 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: We need the __builtin_hlsl_is_typed_resource_element_compatible builtin to be implemented. We need other constraints, like is_intangible 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. This PR is an edit of #112600, so that new tests that were put into main don't fail >From 92ccbe72ca95ad2df5a81b76244a8a8d7cedef40 Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 15 Nov 2024 09:00:15 -0800 Subject: [PATCH 1/2] update new tests --- clang/lib/Sema/HLSLExternalSemaSource.cpp | 210 +- .../AST/HLSL/AppendStructuredBuffer-AST.hlsl | 4 +- .../AST/HLSL/ConsumeStructuredBuffer-AST.hlsl | 4 +- clang/test/AST/HLSL/RWBuffer-AST.hlsl | 22 +- .../test/AST/HLSL/RWStructuredBuffer-AST.hlsl | 4 +- ...RasterizerOrderedStructuredBuffer-AST.hlsl | 4 +- clang/test/AST/HLSL/StructuredBuffer-AST.hlsl | 4 +- ...d_resource_element_compatible_concept.hlsl | 10 + clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl | 16 +- .../SemaHLSL/BuiltIns/StructuredBuffers.hlsl | 4 +- 10 files changed, 253 insertions(+), 29 deletions(-) create mode 100644 clang/test/AST/HLSL/is_typed_resource_element_compatible_concept.hlsl diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index cac15b974a276e..400d3334f6f0de 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -289,8 +289,9 @@ struct BuiltinTypeDeclBuilder { } TemplateParameterListBuilder addTemplateArgumentList(Sema &S); - BuiltinTypeDeclBuilder &addSimpleTemplateParams(Sema &S, - ArrayRef Names); + BuiltinTypeDeclBuilder & + addSimpleTemplateParams(Sema &S, ArrayRef Names, ConceptDecl *CD); + BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S); }; struct TemplateParameterListBuilder { @@ -312,8 +313,9 @@ struct TemplateParameterListBuilder { S.Context, Builder.Record->getDeclContext(), SourceLocation(), SourceLocation(), /* TemplateDepth */ 0, Position, &S.Context.Idents.get(Name, tok::TokenKind::identifier), -/* Typename */ false, -/* ParameterPack */ false); +/* Typename */ true, +/* ParameterPack */ false, +/* HasTypeConstraint*/ false); if (!DefaultValue.isNull()) Decl->setDefaultArgument( S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(), @@ -323,19 +325,114 @@ struct TemplateParameterListBuilder { return *this; } - BuiltinTypeDeclBuilder &finalizeTemplateArgs() { + /* +The concept specialization expression (CSE) constructed in +constructConceptSpecializationExpr is constructed so that it +matches the CSE that is constructed when parsing the below C++ code: +template +concept is_typed_resource_element_compatible = sizeof(T) <= 16; +template requires +is_typed_resource_element_compatible +struct RWBuffer { +element_type Val; +}; +int fn() { +RWBuffer 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 * + constructConceptSpecializationExpr(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( +CD->getTemplateParameters()->getParam(0)); + +// this TemplateTypeParmDecl is the template for the resource, and is +// used to construct a template argumentthat will be used +// to construct the ImplicitConceptSpecializationDecl +TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create( +Context, // AST context +Builder.Record->getDeclContext(), // DeclCon