@@ -864,6 +864,10 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
864864 .addDefaultHandleConstructor ();
865865}
866866
867+ // This function is responsible for constructing the constraint expression for
868+ // this concept:
869+ // template<typename T> concept is_typed_resource_element_compatible =
870+ // __is_typed_resource_element_compatible<T>;
867871static Expr *constructTypedBufferConstraintExpr (Sema &S, SourceLocation NameLoc,
868872 TemplateTypeParmDecl *T) {
869873 ASTContext &Context = S.getASTContext ();
@@ -885,8 +889,58 @@ static Expr *constructTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
885889 return TypedResExpr;
886890}
887891
888- static ConceptDecl *constructTypedBufferConceptDecl (Sema &S,
889- NamespaceDecl *NSD) {
892+ // This function is responsible for constructing the constraint expression for
893+ // this concept:
894+ // template<typename T> concept is_structured_resource_element_compatible =
895+ // !__is_intangible<T> && sizeof(T) >= 1;
896+ static Expr *constructStructuredBufferConstraintExpr (Sema &S,
897+ SourceLocation NameLoc,
898+ TemplateTypeParmDecl *T) {
899+ ASTContext &Context = S.getASTContext ();
900+
901+ // Obtain the QualType for 'bool'
902+ QualType BoolTy = Context.BoolTy ;
903+
904+ // Create a QualType that points to this TemplateTypeParmDecl
905+ QualType TType = Context.getTypeDeclType (T);
906+
907+ // Create a TypeSourceInfo for the template type parameter 'T'
908+ TypeSourceInfo *TTypeSourceInfo =
909+ Context.getTrivialTypeSourceInfo (TType, NameLoc);
910+
911+ TypeTraitExpr *IsIntangibleExpr =
912+ TypeTraitExpr::Create (Context, BoolTy, NameLoc, UTT_IsIntangibleType,
913+ {TTypeSourceInfo}, NameLoc, true );
914+
915+ // negate IsIntangibleExpr
916+ UnaryOperator *NotIntangibleExpr = UnaryOperator::Create (
917+ Context, IsIntangibleExpr, UO_LNot, BoolTy, VK_LValue, OK_Ordinary,
918+ NameLoc, false , FPOptionsOverride ());
919+
920+ // element types also may not be of 0 size
921+ UnaryExprOrTypeTraitExpr *SizeOfExpr = new (Context) UnaryExprOrTypeTraitExpr (
922+ UETT_SizeOf, TTypeSourceInfo, BoolTy, NameLoc, NameLoc);
923+
924+ // Create a BinaryOperator that checks if the size of the type is not equal to
925+ // 1 Empty structs have a size of 1 in HLSL, so we need to check for that
926+ IntegerLiteral *rhs = IntegerLiteral::Create (
927+ Context, llvm::APInt (Context.getTypeSize (Context.getSizeType ()), 1 , true ),
928+ Context.getSizeType (), NameLoc);
929+
930+ BinaryOperator *SizeGEQOneExpr =
931+ BinaryOperator::Create (Context, SizeOfExpr, rhs, BO_GE, BoolTy, VK_LValue,
932+ OK_Ordinary, NameLoc, FPOptionsOverride ());
933+
934+ // Combine the two constraints
935+ BinaryOperator *CombinedExpr = BinaryOperator::Create (
936+ Context, NotIntangibleExpr, SizeGEQOneExpr, BO_LAnd, BoolTy, VK_LValue,
937+ OK_Ordinary, NameLoc, FPOptionsOverride ());
938+
939+ return CombinedExpr;
940+ }
941+
942+ static ConceptDecl *constructBufferConceptDecl (Sema &S, NamespaceDecl *NSD,
943+ bool isTypedBuffer) {
890944 ASTContext &Context = S.getASTContext ();
891945 DeclContext *DC = NSD->getDeclContext ();
892946 SourceLocation DeclLoc = SourceLocation ();
@@ -907,9 +961,18 @@ static ConceptDecl *constructTypedBufferConceptDecl(Sema &S,
907961 TemplateParameterList *ConceptParams = TemplateParameterList::Create (
908962 Context, DeclLoc, DeclLoc, {T}, DeclLoc, nullptr );
909963
910- DeclarationName DeclName = DeclarationName (
911- &Context.Idents .get (" __is_typed_resource_element_compatible" ));
912- Expr *ConstraintExpr = constructTypedBufferConstraintExpr (S, DeclLoc, T);
964+ DeclarationName DeclName;
965+ Expr *ConstraintExpr = nullptr ;
966+
967+ if (isTypedBuffer) {
968+ DeclName = DeclarationName (
969+ &Context.Idents .get (" __is_typed_resource_element_compatible" ));
970+ ConstraintExpr = constructTypedBufferConstraintExpr (S, DeclLoc, T);
971+ } else {
972+ DeclName = DeclarationName (
973+ &Context.Idents .get (" __is_structured_resource_element_compatible" ));
974+ ConstraintExpr = constructStructuredBufferConstraintExpr (S, DeclLoc, T);
975+ }
913976
914977 // Create a ConceptDecl
915978 ConceptDecl *CD =
@@ -927,8 +990,10 @@ static ConceptDecl *constructTypedBufferConceptDecl(Sema &S,
927990
928991void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations () {
929992 CXXRecordDecl *Decl;
930- ConceptDecl *TypedBufferConcept =
931- constructTypedBufferConceptDecl (*SemaPtr, HLSLNamespace);
993+ ConceptDecl *TypedBufferConcept = constructBufferConceptDecl (
994+ *SemaPtr, HLSLNamespace, /* isTypedBuffer*/ true );
995+ ConceptDecl *StructuredBufferConcept = constructBufferConceptDecl (
996+ *SemaPtr, HLSLNamespace, /* isTypedBuffer*/ false );
932997 Decl = BuiltinTypeDeclBuilder (*SemaPtr, HLSLNamespace, " RWBuffer" )
933998 .addSimpleTemplateParams ({" element_type" }, TypedBufferConcept)
934999 .finalizeForwardDeclaration ();
@@ -944,7 +1009,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
9441009
9451010 Decl =
9461011 BuiltinTypeDeclBuilder (*SemaPtr, HLSLNamespace, " RasterizerOrderedBuffer" )
947- .addSimpleTemplateParams ({" element_type" })
1012+ .addSimpleTemplateParams ({" element_type" }, StructuredBufferConcept )
9481013 .finalizeForwardDeclaration ();
9491014 onCompletion (Decl, [this ](CXXRecordDecl *Decl) {
9501015 setupBufferType (Decl, *SemaPtr, ResourceClass::UAV,
@@ -956,7 +1021,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
9561021 });
9571022
9581023 Decl = BuiltinTypeDeclBuilder (*SemaPtr, HLSLNamespace, " StructuredBuffer" )
959- .addSimpleTemplateParams ({" element_type" })
1024+ .addSimpleTemplateParams ({" element_type" }, StructuredBufferConcept )
9601025 .finalizeForwardDeclaration ();
9611026 onCompletion (Decl, [this ](CXXRecordDecl *Decl) {
9621027 setupBufferType (Decl, *SemaPtr, ResourceClass::SRV, ResourceKind::RawBuffer,
@@ -966,7 +1031,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
9661031 });
9671032
9681033 Decl = BuiltinTypeDeclBuilder (*SemaPtr, HLSLNamespace, " RWStructuredBuffer" )
969- .addSimpleTemplateParams ({" element_type" })
1034+ .addSimpleTemplateParams ({" element_type" }, StructuredBufferConcept )
9701035 .finalizeForwardDeclaration ();
9711036 onCompletion (Decl, [this ](CXXRecordDecl *Decl) {
9721037 setupBufferType (Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
@@ -979,7 +1044,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
9791044
9801045 Decl =
9811046 BuiltinTypeDeclBuilder (*SemaPtr, HLSLNamespace, " AppendStructuredBuffer" )
982- .addSimpleTemplateParams ({" element_type" })
1047+ .addSimpleTemplateParams ({" element_type" }, StructuredBufferConcept )
9831048 .finalizeForwardDeclaration ();
9841049 onCompletion (Decl, [this ](CXXRecordDecl *Decl) {
9851050 setupBufferType (Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
@@ -990,7 +1055,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
9901055
9911056 Decl =
9921057 BuiltinTypeDeclBuilder (*SemaPtr, HLSLNamespace, " ConsumeStructuredBuffer" )
993- .addSimpleTemplateParams ({" element_type" })
1058+ .addSimpleTemplateParams ({" element_type" }, StructuredBufferConcept )
9941059 .finalizeForwardDeclaration ();
9951060 onCompletion (Decl, [this ](CXXRecordDecl *Decl) {
9961061 setupBufferType (Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
@@ -1001,7 +1066,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
10011066
10021067 Decl = BuiltinTypeDeclBuilder (*SemaPtr, HLSLNamespace,
10031068 " RasterizerOrderedStructuredBuffer" )
1004- .addSimpleTemplateParams ({" element_type" })
1069+ .addSimpleTemplateParams ({" element_type" }, StructuredBufferConcept )
10051070 .finalizeForwardDeclaration ();
10061071 onCompletion (Decl, [this ](CXXRecordDecl *Decl) {
10071072 setupBufferType (Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
0 commit comments