summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorT. Foley <tfoleyNV@users.noreply.github.com>2021-05-27 15:05:34 -0700
committerGitHub <noreply@github.com>2021-05-27 15:05:34 -0700
commit89faa8a7d9b441b5dd92eec5fcf362eb3f38fa2b (patch)
treec47bfa07f908143493f08f1080c170d0506dc3e9 /tests
parent63dcc7acf4784d95407866730a70f5d37d391b88 (diff)
Fix initializer lists for derived structs (#1862)
If the user has a derived `struct` type: ```hlsl struct Base { int b = 1; } struct Derived : Base { int d = 2; } ``` Then it is still reasonable for them to want to use initializer lists when declaring variables using the `Derived` type: ```hlsl Derived x = {}; Derived y = { 7, 8 }; ``` This change implements two missing pieces of functionality in the Slang compiler to allow this case: * First, when the front-end semantic checks are applied to an initializer list, if the type being initialized is a derived `struct` type it always expects to find initialization arguments for its base type before those for its fields. * Second, when lowering an initializer-list expression from the AST to the IR, the compiler expects the first argument in the list to be the initial value for the base field (if any). This also applies to default-initialization of fields/variables. This change slightly entangles front-end logic with the logic for how struct inheritance is lowered to the IR, but the behavior is unlikely to confuse users who expect C++-like layout. It is worth noting that with this change it should be possible to initialize the base type using either a nested initializer list or flat arguments: ```hlsl struct BigBase { int x; int y; int z; } struct BigDerived : BigBase { int w; } BigDerived a = { {1,2,3}, 4 }; BigDerived b = { 1, 2, 3, 4 }; ``` This behavior should Just Work because of the existing C-like rules for initializer lists where an aggregate can be initialized by either a `{}`-enclosed block or distinct values for its leaf fields.
Diffstat (limited to 'tests')
-rw-r--r--tests/language-feature/inheritance/derived-struct-init-list.slang42
-rw-r--r--tests/language-feature/inheritance/derived-struct-init-list.slang.expected.txt4
2 files changed, 46 insertions, 0 deletions
diff --git a/tests/language-feature/inheritance/derived-struct-init-list.slang b/tests/language-feature/inheritance/derived-struct-init-list.slang
new file mode 100644
index 000000000..edcb685e6
--- /dev/null
+++ b/tests/language-feature/inheritance/derived-struct-init-list.slang
@@ -0,0 +1,42 @@
+// derived-struct-init-list.slang
+
+//TEST(compute):COMPARE_COMPUTE:
+
+// Test that use of an initializer list (especially
+// an empty initializer list) is still possible
+// when using `struct` inheritance.
+
+struct Base
+{
+ int a = 1;
+}
+
+struct Derived : Base
+{
+ int b = 2;
+
+ void write(inout int val) { val = val*0x100 + a*0x10 + b; }
+}
+
+int test(int val)
+{
+ Derived x = {};
+ Derived y = { val, val+1 };
+
+ int result = 1;
+ x.write(result);
+ y.write(result);
+ return result;
+}
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ uint tid = dispatchThreadID.x;
+ int inVal = tid;
+ int outVal = test(inVal);
+ outputBuffer[tid] = outVal;
+}
diff --git a/tests/language-feature/inheritance/derived-struct-init-list.slang.expected.txt b/tests/language-feature/inheritance/derived-struct-init-list.slang.expected.txt
new file mode 100644
index 000000000..373286856
--- /dev/null
+++ b/tests/language-feature/inheritance/derived-struct-init-list.slang.expected.txt
@@ -0,0 +1,4 @@
+11201
+11212
+11223
+11234