Skip to content

Commit 7c58efd

Browse files
committed
add tests for rwbuffer concept validation
1 parent 554e3c6 commit 7c58efd

File tree

5 files changed

+348
-49
lines changed

5 files changed

+348
-49
lines changed

asa1qqqq

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
2+
index 6c93afdfaa81..e36bfeab7b49 100644
3+
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
4+
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
5+
@@ -330,7 +330,7 @@ struct TemplateParameterListBuilder {
6+
// matches the CSE that is constructed when parsing the below C++ code:
7+
//
8+
// template<typename T>
9+
- // concept is_typed_resource_element_compatible = sizeof(T) <= 16;
10+
+ // concept is_typed_resource_element_compatible = __builtin_hlsl_typed_resource_element_compatible<T> && !__builtin_hlsl_is_intangible<T>
11+
// template<typename element_type> requires
12+
// is_typed_resource_element_compatible<element_type>
13+
// struct RWBuffer {
14+
@@ -568,11 +568,11 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
15+
.addDefaultHandleConstructor(S);
16+
}
17+

18+
-BinaryOperator *constructSizeOfLEQ16Expr(ASTContext &Context,
19+
+BinaryOperator *constructTypedResourceConstraintExpr(ASTContext &Context,
20+
SourceLocation NameLoc,
21+
TemplateTypeParmDecl *T) {
22+
// Obtain the QualType for 'unsigned long'
23+
- QualType UnsignedLongType = Context.UnsignedLongTy;
24+
+ QualType BoolTy = Context.BoolTy;
25+

26+
// Create a QualType that points to this TemplateTypeParmDecl
27+
QualType TType = Context.getTypeDeclType(T);
28+
@@ -581,21 +581,22 @@ BinaryOperator *constructSizeOfLEQ16Expr(ASTContext &Context,
29+
TypeSourceInfo *TTypeSourceInfo =
30+
Context.getTrivialTypeSourceInfo(TType, NameLoc);
31+

32+
- UnaryExprOrTypeTraitExpr *sizeOfExpr = new (Context) UnaryExprOrTypeTraitExpr(
33+
- UETT_SizeOf, TTypeSourceInfo, UnsignedLongType, NameLoc, NameLoc);
34+
+ TypeTraitExpr *TypedResExpr = TypeTraitExpr::Create(
35+
+ Context, BoolTy, NameLoc, UTT_IsTypedResourceElementCompatible,
36+
+ {TTypeSourceInfo}, NameLoc, true);
37+

38+
- // Create an IntegerLiteral for the value '16' with size type
39+
- QualType SizeType = Context.getSizeType();
40+
- llvm::APInt SizeValue = llvm::APInt(Context.getTypeSize(SizeType), 16);
41+
- IntegerLiteral *SizeLiteral =
42+
- new (Context) IntegerLiteral(Context, SizeValue, SizeType, NameLoc);
43+
+ TypeTraitExpr *IsIntangibleExpr =
44+
+ TypeTraitExpr::Create(Context, BoolTy, NameLoc, UTT_IsIntangibleType,
45+
+ {TTypeSourceInfo}, NameLoc, true);
46+

47+
- QualType BoolTy = Context.BoolTy;
48+
+ UnaryOperator *NotIntangibleExpr = UnaryOperator::Create(
49+
+ Context, IsIntangibleExpr, UO_Not, BoolTy, VK_LValue, OK_Ordinary,
50+
+ NameLoc, false, FPOptionsOverride());
51+

52+
BinaryOperator *binaryOperator =
53+
- BinaryOperator::Create(Context, sizeOfExpr, // Left-hand side expression
54+
- SizeLiteral, // Right-hand side expression
55+
- BO_LE, // Binary operator kind (<=)
56+
+ BinaryOperator::Create(Context, TypedResExpr, // Left-hand side expression
57+
+ NotIntangibleExpr, // Right-hand side expression
58+
+ BO_LAnd, // Binary operator kind (&&)
59+
BoolTy, // Result type (bool)
60+
VK_LValue, // Value kind
61+
OK_Ordinary, // Object kind
62+
@@ -609,13 +610,10 @@ Expr *constructTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
63+
TemplateTypeParmDecl *T) {
64+
ASTContext &Context = S.getASTContext();
65+

66+
- // first get the "sizeof(T) <= 16" expression, as a binary operator
67+
- BinaryOperator *SizeOfLEQ16 = constructSizeOfLEQ16Expr(Context, NameLoc, T);
68+
- // TODO: add the 'builtin_hlsl_is_typed_resource_element_compatible' builtin
69+
- // and return a binary operator that evaluates the builtin on the given
70+
- // template type parameter 'T'.
71+
- // Defined in issue https://github.com/llvm/llvm-project/issues/113223
72+
- return SizeOfLEQ16;
73+
+ BinaryOperator *TypedResourceConstraintExpr =
74+
+ constructTypedResourceConstraintExpr(Context, NameLoc, T);
75+
+
76+
+ return TypedResourceConstraintExpr;
77+
}
78+

79+
ConceptDecl *constructTypedBufferConceptDecl(Sema &S, NamespaceDecl *NSD) {
80+
diff --git a/clang/test/AST/HLSL/is_typed_resource_element_compatible_concept.hlsl b/clang/test/AST/HLSL/is_typed_resource_element_compatible_concept.hlsl
81+
index 414ed6eb8212..362ce96e808f 100644
82+
--- a/clang/test/AST/HLSL/is_typed_resource_element_compatible_concept.hlsl
83+
+++ b/clang/test/AST/HLSL/is_typed_resource_element_compatible_concept.hlsl
84+
@@ -2,9 +2,13 @@
85+

86+
// CHECK: ConceptDecl 0x{{[0-9a-f]+}} <<invalid sloc>> <invalid sloc> __is_typed_resource_element_compatible
87+
// CHECK: |-TemplateTypeParmDecl 0x{{[0-9a-f]+}} <<invalid sloc>> <invalid sloc> referenced typename depth 0 index 0 element_type
88+
-// CHECK: `-BinaryOperator 0x{{[0-9a-f]+}} <<invalid sloc>> 'bool' lvalue '<='
89+
-// CHECK: |-UnaryExprOrTypeTraitExpr 0x{{[0-9a-f]+}} <<invalid sloc>> 'unsigned long' sizeof 'element_type'
90+
-// CHECK: `-IntegerLiteral 0x{{[0-9a-f]+}} <<invalid sloc>> 'unsigned long' 16
91+
-
92+
+// CHECK: `-BinaryOperator 0x{{[0-9a-f]+}} <<invalid sloc>> 'bool' lvalue '&&'
93+
+// CHECK: |-TypeTraitExpr 0x{{[0-9a-f]+}} <<invalid sloc>> 'bool' __builtin_hlsl_is_typed_resource_element_compatible
94+
+// CHECK: `-TemplateTypeParmType 0x{{[0-9a-f]+}} 'element_type' dependent depth 0 index 0
95+
+// CHECK: `-TemplateTypeParm 0x{{[0-9a-f]+}} 'element_type'
96+
+// CHECK: `-UnaryOperator 0x{{[0-9a-f]+}} <<invalid sloc>> 'bool' lvalue prefix '~' cannot overflow
97+
+// CHECK: `-TypeTraitExpr 0x{{[0-9a-f]+}} <<invalid sloc>> 'bool' __builtin_hlsl_is_intangible
98+
+// CHECK: `-TemplateTypeParmType 0x{{[0-9a-f]+}} 'element_type' dependent depth 0 index 0
99+
+// CHECK: `-TemplateTypeParm 0x{{[0-9a-f]+}} 'element_type'
100+

101+
RWBuffer<float> Buffer;
102+
diff --git a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl
103+
index 438f8021f96a..8d018bacea7f 100644
104+
--- a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl
105+
+++ b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl
106+
@@ -1,16 +1,79 @@
107+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -fsyntax-only -verify %s
108+

109+
typedef vector<float, 3> float3;
110+
+typedef vector<double, 2> double2;
111+
+typedef vector<double, 3> double3;
112+

113+
-RWBuffer<float3> Buffer;
114+

115+
-// expected-error@+2 {{class template 'RWBuffer' requires template arguments}}
116+
-// expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires __is_typed_resource_element_compatible<element_type> class RWBuffer {}}}
117+
-RWBuffer BufferErr1;
118+
+// expected-error@+4 {{constraints not satisfied for class template 'RWBuffer'}}
119+
+// expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires __is_typed_resource_element_compatible<element_type> class RWBuffer}}
120+
+// expected-note@*:* {{because 'hlsl::RWBuffer<int>' does not satisfy '__is_typed_resource_element_compatible'}}
121+
+// expected-note@*:* {{because '__builtin_hlsl_is_typed_resource_element_compatible(hlsl::RWBuffer<int>)' evaluated to false}}
122+
+RWBuffer<RWBuffer<int> > r5;
123+
+
124+
+struct s {
125+
+ int x;
126+
+};
127+
+
128+
+struct Empty {};
129+
+
130+
+template<typename T> struct TemplatedBuffer {
131+
+ T a;
132+
+};
133+
+
134+
+template<typename T> struct TemplatedVector {
135+
+ vector<T, 4> v;
136+
+};
137+
+
138+
+
139+
+// expected-error@+4 {{constraints not satisfied for class template 'RWBuffer'}}
140+
+// expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires __is_typed_resource_element_compatible<element_type> class RWBuffer}}
141+
+// expected-note@*:* {{because 'TemplatedBuffer<int>' does not satisfy '__is_typed_resource_element_compatible'}}
142+
+// expected-note@*:* {{because '__builtin_hlsl_is_typed_resource_element_compatible(TemplatedBuffer<int>)' evaluated to false}}
143+
+RWBuffer<TemplatedBuffer<int> > r8;
144+
+// expected-error@+4 {{constraints not satisfied for class template 'RWBuffer'}}
145+
+// expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires __is_typed_resource_element_compatible<element_type> class RWBuffer}}
146+
+// expected-note@*:* {{because 'TemplatedVector<int>' does not satisfy '__is_typed_resource_element_compatible'}}
147+
+// expected-note@*:* {{because '__builtin_hlsl_is_typed_resource_element_compatible(TemplatedVector<int>)' evaluated to false}}
148+
+RWBuffer<TemplatedVector<int> > r9;
149+
+
150+
+// arrays not allowed
151+
+// expected-error@+3 {{constraints not satisfied for class template 'RWBuffer'}}
152+
+// expected-note@*:* {{because 'half[4]' does not satisfy '__is_typed_resource_element_compatible'}}
153+
+// expected-note@*:* {{because '__builtin_hlsl_is_typed_resource_element_compatible(__fp16[4])' evaluated to false}}
154+
+RWBuffer<half[4]> r10;
155+
+
156+
+typedef vector<int, 8> int8;
157+
+// expected-error@+3 {{constraints not satisfied for class template 'RWBuffer'}}
158+
+// expected-note@*:* {{because 'vector<int, 8>' (vector of 8 'int' values) does not satisfy '__is_typed_resource_element_compatible'}}
159+
+// expected-note@*:* {{because '__builtin_hlsl_is_typed_resource_element_compatible(int __attribute__((ext_vector_type(8))))' evaluated to false}}
160+
+RWBuffer<int8> r11;
161+
+
162+
+typedef int MyInt;
163+
+RWBuffer<MyInt> r12;
164+
+
165+
+// expected-error@+3 {{constraints not satisfied for class template 'RWBuffer'}}
166+
+// expected-note@*:* {{because 'bool' does not satisfy '__is_typed_resource_element_compatible'}}
167+
+// expected-note@*:* {{because '__builtin_hlsl_is_typed_resource_element_compatible(_Bool)' evaluated to false}}
168+
+RWBuffer<bool> r13;
169+
+
170+
+// expected-error@+3 {{constraints not satisfied for class template 'RWBuffer'}}
171+
+// expected-note@*:* {{because 'vector<bool, 2>' (vector of 2 'bool' values) does not satisfy '__is_typed_resource_element_compatible'}}
172+
+// expected-note@*:* {{because '__builtin_hlsl_is_typed_resource_element_compatible(_Bool __attribute__((ext_vector_type(2))))' evaluated to false}}
173+
+RWBuffer<vector<bool, 2>> r14;
174+
+
175+
+enum numbers { one, two, three };
176+
+
177+
+// expected-error@+3 {{constraints not satisfied for class template 'RWBuffer'}}
178+
+// expected-note@*:* {{because 'numbers' does not satisfy '__is_typed_resource_element_compatible'}}
179+
+// expected-note@*:* {{because '__builtin_hlsl_is_typed_resource_element_compatible(numbers)' evaluated to false}}
180+
+RWBuffer<numbers> r15;
181+
+
182+
+// expected-error@+3 {{constraints not satisfied for class template 'RWBuffer'}}
183+
+// expected-note@*:* {{because 'vector<double, 3>' (vector of 3 'double' values) does not satisfy '__is_typed_resource_element_compatible'}}
184+
+// expected-note@*:* {{because '__builtin_hlsl_is_typed_resource_element_compatible(double __attribute__((ext_vector_type(3))))' evaluated to false}}
185+
+RWBuffer<double3> r16;
186+

187+
-// expected-error@+2 {{too few template arguments for class template 'RWBuffer'}}
188+
-// expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires __is_typed_resource_element_compatible<element_type> class RWBuffer {}}}
189+
-RWBuffer<> BufferErr2;
190+

191+
struct threeDoubles {
192+
double a;
193+
@@ -20,7 +83,7 @@ struct threeDoubles {
194+

195+
// expected-error@+3 {{constraints not satisfied for class template 'RWBuffer'}}
196+
// expected-note@*:* {{because 'threeDoubles' does not satisfy '__is_typed_resource_element_compatible'}}
197+
-// expected-note@*:* {{because 'sizeof(threeDoubles) <= 16UL' (24 <= 16) evaluated to false}}
198+
+// expected-note@*:* {{because '__builtin_hlsl_is_typed_resource_element_compatible(threeDoubles)' evaluated to false}}
199+
RWBuffer<threeDoubles> BufferErr3;
200+

201+

202+
diff --git a/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl
203+
index d3d79aa0499e..cb3e9ae7a615 100644
204+
--- a/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl
205+
+++ b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl
206+
@@ -1,9 +1,10 @@
207+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s
208+

209+
// types must be complete
210+
-_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(__hlsl_resource_t), "");
211+
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(__hlsl_resource_t), "");
212+

213+
// expected-note@+1{{forward declaration of 'notComplete'}}
214+
struct notComplete;
215+
// expected-error@+1{{incomplete type 'notComplete' where a complete type is required}}
216+
_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(notComplete), "");
217+
+ 

clang/lib/Sema/HLSLExternalSemaSource.cpp

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,9 @@ struct TemplateParameterListBuilder {
330330
// matches the CSE that is constructed when parsing the below C++ code:
331331
//
332332
// template<typename T>
333-
// concept is_typed_resource_element_compatible = sizeof(T) <= 16;
334-
// template<typename element_type> requires
333+
// concept is_typed_resource_element_compatible =
334+
// __builtin_hlsl_typed_resource_element_compatible<T> &&
335+
// !__builtin_hlsl_is_intangible<T> template<typename element_type> requires
335336
// is_typed_resource_element_compatible<element_type>
336337
// struct RWBuffer {
337338
// element_type Val;
@@ -568,11 +569,12 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
568569
.addDefaultHandleConstructor(S);
569570
}
570571

571-
BinaryOperator *constructSizeOfLEQ16Expr(ASTContext &Context,
572-
SourceLocation NameLoc,
572+
Expr *constructTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
573573
TemplateTypeParmDecl *T) {
574+
ASTContext &Context = S.getASTContext();
575+
574576
// Obtain the QualType for 'unsigned long'
575-
QualType UnsignedLongType = Context.UnsignedLongTy;
577+
QualType BoolTy = Context.BoolTy;
576578

577579
// Create a QualType that points to this TemplateTypeParmDecl
578580
QualType TType = Context.getTypeDeclType(T);
@@ -581,41 +583,29 @@ BinaryOperator *constructSizeOfLEQ16Expr(ASTContext &Context,
581583
TypeSourceInfo *TTypeSourceInfo =
582584
Context.getTrivialTypeSourceInfo(TType, NameLoc);
583585

584-
UnaryExprOrTypeTraitExpr *sizeOfExpr = new (Context) UnaryExprOrTypeTraitExpr(
585-
UETT_SizeOf, TTypeSourceInfo, UnsignedLongType, NameLoc, NameLoc);
586-
587-
// Create an IntegerLiteral for the value '16' with size type
588-
QualType SizeType = Context.getSizeType();
589-
llvm::APInt SizeValue = llvm::APInt(Context.getTypeSize(SizeType), 16);
590-
IntegerLiteral *SizeLiteral =
591-
new (Context) IntegerLiteral(Context, SizeValue, SizeType, NameLoc);
592-
593-
QualType BoolTy = Context.BoolTy;
594-
595-
BinaryOperator *binaryOperator =
596-
BinaryOperator::Create(Context, sizeOfExpr, // Left-hand side expression
597-
SizeLiteral, // Right-hand side expression
598-
BO_LE, // Binary operator kind (<=)
599-
BoolTy, // Result type (bool)
600-
VK_LValue, // Value kind
601-
OK_Ordinary, // Object kind
602-
NameLoc, // Source location of operator
586+
TypeTraitExpr *TypedResExpr = TypeTraitExpr::Create(
587+
Context, BoolTy, NameLoc, UTT_IsTypedResourceElementCompatible,
588+
{TTypeSourceInfo}, NameLoc, true);
589+
590+
TypeTraitExpr *IsIntangibleExpr =
591+
TypeTraitExpr::Create(Context, BoolTy, NameLoc, UTT_IsIntangibleType,
592+
{TTypeSourceInfo}, NameLoc, true);
593+
594+
UnaryOperator *NotIntangibleExpr = UnaryOperator::Create(
595+
Context, IsIntangibleExpr, UO_Not, BoolTy, VK_LValue, OK_Ordinary,
596+
NameLoc, false, FPOptionsOverride());
597+
598+
BinaryOperator *TypedResourceConstraintExpr =
599+
BinaryOperator::Create(Context, TypedResExpr, // Left-hand side expression
600+
NotIntangibleExpr, // Right-hand side expression
601+
BO_LAnd, // Binary operator kind (&&)
602+
BoolTy, // Result type (bool)
603+
VK_LValue, // Value kind
604+
OK_Ordinary, // Object kind
605+
NameLoc, // Source location of operator
603606
FPOptionsOverride());
604607

605-
return binaryOperator;
606-
}
607-
608-
Expr *constructTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
609-
TemplateTypeParmDecl *T) {
610-
ASTContext &Context = S.getASTContext();
611-
612-
// first get the "sizeof(T) <= 16" expression, as a binary operator
613-
BinaryOperator *SizeOfLEQ16 = constructSizeOfLEQ16Expr(Context, NameLoc, T);
614-
// TODO: add the 'builtin_hlsl_is_typed_resource_element_compatible' builtin
615-
// and return a binary operator that evaluates the builtin on the given
616-
// template type parameter 'T'.
617-
// Defined in issue https://github.com/llvm/llvm-project/issues/113223
618-
return SizeOfLEQ16;
608+
return TypedResourceConstraintExpr;
619609
}
620610

621611
ConceptDecl *constructTypedBufferConceptDecl(Sema &S, NamespaceDecl *NSD) {

0 commit comments

Comments
 (0)